QGIS/src/app/qgslabelinggui.cpp
Nyall Dawson ce6bd6c973 Move QgsSymbolV2::OutputUnit enum to QgsUnitTypes
And rename to QgsUnitTypes::RenderUnits. This enum is used in
much more contexts than just symbols, so QgsUnitTypes is a
better fit for it.

All methods which previously accepted QgsSymbolV2::OutputUnit
parameters or QgsSymbolV2::OutputUnitList parameters now take
QgsUnitTypes::RenderUnit or QgsUnitTypes::RenderUnitList
parameters respectively.
2016-07-25 15:22:12 +10:00

2115 lines
96 KiB
C++

/***************************************************************************
qgslabelinggui.cpp
Smart labeling for vector layers
-------------------
begin : June 2009
copyright : (C) Martin Dobias
email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgslabelinggui.h"
#include <qgsmapcanvas.h>
#include <qgsvectorlayer.h>
#include <qgsvectordataprovider.h>
#include <qgsmaplayerregistry.h>
#include "qgsdatadefinedbutton.h"
#include "qgsexpressionbuilderdialog.h"
#include "qgsexpression.h"
#include "qgsfontutils.h"
#include "qgisapp.h"
#include "qgsproject.h"
#include "qgssvgcache.h"
#include "qgssymbollayerv2utils.h"
#include "qgscharacterselectdialog.h"
#include "qgssvgselectorwidget.h"
#include "qgsvectorlayerlabeling.h"
#include "qgslogger.h"
#include <QCheckBox>
#include <QSettings>
static QgsExpressionContext _getExpressionContext( const void* context )
{
QgsExpressionContext expContext;
expContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope()
<< QgsExpressionContextUtils::atlasScope( nullptr )
<< QgsExpressionContextUtils::mapSettingsScope( QgisApp::instance()->mapCanvas()->mapSettings() );
const QgsVectorLayer* layer = ( const QgsVectorLayer* ) context;
if ( layer )
expContext << QgsExpressionContextUtils::layerScope( layer );
expContext << QgsExpressionContextUtils::updateSymbolScope( nullptr, new QgsExpressionContextScope() );
//TODO - show actual value
expContext.setOriginalValueVariable( QVariant() );
expContext.setHighlightedVariables( QStringList() << QgsExpressionContext::EXPR_ORIGINAL_VALUE << QgsExpressionContext::EXPR_SYMBOL_COLOR );
return expContext;
}
QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, const QgsPalLayerSettings* layerSettings, QWidget* parent )
: QWidget( parent )
, mLayer( layer )
, mMapCanvas( mapCanvas )
, mSettings( layerSettings )
, mMode( NoLabels )
, mCharDlg( nullptr )
, mQuadrantBtnGrp( nullptr )
, mDirectSymbBtnGrp( nullptr )
, mUpsidedownBtnGrp( nullptr )
, mPlacePointBtnGrp( nullptr )
, mPlaceLineBtnGrp( nullptr )
, mPlacePolygonBtnGrp( nullptr )
, mPreviewSize( 24 )
, mMinPixelLimit( 0 )
, mLoadSvgParams( false )
{
setupUi( this );
mFieldExpressionWidget->registerGetExpressionContextCallback( &_getExpressionContext, mLayer );
Q_FOREACH ( QgsUnitSelectionWidget* unitWidget, findChildren<QgsUnitSelectionWidget*>() )
{
unitWidget->setMapCanvas( mMapCanvas );
}
mFontSizeUnitWidget->setUnits( QStringList() << tr( "Points" ) << tr( "Map unit" ), 1 );
mBufferUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMapUnits );
mShapeSizeUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMapUnits );
mShapeOffsetUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMapUnits );
mShapeRadiusUnitWidget->setUnits( QStringList() << tr( "Millimeter" ) << tr( "Map unit" ) << tr( "% of length" ), 1 );
mShapeBorderWidthUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMapUnits );
mShadowOffsetUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMapUnits );
mShadowRadiusUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMapUnits );
mPointOffsetUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMapUnits );
mLineDistanceUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMapUnits );
mRepeatDistanceUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMapUnits );
mFontLineHeightSpinBox->setClearValue( 1.0 );
mShapeRotationDblSpnBx->setClearValue( 0.0 );
mShapeOffsetXSpnBx->setClearValue( 0.0 );
mShapeOffsetYSpnBx->setClearValue( 0.0 );
mPointOffsetXSpinBox->setClearValue( 0.0 );
mPointOffsetYSpinBox->setClearValue( 0.0 );
mPointAngleSpinBox->setClearValue( 0.0 );
mFontLetterSpacingSpinBox->setClearValue( 0.0 );
mFontWordSpacingSpinBox->setClearValue( 0.0 );
mZIndexSpinBox->setClearValue( 0.0 );
mObstacleTypeComboBox->addItem( tr( "Over the feature's interior" ), QgsPalLayerSettings::PolygonInterior );
mObstacleTypeComboBox->addItem( tr( "Over the feature's boundary" ), QgsPalLayerSettings::PolygonBoundary );
mOffsetTypeComboBox->addItem( tr( "From point" ), QgsPalLayerSettings::FromPoint );
mOffsetTypeComboBox->addItem( tr( "From symbol bounds" ), QgsPalLayerSettings::FromSymbolBounds );
mCharDlg = new QgsCharacterSelectorDialog( this );
mRefFont = lblFontPreview->font();
// connections for groupboxes with separate activation checkboxes (that need to honor data defined setting)
connect( mBufferDrawChkBx, SIGNAL( toggled( bool ) ), this, SLOT( updateUi() ) );
connect( mShapeDrawChkBx, SIGNAL( toggled( bool ) ), this, SLOT( updateUi() ) );
connect( mShadowDrawChkBx, SIGNAL( toggled( bool ) ), this, SLOT( updateUi() ) );
connect( mDirectSymbChkBx, SIGNAL( toggled( bool ) ), this, SLOT( updateUi() ) );
connect( mFormatNumChkBx, SIGNAL( toggled( bool ) ), this, SLOT( updateUi() ) );
connect( mScaleBasedVisibilityChkBx, SIGNAL( toggled( bool ) ), this, SLOT( updateUi() ) );
connect( mFontLimitPixelChkBox, SIGNAL( toggled( bool ) ), this, SLOT( updateUi() ) );
// internal connections
connect( mFontTranspSlider, SIGNAL( valueChanged( int ) ), mFontTranspSpinBox, SLOT( setValue( int ) ) );
connect( mFontTranspSpinBox, SIGNAL( valueChanged( int ) ), mFontTranspSlider, SLOT( setValue( int ) ) );
connect( mBufferTranspSlider, SIGNAL( valueChanged( int ) ), mBufferTranspSpinBox, SLOT( setValue( int ) ) );
connect( mBufferTranspSpinBox, SIGNAL( valueChanged( int ) ), mBufferTranspSlider, SLOT( setValue( int ) ) );
connect( mShapeTranspSlider, SIGNAL( valueChanged( int ) ), mShapeTranspSpinBox, SLOT( setValue( int ) ) );
connect( mShapeTranspSpinBox, SIGNAL( valueChanged( int ) ), mShapeTranspSlider, SLOT( setValue( int ) ) );
connect( mShadowOffsetAngleDial, SIGNAL( valueChanged( int ) ), mShadowOffsetAngleSpnBx, SLOT( setValue( int ) ) );
connect( mShadowOffsetAngleSpnBx, SIGNAL( valueChanged( int ) ), mShadowOffsetAngleDial, SLOT( setValue( int ) ) );
connect( mShadowTranspSlider, SIGNAL( valueChanged( int ) ), mShadowTranspSpnBx, SLOT( setValue( int ) ) );
connect( mShadowTranspSpnBx, SIGNAL( valueChanged( int ) ), mShadowTranspSlider, SLOT( setValue( int ) ) );
connect( mLimitLabelChkBox, SIGNAL( toggled( bool ) ), mLimitLabelSpinBox, SLOT( setEnabled( bool ) ) );
//connections to prevent users removing all line placement positions
connect( chkLineAbove, SIGNAL( toggled( bool ) ), this, SLOT( updateLinePlacementOptions() ) );
connect( chkLineBelow, SIGNAL( toggled( bool ) ), this, SLOT( updateLinePlacementOptions() ) );
connect( chkLineOn, SIGNAL( toggled( bool ) ), this, SLOT( updateLinePlacementOptions() ) );
populateFontCapitalsComboBox();
// color buttons
mPreviewBackgroundBtn->setColorDialogTitle( tr( "Select fill color" ) );
mPreviewBackgroundBtn->setContext( "labelling" );
btnTextColor->setColorDialogTitle( tr( "Select text color" ) );
btnTextColor->setContext( "labelling" );
btnTextColor->setDefaultColor( Qt::black );
btnBufferColor->setColorDialogTitle( tr( "Select buffer color" ) );
btnBufferColor->setContext( "labelling" );
btnBufferColor->setDefaultColor( Qt::white );
mShapeBorderColorBtn->setColorDialogTitle( tr( "Select border color" ) );
mShapeBorderColorBtn->setContext( "labelling" );
mShapeFillColorBtn->setColorDialogTitle( tr( "Select fill color" ) );
mShapeFillColorBtn->setContext( "labelling" );
mShadowColorBtn->setColorDialogTitle( tr( "Select shadow color" ) );
mShadowColorBtn->setContext( "labelling" );
mShadowColorBtn->setDefaultColor( Qt::black );
// set up quadrant offset button group
mQuadrantBtnGrp = new QButtonGroup( this );
mQuadrantBtnGrp->addButton( mPointOffsetAboveLeft, ( int )QgsPalLayerSettings::QuadrantAboveLeft );
mQuadrantBtnGrp->addButton( mPointOffsetAbove, ( int )QgsPalLayerSettings::QuadrantAbove );
mQuadrantBtnGrp->addButton( mPointOffsetAboveRight, ( int )QgsPalLayerSettings::QuadrantAboveRight );
mQuadrantBtnGrp->addButton( mPointOffsetLeft, ( int )QgsPalLayerSettings::QuadrantLeft );
mQuadrantBtnGrp->addButton( mPointOffsetOver, ( int )QgsPalLayerSettings::QuadrantOver );
mQuadrantBtnGrp->addButton( mPointOffsetRight, ( int )QgsPalLayerSettings::QuadrantRight );
mQuadrantBtnGrp->addButton( mPointOffsetBelowLeft, ( int )QgsPalLayerSettings::QuadrantBelowLeft );
mQuadrantBtnGrp->addButton( mPointOffsetBelow, ( int )QgsPalLayerSettings::QuadrantBelow );
mQuadrantBtnGrp->addButton( mPointOffsetBelowRight, ( int )QgsPalLayerSettings::QuadrantBelowRight );
mQuadrantBtnGrp->setExclusive( true );
// setup direction symbol(s) button group
mDirectSymbBtnGrp = new QButtonGroup( this );
mDirectSymbBtnGrp->addButton( mDirectSymbRadioBtnLR, ( int )QgsPalLayerSettings::SymbolLeftRight );
mDirectSymbBtnGrp->addButton( mDirectSymbRadioBtnAbove, ( int )QgsPalLayerSettings::SymbolAbove );
mDirectSymbBtnGrp->addButton( mDirectSymbRadioBtnBelow, ( int )QgsPalLayerSettings::SymbolBelow );
mDirectSymbBtnGrp->setExclusive( true );
// upside-down labels button group
mUpsidedownBtnGrp = new QButtonGroup( this );
mUpsidedownBtnGrp->addButton( mUpsidedownRadioOff, ( int )QgsPalLayerSettings::Upright );
mUpsidedownBtnGrp->addButton( mUpsidedownRadioDefined, ( int )QgsPalLayerSettings::ShowDefined );
mUpsidedownBtnGrp->addButton( mUpsidedownRadioAll, ( int )QgsPalLayerSettings::ShowAll );
mUpsidedownBtnGrp->setExclusive( true );
//mShapeCollisionsChkBx->setVisible( false ); // until implemented
// post updatePlacementWidgets() connections
connect( chkLineAbove, SIGNAL( toggled( bool ) ), this, SLOT( updatePlacementWidgets() ) );
connect( chkLineBelow, SIGNAL( toggled( bool ) ), this, SLOT( updatePlacementWidgets() ) );
// setup point placement button group
mPlacePointBtnGrp = new QButtonGroup( this );
mPlacePointBtnGrp->addButton( radPredefinedOrder, ( int )QgsPalLayerSettings::OrderedPositionsAroundPoint );
mPlacePointBtnGrp->addButton( radAroundPoint, ( int )QgsPalLayerSettings::AroundPoint );
mPlacePointBtnGrp->addButton( radOverPoint, ( int )QgsPalLayerSettings::OverPoint );
mPlacePointBtnGrp->setExclusive( true );
connect( mPlacePointBtnGrp, SIGNAL( buttonClicked( int ) ), this, SLOT( updatePlacementWidgets() ) );
// setup line placement button group (assigned enum id currently unused)
mPlaceLineBtnGrp = new QButtonGroup( this );
mPlaceLineBtnGrp->addButton( radLineParallel, ( int )QgsPalLayerSettings::Line );
mPlaceLineBtnGrp->addButton( radLineCurved, ( int )QgsPalLayerSettings::Curved );
mPlaceLineBtnGrp->addButton( radLineHorizontal, ( int )QgsPalLayerSettings::Horizontal );
mPlaceLineBtnGrp->setExclusive( true );
connect( mPlaceLineBtnGrp, SIGNAL( buttonClicked( int ) ), this, SLOT( updatePlacementWidgets() ) );
// setup polygon placement button group (assigned enum id currently unused)
mPlacePolygonBtnGrp = new QButtonGroup( this );
mPlacePolygonBtnGrp->addButton( radOverCentroid, ( int )QgsPalLayerSettings::OverPoint );
mPlacePolygonBtnGrp->addButton( radAroundCentroid, ( int )QgsPalLayerSettings::AroundPoint );
mPlacePolygonBtnGrp->addButton( radPolygonHorizontal, ( int )QgsPalLayerSettings::Horizontal );
mPlacePolygonBtnGrp->addButton( radPolygonFree, ( int )QgsPalLayerSettings::Free );
mPlacePolygonBtnGrp->addButton( radPolygonPerimeter, ( int )QgsPalLayerSettings::Line );
mPlacePolygonBtnGrp->setExclusive( true );
connect( mPlacePolygonBtnGrp, SIGNAL( buttonClicked( int ) ), this, SLOT( updatePlacementWidgets() ) );
// TODO: is this necessary? maybe just use the data defined-only rotation?
mPointAngleDDBtn->setVisible( false );
// Global settings group for groupboxes' saved/retored collapsed state
// maintains state across different dialogs
Q_FOREACH ( QgsCollapsibleGroupBox *grpbox, findChildren<QgsCollapsibleGroupBox*>() )
{
grpbox->setSettingGroup( QString( "mAdvLabelingDlg" ) );
}
connect( groupBox_mPreview,
SIGNAL( collapsedStateChanged( bool ) ),
this,
SLOT( collapseSample( bool ) ) );
// get rid of annoying outer focus rect on Mac
mLabelingOptionsListWidget->setAttribute( Qt::WA_MacShowFocusRect, false );
QSettings settings;
// reset horiz strech of left side of options splitter (set to 1 for previewing in Qt Designer)
QSizePolicy policy( mLabelingOptionsListFrame->sizePolicy() );
policy.setHorizontalStretch( 0 );
mLabelingOptionsListFrame->setSizePolicy( policy );
if ( !settings.contains( QString( "/Windows/Labeling/OptionsSplitState" ) ) )
{
// set left list widget width on intial showing
QList<int> splitsizes;
splitsizes << 115;
mLabelingOptionsSplitter->setSizes( splitsizes );
}
// set up reverse connection from stack to list
connect( mLabelStackedWidget, SIGNAL( currentChanged( int ) ), this, SLOT( optionsStackedWidget_CurrentChanged( int ) ) );
// restore dialog, splitters and current tab
mFontPreviewSplitter->restoreState( settings.value( QString( "/Windows/Labeling/FontPreviewSplitState" ) ).toByteArray() );
mLabelingOptionsSplitter->restoreState( settings.value( QString( "/Windows/Labeling/OptionsSplitState" ) ).toByteArray() );
mLabelingOptionsListWidget->setCurrentRow( settings.value( QString( "/Windows/Labeling/Tab" ), 0 ).toInt() );
setDockMode( false );
QList<QWidget*> widgets;
widgets << btnBufferColor
<< btnTextColor
<< chkLabelPerFeaturePart
<< chkLineAbove
<< chkLineBelow
<< chkLineOn
<< chkLineOrientationDependent
<< chkMergeLines
<< chkPreserveRotation
<< comboBlendMode
<< comboBufferBlendMode
<< mAlwaysShowDDBtn
<< mBufferBlendModeDDBtn
<< mBufferColorDDBtn
<< mBufferDrawChkBx
<< mBufferDrawDDBtn
<< mBufferJoinStyleComboBox
<< mBufferJoinStyleDDBtn
<< mBufferSizeDDBtn
<< mBufferTranspDDBtn
<< mBufferTranspFillChbx
<< mBufferTranspSpinBox
<< mBufferUnitsDDBtn
<< mCentroidDDBtn
<< mCentroidInsideCheckBox
<< mChkNoObstacle
<< mCoordAlignmentHDDBtn
<< mCoordAlignmentVDDBtn
<< mCoordRotationDDBtn
<< mCoordXDDBtn
<< mCoordYDDBtn
<< mDirectSymbChkBx
<< mDirectSymbDDBtn
<< mDirectSymbLeftDDBtn
<< mDirectSymbLeftLineEdit
<< mDirectSymbPlacementDDBtn
<< mDirectSymbRevChkBx
<< mDirectSymbRevDDBtn
<< mDirectSymbRightDDBtn
<< mDirectSymbRightLineEdit
<< mFitInsidePolygonCheckBox
<< mFontBlendModeDDBtn
<< mFontBoldDDBtn
<< mFontCapitalsComboBox
<< mFontCaseDDBtn
<< mFontColorDDBtn
<< mFontDDBtn
<< mFontItalicDDBtn
<< mFontLetterSpacingDDBtn
<< mFontLetterSpacingSpinBox
<< mFontLimitPixelChkBox
<< mFontLimitPixelDDBtn
<< mFontLineHeightDDBtn
<< mFontLineHeightSpinBox
<< mFontMaxPixelDDBtn
<< mFontMaxPixelSpinBox
<< mFontMinPixelDDBtn
<< mFontMinPixelSpinBox
<< mFontMultiLineAlignComboBox
<< mFontMultiLineAlignDDBtn
<< mFontSizeDDBtn
<< mFontSizeSpinBox
<< mFontStrikeoutDDBtn
<< mFontStyleComboBox
<< mFontStyleDDBtn
<< mFontTranspDDBtn
<< mFontTranspSpinBox
<< mFontUnderlineDDBtn
<< mFontUnitsDDBtn
<< mFontWordSpacingDDBtn
<< mFontWordSpacingSpinBox
<< mFormatNumChkBx
<< mFormatNumDDBtn
<< mFormatNumDecimalsDDBtn
<< mFormatNumDecimalsSpnBx
<< mFormatNumPlusSignChkBx
<< mFormatNumPlusSignDDBtn
<< mIsObstacleDDBtn
<< mLimitLabelChkBox
<< mLimitLabelSpinBox
<< mLineDistanceDDBtn
<< mLineDistanceSpnBx
<< mLineDistanceUnitDDBtn
<< mMaxCharAngleDDBtn
<< mMaxCharAngleInDSpinBox
<< mMaxCharAngleOutDSpinBox
<< mMinSizeSpinBox
<< mObstacleFactorDDBtn
<< mObstacleFactorSlider
<< mObstacleTypeComboBox
<< mOffsetTypeComboBox
<< mPalShowAllLabelsForLayerChkBx
<< mPointAngleDDBtn
<< mPointAngleSpinBox
<< mPointOffsetDDBtn
<< mPointOffsetUnitsDDBtn
<< mPointOffsetXSpinBox
<< mPointOffsetYSpinBox
<< mPointPositionOrderDDBtn
<< mPointQuadOffsetDDBtn
<< mPreviewBackgroundBtn
<< mPreviewTextEdit
<< mPriorityDDBtn
<< mPrioritySlider
<< mRepeatDistanceDDBtn
<< mRepeatDistanceSpinBox
<< mRepeatDistanceUnitDDBtn
<< mScaleBasedVisibilityChkBx
<< mScaleBasedVisibilityDDBtn
<< mScaleBasedVisibilityMaxDDBtn
<< mScaleBasedVisibilityMaxSpnBx
<< mScaleBasedVisibilityMinDDBtn
<< mScaleBasedVisibilityMinSpnBx
<< mShadowBlendCmbBx
<< mShadowBlendDDBtn
<< mShadowColorBtn
<< mShadowColorDDBtn
<< mShadowDrawChkBx
<< mShadowDrawDDBtn
<< mShadowOffsetAngleDDBtn
<< mShadowOffsetAngleSpnBx
<< mShadowOffsetDDBtn
<< mShadowOffsetGlobalChkBx
<< mShadowOffsetSpnBx
<< mShadowOffsetUnitsDDBtn
<< mShadowRadiusAlphaChkBx
<< mShadowRadiusDDBtn
<< mShadowRadiusDblSpnBx
<< mShadowRadiusUnitsDDBtn
<< mShadowScaleDDBtn
<< mShadowScaleSpnBx
<< mShadowTranspDDBtn
<< mShadowTranspSpnBx
<< mShadowUnderCmbBx
<< mShadowUnderDDBtn
<< mShapeBlendCmbBx
<< mShapeBlendModeDDBtn
<< mShapeBorderColorBtn
<< mShapeBorderColorDDBtn
<< mShapeBorderUnitsDDBtn
<< mShapeBorderWidthDDBtn
<< mShapeBorderWidthSpnBx
<< mShapeDrawChkBx
<< mShapeDrawDDBtn
<< mShapeFillColorBtn
<< mShapeFillColorDDBtn
<< mShapeOffsetDDBtn
<< mShapeOffsetUnitsDDBtn
<< mShapeOffsetXSpnBx
<< mShapeOffsetYSpnBx
<< mShapePenStyleCmbBx
<< mShapePenStyleDDBtn
<< mShapeRadiusDDBtn
<< mShapeRadiusUnitsDDBtn
<< mShapeRadiusXDbSpnBx
<< mShapeRadiusYDbSpnBx
<< mShapeRotationCmbBx
<< mShapeRotationDDBtn
<< mShapeRotationDblSpnBx
<< mShapeRotationTypeDDBtn
<< mShapeSVGPathDDBtn
<< mShapeSVGPathLineEdit
<< mShapeSizeCmbBx
<< mShapeSizeTypeDDBtn
<< mShapeSizeUnitsDDBtn
<< mShapeSizeXDDBtn
<< mShapeSizeXSpnBx
<< mShapeSizeYDDBtn
<< mShapeSizeYSpnBx
<< mShapeTranspDDBtn
<< mShapeTranspSpinBox
<< mShapeTypeCmbBx
<< mShapeTypeDDBtn
<< mShowLabelDDBtn
<< mWrapCharDDBtn
<< mZIndexDDBtn
<< mZIndexSpinBox
<< spinBufferSize
<< wrapCharacterEdit
<< mCentroidRadioVisible
<< mCentroidRadioWhole
<< mDirectSymbRadioBtnAbove
<< mDirectSymbRadioBtnBelow
<< mDirectSymbRadioBtnLR
<< mUpsidedownRadioAll
<< mUpsidedownRadioDefined
<< mUpsidedownRadioOff
<< radAroundCentroid
<< radAroundPoint
<< radLineCurved
<< radLineHorizontal
<< radLineParallel
<< radOverCentroid
<< radOverPoint
<< radPolygonFree
<< radPolygonHorizontal
<< radPolygonPerimeter
<< radPredefinedOrder
<< mFieldExpressionWidget;
connectValueChanged( widgets, SLOT( updatePreview() ) );
connect( mQuadrantBtnGrp, SIGNAL( buttonClicked( int ) ), this, SLOT( updatePreview() ) );
// set correct initial tab to match displayed setting page
whileBlocking( mOptionsTab )->setCurrentIndex( mLabelStackedWidget->currentIndex() );
}
void QgsLabelingGui::setDockMode( bool enabled )
{
mOptionsTab->setVisible( enabled );
mOptionsTab->setTabToolTip( 0, tr( "Text" ) );
mOptionsTab->setTabToolTip( 1, tr( "Formatting" ) );
mOptionsTab->setTabToolTip( 2, tr( "Buffer" ) );
mOptionsTab->setTabToolTip( 3, tr( "Background" ) );
mOptionsTab->setTabToolTip( 4, tr( "Shadow" ) );
mOptionsTab->setTabToolTip( 5, tr( "Placement" ) );
mOptionsTab->setTabToolTip( 6, tr( "Rendering" ) );
mLabelingOptionsListFrame->setVisible( !enabled );
groupBox_mPreview->setVisible( !enabled );
mDockMode = enabled;
}
void QgsLabelingGui::connectValueChanged( QList<QWidget *> widgets, const char *slot )
{
Q_FOREACH ( QWidget* widget, widgets )
{
if ( QgsDataDefinedButton* w = qobject_cast<QgsDataDefinedButton*>( widget ) )
{
connect( w, SIGNAL( dataDefinedActivated( bool ) ), this, slot );
connect( w, SIGNAL( dataDefinedChanged( QString ) ), this, slot );
}
else if ( QgsFieldExpressionWidget* w = qobject_cast<QgsFieldExpressionWidget*>( widget ) )
{
connect( w, SIGNAL( fieldChanged( QString ) ), this, slot );
}
else if ( QComboBox* w = qobject_cast<QComboBox*>( widget ) )
{
connect( w, SIGNAL( currentIndexChanged( int ) ), this, slot );
}
else if ( QSpinBox* w = qobject_cast<QSpinBox*>( widget ) )
{
connect( w, SIGNAL( valueChanged( int ) ), this, slot );
}
else if ( QDoubleSpinBox* w = qobject_cast<QDoubleSpinBox*>( widget ) )
{
connect( w , SIGNAL( valueChanged( double ) ), this, slot );
}
else if ( QgsColorButtonV2* w = qobject_cast<QgsColorButtonV2*>( widget ) )
{
connect( w, SIGNAL( colorChanged( QColor ) ), this, slot );
}
else if ( QCheckBox* w = qobject_cast<QCheckBox*>( widget ) )
{
connect( w, SIGNAL( toggled( bool ) ), this, slot );
}
else if ( QRadioButton* w = qobject_cast<QRadioButton*>( widget ) )
{
connect( w, SIGNAL( toggled( bool ) ), this, slot );
}
else if ( QLineEdit* w = qobject_cast<QLineEdit*>( widget ) )
{
connect( w, SIGNAL( textEdited( QString ) ), this, slot );
}
else if ( QSlider* w = qobject_cast<QSlider*>( widget ) )
{
connect( w, SIGNAL( valueChanged( int ) ), this, slot );
}
else
{
QgsLogger::warning( QString( "Could not create connection for widget %1" ).arg( widget->objectName() ) );
}
}
}
void QgsLabelingGui::setLayer( QgsMapLayer* mapLayer )
{
if ( !mapLayer || mapLayer->type() != QgsMapLayer::VectorLayer )
{
setEnabled( false );
return;
}
else
{
setEnabled( true );
}
QgsVectorLayer *layer = qobject_cast<QgsVectorLayer*>( mapLayer );
mLayer = layer ;
init();
}
void QgsLabelingGui::init()
{
// show/hide options based upon geometry type
chkMergeLines->setVisible( mLayer->geometryType() == Qgis::Line );
mDirectSymbolsFrame->setVisible( mLayer->geometryType() == Qgis::Line );
mMinSizeFrame->setVisible( mLayer->geometryType() != Qgis::Point );
mPolygonObstacleTypeFrame->setVisible( mLayer->geometryType() == Qgis::Polygon );
mPolygonFeatureOptionsFrame->setVisible( mLayer->geometryType() == Qgis::Polygon );
// field combo and expression button
mFieldExpressionWidget->setLayer( mLayer );
QgsDistanceArea myDa;
myDa.setSourceCrs( mLayer->crs().srsid() );
myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapSettings().hasCrsTransformEnabled() );
myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
mFieldExpressionWidget->setGeomCalculator( myDa );
// set placement methods page based on geometry type
switch ( mLayer->geometryType() )
{
case Qgis::Point:
stackedPlacement->setCurrentWidget( pagePoint );
break;
case Qgis::Line:
stackedPlacement->setCurrentWidget( pageLine );
break;
case Qgis::Polygon:
stackedPlacement->setCurrentWidget( pagePolygon );
break;
case Qgis::NoGeometry:
break;
case Qgis::UnknownGeometry:
qFatal( "unknown geometry type unexpected" );
}
if ( mLayer->geometryType() == Qgis::Point )
{
// follow placement alignment is only valid for point layers
if ( mFontMultiLineAlignComboBox->findText( tr( "Follow label placement" ) ) == -1 )
mFontMultiLineAlignComboBox->addItem( tr( "Follow label placement" ) );
}
else
{
int idx = mFontMultiLineAlignComboBox->findText( tr( "Follow label placement" ) );
if ( idx >= 0 )
mFontMultiLineAlignComboBox->removeItem( idx );
}
// load labeling settings from layer
QgsPalLayerSettings lyr;
if ( mSettings )
lyr = *mSettings;
else
lyr.readFromLayer( mLayer );
blockInitSignals( true );
mFieldExpressionWidget->setEnabled( mMode == Labels );
mLabelingFrame->setEnabled( mMode == Labels );
// set the current field or add the current expression to the bottom of the list
mFieldExpressionWidget->setRow( -1 );
mFieldExpressionWidget->setField( lyr.fieldName );
// populate placement options
mCentroidRadioWhole->setChecked( lyr.centroidWhole );
mCentroidInsideCheckBox->setChecked( lyr.centroidInside );
mFitInsidePolygonCheckBox->setChecked( lyr.fitInPolygonOnly );
mLineDistanceSpnBx->setValue( lyr.dist );
mLineDistanceUnitWidget->setUnit( lyr.distInMapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters );
mLineDistanceUnitWidget->setMapUnitScale( lyr.distMapUnitScale );
mOffsetTypeComboBox->setCurrentIndex( mOffsetTypeComboBox->findData( lyr.offsetType ) );
mQuadrantBtnGrp->button(( int )lyr.quadOffset )->setChecked( true );
mPointOffsetXSpinBox->setValue( lyr.xOffset );
mPointOffsetYSpinBox->setValue( lyr.yOffset );
mPointOffsetUnitWidget->setUnit( lyr.labelOffsetInMapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters );
mPointOffsetUnitWidget->setMapUnitScale( lyr.labelOffsetMapUnitScale );
mPointAngleSpinBox->setValue( lyr.angleOffset );
chkLineAbove->setChecked( lyr.placementFlags & QgsPalLayerSettings::AboveLine );
chkLineBelow->setChecked( lyr.placementFlags & QgsPalLayerSettings::BelowLine );
chkLineOn->setChecked( lyr.placementFlags & QgsPalLayerSettings::OnLine );
if ( !( lyr.placementFlags & QgsPalLayerSettings::MapOrientation ) )
chkLineOrientationDependent->setChecked( true );
switch ( lyr.placement )
{
case QgsPalLayerSettings::AroundPoint:
radAroundPoint->setChecked( true );
radAroundCentroid->setChecked( true );
//spinAngle->setValue( lyr.angle ); // TODO: uncomment when supported
break;
case QgsPalLayerSettings::OverPoint:
radOverPoint->setChecked( true );
radOverCentroid->setChecked( true );
break;
case QgsPalLayerSettings::OrderedPositionsAroundPoint:
radPredefinedOrder->setChecked( true );
break;
case QgsPalLayerSettings::Line:
radLineParallel->setChecked( true );
radPolygonPerimeter->setChecked( true );
break;
case QgsPalLayerSettings::Curved:
radLineCurved->setChecked( true );
break;
case QgsPalLayerSettings::Horizontal:
radPolygonHorizontal->setChecked( true );
radLineHorizontal->setChecked( true );
break;
case QgsPalLayerSettings::Free:
radPolygonFree->setChecked( true );
break;
}
// Label repeat distance
mRepeatDistanceSpinBox->setValue( lyr.repeatDistance );
mRepeatDistanceUnitWidget->setUnit( lyr.repeatDistanceUnit == QgsPalLayerSettings::MapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters );
mRepeatDistanceUnitWidget->setMapUnitScale( lyr.repeatDistanceMapUnitScale );
mPrioritySlider->setValue( lyr.priority );
mChkNoObstacle->setChecked( lyr.obstacle );
mObstacleFactorSlider->setValue( lyr.obstacleFactor * 50 );
mObstacleTypeComboBox->setCurrentIndex( mObstacleTypeComboBox->findData( lyr.obstacleType ) );
mPolygonObstacleTypeFrame->setEnabled( lyr.obstacle );
mObstaclePriorityFrame->setEnabled( lyr.obstacle );
chkLabelPerFeaturePart->setChecked( lyr.labelPerPart );
mPalShowAllLabelsForLayerChkBx->setChecked( lyr.displayAll );
chkMergeLines->setChecked( lyr.mergeLines );
mMinSizeSpinBox->setValue( lyr.minFeatureSize );
mLimitLabelChkBox->setChecked( lyr.limitNumLabels );
mLimitLabelSpinBox->setValue( lyr.maxNumLabels );
// direction symbol(s)
mDirectSymbChkBx->setChecked( lyr.addDirectionSymbol );
mDirectSymbLeftLineEdit->setText( lyr.leftDirectionSymbol );
mDirectSymbRightLineEdit->setText( lyr.rightDirectionSymbol );
mDirectSymbRevChkBx->setChecked( lyr.reverseDirectionSymbol );
mDirectSymbBtnGrp->button(( int )lyr.placeDirectionSymbol )->setChecked( true );
mUpsidedownBtnGrp->button(( int )lyr.upsidedownLabels )->setChecked( true );
// curved label max character angles
mMaxCharAngleInDSpinBox->setValue( lyr.maxCurvedCharAngleIn );
// lyr.maxCurvedCharAngleOut must be negative, but it is shown as positive spinbox in GUI
mMaxCharAngleOutDSpinBox->setValue( qAbs( lyr.maxCurvedCharAngleOut ) );
wrapCharacterEdit->setText( lyr.wrapChar );
mFontLineHeightSpinBox->setValue( lyr.multilineHeight );
mFontMultiLineAlignComboBox->setCurrentIndex(( unsigned int ) lyr.multilineAlign );
chkPreserveRotation->setChecked( lyr.preserveRotation );
mPreviewBackgroundBtn->setColor( lyr.previewBkgrdColor );
mPreviewBackgroundBtn->setDefaultColor( lyr.previewBkgrdColor );
setPreviewBackground( lyr.previewBkgrdColor );
mScaleBasedVisibilityChkBx->setChecked( lyr.scaleVisibility );
mScaleBasedVisibilityMinSpnBx->setValue( lyr.scaleMin );
mScaleBasedVisibilityMaxSpnBx->setValue( lyr.scaleMax );
// buffer
mBufferDrawChkBx->setChecked( lyr.bufferDraw );
spinBufferSize->setValue( lyr.bufferSize );
mBufferUnitWidget->setUnit( lyr.bufferSizeInMapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters );
mBufferUnitWidget->setMapUnitScale( lyr.bufferSizeMapUnitScale );
btnBufferColor->setColor( lyr.bufferColor );
mBufferTranspSpinBox->setValue( lyr.bufferTransp );
mBufferJoinStyleComboBox->setPenJoinStyle( lyr.bufferJoinStyle );
mBufferTranspFillChbx->setChecked( !lyr.bufferNoFill );
comboBufferBlendMode->setBlendMode( lyr.bufferBlendMode );
mFormatNumChkBx->setChecked( lyr.formatNumbers );
mFormatNumDecimalsSpnBx->setValue( lyr.decimals );
mFormatNumPlusSignChkBx->setChecked( lyr.plusSign );
// set pixel size limiting checked state before unit choice so limiting can be
// turned on as a default for map units, if minimum trigger value of 0 is used
mFontLimitPixelChkBox->setChecked( lyr.fontLimitPixelSize );
mMinPixelLimit = lyr.fontMinPixelSize; // ignored after first settings save
mFontMinPixelSpinBox->setValue( lyr.fontMinPixelSize == 0 ? 3 : lyr.fontMinPixelSize );
mFontMaxPixelSpinBox->setValue( lyr.fontMaxPixelSize );
mFontSizeUnitWidget->setUnit( lyr.fontSizeInMapUnits ? 1 : 0 );
mFontSizeUnitWidget->setMapUnitScale( lyr.fontSizeMapUnitScale );
mZIndexSpinBox->setValue( lyr.zIndex );
mRefFont = lyr.textFont;
mFontSizeSpinBox->setValue( lyr.textFont.pointSizeF() );
btnTextColor->setColor( lyr.textColor );
mFontTranspSpinBox->setValue( lyr.textTransp );
comboBlendMode->setBlendMode( lyr.blendMode );
mFontWordSpacingSpinBox->setValue( lyr.textFont.wordSpacing() );
mFontLetterSpacingSpinBox->setValue( lyr.textFont.letterSpacing() );
QgsFontUtils::updateFontViaStyle( mRefFont, lyr.textNamedStyle );
updateFont( mRefFont );
// show 'font not found' if substitution has occurred (should come after updateFont())
mFontMissingLabel->setVisible( !lyr.mTextFontFound );
if ( !lyr.mTextFontFound )
{
QString missingTxt = tr( "%1 not found. Default substituted." );
QString txtPrepend = tr( "Chosen font" );
if ( !lyr.mTextFontFamily.isEmpty() )
{
txtPrepend = QString( "'%1'" ).arg( lyr.mTextFontFamily );
}
mFontMissingLabel->setText( missingTxt.arg( txtPrepend ) );
// ensure user is sent to 'Text style' section to see notice
mLabelingOptionsListWidget->setCurrentRow( 0 );
}
// shape background
mShapeDrawChkBx->setChecked( lyr.shapeDraw );
mShapeTypeCmbBx->blockSignals( true );
mShapeTypeCmbBx->setCurrentIndex( lyr.shapeType );
mShapeTypeCmbBx->blockSignals( false );
mShapeSVGPathLineEdit->setText( lyr.shapeSVGFile );
mShapeSizeCmbBx->setCurrentIndex( lyr.shapeSizeType );
mShapeSizeXSpnBx->setValue( lyr.shapeSize.x() );
mShapeSizeYSpnBx->setValue( lyr.shapeSize.y() );
mShapeSizeUnitWidget->setUnit( lyr.shapeSizeUnits == QgsPalLayerSettings::MapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters );
mShapeSizeUnitWidget->setMapUnitScale( lyr.shapeSizeMapUnitScale );
mShapeRotationCmbBx->setCurrentIndex( lyr.shapeRotationType );
mShapeRotationDblSpnBx->setEnabled( lyr.shapeRotationType != QgsPalLayerSettings::RotationSync );
mShapeRotationDDBtn->setEnabled( lyr.shapeRotationType != QgsPalLayerSettings::RotationSync );
mShapeRotationDblSpnBx->setValue( lyr.shapeRotation );
mShapeOffsetXSpnBx->setValue( lyr.shapeOffset.x() );
mShapeOffsetYSpnBx->setValue( lyr.shapeOffset.y() );
mShapeOffsetUnitWidget->setUnit( lyr.shapeOffsetUnits == QgsPalLayerSettings::MapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters );
mShapeOffsetUnitWidget->setMapUnitScale( lyr.shapeOffsetMapUnitScale );
mShapeRadiusXDbSpnBx->setValue( lyr.shapeRadii.x() );
mShapeRadiusYDbSpnBx->setValue( lyr.shapeRadii.y() );
mShapeRadiusUnitWidget->setUnit( lyr.shapeRadiiUnits - 1 );
mShapeRadiusUnitWidget->setMapUnitScale( lyr.shapeRadiiMapUnitScale );
mShapeFillColorBtn->setColor( lyr.shapeFillColor );
mShapeBorderColorBtn->setColor( lyr.shapeBorderColor );
mShapeBorderWidthSpnBx->setValue( lyr.shapeBorderWidth );
mShapeBorderWidthUnitWidget->setUnit( lyr.shapeBorderWidthUnits == QgsPalLayerSettings::MapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters );
mShapeBorderWidthUnitWidget->setMapUnitScale( lyr.shapeBorderWidthMapUnitScale );
mShapePenStyleCmbBx->setPenJoinStyle( lyr.shapeJoinStyle );
mShapeTranspSpinBox->setValue( lyr.shapeTransparency );
mShapeBlendCmbBx->setBlendMode( lyr.shapeBlendMode );
mLoadSvgParams = false;
on_mShapeTypeCmbBx_currentIndexChanged( lyr.shapeType ); // force update of shape background gui
// drop shadow
mShadowDrawChkBx->setChecked( lyr.shadowDraw );
mShadowUnderCmbBx->setCurrentIndex( lyr.shadowUnder );
mShadowOffsetAngleSpnBx->setValue( lyr.shadowOffsetAngle );
mShadowOffsetSpnBx->setValue( lyr.shadowOffsetDist );
mShadowOffsetUnitWidget->setUnit( lyr.shadowOffsetUnits == QgsPalLayerSettings::MapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters );
mShadowOffsetUnitWidget->setMapUnitScale( lyr.shadowOffsetMapUnitScale );
mShadowOffsetGlobalChkBx->setChecked( lyr.shadowOffsetGlobal );
mShadowRadiusDblSpnBx->setValue( lyr.shadowRadius );
mShadowRadiusUnitWidget->setUnit( lyr.shadowRadiusUnits == QgsPalLayerSettings::MapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters );
mShadowRadiusUnitWidget->setMapUnitScale( lyr.shadowRadiusMapUnitScale );
mShadowRadiusAlphaChkBx->setChecked( lyr.shadowRadiusAlphaOnly );
mShadowTranspSpnBx->setValue( lyr.shadowTransparency );
mShadowScaleSpnBx->setValue( lyr.shadowScale );
mShadowColorBtn->setColor( lyr.shadowColor );
mShadowBlendCmbBx->setBlendMode( lyr.shadowBlendMode );
updatePlacementWidgets();
updateLinePlacementOptions();
// needs to come before data defined setup, so connections work
blockInitSignals( false );
// set up data defined toolbuttons
// do this after other widgets are configured, so they can be enabled/disabled
populateDataDefinedButtons( lyr );
enableDataDefinedAlignment( mCoordXDDBtn->isActive() && mCoordYDDBtn->isActive() );
updateUi(); // should come after data defined button setup
}
QgsLabelingGui::~QgsLabelingGui()
{
QSettings settings;
settings.setValue( QString( "/Windows/Labeling/FontPreviewSplitState" ), mFontPreviewSplitter->saveState() );
settings.setValue( QString( "/Windows/Labeling/OptionsSplitState" ), mLabelingOptionsSplitter->saveState() );
settings.setValue( QString( "/Windows/Labeling/Tab" ), mLabelingOptionsListWidget->currentRow() );
}
void QgsLabelingGui::blockInitSignals( bool block )
{
chkLineAbove->blockSignals( block );
chkLineBelow->blockSignals( block );
mPlacePointBtnGrp->blockSignals( block );
mPlaceLineBtnGrp->blockSignals( block );
mPlacePolygonBtnGrp->blockSignals( block );
}
void QgsLabelingGui::optionsStackedWidget_CurrentChanged( int indx )
{
mLabelingOptionsListWidget->blockSignals( true );
mLabelingOptionsListWidget->setCurrentRow( indx );
mLabelingOptionsListWidget->blockSignals( false );
}
void QgsLabelingGui::collapseSample( bool collapse )
{
if ( collapse )
{
QList<int> splitSizes = mFontPreviewSplitter->sizes();
if ( splitSizes[0] > groupBox_mPreview->height() )
{
int delta = splitSizes[0] - groupBox_mPreview->height();
splitSizes[0] -= delta;
splitSizes[1] += delta;
mFontPreviewSplitter->setSizes( splitSizes );
}
}
}
void QgsLabelingGui::apply()
{
writeSettingsToLayer();
mFontMissingLabel->setVisible( false );
QgisApp::instance()->markDirty();
// trigger refresh
mLayer->triggerRepaint();
}
void QgsLabelingGui::writeSettingsToLayer()
{
mLayer->setLabeling( new QgsVectorLayerSimpleLabeling );
// all configuration is still in layer's custom properties
QgsPalLayerSettings settings = layerSettings();
settings.writeToLayer( mLayer );
}
void QgsLabelingGui::setLabelMode( LabelMode mode )
{
mMode = mode;
mFieldExpressionWidget->setEnabled( mMode == Labels );
mLabelingFrame->setEnabled( mMode == Labels );
}
QgsPalLayerSettings QgsLabelingGui::layerSettings()
{
QgsPalLayerSettings lyr;
lyr.enabled = ( mMode == Labels || mMode == ObstaclesOnly );
lyr.drawLabels = ( mMode == Labels );
bool isExpression;
lyr.fieldName = mFieldExpressionWidget->currentField( &isExpression );
lyr.isExpression = isExpression;
lyr.dist = 0;
lyr.placementFlags = 0;
QWidget* curPlacementWdgt = stackedPlacement->currentWidget();
lyr.centroidWhole = mCentroidRadioWhole->isChecked();
lyr.centroidInside = mCentroidInsideCheckBox->isChecked();
lyr.fitInPolygonOnly = mFitInsidePolygonCheckBox->isChecked();
lyr.dist = mLineDistanceSpnBx->value();
lyr.distInMapUnits = ( mLineDistanceUnitWidget->unit() == QgsUnitTypes::RenderMapUnits );
lyr.distMapUnitScale = mLineDistanceUnitWidget->getMapUnitScale();
lyr.offsetType = static_cast< QgsPalLayerSettings::OffsetType >( mOffsetTypeComboBox->itemData( mOffsetTypeComboBox->currentIndex() ).toInt() );
lyr.quadOffset = ( QgsPalLayerSettings::QuadrantPosition )mQuadrantBtnGrp->checkedId();
lyr.xOffset = mPointOffsetXSpinBox->value();
lyr.yOffset = mPointOffsetYSpinBox->value();
lyr.labelOffsetInMapUnits = ( mPointOffsetUnitWidget->unit() == QgsUnitTypes::RenderMapUnits );
lyr.labelOffsetMapUnitScale = mPointOffsetUnitWidget->getMapUnitScale();
lyr.angleOffset = mPointAngleSpinBox->value();
if ( chkLineAbove->isChecked() )
lyr.placementFlags |= QgsPalLayerSettings::AboveLine;
if ( chkLineBelow->isChecked() )
lyr.placementFlags |= QgsPalLayerSettings::BelowLine;
if ( chkLineOn->isChecked() )
lyr.placementFlags |= QgsPalLayerSettings::OnLine;
if ( ! chkLineOrientationDependent->isChecked() )
lyr.placementFlags |= QgsPalLayerSettings::MapOrientation;
if (( curPlacementWdgt == pagePoint && radAroundPoint->isChecked() )
|| ( curPlacementWdgt == pagePolygon && radAroundCentroid->isChecked() ) )
{
lyr.placement = QgsPalLayerSettings::AroundPoint;
}
else if (( curPlacementWdgt == pagePoint && radOverPoint->isChecked() )
|| ( curPlacementWdgt == pagePolygon && radOverCentroid->isChecked() ) )
{
lyr.placement = QgsPalLayerSettings::OverPoint;
}
else if ( curPlacementWdgt == pagePoint && radPredefinedOrder->isChecked() )
{
lyr.placement = QgsPalLayerSettings::OrderedPositionsAroundPoint;
}
else if (( curPlacementWdgt == pageLine && radLineParallel->isChecked() )
|| ( curPlacementWdgt == pagePolygon && radPolygonPerimeter->isChecked() )
|| ( curPlacementWdgt == pageLine && radLineCurved->isChecked() ) )
{
bool curved = ( curPlacementWdgt == pageLine && radLineCurved->isChecked() );
lyr.placement = ( curved ? QgsPalLayerSettings::Curved : QgsPalLayerSettings::Line );
}
else if (( curPlacementWdgt == pageLine && radLineHorizontal->isChecked() )
|| ( curPlacementWdgt == pagePolygon && radPolygonHorizontal->isChecked() ) )
{
lyr.placement = QgsPalLayerSettings::Horizontal;
}
else if ( radPolygonFree->isChecked() )
{
lyr.placement = QgsPalLayerSettings::Free;
}
else
{
qFatal( "Invalid settings" );
}
lyr.repeatDistance = mRepeatDistanceSpinBox->value();
lyr.repeatDistanceUnit = mRepeatDistanceUnitWidget->unit() == QgsUnitTypes::RenderMapUnits ? QgsPalLayerSettings::MapUnits : QgsPalLayerSettings::MM;
lyr.repeatDistanceMapUnitScale = mRepeatDistanceUnitWidget->getMapUnitScale();
lyr.textColor = btnTextColor->color();
lyr.textFont = mRefFont;
lyr.textNamedStyle = mFontStyleComboBox->currentText();
lyr.textTransp = mFontTranspSpinBox->value();
lyr.blendMode = comboBlendMode->blendMode();
lyr.previewBkgrdColor = mPreviewBackgroundBtn->color();
lyr.priority = mPrioritySlider->value();
lyr.obstacle = mChkNoObstacle->isChecked() || mMode == ObstaclesOnly;
lyr.obstacleFactor = mObstacleFactorSlider->value() / 50.0;
lyr.obstacleType = ( QgsPalLayerSettings::ObstacleType )mObstacleTypeComboBox->itemData( mObstacleTypeComboBox->currentIndex() ).toInt();
lyr.labelPerPart = chkLabelPerFeaturePart->isChecked();
lyr.displayAll = mPalShowAllLabelsForLayerChkBx->isChecked();
lyr.mergeLines = chkMergeLines->isChecked();
lyr.scaleVisibility = mScaleBasedVisibilityChkBx->isChecked();
lyr.scaleMin = mScaleBasedVisibilityMinSpnBx->value();
lyr.scaleMax = mScaleBasedVisibilityMaxSpnBx->value();
// buffer
lyr.bufferDraw = mBufferDrawChkBx->isChecked();
lyr.bufferSize = spinBufferSize->value();
lyr.bufferColor = btnBufferColor->color();
lyr.bufferTransp = mBufferTranspSpinBox->value();
lyr.bufferSizeInMapUnits = ( mBufferUnitWidget->unit() == QgsUnitTypes::RenderMapUnits );
lyr.bufferSizeMapUnitScale = mBufferUnitWidget->getMapUnitScale();
lyr.bufferJoinStyle = mBufferJoinStyleComboBox->penJoinStyle();
lyr.bufferNoFill = !mBufferTranspFillChbx->isChecked();
lyr.bufferBlendMode = comboBufferBlendMode->blendMode();
// shape background
lyr.shapeDraw = mShapeDrawChkBx->isChecked();
lyr.shapeType = ( QgsPalLayerSettings::ShapeType )mShapeTypeCmbBx->currentIndex();
lyr.shapeSVGFile = mShapeSVGPathLineEdit->text();
lyr.shapeSizeType = ( QgsPalLayerSettings::SizeType )mShapeSizeCmbBx->currentIndex();
lyr.shapeSize = QPointF( mShapeSizeXSpnBx->value(), mShapeSizeYSpnBx->value() );
lyr.shapeSizeUnits = mShapeSizeUnitWidget->unit() == QgsUnitTypes::RenderMapUnits ? QgsPalLayerSettings::MapUnits : QgsPalLayerSettings::MM;
lyr.shapeSizeMapUnitScale = mShapeSizeUnitWidget->getMapUnitScale();
lyr.shapeRotationType = ( QgsPalLayerSettings::RotationType )( mShapeRotationCmbBx->currentIndex() );
lyr.shapeRotation = mShapeRotationDblSpnBx->value();
lyr.shapeOffset = QPointF( mShapeOffsetXSpnBx->value(), mShapeOffsetYSpnBx->value() );
lyr.shapeOffsetUnits = mShapeOffsetUnitWidget->unit() == QgsUnitTypes::RenderMapUnits ? QgsPalLayerSettings::MapUnits : QgsPalLayerSettings::MM;
lyr.shapeOffsetMapUnitScale = mShapeOffsetUnitWidget->getMapUnitScale();
lyr.shapeRadii = QPointF( mShapeRadiusXDbSpnBx->value(), mShapeRadiusYDbSpnBx->value() );
lyr.shapeRadiiUnits = ( QgsPalLayerSettings::SizeUnit )( mShapeRadiusUnitWidget->getUnit() + 1 );
lyr.shapeRadiiMapUnitScale = mShapeRadiusUnitWidget->getMapUnitScale();
lyr.shapeFillColor = mShapeFillColorBtn->color();
lyr.shapeBorderColor = mShapeBorderColorBtn->color();
lyr.shapeBorderWidth = mShapeBorderWidthSpnBx->value();
lyr.shapeBorderWidthUnits = mShapeBorderWidthUnitWidget->unit() == QgsUnitTypes::RenderMapUnits ? QgsPalLayerSettings::MapUnits : QgsPalLayerSettings::MM;
lyr.shapeBorderWidthMapUnitScale = mShapeBorderWidthUnitWidget->getMapUnitScale();
lyr.shapeJoinStyle = mShapePenStyleCmbBx->penJoinStyle();
lyr.shapeTransparency = mShapeTranspSpinBox->value();
lyr.shapeBlendMode = mShapeBlendCmbBx->blendMode();
// drop shadow
lyr.shadowDraw = mShadowDrawChkBx->isChecked();
lyr.shadowUnder = ( QgsPalLayerSettings::ShadowType )mShadowUnderCmbBx->currentIndex();
lyr.shadowOffsetAngle = mShadowOffsetAngleSpnBx->value();
lyr.shadowOffsetDist = mShadowOffsetSpnBx->value();
lyr.shadowOffsetUnits = mShadowOffsetUnitWidget->unit() == QgsUnitTypes::RenderMapUnits ? QgsPalLayerSettings::MapUnits : QgsPalLayerSettings::MM;
lyr.shadowOffsetMapUnitScale = mShadowOffsetUnitWidget->getMapUnitScale();
lyr.shadowOffsetGlobal = mShadowOffsetGlobalChkBx->isChecked();
lyr.shadowRadius = mShadowRadiusDblSpnBx->value();
lyr.shadowRadiusUnits = mShadowRadiusUnitWidget->unit() == QgsUnitTypes::RenderMapUnits ? QgsPalLayerSettings::MapUnits : QgsPalLayerSettings::MM;
lyr.shadowRadiusMapUnitScale = mShadowRadiusUnitWidget->getMapUnitScale();
lyr.shadowRadiusAlphaOnly = mShadowRadiusAlphaChkBx->isChecked();
lyr.shadowTransparency = mShadowTranspSpnBx->value();
lyr.shadowScale = mShadowScaleSpnBx->value();
lyr.shadowColor = mShadowColorBtn->color();
lyr.shadowBlendMode = mShadowBlendCmbBx->blendMode();
// format numbers
lyr.formatNumbers = mFormatNumChkBx->isChecked();
lyr.decimals = mFormatNumDecimalsSpnBx->value();
lyr.plusSign = mFormatNumPlusSignChkBx->isChecked();
// direction symbol(s)
lyr.addDirectionSymbol = mDirectSymbChkBx->isChecked();
lyr.leftDirectionSymbol = mDirectSymbLeftLineEdit->text();
lyr.rightDirectionSymbol = mDirectSymbRightLineEdit->text();
lyr.reverseDirectionSymbol = mDirectSymbRevChkBx->isChecked();
lyr.placeDirectionSymbol = ( QgsPalLayerSettings::DirectionSymbols )mDirectSymbBtnGrp->checkedId();
lyr.upsidedownLabels = ( QgsPalLayerSettings::UpsideDownLabels )mUpsidedownBtnGrp->checkedId();
lyr.maxCurvedCharAngleIn = mMaxCharAngleInDSpinBox->value();
// lyr.maxCurvedCharAngleOut must be negative, but it is shown as positive spinbox in GUI
lyr.maxCurvedCharAngleOut = -mMaxCharAngleOutDSpinBox->value();
lyr.minFeatureSize = mMinSizeSpinBox->value();
lyr.limitNumLabels = mLimitLabelChkBox->isChecked();
lyr.maxNumLabels = mLimitLabelSpinBox->value();
lyr.fontSizeInMapUnits = ( mFontSizeUnitWidget->getUnit() == 1 );
lyr.fontSizeMapUnitScale = mFontSizeUnitWidget->getMapUnitScale();
lyr.fontLimitPixelSize = mFontLimitPixelChkBox->isChecked();
lyr.fontMinPixelSize = mFontMinPixelSpinBox->value();
lyr.fontMaxPixelSize = mFontMaxPixelSpinBox->value();
lyr.wrapChar = wrapCharacterEdit->text();
lyr.multilineHeight = mFontLineHeightSpinBox->value();
lyr.multilineAlign = ( QgsPalLayerSettings::MultiLineAlign ) mFontMultiLineAlignComboBox->currentIndex();
lyr.preserveRotation = chkPreserveRotation->isChecked();
lyr.zIndex = mZIndexSpinBox->value();
// data defined labeling
// text style
setDataDefinedProperty( mFontDDBtn, QgsPalLayerSettings::Family, lyr );
setDataDefinedProperty( mFontStyleDDBtn, QgsPalLayerSettings::FontStyle, lyr );
setDataDefinedProperty( mFontUnderlineDDBtn, QgsPalLayerSettings::Underline, lyr );
setDataDefinedProperty( mFontStrikeoutDDBtn, QgsPalLayerSettings::Strikeout, lyr );
setDataDefinedProperty( mFontBoldDDBtn, QgsPalLayerSettings::Bold, lyr );
setDataDefinedProperty( mFontItalicDDBtn, QgsPalLayerSettings::Italic, lyr );
setDataDefinedProperty( mFontSizeDDBtn, QgsPalLayerSettings::Size, lyr );
setDataDefinedProperty( mFontUnitsDDBtn, QgsPalLayerSettings::FontSizeUnit, lyr );
setDataDefinedProperty( mFontColorDDBtn, QgsPalLayerSettings::Color, lyr );
setDataDefinedProperty( mFontTranspDDBtn, QgsPalLayerSettings::FontTransp, lyr );
setDataDefinedProperty( mFontCaseDDBtn, QgsPalLayerSettings::FontCase, lyr );
setDataDefinedProperty( mFontLetterSpacingDDBtn, QgsPalLayerSettings::FontLetterSpacing, lyr );
setDataDefinedProperty( mFontWordSpacingDDBtn, QgsPalLayerSettings::FontWordSpacing, lyr );
setDataDefinedProperty( mFontBlendModeDDBtn, QgsPalLayerSettings::FontBlendMode, lyr );
// text formatting
setDataDefinedProperty( mWrapCharDDBtn, QgsPalLayerSettings::MultiLineWrapChar, lyr );
setDataDefinedProperty( mFontLineHeightDDBtn, QgsPalLayerSettings::MultiLineHeight, lyr );
setDataDefinedProperty( mFontMultiLineAlignDDBtn, QgsPalLayerSettings::MultiLineAlignment, lyr );
setDataDefinedProperty( mDirectSymbDDBtn, QgsPalLayerSettings::DirSymbDraw, lyr );
setDataDefinedProperty( mDirectSymbLeftDDBtn, QgsPalLayerSettings::DirSymbLeft, lyr );
setDataDefinedProperty( mDirectSymbRightDDBtn, QgsPalLayerSettings::DirSymbRight, lyr );
setDataDefinedProperty( mDirectSymbPlacementDDBtn, QgsPalLayerSettings::DirSymbPlacement, lyr );
setDataDefinedProperty( mDirectSymbRevDDBtn, QgsPalLayerSettings::DirSymbReverse, lyr );
setDataDefinedProperty( mFormatNumDDBtn, QgsPalLayerSettings::NumFormat, lyr );
setDataDefinedProperty( mFormatNumDecimalsDDBtn, QgsPalLayerSettings::NumDecimals, lyr );
setDataDefinedProperty( mFormatNumPlusSignDDBtn, QgsPalLayerSettings::NumPlusSign, lyr );
// text buffer
setDataDefinedProperty( mBufferDrawDDBtn, QgsPalLayerSettings::BufferDraw, lyr );
setDataDefinedProperty( mBufferSizeDDBtn, QgsPalLayerSettings::BufferSize, lyr );
setDataDefinedProperty( mBufferUnitsDDBtn, QgsPalLayerSettings::BufferUnit, lyr );
setDataDefinedProperty( mBufferColorDDBtn, QgsPalLayerSettings::BufferColor, lyr );
setDataDefinedProperty( mBufferTranspDDBtn, QgsPalLayerSettings::BufferTransp, lyr );
setDataDefinedProperty( mBufferJoinStyleDDBtn, QgsPalLayerSettings::BufferJoinStyle, lyr );
setDataDefinedProperty( mBufferBlendModeDDBtn, QgsPalLayerSettings::BufferBlendMode, lyr );
// background
setDataDefinedProperty( mShapeDrawDDBtn, QgsPalLayerSettings::ShapeDraw, lyr );
setDataDefinedProperty( mShapeTypeDDBtn, QgsPalLayerSettings::ShapeKind, lyr );
setDataDefinedProperty( mShapeSVGPathDDBtn, QgsPalLayerSettings::ShapeSVGFile, lyr );
setDataDefinedProperty( mShapeSizeTypeDDBtn, QgsPalLayerSettings::ShapeSizeType, lyr );
setDataDefinedProperty( mShapeSizeXDDBtn, QgsPalLayerSettings::ShapeSizeX, lyr );
setDataDefinedProperty( mShapeSizeYDDBtn, QgsPalLayerSettings::ShapeSizeY, lyr );
setDataDefinedProperty( mShapeSizeUnitsDDBtn, QgsPalLayerSettings::ShapeSizeUnits, lyr );
setDataDefinedProperty( mShapeRotationTypeDDBtn, QgsPalLayerSettings::ShapeRotationType, lyr );
setDataDefinedProperty( mShapeRotationDDBtn, QgsPalLayerSettings::ShapeRotation, lyr );
setDataDefinedProperty( mShapeOffsetDDBtn, QgsPalLayerSettings::ShapeOffset, lyr );
setDataDefinedProperty( mShapeOffsetUnitsDDBtn, QgsPalLayerSettings::ShapeOffsetUnits, lyr );
setDataDefinedProperty( mShapeRadiusDDBtn, QgsPalLayerSettings::ShapeRadii, lyr );
setDataDefinedProperty( mShapeRadiusUnitsDDBtn, QgsPalLayerSettings::ShapeRadiiUnits, lyr );
setDataDefinedProperty( mShapeTranspDDBtn, QgsPalLayerSettings::ShapeTransparency, lyr );
setDataDefinedProperty( mShapeBlendModeDDBtn, QgsPalLayerSettings::ShapeBlendMode, lyr );
setDataDefinedProperty( mShapeFillColorDDBtn, QgsPalLayerSettings::ShapeFillColor, lyr );
setDataDefinedProperty( mShapeBorderColorDDBtn, QgsPalLayerSettings::ShapeBorderColor, lyr );
setDataDefinedProperty( mShapeBorderWidthDDBtn, QgsPalLayerSettings::ShapeBorderWidth, lyr );
setDataDefinedProperty( mShapeBorderUnitsDDBtn, QgsPalLayerSettings::ShapeBorderWidthUnits, lyr );
setDataDefinedProperty( mShapePenStyleDDBtn, QgsPalLayerSettings::ShapeJoinStyle, lyr );
// drop shadow
setDataDefinedProperty( mShadowDrawDDBtn, QgsPalLayerSettings::ShadowDraw, lyr );
setDataDefinedProperty( mShadowUnderDDBtn, QgsPalLayerSettings::ShadowUnder, lyr );
setDataDefinedProperty( mShadowOffsetAngleDDBtn, QgsPalLayerSettings::ShadowOffsetAngle, lyr );
setDataDefinedProperty( mShadowOffsetDDBtn, QgsPalLayerSettings::ShadowOffsetDist, lyr );
setDataDefinedProperty( mShadowOffsetUnitsDDBtn, QgsPalLayerSettings::ShadowOffsetUnits, lyr );
setDataDefinedProperty( mShadowRadiusDDBtn, QgsPalLayerSettings::ShadowRadius, lyr );
setDataDefinedProperty( mShadowRadiusUnitsDDBtn, QgsPalLayerSettings::ShadowRadiusUnits, lyr );
setDataDefinedProperty( mShadowTranspDDBtn, QgsPalLayerSettings::ShadowTransparency, lyr );
setDataDefinedProperty( mShadowScaleDDBtn, QgsPalLayerSettings::ShadowScale, lyr );
setDataDefinedProperty( mShadowColorDDBtn, QgsPalLayerSettings::ShadowColor, lyr );
setDataDefinedProperty( mShadowBlendDDBtn, QgsPalLayerSettings::ShadowBlendMode, lyr );
// placement
setDataDefinedProperty( mCentroidDDBtn, QgsPalLayerSettings::CentroidWhole, lyr );
setDataDefinedProperty( mPointQuadOffsetDDBtn, QgsPalLayerSettings::OffsetQuad, lyr );
setDataDefinedProperty( mPointPositionOrderDDBtn, QgsPalLayerSettings::PredefinedPositionOrder, lyr );
setDataDefinedProperty( mPointOffsetDDBtn, QgsPalLayerSettings::OffsetXY, lyr );
setDataDefinedProperty( mPointOffsetUnitsDDBtn, QgsPalLayerSettings::OffsetUnits, lyr );
setDataDefinedProperty( mLineDistanceDDBtn, QgsPalLayerSettings::LabelDistance, lyr );
setDataDefinedProperty( mLineDistanceUnitDDBtn, QgsPalLayerSettings::DistanceUnits, lyr );
// TODO: is this necessary? maybe just use the data defined-only rotation?
//setDataDefinedProperty( mPointAngleDDBtn, QgsPalLayerSettings::OffsetRotation, lyr );
setDataDefinedProperty( mMaxCharAngleDDBtn, QgsPalLayerSettings::CurvedCharAngleInOut, lyr );
setDataDefinedProperty( mRepeatDistanceDDBtn, QgsPalLayerSettings::RepeatDistance, lyr );
setDataDefinedProperty( mRepeatDistanceUnitDDBtn, QgsPalLayerSettings::RepeatDistanceUnit, lyr );
setDataDefinedProperty( mPriorityDDBtn, QgsPalLayerSettings::Priority, lyr );
// data defined-only
setDataDefinedProperty( mCoordXDDBtn, QgsPalLayerSettings::PositionX, lyr );
setDataDefinedProperty( mCoordYDDBtn, QgsPalLayerSettings::PositionY, lyr );
setDataDefinedProperty( mCoordAlignmentHDDBtn, QgsPalLayerSettings::Hali, lyr );
setDataDefinedProperty( mCoordAlignmentVDDBtn, QgsPalLayerSettings::Vali, lyr );
setDataDefinedProperty( mCoordRotationDDBtn, QgsPalLayerSettings::Rotation, lyr );
// rendering
setDataDefinedProperty( mScaleBasedVisibilityDDBtn, QgsPalLayerSettings::ScaleVisibility, lyr );
setDataDefinedProperty( mScaleBasedVisibilityMinDDBtn, QgsPalLayerSettings::MinScale, lyr );
setDataDefinedProperty( mScaleBasedVisibilityMaxDDBtn, QgsPalLayerSettings::MaxScale, lyr );
setDataDefinedProperty( mFontLimitPixelDDBtn, QgsPalLayerSettings::FontLimitPixel, lyr );
setDataDefinedProperty( mFontMinPixelDDBtn, QgsPalLayerSettings::FontMinPixel, lyr );
setDataDefinedProperty( mFontMaxPixelDDBtn, QgsPalLayerSettings::FontMaxPixel, lyr );
setDataDefinedProperty( mShowLabelDDBtn, QgsPalLayerSettings::Show, lyr );
setDataDefinedProperty( mAlwaysShowDDBtn, QgsPalLayerSettings::AlwaysShow, lyr );
setDataDefinedProperty( mIsObstacleDDBtn, QgsPalLayerSettings::IsObstacle, lyr );
setDataDefinedProperty( mObstacleFactorDDBtn, QgsPalLayerSettings::ObstacleFactor, lyr );
setDataDefinedProperty( mZIndexDDBtn, QgsPalLayerSettings::ZIndex, lyr );
return lyr;
}
void QgsLabelingGui::setDataDefinedProperty( const QgsDataDefinedButton* ddBtn, QgsPalLayerSettings::DataDefinedProperties p, QgsPalLayerSettings& lyr )
{
const QMap< QString, QString >& map = ddBtn->definedProperty();
lyr.setDataDefinedProperty( p, map.value( "active" ).toInt(), map.value( "useexpr" ).toInt(), map.value( "expression" ), map.value( "field" ) );
}
void QgsLabelingGui::populateDataDefinedButtons( QgsPalLayerSettings& s )
{
Q_FOREACH ( QgsDataDefinedButton* button, findChildren< QgsDataDefinedButton* >() )
{
button->registerGetExpressionContextCallback( &_getExpressionContext, mLayer );
}
// don't register enable/disable siblings, since visual feedback from data defined buttons should be enough,
// and ability to edit layer-level setting should remain enabled regardless
QString trString = tr( "string " );
// text style
mFontDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::Family ),
QgsDataDefinedButton::String,
trString + tr( "[<b>family</b>|<b>family[foundry]</b>],<br>"
"e.g. Helvetica or Helvetica [Cronyx]" ) );
mFontStyleDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::FontStyle ),
QgsDataDefinedButton::String,
trString + tr( "[<b>font style name</b>|<b>Ignore</b>],<br>"
"e.g. Bold Condensed or Light Italic" ) );
mFontUnderlineDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::Underline ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::boolDesc() );
mFontStrikeoutDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::Strikeout ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::boolDesc() );
mFontBoldDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::Bold ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::boolDesc() );
mFontItalicDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::Italic ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::boolDesc() );
mFontSizeDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::Size ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doublePosDesc() );
mFontUnitsDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::FontSizeUnit ),
QgsDataDefinedButton::String, trString + "[<b>Points</b>|<b>MapUnit</b>]" );
mFontColorDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::Color ),
QgsDataDefinedButton::String, QgsDataDefinedButton::colorNoAlphaDesc() );
mFontTranspDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::FontTransp ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::intTranspDesc() );
mFontCaseDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::FontCase ),
QgsDataDefinedButton::String,
trString + QLatin1String( "[<b>NoChange</b>|<b>Upper</b>|<br>"
"<b>Lower</b>|<b>Capitalize</b>]" ) );
mFontLetterSpacingDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::FontLetterSpacing ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleDesc() );
mFontWordSpacingDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::FontWordSpacing ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleDesc() );
mFontBlendModeDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::FontBlendMode ),
QgsDataDefinedButton::String, QgsDataDefinedButton::blendModesDesc() );
// text formatting
mWrapCharDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::MultiLineWrapChar ),
QgsDataDefinedButton::String, QgsDataDefinedButton::anyStringDesc() );
mFontLineHeightDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::MultiLineHeight ),
QgsDataDefinedButton::AnyType, tr( "double [0.0-10.0]" ) );
mFontMultiLineAlignDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::MultiLineAlignment ),
QgsDataDefinedButton::String, trString + "[<b>Left</b>|<b>Center</b>|<b>Right</b>|<b>Follow</b>]" );
mDirectSymbDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::DirSymbDraw ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::boolDesc() );
mDirectSymbDDBtn->registerCheckedWidget( mDirectSymbChkBx );
mDirectSymbLeftDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::DirSymbLeft ),
QgsDataDefinedButton::String, QgsDataDefinedButton::anyStringDesc() );
mDirectSymbRightDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::DirSymbRight ),
QgsDataDefinedButton::String, QgsDataDefinedButton::anyStringDesc() );
mDirectSymbPlacementDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::DirSymbPlacement ),
QgsDataDefinedButton::String,
trString + "[<b>LeftRight</b>|<b>Above</b>|<b>Below</b>]" );
mDirectSymbRevDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::DirSymbReverse ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::boolDesc() );
mFormatNumDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::NumFormat ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::boolDesc() );
mFormatNumDDBtn->registerCheckedWidget( mFormatNumChkBx );
mFormatNumDecimalsDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::NumDecimals ),
QgsDataDefinedButton::AnyType, tr( "int [0-20]" ) );
mFormatNumPlusSignDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::NumPlusSign ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::boolDesc() );
// text buffer
mBufferDrawDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::BufferDraw ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::boolDesc() );
mBufferDrawDDBtn->registerCheckedWidget( mBufferDrawChkBx );
mBufferSizeDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::BufferSize ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doublePosDesc() );
mBufferUnitsDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::BufferUnit ),
QgsDataDefinedButton::String, QgsDataDefinedButton::unitsMmMuDesc() );
mBufferColorDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::BufferColor ),
QgsDataDefinedButton::String, QgsDataDefinedButton::colorNoAlphaDesc() );
mBufferTranspDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::BufferTransp ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::intTranspDesc() );
mBufferJoinStyleDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::BufferJoinStyle ),
QgsDataDefinedButton::String, QgsDataDefinedButton::penJoinStyleDesc() );
mBufferBlendModeDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::BufferBlendMode ),
QgsDataDefinedButton::String, QgsDataDefinedButton::blendModesDesc() );
// background
mShapeDrawDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeDraw ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::boolDesc() );
mShapeDrawDDBtn->registerCheckedWidget( mShapeDrawChkBx );
mShapeTypeDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeKind ),
QgsDataDefinedButton::String,
trString + QLatin1String( "[<b>Rectangle</b>|<b>Square</b>|<br>"
"<b>Ellipse</b>|<b>Circle</b>|<b>SVG</b>]" ) );
mShapeSVGPathDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeSVGFile ),
QgsDataDefinedButton::String, QgsDataDefinedButton::svgPathDesc() );
mShapeSizeTypeDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeSizeType ),
QgsDataDefinedButton::String,
trString + "[<b>Buffer</b>|<b>Fixed</b>]" );
mShapeSizeXDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeSizeX ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleDesc() );
mShapeSizeYDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeSizeY ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleDesc() );
mShapeSizeUnitsDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeSizeUnits ),
QgsDataDefinedButton::String, QgsDataDefinedButton::unitsMmMuDesc() );
mShapeRotationTypeDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeRotationType ),
QgsDataDefinedButton::String,
trString + "[<b>Sync</b>|<b>Offset</b>|<b>Fixed</b>]" );
mShapeRotationDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeRotation ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::double180RotDesc() );
mShapeOffsetDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeOffset ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleXYDesc() );
mShapeOffsetUnitsDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeOffsetUnits ),
QgsDataDefinedButton::String, QgsDataDefinedButton::unitsMmMuDesc() );
mShapeRadiusDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeRadii ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleXYDesc() );
mShapeRadiusUnitsDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeRadiiUnits ),
QgsDataDefinedButton::String, QgsDataDefinedButton::unitsMmMuPercentDesc() );
mShapeTranspDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeTransparency ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::intTranspDesc() );
mShapeBlendModeDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeBlendMode ),
QgsDataDefinedButton::String, QgsDataDefinedButton::blendModesDesc() );
mShapeFillColorDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeFillColor ),
QgsDataDefinedButton::String, QgsDataDefinedButton::colorAlphaDesc() );
mShapeBorderColorDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeBorderColor ),
QgsDataDefinedButton::String, QgsDataDefinedButton::colorAlphaDesc() );
mShapeBorderWidthDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeBorderWidth ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doublePosDesc() );
mShapeBorderUnitsDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeBorderWidthUnits ),
QgsDataDefinedButton::String, QgsDataDefinedButton::unitsMmMuDesc() );
mShapePenStyleDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShapeJoinStyle ),
QgsDataDefinedButton::String, QgsDataDefinedButton::penJoinStyleDesc() );
// drop shadows
mShadowDrawDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShadowDraw ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::boolDesc() );
mShadowDrawDDBtn->registerCheckedWidget( mShadowDrawChkBx );
mShadowUnderDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShadowUnder ),
QgsDataDefinedButton::String,
trString + QLatin1String( "[<b>Lowest</b>|<b>Text</b>|<br>"
"<b>Buffer</b>|<b>Background</b>]" ) );
mShadowOffsetAngleDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShadowOffsetAngle ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::double180RotDesc() );
mShadowOffsetDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShadowOffsetDist ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doublePosDesc() );
mShadowOffsetUnitsDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShadowOffsetUnits ),
QgsDataDefinedButton::String, QgsDataDefinedButton::unitsMmMuDesc() );
mShadowRadiusDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShadowRadius ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doublePosDesc() );
mShadowRadiusUnitsDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShadowRadiusUnits ),
QgsDataDefinedButton::String, QgsDataDefinedButton::unitsMmMuDesc() );
mShadowTranspDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShadowTransparency ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::intTranspDesc() );
mShadowScaleDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShadowScale ),
QgsDataDefinedButton::AnyType, tr( "int [0-2000]" ) );
mShadowColorDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShadowColor ),
QgsDataDefinedButton::String, QgsDataDefinedButton::colorNoAlphaDesc() );
mShadowBlendDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ShadowBlendMode ),
QgsDataDefinedButton::String, QgsDataDefinedButton::blendModesDesc() );
// placement
mCentroidDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::CentroidWhole ),
QgsDataDefinedButton::String,
trString + "[<b>Visible</b>|<b>Whole</b>]" );
mPointQuadOffsetDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::OffsetQuad ),
QgsDataDefinedButton::AnyType,
tr( "int<br>" ) + QLatin1String( "[<b>0</b>=Above Left|<b>1</b>=Above|<b>2</b>=Above Right|<br>"
"<b>3</b>=Left|<b>4</b>=Over|<b>5</b>=Right|<br>"
"<b>6</b>=Below Left|<b>7</b>=Below|<b>8</b>=Below Right]" ) );
mPointPositionOrderDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::PredefinedPositionOrder ),
QgsDataDefinedButton::String,
tr( "Comma separated list of placements in order of priority<br>" )
+ QLatin1String( "[<b>TL</b>=Top left|<b>TSL</b>=Top, slightly left|<b>T</b>=Top middle|<br>"
"<b>TSR</b>=Top, slightly right|<b>TR</b>=Top right|<br>"
"<b>L</b>=Left|<b>R</b>=Right|<br>"
"<b>BL</b>=Bottom left|<b>BSL</b>=Bottom, slightly left|<b>B</b>=Bottom middle|<br>"
"<b>BSR</b>=Bottom, slightly right|<b>BR</b>=Bottom right]" ) );
mPointOffsetDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::OffsetXY ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleXYDesc() );
mPointOffsetUnitsDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::OffsetUnits ),
QgsDataDefinedButton::String, QgsDataDefinedButton::unitsMmMuDesc() );
mLineDistanceDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::LabelDistance ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doublePosDesc() );
mLineDistanceUnitDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::DistanceUnits ),
QgsDataDefinedButton::String, QgsDataDefinedButton::unitsMmMuDesc() );
mPriorityDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::Priority ),
QgsDataDefinedButton::AnyType, tr( "double [0.0-10.0]" ) );
// TODO: is this necessary? maybe just use the data defined-only rotation?
//mPointAngleDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::OffsetRotation ),
// QgsDataDefinedButton::AnyType, QgsDataDefinedButton::double180RotDesc() );
mMaxCharAngleDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::CurvedCharAngleInOut ),
QgsDataDefinedButton::AnyType, tr( "double coord [<b>in,out</b> as 20.0-60.0,20.0-95.0]" ) );
mRepeatDistanceDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::RepeatDistance ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doublePosDesc() );
mRepeatDistanceUnitDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::RepeatDistanceUnit ),
QgsDataDefinedButton::String, QgsDataDefinedButton::unitsMmMuDesc() );
// data defined-only
QString ddPlaceInfo = tr( "In edit mode, layer's relevant labeling map tool is:<br>"
"&nbsp;&nbsp;Defined attribute field -&gt; <i>enabled</i><br>"
"&nbsp;&nbsp;Defined expression -&gt; <i>disabled</i>" );
mCoordXDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::PositionX ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleDesc() );
mCoordXDDBtn->setUsageInfo( ddPlaceInfo );
mCoordYDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::PositionY ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleDesc() );
mCoordYDDBtn->setUsageInfo( ddPlaceInfo );
mCoordAlignmentHDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::Hali ),
QgsDataDefinedButton::String,
trString + "[<b>Left</b>|<b>Center</b>|<b>Right</b>]" );
mCoordAlignmentHDDBtn->setUsageInfo( ddPlaceInfo );
mCoordAlignmentVDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::Vali ),
QgsDataDefinedButton::String,
trString + QLatin1String( "[<b>Bottom</b>|<b>Base</b>|<br>"
"<b>Half</b>|<b>Cap</b>|<b>Top</b>]" ) );
mCoordAlignmentVDDBtn->setUsageInfo( ddPlaceInfo );
mCoordRotationDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::Rotation ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::double180RotDesc() );
mCoordRotationDDBtn->setUsageInfo( ddPlaceInfo );
// rendering
QString ddScaleVisInfo = tr( "Value &lt; 0 represents a scale closer than 1:1, e.g. -10 = 10:1<br>"
"Value of 0 disables the specific limit." );
mScaleBasedVisibilityDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ScaleVisibility ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::boolDesc() );
mScaleBasedVisibilityDDBtn->registerCheckedWidget( mScaleBasedVisibilityChkBx );
mScaleBasedVisibilityMinDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::MinScale ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::intDesc() );
mScaleBasedVisibilityMinDDBtn->setUsageInfo( ddScaleVisInfo );
mScaleBasedVisibilityMaxDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::MaxScale ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::intDesc() );
mScaleBasedVisibilityMaxDDBtn->setUsageInfo( ddScaleVisInfo );
mFontLimitPixelDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::FontLimitPixel ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::boolDesc() );
mFontLimitPixelDDBtn->registerCheckedWidget( mFontLimitPixelChkBox );
mFontMinPixelDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::FontMinPixel ),
QgsDataDefinedButton::AnyType, tr( "int [1-1000]" ) );
mFontMaxPixelDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::FontMaxPixel ),
QgsDataDefinedButton::AnyType, tr( "int [1-10000]" ) );
mShowLabelDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::Show ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::boolDesc() );
mAlwaysShowDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::AlwaysShow ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::boolDesc() );
mIsObstacleDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::IsObstacle ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::boolDesc() );
mObstacleFactorDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ObstacleFactor ),
QgsDataDefinedButton::AnyType, tr( "double [0.0-10.0]" ) );
mZIndexDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ZIndex ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleDesc() );
}
void QgsLabelingGui::changeTextColor( const QColor &color )
{
Q_UNUSED( color )
updatePreview();
}
void QgsLabelingGui::updateFont( const QFont& font )
{
// update background reference font
if ( font != mRefFont )
{
mRefFont = font;
}
// test if font is actually available
// NOTE: QgsFontUtils::fontMatchOnSystem may fail here, just crosscheck family
mFontMissingLabel->setVisible( !QgsFontUtils::fontFamilyMatchOnSystem( mRefFont.family() ) );
mDirectSymbLeftLineEdit->setFont( mRefFont );
mDirectSymbRightLineEdit->setFont( mRefFont );
blockFontChangeSignals( true );
mFontFamilyCmbBx->setCurrentFont( mRefFont );
populateFontStyleComboBox();
int idx = mFontCapitalsComboBox->findData( QVariant(( unsigned int ) mRefFont.capitalization() ) );
mFontCapitalsComboBox->setCurrentIndex( idx == -1 ? 0 : idx );
mFontUnderlineBtn->setChecked( mRefFont.underline() );
mFontStrikethroughBtn->setChecked( mRefFont.strikeOut() );
blockFontChangeSignals( false );
// update font name with font face
// font.setPixelSize( 24 );
updatePreview();
}
void QgsLabelingGui::blockFontChangeSignals( bool blk )
{
mFontFamilyCmbBx->blockSignals( blk );
mFontStyleComboBox->blockSignals( blk );
mFontCapitalsComboBox->blockSignals( blk );
mFontUnderlineBtn->blockSignals( blk );
mFontStrikethroughBtn->blockSignals( blk );
mFontWordSpacingSpinBox->blockSignals( blk );
mFontLetterSpacingSpinBox->blockSignals( blk );
}
void QgsLabelingGui::updatePreview()
{
// In dock mode we don't have a preview we
// just let stuff know we have changed because
// there might be live updates connected.
if ( mLayer && mDockMode )
{
emit widgetChanged();
return;
}
scrollPreview();
lblFontPreview->setFont( mRefFont );
QFont previewFont = lblFontPreview->font();
double fontSize = mFontSizeSpinBox->value();
double previewRatio = mPreviewSize / fontSize;
double bufferSize = 0.0;
QString grpboxtitle;
QString sampleTxt = tr( "Text/Buffer sample" );
if ( mFontSizeUnitWidget->getUnit() == 1 ) // map units
{
// TODO: maybe match current map zoom level instead?
previewFont.setPointSize( mPreviewSize );
mPreviewSizeSlider->setEnabled( true );
grpboxtitle = sampleTxt + tr( " @ %1 pts (using map units)" ).arg( mPreviewSize );
previewFont.setWordSpacing( previewRatio * mFontWordSpacingSpinBox->value() );
previewFont.setLetterSpacing( QFont::AbsoluteSpacing, previewRatio * mFontLetterSpacingSpinBox->value() );
if ( mBufferDrawChkBx->isChecked() )
{
if ( mBufferUnitWidget->unit() == QgsUnitTypes::RenderMapUnits )
{
bufferSize = previewRatio * spinBufferSize->value() / 3.527;
}
else // millimeters
{
grpboxtitle = sampleTxt + tr( " @ %1 pts (using map units, BUFFER IN MILLIMETERS)" ).arg( mPreviewSize );
bufferSize = spinBufferSize->value();
}
}
}
else // in points
{
if ( fontSize > 0 )
previewFont.setPointSize( fontSize );
mPreviewSizeSlider->setEnabled( false );
grpboxtitle = sampleTxt;
if ( mBufferDrawChkBx->isChecked() )
{
if ( mBufferUnitWidget->unit() == QgsUnitTypes::RenderMillimeters )
{
bufferSize = spinBufferSize->value();
}
else // map units
{
grpboxtitle = sampleTxt + tr( " (BUFFER NOT SHOWN, in map units)" );
}
}
}
lblFontPreview->setFont( previewFont );
groupBox_mPreview->setTitle( grpboxtitle );
QColor prevColor = btnTextColor->color();
prevColor.setAlphaF(( 100.0 - ( double )( mFontTranspSpinBox->value() ) ) / 100.0 );
lblFontPreview->setTextColor( prevColor );
bool bufferNoFill = false;
if ( mBufferDrawChkBx->isChecked() && bufferSize != 0.0 )
{
QColor buffColor = btnBufferColor->color();
buffColor.setAlphaF(( 100.0 - ( double )( mBufferTranspSpinBox->value() ) ) / 100.0 );
bufferNoFill = !mBufferTranspFillChbx->isChecked();
lblFontPreview->setBuffer( bufferSize, buffColor, mBufferJoinStyleComboBox->penJoinStyle(), bufferNoFill );
}
else
{
lblFontPreview->setBuffer( 0, Qt::white, Qt::BevelJoin, bufferNoFill );
}
}
void QgsLabelingGui::scrollPreview()
{
scrollArea_mPreview->ensureVisible( 0, 0, 0, 0 );
}
void QgsLabelingGui::setPreviewBackground( const QColor& color )
{
scrollArea_mPreview->widget()->setStyleSheet( QString( "background: rgb(%1, %2, %3);" ).arg( QString::number( color.red() ),
QString::number( color.green() ),
QString::number( color.blue() ) ) );
}
void QgsLabelingGui::syncDefinedCheckboxFrame( QgsDataDefinedButton* ddBtn, QCheckBox* chkBx, QFrame* f )
{
if ( ddBtn->isActive() && !chkBx->isChecked() )
{
chkBx->setChecked( true );
}
f->setEnabled( chkBx->isChecked() );
}
void QgsLabelingGui::updateUi()
{
// enable/disable inline groupbox-like setups (that need to honor data defined setting)
syncDefinedCheckboxFrame( mBufferDrawDDBtn, mBufferDrawChkBx, mBufferFrame );
syncDefinedCheckboxFrame( mShapeDrawDDBtn, mShapeDrawChkBx, mShapeFrame );
syncDefinedCheckboxFrame( mShadowDrawDDBtn, mShadowDrawChkBx, mShadowFrame );
syncDefinedCheckboxFrame( mDirectSymbDDBtn, mDirectSymbChkBx, mDirectSymbFrame );
syncDefinedCheckboxFrame( mFormatNumDDBtn, mFormatNumChkBx, mFormatNumFrame );
syncDefinedCheckboxFrame( mScaleBasedVisibilityDDBtn, mScaleBasedVisibilityChkBx, mScaleBasedVisibilityFrame );
syncDefinedCheckboxFrame( mFontLimitPixelDDBtn, mFontLimitPixelChkBox, mFontLimitPixelFrame );
}
void QgsLabelingGui::changeBufferColor( const QColor &color )
{
Q_UNUSED( color )
updatePreview();
}
void QgsLabelingGui::updatePlacementWidgets()
{
QWidget* curWdgt = stackedPlacement->currentWidget();
bool showLineFrame = false;
bool showCentroidFrame = false;
bool showQuadrantFrame = false;
bool showFixedQuadrantFrame = false;
bool showPlacementPriorityFrame = false;
bool showOffsetTypeFrame = false;
bool showOffsetFrame = false;
bool showDistanceFrame = false;
bool showRotationFrame = false;
bool showMaxCharAngleFrame = false;
bool enableMultiLinesFrame = true;
if (( curWdgt == pagePoint && radAroundPoint->isChecked() )
|| ( curWdgt == pagePolygon && radAroundCentroid->isChecked() ) )
{
showCentroidFrame = ( curWdgt == pagePolygon && radAroundCentroid->isChecked() );
showDistanceFrame = true;
//showRotationFrame = true; // TODO: uncomment when supported
if ( curWdgt == pagePoint )
{
showQuadrantFrame = true;
}
}
else if (( curWdgt == pagePoint && radOverPoint->isChecked() )
|| ( curWdgt == pagePolygon && radOverCentroid->isChecked() ) )
{
showCentroidFrame = ( curWdgt == pagePolygon && radOverCentroid->isChecked() );
showQuadrantFrame = true;
showFixedQuadrantFrame = true;
showOffsetFrame = true;
showRotationFrame = true;
}
else if ( curWdgt == pagePoint && radPredefinedOrder->isChecked() )
{
showDistanceFrame = true;
showPlacementPriorityFrame = true;
showOffsetTypeFrame = true;
}
else if (( curWdgt == pageLine && radLineParallel->isChecked() )
|| ( curWdgt == pagePolygon && radPolygonPerimeter->isChecked() )
|| ( curWdgt == pageLine && radLineCurved->isChecked() ) )
{
showLineFrame = true;
showDistanceFrame = true;
//showRotationFrame = true; // TODO: uncomment when supported
bool offline = chkLineAbove->isChecked() || chkLineBelow->isChecked();
chkLineOrientationDependent->setEnabled( offline );
mPlacementDistanceFrame->setEnabled( offline );
showMaxCharAngleFrame = ( curWdgt == pageLine && radLineCurved->isChecked() );
// TODO: enable mMultiLinesFrame when supported for curved labels
enableMultiLinesFrame = !( curWdgt == pageLine && radLineCurved->isChecked() );
}
mPlacementLineFrame->setVisible( showLineFrame );
mPlacementCentroidFrame->setVisible( showCentroidFrame );
mPlacementQuadrantFrame->setVisible( showQuadrantFrame );
mPlacementFixedQuadrantFrame->setVisible( showFixedQuadrantFrame );
mPlacementCartographicFrame->setVisible( showPlacementPriorityFrame );
mPlacementOffsetFrame->setVisible( showOffsetFrame );
mPlacementDistanceFrame->setVisible( showDistanceFrame );
mPlacementOffsetTypeFrame->setVisible( showOffsetTypeFrame );
mPlacementRotationFrame->setVisible( showRotationFrame );
mPlacementRepeatDistanceFrame->setVisible( curWdgt == pageLine || ( curWdgt == pagePolygon && radPolygonPerimeter->isChecked() ) );
mPlacementMaxCharAngleFrame->setVisible( showMaxCharAngleFrame );
mMultiLinesFrame->setEnabled( enableMultiLinesFrame );
}
void QgsLabelingGui::populateFontCapitalsComboBox()
{
mFontCapitalsComboBox->addItem( tr( "No change" ), QVariant( 0 ) );
mFontCapitalsComboBox->addItem( tr( "All uppercase" ), QVariant( 1 ) );
mFontCapitalsComboBox->addItem( tr( "All lowercase" ), QVariant( 2 ) );
// Small caps doesn't work right with QPainterPath::addText()
// https://bugreports.qt-project.org/browse/QTBUG-13965
// mFontCapitalsComboBox->addItem( tr( "Small caps" ), QVariant( 3 ) );
mFontCapitalsComboBox->addItem( tr( "Capitalize first letter" ), QVariant( 4 ) );
}
void QgsLabelingGui::populateFontStyleComboBox()
{
mFontStyleComboBox->clear();
Q_FOREACH ( const QString &style, mFontDB.styles( mRefFont.family() ) )
{
mFontStyleComboBox->addItem( style );
}
int curIndx = 0;
int stylIndx = mFontStyleComboBox->findText( mFontDB.styleString( mRefFont ) );
if ( stylIndx > -1 )
{
curIndx = stylIndx;
}
mFontStyleComboBox->setCurrentIndex( curIndx );
}
void QgsLabelingGui::on_mPreviewSizeSlider_valueChanged( int i )
{
mPreviewSize = i;
updatePreview();
}
void QgsLabelingGui::on_mFontSizeSpinBox_valueChanged( double d )
{
mRefFont.setPointSizeF( d );
updateFont( mRefFont );
}
void QgsLabelingGui::on_mFontCapitalsComboBox_currentIndexChanged( int index )
{
int capitalsindex = mFontCapitalsComboBox->itemData( index ).toUInt();
mRefFont.setCapitalization(( QFont::Capitalization ) capitalsindex );
updateFont( mRefFont );
}
void QgsLabelingGui::on_mFontFamilyCmbBx_currentFontChanged( const QFont& f )
{
mRefFont.setFamily( f.family() );
updateFont( mRefFont );
}
void QgsLabelingGui::on_mFontStyleComboBox_currentIndexChanged( const QString & text )
{
QgsFontUtils::updateFontViaStyle( mRefFont, text );
updateFont( mRefFont );
}
void QgsLabelingGui::on_mFontUnderlineBtn_toggled( bool ckd )
{
mRefFont.setUnderline( ckd );
updateFont( mRefFont );
}
void QgsLabelingGui::on_mFontStrikethroughBtn_toggled( bool ckd )
{
mRefFont.setStrikeOut( ckd );
updateFont( mRefFont );
}
void QgsLabelingGui::on_mFontWordSpacingSpinBox_valueChanged( double spacing )
{
mRefFont.setWordSpacing( spacing );
updateFont( mRefFont );
}
void QgsLabelingGui::on_mFontLetterSpacingSpinBox_valueChanged( double spacing )
{
mRefFont.setLetterSpacing( QFont::AbsoluteSpacing, spacing );
updateFont( mRefFont );
}
void QgsLabelingGui::on_mFontSizeUnitWidget_changed()
{
int index = mFontSizeUnitWidget->getUnit();
// disable pixel size limiting for labels defined in points
if ( index == 0 )
{
mFontLimitPixelChkBox->setChecked( false );
}
else if ( index == 1 && mMinPixelLimit == 0 )
{
// initial minimum trigger value set, turn on pixel size limiting by default
// for labels defined in map units (ignored after first settings save)
mFontLimitPixelChkBox->setChecked( true );
}
updateFont( mRefFont );
}
void QgsLabelingGui::on_mFontMinPixelSpinBox_valueChanged( int px )
{
// ensure max font pixel size for map unit labels can't be lower than min
mFontMaxPixelSpinBox->setMinimum( px );
mFontMaxPixelSpinBox->update();
}
void QgsLabelingGui::on_mFontMaxPixelSpinBox_valueChanged( int px )
{
// ensure max font pixel size for map unit labels can't be lower than min
if ( px < mFontMinPixelSpinBox->value() )
{
mFontMaxPixelSpinBox->blockSignals( true );
mFontMaxPixelSpinBox->setValue( mFontMinPixelSpinBox->value() );
mFontMaxPixelSpinBox->blockSignals( false );
}
mFontMaxPixelSpinBox->setMinimum( mFontMinPixelSpinBox->value() );
}
void QgsLabelingGui::on_mBufferUnitWidget_changed()
{
updateFont( mRefFont );
}
void QgsLabelingGui::on_mCoordXDDBtn_dataDefinedActivated( bool active )
{
if ( !active ) //no data defined alignment without data defined position
{
enableDataDefinedAlignment( false );
}
else if ( mCoordYDDBtn->isActive() )
{
enableDataDefinedAlignment( true );
}
}
void QgsLabelingGui::on_mCoordYDDBtn_dataDefinedActivated( bool active )
{
if ( !active ) //no data defined alignment without data defined position
{
enableDataDefinedAlignment( false );
}
else if ( mCoordXDDBtn->isActive() )
{
enableDataDefinedAlignment( true );
}
}
void QgsLabelingGui::on_mShapeTypeCmbBx_currentIndexChanged( int index )
{
// shape background
bool isRect = (( QgsPalLayerSettings::ShapeType )index == QgsPalLayerSettings::ShapeRectangle
|| ( QgsPalLayerSettings::ShapeType )index == QgsPalLayerSettings::ShapeSquare );
bool isSVG = (( QgsPalLayerSettings::ShapeType )index == QgsPalLayerSettings::ShapeSVG );
showBackgroundPenStyle( isRect );
showBackgroundRadius( isRect );
mShapeSVGPathFrame->setVisible( isSVG );
// symbology SVG renderer only supports size^2 scaling, so we only use the x size spinbox
mShapeSizeYLabel->setVisible( !isSVG );
mShapeSizeYSpnBx->setVisible( !isSVG );
mShapeSizeYDDBtn->setVisible( !isSVG );
mShapeSizeXLabel->setText( tr( "Size%1" ).arg( !isSVG ? tr( " X" ) : "" ) );
// SVG parameter setting doesn't support color's alpha component yet
mShapeFillColorBtn->setAllowAlpha( !isSVG );
mShapeFillColorBtn->setButtonBackground();
mShapeBorderColorBtn->setAllowAlpha( !isSVG );
mShapeBorderColorBtn->setButtonBackground();
// configure SVG parameter widgets
mShapeSVGParamsBtn->setVisible( isSVG );
if ( isSVG )
{
updateSvgWidgets( mShapeSVGPathLineEdit->text() );
}
else
{
mShapeFillColorLabel->setEnabled( true );
mShapeFillColorBtn->setEnabled( true );
mShapeFillColorDDBtn->setEnabled( true );
mShapeBorderColorLabel->setEnabled( true );
mShapeBorderColorBtn->setEnabled( true );
mShapeBorderColorDDBtn->setEnabled( true );
mShapeBorderWidthLabel->setEnabled( true );
mShapeBorderWidthSpnBx->setEnabled( true );
mShapeBorderWidthDDBtn->setEnabled( true );
}
// TODO: fix overriding SVG symbol's border width units in QgsSvgCache
// currently broken, fall back to symbol units only
mShapeBorderWidthUnitWidget->setVisible( !isSVG );
mShapeSVGUnitsLabel->setVisible( isSVG );
mShapeBorderUnitsDDBtn->setEnabled( !isSVG );
}
void QgsLabelingGui::on_mShapeSVGPathLineEdit_textChanged( const QString& text )
{
updateSvgWidgets( text );
}
void QgsLabelingGui::updateLinePlacementOptions()
{
int numOptionsChecked = ( chkLineAbove->isChecked() ? 1 : 0 ) +
( chkLineBelow->isChecked() ? 1 : 0 ) +
( chkLineOn->isChecked() ? 1 : 0 );
if ( numOptionsChecked == 1 )
{
//prevent unchecking last option
chkLineAbove->setEnabled( !chkLineAbove->isChecked() );
chkLineBelow->setEnabled( !chkLineBelow->isChecked() );
chkLineOn->setEnabled( !chkLineOn->isChecked() );
}
else
{
chkLineAbove->setEnabled( true );
chkLineBelow->setEnabled( true );
chkLineOn->setEnabled( true );
}
}
void QgsLabelingGui::updateSvgWidgets( const QString& svgPath )
{
if ( mShapeSVGPathLineEdit->text() != svgPath )
{
mShapeSVGPathLineEdit->setText( svgPath );
}
QString resolvedPath = QgsSymbolLayerV2Utils::symbolNameToPath( svgPath );
bool validSVG = !resolvedPath.isNull();
// draw red text for path field if invalid (path can't be resolved)
mShapeSVGPathLineEdit->setStyleSheet( QString( !validSVG ? "QLineEdit{ color: rgb(225, 0, 0); }" : "" ) );
mShapeSVGPathLineEdit->setToolTip( !validSVG ? tr( "File not found" ) : resolvedPath );
QColor fill, outline;
double outlineWidth = 0.0;
bool fillParam = false, outlineParam = false, outlineWidthParam = false;
if ( validSVG )
{
QgsSvgCache::instance()->containsParams( resolvedPath, fillParam, fill, outlineParam, outline, outlineWidthParam, outlineWidth );
}
mShapeSVGParamsBtn->setEnabled( validSVG && ( fillParam || outlineParam || outlineWidthParam ) );
mShapeFillColorLabel->setEnabled( validSVG && fillParam );
mShapeFillColorBtn->setEnabled( validSVG && fillParam );
mShapeFillColorDDBtn->setEnabled( validSVG && fillParam );
if ( mLoadSvgParams && validSVG && fillParam )
mShapeFillColorBtn->setColor( fill );
mShapeBorderColorLabel->setEnabled( validSVG && outlineParam );
mShapeBorderColorBtn->setEnabled( validSVG && outlineParam );
mShapeBorderColorDDBtn->setEnabled( validSVG && outlineParam );
if ( mLoadSvgParams && validSVG && outlineParam )
mShapeBorderColorBtn->setColor( outline );
mShapeBorderWidthLabel->setEnabled( validSVG && outlineWidthParam );
mShapeBorderWidthSpnBx->setEnabled( validSVG && outlineWidthParam );
mShapeBorderWidthDDBtn->setEnabled( validSVG && outlineWidthParam );
if ( mLoadSvgParams && validSVG && outlineWidthParam )
mShapeBorderWidthSpnBx->setValue( outlineWidth );
// TODO: fix overriding SVG symbol's border width units in QgsSvgCache
// currently broken, fall back to symbol's
//mShapeBorderWidthUnitWidget->setEnabled( validSVG && outlineWidthParam );
//mShapeBorderUnitsDDBtn->setEnabled( validSVG && outlineWidthParam );
mShapeSVGUnitsLabel->setEnabled( validSVG && outlineWidthParam );
}
void QgsLabelingGui::on_mShapeSVGSelectorBtn_clicked()
{
QgsSvgSelectorDialog svgDlg( this );
svgDlg.setWindowTitle( tr( "Select SVG file" ) );
svgDlg.svgSelector()->setSvgPath( mShapeSVGPathLineEdit->text().trimmed() );
if ( svgDlg.exec() == QDialog::Accepted )
{
QString svgPath = svgDlg.svgSelector()->currentSvgPath();
if ( !svgPath.isEmpty() )
{
mShapeSVGPathLineEdit->setText( svgPath );
}
}
}
void QgsLabelingGui::on_mShapeSVGParamsBtn_clicked()
{
QString svgPath = mShapeSVGPathLineEdit->text();
mLoadSvgParams = true;
updateSvgWidgets( svgPath );
mLoadSvgParams = false;
}
void QgsLabelingGui::on_mShapeRotationCmbBx_currentIndexChanged( int index )
{
mShapeRotationDblSpnBx->setEnabled(( QgsPalLayerSettings::RotationType )index != QgsPalLayerSettings::RotationSync );
mShapeRotationDDBtn->setEnabled(( QgsPalLayerSettings::RotationType )index != QgsPalLayerSettings::RotationSync );
}
void QgsLabelingGui::on_mPreviewTextEdit_textChanged( const QString & text )
{
lblFontPreview->setText( text );
updatePreview();
}
void QgsLabelingGui::on_mPreviewTextBtn_clicked()
{
mPreviewTextEdit->setText( QString( "Lorem Ipsum" ) );
updatePreview();
}
void QgsLabelingGui::on_mPreviewBackgroundBtn_colorChanged( const QColor &color )
{
setPreviewBackground( color );
}
void QgsLabelingGui::on_mDirectSymbLeftToolBtn_clicked()
{
bool gotChar = false;
QChar dirSymb = mCharDlg->selectCharacter( &gotChar, mRefFont, mFontDB.styleString( mRefFont ) );
if ( !gotChar )
return;
if ( !dirSymb.isNull() )
mDirectSymbLeftLineEdit->setText( QString( dirSymb ) );
}
void QgsLabelingGui::on_mDirectSymbRightToolBtn_clicked()
{
bool gotChar = false;
QChar dirSymb = mCharDlg->selectCharacter( &gotChar, mRefFont, mFontDB.styleString( mRefFont ) );
if ( !gotChar )
return;
if ( !dirSymb.isNull() )
mDirectSymbRightLineEdit->setText( QString( dirSymb ) );
}
void QgsLabelingGui::on_mChkNoObstacle_toggled( bool active )
{
mPolygonObstacleTypeFrame->setEnabled( active );
mObstaclePriorityFrame->setEnabled( active );
}
void QgsLabelingGui::showBackgroundRadius( bool show )
{
mShapeRadiusLabel->setVisible( show );
mShapeRadiusXDbSpnBx->setVisible( show );
mShapeRadiusYDbSpnBx->setVisible( show );
mShapeRadiusUnitWidget->setVisible( show );
mShapeRadiusDDBtn->setVisible( show );
mShapeRadiusUnitsDDBtn->setVisible( show );
}
void QgsLabelingGui::showBackgroundPenStyle( bool show )
{
mShapePenStyleLabel->setVisible( show );
mShapePenStyleCmbBx->setVisible( show );
mShapePenStyleDDBtn->setVisible( show );
}
void QgsLabelingGui::enableDataDefinedAlignment( bool enable )
{
mCoordAlignmentFrame->setEnabled( enable );
}