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