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