mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
- Initial limit set to 2000 - Results would look better if limited subset was a random sampling of all features
1181 lines
42 KiB
C++
1181 lines
42 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 "qgslabelengineconfigdialog.h"
|
|
#include "qgsexpressionbuilderdialog.h"
|
|
#include "qgsexpression.h"
|
|
#include "qgsmapcanvas.h"
|
|
#include "qgscharacterselectdialog.h"
|
|
|
|
#include <QColorDialog>
|
|
#include <QFontDialog>
|
|
#include <QTextEdit>
|
|
#include <QApplication>
|
|
#include <QMessageBox>
|
|
#include <QSettings>
|
|
|
|
|
|
QgsLabelingGui::QgsLabelingGui( QgsPalLabeling* lbl, QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, QWidget* parent )
|
|
: QWidget( parent ), mLBL( lbl ), mLayer( layer ), mMapCanvas( mapCanvas )
|
|
{
|
|
if ( !layer ) return;
|
|
|
|
setupUi( this );
|
|
mCharDlg = new QgsCharacterSelectorDialog( this );
|
|
|
|
mRefFont = lblFontPreview->font();
|
|
mPreviewSize = 24;
|
|
|
|
connect( btnTextColor, SIGNAL( clicked() ), this, SLOT( changeTextColor() ) );
|
|
connect( btnChangeFont, SIGNAL( clicked() ), this, SLOT( changeTextFont() ) );
|
|
connect( mFontTranspSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( updatePreview() ) );
|
|
connect( chkBuffer, SIGNAL( toggled( bool ) ), this, SLOT( updatePreview() ) );
|
|
connect( btnBufferColor, SIGNAL( clicked() ), this, SLOT( changeBufferColor() ) );
|
|
connect( spinBufferSize, SIGNAL( valueChanged( double ) ), this, SLOT( updatePreview() ) );
|
|
connect( mBufferTranspSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( updatePreview() ) );
|
|
connect( mBufferJoinStyleComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( updatePreview() ) );
|
|
connect( mBufferTranspFillChbx, SIGNAL( toggled( bool ) ), this, SLOT( updatePreview() ) );
|
|
connect( btnEngineSettings, SIGNAL( clicked() ), this, SLOT( showEngineConfigDialog() ) );
|
|
connect( btnExpression, SIGNAL( clicked() ), this, SLOT( showExpressionDialog() ) );
|
|
|
|
// set placement methods page based on geometry type
|
|
switch ( layer->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;
|
|
default:
|
|
Q_ASSERT( 0 && "NOOOO!" );
|
|
}
|
|
|
|
//mTabWidget->setEnabled( chkEnableLabeling->isChecked() );
|
|
chkMergeLines->setEnabled( layer->geometryType() == QGis::Line );
|
|
mDirectSymbGroupBox->setEnabled( layer->geometryType() == QGis::Line );
|
|
label_19->setEnabled( layer->geometryType() != QGis::Point );
|
|
mMinSizeSpinBox->setEnabled( layer->geometryType() != QGis::Point );
|
|
|
|
// load labeling settings from layer
|
|
QgsPalLayerSettings lyr;
|
|
lyr.readFromLayer( layer );
|
|
populateFieldNames();
|
|
populateDataDefinedCombos( lyr );
|
|
populateFontCapitalsComboBox();
|
|
|
|
chkEnableLabeling->setChecked( lyr.enabled );
|
|
mTabWidget->setEnabled( lyr.enabled );
|
|
cboFieldName->setEnabled( lyr.enabled );
|
|
btnExpression->setEnabled( lyr.enabled );
|
|
|
|
//Add the current expression to the bottom of the list.
|
|
if ( lyr.isExpression && !lyr.fieldName.isEmpty() )
|
|
cboFieldName->addItem( lyr.fieldName );
|
|
|
|
// placement
|
|
int distUnitIndex = lyr.distInMapUnits ? 1 : 0;
|
|
mXQuadOffset = lyr.xQuadOffset;
|
|
mYQuadOffset = lyr.yQuadOffset;
|
|
mCentroidRadioWhole->setChecked( lyr.centroidWhole );
|
|
mCentroidFrame->setVisible( false );
|
|
switch ( lyr.placement )
|
|
{
|
|
case QgsPalLayerSettings::AroundPoint:
|
|
radAroundPoint->setChecked( true );
|
|
radAroundCentroid->setChecked( true );
|
|
spinDistPoint->setValue( lyr.dist );
|
|
mPointDistanceUnitComboBox->setCurrentIndex( distUnitIndex );
|
|
mCentroidFrame->setVisible( layer->geometryType() == QGis::Polygon );
|
|
|
|
//spinAngle->setValue( lyr.angle );
|
|
break;
|
|
case QgsPalLayerSettings::OverPoint:
|
|
radOverPoint->setChecked( true );
|
|
radOverCentroid->setChecked( true );
|
|
|
|
mPointOffsetRadioAboveLeft->setChecked( mXQuadOffset == -1 && mYQuadOffset == 1 );
|
|
mPointOffsetRadioAbove->setChecked( mXQuadOffset == 0 && mYQuadOffset == 1 );
|
|
mPointOffsetRadioAboveRight->setChecked( mXQuadOffset == 1 && mYQuadOffset == 1 );
|
|
mPointOffsetRadioLeft->setChecked( mXQuadOffset == -1 && mYQuadOffset == 0 );
|
|
mPointOffsetRadioOver->setChecked( mXQuadOffset == 0 && mYQuadOffset == 0 );
|
|
mPointOffsetRadioRight->setChecked( mXQuadOffset == 1 && mYQuadOffset == 0 );
|
|
mPointOffsetRadioBelowLeft->setChecked( mXQuadOffset == -1 && mYQuadOffset == -1 );
|
|
mPointOffsetRadioBelow->setChecked( mXQuadOffset == 0 && mYQuadOffset == -1 );
|
|
mPointOffsetRadioBelowRight->setChecked( mXQuadOffset == 1 && mYQuadOffset == -1 );
|
|
|
|
mPointOffsetXOffsetSpinBox->setValue( lyr.xOffset );
|
|
mPointOffsetYOffsetSpinBox->setValue( lyr.yOffset );
|
|
mPointOffsetUnitsComboBox->setCurrentIndex( lyr.labelOffsetInMapUnits ? 1 : 0 );
|
|
mPointOffsetAngleSpinBox->setValue( lyr.angleOffset );
|
|
mCentroidFrame->setVisible( layer->geometryType() == QGis::Polygon );
|
|
|
|
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;
|
|
default:
|
|
Q_ASSERT( 0 && "NOOO!" );
|
|
}
|
|
|
|
if ( lyr.placement == QgsPalLayerSettings::Line || lyr.placement == QgsPalLayerSettings::Curved )
|
|
{
|
|
spinDistLine->setValue( lyr.dist );
|
|
mLineDistanceUnitComboBox->setCurrentIndex( distUnitIndex );
|
|
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 );
|
|
}
|
|
|
|
cboFieldName->setCurrentIndex( cboFieldName->findText( lyr.fieldName ) );
|
|
chkEnableLabeling->setChecked( lyr.enabled );
|
|
sliderPriority->setValue( lyr.priority );
|
|
chkNoObstacle->setChecked( !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 );
|
|
mDirectSymbGroupBox->setChecked( lyr.addDirectionSymbol );
|
|
mDirectSymbLeftLineEdit->setText( lyr.leftDirectionSymbol );
|
|
mDirectSymbRightLineEdit->setText( lyr.rightDirectionSymbol );
|
|
mDirectSymbRevChkBx->setChecked( lyr.reverseDirectionSymbol );
|
|
switch ( lyr.placeDirectionSymbol )
|
|
{
|
|
case QgsPalLayerSettings::SymbolLeftRight:
|
|
mDirectSymbRadioBtnLR->setChecked( true );
|
|
break;
|
|
case QgsPalLayerSettings::SymbolAbove:
|
|
mDirectSymbRadioBtnAbove->setChecked( true );
|
|
break;
|
|
case QgsPalLayerSettings::SymbolBelow:
|
|
mDirectSymbRadioBtnBelow->setChecked( true );
|
|
break;
|
|
default:
|
|
mDirectSymbRadioBtnLR->setChecked( true );
|
|
break;
|
|
}
|
|
|
|
// upside-down labels
|
|
switch ( lyr.upsidedownLabels )
|
|
{
|
|
case QgsPalLayerSettings::Upright:
|
|
mUpsidedownRadioOff->setChecked( true );
|
|
break;
|
|
case QgsPalLayerSettings::ShowDefined:
|
|
mUpsidedownRadioDefined->setChecked( true );
|
|
break;
|
|
case QgsPalLayerSettings::ShowAll:
|
|
mUpsidedownRadioAll->setChecked( true );
|
|
break;
|
|
default:
|
|
mUpsidedownRadioOff->setChecked( true );
|
|
break;
|
|
}
|
|
|
|
wrapCharacterEdit->setText( lyr.wrapChar );
|
|
mFontLineHeightSpinBox->setValue( lyr.multilineHeight );
|
|
mFontMultiLineComboBox->setCurrentIndex(( unsigned int ) lyr.multilineAlign );
|
|
chkPreserveRotation->setChecked( lyr.preserveRotation );
|
|
|
|
mPreviewBackgroundBtn->setColor( lyr.previewBkgrdColor );
|
|
setPreviewBackground( lyr.previewBkgrdColor );
|
|
|
|
bool scaleBased = ( lyr.scaleMin != 0 && lyr.scaleMax != 0 );
|
|
chkScaleBasedVisibility->setChecked( scaleBased );
|
|
if ( scaleBased )
|
|
{
|
|
spinScaleMin->setValue( lyr.scaleMin );
|
|
spinScaleMax->setValue( lyr.scaleMax );
|
|
}
|
|
|
|
bool buffer = ( lyr.bufferSize != 0 );
|
|
chkBuffer->setChecked( buffer );
|
|
if ( buffer )
|
|
{
|
|
spinBufferSize->setValue( lyr.bufferSize );
|
|
if ( lyr.bufferSizeInMapUnits )
|
|
{
|
|
mBufferUnitComboBox->setCurrentIndex( 1 );
|
|
}
|
|
else
|
|
{
|
|
mBufferUnitComboBox->setCurrentIndex( 0 );
|
|
}
|
|
btnBufferColor->setColor( lyr.bufferColor );
|
|
mBufferTranspSpinBox->setValue( lyr.bufferTransp );
|
|
mBufferJoinStyleComboBox->setPenJoinStyle( lyr.bufferJoinStyle );
|
|
mBufferTranspFillChbx->setChecked( !lyr.bufferNoFill );
|
|
}
|
|
|
|
bool formattedNumbers = lyr.formatNumbers;
|
|
bool plusSign = lyr.plusSign;
|
|
|
|
chkFormattedNumbers->setChecked( formattedNumbers );
|
|
if ( formattedNumbers )
|
|
{
|
|
spinDecimals->setValue( lyr.decimals );
|
|
}
|
|
if ( plusSign )
|
|
{
|
|
chkPlusSign->setChecked( 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
|
|
mFontLimitPixelGroupBox->setChecked( lyr.fontLimitPixelSize );
|
|
mMinPixelLimit = lyr.fontMinPixelSize; // ignored after first settings save
|
|
mFontMinPixelSpinBox->setValue( lyr.fontMinPixelSize == 0 ? 3 : lyr.fontMinPixelSize );
|
|
mFontMaxPixelSpinBox->setValue( lyr.fontMaxPixelSize );
|
|
if ( lyr.fontSizeInMapUnits )
|
|
{
|
|
mFontSizeUnitComboBox->setCurrentIndex( 1 );
|
|
}
|
|
else
|
|
{
|
|
mFontSizeUnitComboBox->setCurrentIndex( 0 );
|
|
}
|
|
|
|
mRefFont = lyr.textFont;
|
|
mFontSizeSpinBox->setValue( lyr.textFont.pointSizeF() );
|
|
btnTextColor->setColor( lyr.textColor );
|
|
mFontTranspSpinBox->setValue( lyr.textTransp );
|
|
|
|
mFontWordSpacingSpinBox->setValue( lyr.textFont.wordSpacing() );
|
|
mFontLetterSpacingSpinBox->setValue( lyr.textFont.letterSpacing() );
|
|
|
|
updateFontViaStyle( lyr.textNamedStyle );
|
|
updateFont( mRefFont );
|
|
|
|
updateUi();
|
|
|
|
updateOptions();
|
|
|
|
connect( chkBuffer, SIGNAL( toggled( bool ) ), this, SLOT( updateUi() ) );
|
|
connect( chkScaleBasedVisibility, SIGNAL( toggled( bool ) ), this, SLOT( updateUi() ) );
|
|
connect( chkFormattedNumbers, SIGNAL( toggled( bool ) ), this, SLOT( updateUi() ) );
|
|
connect( chkLineAbove, SIGNAL( toggled( bool ) ), this, SLOT( updateUi() ) );
|
|
connect( chkLineBelow, SIGNAL( toggled( bool ) ), this, SLOT( updateUi() ) );
|
|
|
|
// setup connection to changes in the placement
|
|
QRadioButton* placementRadios[] =
|
|
{
|
|
radAroundPoint, radOverPoint, // point
|
|
radLineParallel, radLineCurved, radLineHorizontal, // line
|
|
radAroundCentroid, radPolygonHorizontal, radPolygonFree, radPolygonPerimeter // polygon
|
|
};
|
|
for ( unsigned int i = 0; i < sizeof( placementRadios ) / sizeof( QRadioButton* ); i++ )
|
|
{
|
|
connect( placementRadios[i], SIGNAL( toggled( bool ) ), this, SLOT( updateOptions() ) );
|
|
}
|
|
|
|
// setup connections for label quadrant offsets
|
|
QRadioButton* quadrantRadios[] =
|
|
{
|
|
mPointOffsetRadioAboveLeft, mPointOffsetRadioAbove, mPointOffsetRadioAboveRight,
|
|
mPointOffsetRadioLeft, mPointOffsetRadioOver, mPointOffsetRadioRight,
|
|
mPointOffsetRadioBelowLeft, mPointOffsetRadioBelow, mPointOffsetRadioBelowRight
|
|
};
|
|
for ( unsigned int i = 0; i < sizeof( quadrantRadios ) / sizeof( QRadioButton* ); i++ )
|
|
{
|
|
connect( quadrantRadios[i], SIGNAL( toggled( bool ) ), this, SLOT( updateQuadrant() ) );
|
|
}
|
|
|
|
// Global settings group for groupboxes' saved/retored collapsed state
|
|
// maintains state across different dialogs
|
|
foreach ( QgsCollapsibleGroupBox *grpbox, findChildren<QgsCollapsibleGroupBox*>() )
|
|
{
|
|
grpbox->setSettingGroup( QString( "mAdvLabelingDlg" ) );
|
|
}
|
|
|
|
connect( groupBox_mPreview,
|
|
SIGNAL( collapsedStateChanged( QgsCollapsibleGroupBox* ) ),
|
|
this,
|
|
SLOT( collapseSample( QgsCollapsibleGroupBox* ) ) );
|
|
}
|
|
|
|
QgsLabelingGui::~QgsLabelingGui()
|
|
{
|
|
}
|
|
|
|
void QgsLabelingGui::collapseSample( QgsCollapsibleGroupBox* grpbx )
|
|
{
|
|
if ( grpbx->isCollapsed() )
|
|
{
|
|
QList<int> splitSizes = mFontPreviewSplitter->sizes();
|
|
if ( splitSizes[0] > grpbx->height() )
|
|
{
|
|
int delta = splitSizes[0] - grpbx->height();
|
|
splitSizes[0] -= delta;
|
|
splitSizes[1] += delta;
|
|
mFontPreviewSplitter->setSizes( splitSizes );
|
|
}
|
|
}
|
|
}
|
|
|
|
void QgsLabelingGui::apply()
|
|
{
|
|
QgsPalLayerSettings settings = layerSettings();
|
|
settings.writeToLayer( mLayer );
|
|
// trigger refresh
|
|
if ( mMapCanvas )
|
|
{
|
|
mMapCanvas->refresh();
|
|
}
|
|
}
|
|
|
|
QgsPalLayerSettings QgsLabelingGui::layerSettings()
|
|
{
|
|
QgsPalLayerSettings lyr;
|
|
lyr.fieldName = cboFieldName->currentText();
|
|
// Check if we are an expression. Also treats expressions with just a column name as non expressions,
|
|
// this saves time later so we don't have to parse the expression tree.
|
|
lyr.isExpression = mLayer->fieldNameIndex( lyr.fieldName ) == -1 && !lyr.fieldName.isEmpty();
|
|
|
|
lyr.dist = 0;
|
|
lyr.placementFlags = 0;
|
|
|
|
lyr.centroidWhole = mCentroidRadioWhole->isChecked();
|
|
if (( stackedPlacement->currentWidget() == pagePoint && radAroundPoint->isChecked() )
|
|
|| ( stackedPlacement->currentWidget() == pagePolygon && radAroundCentroid->isChecked() ) )
|
|
{
|
|
lyr.placement = QgsPalLayerSettings::AroundPoint;
|
|
lyr.dist = spinDistPoint->value();
|
|
lyr.distInMapUnits = ( mPointDistanceUnitComboBox->currentIndex() == 1 );
|
|
}
|
|
else if (( stackedPlacement->currentWidget() == pagePoint && radOverPoint->isChecked() )
|
|
|| ( stackedPlacement->currentWidget() == pagePolygon && radOverCentroid->isChecked() ) )
|
|
{
|
|
lyr.placement = QgsPalLayerSettings::OverPoint;
|
|
|
|
lyr.xQuadOffset = mXQuadOffset;
|
|
lyr.yQuadOffset = mYQuadOffset;
|
|
lyr.xOffset = mPointOffsetXOffsetSpinBox->value();
|
|
lyr.yOffset = mPointOffsetYOffsetSpinBox->value();
|
|
lyr.labelOffsetInMapUnits = ( mPointOffsetUnitsComboBox->currentIndex() == 1 );
|
|
lyr.angleOffset = mPointOffsetAngleSpinBox->value();
|
|
}
|
|
else if (( stackedPlacement->currentWidget() == pageLine && radLineParallel->isChecked() )
|
|
|| ( stackedPlacement->currentWidget() == pagePolygon && radPolygonPerimeter->isChecked() )
|
|
|| ( stackedPlacement->currentWidget() == pageLine && radLineCurved->isChecked() ) )
|
|
{
|
|
bool curved = ( stackedPlacement->currentWidget() == pageLine && radLineCurved->isChecked() );
|
|
lyr.placement = ( curved ? QgsPalLayerSettings::Curved : QgsPalLayerSettings::Line );
|
|
lyr.dist = spinDistLine->value();
|
|
lyr.distInMapUnits = ( mLineDistanceUnitComboBox->currentIndex() == 1 );
|
|
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;
|
|
}
|
|
else if (( stackedPlacement->currentWidget() == pageLine && radLineHorizontal->isChecked() )
|
|
|| ( stackedPlacement->currentWidget() == pagePolygon && radPolygonHorizontal->isChecked() ) )
|
|
{
|
|
lyr.placement = QgsPalLayerSettings::Horizontal;
|
|
}
|
|
else if ( radPolygonFree->isChecked() )
|
|
{
|
|
lyr.placement = QgsPalLayerSettings::Free;
|
|
}
|
|
else
|
|
Q_ASSERT( 0 && "NOOO!" );
|
|
|
|
|
|
lyr.textColor = btnTextColor->color();
|
|
lyr.textFont = mRefFont;
|
|
lyr.textNamedStyle = mFontStyleComboBox->currentText();
|
|
lyr.textTransp = mFontTranspSpinBox->value();
|
|
lyr.previewBkgrdColor = mPreviewBackgroundBtn->color();
|
|
lyr.enabled = chkEnableLabeling->isChecked();
|
|
lyr.priority = sliderPriority->value();
|
|
lyr.obstacle = !chkNoObstacle->isChecked();
|
|
lyr.labelPerPart = chkLabelPerFeaturePart->isChecked();
|
|
lyr.displayAll = mPalShowAllLabelsForLayerChkBx->isChecked();
|
|
lyr.mergeLines = chkMergeLines->isChecked();
|
|
if ( chkScaleBasedVisibility->isChecked() )
|
|
{
|
|
lyr.scaleMin = spinScaleMin->value();
|
|
lyr.scaleMax = spinScaleMax->value();
|
|
}
|
|
else
|
|
{
|
|
lyr.scaleMin = lyr.scaleMax = 0;
|
|
}
|
|
if ( chkBuffer->isChecked() )
|
|
{
|
|
lyr.bufferSize = spinBufferSize->value();
|
|
lyr.bufferColor = btnBufferColor->color();
|
|
lyr.bufferTransp = mBufferTranspSpinBox->value();
|
|
lyr.bufferSizeInMapUnits = ( mBufferUnitComboBox->currentIndex() == 1 );
|
|
lyr.bufferJoinStyle = mBufferJoinStyleComboBox->penJoinStyle();
|
|
lyr.bufferNoFill = !mBufferTranspFillChbx->isChecked();
|
|
}
|
|
else
|
|
{
|
|
lyr.bufferSize = 0;
|
|
}
|
|
if ( chkFormattedNumbers->isChecked() )
|
|
{
|
|
lyr.formatNumbers = true;
|
|
lyr.decimals = spinDecimals->value();
|
|
lyr.plusSign = chkPlusSign->isChecked();
|
|
}
|
|
else
|
|
{
|
|
lyr.formatNumbers = false;
|
|
lyr.decimals = spinDecimals->value();
|
|
lyr.plusSign = true;
|
|
}
|
|
|
|
lyr.addDirectionSymbol = mDirectSymbGroupBox->isChecked();
|
|
lyr.leftDirectionSymbol = mDirectSymbLeftLineEdit->text();
|
|
lyr.rightDirectionSymbol = mDirectSymbRightLineEdit->text();
|
|
lyr.reverseDirectionSymbol = mDirectSymbRevChkBx->isChecked();
|
|
if ( mDirectSymbRadioBtnLR->isChecked() )
|
|
{
|
|
lyr.placeDirectionSymbol = QgsPalLayerSettings::SymbolLeftRight;
|
|
}
|
|
else if ( mDirectSymbRadioBtnAbove->isChecked() )
|
|
{
|
|
lyr.placeDirectionSymbol = QgsPalLayerSettings::SymbolAbove;
|
|
}
|
|
else if ( mDirectSymbRadioBtnBelow->isChecked() )
|
|
{
|
|
lyr.placeDirectionSymbol = QgsPalLayerSettings::SymbolBelow;
|
|
}
|
|
|
|
if ( mUpsidedownRadioOff->isChecked() )
|
|
{
|
|
lyr.upsidedownLabels = QgsPalLayerSettings::Upright;
|
|
}
|
|
else if ( mUpsidedownRadioDefined->isChecked() )
|
|
{
|
|
lyr.upsidedownLabels = QgsPalLayerSettings::ShowDefined;
|
|
}
|
|
else if ( mUpsidedownRadioAll->isChecked() )
|
|
{
|
|
lyr.upsidedownLabels = QgsPalLayerSettings::ShowAll;
|
|
}
|
|
lyr.minFeatureSize = mMinSizeSpinBox->value();
|
|
lyr.limitNumLabels = mLimitLabelChkBox->isChecked();
|
|
lyr.maxNumLabels = mLimitLabelSpinBox->value();
|
|
lyr.fontSizeInMapUnits = ( mFontSizeUnitComboBox->currentIndex() == 1 );
|
|
lyr.fontLimitPixelSize = mFontLimitPixelGroupBox->isChecked();
|
|
lyr.fontMinPixelSize = mFontMinPixelSpinBox->value();
|
|
lyr.fontMaxPixelSize = mFontMaxPixelSpinBox->value();
|
|
lyr.wrapChar = wrapCharacterEdit->text();
|
|
lyr.multilineHeight = mFontLineHeightSpinBox->value();
|
|
lyr.multilineAlign = ( QgsPalLayerSettings::MultiLineAlign ) mFontMultiLineComboBox->currentIndex();
|
|
if ( chkPreserveRotation->isChecked() )
|
|
{
|
|
lyr.preserveRotation = true;
|
|
}
|
|
else
|
|
{
|
|
lyr.preserveRotation = false;
|
|
}
|
|
|
|
//data defined labeling
|
|
setDataDefinedProperty( mSizeAttributeComboBox, QgsPalLayerSettings::Size, lyr );
|
|
setDataDefinedProperty( mColorAttributeComboBox, QgsPalLayerSettings::Color, lyr );
|
|
setDataDefinedProperty( mBoldAttributeComboBox, QgsPalLayerSettings::Bold, lyr );
|
|
setDataDefinedProperty( mItalicAttributeComboBox, QgsPalLayerSettings::Italic, lyr );
|
|
setDataDefinedProperty( mUnderlineAttributeComboBox, QgsPalLayerSettings::Underline, lyr );
|
|
setDataDefinedProperty( mStrikeoutAttributeComboBox, QgsPalLayerSettings::Strikeout, lyr );
|
|
setDataDefinedProperty( mFontFamilyAttributeComboBox, QgsPalLayerSettings::Family, lyr );
|
|
setDataDefinedProperty( mBufferSizeAttributeComboBox, QgsPalLayerSettings:: BufferSize, lyr );
|
|
setDataDefinedProperty( mBufferColorAttributeComboBox, QgsPalLayerSettings::BufferColor, lyr );
|
|
setDataDefinedProperty( mXCoordinateComboBox, QgsPalLayerSettings::PositionX, lyr );
|
|
setDataDefinedProperty( mYCoordinateComboBox, QgsPalLayerSettings::PositionY, lyr );
|
|
setDataDefinedProperty( mHorizontalAlignmentComboBox, QgsPalLayerSettings::Hali, lyr );
|
|
setDataDefinedProperty( mVerticalAlignmentComboBox, QgsPalLayerSettings::Vali, lyr );
|
|
setDataDefinedProperty( mLabelDistanceComboBox, QgsPalLayerSettings::LabelDistance, lyr );
|
|
setDataDefinedProperty( mRotationComboBox, QgsPalLayerSettings::Rotation, lyr );
|
|
setDataDefinedProperty( mShowLabelAttributeComboBox, QgsPalLayerSettings::Show, lyr );
|
|
setDataDefinedProperty( mMinScaleAttributeComboBox, QgsPalLayerSettings::MinScale, lyr );
|
|
setDataDefinedProperty( mMaxScaleAttributeComboBox, QgsPalLayerSettings::MaxScale, lyr );
|
|
setDataDefinedProperty( mTranspAttributeComboBox, QgsPalLayerSettings::FontTransp, lyr );
|
|
setDataDefinedProperty( mBufferTranspAttributeComboBox, QgsPalLayerSettings::BufferTransp, lyr );
|
|
setDataDefinedProperty( mAlwaysShowAttributeComboBox, QgsPalLayerSettings::AlwaysShow, lyr );
|
|
|
|
return lyr;
|
|
}
|
|
|
|
void QgsLabelingGui::populateFieldNames()
|
|
{
|
|
const QgsFieldMap& fields = mLayer->pendingFields();
|
|
QgsFieldMap::const_iterator it = fields.constBegin();
|
|
for ( ; it != fields.constEnd(); it++ )
|
|
{
|
|
cboFieldName->addItem( it->name() );
|
|
}
|
|
}
|
|
|
|
void QgsLabelingGui::setDataDefinedProperty( const QComboBox* c, QgsPalLayerSettings::DataDefinedProperties p, QgsPalLayerSettings& lyr )
|
|
{
|
|
if ( !c )
|
|
{
|
|
return;
|
|
}
|
|
|
|
QVariant propertyField = c->itemData( c->currentIndex() );
|
|
if ( propertyField.isValid() )
|
|
{
|
|
lyr.setDataDefinedProperty( p, propertyField.toInt() );
|
|
}
|
|
}
|
|
|
|
void QgsLabelingGui::setCurrentComboValue( QComboBox* c, const QgsPalLayerSettings& s, QgsPalLayerSettings::DataDefinedProperties p )
|
|
{
|
|
if ( !c )
|
|
{
|
|
return;
|
|
}
|
|
|
|
QMap< QgsPalLayerSettings::DataDefinedProperties, int >::const_iterator it = s.dataDefinedProperties.find( p );
|
|
if ( it == s.dataDefinedProperties.constEnd() )
|
|
{
|
|
c->setCurrentIndex( 0 );
|
|
}
|
|
else
|
|
{
|
|
c->setCurrentIndex( c->findData( it.value() ) );
|
|
}
|
|
}
|
|
|
|
void QgsLabelingGui::populateDataDefinedCombos( QgsPalLayerSettings& s )
|
|
{
|
|
QList<QComboBox*> comboList;
|
|
comboList << mSizeAttributeComboBox;
|
|
comboList << mColorAttributeComboBox;
|
|
comboList << mBoldAttributeComboBox;
|
|
comboList << mItalicAttributeComboBox;
|
|
comboList << mUnderlineAttributeComboBox;
|
|
comboList << mStrikeoutAttributeComboBox;
|
|
comboList << mFontFamilyAttributeComboBox;
|
|
comboList << mBufferSizeAttributeComboBox;
|
|
comboList << mBufferColorAttributeComboBox;
|
|
comboList << mXCoordinateComboBox;
|
|
comboList << mYCoordinateComboBox;
|
|
comboList << mHorizontalAlignmentComboBox;
|
|
comboList << mVerticalAlignmentComboBox;
|
|
comboList << mLabelDistanceComboBox;
|
|
comboList << mRotationComboBox;
|
|
comboList << mShowLabelAttributeComboBox;
|
|
comboList << mMinScaleAttributeComboBox;
|
|
comboList << mMaxScaleAttributeComboBox;
|
|
comboList << mTranspAttributeComboBox;
|
|
comboList << mBufferTranspAttributeComboBox;
|
|
comboList << mAlwaysShowAttributeComboBox;
|
|
|
|
QList<QComboBox*>::iterator comboIt = comboList.begin();
|
|
for ( ; comboIt != comboList.end(); ++comboIt )
|
|
{
|
|
( *comboIt )->addItem( "", QVariant() );
|
|
}
|
|
|
|
// TODO: don't add field that aren't of appropriate type for the data defined property
|
|
const QgsFieldMap& fields = mLayer->dataProvider()->fields();
|
|
for ( QgsFieldMap::const_iterator it = fields.constBegin(); it != fields.constEnd(); it++ )
|
|
{
|
|
for ( comboIt = comboList.begin(); comboIt != comboList.end(); ++comboIt )
|
|
{
|
|
( *comboIt )->addItem( it.value().name(), it.key() );
|
|
}
|
|
|
|
}
|
|
|
|
//set current combo boxes to already existing indices
|
|
setCurrentComboValue( mSizeAttributeComboBox, s, QgsPalLayerSettings::Size );
|
|
setCurrentComboValue( mColorAttributeComboBox, s, QgsPalLayerSettings::Color );
|
|
setCurrentComboValue( mBoldAttributeComboBox, s, QgsPalLayerSettings::Bold );
|
|
setCurrentComboValue( mItalicAttributeComboBox, s, QgsPalLayerSettings::Italic );
|
|
setCurrentComboValue( mUnderlineAttributeComboBox, s, QgsPalLayerSettings::Underline );
|
|
setCurrentComboValue( mStrikeoutAttributeComboBox, s, QgsPalLayerSettings::Strikeout );
|
|
setCurrentComboValue( mFontFamilyAttributeComboBox, s, QgsPalLayerSettings::Family );
|
|
setCurrentComboValue( mBufferSizeAttributeComboBox, s , QgsPalLayerSettings::BufferSize );
|
|
setCurrentComboValue( mBufferColorAttributeComboBox, s, QgsPalLayerSettings::BufferColor );
|
|
setCurrentComboValue( mXCoordinateComboBox, s, QgsPalLayerSettings::PositionX );
|
|
setCurrentComboValue( mYCoordinateComboBox, s, QgsPalLayerSettings::PositionY );
|
|
setCurrentComboValue( mHorizontalAlignmentComboBox, s, QgsPalLayerSettings::Hali );
|
|
setCurrentComboValue( mVerticalAlignmentComboBox, s, QgsPalLayerSettings::Vali );
|
|
setCurrentComboValue( mLabelDistanceComboBox, s, QgsPalLayerSettings::LabelDistance );
|
|
setCurrentComboValue( mRotationComboBox, s, QgsPalLayerSettings::Rotation );
|
|
setCurrentComboValue( mShowLabelAttributeComboBox, s, QgsPalLayerSettings::Show );
|
|
setCurrentComboValue( mMinScaleAttributeComboBox, s, QgsPalLayerSettings::MinScale );
|
|
setCurrentComboValue( mMaxScaleAttributeComboBox, s, QgsPalLayerSettings::MaxScale );
|
|
setCurrentComboValue( mTranspAttributeComboBox, s, QgsPalLayerSettings::FontTransp );
|
|
setCurrentComboValue( mBufferTranspAttributeComboBox, s, QgsPalLayerSettings::BufferTransp );
|
|
setCurrentComboValue( mAlwaysShowAttributeComboBox, s, QgsPalLayerSettings::AlwaysShow );
|
|
}
|
|
|
|
void QgsLabelingGui::changeTextColor()
|
|
{
|
|
QColor color = QColorDialog::getColor( btnTextColor->color(), this );
|
|
if ( !color.isValid() )
|
|
return;
|
|
|
|
btnTextColor->setColor( color );
|
|
updatePreview();
|
|
}
|
|
|
|
void QgsLabelingGui::changeTextFont()
|
|
{
|
|
// store properties of QFont that might be stripped by font dialog
|
|
QFont::Capitalization captials = mRefFont.capitalization();
|
|
double wordspacing = mRefFont.wordSpacing();
|
|
double letterspacing = mRefFont.letterSpacing();
|
|
|
|
bool ok;
|
|
#if defined(Q_WS_MAC) && QT_VERSION >= 0x040500 && defined(QT_MAC_USE_COCOA)
|
|
// Native Mac dialog works only for Qt Carbon
|
|
QFont font = QFontDialog::getFont( &ok, mRefFont, 0, QString(), QFontDialog::DontUseNativeDialog );
|
|
#else
|
|
QFont font = QFontDialog::getFont( &ok, mRefFont );
|
|
#endif
|
|
if ( ok )
|
|
{
|
|
if ( mFontSizeUnitComboBox->currentIndex() == 1 )
|
|
{
|
|
// don't override map units size with selected size from font dialog
|
|
font.setPointSizeF( mFontSizeSpinBox->value() );
|
|
}
|
|
else
|
|
{
|
|
mFontSizeSpinBox->setValue( font.pointSizeF() );
|
|
}
|
|
|
|
// reassign possibly stripped QFont properties
|
|
font.setCapitalization( captials );
|
|
font.setWordSpacing( wordspacing );
|
|
font.setLetterSpacing( QFont::AbsoluteSpacing, letterspacing );
|
|
|
|
updateFont( font );
|
|
}
|
|
}
|
|
|
|
void QgsLabelingGui::updateFontViaStyle( const QString & fontstyle )
|
|
{
|
|
QFont styledfont;
|
|
bool foundmatch = false;
|
|
int fontSize = 12; // QFontDatabase::font() needs an integer for size
|
|
if ( !fontstyle.isEmpty() )
|
|
{
|
|
styledfont = mFontDB.font( mRefFont.family(), fontstyle, fontSize );
|
|
styledfont.setPointSizeF( mRefFont.pointSizeF() );
|
|
if ( QApplication::font().toString() != styledfont.toString() )
|
|
{
|
|
foundmatch = true;
|
|
}
|
|
}
|
|
if ( !foundmatch )
|
|
{
|
|
foreach ( const QString &style, mFontDB.styles( mRefFont.family() ) )
|
|
{
|
|
styledfont = mFontDB.font( mRefFont.family(), style, fontSize );
|
|
styledfont.setPointSizeF( mRefFont.pointSizeF() );
|
|
styledfont = styledfont.resolve( mRefFont );
|
|
if ( mRefFont.toString() == styledfont.toString() )
|
|
{
|
|
foundmatch = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if ( foundmatch )
|
|
{
|
|
// styledfont.setPointSizeF( mRefFont.pointSizeF() );
|
|
styledfont.setCapitalization( mRefFont.capitalization() );
|
|
styledfont.setUnderline( mRefFont.underline() );
|
|
styledfont.setStrikeOut( mRefFont.strikeOut() );
|
|
styledfont.setWordSpacing( mRefFont.wordSpacing() );
|
|
styledfont.setLetterSpacing( QFont::AbsoluteSpacing, mRefFont.letterSpacing() );
|
|
mRefFont = styledfont;
|
|
}
|
|
// if no match, style combobox will be left blank, which should not affect engine labeling
|
|
}
|
|
|
|
void QgsLabelingGui::updateFont( QFont font )
|
|
{
|
|
// update background reference font
|
|
if ( font != mRefFont )
|
|
{
|
|
mRefFont = font;
|
|
}
|
|
|
|
// test if font is actually available
|
|
QString missingtxt = QString( "" );
|
|
bool missing = false;
|
|
if ( QApplication::font().toString() != mRefFont.toString() )
|
|
{
|
|
QFont testfont = mFontDB.font( mRefFont.family(), mFontDB.styleString( mRefFont ), 12 );
|
|
if ( QApplication::font().toString() == testfont.toString() )
|
|
{
|
|
missing = true;
|
|
}
|
|
}
|
|
if ( missing )
|
|
{
|
|
missingtxt = tr( " (not found!)" );
|
|
lblFontName->setStyleSheet( "color: #990000;" );
|
|
}
|
|
else
|
|
{
|
|
lblFontName->setStyleSheet( "color: #000000;" );
|
|
}
|
|
|
|
lblFontName->setText( QString( "%1%2" ).arg( mRefFont.family() ).arg( missingtxt ) );
|
|
mDirectSymbLeftLineEdit->setFont( mRefFont );
|
|
mDirectSymbRightLineEdit->setFont( mRefFont );
|
|
|
|
blockFontChangeSignals( true );
|
|
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 );
|
|
// lblFontName->setFont( QFont( font ) );
|
|
|
|
updatePreview();
|
|
}
|
|
|
|
void QgsLabelingGui::blockFontChangeSignals( bool blk )
|
|
{
|
|
mFontStyleComboBox->blockSignals( blk );
|
|
mFontCapitalsComboBox->blockSignals( blk );
|
|
mFontUnderlineBtn->blockSignals( blk );
|
|
mFontStrikethroughBtn->blockSignals( blk );
|
|
mFontWordSpacingSpinBox->blockSignals( blk );
|
|
mFontLetterSpacingSpinBox->blockSignals( blk );
|
|
}
|
|
|
|
void QgsLabelingGui::updatePreview()
|
|
{
|
|
scrollPreview();
|
|
lblFontPreview->setFont( mRefFont );
|
|
QFont previewFont = lblFontPreview->font();
|
|
double fontSize = mFontSizeSpinBox->value();
|
|
double previewRatio = mPreviewSize / fontSize;
|
|
double bufferSize = 0.0;
|
|
QString grpboxtitle;
|
|
|
|
if ( mFontSizeUnitComboBox->currentIndex() == 1 ) // map units
|
|
{
|
|
// TODO: maybe match current map zoom level instead?
|
|
previewFont.setPointSize( mPreviewSize );
|
|
mPreviewSizeSlider->setEnabled( true );
|
|
grpboxtitle = tr( "Sample @ %1 pts (using map units)" ).arg( mPreviewSize );
|
|
|
|
previewFont.setWordSpacing( previewRatio * mFontWordSpacingSpinBox->value() );
|
|
previewFont.setLetterSpacing( QFont::AbsoluteSpacing, previewRatio * mFontLetterSpacingSpinBox->value() );
|
|
|
|
if ( chkBuffer->isChecked() )
|
|
{
|
|
if ( mBufferUnitComboBox->currentIndex() == 1 ) // map units
|
|
{
|
|
bufferSize = previewRatio * spinBufferSize->value() / 3.527;
|
|
}
|
|
else // millimeters
|
|
{
|
|
grpboxtitle = tr( "Sample @ %1 pts (using map units, BUFFER IN MILLIMETERS)" ).arg( mPreviewSize );
|
|
bufferSize = spinBufferSize->value();
|
|
}
|
|
}
|
|
}
|
|
else // in points
|
|
{
|
|
previewFont.setPointSize( fontSize );
|
|
mPreviewSizeSlider->setEnabled( false );
|
|
grpboxtitle = tr( "Sample" );
|
|
|
|
if ( chkBuffer->isChecked() )
|
|
{
|
|
if ( mBufferUnitComboBox->currentIndex() == 0 ) // millimeters
|
|
{
|
|
bufferSize = spinBufferSize->value();
|
|
}
|
|
else // map units
|
|
{
|
|
grpboxtitle = tr( "Sample (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 ( chkBuffer->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( 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::showEngineConfigDialog()
|
|
{
|
|
QgsLabelEngineConfigDialog dlg( mLBL, this );
|
|
dlg.exec();
|
|
}
|
|
|
|
void QgsLabelingGui::showExpressionDialog()
|
|
{
|
|
QgsExpressionBuilderDialog dlg( mLayer, cboFieldName->currentText() , this );
|
|
dlg.setWindowTitle( tr( "Expression based label" ) );
|
|
if ( dlg.exec() == QDialog::Accepted )
|
|
{
|
|
QString expression = dlg.expressionText();
|
|
//Only add the expression if the user has entered some text.
|
|
if ( !expression.isEmpty() )
|
|
{
|
|
cboFieldName->addItem( expression );
|
|
cboFieldName->setCurrentIndex( cboFieldName->count() - 1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
void QgsLabelingGui::updateUi()
|
|
{
|
|
// enable/disable scale-based, buffer, decimals
|
|
bool buf = chkBuffer->isChecked();
|
|
spinBufferSize->setEnabled( buf );
|
|
btnBufferColor->setEnabled( buf );
|
|
mBufferUnitComboBox->setEnabled( buf );
|
|
mBufferTranspSlider->setEnabled( buf );
|
|
mBufferTranspSpinBox->setEnabled( buf );
|
|
|
|
bool scale = chkScaleBasedVisibility->isChecked();
|
|
spinScaleMin->setEnabled( scale );
|
|
spinScaleMax->setEnabled( scale );
|
|
|
|
spinDecimals->setEnabled( chkFormattedNumbers->isChecked() );
|
|
|
|
bool offline = chkLineAbove->isChecked() || chkLineBelow->isChecked();
|
|
offlineOptions->setEnabled( offline );
|
|
}
|
|
|
|
void QgsLabelingGui::changeBufferColor()
|
|
{
|
|
QColor color = QColorDialog::getColor( btnBufferColor->color(), this );
|
|
if ( !color.isValid() )
|
|
return;
|
|
|
|
btnBufferColor->setColor( color );
|
|
updatePreview();
|
|
}
|
|
|
|
void QgsLabelingGui::updateOptions()
|
|
{
|
|
mCentroidFrame->setVisible( false );
|
|
if (( stackedPlacement->currentWidget() == pagePoint && radAroundPoint->isChecked() )
|
|
|| ( stackedPlacement->currentWidget() == pagePolygon && radAroundCentroid->isChecked() ) )
|
|
{
|
|
stackedOptions->setCurrentWidget( pageOptionsPoint );
|
|
mCentroidFrame->setVisible( stackedPlacement->currentWidget() == pagePolygon
|
|
&& radAroundCentroid->isChecked() );
|
|
}
|
|
else if (( stackedPlacement->currentWidget() == pagePoint && radOverPoint->isChecked() )
|
|
|| ( stackedPlacement->currentWidget() == pagePolygon && radOverCentroid->isChecked() ) )
|
|
{
|
|
stackedOptions->setCurrentWidget( pageOptionsPointOffset );
|
|
mCentroidFrame->setVisible( stackedPlacement->currentWidget() == pagePolygon
|
|
&& radOverCentroid->isChecked() );
|
|
}
|
|
else if (( stackedPlacement->currentWidget() == pageLine && radLineParallel->isChecked() )
|
|
|| ( stackedPlacement->currentWidget() == pagePolygon && radPolygonPerimeter->isChecked() )
|
|
|| ( stackedPlacement->currentWidget() == pageLine && radLineCurved->isChecked() ) )
|
|
{
|
|
stackedOptions->setCurrentWidget( pageOptionsLine );
|
|
}
|
|
else
|
|
{
|
|
stackedOptions->setCurrentWidget( pageOptionsEmpty );
|
|
}
|
|
}
|
|
|
|
void QgsLabelingGui::updateQuadrant()
|
|
{
|
|
if ( mPointOffsetRadioAboveLeft->isChecked() ) { mXQuadOffset = -1; mYQuadOffset = 1; };
|
|
if ( mPointOffsetRadioAbove->isChecked() ) { mXQuadOffset = 0; mYQuadOffset = 1; };
|
|
if ( mPointOffsetRadioAboveRight->isChecked() ) { mXQuadOffset = 1; mYQuadOffset = 1; };
|
|
|
|
if ( mPointOffsetRadioLeft->isChecked() ) { mXQuadOffset = -1; mYQuadOffset = 0; };
|
|
if ( mPointOffsetRadioOver->isChecked() ) { mXQuadOffset = 0; mYQuadOffset = 0; };
|
|
if ( mPointOffsetRadioRight->isChecked() ) { mXQuadOffset = 1; mYQuadOffset = 0; };
|
|
|
|
if ( mPointOffsetRadioBelowLeft->isChecked() ) { mXQuadOffset = -1; mYQuadOffset = -1; };
|
|
if ( mPointOffsetRadioBelow->isChecked() ) { mXQuadOffset = 0; mYQuadOffset = -1; };
|
|
if ( mPointOffsetRadioBelowRight->isChecked() ) { mXQuadOffset = 1; mYQuadOffset = -1; };
|
|
}
|
|
|
|
void QgsLabelingGui::populateFontCapitalsComboBox()
|
|
{
|
|
mFontCapitalsComboBox->addItem( tr( "Mixed Case" ), 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( "Title Case" ), QVariant( 4 ) );
|
|
}
|
|
|
|
void QgsLabelingGui::populateFontStyleComboBox()
|
|
{
|
|
mFontStyleComboBox->clear();
|
|
foreach ( const QString &style, mFontDB.styles( mRefFont.family() ) )
|
|
{
|
|
mFontStyleComboBox->addItem( style );
|
|
}
|
|
mFontStyleComboBox->setCurrentIndex( mFontStyleComboBox->findText( mFontDB.styleString( mRefFont ) ) );
|
|
}
|
|
|
|
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_mFontStyleComboBox_currentIndexChanged( const QString & text )
|
|
{
|
|
updateFontViaStyle( 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_mFontSizeUnitComboBox_currentIndexChanged( int index )
|
|
{
|
|
// disable pixel size limiting for labels defined in points
|
|
if ( index == 0 )
|
|
{
|
|
mFontLimitPixelGroupBox->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)
|
|
mFontLimitPixelGroupBox->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_mBufferUnitComboBox_currentIndexChanged( int index )
|
|
{
|
|
Q_UNUSED( index );
|
|
updateFont( mRefFont );
|
|
}
|
|
|
|
void QgsLabelingGui::on_mXCoordinateComboBox_currentIndexChanged( const QString & text )
|
|
{
|
|
if ( text.isEmpty() ) //no data defined alignment without data defined position
|
|
{
|
|
disableDataDefinedAlignment();
|
|
}
|
|
else if ( !mYCoordinateComboBox->currentText().isEmpty() )
|
|
{
|
|
enableDataDefinedAlignment();
|
|
}
|
|
}
|
|
|
|
void QgsLabelingGui::on_mYCoordinateComboBox_currentIndexChanged( const QString & text )
|
|
{
|
|
if ( text.isEmpty() ) //no data defined alignment without data defined position
|
|
{
|
|
disableDataDefinedAlignment();
|
|
}
|
|
else if ( !mXCoordinateComboBox->currentText().isEmpty() )
|
|
{
|
|
enableDataDefinedAlignment();
|
|
}
|
|
}
|
|
|
|
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_clicked()
|
|
{
|
|
QColor color = QColorDialog::getColor( mPreviewBackgroundBtn->color(), this );
|
|
if ( !color.isValid() )
|
|
return;
|
|
|
|
mPreviewBackgroundBtn->setColor( color );
|
|
setPreviewBackground( color );
|
|
}
|
|
|
|
void QgsLabelingGui::on_mDirectSymbLeftToolBtn_clicked()
|
|
{
|
|
bool gotChar = false;
|
|
QChar dirSymb = 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 = QChar();
|
|
|
|
dirSymb = mCharDlg->selectCharacter( &gotChar, mRefFont, mFontDB.styleString( mRefFont ) );
|
|
|
|
if ( !gotChar )
|
|
return;
|
|
|
|
if ( !dirSymb.isNull() )
|
|
mDirectSymbRightLineEdit->setText( QString( dirSymb ) );
|
|
}
|
|
|
|
void QgsLabelingGui::disableDataDefinedAlignment()
|
|
{
|
|
mHorizontalAlignmentComboBox->setCurrentIndex( mHorizontalAlignmentComboBox->findText( "" ) );
|
|
mHorizontalAlignmentComboBox->setEnabled( false );
|
|
mVerticalAlignmentComboBox->setCurrentIndex( mVerticalAlignmentComboBox->findText( "" ) );
|
|
mVerticalAlignmentComboBox->setEnabled( false );
|
|
}
|
|
|
|
void QgsLabelingGui::enableDataDefinedAlignment()
|
|
{
|
|
mHorizontalAlignmentComboBox->setEnabled( true );
|
|
mVerticalAlignmentComboBox->setEnabled( true );
|
|
}
|