QGIS API Documentation 4.3.0-Master (0978c174f8e)
Loading...
Searching...
No Matches
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 "qgsconfig.h"
17#include "qgstextformatwidget.h"
18
19#include "qgsauxiliarystorage.h"
22#include "qgsfillsymbol.h"
23#include "qgsfontutils.h"
24#include "qgsgui.h"
25#include "qgshelp.h"
26#include "qgsiconutils.h"
27#include "qgslogger.h"
28#include "qgsmapcanvas.h"
29#include "qgsmaplayer.h"
30#include "qgsmarkersymbol.h"
31#include "qgsmeshlayer.h"
33#include "qgspainteffect.h"
35#include "qgspallabeling.h"
36#include "qgspathresolver.h"
37#include "qgsproject.h"
40#include "qgssettings.h"
41#include "qgsstylesavedialog.h"
43#include "qgssvgcache.h"
46#include "qgssymbollayerutils.h"
48#include "qgsvectorlayer.h"
49
50#include <QButtonGroup>
51#include <QMessageBox>
52#include <QString>
53
54#include "moc_qgstextformatwidget.cpp"
55
56using namespace Qt::StringLiterals;
57
59 : QWidget( parent )
60 , mMapCanvas( mapCanvas )
61 , mLayer( layer )
62{
63 initWidget();
64 setWidgetMode( Text );
67}
68
69QgsTextFormatWidget::QgsTextFormatWidget( QgsMapCanvas *mapCanvas, QWidget *parent, Mode mode, QgsMapLayer *layer )
70 : QWidget( parent )
71 , mMapCanvas( mapCanvas )
72 , mLayer( layer )
73 , mWidgetMode( mode )
74{
75 initWidget();
76 if ( mode == Text )
78 setWidgetMode( mode );
79}
80
81void QgsTextFormatWidget::initWidget()
82{
83 setupUi( this );
84
85 mGeometryGeneratorGroupBox->setCollapsed( true );
86
87 mTextItem = new QListWidgetItem( tr( "Text" ), mLabelingOptionsListWidget );
88 mTextItem->setIcon( QgsApplication::getThemeIcon( u"propertyicons/labeltext.svg"_s ) );
89 mTextItem->setToolTip( tr( "Text style" ) );
90
91 mFormattingItem = new QListWidgetItem( tr( "Formatting" ), mLabelingOptionsListWidget );
92 mFormattingItem->setIcon( QgsApplication::getThemeIcon( u"propertyicons/labelformatting.svg"_s ) );
93 mFormattingItem->setToolTip( tr( "Formatting" ) );
94
95 mBufferItem = new QListWidgetItem( tr( "Buffer" ), mLabelingOptionsListWidget );
96 mBufferItem->setIcon( QgsApplication::getThemeIcon( u"propertyicons/labelbuffer.svg"_s ) );
97 mBufferItem->setToolTip( tr( "Buffer" ) );
98
99 mMaskItem = new QListWidgetItem( tr( "Mask" ), mLabelingOptionsListWidget );
100 mMaskItem->setIcon( QgsApplication::getThemeIcon( u"propertyicons/labelmask.svg"_s ) );
101 mMaskItem->setToolTip( tr( "Mask" ) );
102
103 mBackgroundItem = new QListWidgetItem( tr( "Background" ), mLabelingOptionsListWidget );
104 mBackgroundItem->setIcon( QgsApplication::getThemeIcon( u"propertyicons/labelbackground.svg"_s ) );
105 mBackgroundItem->setToolTip( tr( "Background" ) );
106
107 mShadowItem = new QListWidgetItem( tr( "Shadow" ), mLabelingOptionsListWidget );
108 mShadowItem->setIcon( QgsApplication::getThemeIcon( u"propertyicons/labelshadow.svg"_s ) );
109 mShadowItem->setToolTip( tr( "Shadow" ) );
110
111 mCalloutItem = new QListWidgetItem( tr( "Callouts" ), mLabelingOptionsListWidget );
112 mCalloutItem->setIcon( QgsApplication::getThemeIcon( u"propertyicons/labelcallout.svg"_s ) );
113 mCalloutItem->setToolTip( tr( "Callouts" ) );
114
115 mPlacementItem = new QListWidgetItem( tr( "Placement" ), mLabelingOptionsListWidget );
116 mPlacementItem->setIcon( QgsApplication::getThemeIcon( u"propertyicons/labelplacement.svg"_s ) );
117 mPlacementItem->setToolTip( tr( "Placement" ) );
118
119 mRenderingItem = new QListWidgetItem( tr( "Rendering" ), mLabelingOptionsListWidget );
120 mRenderingItem->setIcon( QgsApplication::getThemeIcon( u"propertyicons/render.svg"_s ) );
121 mRenderingItem->setToolTip( tr( "Rendering" ) );
122
123#if ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR < 10 )
124 mDuplicatesStackedWidget->setCurrentWidget( mDuplicatesNotAvailableWidget );
125 mLabelSpacingStackedWidget->setCurrentWidget( mLabelSpacingNotAvailableWidget );
126#endif
127
128 mLabelingOptionsListWidget->addItem( mTextItem );
129 mLabelingOptionsListWidget->addItem( mFormattingItem );
130 mLabelingOptionsListWidget->addItem( mBufferItem );
131 mLabelingOptionsListWidget->addItem( mMaskItem );
132 mLabelingOptionsListWidget->addItem( mBackgroundItem );
133 mLabelingOptionsListWidget->addItem( mShadowItem );
134 mLabelingOptionsListWidget->addItem( mCalloutItem );
135 mLabelingOptionsListWidget->addItem( mPlacementItem );
136 mLabelingOptionsListWidget->addItem( mRenderingItem );
137
138 QObject::connect( mOptionsTab, &QTabWidget::currentChanged, this, [this]( int index ) {
139 if ( index == mOptionsTab->indexOf( textTab ) )
140 mLabelStackedWidget->setCurrentWidget( mLabelPage_Text );
141 else if ( index == mOptionsTab->indexOf( formattingTab ) )
142 mLabelStackedWidget->setCurrentWidget( mLabelPage_Formatting );
143 else if ( index == mOptionsTab->indexOf( maskTab ) )
144 mLabelStackedWidget->setCurrentWidget( mLabelPage_Mask );
145 else if ( index == mOptionsTab->indexOf( bufferTab ) )
146 mLabelStackedWidget->setCurrentWidget( mLabelPage_Buffer );
147 else if ( index == mOptionsTab->indexOf( backgroundTab ) )
148 mLabelStackedWidget->setCurrentWidget( mLabelPage_Background );
149 else if ( index == mOptionsTab->indexOf( shadowTab ) )
150 mLabelStackedWidget->setCurrentWidget( mLabelPage_Shadow );
151 else if ( index == mOptionsTab->indexOf( calloutsTab ) )
152 mLabelStackedWidget->setCurrentWidget( mLabelPage_Callouts );
153 else if ( index == mOptionsTab->indexOf( placementTab ) )
154 mLabelStackedWidget->setCurrentWidget( mLabelPage_Placement );
155 else if ( index == mOptionsTab->indexOf( renderingTab ) )
156 mLabelStackedWidget->setCurrentWidget( mLabelPage_Rendering );
157 } );
158
159 QObject::connect( mLabelingOptionsListWidget, &QListWidget::currentRowChanged, this, [this]( int ) {
160 QListWidgetItem *currentItem = mLabelingOptionsListWidget->currentItem();
161 if ( !currentItem )
162 return;
163 if ( currentItem == mTextItem )
164 mLabelStackedWidget->setCurrentWidget( mLabelPage_Text );
165 else if ( currentItem == mFormattingItem )
166 mLabelStackedWidget->setCurrentWidget( mLabelPage_Formatting );
167 else if ( currentItem == mMaskItem )
168 mLabelStackedWidget->setCurrentWidget( mLabelPage_Mask );
169 else if ( currentItem == mBufferItem )
170 mLabelStackedWidget->setCurrentWidget( mLabelPage_Buffer );
171 else if ( currentItem == mBackgroundItem )
172 mLabelStackedWidget->setCurrentWidget( mLabelPage_Background );
173 else if ( currentItem == mShadowItem )
174 mLabelStackedWidget->setCurrentWidget( mLabelPage_Shadow );
175 else if ( currentItem == mCalloutItem )
176 mLabelStackedWidget->setCurrentWidget( mLabelPage_Callouts );
177 else if ( currentItem == mPlacementItem )
178 mLabelStackedWidget->setCurrentWidget( mLabelPage_Placement );
179 else if ( currentItem == mRenderingItem )
180 mLabelStackedWidget->setCurrentWidget( mLabelPage_Rendering );
181 } );
182
183 QObject::connect( mLabelingOptionsListWidget, &QListWidget::currentRowChanged, mLabelStackedWidget, &QStackedWidget::setCurrentIndex );
184
185 connect( mShapeSVGPathLineEdit, &QLineEdit::textChanged, this, &QgsTextFormatWidget::mShapeSVGPathLineEdit_textChanged );
186 connect( mFontSizeSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTextFormatWidget::mFontSizeSpinBox_valueChanged );
187 connect( mFontFamilyCmbBx, &QFontComboBox::currentFontChanged, this, &QgsTextFormatWidget::mFontFamilyCmbBx_currentFontChanged );
188 connect( mFontStyleComboBox, &QComboBox::currentTextChanged, this, &QgsTextFormatWidget::mFontStyleComboBox_currentIndexChanged );
189 connect( mFontUnderlineBtn, &QToolButton::toggled, this, &QgsTextFormatWidget::mFontUnderlineBtn_toggled );
190 connect( mFontStrikethroughBtn, &QToolButton::toggled, this, &QgsTextFormatWidget::mFontStrikethroughBtn_toggled );
191 connect( mFontWordSpacingSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTextFormatWidget::mFontWordSpacingSpinBox_valueChanged );
192 connect( mFontLetterSpacingSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTextFormatWidget::mFontLetterSpacingSpinBox_valueChanged );
193 connect( mFontSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTextFormatWidget::mFontSizeUnitWidget_changed );
194 connect( mFontMinPixelSpinBox, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), this, &QgsTextFormatWidget::mFontMinPixelSpinBox_valueChanged );
195 connect( mFontMaxPixelSpinBox, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), this, &QgsTextFormatWidget::mFontMaxPixelSpinBox_valueChanged );
196 connect( mBufferUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTextFormatWidget::mBufferUnitWidget_changed );
197 connect( mMaskBufferUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTextFormatWidget::mMaskBufferUnitWidget_changed );
198 connect( mCoordXDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsTextFormatWidget::mCoordXDDBtn_changed );
199 connect( mCoordXDDBtn, &QgsPropertyOverrideButton::activated, this, &QgsTextFormatWidget::mCoordXDDBtn_activated );
200 connect( mCoordYDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsTextFormatWidget::mCoordYDDBtn_changed );
201 connect( mCoordYDDBtn, &QgsPropertyOverrideButton::activated, this, &QgsTextFormatWidget::mCoordYDDBtn_activated );
202 connect( mCoordPointDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsTextFormatWidget::mCoordPointDDBtn_changed );
203 connect( mCoordPointDDBtn, &QgsPropertyOverrideButton::activated, this, &QgsTextFormatWidget::mCoordPointDDBtn_activated );
204 connect( mShapeTypeCmbBx, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::mShapeTypeCmbBx_currentIndexChanged );
205 connect( mShapeRotationCmbBx, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::mShapeRotationCmbBx_currentIndexChanged );
206 connect( mShapeSVGParamsBtn, &QPushButton::clicked, this, &QgsTextFormatWidget::mShapeSVGParamsBtn_clicked );
207 connect( mShapeSVGSelectorBtn, &QPushButton::clicked, this, &QgsTextFormatWidget::mShapeSVGSelectorBtn_clicked );
208 connect( mPreviewTextEdit, &QLineEdit::textChanged, this, &QgsTextFormatWidget::mPreviewTextEdit_textChanged );
209 connect( mPreviewTextBtn, &QToolButton::clicked, this, &QgsTextFormatWidget::mPreviewTextBtn_clicked );
210 connect( mPreviewBackgroundBtn, &QgsColorButton::colorChanged, this, &QgsTextFormatWidget::mPreviewBackgroundBtn_colorChanged );
211 connect( mDirectSymbLeftToolBtn, &QToolButton::clicked, this, &QgsTextFormatWidget::mDirectSymbLeftToolBtn_clicked );
212 connect( mDirectSymbRightToolBtn, &QToolButton::clicked, this, &QgsTextFormatWidget::mDirectSymbRightToolBtn_clicked );
213 connect( chkLineOrientationDependent, &QCheckBox::toggled, this, &QgsTextFormatWidget::chkLineOrientationDependent_toggled );
214 connect( mToolButtonConfigureSubstitutes, &QToolButton::clicked, this, &QgsTextFormatWidget::mToolButtonConfigureSubstitutes_clicked );
215 connect( mKerningCheckBox, &QCheckBox::toggled, this, &QgsTextFormatWidget::kerningToggled );
216 connect( mComboOverlapHandling, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::overlapModeChanged );
217 connect( mTabStopsButton, &QToolButton::clicked, this, &QgsTextFormatWidget::configureTabStops );
218
219 const int iconSize = QgsGuiUtils::scaleIconSize( 20 );
220 mOptionsTab->setIconSize( QSize( iconSize, iconSize ) );
221 mLabelingOptionsListWidget->setIconSize( QSize( iconSize, iconSize ) );
222 const int iconSize32 = QgsGuiUtils::scaleIconSize( 32 );
223 const int iconSize24 = QgsGuiUtils::scaleIconSize( 24 );
224 const int iconSize18 = QgsGuiUtils::scaleIconSize( 18 );
225 const int iconSize16 = QgsGuiUtils::scaleIconSize( 16 );
226
227 mPreviewTextBtn->setIconSize( QSize( iconSize16, iconSize16 ) );
228 mPointOffsetAboveLeft->setIconSize( QSize( iconSize32, iconSize18 ) );
229 mPointOffsetAbove->setIconSize( QSize( iconSize32, iconSize18 ) );
230 mPointOffsetAboveRight->setIconSize( QSize( iconSize32, iconSize18 ) );
231 mPointOffsetLeft->setIconSize( QSize( iconSize32, iconSize18 ) );
232 mPointOffsetOver->setIconSize( QSize( iconSize32, iconSize18 ) );
233 mPointOffsetRight->setIconSize( QSize( iconSize32, iconSize18 ) );
234 mPointOffsetBelowLeft->setIconSize( QSize( iconSize32, iconSize18 ) );
235 mPointOffsetBelow->setIconSize( QSize( iconSize32, iconSize18 ) );
236 mPointOffsetBelowRight->setIconSize( QSize( iconSize32, iconSize18 ) );
237 mLabelMinScale->setPixmap( QgsApplication::getThemeIcon( u"/mActionZoomOut.svg"_s ).pixmap( QSize( iconSize24, iconSize24 ) ) );
238 mLabelMaxScale->setPixmap( QgsApplication::getThemeIcon( u"/mActionZoomIn.svg"_s ).pixmap( QSize( iconSize24, iconSize24 ) ) );
239
240 const int buttonSize = QgsGuiUtils::scaleIconSize( 24 );
241 mFontUnderlineBtn->setMinimumSize( buttonSize, buttonSize );
242 mFontUnderlineBtn->setMaximumSize( buttonSize, buttonSize );
243 mFontStrikethroughBtn->setMinimumSize( buttonSize, buttonSize );
244 mFontStrikethroughBtn->setMaximumSize( buttonSize, buttonSize );
245 mFontBoldBtn->setMinimumSize( buttonSize, buttonSize );
246 mFontBoldBtn->setMaximumSize( buttonSize, buttonSize );
247 mFontItalicBtn->setMinimumSize( buttonSize, buttonSize );
248 mFontItalicBtn->setMaximumSize( buttonSize, buttonSize );
249
250 mPreviewScaleComboBox->setMapCanvas( mMapCanvas );
251 mPreviewScaleComboBox->setShowCurrentScaleButton( true );
252 connect( mPreviewScaleComboBox, &QgsScaleWidget::scaleChanged, this, &QgsTextFormatWidget::previewScaleChanged );
253
254 const auto unitWidgets = findChildren<QgsUnitSelectionWidget *>();
255 for ( QgsUnitSelectionWidget *unitWidget : unitWidgets )
256 {
257 unitWidget->setMapCanvas( mMapCanvas );
258 }
259 mFontSizeUnitWidget->setUnits(
261 );
262 mBufferUnitWidget->setUnits(
271 );
272 mMaskBufferUnitWidget->setUnits(
281 );
282 mShapeSizeUnitWidget->setUnits(
284 );
285 mShapeOffsetUnitWidget->setUnits(
287 );
288 mShapeRadiusUnitWidget->setUnits(
297 );
298 mShapeStrokeWidthUnitWidget->setUnits(
300 );
301 mShadowOffsetUnitWidget->setUnits(
310 );
311 mShadowRadiusUnitWidget->setUnits(
320 );
321 mPointOffsetUnitWidget->setUnits(
323 );
324 mLineDistanceUnitWidget->setUnits(
326 );
327 mMaximumDistanceUnitWidget->setUnits(
329 );
330 mRepeatDistanceUnitWidget->setUnits(
332 );
333 mOverrunDistanceUnitWidget->setUnits(
335 );
336 mLabelMarginUnitWidget->setUnits(
338 );
339 mLineHeightUnitWidget->setUnits(
341 );
342 mTabDistanceUnitWidget->setUnits(
344 );
345 mFontLineHeightSpinBox->setClearValue( 100.0 );
346 mShapeRotationDblSpnBx->setClearValue( 0.0 );
347 mShapeOffsetXSpnBx->setClearValue( 0.0 );
348 mShapeOffsetYSpnBx->setClearValue( 0.0 );
349 mPointOffsetXSpinBox->setClearValue( 0.0 );
350 mPointOffsetYSpinBox->setClearValue( 0.0 );
351 mPointAngleSpinBox->setClearValue( 0.0 );
352 mFontLetterSpacingSpinBox->setClearValue( 0.0 );
353 mFontWordSpacingSpinBox->setClearValue( 0.0 );
354 mZIndexSpinBox->setClearValue( 0.0 );
355 mLineDistanceSpnBx->setClearValue( 0.0 );
356 mMaximumDistanceSpnBx->setMinimum( 0 );
357 mMaximumDistanceSpnBx->setClearValue( 0.0, tr( "Not set" ) );
358 mSpinStretch->setClearValue( 100 );
359 mTabStopDistanceSpin->setMinimum( 0 );
360
361 connect( mLineHeightUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
362 if ( mLineHeightUnitWidget->unit() == Qgis::RenderUnit::Percentage )
363 mFontLineHeightSpinBox->setClearValue( 100.0 );
364 else
365 mFontLineHeightSpinBox->setClearValue( 10.0 );
366 } );
367
368 mOffsetTypeComboBox->addItem( tr( "From Point" ), static_cast<int>( Qgis::LabelOffsetType::FromPoint ) );
369 mOffsetTypeComboBox->addItem( tr( "From Symbol Bounds" ), static_cast<int>( Qgis::LabelOffsetType::FromSymbolBounds ) );
370
371 mShapeTypeCmbBx->addItem( tr( "Rectangle" ), QgsTextBackgroundSettings::ShapeRectangle );
372 mShapeTypeCmbBx->addItem( tr( "Square" ), QgsTextBackgroundSettings::ShapeSquare );
373 mShapeTypeCmbBx->addItem( tr( "Ellipse" ), QgsTextBackgroundSettings::ShapeEllipse );
374 mShapeTypeCmbBx->addItem( tr( "Circle" ), QgsTextBackgroundSettings::ShapeCircle );
375 mShapeTypeCmbBx->addItem( tr( "SVG" ), QgsTextBackgroundSettings::ShapeSVG );
376 mShapeTypeCmbBx->addItem( tr( "Marker Symbol" ), QgsTextBackgroundSettings::ShapeMarkerSymbol );
377
378 mComboOverlapHandling->addItem( tr( "Never Overlap" ), static_cast<int>( Qgis::LabelOverlapHandling::PreventOverlap ) );
379 mComboOverlapHandling->addItem( tr( "Allow Overlaps if Required" ), static_cast<int>( Qgis::LabelOverlapHandling::AllowOverlapIfRequired ) );
380 mComboOverlapHandling->addItem( tr( "Allow Overlaps without Penalty" ), static_cast<int>( Qgis::LabelOverlapHandling::AllowOverlapAtNoCost ) );
381
382 mPrioritizationComboBox->addItem( tr( "Prefer Closer Labels" ), QVariant::fromValue( Qgis::LabelPrioritization::PreferCloser ) );
383 mPrioritizationComboBox->addItem( tr( "Prefer Position Ordering" ), QVariant::fromValue( Qgis::LabelPrioritization::PreferPositionOrdering ) );
384
385 mComboCurvedLabelMode->addItem( tr( "Default" ), QVariant::fromValue( Qgis::CurvedLabelMode::Default ) );
386 mComboCurvedLabelMode->addItem( tr( "Stretch Word Spacing" ), QVariant::fromValue( Qgis::CurvedLabelMode::StretchWordSpacingToFitLine ) );
387 mComboCurvedLabelMode->addItem( tr( "Stretch Character Spacing" ), QVariant::fromValue( Qgis::CurvedLabelMode::StretchCharacterSpacingToFitLine ) );
388 mComboCurvedLabelMode->addItem( tr( "Characters at Vertices" ), QVariant::fromValue( Qgis::CurvedLabelMode::PlaceCharactersAtVertices ) );
389 connect( mComboCurvedLabelMode, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::updateCurvedLabelDescription );
390 QFont font = mCurvedModeDescriptionLabel->font();
391 font.setItalic( true );
392 mCurvedModeDescriptionLabel->setFont( font );
393 updateCurvedLabelDescription();
394
395 mComboMultipartBehavior->addItem( tr( "Label Largest Part Only" ), QVariant::fromValue( Qgis::MultiPartLabelingBehavior::LabelLargestPartOnly ) );
396 mComboMultipartBehavior->addItem( tr( "Label Every Part with Entire Label" ), QVariant::fromValue( Qgis::MultiPartLabelingBehavior::LabelEveryPartWithEntireLabel ) );
397 mComboMultipartBehavior->addItem( tr( "Split Label Text Lines over Parts" ), QVariant::fromValue( Qgis::MultiPartLabelingBehavior::SplitLabelTextLinesOverParts ) );
398
399 updateAvailableShadowPositions();
400
401 mBackgroundMarkerSymbolButton->setSymbolType( Qgis::SymbolType::Marker );
402 mBackgroundMarkerSymbolButton->setDialogTitle( tr( "Background Symbol" ) );
403 mBackgroundMarkerSymbolButton->registerExpressionContextGenerator( this );
404 mBackgroundMarkerSymbolButton->setMapCanvas( mMapCanvas );
405 mBackgroundFillSymbolButton->setSymbolType( Qgis::SymbolType::Fill );
406 mBackgroundFillSymbolButton->setDialogTitle( tr( "Background Symbol" ) );
407 mBackgroundFillSymbolButton->registerExpressionContextGenerator( this );
408 mBackgroundFillSymbolButton->setMapCanvas( mMapCanvas );
409
410 mCharDlg = new QgsCharacterSelectorDialog( this );
411
412 mRefFont = lblFontPreview->font();
413
414 // internal connections
415 connect( mShadowOffsetAngleDial, &QAbstractSlider::valueChanged, mShadowOffsetAngleSpnBx, &QSpinBox::setValue );
416 connect( mShadowOffsetAngleSpnBx, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), mShadowOffsetAngleDial, &QAbstractSlider::setValue );
417 connect( mLimitLabelChkBox, &QAbstractButton::toggled, mLimitLabelSpinBox, &QWidget::setEnabled );
418 connect( mCheckBoxSubstituteText, &QAbstractButton::toggled, mToolButtonConfigureSubstitutes, &QWidget::setEnabled );
419
420 //connections to prevent users removing all line placement positions
421 connect( chkLineAbove, &QAbstractButton::toggled, this, &QgsTextFormatWidget::updateLinePlacementOptions );
422 connect( chkLineBelow, &QAbstractButton::toggled, this, &QgsTextFormatWidget::updateLinePlacementOptions );
423 connect( chkLineOn, &QAbstractButton::toggled, this, &QgsTextFormatWidget::updateLinePlacementOptions );
424
425 mTextOrientationComboBox->addItem( tr( "Horizontal" ), static_cast<int>( Qgis::TextOrientation::Horizontal ) );
426 mTextOrientationComboBox->addItem( tr( "Vertical" ), static_cast<int>( Qgis::TextOrientation::Vertical ) );
427
428 populateFontCapitalsComboBox();
429
430 // color buttons
431 mPreviewBackgroundBtn->setColorDialogTitle( tr( "Select Fill Color" ) );
432 mPreviewBackgroundBtn->setContext( u"labeling"_s );
433 mPreviewBackgroundBtn->setColor( QColor( 255, 255, 255 ) );
434 btnTextColor->setColorDialogTitle( tr( "Select Text Color" ) );
435 btnTextColor->setContext( u"labeling"_s );
436 btnTextColor->setDefaultColor( Qt::black );
437 btnBufferColor->setColorDialogTitle( tr( "Select Buffer Color" ) );
438 btnBufferColor->setContext( u"labeling"_s );
439 btnBufferColor->setDefaultColor( Qt::white );
440 mShapeStrokeColorBtn->setColorDialogTitle( tr( "Select Stroke Color" ) );
441 mShapeStrokeColorBtn->setContext( u"labeling"_s );
442 mShapeFillColorBtn->setColorDialogTitle( tr( "Select Fill Color" ) );
443 mShapeFillColorBtn->setContext( u"labeling"_s );
444 mShadowColorBtn->setColorDialogTitle( tr( "Select Shadow Color" ) );
445 mShadowColorBtn->setContext( u"labeling"_s );
446 mShadowColorBtn->setDefaultColor( Qt::black );
447
448 mFontColorDDBtn->registerLinkedWidget( btnTextColor );
449 mBufferColorDDBtn->registerLinkedWidget( btnBufferColor );
450 mShapeStrokeColorDDBtn->registerLinkedWidget( mShapeStrokeColorBtn );
451 mShapeFillColorDDBtn->registerLinkedWidget( mShapeFillColorBtn );
452 mShadowColorDDBtn->registerLinkedWidget( mShadowColorBtn );
453
454 // set up quadrant offset button group
455 mQuadrantBtnGrp = new QButtonGroup( this );
456 mQuadrantBtnGrp->addButton( mPointOffsetAboveLeft, static_cast<int>( Qgis::LabelQuadrantPosition::AboveLeft ) );
457 mQuadrantBtnGrp->addButton( mPointOffsetAbove, static_cast<int>( Qgis::LabelQuadrantPosition::Above ) );
458 mQuadrantBtnGrp->addButton( mPointOffsetAboveRight, static_cast<int>( Qgis::LabelQuadrantPosition::AboveRight ) );
459 mQuadrantBtnGrp->addButton( mPointOffsetLeft, static_cast<int>( Qgis::LabelQuadrantPosition::Left ) );
460 mQuadrantBtnGrp->addButton( mPointOffsetOver, static_cast<int>( Qgis::LabelQuadrantPosition::Over ) );
461 mQuadrantBtnGrp->addButton( mPointOffsetRight, static_cast<int>( Qgis::LabelQuadrantPosition::Right ) );
462 mQuadrantBtnGrp->addButton( mPointOffsetBelowLeft, static_cast<int>( Qgis::LabelQuadrantPosition::BelowLeft ) );
463 mQuadrantBtnGrp->addButton( mPointOffsetBelow, static_cast<int>( Qgis::LabelQuadrantPosition::Below ) );
464 mQuadrantBtnGrp->addButton( mPointOffsetBelowRight, static_cast<int>( Qgis::LabelQuadrantPosition::BelowRight ) );
465 mQuadrantBtnGrp->setExclusive( true );
466
467 // setup direction symbol(s) button group
468 mDirectSymbBtnGrp = new QButtonGroup( this );
469 mDirectSymbBtnGrp->addButton( mDirectSymbRadioBtnLR, static_cast<int>( QgsLabelLineSettings::DirectionSymbolPlacement::SymbolLeftRight ) );
470 mDirectSymbBtnGrp->addButton( mDirectSymbRadioBtnAbove, static_cast<int>( QgsLabelLineSettings::DirectionSymbolPlacement::SymbolAbove ) );
471 mDirectSymbBtnGrp->addButton( mDirectSymbRadioBtnBelow, static_cast<int>( QgsLabelLineSettings::DirectionSymbolPlacement::SymbolBelow ) );
472 mDirectSymbBtnGrp->setExclusive( true );
473
474 // upside-down labels button group
475 mUpsidedownBtnGrp = new QButtonGroup( this );
476 mUpsidedownBtnGrp->addButton( mUpsidedownRadioOff, static_cast<int>( Qgis::UpsideDownLabelHandling::FlipUpsideDownLabels ) );
477 mUpsidedownBtnGrp->addButton( mUpsidedownRadioDefined, static_cast<int>( Qgis::UpsideDownLabelHandling::AllowUpsideDownWhenRotationIsDefined ) );
478 mUpsidedownBtnGrp->addButton( mUpsidedownRadioAll, static_cast<int>( Qgis::UpsideDownLabelHandling::AlwaysAllowUpsideDown ) );
479 mUpsidedownBtnGrp->setExclusive( true );
480
481 //mShapeCollisionsChkBx->setVisible( false ); // until implemented
482
483 // post updatePlacementWidgets() connections
484 connect( chkLineAbove, &QAbstractButton::toggled, this, &QgsTextFormatWidget::updatePlacementWidgets );
485 connect( chkLineBelow, &QAbstractButton::toggled, this, &QgsTextFormatWidget::updatePlacementWidgets );
486 connect( mCheckAllowLabelsOutsidePolygons, &QAbstractButton::toggled, this, &QgsTextFormatWidget::updatePlacementWidgets );
487 connect( mAllowOutsidePolygonsDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsTextFormatWidget::updatePlacementWidgets );
488
489 connect( mPlacementModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::updatePlacementWidgets );
490
491 // Global settings group for groupboxes' saved/restored collapsed state
492 // maintains state across different dialogs
493 const auto groupBoxes = findChildren<QgsCollapsibleGroupBox *>();
494 for ( QgsCollapsibleGroupBox *grpbox : groupBoxes )
495 {
496 grpbox->setSettingGroup( u"mAdvLabelingDlg"_s );
497 }
498
499 connect( groupBox_mPreview, &QgsCollapsibleGroupBoxBasic::collapsedStateChanged, this, &QgsTextFormatWidget::collapseSample );
500
501 // get rid of annoying outer focus rect on Mac
502 mLabelingOptionsListWidget->setAttribute( Qt::WA_MacShowFocusRect, false );
503
504 const QgsSettings settings;
505
506 // reset horiz stretch of left side of options splitter (set to 1 for previewing in Qt Designer)
507 QSizePolicy policy( mLabelingOptionsListFrame->sizePolicy() );
508 policy.setHorizontalStretch( 0 );
509 mLabelingOptionsListFrame->setSizePolicy( policy );
510 if ( !settings.contains( u"/Windows/Labeling/OptionsSplitState"_s ) )
511 {
512 // set left list widget width on initial showing
513 QList<int> splitsizes;
514 splitsizes << 115;
515 mLabelingOptionsSplitter->setSizes( splitsizes );
516 }
517
518 // set up reverse connection from stack to list
519 connect( mLabelStackedWidget, &QStackedWidget::currentChanged, this, &QgsTextFormatWidget::optionsStackedWidget_CurrentChanged );
520
521 // restore dialog, splitters and current tab
522 mFontPreviewSplitter->restoreState( settings.value( u"Windows/Labeling/FontPreviewSplitState"_s ).toByteArray() );
523 mLabelingOptionsSplitter->restoreState( settings.value( u"Windows/Labeling/OptionsSplitState"_s ).toByteArray() );
524
525 mLabelingOptionsListWidget->setCurrentRow( settings.value( u"Windows/Labeling/Tab"_s, 0 ).toInt() );
526
527 mBufferEffect.reset( QgsPaintEffectRegistry::defaultStack() );
528 connect( mBufferEffectWidget, &QgsEffectStackCompactWidget::changed, this, &QgsTextFormatWidget::updatePreview );
529 mBufferEffectWidget->setPaintEffect( mBufferEffect.get() );
530
531 mMaskEffect.reset( QgsPaintEffectRegistry::defaultStack() );
533 mMaskEffectWidget->setPaintEffect( mMaskEffect.get() );
534
535 mBackgroundEffect.reset( QgsPaintEffectRegistry::defaultStack() );
536 connect( mBackgroundEffectWidget, &QgsEffectStackCompactWidget::changed, this, &QgsTextFormatWidget::updatePreview );
537 mBackgroundEffectWidget->setPaintEffect( mBackgroundEffect.get() );
538
539 overlapModeChanged();
540
541 setDockMode( false );
542
543 QList<QWidget *> widgets;
544 widgets
545 << btnBufferColor
546 << btnTextColor
547 << mComboMultipartBehavior
548 << chkLineAbove
549 << chkLineBelow
550 << chkLineOn
551 << chkLineOrientationDependent
552 << chkMergeLines
553 << chkPreserveRotation
554 << comboBlendMode
555 << comboBufferBlendMode
556 << mBufferDrawChkBx
557 << mBufferJoinStyleComboBox
558 << mBufferTranspFillChbx
559 << mBufferOpacityWidget
560 << mCentroidInsideCheckBox
561 << mChkNoObstacle
562 << mCoordRotationUnitComboBox
563 << mDirectSymbChkBx
564 << mDirectSymbLeftLineEdit
565 << mDirectSymbRevChkBx
566 << mDirectSymbRightLineEdit
567 << mFitInsidePolygonCheckBox
568 << mFontCapitalsComboBox
569 << mFontLetterSpacingSpinBox
570 << mFontLimitPixelChkBox
571 << mFontLineHeightSpinBox
572 << mLineHeightUnitWidget
573 << mFontMaxPixelSpinBox
574 << mFontMinPixelSpinBox
575 << mFontMultiLineAlignComboBox
576 << mFontSizeSpinBox
577 << mFontStyleComboBox
578 << mTextOrientationComboBox
579 << mTextOpacityWidget
580 << mSpinStretch
581 << mFontWordSpacingSpinBox
582 << mFormatNumChkBx
583 << mFormatNumDecimalsSpnBx
584 << mFormatNumPlusSignChkBx
585 << mLimitLabelChkBox
586 << mLimitLabelSpinBox
587 << mLineDistanceSpnBx
588 << mLineDistanceUnitWidget
589 << mMaximumDistanceSpnBx
590 << mMaximumDistanceUnitWidget
591 << mMaxCharAngleInDSpinBox
592 << mMaxCharAngleOutDSpinBox
593 << mMinSizeSpinBox
594 << mOffsetTypeComboBox
595 << mCheckAllowDegradedPlacement
596 << mComboOverlapHandling
597 << mPointAngleSpinBox
598 << mPointOffsetUnitWidget
599 << mPointOffsetXSpinBox
600 << mPointOffsetYSpinBox
601 << mPreviewBackgroundBtn
602 << mPreviewTextEdit
603 << mPrioritySlider
604 << mRepeatDistanceSpinBox
605 << mRepeatDistanceUnitWidget
606 << mOverrunDistanceSpinBox
607 << mOverrunDistanceUnitWidget
608 << mLabelMarginSpinBox
609 << mLabelMarginUnitWidget
610 << mScaleBasedVisibilityChkBx
611 << mMaxScaleWidget
612 << mMinScaleWidget
613 << mShadowBlendCmbBx
614 << mShadowColorBtn
615 << mShadowDrawChkBx
616 << mShadowOffsetAngleSpnBx
617 << mShadowOffsetGlobalChkBx
618 << mShadowOffsetSpnBx
619 << mShadowOffsetUnitWidget
620 << mShadowRadiusAlphaChkBx
621 << mShadowRadiusDblSpnBx
622 << mShadowRadiusUnitWidget
623 << mShadowScaleSpnBx
624 << mShadowOpacityWidget
625 << mShadowUnderCmbBx
626 << mShapeBlendCmbBx
627 << mShapeStrokeColorBtn
628 << mShapeStrokeWidthSpnBx
629 << mShapeStrokeWidthUnitWidget
630 << mShapeDrawChkBx
631 << mShapeFillColorBtn
632 << mShapeOffsetXSpnBx
633 << mShapeOffsetYSpnBx
634 << mShapeOffsetUnitWidget
635 << mShapeRadiusXDbSpnBx
636 << mShapeRadiusYDbSpnBx
637 << mShapeRotationCmbBx
638 << mShapeRotationDblSpnBx
639 << mShapeRadiusUnitWidget
640 << mShapeSVGPathLineEdit
641 << mShapeSizeCmbBx
642 << mShapeSizeUnitWidget
643 << mShapeSizeXSpnBx
644 << mShapeSizeYSpnBx
645 << mBackgroundOpacityWidget
646 << mShapeTypeCmbBx
647 << mZIndexSpinBox
648 << spinBufferSize
649 << wrapCharacterEdit
650 << mAutoWrapLengthSpinBox
651 << mAutoWrapTypeComboBox
652 << mCentroidRadioVisible
653 << mCentroidRadioWhole
654 << mDirectSymbRadioBtnAbove
655 << mDirectSymbRadioBtnBelow
656 << mDirectSymbRadioBtnLR
657 << mUpsidedownRadioAll
658 << mUpsidedownRadioDefined
659 << mUpsidedownRadioOff
660 << mPlacementModeComboBox
661 << mFieldExpressionWidget
662 << mCheckBoxSubstituteText
663 << mGeometryGeneratorGroupBox
664 << mGeometryGenerator
665 << mGeometryGeneratorType
666 << mBackgroundMarkerSymbolButton
667 << mBackgroundFillSymbolButton
668 << mCalloutsDrawCheckBox
669 << mCalloutStyleComboBox
670 << mKerningCheckBox
671 << mEnableMaskChkBx
672 << mMaskJoinStyleComboBox
673 << mMaskBufferSizeSpinBox
674 << mMaskOpacityWidget
675 << mCheckAllowLabelsOutsidePolygons
676 << mHtmlFormattingCheckBox
677 << mPrioritizationComboBox
678 << mComboCurvedLabelMode
679 << mTabDistanceUnitWidget
680 << mTabStopDistanceSpin
681 << mChkNoDuplicates
682 << mCheckWhitespaceIsNotACollision;
683
684 connectValueChanged( widgets );
685
686 connect( mQuadrantBtnGrp, qOverload<QAbstractButton *>( &QButtonGroup::buttonClicked ), this, &QgsTextFormatWidget::updatePreview );
687
688 connect( mBufferDrawDDBtn, &QgsPropertyOverrideButton::activated, this, &QgsTextFormatWidget::updateBufferFrameStatus );
689 connect( mBufferDrawChkBx, &QCheckBox::stateChanged, this, [this]( int ) { updateBufferFrameStatus(); } );
690 connect( mShapeDrawDDBtn, &QgsPropertyOverrideButton::activated, this, &QgsTextFormatWidget::updateShapeFrameStatus );
691 connect( mShapeDrawChkBx, &QCheckBox::stateChanged, this, [this]( int ) { updateShapeFrameStatus(); } );
692 connect( mShadowDrawDDBtn, &QgsPropertyOverrideButton::activated, this, &QgsTextFormatWidget::updateShadowFrameStatus );
693 connect( mShadowDrawChkBx, &QCheckBox::stateChanged, this, [this]( int ) { updateShadowFrameStatus(); } );
694 connect( mCalloutDrawDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsTextFormatWidget::updateCalloutFrameStatus );
695 connect( mCalloutsDrawCheckBox, &QCheckBox::stateChanged, this, [this]( int ) { updateCalloutFrameStatus(); } );
696
697 mGeometryGeneratorType->addItem( QgsIconUtils::iconForWkbType( Qgis::WkbType::Polygon ), tr( "Polygon / MultiPolygon" ), static_cast<int>( Qgis::GeometryType::Polygon ) );
698 mGeometryGeneratorType->addItem( QgsIconUtils::iconForWkbType( Qgis::WkbType::LineString ), tr( "LineString / MultiLineString" ), static_cast<int>( Qgis::GeometryType::Line ) );
699 mGeometryGeneratorType->addItem( QgsIconUtils::iconForWkbType( Qgis::WkbType::Point ), tr( "Point / MultiPoint" ), static_cast<int>( Qgis::GeometryType::Point ) );
700
701 // set correct initial tab to match displayed setting page
702 whileBlocking( mOptionsTab )->setCurrentIndex( mLabelStackedWidget->currentIndex() );
703 mOptionsTab->tabBar()->setUsesScrollButtons( true );
704
705
706 if ( mMapCanvas )
707 {
708 lblFontPreview->setMapUnits( mMapCanvas->mapSettings().mapUnits() );
709 mPreviewScaleComboBox->setScale( mMapCanvas->mapSettings().scale() );
710 }
711
712 mTextFormatsListWidget->setStyle( QgsStyle::defaultStyle() );
713 mTextFormatsListWidget->setEntityType( QgsStyle::TextFormatEntity );
715 connect( mTextFormatsListWidget, &QgsStyleItemsListWidget::saveEntity, this, &QgsTextFormatWidget::saveFormat );
716}
717
718void QgsTextFormatWidget::setWidgetMode( QgsTextFormatWidget::Mode mode )
719{
720 mWidgetMode = mode;
721 switch ( mode )
722 {
723 case Labeling:
725 mTextFormatsListWidget->setEntityTypes( QList<QgsStyle::StyleEntity>() << QgsStyle::TextFormatEntity << QgsStyle::LabelSettingsEntity );
726 mTextOrientationComboBox->addItem( tr( "Rotation-based" ), static_cast<int>( Qgis::TextOrientation::RotationBased ) );
727 break;
728
729 case Text:
730 {
731 const int prevIndex = mOptionsTab->currentIndex();
733 delete mRenderingItem;
734 mRenderingItem = nullptr;
735 delete mPlacementItem;
736 mPlacementItem = nullptr;
737 delete mCalloutItem;
738 mCalloutItem = nullptr;
739 delete mMaskItem;
740 mMaskItem = nullptr;
741 mOptionsTab->removeTab( mOptionsTab->indexOf( renderingTab ) );
742 mOptionsTab->removeTab( mOptionsTab->indexOf( placementTab ) );
743 mOptionsTab->removeTab( mOptionsTab->indexOf( calloutsTab ) );
744 mOptionsTab->removeTab( mOptionsTab->indexOf( maskTab ) );
745 mLabelStackedWidget->removeWidget( mLabelPage_Rendering );
746 mLabelStackedWidget->removeWidget( mLabelPage_Callouts );
747 mLabelStackedWidget->removeWidget( mLabelPage_Mask );
748 mLabelStackedWidget->removeWidget( mLabelPage_Placement );
749 switch ( prevIndex )
750 {
751 case 0:
752 case 1:
753 case 2:
754 break;
755
756 case 4: // background - account for removed mask tab
757 case 5: // shadow
758 mLabelStackedWidget->setCurrentIndex( prevIndex - 1 );
759 mOptionsTab->setCurrentIndex( prevIndex - 1 );
760 break;
761
762 case 3: // mask
763 case 6: // callouts
764 case 7: // placement
765 case 8: // rendering
766 mLabelStackedWidget->setCurrentIndex( 0 );
767 mOptionsTab->setCurrentIndex( 0 );
768 break;
769 }
770
771 mStackedWidgetLabelWith->hide();
772 mDirectSymbolsFrame->hide();
773 mFormatNumFrame->hide();
774 mFormatNumChkBx->hide();
775 mFormatNumDDBtn->hide();
776 mCheckBoxSubstituteText->hide();
777 mToolButtonConfigureSubstitutes->hide();
778 mLabelWrapOnCharacter->hide();
779 wrapCharacterEdit->hide();
780 mWrapCharDDBtn->hide();
781 mLabelWrapLinesTo->hide();
782 mAutoWrapLengthSpinBox->hide();
783 mAutoWrapLengthDDBtn->hide();
784 mAutoWrapTypeComboBox->hide();
785 mFontMultiLineLabel->hide();
786 mFontMultiLineAlignComboBox->hide();
787 mFontMultiLineAlignDDBtn->hide();
788
789 mTextOrientationComboBox->removeItem( mTextOrientationComboBox->findData( static_cast<int>( Qgis::TextOrientation::RotationBased ) ) );
790 break;
791 }
792 }
793}
794
796{
797 const QList<QgsPropertyOverrideButton *> buttons = findChildren<QgsPropertyOverrideButton *>();
798 for ( QgsPropertyOverrideButton *button : buttons )
799 {
800 button->setVisible( visible );
801 }
802}
803
805{
806 mOptionsTab->setVisible( enabled );
807 if ( int tabIndex = mOptionsTab->indexOf( textTab ); tabIndex >= 0 )
808 mOptionsTab->setTabToolTip( tabIndex, tr( "Text" ) );
809 if ( int tabIndex = mOptionsTab->indexOf( formattingTab ); tabIndex >= 0 )
810 mOptionsTab->setTabToolTip( tabIndex, tr( "Formatting" ) );
811 if ( int tabIndex = mOptionsTab->indexOf( bufferTab ); tabIndex >= 0 )
812 mOptionsTab->setTabToolTip( tabIndex, tr( "Buffer" ) );
813 if ( int tabIndex = mOptionsTab->indexOf( maskTab ); tabIndex >= 0 )
814 mOptionsTab->setTabToolTip( tabIndex, tr( "Mask" ) );
815 if ( int tabIndex = mOptionsTab->indexOf( backgroundTab ); tabIndex >= 0 )
816 mOptionsTab->setTabToolTip( tabIndex, tr( "Background" ) );
817 if ( int tabIndex = mOptionsTab->indexOf( shadowTab ); tabIndex >= 0 )
818 mOptionsTab->setTabToolTip( tabIndex, tr( "Shadow" ) );
819 if ( int tabIndex = mOptionsTab->indexOf( calloutsTab ); tabIndex >= 0 )
820 mOptionsTab->setTabToolTip( tabIndex, tr( "Callouts" ) );
821 if ( int tabIndex = mOptionsTab->indexOf( placementTab ); tabIndex >= 0 )
822 mOptionsTab->setTabToolTip( tabIndex, tr( "Placement" ) );
823 if ( int tabIndex = mOptionsTab->indexOf( renderingTab ); tabIndex >= 0 )
824 mOptionsTab->setTabToolTip( tabIndex, tr( "Rendering" ) );
825
826 mLabelingOptionsListFrame->setVisible( !enabled );
827 groupBox_mPreview->setVisible( !enabled );
828 mDockMode = enabled;
829}
830
831void QgsTextFormatWidget::connectValueChanged( const QList<QWidget *> &widgets )
832{
833 const auto constWidgets = widgets;
834 for ( QWidget *widget : constWidgets )
835 {
836 if ( QgsSymbolButton *w = qobject_cast<QgsSymbolButton *>( widget ) )
837 {
839 }
840 else if ( QgsFieldExpressionWidget *w = qobject_cast<QgsFieldExpressionWidget *>( widget ) )
841 {
842 connect( w, qOverload<const QString &>( &QgsFieldExpressionWidget::fieldChanged ), this, &QgsTextFormatWidget::updatePreview );
843 }
844 else if ( QgsOpacityWidget *w = qobject_cast<QgsOpacityWidget *>( widget ) )
845 {
847 }
848 else if ( QgsScaleWidget *w = qobject_cast<QgsScaleWidget *>( widget ) )
849 {
851 }
852 else if ( QgsUnitSelectionWidget *w = qobject_cast<QgsUnitSelectionWidget *>( widget ) )
853 {
855 }
856 else if ( QComboBox *w = qobject_cast<QComboBox *>( widget ) )
857 {
858 connect( w, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::updatePreview );
859 }
860 else if ( QSpinBox *w = qobject_cast<QSpinBox *>( widget ) )
861 {
862 connect( w, qOverload<int>( &QSpinBox::valueChanged ), this, &QgsTextFormatWidget::updatePreview );
863 }
864 else if ( QDoubleSpinBox *w = qobject_cast<QDoubleSpinBox *>( widget ) )
865 {
866 connect( w, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsTextFormatWidget::updatePreview );
867 }
868 else if ( QgsColorButton *w = qobject_cast<QgsColorButton *>( widget ) )
869 {
871 }
872 else if ( QCheckBox *w = qobject_cast<QCheckBox *>( widget ) )
873 {
874 connect( w, &QCheckBox::toggled, this, &QgsTextFormatWidget::updatePreview );
875 }
876 else if ( QRadioButton *w = qobject_cast<QRadioButton *>( widget ) )
877 {
878 connect( w, &QRadioButton::toggled, this, &QgsTextFormatWidget::updatePreview );
879 }
880 else if ( QLineEdit *w = qobject_cast<QLineEdit *>( widget ) )
881 {
882 connect( w, &QLineEdit::textEdited, this, &QgsTextFormatWidget::updatePreview );
883 }
884 else if ( QSlider *w = qobject_cast<QSlider *>( widget ) )
885 {
886 connect( w, &QSlider::valueChanged, this, &QgsTextFormatWidget::updatePreview );
887 }
888 else if ( QGroupBox *w = qobject_cast<QGroupBox *>( widget ) )
889 {
890 connect( w, &QGroupBox::toggled, this, &QgsTextFormatWidget::updatePreview );
891 }
892 else if ( QgsCodeEditorExpression *w = qobject_cast<QgsCodeEditorExpression *>( widget ) )
893 {
894 connect( w, &QgsCodeEditorExpression::textChanged, this, &QgsTextFormatWidget::updatePreview );
895 }
896 else
897 {
898 QgsLogger::warning( u"Could not create connection for widget %1"_s.arg( widget->objectName() ) );
899 }
900 }
901}
902
904{
905 // text style
906 registerDataDefinedButton( mFontDDBtn, QgsPalLayerSettings::Property::Family );
907 registerDataDefinedButton( mFontStyleDDBtn, QgsPalLayerSettings::Property::FontStyle );
908 registerDataDefinedButton( mFontUnderlineDDBtn, QgsPalLayerSettings::Property::Underline );
909 registerDataDefinedButton( mFontStrikeoutDDBtn, QgsPalLayerSettings::Property::Strikeout );
910 registerDataDefinedButton( mFontBoldDDBtn, QgsPalLayerSettings::Property::Bold );
911 registerDataDefinedButton( mFontItalicDDBtn, QgsPalLayerSettings::Property::Italic );
912 registerDataDefinedButton( mFontSizeDDBtn, QgsPalLayerSettings::Property::Size );
913 registerDataDefinedButton( mFontUnitsDDBtn, QgsPalLayerSettings::Property::FontSizeUnit );
914 registerDataDefinedButton( mFontColorDDBtn, QgsPalLayerSettings::Property::Color );
915 registerDataDefinedButton( mFontOpacityDDBtn, QgsPalLayerSettings::Property::FontOpacity );
916 registerDataDefinedButton( mFontCaseDDBtn, QgsPalLayerSettings::Property::FontCase );
917 registerDataDefinedButton( mFontLetterSpacingDDBtn, QgsPalLayerSettings::Property::FontLetterSpacing );
918 registerDataDefinedButton( mFontWordSpacingDDBtn, QgsPalLayerSettings::Property::FontWordSpacing );
919 registerDataDefinedButton( mFontBlendModeDDBtn, QgsPalLayerSettings::Property::FontBlendMode );
920 registerDataDefinedButton( mFontStretchDDBtn, QgsPalLayerSettings::Property::FontStretchFactor );
921 registerDataDefinedButton( mTabDistanceDDBtn, QgsPalLayerSettings::Property::TabStopDistance );
922
923 // text formatting
924 registerDataDefinedButton( mWrapCharDDBtn, QgsPalLayerSettings::Property::MultiLineWrapChar );
925 registerDataDefinedButton( mAutoWrapLengthDDBtn, QgsPalLayerSettings::Property::AutoWrapLength );
926 registerDataDefinedButton( mFontLineHeightDDBtn, QgsPalLayerSettings::Property::MultiLineHeight );
927 registerDataDefinedButton( mFontMultiLineAlignDDBtn, QgsPalLayerSettings::Property::MultiLineAlignment );
928 registerDataDefinedButton( mTextOrientationDDBtn, QgsPalLayerSettings::Property::TextOrientation );
929
930 registerDataDefinedButton( mDirectSymbDDBtn, QgsPalLayerSettings::Property::DirSymbDraw );
931 mDirectSymbDDBtn->registerCheckedWidget( mDirectSymbChkBx );
932 registerDataDefinedButton( mDirectSymbLeftDDBtn, QgsPalLayerSettings::Property::DirSymbLeft );
933 registerDataDefinedButton( mDirectSymbRightDDBtn, QgsPalLayerSettings::Property::DirSymbRight );
934
935 registerDataDefinedButton( mDirectSymbPlacementDDBtn, QgsPalLayerSettings::Property::DirSymbPlacement );
936 registerDataDefinedButton( mDirectSymbRevDDBtn, QgsPalLayerSettings::Property::DirSymbReverse );
937
938 registerDataDefinedButton( mFormatNumDDBtn, QgsPalLayerSettings::Property::NumFormat );
939 mFormatNumDDBtn->registerCheckedWidget( mFormatNumChkBx );
940 registerDataDefinedButton( mFormatNumDecimalsDDBtn, QgsPalLayerSettings::Property::NumDecimals );
941 registerDataDefinedButton( mFormatNumPlusSignDDBtn, QgsPalLayerSettings::Property::NumPlusSign );
942
943 // text buffer
944 registerDataDefinedButton( mBufferDrawDDBtn, QgsPalLayerSettings::Property::BufferDraw );
945 registerDataDefinedButton( mBufferSizeDDBtn, QgsPalLayerSettings::Property::BufferSize );
946 registerDataDefinedButton( mBufferUnitsDDBtn, QgsPalLayerSettings::Property::BufferUnit );
947 registerDataDefinedButton( mBufferColorDDBtn, QgsPalLayerSettings::Property::BufferColor );
948 registerDataDefinedButton( mBufferOpacityDDBtn, QgsPalLayerSettings::Property::BufferOpacity );
949 registerDataDefinedButton( mBufferJoinStyleDDBtn, QgsPalLayerSettings::Property::BufferJoinStyle );
950 registerDataDefinedButton( mBufferBlendModeDDBtn, QgsPalLayerSettings::Property::BufferBlendMode );
951
952 // mask
953 registerDataDefinedButton( mEnableMaskDDBtn, QgsPalLayerSettings::Property::MaskEnabled );
954 mEnableMaskDDBtn->registerCheckedWidget( mEnableMaskChkBx );
955 registerDataDefinedButton( mMaskBufferSizeDDBtn, QgsPalLayerSettings::Property::MaskBufferSize );
956 registerDataDefinedButton( mMaskBufferUnitsDDBtn, QgsPalLayerSettings::Property::MaskBufferUnit );
957 registerDataDefinedButton( mMaskOpacityDDBtn, QgsPalLayerSettings::Property::MaskOpacity );
958 registerDataDefinedButton( mMaskJoinStyleDDBtn, QgsPalLayerSettings::Property::MaskJoinStyle );
959
960 // background
961 registerDataDefinedButton( mShapeDrawDDBtn, QgsPalLayerSettings::Property::ShapeDraw );
962 mShapeDrawDDBtn->registerCheckedWidget( mShapeDrawChkBx );
963 registerDataDefinedButton( mShapeTypeDDBtn, QgsPalLayerSettings::Property::ShapeKind );
964 registerDataDefinedButton( mShapeSVGPathDDBtn, QgsPalLayerSettings::Property::ShapeSVGFile );
965 registerDataDefinedButton( mShapeSizeTypeDDBtn, QgsPalLayerSettings::Property::ShapeSizeType );
966 registerDataDefinedButton( mShapeSizeXDDBtn, QgsPalLayerSettings::Property::ShapeSizeX );
967 registerDataDefinedButton( mShapeSizeYDDBtn, QgsPalLayerSettings::Property::ShapeSizeY );
968 registerDataDefinedButton( mShapeSizeUnitsDDBtn, QgsPalLayerSettings::Property::ShapeSizeUnits );
969 registerDataDefinedButton( mShapeRotationTypeDDBtn, QgsPalLayerSettings::Property::ShapeRotationType );
970 registerDataDefinedButton( mShapeRotationDDBtn, QgsPalLayerSettings::Property::ShapeRotation );
971 registerDataDefinedButton( mShapeOffsetDDBtn, QgsPalLayerSettings::Property::ShapeOffset );
972 registerDataDefinedButton( mShapeOffsetUnitsDDBtn, QgsPalLayerSettings::Property::ShapeOffsetUnits );
973 registerDataDefinedButton( mShapeRadiusDDBtn, QgsPalLayerSettings::Property::ShapeRadii );
974 registerDataDefinedButton( mShapeRadiusUnitsDDBtn, QgsPalLayerSettings::Property::ShapeRadiiUnits );
975 registerDataDefinedButton( mShapeOpacityDDBtn, QgsPalLayerSettings::Property::ShapeOpacity );
976 registerDataDefinedButton( mShapeBlendModeDDBtn, QgsPalLayerSettings::Property::ShapeBlendMode );
977 registerDataDefinedButton( mShapeFillColorDDBtn, QgsPalLayerSettings::Property::ShapeFillColor );
978 registerDataDefinedButton( mShapeStrokeColorDDBtn, QgsPalLayerSettings::Property::ShapeStrokeColor );
979 registerDataDefinedButton( mShapeStrokeWidthDDBtn, QgsPalLayerSettings::Property::ShapeStrokeWidth );
980 registerDataDefinedButton( mShapeStrokeUnitsDDBtn, QgsPalLayerSettings::Property::ShapeStrokeWidthUnits );
981
982 // drop shadows
983 registerDataDefinedButton( mShadowDrawDDBtn, QgsPalLayerSettings::Property::ShadowDraw );
984 mShadowDrawDDBtn->registerCheckedWidget( mShadowDrawChkBx );
985 registerDataDefinedButton( mShadowUnderDDBtn, QgsPalLayerSettings::Property::ShadowUnder );
986 registerDataDefinedButton( mShadowOffsetAngleDDBtn, QgsPalLayerSettings::Property::ShadowOffsetAngle );
987 registerDataDefinedButton( mShadowOffsetDDBtn, QgsPalLayerSettings::Property::ShadowOffsetDist );
988 registerDataDefinedButton( mShadowOffsetUnitsDDBtn, QgsPalLayerSettings::Property::ShadowOffsetUnits );
989 registerDataDefinedButton( mShadowRadiusDDBtn, QgsPalLayerSettings::Property::ShadowRadius );
990 registerDataDefinedButton( mShadowRadiusUnitsDDBtn, QgsPalLayerSettings::Property::ShadowRadiusUnits );
991 registerDataDefinedButton( mShadowOpacityDDBtn, QgsPalLayerSettings::Property::ShadowOpacity );
992 registerDataDefinedButton( mShadowScaleDDBtn, QgsPalLayerSettings::Property::ShadowScale );
993 registerDataDefinedButton( mShadowColorDDBtn, QgsPalLayerSettings::Property::ShadowColor );
994 registerDataDefinedButton( mShadowBlendDDBtn, QgsPalLayerSettings::Property::ShadowBlendMode );
995
996 // placement
997 registerDataDefinedButton( mCentroidDDBtn, QgsPalLayerSettings::Property::CentroidWhole );
998 registerDataDefinedButton( mPointQuadOffsetDDBtn, QgsPalLayerSettings::Property::OffsetQuad );
999 registerDataDefinedButton( mPointPositionOrderDDBtn, QgsPalLayerSettings::Property::PredefinedPositionOrder );
1000 registerDataDefinedButton( mLinePlacementFlagsDDBtn, QgsPalLayerSettings::Property::LinePlacementOptions );
1001 registerDataDefinedButton( mPointOffsetDDBtn, QgsPalLayerSettings::Property::OffsetXY );
1002 registerDataDefinedButton( mPointOffsetUnitsDDBtn, QgsPalLayerSettings::Property::OffsetUnits );
1003 registerDataDefinedButton( mLineDistanceDDBtn, QgsPalLayerSettings::Property::LabelDistance );
1004 registerDataDefinedButton( mLineDistanceUnitDDBtn, QgsPalLayerSettings::Property::DistanceUnits );
1005 registerDataDefinedButton( mMaximumDistanceDDBtn, QgsPalLayerSettings::Property::MaximumDistance );
1006 registerDataDefinedButton( mPriorityDDBtn, QgsPalLayerSettings::Property::Priority );
1007 registerDataDefinedButton( mAllowOutsidePolygonsDDBtn, QgsPalLayerSettings::Property::PolygonLabelOutside );
1008 registerDataDefinedButton( mAllowInferiorPlacementDBtn, QgsPalLayerSettings::Property::AllowDegradedPlacement );
1009 registerDataDefinedButton( mOverlapHandlingDBtn, QgsPalLayerSettings::Property::OverlapHandling );
1010 registerDataDefinedButton( mCurvedLabelModeDDBtn, QgsPalLayerSettings::Property::CurvedLabelMode );
1011 registerDataDefinedButton( mWhitespaceDDBtn, QgsPalLayerSettings::Property::WhitespaceCollisionHandling );
1012
1013 // TODO: is this necessary? maybe just use the data defined-only rotation?
1014 //mPointAngleDDBtn, QgsPalLayerSettings::OffsetRotation,
1015 // QgsPropertyOverrideButton::AnyType, QgsPropertyOverrideButton::double180RotDesc() );
1016 registerDataDefinedButton( mMaxCharAngleDDBtn, QgsPalLayerSettings::Property::CurvedCharAngleInOut );
1017 registerDataDefinedButton( mRepeatDistanceDDBtn, QgsPalLayerSettings::Property::RepeatDistance );
1018 registerDataDefinedButton( mRepeatDistanceUnitDDBtn, QgsPalLayerSettings::Property::RepeatDistanceUnit );
1019 registerDataDefinedButton( mOverrunDistanceDDBtn, QgsPalLayerSettings::Property::OverrunDistance );
1020
1021 registerDataDefinedButton( mLabelMarginDDBtn, QgsPalLayerSettings::Property::LabelMarginDistance );
1022
1023 // data defined-only
1024 registerDataDefinedButton( mCoordXDDBtn, QgsPalLayerSettings::Property::PositionX );
1025 registerDataDefinedButton( mCoordYDDBtn, QgsPalLayerSettings::Property::PositionY );
1026 registerDataDefinedButton( mCoordPointDDBtn, QgsPalLayerSettings::Property::PositionPoint );
1027 registerDataDefinedButton( mCoordAlignmentHDDBtn, QgsPalLayerSettings::Property::Hali );
1028 registerDataDefinedButton( mCoordAlignmentVDDBtn, QgsPalLayerSettings::Property::Vali );
1029 registerDataDefinedButton( mCoordRotationDDBtn, QgsPalLayerSettings::Property::LabelRotation );
1030
1031 updateDataDefinedAlignment();
1032
1033 // rendering
1034 const QString ddScaleVisInfo = tr(
1035 "Value &lt; 0 represents a scale closer than 1:1, e.g. -10 = 10:1<br>"
1036 "Value of 0 disables the specific limit."
1037 );
1038 registerDataDefinedButton( mScaleBasedVisibilityDDBtn, QgsPalLayerSettings::Property::ScaleVisibility );
1039 mScaleBasedVisibilityDDBtn->registerCheckedWidget( mScaleBasedVisibilityChkBx );
1040 registerDataDefinedButton( mScaleBasedVisibilityMinDDBtn, QgsPalLayerSettings::Property::MinimumScale );
1041 mScaleBasedVisibilityMinDDBtn->setUsageInfo( ddScaleVisInfo );
1042 registerDataDefinedButton( mScaleBasedVisibilityMaxDDBtn, QgsPalLayerSettings::Property::MaximumScale );
1043 mScaleBasedVisibilityMaxDDBtn->setUsageInfo( ddScaleVisInfo );
1044
1045 // use either global scales or project scales
1046 if ( QgsProject::instance()->viewSettings()->useProjectScales() )
1047 {
1048 const QVector<double> scales = QgsProject::instance()->viewSettings()->mapScales();
1049 mMinScaleWidget->setPredefinedScales( scales );
1050 mMaxScaleWidget->setPredefinedScales( scales );
1051 }
1052 else
1053 {
1054 // use global scales
1055 mMinScaleWidget->updateScales();
1056 mMaxScaleWidget->updateScales();
1057 }
1058
1059 registerDataDefinedButton( mFontLimitPixelDDBtn, QgsPalLayerSettings::Property::FontLimitPixel );
1060 mFontLimitPixelDDBtn->registerCheckedWidget( mFontLimitPixelChkBox );
1061 registerDataDefinedButton( mFontMinPixelDDBtn, QgsPalLayerSettings::Property::FontMinPixel );
1062 registerDataDefinedButton( mFontMaxPixelDDBtn, QgsPalLayerSettings::Property::FontMaxPixel );
1063
1064 registerDataDefinedButton( mShowLabelDDBtn, QgsPalLayerSettings::Property::Show );
1065
1066 registerDataDefinedButton( mAlwaysShowDDBtn, QgsPalLayerSettings::Property::AlwaysShow );
1067
1068 registerDataDefinedButton( mIsObstacleDDBtn, QgsPalLayerSettings::Property::IsObstacle );
1069 registerDataDefinedButton( mZIndexDDBtn, QgsPalLayerSettings::Property::ZIndex );
1070
1071 registerDataDefinedButton( mCalloutDrawDDBtn, QgsPalLayerSettings::Property::CalloutDraw );
1072
1073 registerDataDefinedButton( mLabelAllPartsDDBtn, QgsPalLayerSettings::Property::LabelAllParts );
1074
1075 registerDataDefinedButton( mNoDuplicatesDDBtn, QgsPalLayerSettings::Property::RemoveDuplicateLabels );
1076}
1077
1078void QgsTextFormatWidget::registerDataDefinedButton( QgsPropertyOverrideButton *button, QgsPalLayerSettings::Property key )
1079{
1080 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
1081
1082 button->init( static_cast<int>( key ), mDataDefinedProperties, QgsPalLayerSettings::propertyDefinitions(), vLayer, true );
1083 if ( !mButtons.contains( key ) )
1084 {
1085 connect( button, &QgsPropertyOverrideButton::changed, this, &QgsTextFormatWidget::updateProperty );
1086 connect( button, &QgsPropertyOverrideButton::createAuxiliaryField, this, &QgsTextFormatWidget::createAuxiliaryField );
1087 button->registerExpressionContextGenerator( this );
1088 mButtons[key] = button;
1089 }
1090}
1091
1093{
1094 const QgsTextBufferSettings buffer = format.buffer();
1095 const QgsTextMaskSettings mask = format.mask();
1096 const QgsTextBackgroundSettings background = format.background();
1097 const QgsTextShadowSettings shadow = format.shadow();
1098
1099 if ( mWidgetMode != Labeling )
1100 {
1101 mDataDefinedProperties = format.dataDefinedProperties();
1102 }
1103
1104 mTabPositions = format.tabPositions();
1105 mTabStopDistanceSpin->setEnabled( mTabPositions.empty() );
1106
1107 // buffer
1108 mBufferDrawChkBx->setChecked( buffer.enabled() );
1109 mBufferFrame->setEnabled( buffer.enabled() );
1110 spinBufferSize->setValue( buffer.size() );
1111 mBufferUnitWidget->setUnit( buffer.sizeUnit() );
1112 mBufferUnitWidget->setMapUnitScale( buffer.sizeMapUnitScale() );
1113 btnBufferColor->setColor( buffer.color() );
1114 mBufferOpacityWidget->setOpacity( buffer.opacity() );
1115 mBufferJoinStyleComboBox->setPenJoinStyle( buffer.joinStyle() );
1116 mBufferTranspFillChbx->setChecked( buffer.fillBufferInterior() );
1117 comboBufferBlendMode->setBlendMode( buffer.blendMode() );
1118 if ( auto *lPaintEffect = buffer.paintEffect() )
1119 mBufferEffect.reset( lPaintEffect->clone() );
1120 else
1121 {
1122 mBufferEffect.reset( QgsPaintEffectRegistry::defaultStack() );
1123 mBufferEffect->setEnabled( false );
1124 }
1125 mBufferEffectWidget->setPaintEffect( mBufferEffect.get() );
1126
1127 // mask
1129 mEnableMaskChkBx->setChecked( mask.enabled() );
1130 mMaskBufferSizeSpinBox->setValue( mask.size() );
1131 mMaskBufferUnitWidget->setUnit( mask.sizeUnit() );
1132 mMaskBufferUnitWidget->setMapUnitScale( mask.sizeMapUnitScale() );
1133 mMaskOpacityWidget->setOpacity( mask.opacity() );
1134 mMaskJoinStyleComboBox->setPenJoinStyle( mask.joinStyle() );
1135 if ( auto *lPaintEffect = mask.paintEffect() )
1136 mMaskEffect.reset( lPaintEffect->clone() );
1137 else
1138 {
1139 mMaskEffect.reset( QgsPaintEffectRegistry::defaultStack() );
1140 mMaskEffect->setEnabled( false );
1141 }
1142 mMaskEffectWidget->setPaintEffect( mMaskEffect.get() );
1143
1144 mFontSizeUnitWidget->setUnit( format.sizeUnit() );
1145 mFontSizeUnitWidget->setMapUnitScale( format.sizeMapUnitScale() );
1146 mRefFont = format.font();
1147 mFontSizeSpinBox->setValue( format.size() );
1148 btnTextColor->setColor( format.color() );
1149 whileBlocking( mSpinStretch )->setValue( format.stretchFactor() );
1150 mTextOpacityWidget->setOpacity( format.opacity() );
1151 comboBlendMode->setBlendMode( format.blendMode() );
1152 mTextOrientationComboBox->setCurrentIndex( mTextOrientationComboBox->findData( static_cast<int>( format.orientation() ) ) );
1153 mHtmlFormattingCheckBox->setChecked( format.allowHtmlFormatting() );
1154
1155 mFontWordSpacingSpinBox->setValue( format.font().wordSpacing() );
1156 mFontLetterSpacingSpinBox->setValue( format.font().letterSpacing() );
1157 whileBlocking( mKerningCheckBox )->setChecked( format.font().kerning() );
1158
1159 mTabDistanceUnitWidget->setUnit( format.tabStopDistanceUnit() );
1160 mTabDistanceUnitWidget->setMapUnitScale( format.tabStopDistanceMapUnitScale() );
1161 whileBlocking( mTabStopDistanceSpin )->setValue( format.tabStopDistanceUnit() == Qgis::RenderUnit::Percentage ? ( format.tabStopDistance() * 100 ) : format.tabStopDistance() );
1162
1163 whileBlocking( mFontCapitalsComboBox )->setCurrentIndex( mFontCapitalsComboBox->findData( static_cast<int>( format.capitalization() ) ) );
1164 QgsFontUtils::updateFontViaStyle( mRefFont, format.namedStyle() );
1165 updateFont( mRefFont );
1166
1167 // show 'font not found' if substitution has occurred (should come after updateFont())
1168 mFontMissingLabel->setVisible( !format.fontFound() );
1169 if ( !format.fontFound() )
1170 {
1171 const QString missingTxt = tr( "%1 not found. Default substituted." );
1172 QString txtPrepend = tr( "Chosen font" );
1173 if ( !format.resolvedFontFamily().isEmpty() )
1174 {
1175 txtPrepend = u"'%1'"_s.arg( format.resolvedFontFamily() );
1176 }
1177 mFontMissingLabel->setText( missingTxt.arg( txtPrepend ) );
1178
1179 // ensure user is sent to 'Text style' section to see notice
1180 mLabelingOptionsListWidget->setCurrentItem( mTextItem );
1181 whileBlocking( mOptionsTab )->setCurrentIndex( mOptionsTab->indexOf( textTab ) );
1182 }
1183 mFontLineHeightSpinBox->setValue( format.lineHeightUnit() == Qgis::RenderUnit::Percentage ? ( format.lineHeight() * 100 ) : format.lineHeight() );
1184 mLineHeightUnitWidget->setUnit( format.lineHeightUnit() );
1185
1186 // shape background
1187 mShapeDrawChkBx->setChecked( background.enabled() );
1188 mShapeFrame->setEnabled( background.enabled() );
1189 mShapeTypeCmbBx->blockSignals( true );
1190 mShapeTypeCmbBx->setCurrentIndex( mShapeTypeCmbBx->findData( background.type() ) );
1191 mShapeTypeCmbBx->blockSignals( false );
1192 updateAvailableShadowPositions();
1193 mShapeSVGPathLineEdit->setText( background.svgFile() );
1194
1195 mShapeSizeCmbBx->setCurrentIndex( background.sizeType() );
1196 mShapeSizeXSpnBx->setValue( background.size().width() );
1197 mShapeSizeYSpnBx->setValue( background.size().height() );
1198 mShapeSizeUnitWidget->setUnit( background.sizeUnit() );
1199 mShapeSizeUnitWidget->setMapUnitScale( background.sizeMapUnitScale() );
1200 mShapeRotationCmbBx->setCurrentIndex( background.rotationType() );
1201 mShapeRotationDblSpnBx->setEnabled( background.rotationType() != QgsTextBackgroundSettings::RotationSync );
1202 mShapeRotationDDBtn->setEnabled( background.rotationType() != QgsTextBackgroundSettings::RotationSync );
1203 mShapeRotationDblSpnBx->setValue( background.rotation() );
1204 mShapeOffsetXSpnBx->setValue( background.offset().x() );
1205 mShapeOffsetYSpnBx->setValue( background.offset().y() );
1206 mShapeOffsetUnitWidget->setUnit( background.offsetUnit() );
1207 mShapeOffsetUnitWidget->setMapUnitScale( background.offsetMapUnitScale() );
1208 mShapeRadiusXDbSpnBx->setValue( background.radii().width() );
1209 mShapeRadiusYDbSpnBx->setValue( background.radii().height() );
1210 mShapeRadiusUnitWidget->setUnit( background.radiiUnit() );
1211 mShapeRadiusUnitWidget->setMapUnitScale( background.radiiMapUnitScale() );
1212
1213 mShapeFillColorBtn->setColor( background.fillColor() );
1214 mShapeStrokeColorBtn->setColor( background.strokeColor() );
1215 mShapeStrokeWidthSpnBx->setValue( background.strokeWidth() );
1216 mShapeStrokeWidthUnitWidget->setUnit( background.strokeWidthUnit() );
1217 mShapeStrokeWidthUnitWidget->setMapUnitScale( background.strokeWidthMapUnitScale() );
1218
1219 mBackgroundOpacityWidget->setOpacity( background.opacity() );
1220 mShapeBlendCmbBx->setBlendMode( background.blendMode() );
1221
1222 mLoadSvgParams = false;
1223 mShapeTypeCmbBx_currentIndexChanged( background.type() ); // force update of shape background gui
1224
1225 if ( auto *lPaintEffect = background.paintEffect() )
1226 mBackgroundEffect.reset( lPaintEffect->clone() );
1227 else
1228 {
1229 mBackgroundEffect.reset( QgsPaintEffectRegistry::defaultStack() );
1230 mBackgroundEffect->setEnabled( false );
1231 }
1232 mBackgroundEffectWidget->setPaintEffect( mBackgroundEffect.get() );
1233
1234 mBackgroundMarkerSymbolButton->setSymbol( background.markerSymbol() ? background.markerSymbol()->clone() : QgsSymbol::defaultSymbol( Qgis::GeometryType::Point ) );
1235 mBackgroundFillSymbolButton->setSymbol( background.fillSymbol() ? background.fillSymbol()->clone() : QgsSymbol::defaultSymbol( Qgis::GeometryType::Polygon ) );
1236
1237 // drop shadow
1238 mShadowDrawChkBx->setChecked( shadow.enabled() );
1239 mShadowFrame->setEnabled( shadow.enabled() );
1240 mShadowUnderCmbBx->setCurrentIndex( mShadowUnderCmbBx->findData( shadow.shadowPlacement() ) );
1241 mShadowOffsetAngleSpnBx->setValue( shadow.offsetAngle() );
1242 mShadowOffsetSpnBx->setValue( shadow.offsetDistance() );
1243 mShadowOffsetUnitWidget->setUnit( shadow.offsetUnit() );
1244 mShadowOffsetUnitWidget->setMapUnitScale( shadow.offsetMapUnitScale() );
1245 mShadowOffsetGlobalChkBx->setChecked( shadow.offsetGlobal() );
1246
1247 mShadowRadiusDblSpnBx->setValue( shadow.blurRadius() );
1248 mShadowRadiusUnitWidget->setUnit( shadow.blurRadiusUnit() );
1249 mShadowRadiusUnitWidget->setMapUnitScale( shadow.blurRadiusMapUnitScale() );
1250 mShadowRadiusAlphaChkBx->setChecked( shadow.blurAlphaOnly() );
1251 mShadowOpacityWidget->setOpacity( shadow.opacity() );
1252 mShadowScaleSpnBx->setValue( shadow.scale() );
1253
1254 mShadowColorBtn->setColor( shadow.color() );
1255 mShadowBlendCmbBx->setBlendMode( shadow.blendMode() );
1256
1257 mPreviewBackgroundBtn->setColor( format.previewBackgroundColor() );
1258 mPreviewBackgroundBtn->setDefaultColor( format.previewBackgroundColor() );
1259 setPreviewBackground( format.previewBackgroundColor() );
1260
1262}
1263
1265{
1266 QgsSettings settings;
1267 settings.setValue( u"Windows/Labeling/FontPreviewSplitState"_s, mFontPreviewSplitter->saveState() );
1268 settings.setValue( u"Windows/Labeling/OptionsSplitState"_s, mLabelingOptionsSplitter->saveState() );
1269
1270 int prevIndex = mLabelingOptionsListWidget->currentRow();
1271 if ( mWidgetMode == Text )
1272 {
1273 switch ( prevIndex )
1274 {
1275 case 3: // background - account for removed mask tab
1276 case 4: // shadow - account for removed mask tab
1277 prevIndex++;
1278 break;
1279 }
1280 }
1281
1282 settings.setValue( u"Windows/Labeling/Tab"_s, prevIndex );
1283}
1284
1285QgsTextFormat QgsTextFormatWidget::format( bool includeDataDefinedProperties ) const
1286{
1288 format.setColor( btnTextColor->color() );
1289 format.setFont( mRefFont );
1290 format.setSize( mFontSizeSpinBox->value() );
1291 format.setNamedStyle( mFontStyleComboBox->currentText() );
1292 format.setOpacity( mTextOpacityWidget->opacity() );
1293 format.setStretchFactor( mSpinStretch->value() );
1294 format.setBlendMode( comboBlendMode->blendMode() );
1295 format.setSizeUnit( mFontSizeUnitWidget->unit() );
1296 format.setSizeMapUnitScale( mFontSizeUnitWidget->getMapUnitScale() );
1297 format.setLineHeight( mLineHeightUnitWidget->unit() == Qgis::RenderUnit::Percentage ? ( mFontLineHeightSpinBox->value() / 100 ) : mFontLineHeightSpinBox->value() );
1298 format.setLineHeightUnit( mLineHeightUnitWidget->unit() );
1299 format.setPreviewBackgroundColor( mPreviewBackgroundColor );
1300 format.setOrientation( static_cast<Qgis::TextOrientation>( mTextOrientationComboBox->currentData().toInt() ) );
1301 format.setAllowHtmlFormatting( mHtmlFormattingCheckBox->isChecked() );
1302 format.setCapitalization( static_cast<Qgis::Capitalization>( mFontCapitalsComboBox->currentData().toInt() ) );
1303 format.setTabStopDistance( mTabDistanceUnitWidget->unit() == Qgis::RenderUnit::Percentage ? ( mTabStopDistanceSpin->value() / 100 ) : mTabStopDistanceSpin->value() );
1304 format.setTabStopDistanceUnit( mTabDistanceUnitWidget->unit() );
1305 format.setTabStopDistanceMapUnitScale( mTabDistanceUnitWidget->getMapUnitScale() );
1306 format.setTabPositions( mTabPositions );
1307
1308 // buffer
1309 QgsTextBufferSettings buffer;
1310 buffer.setEnabled( mBufferDrawChkBx->isChecked() );
1311 buffer.setSize( spinBufferSize->value() );
1312 buffer.setColor( btnBufferColor->color() );
1313 buffer.setOpacity( mBufferOpacityWidget->opacity() );
1314 buffer.setSizeUnit( mBufferUnitWidget->unit() );
1315 buffer.setSizeMapUnitScale( mBufferUnitWidget->getMapUnitScale() );
1316 buffer.setJoinStyle( mBufferJoinStyleComboBox->penJoinStyle() );
1317 buffer.setFillBufferInterior( mBufferTranspFillChbx->isChecked() );
1318 buffer.setBlendMode( comboBufferBlendMode->blendMode() );
1319 if ( mBufferEffect && ( !QgsPaintEffectRegistry::isDefaultStack( mBufferEffect.get() ) || mBufferEffect->enabled() ) )
1320 buffer.setPaintEffect( mBufferEffect->clone() );
1321 else
1322 buffer.setPaintEffect( nullptr );
1323 format.setBuffer( buffer );
1324
1325 // mask
1327 mask.setEnabled( mEnableMaskChkBx->isChecked() );
1328 mask.setSize( mMaskBufferSizeSpinBox->value() );
1329 mask.setOpacity( mMaskOpacityWidget->opacity() );
1330 mask.setSizeUnit( mMaskBufferUnitWidget->unit() );
1331 mask.setSizeMapUnitScale( mMaskBufferUnitWidget->getMapUnitScale() );
1332 mask.setJoinStyle( mMaskJoinStyleComboBox->penJoinStyle() );
1333 if ( mMaskEffect && ( !QgsPaintEffectRegistry::isDefaultStack( mMaskEffect.get() ) || mMaskEffect->enabled() ) )
1334 mask.setPaintEffect( mMaskEffect->clone() );
1335 else
1336 mask.setPaintEffect( nullptr );
1338 format.setMask( mask );
1339
1340 // shape background
1341 QgsTextBackgroundSettings background;
1342 background.setEnabled( mShapeDrawChkBx->isChecked() );
1343 background.setType( static_cast<QgsTextBackgroundSettings::ShapeType>( mShapeTypeCmbBx->currentData().toInt() ) );
1344 background.setSvgFile( mShapeSVGPathLineEdit->text() );
1345 background.setSizeType( static_cast<QgsTextBackgroundSettings::SizeType>( mShapeSizeCmbBx->currentIndex() ) );
1346 background.setSize( QSizeF( mShapeSizeXSpnBx->value(), mShapeSizeYSpnBx->value() ) );
1347 background.setSizeUnit( mShapeSizeUnitWidget->unit() );
1348 background.setSizeMapUnitScale( mShapeSizeUnitWidget->getMapUnitScale() );
1349 background.setRotationType( static_cast<QgsTextBackgroundSettings::RotationType>( mShapeRotationCmbBx->currentIndex() ) );
1350 background.setRotation( mShapeRotationDblSpnBx->value() );
1351 background.setOffset( QPointF( mShapeOffsetXSpnBx->value(), mShapeOffsetYSpnBx->value() ) );
1352 background.setOffsetUnit( mShapeOffsetUnitWidget->unit() );
1353 background.setOffsetMapUnitScale( mShapeOffsetUnitWidget->getMapUnitScale() );
1354 background.setRadii( QSizeF( mShapeRadiusXDbSpnBx->value(), mShapeRadiusYDbSpnBx->value() ) );
1355 background.setRadiiUnit( mShapeRadiusUnitWidget->unit() );
1356 background.setRadiiMapUnitScale( mShapeRadiusUnitWidget->getMapUnitScale() );
1357
1358 background.setFillColor( mShapeFillColorBtn->color() );
1359 background.setStrokeColor( mShapeStrokeColorBtn->color() );
1360 background.setStrokeWidth( mShapeStrokeWidthSpnBx->value() );
1361 background.setStrokeWidthUnit( mShapeStrokeWidthUnitWidget->unit() );
1362 background.setStrokeWidthMapUnitScale( mShapeStrokeWidthUnitWidget->getMapUnitScale() );
1363 background.setOpacity( mBackgroundOpacityWidget->opacity() );
1364 background.setBlendMode( mShapeBlendCmbBx->blendMode() );
1365 if ( mBackgroundEffect && ( !QgsPaintEffectRegistry::isDefaultStack( mBackgroundEffect.get() ) || mBackgroundEffect->enabled() ) )
1366 background.setPaintEffect( mBackgroundEffect->clone() );
1367 else
1368 background.setPaintEffect( nullptr );
1369 background.setMarkerSymbol( mBackgroundMarkerSymbolButton->clonedSymbol<QgsMarkerSymbol>() );
1370 background.setFillSymbol( mBackgroundFillSymbolButton->clonedSymbol<QgsFillSymbol>() );
1371 format.setBackground( background );
1372
1373 // drop shadow
1374 QgsTextShadowSettings shadow;
1375 shadow.setEnabled( mShadowDrawChkBx->isChecked() );
1376 shadow.setShadowPlacement( static_cast<QgsTextShadowSettings::ShadowPlacement>( mShadowUnderCmbBx->currentData().toInt() ) );
1377 shadow.setOffsetAngle( mShadowOffsetAngleSpnBx->value() );
1378 shadow.setOffsetDistance( mShadowOffsetSpnBx->value() );
1379 shadow.setOffsetUnit( mShadowOffsetUnitWidget->unit() );
1380 shadow.setOffsetMapUnitScale( mShadowOffsetUnitWidget->getMapUnitScale() );
1381 shadow.setOffsetGlobal( mShadowOffsetGlobalChkBx->isChecked() );
1382 shadow.setBlurRadius( mShadowRadiusDblSpnBx->value() );
1383 shadow.setBlurRadiusUnit( mShadowRadiusUnitWidget->unit() );
1384 shadow.setBlurRadiusMapUnitScale( mShadowRadiusUnitWidget->getMapUnitScale() );
1385 shadow.setBlurAlphaOnly( mShadowRadiusAlphaChkBx->isChecked() );
1386 shadow.setOpacity( mShadowOpacityWidget->opacity() );
1387 shadow.setScale( mShadowScaleSpnBx->value() );
1388 shadow.setColor( mShadowColorBtn->color() );
1389 shadow.setBlendMode( mShadowBlendCmbBx->blendMode() );
1390 format.setShadow( shadow );
1391
1392 if ( includeDataDefinedProperties )
1393 format.setDataDefinedProperties( mDataDefinedProperties );
1394
1395 return format;
1396}
1397
1399{
1400 if ( mWidgetMode != Labeling )
1401 {
1402 // we need to combine any data defined properties from the text format with existing ones from the label settings
1403 const QgsPropertyCollection formatProps = format.dataDefinedProperties();
1404 for ( const int key : formatProps.propertyKeys() )
1405 {
1406 if ( formatProps.isActive( key ) )
1407 {
1408 mDataDefinedProperties.setProperty( key, formatProps.property( key ) );
1409 }
1410 }
1411 }
1412
1414}
1415
1420
1422{
1423 if ( mButtons.contains( key ) )
1424 {
1425 QgsPropertyOverrideButton *button = mButtons[key];
1426 button->updateFieldLists();
1427 button->setToProperty( QgsProperty() );
1428 mDataDefinedProperties.setProperty( key, QgsProperty() );
1429 }
1430}
1431
1432void QgsTextFormatWidget::optionsStackedWidget_CurrentChanged( int )
1433{
1434 mLabelingOptionsListWidget->blockSignals( true );
1435 QWidget *currentPage = mLabelStackedWidget->currentWidget();
1436 if ( currentPage == mLabelPage_Text )
1437 mLabelingOptionsListWidget->setCurrentItem( mTextItem );
1438 else if ( currentPage == mLabelPage_Formatting )
1439 mLabelingOptionsListWidget->setCurrentItem( mFormattingItem );
1440 else if ( currentPage == mLabelPage_Mask )
1441 mLabelingOptionsListWidget->setCurrentItem( mMaskItem );
1442 if ( currentPage == mLabelPage_Buffer )
1443 mLabelingOptionsListWidget->setCurrentItem( mBufferItem );
1444 if ( currentPage == mLabelPage_Background )
1445 mLabelingOptionsListWidget->setCurrentItem( mBackgroundItem );
1446 if ( currentPage == mLabelPage_Shadow )
1447 mLabelingOptionsListWidget->setCurrentItem( mShadowItem );
1448 if ( currentPage == mLabelPage_Callouts )
1449 mLabelingOptionsListWidget->setCurrentItem( mCalloutItem );
1450 if ( currentPage == mLabelPage_Rendering )
1451 mLabelingOptionsListWidget->setCurrentItem( mRenderingItem );
1452 if ( currentPage == mLabelPage_Placement )
1453 mLabelingOptionsListWidget->setCurrentItem( mPlacementItem );
1454 mLabelingOptionsListWidget->blockSignals( false );
1455}
1456
1458{
1459 mContext = context;
1460
1461 if ( auto *lExpressionContext = mContext.expressionContext() )
1462 {
1463 mPreviewExpressionContext = *lExpressionContext;
1464 if ( mLayer )
1465 mPreviewExpressionContext.appendScope( QgsExpressionContextUtils::layerScope( mLayer ) );
1466 }
1467
1468 const auto symbolButtonWidgets = findChildren<QgsSymbolButton *>();
1469 for ( QgsSymbolButton *symbolWidget : symbolButtonWidgets )
1470 {
1471 symbolWidget->setMapCanvas( mContext.mapCanvas() );
1472 symbolWidget->setMessageBar( mContext.messageBar() );
1473 }
1474}
1475
1476void QgsTextFormatWidget::collapseSample( bool collapse )
1477{
1478 if ( collapse )
1479 {
1480 QList<int> splitSizes = mFontPreviewSplitter->sizes();
1481 if ( splitSizes[0] > groupBox_mPreview->height() )
1482 {
1483 const int delta = splitSizes[0] - groupBox_mPreview->height();
1484 splitSizes[0] -= delta;
1485 splitSizes[1] += delta;
1486 mFontPreviewSplitter->setSizes( splitSizes );
1487 }
1488 }
1489}
1490
1491void QgsTextFormatWidget::changeTextColor( const QColor &color )
1492{
1493 Q_UNUSED( color )
1494 updatePreview();
1495}
1496
1497void QgsTextFormatWidget::updateFont( const QFont &newFont )
1498{
1499 // update background reference font
1500 if ( newFont != mRefFont )
1501 {
1502 mRefFont = newFont;
1503 }
1504
1505 // test if font is actually available
1506 // NOTE: QgsFontUtils::fontMatchOnSystem may fail here, just crosscheck family
1507 mFontMissingLabel->setVisible( !QgsFontUtils::fontFamilyMatchOnSystem( mRefFont.family() ) );
1508
1509 QFont symbolFont = mRefFont;
1510 symbolFont.setPointSize( font().pointSize() );
1511 mDirectSymbLeftLineEdit->setFont( symbolFont );
1512 mDirectSymbRightLineEdit->setFont( symbolFont );
1513
1514 blockFontChangeSignals( true );
1515 mFontFamilyCmbBx->setCurrentFont( symbolFont );
1516 populateFontStyleComboBox();
1517 mFontUnderlineBtn->setChecked( mRefFont.underline() );
1518 mFontStrikethroughBtn->setChecked( mRefFont.strikeOut() );
1519 mKerningCheckBox->setChecked( mRefFont.kerning() );
1520 blockFontChangeSignals( false );
1521
1522 // update font name with font face
1523 // font.setPixelSize( 24 );
1524
1525 updatePreview();
1526}
1527
1528void QgsTextFormatWidget::blockFontChangeSignals( bool blk )
1529{
1530 mFontFamilyCmbBx->blockSignals( blk );
1531 mFontStyleComboBox->blockSignals( blk );
1532 mFontCapitalsComboBox->blockSignals( blk );
1533 mFontUnderlineBtn->blockSignals( blk );
1534 mFontStrikethroughBtn->blockSignals( blk );
1535 mFontWordSpacingSpinBox->blockSignals( blk );
1536 mFontLetterSpacingSpinBox->blockSignals( blk );
1537 mKerningCheckBox->blockSignals( blk );
1538}
1539
1541{
1542 // In dock mode we don't have a preview we
1543 // just let stuff know we have changed because
1544 // there might be live updates connected.
1545 if ( mDockMode )
1546 {
1547 emit widgetChanged();
1548 return;
1549 }
1550
1551 scrollPreview();
1552 lblFontPreview->setFormat( format() );
1553}
1554
1555void QgsTextFormatWidget::scrollPreview()
1556{
1557 scrollArea_mPreview->ensureVisible( 0, 0, 0, 0 );
1558}
1559
1561{
1562 mPreviewBackgroundColor = color;
1563
1564 scrollArea_mPreview->widget()->setStyleSheet( u"background: rgb(%1, %2, %3);"_s.arg( QString::number( color.red() ), QString::number( color.green() ), QString::number( color.blue() ) ) );
1565}
1566
1567void QgsTextFormatWidget::changeBufferColor( const QColor &color )
1568{
1569 Q_UNUSED( color )
1570 updatePreview();
1571}
1572
1574{
1575 const Qgis::GeometryType currentGeometryType = labelGeometryType();
1576 bool showLineFrame = false;
1577 bool showCentroidFrame = false;
1578 bool showQuadrantFrame = false;
1579 bool showFixedQuadrantFrame = false;
1580 bool showPlacementPriorityFrame = false;
1581 bool showOffsetTypeFrame = false;
1582 bool showOffsetFrame = false;
1583 bool showDistanceFrame = false;
1584 bool showMaximumDistanceFrame = false;
1585 bool showPrioritizationFrame = false;
1586 bool showRotationFrame = false;
1587 bool showMaxCharAngleFrame = false;
1588 bool showCurvedLabelModeFrame = false;
1589 bool showWhitespaceCollisionFrame = false;
1590
1591 const Qgis::LabelPlacement currentPlacement = static_cast<Qgis::LabelPlacement>( mPlacementModeComboBox->currentData().toInt() );
1592 const bool showPolygonPlacementOptions
1593 = ( currentGeometryType == Qgis::GeometryType::Polygon && currentPlacement != Qgis::LabelPlacement::Line && currentPlacement != Qgis::LabelPlacement::PerimeterCurved && currentPlacement != Qgis::LabelPlacement::OutsidePolygons );
1594
1595 bool enableMultiLinesFrame = true;
1596
1597 if ( currentPlacement == Qgis::LabelPlacement::AroundPoint && ( currentGeometryType == Qgis::GeometryType::Point || currentGeometryType == Qgis::GeometryType::Polygon ) )
1598 {
1599 showCentroidFrame = currentGeometryType == Qgis::GeometryType::Polygon;
1600 showDistanceFrame = true;
1601 mPlacementDistanceFrame->setEnabled( true );
1602 showMaximumDistanceFrame = true;
1603 //showRotationFrame = true; // TODO: uncomment when supported
1604 showQuadrantFrame = currentGeometryType == Qgis::GeometryType::Point;
1605 }
1606 else if ( currentPlacement == Qgis::LabelPlacement::OverPoint && ( currentGeometryType == Qgis::GeometryType::Point || currentGeometryType == Qgis::GeometryType::Polygon ) )
1607 {
1608 showCentroidFrame = currentGeometryType == Qgis::GeometryType::Polygon;
1609 showQuadrantFrame = true;
1610 showFixedQuadrantFrame = true;
1611 showOffsetFrame = true;
1612 showRotationFrame = true;
1613 }
1614 else if ( currentGeometryType == Qgis::GeometryType::Point && currentPlacement == Qgis::LabelPlacement::OrderedPositionsAroundPoint )
1615 {
1616 showDistanceFrame = true;
1617 showMaximumDistanceFrame = true;
1618 showPlacementPriorityFrame = true;
1619 showPrioritizationFrame = true;
1620 showOffsetTypeFrame = true;
1621 }
1622 else if ( ( currentGeometryType == Qgis::GeometryType::Line && currentPlacement == Qgis::LabelPlacement::Line )
1623 || ( currentGeometryType == Qgis::GeometryType::Polygon && currentPlacement == Qgis::LabelPlacement::Line )
1624 || ( currentGeometryType == Qgis::GeometryType::Line && currentPlacement == Qgis::LabelPlacement::Curved )
1625 || ( currentGeometryType == Qgis::GeometryType::Polygon && currentPlacement == Qgis::LabelPlacement::PerimeterCurved ) )
1626 {
1627 showLineFrame = true;
1628 showDistanceFrame = true;
1629 showCurvedLabelModeFrame = currentPlacement == Qgis::LabelPlacement::Curved || currentPlacement == Qgis::LabelPlacement::PerimeterCurved;
1630 showWhitespaceCollisionFrame = currentPlacement == Qgis::LabelPlacement::Curved || currentPlacement == Qgis::LabelPlacement::PerimeterCurved;
1631 //showRotationFrame = true; // TODO: uncomment when supported
1632
1633 const bool offline = chkLineAbove->isChecked() || chkLineBelow->isChecked();
1634 chkLineOrientationDependent->setEnabled( offline );
1635 mPlacementDistanceFrame->setEnabled( offline );
1636
1637 const bool isCurved = ( currentGeometryType == Qgis::GeometryType::Line && currentPlacement == Qgis::LabelPlacement::Curved )
1638 || ( currentGeometryType == Qgis::GeometryType::Polygon && currentPlacement == Qgis::LabelPlacement::PerimeterCurved );
1639 showMaxCharAngleFrame = isCurved;
1640 // TODO: enable mMultiLinesFrame when supported for curved labels
1641 enableMultiLinesFrame = !isCurved;
1642 }
1643 else if ( currentGeometryType == Qgis::GeometryType::Polygon
1644 && ( currentPlacement == Qgis::LabelPlacement::OutsidePolygons || mCheckAllowLabelsOutsidePolygons->isChecked() || mAllowOutsidePolygonsDDBtn->isActive() ) )
1645 {
1646 showDistanceFrame = true;
1647 mPlacementDistanceFrame->setEnabled( true );
1648 }
1649 else if ( currentGeometryType == Qgis::GeometryType::Line && currentPlacement == Qgis::LabelPlacement::Horizontal )
1650 {
1651 showRotationFrame = true;
1652 }
1653
1654 mPlacementLineFrame->setVisible( showLineFrame );
1655 mPlacementPolygonFrame->setVisible( showPolygonPlacementOptions );
1656 mPlacementCentroidFrame->setVisible( showCentroidFrame );
1657 mPlacementQuadrantFrame->setVisible( showQuadrantFrame );
1658 mPlacementFixedQuadrantFrame->setVisible( showFixedQuadrantFrame );
1659 mPlacementCartographicFrame->setVisible( showPlacementPriorityFrame );
1660 mPlacementOffsetFrame->setVisible( showOffsetFrame );
1661 mPlacementDistanceFrame->setVisible( showDistanceFrame );
1662 mPlacementMaximumDistanceFrame->setVisible( showMaximumDistanceFrame );
1663 mPlacementPrioritizationFrame->setVisible( showPrioritizationFrame );
1664 mPlacementOffsetTypeFrame->setVisible( showOffsetTypeFrame );
1665 mWhitespaceCollisionFrame->setVisible( showWhitespaceCollisionFrame );
1666 mPlacementRotationFrame->setVisible( showRotationFrame );
1667 mPlacementRepeatGroupBox->setVisible(
1668 currentGeometryType == Qgis::GeometryType::Line
1669 || ( currentGeometryType == Qgis::GeometryType::Polygon && ( currentPlacement == Qgis::LabelPlacement::Line || currentPlacement == Qgis::LabelPlacement::PerimeterCurved ) )
1670 );
1671 mPlacementOverrunGroupBox->setVisible( currentGeometryType == Qgis::GeometryType::Line && currentPlacement != Qgis::LabelPlacement::Horizontal );
1672 mLineAnchorGroupBox->setVisible( currentGeometryType == Qgis::GeometryType::Line || currentPlacement == Qgis::LabelPlacement::Line || currentPlacement == Qgis::LabelPlacement::PerimeterCurved );
1673 mPlacementMaxCharAngleFrame->setVisible( showMaxCharAngleFrame );
1674 mCurvedLabelModeFrame->setVisible( showCurvedLabelModeFrame );
1675
1676 mMultiLinesFrame->setEnabled( enableMultiLinesFrame );
1677
1678
1679 QString helperText;
1680 switch ( currentPlacement )
1681 {
1683 if ( currentGeometryType == Qgis::GeometryType::Point )
1684 helperText = tr( "Arranges label candidates in a clockwise circle around the feature, preferring placements to the top-right of the feature." );
1685 else if ( currentGeometryType == Qgis::GeometryType::Polygon )
1686 helperText = tr( "Arranges label candidates in a cluster around the feature's centroid, preferring placements directly over the centroid." );
1687 break;
1689 if ( currentGeometryType == Qgis::GeometryType::Point )
1690 helperText = tr( "Arranges label candidates directly over the feature or at a preset offset from the feature." );
1691 else if ( currentGeometryType == Qgis::GeometryType::Polygon )
1692 helperText = tr( "Arranges label candidates directly over the feature's centroid, or at a preset offset from the centroid." );
1693 break;
1695 if ( currentGeometryType == Qgis::GeometryType::Line )
1696 helperText = tr( "Arranges label candidates parallel to a generalised line representing the feature. Placements which fall over straighter portions of the line are preferred." );
1697 else if ( currentGeometryType == Qgis::GeometryType::Polygon )
1698 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." );
1699 break;
1701 if ( currentGeometryType == Qgis::GeometryType::Line )
1702 helperText = tr( "Arranges candidates following the curvature of a line feature. Placements which fall over straighter portions of the line are preferred." );
1703 break;
1705 if ( currentGeometryType == Qgis::GeometryType::Polygon )
1706 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." );
1707 else if ( currentGeometryType == Qgis::GeometryType::Line )
1708 helperText = tr( "Label candidates are arranged horizontally along the length of the feature." );
1709 break;
1711 if ( currentGeometryType == Qgis::GeometryType::Polygon )
1712 helperText = tr(
1713 "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."
1714 );
1715 break;
1717 if ( currentGeometryType == Qgis::GeometryType::Point )
1718 helperText
1719 = 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." );
1720 break;
1722 if ( currentGeometryType == Qgis::GeometryType::Polygon )
1723 helperText = tr( "Arranges candidates following the curvature of the feature's perimeter. Placements which fall over straighter portions of the perimeter are preferred." );
1724 break;
1726 if ( currentGeometryType == Qgis::GeometryType::Polygon )
1727 helperText = tr( "Label candidates are placed outside of the features, preferring placements which give greatest visual association between the label and the feature." );
1728 break;
1729 }
1730 mPlacementModeDescriptionLabel->setText( u"<i>%1</i>"_s.arg( helperText ) );
1731}
1732
1733void QgsTextFormatWidget::populateFontCapitalsComboBox()
1734{
1735 mFontCapitalsComboBox->addItem( tr( "No Change" ), static_cast<int>( Qgis::Capitalization::MixedCase ) );
1736 mFontCapitalsComboBox->addItem( tr( "All Uppercase" ), static_cast<int>( Qgis::Capitalization::AllUppercase ) );
1737 mFontCapitalsComboBox->addItem( tr( "All Lowercase" ), static_cast<int>( Qgis::Capitalization::AllLowercase ) );
1738 mFontCapitalsComboBox->addItem( tr( "Small Caps" ), static_cast<int>( Qgis::Capitalization::SmallCaps ) );
1739 mFontCapitalsComboBox->addItem( tr( "All Small Caps" ), static_cast<int>( Qgis::Capitalization::AllSmallCaps ) );
1740 mFontCapitalsComboBox->addItem( tr( "Title Case" ), static_cast<int>( Qgis::Capitalization::TitleCase ) );
1741 mFontCapitalsComboBox->addItem( tr( "Force First Letter to Capital" ), static_cast<int>( Qgis::Capitalization::ForceFirstLetterToCapital ) );
1742}
1743
1744void QgsTextFormatWidget::populateFontStyleComboBox()
1745{
1746 mFontStyleComboBox->clear();
1747 const QStringList styles = mFontDB.styles( mRefFont.family() );
1748 const auto constStyles = styles;
1749 for ( const QString &style : constStyles )
1750 {
1751 mFontStyleComboBox->addItem( style );
1752 }
1753
1754 QString targetStyle = mFontDB.styleString( mRefFont );
1755 if ( !styles.contains( targetStyle ) )
1756 {
1757 const QFont f = QgsFontUtils::createFont( mRefFont.family() );
1758 targetStyle = QFontInfo( f ).styleName();
1759 mRefFont.setStyleName( targetStyle );
1760 }
1761 int curIndx = 0;
1762 const int stylIndx = mFontStyleComboBox->findText( targetStyle );
1763 if ( stylIndx > -1 )
1764 {
1765 curIndx = stylIndx;
1766 }
1767
1768 mFontStyleComboBox->setCurrentIndex( curIndx );
1769}
1770
1771void QgsTextFormatWidget::mFontSizeSpinBox_valueChanged( double d )
1772{
1773 mRefFont.setPointSizeF( d );
1774 updateFont( mRefFont );
1775}
1776
1777void QgsTextFormatWidget::mFontFamilyCmbBx_currentFontChanged( const QFont &f )
1778{
1779 QgsFontUtils::setFontFamily( mRefFont, f.family() );
1780 updateFont( mRefFont );
1781}
1782
1783void QgsTextFormatWidget::mFontStyleComboBox_currentIndexChanged( const QString &text )
1784{
1785 QgsFontUtils::updateFontViaStyle( mRefFont, text );
1786 updateFont( mRefFont );
1787}
1788
1789void QgsTextFormatWidget::mFontUnderlineBtn_toggled( bool ckd )
1790{
1791 mRefFont.setUnderline( ckd );
1792 updateFont( mRefFont );
1793}
1794
1795void QgsTextFormatWidget::mFontStrikethroughBtn_toggled( bool ckd )
1796{
1797 mRefFont.setStrikeOut( ckd );
1798 updateFont( mRefFont );
1799}
1800
1801void QgsTextFormatWidget::kerningToggled( bool checked )
1802{
1803 mRefFont.setKerning( checked );
1804 updateFont( mRefFont );
1805}
1806
1807void QgsTextFormatWidget::mFontWordSpacingSpinBox_valueChanged( double spacing )
1808{
1809 mRefFont.setWordSpacing( spacing );
1810 updateFont( mRefFont );
1811}
1812
1813void QgsTextFormatWidget::mFontLetterSpacingSpinBox_valueChanged( double spacing )
1814{
1815 mRefFont.setLetterSpacing( QFont::AbsoluteSpacing, spacing );
1816 updateFont( mRefFont );
1817}
1818
1819void QgsTextFormatWidget::mFontSizeUnitWidget_changed()
1820{
1821 // disable pixel size limiting for labels defined in points
1822 if ( mFontSizeUnitWidget->unit() != Qgis::RenderUnit::MapUnits )
1823 {
1824 mFontLimitPixelChkBox->setChecked( false );
1825 }
1826 else if ( mMinPixelLimit == 0 )
1827 {
1828 // initial minimum trigger value set, turn on pixel size limiting by default
1829 // for labels defined in map units (ignored after first settings save)
1830 mFontLimitPixelChkBox->setChecked( true );
1831 }
1832 updateFont( mRefFont );
1833}
1834
1835void QgsTextFormatWidget::mFontMinPixelSpinBox_valueChanged( int px )
1836{
1837 // ensure max font pixel size for map unit labels can't be lower than min
1838 mFontMaxPixelSpinBox->setMinimum( px );
1839 mFontMaxPixelSpinBox->update();
1840}
1841
1842void QgsTextFormatWidget::mFontMaxPixelSpinBox_valueChanged( int px )
1843{
1844 // ensure max font pixel size for map unit labels can't be lower than min
1845 if ( px < mFontMinPixelSpinBox->value() )
1846 {
1847 mFontMaxPixelSpinBox->blockSignals( true );
1848 mFontMaxPixelSpinBox->setValue( mFontMinPixelSpinBox->value() );
1849 mFontMaxPixelSpinBox->blockSignals( false );
1850 }
1851 mFontMaxPixelSpinBox->setMinimum( mFontMinPixelSpinBox->value() );
1852}
1853
1854void QgsTextFormatWidget::mBufferUnitWidget_changed()
1855{
1856 updateFont( mRefFont );
1857}
1858
1859void QgsTextFormatWidget::mMaskBufferUnitWidget_changed()
1860{
1861 updateFont( mRefFont );
1862}
1863
1864void QgsTextFormatWidget::mCoordXDDBtn_changed()
1865{
1866 updateDataDefinedAlignment();
1867}
1868
1869void QgsTextFormatWidget::mCoordXDDBtn_activated( bool isActive )
1870{
1871 if ( !isActive )
1872 return;
1873
1874 mCoordPointDDBtn->setActive( false );
1875}
1876
1877void QgsTextFormatWidget::mCoordYDDBtn_changed()
1878{
1879 updateDataDefinedAlignment();
1880}
1881
1882void QgsTextFormatWidget::mCoordYDDBtn_activated( bool isActive )
1883{
1884 if ( !isActive )
1885 return;
1886
1887 mCoordPointDDBtn->setActive( false );
1888}
1889
1890void QgsTextFormatWidget::mCoordPointDDBtn_changed()
1891{
1892 updateDataDefinedAlignment();
1893}
1894
1895void QgsTextFormatWidget::mCoordPointDDBtn_activated( bool isActive )
1896{
1897 if ( !isActive )
1898 return;
1899
1900 mCoordXDDBtn->setActive( false );
1901 mCoordYDDBtn->setActive( false );
1902}
1903
1904void QgsTextFormatWidget::mShapeTypeCmbBx_currentIndexChanged( int )
1905{
1906 // shape background
1907 const QgsTextBackgroundSettings::ShapeType type = static_cast<QgsTextBackgroundSettings::ShapeType>( mShapeTypeCmbBx->currentData().toInt() );
1909 const bool isSVG = type == QgsTextBackgroundSettings::ShapeSVG;
1910 const bool isMarker = type == QgsTextBackgroundSettings::ShapeMarkerSymbol;
1911
1912 showBackgroundRadius( isRect );
1913
1914 mShapeSVGPathFrame->setVisible( isSVG );
1915 mBackgroundMarkerSymbolButton->setVisible( isMarker );
1916 mBackgroundFillSymbolButton->setVisible( !isSVG && !isMarker );
1917
1918 // symbology SVG and marker renderers only support size^2 scaling,
1919 // so we only use the x size spinbox
1920 mShapeSizeYLabel->setVisible( !isSVG && !isMarker );
1921 mShapeSizeYSpnBx->setVisible( !isSVG && !isMarker );
1922 mShapeSizeYDDBtn->setVisible( !isSVG && !isMarker );
1923 mShapeSizeXLabel->setText( tr( "Size%1" ).arg( !isSVG && !isMarker ? tr( " X" ) : QString() ) );
1924
1925 // SVG parameter setting doesn't support color's alpha component yet
1926 mShapeFillColorBtn->setAllowOpacity( !isSVG );
1927 mShapeFillColorBtn->setButtonBackground();
1928 mShapeStrokeColorBtn->setAllowOpacity( !isSVG );
1929 mShapeStrokeColorBtn->setButtonBackground();
1930
1931 // Hide parameter widgets not used by marker symbol
1932 mShapeFillColorLabel->setVisible( isSVG );
1933 mShapeFillColorLabel->setEnabled( isSVG );
1934 mShapeFillColorBtn->setVisible( isSVG );
1935 mShapeFillColorBtn->setEnabled( isSVG );
1936 mShapeFillColorDDBtn->setVisible( isSVG );
1937 mShapeFillColorDDBtn->setEnabled( isSVG );
1938 mShapeStrokeColorLabel->setVisible( isSVG );
1939 mShapeStrokeColorLabel->setEnabled( isSVG );
1940 mShapeStrokeColorBtn->setVisible( isSVG );
1941 mShapeStrokeColorBtn->setEnabled( isSVG );
1942 mShapeStrokeColorDDBtn->setVisible( isSVG );
1943 mShapeStrokeColorDDBtn->setEnabled( isSVG );
1944 mShapeStrokeWidthLabel->setVisible( isSVG );
1945 mShapeStrokeWidthLabel->setEnabled( isSVG );
1946 mShapeStrokeWidthSpnBx->setVisible( isSVG );
1947 mShapeStrokeWidthSpnBx->setEnabled( isSVG );
1948 mShapeStrokeWidthDDBtn->setVisible( isSVG );
1949 mShapeStrokeWidthDDBtn->setEnabled( isSVG );
1950
1951 // configure SVG parameter widgets
1952 mShapeSVGParamsBtn->setVisible( isSVG );
1953 if ( isSVG )
1954 {
1955 updateSvgWidgets( mShapeSVGPathLineEdit->text() );
1956 }
1957 // TODO: fix overriding SVG symbol's stroke width units in QgsSvgCache
1958 // currently broken, fall back to symbol units only
1959 mShapeSVGUnitsLabel->setVisible( isSVG );
1960 mShapeStrokeWidthUnitWidget->setVisible( false );
1961 mShapeStrokeUnitsDDBtn->setVisible( false );
1962 mShapeStrokeUnitsDDBtn->setEnabled( false );
1963
1964 updateAvailableShadowPositions();
1965}
1966
1967void QgsTextFormatWidget::mShapeSVGPathLineEdit_textChanged( const QString &text )
1968{
1969 updateSvgWidgets( text );
1970}
1971
1973{
1974 const int numOptionsChecked = ( chkLineAbove->isChecked() ? 1 : 0 ) + ( chkLineBelow->isChecked() ? 1 : 0 ) + ( chkLineOn->isChecked() ? 1 : 0 );
1975
1976 if ( numOptionsChecked == 1 )
1977 {
1978 //prevent unchecking last option
1979 chkLineAbove->setEnabled( !chkLineAbove->isChecked() );
1980 chkLineBelow->setEnabled( !chkLineBelow->isChecked() );
1981 chkLineOn->setEnabled( !chkLineOn->isChecked() );
1982 }
1983 else
1984 {
1985 chkLineAbove->setEnabled( true );
1986 chkLineBelow->setEnabled( true );
1987 chkLineOn->setEnabled( true );
1988 }
1989}
1990
1991void QgsTextFormatWidget::onSubstitutionsChanged( const QgsStringReplacementCollection &substitutions )
1992{
1993 mSubstitutions = substitutions;
1994 emit widgetChanged();
1995}
1996
1997void QgsTextFormatWidget::previewScaleChanged( double scale )
1998{
1999 lblFontPreview->setScale( scale );
2000}
2001
2002void QgsTextFormatWidget::updateSvgWidgets( const QString &svgPath )
2003{
2004 if ( mShapeSVGPathLineEdit->text() != svgPath )
2005 {
2006 mShapeSVGPathLineEdit->setText( svgPath );
2007 }
2008
2009 QString resolvedPath;
2010 bool validSVG = true;
2011 if ( !svgPath.startsWith( "base64:"_L1, Qt::CaseInsensitive ) )
2012 {
2013 resolvedPath = QgsSymbolLayerUtils::svgSymbolNameToPath( svgPath, QgsProject::instance()->pathResolver() );
2014 validSVG = QFileInfo::exists( resolvedPath );
2015 }
2016 else
2017 {
2018 resolvedPath = svgPath;
2019 validSVG = true;
2020 }
2021
2022 // draw red text for path field if invalid (path can't be resolved)
2023 mShapeSVGPathLineEdit->setStyleSheet( !validSVG ? u"QLineEdit{ color: rgb(225, 0, 0); }"_s : QString() );
2024 mShapeSVGPathLineEdit->setToolTip( !validSVG ? tr( "File not found" ) : resolvedPath );
2025
2026 QColor fill, stroke;
2027 double strokeWidth = 0.0;
2028 bool fillParam = false, strokeParam = false, strokeWidthParam = false;
2029 if ( validSVG )
2030 {
2031 QgsApplication::svgCache()->containsParams( resolvedPath, fillParam, fill, strokeParam, stroke, strokeWidthParam, strokeWidth );
2032 }
2033
2034 mShapeSVGParamsBtn->setEnabled( validSVG && ( fillParam || strokeParam || strokeWidthParam ) );
2035
2036 mShapeFillColorLabel->setEnabled( validSVG && fillParam );
2037 mShapeFillColorBtn->setEnabled( validSVG && fillParam );
2038 mShapeFillColorDDBtn->setEnabled( validSVG && fillParam );
2039 if ( mLoadSvgParams && validSVG && fillParam )
2040 mShapeFillColorBtn->setColor( fill );
2041
2042 mShapeStrokeColorLabel->setEnabled( validSVG && strokeParam );
2043 mShapeStrokeColorBtn->setEnabled( validSVG && strokeParam );
2044 mShapeStrokeColorDDBtn->setEnabled( validSVG && strokeParam );
2045 if ( mLoadSvgParams && validSVG && strokeParam )
2046 mShapeStrokeColorBtn->setColor( stroke );
2047
2048 mShapeStrokeWidthLabel->setEnabled( validSVG && strokeWidthParam );
2049 mShapeStrokeWidthSpnBx->setEnabled( validSVG && strokeWidthParam );
2050 mShapeStrokeWidthDDBtn->setEnabled( validSVG && strokeWidthParam );
2051 if ( mLoadSvgParams && validSVG && strokeWidthParam )
2052 mShapeStrokeWidthSpnBx->setValue( strokeWidth );
2053
2054 // TODO: fix overriding SVG symbol's stroke width units in QgsSvgCache
2055 // currently broken, fall back to symbol's
2056 //mShapeStrokeWidthUnitWidget->setEnabled( validSVG && strokeWidthParam );
2057 //mShapeStrokeUnitsDDBtn->setEnabled( validSVG && strokeWidthParam );
2058 mShapeSVGUnitsLabel->setEnabled( validSVG && strokeWidthParam );
2059}
2060
2061void QgsTextFormatWidget::updateAvailableShadowPositions()
2062{
2063 if ( mShadowUnderCmbBx->count() == 0
2064 || ( mShadowUnderCmbBx->findData( QgsTextShadowSettings::ShadowShape ) > -1 && mShapeTypeCmbBx->currentData().toInt() == QgsTextBackgroundSettings::ShapeMarkerSymbol )
2065 || ( mShadowUnderCmbBx->findData( QgsTextShadowSettings::ShadowShape ) == -1 && mShapeTypeCmbBx->currentData().toInt() != QgsTextBackgroundSettings::ShapeMarkerSymbol ) )
2066 {
2067 // showing invalid choices, have to rebuild the list
2068 const QgsTextShadowSettings::ShadowPlacement currentPlacement = static_cast<QgsTextShadowSettings::ShadowPlacement>( mShadowUnderCmbBx->currentData().toInt() );
2069 mShadowUnderCmbBx->clear();
2070
2071 mShadowUnderCmbBx->addItem( tr( "Lowest Label Component" ), QgsTextShadowSettings::ShadowLowest );
2072 mShadowUnderCmbBx->addItem( tr( "Text" ), QgsTextShadowSettings::ShadowText );
2073 mShadowUnderCmbBx->addItem( tr( "Buffer" ), QgsTextShadowSettings::ShadowBuffer );
2074 if ( mShapeTypeCmbBx->currentData().toInt() != QgsTextBackgroundSettings::ShapeMarkerSymbol )
2075 mShadowUnderCmbBx->addItem( tr( "Background" ), QgsTextShadowSettings::ShadowShape ); // not supported for marker symbol background shapes
2076
2077 mShadowUnderCmbBx->setCurrentIndex( mShadowUnderCmbBx->findData( currentPlacement ) );
2078 if ( mShadowUnderCmbBx->currentIndex() == -1 )
2079 mShadowUnderCmbBx->setCurrentIndex( 0 );
2080 }
2081}
2082
2083void QgsTextFormatWidget::updateProperty()
2084{
2085 QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
2086 const QgsPalLayerSettings::Property key = static_cast<QgsPalLayerSettings::Property>( button->propertyKey() );
2087 mDataDefinedProperties.setProperty( key, button->toProperty() );
2088 updatePreview();
2089}
2090
2091void QgsTextFormatWidget::createAuxiliaryField()
2092{
2093 if ( !mLayer )
2094 return;
2095
2096 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
2097
2098 if ( !vLayer )
2099 return;
2100
2101 // try to create an auxiliary layer if not yet created
2102 if ( !vLayer->auxiliaryLayer() )
2103 {
2104 QgsNewAuxiliaryLayerDialog dlg( vLayer, this );
2105 dlg.exec();
2106 }
2107
2108 // return if still not exists
2109 if ( !vLayer->auxiliaryLayer() )
2110 return;
2111
2112 QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
2113 const QgsPalLayerSettings::Property key = static_cast<QgsPalLayerSettings::Property>( button->propertyKey() );
2114 const QgsPropertyDefinition def = QgsPalLayerSettings::propertyDefinitions()[static_cast<int>( key )];
2115
2116 // create property in auxiliary storage if necessary
2117 if ( !vLayer->auxiliaryLayer()->exists( def ) )
2118 vLayer->auxiliaryLayer()->addAuxiliaryField( def );
2119
2120 // update property with join field name from auxiliary storage
2121 QgsProperty property = button->toProperty();
2122 property.setField( QgsAuxiliaryLayer::nameFromProperty( def, true ) );
2123 property.setActive( true );
2124 button->updateFieldLists();
2125 button->setToProperty( property );
2126 mDataDefinedProperties.setProperty( key, button->toProperty() );
2127 updatePreview();
2128 emit auxiliaryFieldCreated();
2129}
2130
2131
2132void QgsTextFormatWidget::updateShapeFrameStatus()
2133{
2134 mShapeFrame->setEnabled( mShapeDrawDDBtn->isActive() || mShapeDrawChkBx->isChecked() );
2135}
2136
2137void QgsTextFormatWidget::updateBufferFrameStatus()
2138{
2139 mBufferFrame->setEnabled( mBufferDrawDDBtn->isActive() || mBufferDrawChkBx->isChecked() );
2140}
2141
2142void QgsTextFormatWidget::updateShadowFrameStatus()
2143{
2144 mShadowFrame->setEnabled( mShadowDrawDDBtn->isActive() || mShadowDrawChkBx->isChecked() );
2145}
2146
2147void QgsTextFormatWidget::updateCalloutFrameStatus()
2148{
2149 mCalloutFrame->setEnabled( mCalloutDrawDDBtn->isActive() || mCalloutsDrawCheckBox->isChecked() );
2150}
2151
2152void QgsTextFormatWidget::updateDataDefinedAlignment()
2153{
2154 // no data defined alignment without data defined position
2155 mCoordAlignmentFrame->setEnabled( ( mCoordXDDBtn->isActive() && mCoordYDDBtn->isActive() ) || mCoordPointDDBtn->isActive() );
2156}
2157
2158void QgsTextFormatWidget::overlapModeChanged()
2159{
2160 QString description;
2161 switch ( static_cast<Qgis::LabelOverlapHandling>( mComboOverlapHandling->currentData().toInt() ) )
2162 {
2164 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.)" );
2165 break;
2167 description = tr( "If a label cannot otherwise be placed for a feature then an overlapping label is permitted." );
2168 break;
2170 description = tr( "Labels from this layer may freely overlap other labels or label obstacles without penalty." );
2171 break;
2172 }
2173
2174 mOverlapModeDescriptionLabel->setText( u"<i>%1</i>"_s.arg( description ) );
2175}
2176
2177void QgsTextFormatWidget::updateCurvedLabelDescription()
2178{
2179 switch ( mComboCurvedLabelMode->currentData().value< Qgis::CurvedLabelMode >() )
2180 {
2182 mCurvedModeDescriptionLabel->hide();
2183 break;
2185 mCurvedModeDescriptionLabel->setText( tr( "Places individual characters from the label at each corresponding vertex in the line." ) );
2186 mCurvedModeDescriptionLabel->show();
2187 break;
2189 mCurvedModeDescriptionLabel->setText( tr( "Stretches (or shrinks) character spacing so that the curved label fits the whole line." ) );
2190 mCurvedModeDescriptionLabel->show();
2191 break;
2193 mCurvedModeDescriptionLabel->setText( tr( "Stretches (or shrinks) word spacing so that the curved label fits the whole line." ) );
2194 mCurvedModeDescriptionLabel->show();
2195 break;
2196 }
2197}
2198
2199void QgsTextFormatWidget::setFormatFromStyle( const QString &name, QgsStyle::StyleEntity type, const QString &stylePath )
2200{
2201 if ( name.isEmpty() )
2202 return;
2203
2204 QgsStyle *style = QgsProject::instance()->styleSettings()->styleAtPath( stylePath );
2205
2206 if ( !style )
2207 style = QgsStyle::defaultStyle();
2208
2209 switch ( type )
2210 {
2218 return;
2219
2221 {
2222 if ( !style->textFormatNames().contains( name ) )
2223 return;
2224
2225 const QgsTextFormat newFormat = style->textFormat( name );
2226 setFormat( newFormat );
2227 break;
2228 }
2229
2231 {
2232 if ( !style->labelSettingsNames().contains( name ) )
2233 return;
2234
2235 const QgsTextFormat newFormat = style->labelSettings( name ).format();
2236 setFormat( newFormat );
2237 break;
2238 }
2239 }
2240}
2241
2243{
2245 saveDlg.setDefaultTags( mTextFormatsListWidget->currentTagFilter() );
2246 if ( !saveDlg.exec() )
2247 return;
2248
2249 if ( saveDlg.name().isEmpty() )
2250 return;
2251
2252 QgsStyle *style = saveDlg.destinationStyle();
2253 if ( !style )
2254 return;
2255
2256 // check if there is no format with same name
2257 if ( style->textFormatNames().contains( saveDlg.name() ) )
2258 {
2259 const int res = QMessageBox::warning( this, tr( "Save Text Format" ), tr( "Format with name '%1' already exists. Overwrite?" ).arg( saveDlg.name() ), QMessageBox::Yes | QMessageBox::No );
2260 if ( res != QMessageBox::Yes )
2261 {
2262 return;
2263 }
2264 style->removeTextFormat( saveDlg.name() );
2265 }
2266
2267 const QStringList symbolTags = saveDlg.tags().split( ',' );
2268
2269 const QgsTextFormat newFormat = format();
2270 style->addTextFormat( saveDlg.name(), newFormat );
2271 style->saveTextFormat( saveDlg.name(), newFormat, saveDlg.isFavorite(), symbolTags );
2272}
2273
2274void QgsTextFormatWidget::mShapeSVGSelectorBtn_clicked()
2275{
2276 QgsSvgSelectorDialog svgDlg( this );
2277 svgDlg.setWindowTitle( tr( "Select SVG file" ) );
2278 svgDlg.svgSelector()->setSvgPath( mShapeSVGPathLineEdit->text().trimmed() );
2279
2280 if ( svgDlg.exec() == QDialog::Accepted )
2281 {
2282 const QString svgPath = svgDlg.svgSelector()->currentSvgPath();
2283 if ( !svgPath.isEmpty() )
2284 {
2285 mShapeSVGPathLineEdit->setText( svgPath );
2286 updatePreview();
2287 }
2288 }
2289}
2290
2291void QgsTextFormatWidget::mShapeSVGParamsBtn_clicked()
2292{
2293 const QString svgPath = mShapeSVGPathLineEdit->text();
2294 mLoadSvgParams = true;
2295 updateSvgWidgets( svgPath );
2296 mLoadSvgParams = false;
2297}
2298
2299void QgsTextFormatWidget::mShapeRotationCmbBx_currentIndexChanged( int index )
2300{
2301 mShapeRotationDblSpnBx->setEnabled( static_cast<QgsTextBackgroundSettings::RotationType>( index ) != QgsTextBackgroundSettings::RotationSync );
2302 mShapeRotationDDBtn->setEnabled( static_cast<QgsTextBackgroundSettings::RotationType>( index ) != QgsTextBackgroundSettings::RotationSync );
2303}
2304
2305void QgsTextFormatWidget::mPreviewTextEdit_textChanged( const QString &text )
2306{
2307 lblFontPreview->setText( text );
2308 updatePreview();
2309}
2310
2311void QgsTextFormatWidget::mPreviewTextBtn_clicked()
2312{
2313 mPreviewTextEdit->setText( u"Lorem Ipsum"_s );
2314 updatePreview();
2315}
2316
2317void QgsTextFormatWidget::mPreviewBackgroundBtn_colorChanged( const QColor &color )
2318{
2319 setPreviewBackground( color );
2320}
2321
2322void QgsTextFormatWidget::mDirectSymbLeftToolBtn_clicked()
2323{
2324 bool gotChar = false;
2325
2326 const QChar initial = !mDirectSymbLeftLineEdit->text().isEmpty() ? mDirectSymbLeftLineEdit->text().at( 0 ) : QChar();
2327 const QChar dirSymb = mCharDlg->selectCharacter( &gotChar, mRefFont, mFontDB.styleString( mRefFont ), initial );
2328
2329 if ( !gotChar )
2330 return;
2331
2332 if ( !dirSymb.isNull() )
2333 mDirectSymbLeftLineEdit->setText( QString( dirSymb ) );
2334}
2335
2336void QgsTextFormatWidget::mDirectSymbRightToolBtn_clicked()
2337{
2338 bool gotChar = false;
2339 const QChar initial = !mDirectSymbRightLineEdit->text().isEmpty() ? mDirectSymbRightLineEdit->text().at( 0 ) : QChar();
2340 const QChar dirSymb = mCharDlg->selectCharacter( &gotChar, mRefFont, mFontDB.styleString( mRefFont ), initial );
2341
2342 if ( !gotChar )
2343 return;
2344
2345 if ( !dirSymb.isNull() )
2346 mDirectSymbRightLineEdit->setText( QString( dirSymb ) );
2347}
2348
2349void QgsTextFormatWidget::chkLineOrientationDependent_toggled( bool active )
2350{
2351 if ( active )
2352 {
2353 chkLineAbove->setText( tr( "Left of line" ) );
2354 chkLineBelow->setText( tr( "Right of line" ) );
2355 }
2356 else
2357 {
2358 chkLineAbove->setText( tr( "Above line" ) );
2359 chkLineBelow->setText( tr( "Below line" ) );
2360 }
2361}
2362
2363
2364void QgsTextFormatWidget::mToolButtonConfigureSubstitutes_clicked()
2365{
2366 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
2367 if ( panel && panel->dockMode() )
2368 {
2369 QgsSubstitutionListWidget *widget = new QgsSubstitutionListWidget( panel );
2370 widget->setPanelTitle( tr( "Substitutions" ) );
2372 connect( widget, &QgsSubstitutionListWidget::substitutionsChanged, this, &QgsTextFormatWidget::onSubstitutionsChanged );
2373 panel->openPanel( widget );
2374 return;
2375 }
2376
2377 QgsSubstitutionListDialog dlg( this );
2378 dlg.setSubstitutions( mSubstitutions );
2379 if ( dlg.exec() == QDialog::Accepted )
2380 {
2381 mSubstitutions = dlg.substitutions();
2382 emit widgetChanged();
2383 }
2384}
2385
2386void QgsTextFormatWidget::configureTabStops()
2387{
2388 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
2389 if ( panel && panel->dockMode() )
2390 {
2391 QgsTabPositionWidget *widget = new QgsTabPositionWidget( panel );
2392 widget->setPanelTitle( tr( "Tab Positions" ) );
2393 widget->setPositions( mTabPositions );
2394 widget->setUnit( mTabDistanceUnitWidget->unit() );
2395 connect( widget, &QgsTabPositionWidget::positionsChanged, this, [this]( const QList<QgsTextFormat::Tab> &positions ) {
2396 mTabPositions = positions;
2397 mTabStopDistanceSpin->setEnabled( mTabPositions.empty() );
2398 emit widgetChanged();
2399 } );
2400 panel->openPanel( widget );
2401 }
2402 else
2403 {
2404 QgsTabPositionDialog dlg( this );
2405 dlg.setPositions( mTabPositions );
2406 dlg.setUnit( mTabDistanceUnitWidget->unit() );
2407 if ( dlg.exec() == QDialog::Accepted )
2408 {
2409 mTabPositions = dlg.positions();
2410 mTabStopDistanceSpin->setEnabled( mTabPositions.empty() );
2411 emit widgetChanged();
2412 }
2413 }
2414}
2415
2416void QgsTextFormatWidget::showBackgroundRadius( bool show )
2417{
2418 mShapeRadiusLabel->setVisible( show );
2419 mShapeRadiusXDbSpnBx->setVisible( show );
2420
2421 mShapeRadiusYDbSpnBx->setVisible( show );
2422
2423 mShapeRadiusUnitWidget->setVisible( show );
2424
2425 mShapeRadiusDDBtn->setVisible( show );
2426 mShapeRadiusUnitsDDBtn->setVisible( show );
2427}
2428
2430{
2431 if ( auto *lExpressionContext = mContext.expressionContext() )
2432 return *lExpressionContext;
2433
2434 QgsExpressionContext expContext;
2435 if ( mMapCanvas )
2436 {
2437 expContext = mMapCanvas->createExpressionContext();
2438 }
2439 else
2440 {
2441 expContext
2446 }
2447
2448 if ( mLayer )
2450
2451 //TODO - show actual value
2452 expContext.setOriginalValueVariable( QVariant() );
2454
2455 return expContext;
2456}
2457
2459{
2460 if ( mGeometryGeneratorGroupBox->isChecked() )
2461 return mGeometryGeneratorType->currentData().value<Qgis::GeometryType>();
2462 else if ( QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer ) )
2463 return vLayer->geometryType();
2464 else
2465 return mGeomType;
2466}
2467
2468
2469//
2470// QgsTextFormatDialog
2471//
2472
2473QgsTextFormatDialog::QgsTextFormatDialog( const QgsTextFormat &format, QgsMapCanvas *mapCanvas, QWidget *parent, Qt::WindowFlags fl, QgsMapLayer *layer )
2474 : QDialog( parent, fl )
2475{
2476 setWindowTitle( tr( "Text Settings" ) );
2477
2478 mFormatWidget = new QgsTextFormatWidget( format, mapCanvas, this, layer );
2479 mFormatWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
2480
2481 QVBoxLayout *layout = new QVBoxLayout( this );
2482 layout->addWidget( mFormatWidget );
2483
2484 mButtonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help, Qt::Horizontal, this );
2485 layout->addWidget( mButtonBox );
2486
2487 setLayout( layout );
2489
2490 connect( mButtonBox->button( QDialogButtonBox::Ok ), &QAbstractButton::clicked, this, &QDialog::accept );
2491 connect( mButtonBox->button( QDialogButtonBox::Cancel ), &QAbstractButton::clicked, this, &QDialog::reject );
2492 connect( mButtonBox->button( QDialogButtonBox::Help ), &QAbstractButton::clicked, this, &QgsTextFormatDialog::showHelp );
2493}
2494
2496{
2497 return mFormatWidget->format();
2498}
2499
2500void QgsTextFormatDialog::showHelp()
2501{
2502 QgsHelp::openHelp( u"style_library/label_settings.html#formatting-the-label-text"_s );
2503}
2504
2506{
2507 mFormatWidget->setContext( context );
2508}
2509
2510QDialogButtonBox *QgsTextFormatDialog::buttonBox() const
2511{
2512 return mButtonBox;
2513}
2514
2516 : QgsPanelWidgetWrapper( new QgsTextFormatWidget( format, mapCanvas, nullptr, layer ), parent )
2517{
2518 mFormatWidget = qobject_cast<QgsTextFormatWidget *>( widget() );
2519 connect( mFormatWidget, &QgsTextFormatWidget::widgetChanged, this, [this] {
2520 if ( !mBlockSignals )
2521 emit widgetChanged();
2522 } );
2523}
2524
2526{
2527 return mFormatWidget->format();
2528}
2529
2531{
2532 mBlockSignals = true;
2533 mFormatWidget->setFormat( format );
2534 mBlockSignals = false;
2535}
2536
2538{
2539 mFormatWidget->setContext( context );
2540}
2541
2543{
2544 mFormatWidget->setDockMode( dockMode );
2546}
CurvedLabelMode
Modes which determine how curved labels are generated and placed.
Definition qgis.h:1306
@ StretchCharacterSpacingToFitLine
Increases (or decreases) the character spacing used for each label in order to fit the entire text ov...
Definition qgis.h:1309
@ Default
Default curved placement, characters are placed in an optimal position along the line....
Definition qgis.h:1307
@ StretchWordSpacingToFitLine
Increases (or decreases) the word spacing used for each label in order to fit the entire text over th...
Definition qgis.h:1310
@ PlaceCharactersAtVertices
Each individual character from the label text is placed such that their left-baseline position is loc...
Definition qgis.h:1308
@ LabelLargestPartOnly
Place a label only on the largest part from the geometry.
Definition qgis.h:1346
@ SplitLabelTextLinesOverParts
Splits the label text over the parts of the geometry, such that each consecutive part is labeled with...
Definition qgis.h:1348
@ LabelEveryPartWithEntireLabel
Place the (same) entire label over every part from the geometry.
Definition qgis.h:1347
@ FromPoint
Offset distance applies from point geometry.
Definition qgis.h:1362
@ FromSymbolBounds
Offset distance applies from rendered symbol bounds.
Definition qgis.h:1363
@ PreferCloser
Prefer closer labels, falling back to alternate positions before larger distances.
Definition qgis.h:1274
@ PreferPositionOrdering
Prefer labels follow position ordering, falling back to more distance labels before alternate positio...
Definition qgis.h:1275
LabelPlacement
Placement modes which determine how label candidates are generated for a feature.
Definition qgis.h:1287
@ OverPoint
Arranges candidates over a point (or centroid of a polygon), or at a preset offset from the point....
Definition qgis.h:1289
@ Curved
Arranges candidates following the curvature of a line feature. Applies to line layers only.
Definition qgis.h:1291
@ AroundPoint
Arranges candidates in a circle around a point (or centroid of a polygon). Applies to point or polygo...
Definition qgis.h:1288
@ Line
Arranges candidates parallel to a generalised line representing the feature or parallel to a polygon'...
Definition qgis.h:1290
@ Free
Arranges candidates scattered throughout a polygon feature. Candidates are rotated to respect the pol...
Definition qgis.h:1293
@ OrderedPositionsAroundPoint
Candidates are placed in predefined positions around a point. Preference is given to positions with g...
Definition qgis.h:1294
@ Horizontal
Arranges horizontal candidates scattered throughout a polygon feature or along a line feature....
Definition qgis.h:1292
@ PerimeterCurved
Arranges candidates following the curvature of a polygon's boundary. Applies to polygon layers only.
Definition qgis.h:1295
@ OutsidePolygons
Candidates are placed outside of polygon boundaries. Applies to polygon layers only.
Definition qgis.h:1296
Capitalization
String capitalization options.
Definition qgis.h:3600
@ AllSmallCaps
Force all characters to small caps.
Definition qgis.h:3608
@ MixedCase
Mixed case, ie no change.
Definition qgis.h:3601
@ AllLowercase
Convert all characters to lowercase.
Definition qgis.h:3603
@ TitleCase
Simple title case conversion - does not fully grammatically parse the text and uses simple rules only...
Definition qgis.h:3606
@ SmallCaps
Mixed case small caps.
Definition qgis.h:3605
@ ForceFirstLetterToCapital
Convert just the first letter of each word to uppercase, leave the rest untouched.
Definition qgis.h:3604
@ AllUppercase
Convert all characters to uppercase.
Definition qgis.h:3602
@ AboveRight
Above right.
Definition qgis.h:1378
@ BelowLeft
Below left.
Definition qgis.h:1382
@ Above
Above center.
Definition qgis.h:1377
@ BelowRight
Below right.
Definition qgis.h:1384
@ Right
Right middle.
Definition qgis.h:1381
@ AboveLeft
Above left.
Definition qgis.h:1376
@ Below
Below center.
Definition qgis.h:1383
@ Over
Center middle.
Definition qgis.h:1380
TextOrientation
Text orientations.
Definition qgis.h:3084
@ Vertical
Vertically oriented text.
Definition qgis.h:3086
@ RotationBased
Horizontally or vertically oriented text based on rotation (only available for map labeling).
Definition qgis.h:3087
@ Horizontal
Horizontally oriented text.
Definition qgis.h:3085
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
Definition qgis.h:379
@ Point
Points.
Definition qgis.h:380
@ Line
Lines.
Definition qgis.h:381
@ Polygon
Polygons.
Definition qgis.h:382
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size).
Definition qgis.h:5654
@ Millimeters
Millimeters.
Definition qgis.h:5651
@ Points
Points (e.g., for font sizes).
Definition qgis.h:5655
@ MapUnits
Map units.
Definition qgis.h:5652
@ Pixels
Pixels.
Definition qgis.h:5653
@ Inches
Inches.
Definition qgis.h:5656
@ MetersInMapUnits
Meters value as Map units.
Definition qgis.h:5658
@ Marker
Marker symbol.
Definition qgis.h:652
@ Fill
Fill symbol.
Definition qgis.h:654
@ Point
Point.
Definition qgis.h:296
@ LineString
LineString.
Definition qgis.h:297
@ Polygon
Polygon.
Definition qgis.h:298
LabelOverlapHandling
Label overlap handling.
Definition qgis.h:1248
@ AllowOverlapAtNoCost
Labels may freely overlap other labels, at no cost.
Definition qgis.h:1251
@ AllowOverlapIfRequired
Avoids overlapping labels when possible, but permit overlaps if labels for features cannot otherwise ...
Definition qgis.h:1250
@ PreventOverlap
Do not allow labels to overlap other labels.
Definition qgis.h:1249
@ FlipUpsideDownLabels
Upside-down labels (90 <= angle < 270) are shown upright.
Definition qgis.h:1444
@ AlwaysAllowUpsideDown
Show upside down for all labels, including dynamic ones.
Definition qgis.h:1446
@ AllowUpsideDownWhenRotationIsDefined
Show upside down when rotation is layer- or data-defined.
Definition qgis.h:1445
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.
void collapsedStateChanged(bool collapsed)
Signal emitted when groupbox collapsed/expanded state is changed, and when first shown.
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 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.
void fieldChanged(const QString &fieldName)
Emitted when the currently selected field changes.
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
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:224
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition qgshelp.cpp:41
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.
Map canvas is a class for displaying all GIS data types on a canvas.
Base class for all map layer types.
Definition qgsmaplayer.h:83
Contains configuration for rendering maps.
A marker symbol type, for rendering Point and MultiPoint geometries.
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
void opacityChanged(double opacity)
Emitted when the opacity is changed in the widget, where opacity ranges from 0.0 (transparent) to 1....
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.
@ WhitespaceCollisionHandling
Whitespace collision handling.
@ AllowDegradedPlacement
Allow degraded label placements.
@ MaskEnabled
Whether the mask is enabled.
@ OverlapHandling
Overlap handling technique.
@ 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.
@ LabelAllParts
Multipart geometry behavior.
@ LabelMarginDistance
Minimum distance from labels for this feature to other labels.
@ 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.
@ CurvedLabelMode
Mode which determine how curved labels are generated and placed.
@ MaskBufferSize
Mask buffer size.
@ TabStopDistance
Tab stop distance, since QGIS 3.38.
@ RemoveDuplicateLabels
Whether this feature can cause removal of duplicate labels.
@ PositionPoint
Point-coordinate data defined label position.
@ MaximumDistance
Maximum distance of label from feature.
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.
QWidget * widget()
Returns the internal widget that is wrapped in this panel.
QgsPanelWidgetWrapper(QWidget *widget, QWidget *parent=nullptr)
Wrapper widget for existing widgets which can't have the inheritance tree changed,...
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
bool dockMode() const
Returns the dock mode state.
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.
QgsStyle * styleAtPath(const QString &path)
Returns a reference to the style database associated with the project with matching file path.
QVector< double > mapScales() const
Returns the list of custom project map scales.
static QgsProject * instance()
Returns the QgsProject singleton instance.
const QgsProjectStyleSettings * styleSettings() const
Returns the project's style settings, which contains settings and properties relating to how a QgsPro...
const QgsProjectViewSettings * viewSettings() const
Returns the project's view settings, which contains settings and properties relating to how a QgsProj...
A grouped map of multiple QgsProperty objects, each referenced by an integer key value.
QSet< int > propertyKeys() const final
Returns a list of property keys contained within the collection.
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.
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.
void setField(const QString &field)
Sets the field name the property references.
void scaleChanged(double scale)
Emitted when user has finished editing/selecting a new scale.
Stores settings for use within QGIS.
Definition qgssettings.h:68
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.
A database of saved style entities, including symbols, color ramps, text formats and others.
Definition qgsstyle.h:91
QgsTextFormat textFormat(const QString &name) const
Returns the text format with the specified name.
QStringList textFormatNames() const
Returns a list of names of text formats in the style.
bool removeTextFormat(const QString &name)
Removes a text format from the style.
StyleEntity
Enum for Entities involved in a style.
Definition qgsstyle.h:206
@ LabelSettingsEntity
Label settings.
Definition qgsstyle.h:212
@ TextFormatEntity
Text formats.
Definition qgsstyle.h:211
@ SmartgroupEntity
Smart groups.
Definition qgsstyle.h:210
@ Symbol3DEntity
3D symbol entity
Definition qgsstyle.h:214
@ SymbolEntity
Symbols.
Definition qgsstyle.h:207
@ TagEntity
Tags.
Definition qgsstyle.h:208
@ ColorrampEntity
Color ramps.
Definition qgsstyle.h:209
@ LegendPatchShapeEntity
Legend patch shape.
Definition qgsstyle.h:213
@ MaterialSettingsEntity
Material settings.
Definition qgsstyle.h:215
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
Definition qgsstyle.cpp:164
QStringList labelSettingsNames() const
Returns a list of names of label settings in the style.
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,...
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:388
QgsPalLayerSettings labelSettings(const QString &name) const
Returns the label settings with the specified name.
bool saveTextFormat(const QString &name, const QgsTextFormat &format, bool favorite, const QStringList &tags)
Adds a text format to the database.
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 dialog for selection of an SVG file.
A button for creating and modifying QgsSymbol settings.
void changed()
Emitted when the symbol's settings are changed.
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,...
static QgsSymbol * defaultSymbol(Qgis::GeometryType geomType)
Returns a new default symbol for the specified geometry type.
void setUnit(Qgis::RenderUnit unit)
Sets the unit type used for the tab positions (used to update interface labels).
void setPositions(const QList< QgsTextFormat::Tab > &positions)
Sets the tab positions to show in the widget.
void positionsChanged(const QList< QgsTextFormat::Tab > &positions)
Emitted when positions are changed in the widget.
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...
@ 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.
QListWidgetItem * mMaskItem
Mask widget item.
QButtonGroup * mUpsidedownBtnGrp
Upside down labels button group.
int mMinPixelLimit
Pixel size font limit.
QListWidgetItem * mBackgroundItem
Background widget item.
void setDockMode(bool enabled)
Sets whether the widget should be shown in a compact dock mode.
QgsMapCanvas * mMapCanvas
Associated map canvas.
void setPropertyOverrideButtonsVisible(bool visible)
Toggles whether data defined buttons should be shown in the widget.
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.
QListWidgetItem * mFormattingItem
Formatting widget item.
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.
QListWidgetItem * mTextItem
Text widget item.
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.
QListWidgetItem * mShadowItem
Shadow widget item.
QList< QgsTextFormat::Tab > mTabPositions
Tab positions.
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.
QListWidgetItem * mBufferItem
Buffer widget item.
void updateLinePlacementOptions()
Updates line placement options to reflect current state of widget.
QListWidgetItem * mCalloutItem
Callout widget item.
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...
QListWidgetItem * mRenderingItem
Rendering widget item.
void updatePreview()
Updates the text preview.
QListWidgetItem * mPlacementItem
Placement widget item.
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.
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.
void changed()
Emitted when the selected unit is changed, or the definition of the map unit scale is changed.
QList< Qgis::RenderUnit > RenderUnitList
List of render units.
Represents a vector layer which manages a vector based dataset.
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:7311