Skip to content

Commit

Permalink
[FEATURE][layout] Add above/below segments placement option for scale…
Browse files Browse the repository at this point in the history
… bar labels
  • Loading branch information
nirvn committed Jul 29, 2019
1 parent 5911f96 commit e5deb55
Show file tree
Hide file tree
Showing 14 changed files with 186 additions and 18 deletions.
18 changes: 18 additions & 0 deletions python/core/auto_generated/layout/qgslayoutitemscalebar.sip.in
Expand Up @@ -396,6 +396,24 @@ Returns the spacing (margin) between the scalebar box and content in millimeters
Sets the ``space`` (margin) between the scalebar box and content in millimeters.

.. seealso:: :py:func:`boxContentSpace`
%End

QgsScaleBarSettings::LabelVerticalPlacement labelVerticalPlacement() const;
%Docstring
Returns the vertical placement of text labels.

.. seealso:: :py:func:`setLabelPlacement`

.. versionadded:: 3.10
%End

void setLabelVerticalPlacement( QgsScaleBarSettings::LabelVerticalPlacement placement );
%Docstring
Sets the vertical ``placement`` of text labels.

.. seealso:: :py:func:`labelPlacement`

.. versionadded:: 3.10
%End

QgsScaleBarSettings::Alignment alignment() const;
Expand Down
24 changes: 24 additions & 0 deletions python/core/auto_generated/scalebar/qgsscalebarsettings.sip.in
Expand Up @@ -35,6 +35,12 @@ for scalebar drawing with QgsScaleBarRenderer.
SegmentSizeFitWidth
};

enum LabelVerticalPlacement
{
LabelAboveSegment,
LabelBelowSegment,
};

QgsScaleBarSettings();
%Docstring
Constructor for QgsScaleBarSettings.
Expand Down Expand Up @@ -406,6 +412,24 @@ Returns the spacing (in millimeters) between labels and the scalebar.
Sets the spacing (in millimeters) between labels and the scalebar.

.. seealso:: :py:func:`labelBarSpace`
%End

LabelVerticalPlacement labelVerticalPlacement() const;
%Docstring
Returns the vertical placement of text labels.

.. seealso:: :py:func:`setLabelVerticalPlacement`

.. versionadded:: 3.10
%End

void setLabelVerticalPlacement( LabelVerticalPlacement placement );
%Docstring
Sets the vertical ``placement`` of text labels.

.. seealso:: :py:func:`labelVerticalPlacement`

.. versionadded:: 3.10
%End

