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