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