39 #include <QButtonGroup> 
   40 #include <QMessageBox> 
   70   if ( !abstractMetadata )
 
   72     QgsDebugMsg( QStringLiteral( 
"Failed to find callout entry in registry: %1" ).arg( name ) );
 
   78     QgsDebugMsg( QStringLiteral( 
"Failed to cast callout's metadata: " ) .arg( name ) );
 
   85 void QgsLabelingGui::initCalloutWidgets()
 
   87   _initCalloutWidgetFunction( QStringLiteral( 
"simple" ), QgsSimpleLineCalloutWidget::create );
 
   88   _initCalloutWidgetFunction( QStringLiteral( 
"manhattan" ), QgsManhattanLineCalloutWidget::create );
 
   89   _initCalloutWidgetFunction( QStringLiteral( 
"curved" ), QgsCurvedLineCalloutWidget::create );
 
   90   _initCalloutWidgetFunction( QStringLiteral( 
"balloon" ), QgsBalloonCalloutWidget::create );
 
   93 void QgsLabelingGui::updateCalloutWidget( 
QgsCallout *callout )
 
   97     mCalloutStackedWidget->setCurrentWidget( pageDummy );
 
  101   if ( mCalloutStackedWidget->currentWidget() != pageDummy )
 
  104     if ( 
QgsCalloutWidget *pew = qobject_cast< QgsCalloutWidget * >( mCalloutStackedWidget->currentWidget() ) )
 
  115       if ( mGeometryGeneratorGroupBox->isChecked() )
 
  118         geometryType = mLayer->geometryType();
 
  119       w->setGeometryType( geometryType );
 
  120       w->setCallout( callout );
 
  122       w->setContext( context() );
 
  123       mCalloutStackedWidget->addWidget( w );
 
  124       mCalloutStackedWidget->setCurrentWidget( w );
 
  131   mCalloutStackedWidget->setCurrentWidget( pageDummy );
 
  134 void QgsLabelingGui::showObstacleSettings()
 
  148   auto applySettings = [ = ]
 
  150     mObstacleSettings = widget->
