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