double boxContentSpace() const;
Expand Down
30 changes: 30 additions & 0 deletions src/app/layout/qgslayoutscalebarwidget.cpp
Expand Up @@ -43,7 +43,12 @@ QgsLayoutScaleBarWidget::QgsLayoutScaleBarWidget( QgsLayoutItemScaleBar *scaleBa
connect( mStyleComboBox, static_cast<void ( QComboBox::* )( const QString & )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutScaleBarWidget::mStyleComboBox_currentIndexChanged );
connect( mLabelBarSpaceSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutScaleBarWidget::mLabelBarSpaceSpinBox_valueChanged );
connect( mBoxSizeSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutScaleBarWidget::mBoxSizeSpinBox_valueChanged );
<<<<<<< HEAD
connect( mAlignmentComboBox, &QgsAlignmentComboBox::changed, this, &QgsLayoutScaleBarWidget::alignmentChanged );
=======
connect( mLabelPlacementComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutScaleBarWidget::mLabelPlacementComboBox_currentIndexChanged );
connect( mAlignmentComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutScaleBarWidget::mAlignmentComboBox_currentIndexChanged );
>>>>>>> [FEATURE][layout] Add above/below segments placement option for scale bar labels
connect( mUnitsComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutScaleBarWidget::mUnitsComboBox_currentIndexChanged );
connect( mLineJoinStyleCombo, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutScaleBarWidget::mLineJoinStyleCombo_currentIndexChanged );
connect( mLineCapStyleCombo, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutScaleBarWidget::mLineCapStyleCombo_currentIndexChanged );
Expand Down Expand Up @@ -73,6 +78,10 @@ QgsLayoutScaleBarWidget::QgsLayoutScaleBarWidget( QgsLayoutItemScaleBar *scaleBa
mStyleComboBox->insertItem( 4, tr( "Line Ticks Up" ) );
mStyleComboBox->insertItem( 5, tr( "Numeric" ) );

//label placement combo box
mLabelPlacementComboBox->insertItem( 0, tr( "Above segments" ) );
mLabelPlacementComboBox->insertItem( 1, tr( "Below segments" ) );

//alignment combo box
mAlignmentComboBox->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );

Expand Down Expand Up @@ -210,6 +219,9 @@ void QgsLayoutScaleBarWidget::setGuiElements()
mStyleComboBox->setCurrentIndex( mStyleComboBox->findText( tr( style.toLocal8Bit().data() ) ) );
toggleStyleSpecificControls( style );

//label placement
mLabelPlacementComboBox->setCurrentIndex( static_cast< int >( mScalebar->labelVerticalPlacement() ) );

//alignment

Qt::Alignment a = Qt::AlignLeft;
Expand Down Expand Up @@ -483,6 +495,7 @@ void QgsLayoutScaleBarWidget::toggleStyleSpecificControls( const QString &style
mStrokeColorButton->setEnabled( false );
mLineJoinStyleCombo->setEnabled( false );
mLineCapStyleCombo->setEnabled( false );
mLabelPlacementComboBox->setEnabled( false );
mAlignmentComboBox->setEnabled( true );
}
else
Expand All @@ -495,6 +508,7 @@ void QgsLayoutScaleBarWidget::toggleStyleSpecificControls( const QString &style
mFillColorButton->setEnabled( true );
mFillColor2Button->setEnabled( true );
mStrokeColorButton->setEnabled( true );
mLabelPlacementComboBox->setEnabled( true );
mAlignmentComboBox->setEnabled( false );
if ( style == QLatin1String( "Single Box" ) || style == QLatin1String( "Double Box" ) )
{
Expand Down Expand Up @@ -540,6 +554,21 @@ void QgsLayoutScaleBarWidget::mBoxSizeSpinBox_valueChanged( double d )
mScalebar->endCommand();
}

void QgsLayoutScaleBarWidget::mLabelPlacementComboBox_currentIndexChanged( int index )
{
if ( !mScalebar )
{
return;
}

mScalebar->beginCommand( tr( "Set Scalebar Label Placement" ) );
disconnectUpdateSignal();
mScalebar->setLabelVerticalPlacement( static_cast< QgsScaleBarSettings::LabelVerticalPlacement >( index ) );
mScalebar->update();
connectUpdateSignal();
mScalebar->endCommand();
}

void QgsLayoutScaleBarWidget::alignmentChanged()
{
if ( !mScalebar )
Expand Down Expand Up @@ -596,6 +625,7 @@ void QgsLayoutScaleBarWidget::blockMemberSignals( bool block )
mLineWidthSpinBox->blockSignals( block );
mLabelBarSpaceSpinBox->blockSignals( block );
mBoxSizeSpinBox->blockSignals( block );
mLabelPlacementComboBox->blockSignals( block );
mAlignmentComboBox->blockSignals( block );
mUnitsComboBox->blockSignals( block );
mLineJoinStyleCombo->blockSignals( block );
Expand Down
1 change: 1 addition & 0 deletions src/app/layout/qgslayoutscalebarwidget.h
Expand Up @@ -55,6 +55,7 @@ class QgsLayoutScaleBarWidget: public QgsLayoutItemBaseWidget, public QgsExpress
void mStyleComboBox_currentIndexChanged( const QString &text );
void mLabelBarSpaceSpinBox_valueChanged( double d );
void mBoxSizeSpinBox_valueChanged( double d );
void mLabelPlacementComboBox_currentIndexChanged( int index );
void alignmentChanged();
void mUnitsComboBox_currentIndexChanged( int index );
void mLineJoinStyleCombo_currentIndexChanged( int index );
Expand Down
12 changes: 12 additions & 0 deletions src/core/layout/qgslayoutitemscalebar.cpp
Expand Up @@ -339,6 +339,12 @@ QgsScaleBarRenderer::ScaleBarContext QgsLayoutItemScaleBar::createScaleContext()
return scaleContext;
}

void QgsLayoutItemScaleBar::setLabelVerticalPlacement( QgsScaleBarSettings::LabelVerticalPlacement placement )
{
mSettings.setLabelVerticalPlacement( placement );
emit changed();
}

void QgsLayoutItemScaleBar::setAlignment( QgsScaleBarSettings::Alignment a )
{
mSettings.setAlignment( a );
Expand Down Expand Up @@ -649,6 +655,9 @@ bool QgsLayoutItemScaleBar::writePropertiesToElement( QDomElement &composerScale
strokeColorElem.setAttribute( QStringLiteral( "alpha" ), QString::number( mSettings.lineColor().alpha() ) );
composerScaleBarElem.appendChild( strokeColorElem );

//label placement
composerScaleBarElem.setAttribute( QStringLiteral( "labelVerticalPlacement" ), QString::number( static_cast< int >( mSettings.labelVerticalPlacement() ) ) );

//alignment
composerScaleBarElem.setAttribute( QStringLiteral( "alignment" ), QString::number( static_cast< int >( mSettings.alignment() ) ) );

Expand Down Expand Up @@ -828,6 +837,9 @@ bool QgsLayoutItemScaleBar::readPropertiesFromElement( const QDomElement &itemEl
{
mSettings.setUnits( QgsUnitTypes::decodeDistanceUnit( itemElem.attribute( QStringLiteral( "unitType" ) ) ) );
}

mSettings.setLabelVerticalPlacement( static_cast< QgsScaleBarSettings::LabelVerticalPlacement >( itemElem.attribute( QStringLiteral( "labelVerticalPlacement" ), QStringLiteral( "0" ) ).toInt() ) );

mSettings.setAlignment( static_cast< QgsScaleBarSettings::Alignment >( itemElem.attribute( QStringLiteral( "alignment" ), QStringLiteral( "0" ) ).toInt() ) );

//map
Expand Down
14 changes: 14 additions & 0 deletions src/core/layout/qgslayoutitemscalebar.h
Expand Up @@ -340,6 +340,20 @@ class CORE_EXPORT QgsLayoutItemScaleBar: public QgsLayoutItem
*/
void setBoxContentSpace( double space );

/**
* Returns the vertical placement of text labels.
* \see setLabelPlacement()
* \since QGIS 3.10
*/
QgsScaleBarSettings::LabelVerticalPlacement labelVerticalPlacement() const { return mSettings.labelVerticalPlacement(); }

/**
* Sets the vertical \a placement of text labels.
* \see labelPlacement()
* \since QGIS 3.10
*/
void setLabelVerticalPlacement( QgsScaleBarSettings::LabelVerticalPlacement placement );

/**
* Returns the scalebar alignment.
* \see setAlignment()
Expand Down
2 changes: 1 addition & 1 deletion src/core/scalebar/qgsdoubleboxscalebarrenderer.cpp
Expand Up @@ -31,7 +31,7 @@ void QgsDoubleBoxScaleBarRenderer::draw( QgsRenderContext &context, const QgsSca
double scaledLabelBarSpace = context.convertToPainterUnits( settings.labelBarSpace(), QgsUnitTypes::RenderMillimeters );
double scaledBoxContentSpace = context.convertToPainterUnits( settings.boxContentSpace(), QgsUnitTypes::RenderMillimeters );
QFontMetricsF fontMetrics = QgsTextRenderer::fontMetrics( context, settings.textFormat() );
double barTopPosition = fontMetrics.ascent() + scaledLabelBarSpace + scaledBoxContentSpace;
double barTopPosition = scaledBoxContentSpace + ( settings.labelVerticalPlacement() == QgsScaleBarSettings::LabelAboveSegment ? fontMetrics.ascent() + scaledLabelBarSpace : 0 );
double segmentHeight = context.convertToPainterUnits( settings.height() / 2, QgsUnitTypes::RenderMillimeters );

painter->save();
Expand Down
18 changes: 11 additions & 7 deletions src/core/scalebar/qgsscalebarrenderer.cpp
Expand Up @@ -43,6 +43,8 @@ void QgsScaleBarRenderer::drawDefaultLabels( QgsRenderContext &context, const Qg
double xOffset = fontMetrics.width( firstLabel ) / 2.0;

double scaledBoxContentSpace = context.convertToPainterUnits( settings.boxContentSpace(), QgsUnitTypes::RenderMillimeters );
double scaledLabelBarSpace = context.convertToPainterUnits( settings.labelBarSpace(), QgsUnitTypes::RenderMillimeters );
double scaledHeight = context.convertToPainterUnits( settings.height(), QgsUnitTypes::RenderMillimeters );

double currentLabelNumber = 0.0;

Expand Down Expand Up @@ -72,9 +74,10 @@ void QgsScaleBarRenderer::drawDefaultLabels( QgsRenderContext &context, const Qg
if ( segmentCounter == 0 || segmentCounter >= nSegmentsLeft ) //don't draw label for intermediate left segments
{
scaleScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "scale_value" ), currentNumericLabel, true, false ) );
QgsTextRenderer::drawText( QPointF( context.convertToPainterUnits( positions.at( i ), QgsUnitTypes::RenderMillimeters ) + xOffset,
fontMetrics.ascent() + scaledBoxContentSpace ), 0, QgsTextRenderer::AlignCenter,
QStringList() << currentNumericLabel, context, format );
QPointF pos;
pos.setX( context.convertToPainterUnits( positions.at( i ), QgsUnitTypes::RenderMillimeters ) + xOffset );
pos.setY( fontMetrics.ascent() + scaledBoxContentSpace + ( settings.labelVerticalPlacement() == QgsScaleBarSettings::LabelBelowSegment ? scaledHeight + scaledLabelBarSpace : 0 ) );
QgsTextRenderer::drawText( pos, 0, QgsTextRenderer::AlignCenter, QStringList() << currentNumericLabel, context, format );
}

if ( segmentCounter >= nSegmentsLeft )
Expand All @@ -92,10 +95,11 @@ void QgsScaleBarRenderer::drawDefaultLabels( QgsRenderContext &context, const Qg
// horizontally centering just the numeric portion.
currentNumericLabel = QString::number( currentLabelNumber / settings.mapUnitsPerScaleBarUnit() );
scaleScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "scale_value" ), currentNumericLabel, true, false ) );
QgsTextRenderer::drawText( QPointF( context.convertToPainterUnits( positions.at( positions.size() - 1 ) + scaleContext.segmentWidth, QgsUnitTypes::RenderMillimeters ) + xOffset
- fontMetrics.width( currentNumericLabel ) / 2.0,
fontMetrics.ascent() + scaledBoxContentSpace ), 0, QgsTextRenderer::AlignLeft,
QStringList() << ( currentNumericLabel + ' ' + settings.unitLabel() ), context, format );
QPointF pos;
pos.setX( context.convertToPainterUnits( positions.at( positions.size() - 1 ) + scaleContext.segmentWidth, QgsUnitTypes::RenderMillimeters ) + xOffset
- fontMetrics.width( currentNumericLabel ) / 2.0 );
pos.setY( fontMetrics.ascent() + scaledBoxContentSpace + ( settings.labelVerticalPlacement() == QgsScaleBarSettings::LabelBelowSegment ? scaledHeight + scaledLabelBarSpace : 0 ) );
QgsTextRenderer::drawText( pos, 0, QgsTextRenderer::AlignLeft, QStringList() << ( currentNumericLabel + ' ' + settings.unitLabel() ), context, format );
}

painter->restore();
Expand Down
25 changes: 25 additions & 0 deletions src/core/scalebar/qgsscalebarsettings.h
Expand Up @@ -56,6 +56,15 @@ class CORE_EXPORT QgsScaleBarSettings
SegmentSizeFitWidth = 1 //!< Scale bar segment size is calculated to fit a size range
};

/**
* Label vertical placement.
*/
enum LabelVerticalPlacement
{
LabelAboveSegment = 0, //!< Labels are drawn above the scalebar
LabelBelowSegment, //!< Labels are drawn below the scalebar
};

/**
* Constructor for QgsScaleBarSettings.
*/
Expand Down Expand Up @@ -390,6 +399,20 @@ class CORE_EXPORT QgsScaleBarSettings
*/
void setLabelBarSpace( double space ) { mLabelBarSpace = space; }

/**
* Returns the vertical placement of text labels.
* \see setLabelVerticalPlacement()
* \since QGIS 3.10
*/
LabelVerticalPlacement labelVerticalPlacement() const { return mLabelVerticalPlacement; }

/**
* Sets the vertical \a placement of text labels.
* \see labelVerticalPlacement()
* \since QGIS 3.10
*/
void setLabelVerticalPlacement( LabelVerticalPlacement placement ) { mLabelVerticalPlacement = placement; }

/**
* Returns the spacing (margin) between the scalebar box and content in millimeters.
* \see setBoxContentSpace()
Expand Down Expand Up @@ -480,6 +503,8 @@ class CORE_EXPORT QgsScaleBarSettings

//! Space between bar and Text labels
double mLabelBarSpace = 3.0;
//! Labels placement
LabelVerticalPlacement mLabelVerticalPlacement = LabelAboveSegment;

//! Space between content and item box
double mBoxContentSpace = 1.0;
Expand Down
2 changes: 1 addition & 1 deletion src/core/scalebar/qgssingleboxscalebarrenderer.cpp
Expand Up @@ -31,7 +31,7 @@ void QgsSingleBoxScaleBarRenderer::draw( QgsRenderContext &context, const QgsSca
double scaledLabelBarSpace = context.convertToPainterUnits( settings.labelBarSpace(), QgsUnitTypes::RenderMillimeters );
double scaledBoxContentSpace = context.convertToPainterUnits( settings.boxContentSpace(), QgsUnitTypes::RenderMillimeters );
QFontMetricsF fontMetrics = QgsTextRenderer::fontMetrics( context, settings.textFormat() );
double barTopPosition = fontMetrics.ascent() + scaledLabelBarSpace + scaledBoxContentSpace;
double barTopPosition = scaledBoxContentSpace + ( settings.labelVerticalPlacement() == QgsScaleBarSettings::LabelAboveSegment ? fontMetrics.ascent() + scaledLabelBarSpace : 0 );

painter->save();
if ( context.flags() & QgsRenderContext::Antialiasing )
Expand Down
2 changes: 1 addition & 1 deletion src/core/scalebar/qgsticksscalebarrenderer.cpp
Expand Up @@ -43,7 +43,7 @@ void QgsTicksScaleBarRenderer::draw( QgsRenderContext &context, const QgsScaleBa
double scaledLabelBarSpace = context.convertToPainterUnits( settings.labelBarSpace(), QgsUnitTypes::RenderMillimeters );
double scaledBoxContentSpace = context.convertToPainterUnits( settings.boxContentSpace(), QgsUnitTypes::RenderMillimeters );
QFontMetricsF fontMetrics = QgsTextRenderer::fontMetrics( context, settings.textFormat() );
double barTopPosition = fontMetrics.ascent() + scaledLabelBarSpace + scaledBoxContentSpace;
double barTopPosition = scaledBoxContentSpace + ( settings.labelVerticalPlacement() == QgsScaleBarSettings::LabelAboveSegment ? fontMetrics.ascent() + scaledLabelBarSpace : 0 );
double middlePosition = barTopPosition + context.convertToPainterUnits( settings.height() / 2.0, QgsUnitTypes::RenderMillimeters );
double bottomPosition = barTopPosition + context.convertToPainterUnits( settings.height(), QgsUnitTypes::RenderMillimeters );

Expand Down
26 changes: 18 additions & 8 deletions src/ui/layout/qgslayoutscalebarwidgetbase.ui
Expand Up @@ -377,7 +377,7 @@
</property>
</widget>
</item>
<item row="5" column="0">
<item row="7" column="0">
<widget class="QLabel" name="mAlignmentLabel">
<property name="text">
<string>Alignment</string>
Expand All @@ -391,28 +391,38 @@
</property>
</widget>
</item>
<item row="2" column="0">
<item row="2" column="0" colspan="3">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Labels vertical placement</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QComboBox" name="mLabelPlacementComboBox"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Line width</string>
</property>
</widget>
</item>
<item row="4" column="0">
<item row="6" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Cap style</string>
</property>
</widget>
</item>
<item row="3" column="0">
<item row="5" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Join style</string>
</property>
</widget>
</item>
<item row="2" column="2">
<item row="4" column="2">
<widget class="QgsPropertyOverrideButton" name="mLineWidthDDBtn">
<property name="text">
<string>…</string>
Expand All @@ -439,13 +449,13 @@
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<item row="5" column="1" colspan="2">
<widget class="QgsPenJoinStyleComboBox" name="mLineJoinStyleCombo"/>
</item>
<item row="4" column="1" colspan="2">
<item row="6" column="1" colspan="2">
<widget class="QgsPenCapStyleComboBox" name="mLineCapStyleCombo"/>
</item>
<item row="5" column="1" colspan="2">
<item row="7" column="1" colspan="2">
<widget class="QgsAlignmentComboBox" name="mAlignmentComboBox"/>
</item>
</layout>
Expand Down

0 comments on commit e5deb55

Please sign in to comment.