settings();
 
  153     emit widgetChanged();
 
  169     dialog.buttonBox()->addButton( QDialogButtonBox::Help );
 
  170     connect( dialog.buttonBox(), &QDialogButtonBox::helpRequested, 
this, [ = ]
 
  172       QgsHelp::openHelp( QStringLiteral( 
"style_library/label_settings.html#obstacles" ) );
 
  184 void QgsLabelingGui::showLineAnchorSettings()
 
  198   auto applySettings = [ = ]
 
  202     mLineSettings.setAnchorType( widgetSettings.
anchorType() );
 
  203     mLineSettings.setAnchorClipping( widgetSettings.
anchorClipping() );
 
  207     emit widgetChanged();
 
  233   , mSettings( layerSettings )
 
  235   , mCanvas( mapCanvas )
 
  237   mGeomType = geomType;
 
  238   static std::once_flag initialized;
 
  239   std::call_once( initialized, [ = ]( )
 
  241     initCalloutWidgets();
 
  244   mFontMultiLineAlignComboBox->addItem( tr( 
"Left" ), 
static_cast< int >( Qgis::LabelMultiLineAlignment::Left ) );
 
  245   mFontMultiLineAlignComboBox->addItem( tr( 
"Center" ), 
static_cast< int >( Qgis::LabelMultiLineAlignment::Center ) );
 
  246   mFontMultiLineAlignComboBox->addItem( tr( 
"Right" ), 
static_cast< int >( Qgis::LabelMultiLineAlignment::Right ) );
 
  247   mFontMultiLineAlignComboBox->addItem( tr( 
"Justify" ), 
static_cast< int >( Qgis::LabelMultiLineAlignment::Justify ) );
 
  259   connect( mBufferDrawChkBx, &QAbstractButton::toggled, 
this, &QgsLabelingGui::updateUi );
 
  261   connect( mEnableMaskChkBx, &QAbstractButton::toggled, 
this, &QgsLabelingGui::updateUi );
 
  262   connect( mShapeDrawChkBx, &QAbstractButton::toggled, 
this, &QgsLabelingGui::updateUi );
 
  263   connect( mCalloutsDrawCheckBox, &QAbstractButton::toggled, 
this, &QgsLabelingGui::updateUi );
 
  264   connect( mShadowDrawChkBx, &QAbstractButton::toggled, 
this, &QgsLabelingGui::updateUi );
 
  265   connect( mDirectSymbChkBx, &QAbstractButton::toggled, 
this, &QgsLabelingGui::updateUi );
 
  266   connect( mFormatNumChkBx, &QAbstractButton::toggled, 
this, &QgsLabelingGui::updateUi );
 
  267   connect( mScaleBasedVisibilityChkBx, &QAbstractButton::toggled, 
this, &QgsLabelingGui::updateUi );
 
  268   connect( mFontLimitPixelChkBox, &QAbstractButton::toggled, 
this, &QgsLabelingGui::updateUi );
 
  269   connect( mGeometryGeneratorGroupBox, &QGroupBox::toggled, 
this, &QgsLabelingGui::updateGeometryTypeBasedWidgets );
 
  270   connect( mGeometryGeneratorType, qOverload<int>( &QComboBox::currentIndexChanged ), 
this, &QgsLabelingGui::updateGeometryTypeBasedWidgets );
 
  271   connect( mGeometryGeneratorExpressionButton, &QToolButton::clicked, 
this, &QgsLabelingGui::showGeometryGeneratorExpressionBuilder );
 
  272   connect( mGeometryGeneratorGroupBox, &QGroupBox::toggled, 
this, &QgsLabelingGui::validateGeometryGeneratorExpression );
 
  273   connect( mGeometryGenerator, &QgsCodeEditorExpression::textChanged, 
this, &QgsLabelingGui::validateGeometryGeneratorExpression );
 
  274   connect( mGeometryGeneratorType, qOverload<int>( &QComboBox::currentIndexChanged ), 
this, &QgsLabelingGui::validateGeometryGeneratorExpression );
 
  275   connect( mObstacleSettingsButton, &QAbstractButton::clicked, 
this, &QgsLabelingGui::showObstacleSettings );
 
  276   connect( mLineAnchorSettingsButton, &QAbstractButton::clicked, 
this, &QgsLabelingGui::showLineAnchorSettings );
 
  278   mFieldExpressionWidget->registerExpressionContextGenerator( 
this );
 
  280   mMinScaleWidget->setMapCanvas( mCanvas );
 
  281   mMinScaleWidget->setShowCurrentScaleButton( 
true );
 
  282   mMaxScaleWidget->setMapCanvas( mCanvas );
 
  283   mMaxScaleWidget->setShowCurrentScaleButton( 
true );
 
  286   for ( 
const QString &type : calloutTypes )
 
  292   mGeometryGeneratorWarningLabel->setStyleSheet( QStringLiteral( 
"color: #FFC107;" ) );
 
  293   mGeometryGeneratorWarningLabel->setTextInteractionFlags( Qt::TextBrowserInteraction );
 
  294   connect( mGeometryGeneratorWarningLabel, &QLabel::linkActivated, 
this, [
this]( 
const QString & link )
 
  296     if ( link == QLatin1String( 
"#determineGeometryGeneratorType" ) )
 
  297       determineGeometryGeneratorType();
 
  300   connect( mCalloutStyleComboBox, 
static_cast<void ( QComboBox::* )( 
int )
>( &QComboBox::currentIndexChanged ), 
this, &QgsLabelingGui::calloutTypeChanged );
 
  302   mLblNoObstacle1->installEventFilter( 
this );
 
  307 void QgsLabelingGui::setLayer( 
QgsMapLayer *mapLayer )
 
  322   mTextFormatsListWidget->setLayerType( mLayer ? mLayer->geometryType() : mGeomType );
 
  323   mBackgroundMarkerSymbolButton->setLayer( mLayer );
 
  324   mBackgroundFillSymbolButton->setLayer( mLayer );
 
  327   updateGeometryTypeBasedWidgets();
 
  329   mFieldExpressionWidget->setLayer( mLayer );
 
  334   mFieldExpressionWidget->setGeomCalculator( da );
 
  336   mFieldExpressionWidget->setEnabled( mMode == Labels || !mLayer );
 
  337   mLabelingFrame->setEnabled( mMode == Labels || !mLayer );
 
  339   blockInitSignals( 
true );
 
  341   mGeometryGenerator->setText( mSettings.geometryGenerator );
 
  342   mGeometryGeneratorGroupBox->setChecked( mSettings.geometryGeneratorEnabled );
 
  343   if ( !mSettings.geometryGeneratorEnabled )
 
  344     mGeometryGeneratorGroupBox->setCollapsed( 
true );
 
  345   mGeometryGeneratorType->setCurrentIndex( mGeometryGeneratorType->findData( mSettings.geometryGeneratorType ) );
 
  349   mFieldExpressionWidget->setRow( -1 );
 
  350   mFieldExpressionWidget->setField( mSettings.fieldName );
 
  351   mCheckBoxSubstituteText->setChecked( mSettings.useSubstitutions );
 
  352   mSubstitutions = mSettings.substitutions;
 
  355   mCentroidRadioWhole->setChecked( mSettings.centroidWhole );
 
  356   mCentroidInsideCheckBox->setChecked( mSettings.centroidInside );
 
  357   mFitInsidePolygonCheckBox->setChecked( mSettings.fitInPolygonOnly );
 
  358   mLineDistanceSpnBx->setValue( mSettings.dist );
 
  359   mLineDistanceUnitWidget->setUnit( mSettings.distUnits );
 
  360   mLineDistanceUnitWidget->setMapUnitScale( mSettings.distMapUnitScale );
 
  361   mOffsetTypeComboBox->setCurrentIndex( mOffsetTypeComboBox->findData( 
static_cast< int >( mSettings.offsetType ) ) );
 
  362   mQuadrantBtnGrp->button( 
static_cast<int>( mSettings.quadOffset ) )->setChecked( 
true );
 
  363   mPointOffsetXSpinBox->setValue( mSettings.xOffset );
 
  364   mPointOffsetYSpinBox->setValue( mSettings.yOffset );
 
  365   mPointOffsetUnitWidget->setUnit( mSettings.offsetUnits );
 
  366   mPointOffsetUnitWidget->setMapUnitScale( mSettings.labelOffsetMapUnitScale );
 
  367   mPointAngleSpinBox->setValue( mSettings.angleOffset );
 
  368   chkLineAbove->setChecked( mSettings.lineSettings().placementFlags() & QgsLabeling::LinePlacementFlag::AboveLine );
 
  369   chkLineBelow->setChecked( mSettings.lineSettings().placementFlags() & QgsLabeling::LinePlacementFlag::BelowLine );
 
  370   chkLineOn->setChecked( mSettings.lineSettings().placementFlags() & QgsLabeling::LinePlacementFlag::OnLine );
 
  371   chkLineOrientationDependent->setChecked( !( mSettings.lineSettings().placementFlags() & QgsLabeling::LinePlacementFlag::MapOrientation ) );
 
  373   mCheckAllowLabelsOutsidePolygons->setChecked( mSettings.polygonPlacementFlags() & QgsLabeling::PolygonPlacementFlag::AllowPlacementOutsideOfPolygon );
 
  375   const int placementIndex = mPlacementModeComboBox->findData( 
static_cast< int >( mSettings.placement ) );
 
  376   if ( placementIndex >= 0 )
 
  378     mPlacementModeComboBox->setCurrentIndex( placementIndex );
 
  383     mPlacementModeComboBox->setCurrentIndex( 0 );
 
  387   mRepeatDistanceSpinBox->setValue( mSettings.repeatDistance );
 
  388   mRepeatDistanceUnitWidget->setUnit( mSettings.repeatDistanceUnit );
 
  389   mRepeatDistanceUnitWidget->setMapUnitScale( mSettings.repeatDistanceMapUnitScale );
 
  391   mOverrunDistanceSpinBox->setValue( mSettings.lineSettings().overrunDistance() );
 
  392   mOverrunDistanceUnitWidget->setUnit( mSettings.lineSettings().overrunDistanceUnit() );
 
  393   mOverrunDistanceUnitWidget->setMapUnitScale( mSettings.lineSettings().overrunDistanceMapUnitScale() );
 
  395   mPrioritySlider->setValue( mSettings.priority );
 
  396   mChkNoObstacle->setChecked( mSettings.obstacleSettings().isObstacle() );
 
  398   mObstacleSettings = mSettings.obstacleSettings();
 
  399   mLineSettings = mSettings.lineSettings();
 
  401   chkLabelPerFeaturePart->setChecked( mSettings.labelPerPart );
 
  403   mComboOverlapHandling->setCurrentIndex( mComboOverlapHandling->findData( 
static_cast< int >( mSettings.placementSettings().overlapHandling() ) ) );
 
  404   mCheckAllowDegradedPlacement->setChecked( mSettings.placementSettings().allowDegradedPlacement() );
 
  406   chkMergeLines->setChecked( mSettings.lineSettings().mergeLines() );
 
  407   mMinSizeSpinBox->setValue( mSettings.thinningSettings().minimumFeatureSize() );
 
  408   mLimitLabelChkBox->setChecked( mSettings.thinningSettings().limitNumberOfLabelsEnabled() );
 
  409   mLimitLabelSpinBox->setValue( mSettings.thinningSettings().maximumNumberLabels() );
 
  412   mDirectSymbChkBx->setChecked( mSettings.lineSettings().addDirectionSymbol() );
 
  413   mDirectSymbLeftLineEdit->setText( mSettings.lineSettings().leftDirectionSymbol() );
 
  414   mDirectSymbRightLineEdit->setText( mSettings.lineSettings().rightDirectionSymbol() );
 
  415   mDirectSymbRevChkBx->setChecked( mSettings.lineSettings().reverseDirectionSymbol() );
 
  417   mDirectSymbBtnGrp->button( 
static_cast<int>( mSettings.lineSettings().directionSymbolPlacement() ) )->setChecked( 
true );
 
  418   mUpsidedownBtnGrp->button( 
static_cast<int>( mSettings.upsidedownLabels ) )->setChecked( 
true );
 
  421   mMaxCharAngleInDSpinBox->setValue( mSettings.maxCurvedCharAngleIn );
 
  423   mMaxCharAngleOutDSpinBox->setValue( std::fabs( mSettings.maxCurvedCharAngleOut ) );
 
  425   wrapCharacterEdit->setText( mSettings.wrapChar );
 
  426   mAutoWrapLengthSpinBox->setValue( mSettings.autoWrapLength );
 
  427   mAutoWrapTypeComboBox->setCurrentIndex( mSettings.useMaxLineLengthForAutoWrap ? 0 : 1 );
 
  429   if ( mFontMultiLineAlignComboBox->findData( 
static_cast< int >( mSettings.multilineAlign ) ) != -1 )
 
  431     mFontMultiLineAlignComboBox->setCurrentIndex( mFontMultiLineAlignComboBox->findData( 
static_cast< int >( mSettings.multilineAlign ) ) );
 
  437     mFontMultiLineAlignComboBox->setCurrentIndex( 0 );
 
  440   chkPreserveRotation->setChecked( mSettings.preserveRotation );
 
  442   mCoordRotationUnitComboBox->setCurrentIndex( 0 );
 
  443   if ( mCoordRotationUnitComboBox->findData( 
static_cast< unsigned int >( mSettings.rotationUnit() ) ) >= 0 )
 
  444     mCoordRotationUnitComboBox->setCurrentIndex( mCoordRotationUnitComboBox->findData( 
static_cast< unsigned int >( mSettings.rotationUnit() ) ) );
 
  446   mScaleBasedVisibilityChkBx->setChecked( mSettings.scaleVisibility );
 
  447   mMinScaleWidget->setScale( mSettings.minimumScale );
 
  448   mMaxScaleWidget->setScale( mSettings.maximumScale );
 
  450   mFormatNumChkBx->setChecked( mSettings.formatNumbers );
 
  451   mFormatNumDecimalsSpnBx->setValue( mSettings.decimals );
 
  452   mFormatNumPlusSignChkBx->setChecked( mSettings.plusSign );
 
  456   mFontLimitPixelChkBox->setChecked( mSettings.fontLimitPixelSize );
 
  457   mMinPixelLimit = mSettings.fontMinPixelSize; 
 
  458   mFontMinPixelSpinBox->setValue( mSettings.fontMinPixelSize == 0 ? 3 : mSettings.fontMinPixelSize );
 
  459   mFontMaxPixelSpinBox->setValue( mSettings.fontMaxPixelSize );
 
  461   mZIndexSpinBox->setValue( mSettings.zIndex );
 
  463   mDataDefinedProperties = mSettings.dataDefinedProperties();
 
  466   if ( 
auto *lCallout = mSettings.callout() )
 
  468     whileBlocking( mCalloutsDrawCheckBox )->setChecked( lCallout->enabled() );
 
  469     whileBlocking( mCalloutStyleComboBox )->setCurrentIndex( mCalloutStyleComboBox->findData( lCallout->type() ) );
 
  470     updateCalloutWidget( lCallout );
 
  475     whileBlocking( mCalloutStyleComboBox )->setCurrentIndex( mCalloutStyleComboBox->findData( defaultCallout->type() ) );
 
  477     updateCalloutWidget( defaultCallout.get() );
 
  480   updatePlacementWidgets();
 
  481   updateLinePlacementOptions();
 
  484   blockInitSignals( 
false );
 
  488   populateDataDefinedButtons();
 
  495   mSettings = settings;
 
  499 void QgsLabelingGui::blockInitSignals( 
bool block )
 
  501   chkLineAbove->blockSignals( block );
 
  502   chkLineBelow->blockSignals( block );
 
  503   mPlacementModeComboBox->blockSignals( block );
 
  506 void QgsLabelingGui::setLabelMode( LabelMode mode )
 
  509   mFieldExpressionWidget->setEnabled( mMode == Labels );
 
  510   mLabelingFrame->setEnabled( mMode == Labels );
 
  520   lyr.
drawLabels = ( mMode == Labels ) || !mLayer;
 
  523   lyr.
fieldName = mFieldExpressionWidget->currentField( &isExpression );
 
  528   QgsLabeling::PolygonPlacementFlags polygonPlacementFlags = QgsLabeling::PolygonPlacementFlag::AllowPlacementInsideOfPolygon;
 
  529   if ( mCheckAllowLabelsOutsidePolygons->isChecked() )
 
  530     polygonPlacementFlags |= QgsLabeling::PolygonPlacementFlag::AllowPlacementOutsideOfPolygon;
 
  536   lyr.
dist = mLineDistanceSpnBx->value();
 
  537   lyr.
distUnits = mLineDistanceUnitWidget->unit();
 
  540   if ( mQuadrantBtnGrp )
 
  544   lyr.
xOffset = mPointOffsetXSpinBox->value();
 
  545   lyr.
yOffset = mPointOffsetYSpinBox->value();
 
  550   QgsLabeling::LinePlacementFlags linePlacementFlags = QgsLabeling::LinePlacementFlags();
 
  551   if ( chkLineAbove->isChecked() )
 
  552     linePlacementFlags |= QgsLabeling::LinePlacementFlag::AboveLine;
 
  553   if ( chkLineBelow->isChecked() )
 
  554     linePlacementFlags |= QgsLabeling::LinePlacementFlag::BelowLine;
 
  555   if ( chkLineOn->isChecked() )
 
  556     linePlacementFlags |= QgsLabeling::LinePlacementFlag::OnLine;
 
  557   if ( ! chkLineOrientationDependent->isChecked() )
 
  558     linePlacementFlags |= QgsLabeling::LinePlacementFlag::MapOrientation;
 
  571   lyr.
priority = mPrioritySlider->value();
 
  573   mObstacleSettings.setIsObstacle( mChkNoObstacle->isChecked() || mMode == ObstaclesOnly );
 
  597   lyr.
decimals = mFormatNumDecimalsSpnBx->value();
 
  598   lyr.
plusSign = mFormatNumPlusSignChkBx->isChecked();
 
  605   if ( mDirectSymbBtnGrp )
 
  609   if ( mUpsidedownBtnGrp )
 
  625   lyr.
wrapChar = wrapCharacterEdit->text();
 
  635   lyr.
layerType = mLayer ? mLayer->geometryType() : mGeomType;
 
  637   lyr.
zIndex = mZIndexSpinBox->value();
 
  642   const QString calloutType = mCalloutStyleComboBox->currentData().toString();
 
  643   std::unique_ptr< QgsCallout > callout;
 
  644   if ( 
QgsCalloutWidget *pew = qobject_cast< QgsCalloutWidget * >( mCalloutStackedWidget->currentWidget() ) )
 
  646     callout.reset( pew->callout()->clone() );
 
  651   callout->
setEnabled( mCalloutsDrawCheckBox->isChecked() );
 
  659   f->setEnabled( chkBx->isChecked() || ddBtn->
isActive() );
 
  662 bool QgsLabelingGui::eventFilter( QObject *
object, QEvent *event )
 
  664   if ( 
object == mLblNoObstacle1 )
 
  666     if ( event->type() == QEvent::MouseButtonPress && qgis::down_cast< QMouseEvent * >( event )->button() == Qt::LeftButton )
 
  669       mChkNoObstacle->setChecked( !mChkNoObstacle->isChecked() );
 
  674   return QgsTextFormatWidget::eventFilter( 
object, event );
 
  677 void QgsLabelingGui::updateUi()
 
  681   syncDefinedCheckboxFrame( mBufferDrawDDBtn, mBufferDrawChkBx, mBufferFrame );
 
  682   syncDefinedCheckboxFrame( mEnableMaskDDBtn, mEnableMaskChkBx, mMaskFrame );
 
  683   syncDefinedCheckboxFrame( mShapeDrawDDBtn, mShapeDrawChkBx, mShapeFrame );
 
  684   syncDefinedCheckboxFrame( mShadowDrawDDBtn, mShadowDrawChkBx, mShadowFrame );
 
  685   syncDefinedCheckboxFrame( mCalloutDrawDDBtn, mCalloutsDrawCheckBox, mCalloutFrame );
 
  687   syncDefinedCheckboxFrame( mDirectSymbDDBtn, mDirectSymbChkBx, mDirectSymbFrame );
 
  688   syncDefinedCheckboxFrame( mFormatNumDDBtn, mFormatNumChkBx, mFormatNumFrame );
 
  689   syncDefinedCheckboxFrame( mScaleBasedVisibilityDDBtn, mScaleBasedVisibilityChkBx, mScaleBasedVisibilityFrame );
 
  690   syncDefinedCheckboxFrame( mFontLimitPixelDDBtn, mFontLimitPixelChkBox, mFontLimitPixelFrame );
 
  692   chkMergeLines->setEnabled( !mDirectSymbChkBx->isChecked() );
 
  693   if ( mDirectSymbChkBx->isChecked() )
 
  695     chkMergeLines->setToolTip( tr( 
"This option is not compatible with line direction symbols." ) );
 
  699     chkMergeLines->setToolTip( QString() );
 
  703 void QgsLabelingGui::setFormatFromStyle( 
const QString &name, 
QgsStyle::StyleEntity type, 
const QString &stylePath )
 
  706 #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0) 
  739         settings.
fieldName = mFieldExpressionWidget->currentField( &isExpression );
 
  742       setSettings( settings );
 
  750   if ( 
QgsCalloutWidget *cw = qobject_cast< QgsCalloutWidget * >( mCalloutStackedWidget->currentWidget() ) )
 
  752     cw->setContext( context );
 
  757 void QgsLabelingGui::saveFormat()
 
  760   saveDlg.setDefaultTags( mTextFormatsListWidget->currentTagFilter() );
 
  761   if ( !saveDlg.exec() )
 
  764   if ( saveDlg.name().isEmpty() )
 
  767   QgsStyle *style = saveDlg.destinationStyle();
 
  771   switch ( saveDlg.selectedType() )
 
  778         const int res = QMessageBox::warning( 
this, tr( 
"Save Text Format" ),
 
  779                                               tr( 
"Format with name '%1' already exists. Overwrite?" )
 
  780                                               .arg( saveDlg.name() ),
 
  781                                               QMessageBox::Yes | QMessageBox::No );
 
  782         if ( res != QMessageBox::Yes )
 
  788       const QStringList symbolTags = saveDlg.tags().split( 
',' );
 
  792       style->
saveTextFormat( saveDlg.name(), newFormat, saveDlg.isFavorite(), symbolTags );
 
  801         const int res = QMessageBox::warning( 
this, tr( 
"Save Label Settings" ),
 
  802                                               tr( 
"Label settings with the name '%1' already exist. Overwrite?" )
 
  803                                               .arg( saveDlg.name() ),
 
  804                                               QMessageBox::Yes | QMessageBox::No );
 
  805         if ( res != QMessageBox::Yes )
 
  811       const QStringList symbolTags = saveDlg.tags().split( 
',' );
 
  815       style->
saveLabelSettings( saveDlg.name(), newSettings, saveDlg.isFavorite(), symbolTags );
 
  829 void QgsLabelingGui::updateGeometryTypeBasedWidgets()
 
  833   if ( mGeometryGeneratorGroupBox->isChecked() )
 
  836     geometryType = mLayer->geometryType();
 
  846   mPlacementModeComboBox->clear();
 
  848   switch ( geometryType )
 
  875       qFatal( 
"unknown geometry type unexpected" );
 
  878   if ( mPlacementModeComboBox->findData( 
static_cast< int >( prevPlacement ) ) != -1 )
 
  880     mPlacementModeComboBox->setCurrentIndex( mPlacementModeComboBox->findData( 
static_cast< int >( prevPlacement ) ) );
 
  886     if ( mFontMultiLineAlignComboBox->findData( 
static_cast< int >( Qgis::LabelMultiLineAlignment::FollowPlacement ) ) == -1 )
 
  887       mFontMultiLineAlignComboBox->addItem( tr( 
"Follow Label Placement" ), 
static_cast< int >( Qgis::LabelMultiLineAlignment::FollowPlacement ) );
 
  891     const int idx = mFontMultiLineAlignComboBox->findData( 
static_cast< int >( Qgis::LabelMultiLineAlignment::FollowPlacement ) );
 
  893       mFontMultiLineAlignComboBox->removeItem( idx );
 
  896   updatePlacementWidgets();
 
  897   updateLinePlacementOptions();
 
  900 void QgsLabelingGui::showGeometryGeneratorExpressionBuilder()
 
  904   expressionBuilder.setExpressionText( mGeometryGenerator->text() );
 
  905   expressionBuilder.setExpressionContext( createExpressionContext() );
 
  907   if ( expressionBuilder.exec() )
 
  909     mGeometryGenerator->setText( expressionBuilder.expressionText() );
 
  913 void QgsLabelingGui::validateGeometryGeneratorExpression()
 
  917   if ( mGeometryGeneratorGroupBox->isChecked() )
 
  919     if ( !mPreviewFeature.isValid() && mLayer )
 
  920       mLayer->getFeatures( 
QgsFeatureRequest().setLimit( 1 ) ).nextFeature( mPreviewFeature );
 
  926     expression.prepare( &context );
 
  928     if ( expression.hasParserError() )
 
  930       mGeometryGeneratorWarningLabel->setText( expression.parserErrorString() );
 
  935       const QVariant result = expression.evaluate( &context );
 
  940         mGeometryGeneratorWarningLabel->setText( tr( 
"Result of the expression is not a geometry" ) );
 
  943       else if ( geometry.
type() != configuredGeometryType )
 
  945         mGeometryGeneratorWarningLabel->setText( QStringLiteral( 
"<p>%1</p><p><a href=\"#determineGeometryGeneratorType\">%2</a></p>" ).arg(
 
  946               tr( 
"Result of the expression does not match configured geometry type." ),
 
  955   QTimer *timer = 
new QTimer();
 
  956   connect( timer, &QTimer::timeout, 
this, [
this, valid]()
 
  958     mGeometryGeneratorWarningLabel->setVisible( !valid );
 
  960   connect( timer, &QTimer::timeout, timer, &QTimer::deleteLater );
 
  964 void QgsLabelingGui::determineGeometryGeneratorType()
 
  966   if ( !mPreviewFeature.isValid() && mLayer )
 
  967     mLayer->getFeatures( 
QgsFeatureRequest().setLimit( 1 ) ).nextFeature( mPreviewFeature );
 
  973   expression.prepare( &context );
 
  976   mGeometryGeneratorType->setCurrentIndex( mGeometryGeneratorType->findData( geometry.
type() ) );
 
  979 void QgsLabelingGui::calloutTypeChanged()
 
  981   const QString newCalloutType = mCalloutStyleComboBox->currentData().toString();
 
  982   QgsCalloutWidget *pew = qobject_cast< QgsCalloutWidget * >( mCalloutStackedWidget->currentWidget() );
 
 1001   updateCalloutWidget( newCallout.get() );
 
 1014   QVBoxLayout *vLayout = 
new QVBoxLayout();
 
 1015   mWidget = 
new QgsLabelingGui( layer, mapCanvas, settings, 
nullptr, geomType );
 
 1016   vLayout->addWidget( mWidget );
 
 1017   mButtonBox = 
new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok, Qt::Horizontal );
 
 1018   connect( mButtonBox, &QDialogButtonBox::accepted, 
this, &QDialog::accept );
 
 1019   connect( mButtonBox, &QDialogButtonBox::rejected, 
this, &QDialog::reject );
 
 1020   connect( mButtonBox, &QDialogButtonBox::helpRequested, 
this, &QgsLabelSettingsDialog::showHelp );
 
 1021   vLayout->addWidget( mButtonBox );
 
 1022   setLayout( vLayout );
 
 1023   setWindowTitle( tr( 
"Label Settings" ) );
 
 1026 QDialogButtonBox *QgsLabelSettingsDialog::buttonBox()
 const 
 1031 void QgsLabelSettingsDialog::showHelp()