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