mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-04 00:06:46 -05:00
Add scale method option for layout scale bars
Instead of always calculating the scale along the bottom of the map, expose a choice of methods to the user (along bottom, middle, top, or average of the three measurements) For new scalebars, default to the average method, which better handles the scenario where the scale at the top or bottom of the map cannot be calculated (eg when the top/bottom of the map falls just outside valid areas for the map's crs) This fixes one of the most common scenarios which cause scale bar widths to blow out to massive sizes Refs #55240
This commit is contained in:
parent
ede5a09c69
commit
29b345e2c3
@ -9697,6 +9697,23 @@ Qgis.PictureFormat.__doc__ = """Picture formats.
|
||||
"""
|
||||
# --
|
||||
Qgis.PictureFormat.baseClass = Qgis
|
||||
# monkey patching scoped based enum
|
||||
Qgis.ScaleCalculationMethod.HorizontalTop.__doc__ = "Calculate horizontally, across top of map"
|
||||
Qgis.ScaleCalculationMethod.HorizontalMiddle.__doc__ = "Calculate horizontally, across midle of map"
|
||||
Qgis.ScaleCalculationMethod.HorizontalBottom.__doc__ = "Calculate horizontally, across bottom of map"
|
||||
Qgis.ScaleCalculationMethod.HorizontalAverage.__doc__ = "Calculate horizontally, using the average of the top, middle and bottom scales"
|
||||
Qgis.ScaleCalculationMethod.__doc__ = """Scale calculation logic.
|
||||
|
||||
.. versionadded:: 3.40
|
||||
|
||||
* ``HorizontalTop``: Calculate horizontally, across top of map
|
||||
* ``HorizontalMiddle``: Calculate horizontally, across midle of map
|
||||
* ``HorizontalBottom``: Calculate horizontally, across bottom of map
|
||||
* ``HorizontalAverage``: Calculate horizontally, using the average of the top, middle and bottom scales
|
||||
|
||||
"""
|
||||
# --
|
||||
Qgis.ScaleCalculationMethod.baseClass = Qgis
|
||||
QgsScaleBarSettings.Alignment = Qgis.ScaleBarAlignment
|
||||
# monkey patching scoped based enum
|
||||
QgsScaleBarSettings.AlignLeft = Qgis.ScaleBarAlignment.Left
|
||||
|
||||
@ -813,6 +813,24 @@ Ownership of ``format`` is transferred to the scalebar.
|
||||
.. seealso:: :py:func:`numericFormat`
|
||||
|
||||
.. versionadded:: 3.12
|
||||
%End
|
||||
|
||||
Qgis::ScaleCalculationMethod method() const;
|
||||
%Docstring
|
||||
Returns the scale calculation method, which determines how the bar's scale will be calculated.
|
||||
|
||||
.. seealso:: :py:func:`setMethod`
|
||||
|
||||
.. versionadded:: 3.40
|
||||
%End
|
||||
|
||||
void setMethod( Qgis::ScaleCalculationMethod method );
|
||||
%Docstring
|
||||
Sets the scale calculation ``method``, which determines how the bar's scale will be calculated.
|
||||
|
||||
.. seealso:: :py:func:`method`
|
||||
|
||||
.. versionadded:: 3.40
|
||||
%End
|
||||
|
||||
void update();
|
||||
|
||||
@ -2786,6 +2786,13 @@ The development version
|
||||
Unknown,
|
||||
};
|
||||
|
||||
enum class ScaleCalculationMethod /BaseType=IntEnum/
|
||||
{
|
||||
HorizontalTop,
|
||||
HorizontalMiddle,
|
||||
HorizontalBottom,
|
||||
HorizontalAverage,
|
||||
};
|
||||
|
||||
enum class ScaleBarAlignment /BaseType=IntEnum/
|
||||
{
|
||||
|
||||
@ -9620,6 +9620,23 @@ Qgis.PictureFormat.__doc__ = """Picture formats.
|
||||
"""
|
||||
# --
|
||||
Qgis.PictureFormat.baseClass = Qgis
|
||||
# monkey patching scoped based enum
|
||||
Qgis.ScaleCalculationMethod.HorizontalTop.__doc__ = "Calculate horizontally, across top of map"
|
||||
Qgis.ScaleCalculationMethod.HorizontalMiddle.__doc__ = "Calculate horizontally, across midle of map"
|
||||
Qgis.ScaleCalculationMethod.HorizontalBottom.__doc__ = "Calculate horizontally, across bottom of map"
|
||||
Qgis.ScaleCalculationMethod.HorizontalAverage.__doc__ = "Calculate horizontally, using the average of the top, middle and bottom scales"
|
||||
Qgis.ScaleCalculationMethod.__doc__ = """Scale calculation logic.
|
||||
|
||||
.. versionadded:: 3.40
|
||||
|
||||
* ``HorizontalTop``: Calculate horizontally, across top of map
|
||||
* ``HorizontalMiddle``: Calculate horizontally, across midle of map
|
||||
* ``HorizontalBottom``: Calculate horizontally, across bottom of map
|
||||
* ``HorizontalAverage``: Calculate horizontally, using the average of the top, middle and bottom scales
|
||||
|
||||
"""
|
||||
# --
|
||||
Qgis.ScaleCalculationMethod.baseClass = Qgis
|
||||
QgsScaleBarSettings.Alignment = Qgis.ScaleBarAlignment
|
||||
# monkey patching scoped based enum
|
||||
QgsScaleBarSettings.AlignLeft = Qgis.ScaleBarAlignment.Left
|
||||
|
||||
@ -813,6 +813,24 @@ Ownership of ``format`` is transferred to the scalebar.
|
||||
.. seealso:: :py:func:`numericFormat`
|
||||
|
||||
.. versionadded:: 3.12
|
||||
%End
|
||||
|
||||
Qgis::ScaleCalculationMethod method() const;
|
||||
%Docstring
|
||||
Returns the scale calculation method, which determines how the bar's scale will be calculated.
|
||||
|
||||
.. seealso:: :py:func:`setMethod`
|
||||
|
||||
.. versionadded:: 3.40
|
||||
%End
|
||||
|
||||
void setMethod( Qgis::ScaleCalculationMethod method );
|
||||
%Docstring
|
||||
Sets the scale calculation ``method``, which determines how the bar's scale will be calculated.
|
||||
|
||||
.. seealso:: :py:func:`method`
|
||||
|
||||
.. versionadded:: 3.40
|
||||
%End
|
||||
|
||||
void update();
|
||||
|
||||
@ -2786,6 +2786,13 @@ The development version
|
||||
Unknown,
|
||||
};
|
||||
|
||||
enum class ScaleCalculationMethod
|
||||
{
|
||||
HorizontalTop,
|
||||
HorizontalMiddle,
|
||||
HorizontalBottom,
|
||||
HorizontalAverage,
|
||||
};
|
||||
|
||||
enum class ScaleBarAlignment
|
||||
{
|
||||
|
||||
@ -290,6 +290,21 @@ void QgsLayoutItemScaleBar::disconnectCurrentMap()
|
||||
mMap = nullptr;
|
||||
}
|
||||
|
||||
Qgis::ScaleCalculationMethod QgsLayoutItemScaleBar::method() const
|
||||
{
|
||||
return mMethod;
|
||||
}
|
||||
|
||||
void QgsLayoutItemScaleBar::setMethod( Qgis::ScaleCalculationMethod method )
|
||||
{
|
||||
if ( mMethod == method )
|
||||
return;
|
||||
|
||||
mMethod = method;
|
||||
refreshSegmentMillimeters();
|
||||
resizeToMinimumWidth();
|
||||
}
|
||||
|
||||
void QgsLayoutItemScaleBar::refreshUnitsPerSegment( const QgsExpressionContext *context )
|
||||
{
|
||||
if ( mDataDefinedProperties.isActive( QgsLayoutObject::DataDefinedProperty::ScalebarSegmentWidth ) )
|
||||
@ -570,19 +585,62 @@ double QgsLayoutItemScaleBar::mapWidth() const
|
||||
da.setEllipsoid( mLayout->project()->ellipsoid() );
|
||||
|
||||
const Qgis::DistanceUnit units = da.lengthUnits();
|
||||
double measure = 0;
|
||||
try
|
||||
|
||||
QList< double > yValues;
|
||||
switch ( mMethod )
|
||||
{
|
||||
measure = da.measureLine( QgsPointXY( mapExtent.xMinimum(), mapExtent.yMinimum() ),
|
||||
QgsPointXY( mapExtent.xMaximum(), mapExtent.yMinimum() ) );
|
||||
measure /= QgsUnitTypes::fromUnitToUnitFactor( mSettings.units(), units );
|
||||
case Qgis::ScaleCalculationMethod::HorizontalTop:
|
||||
yValues << mapExtent.yMaximum();
|
||||
break;
|
||||
|
||||
case Qgis::ScaleCalculationMethod::HorizontalMiddle:
|
||||
yValues << 0.5 * ( mapExtent.yMaximum() + mapExtent.yMinimum() );
|
||||
break;
|
||||
|
||||
|
||||
case Qgis::ScaleCalculationMethod::HorizontalBottom:
|
||||
yValues << mapExtent.yMinimum();
|
||||
break;
|
||||
|
||||
case Qgis::ScaleCalculationMethod::HorizontalAverage:
|
||||
yValues << mapExtent.yMaximum();
|
||||
yValues << 0.5 * ( mapExtent.yMaximum() + mapExtent.yMinimum() );
|
||||
yValues << mapExtent.yMinimum();
|
||||
break;
|
||||
}
|
||||
catch ( QgsCsException & )
|
||||
|
||||
double sumValidMeasures = 0;
|
||||
int validMeasureCount = 0;
|
||||
|
||||
for ( const double y : std::as_const( yValues ) )
|
||||
{
|
||||
// TODO report errors to user
|
||||
QgsDebugError( QStringLiteral( "An error occurred while calculating length" ) );
|
||||
try
|
||||
{
|
||||
double measure = da.measureLine( QgsPointXY( mapExtent.xMinimum(), y ),
|
||||
QgsPointXY( mapExtent.xMaximum(), y ) );
|
||||
if ( std::isnan( measure ) )
|
||||
{
|
||||
// TODO report errors to user
|
||||
QgsDebugError( QStringLiteral( "An error occurred while calculating length" ) );
|
||||
continue;
|
||||
}
|
||||
|
||||
measure /= QgsUnitTypes::fromUnitToUnitFactor( mSettings.units(), units );
|
||||
sumValidMeasures += measure;
|
||||
validMeasureCount++;
|
||||
}
|
||||
catch ( QgsCsException & )
|
||||
{
|
||||
// TODO report errors to user
|
||||
QgsDebugError( QStringLiteral( "An error occurred while calculating length" ) );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return measure;
|
||||
|
||||
if ( validMeasureCount == 0 )
|
||||
return std::numeric_limits< double >::quiet_NaN();
|
||||
|
||||
return sumValidMeasures / validMeasureCount;
|
||||
}
|
||||
}
|
||||
|
||||
@ -965,6 +1023,7 @@ bool QgsLayoutItemScaleBar::writePropertiesToElement( QDomElement &composerScale
|
||||
composerScaleBarElem.setAttribute( QStringLiteral( "maxBarWidth" ), mSettings.maximumBarWidth() );
|
||||
composerScaleBarElem.setAttribute( QStringLiteral( "segmentMillimeters" ), QString::number( mSegmentMillimeters ) );
|
||||
composerScaleBarElem.setAttribute( QStringLiteral( "numMapUnitsPerScaleBarUnit" ), QString::number( mSettings.mapUnitsPerScaleBarUnit() ) );
|
||||
composerScaleBarElem.setAttribute( QStringLiteral( "method" ), qgsEnumValueToKey( mMethod ) );
|
||||
|
||||
const QDomElement textElem = mSettings.textFormat().writeXml( doc, rwContext );
|
||||
composerScaleBarElem.appendChild( textElem );
|
||||
@ -1092,6 +1151,9 @@ bool QgsLayoutItemScaleBar::readPropertiesFromElement( const QDomElement &itemEl
|
||||
mSegmentMillimeters = itemElem.attribute( QStringLiteral( "segmentMillimeters" ), QStringLiteral( "0.0" ) ).toDouble();
|
||||
mSettings.setMapUnitsPerScaleBarUnit( itemElem.attribute( QStringLiteral( "numMapUnitsPerScaleBarUnit" ), QStringLiteral( "1.0" ) ).toDouble() );
|
||||
|
||||
// default to horizontal bottom to keep same behavior for older projects
|
||||
mMethod = qgsEnumKeyToValue( itemElem.attribute( QStringLiteral( "method" ) ), Qgis::ScaleCalculationMethod::HorizontalBottom );
|
||||
|
||||
const QDomElement lineSymbolElem = itemElem.firstChildElement( QStringLiteral( "lineSymbol" ) );
|
||||
bool foundLineSymbol = false;
|
||||
if ( !lineSymbolElem.isNull() )
|
||||
|
||||
@ -648,6 +648,22 @@ class CORE_EXPORT QgsLayoutItemScaleBar: public QgsLayoutItem
|
||||
*/
|
||||
void setNumericFormat( QgsNumericFormat *format SIP_TRANSFER );
|
||||
|
||||
/**
|
||||
* Returns the scale calculation method, which determines how the bar's scale will be calculated.
|
||||
*
|
||||
* \see setMethod()
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
Qgis::ScaleCalculationMethod method() const;
|
||||
|
||||
/**
|
||||
* Sets the scale calculation \a method, which determines how the bar's scale will be calculated.
|
||||
*
|
||||
* \see method()
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
void setMethod( Qgis::ScaleCalculationMethod method );
|
||||
|
||||
/**
|
||||
* Adjusts the scale bar box size and updates the item.
|
||||
*/
|
||||
@ -675,6 +691,7 @@ class CORE_EXPORT QgsLayoutItemScaleBar: public QgsLayoutItem
|
||||
QString mMapUuid;
|
||||
|
||||
QgsScaleBarSettings mSettings;
|
||||
Qgis::ScaleCalculationMethod mMethod = Qgis::ScaleCalculationMethod::HorizontalAverage;
|
||||
|
||||
//! Scalebar style
|
||||
std::unique_ptr< QgsScaleBarRenderer > mStyle;
|
||||
|
||||
@ -4897,6 +4897,19 @@ class CORE_EXPORT Qgis
|
||||
};
|
||||
Q_ENUM( PictureFormat )
|
||||
|
||||
/**
|
||||
* Scale calculation logic.
|
||||
*
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
enum class ScaleCalculationMethod : int
|
||||
{
|
||||
HorizontalTop = 0, //!< Calculate horizontally, across top of map
|
||||
HorizontalMiddle, //!< Calculate horizontally, across midle of map
|
||||
HorizontalBottom, //!< Calculate horizontally, across bottom of map
|
||||
HorizontalAverage, //!< Calculate horizontally, using the average of the top, middle and bottom scales
|
||||
};
|
||||
Q_ENUM( ScaleCalculationMethod )
|
||||
|
||||
/**
|
||||
* Scalebar alignment.
|
||||
|
||||
@ -55,6 +55,20 @@ QgsLayoutScaleBarWidget::QgsLayoutScaleBarWidget( QgsLayoutItemScaleBar *scaleBa
|
||||
connect( mMinWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutScaleBarWidget::mMinWidthSpinBox_valueChanged );
|
||||
connect( mMaxWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutScaleBarWidget::mMaxWidthSpinBox_valueChanged );
|
||||
connect( mNumberFormatPushButton, &QPushButton::clicked, this, &QgsLayoutScaleBarWidget::changeNumberFormat );
|
||||
connect( mMethodCombo, qOverload<int>( &QComboBox::currentIndexChanged ), this, [ = ]
|
||||
{
|
||||
if ( !mScalebar )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
disconnectUpdateSignal();
|
||||
mScalebar->beginCommand( tr( "Set Scalebar Method" ) );
|
||||
mScalebar->setMethod( mMethodCombo->currentData().value< Qgis::ScaleCalculationMethod >() );
|
||||
mScalebar->update();
|
||||
connectUpdateSignal();
|
||||
mScalebar->endCommand();
|
||||
} );
|
||||
|
||||
registerDataDefinedButton( mSegmentsLeftDDBtn, QgsLayoutObject::DataDefinedProperty::ScalebarLeftSegments );
|
||||
registerDataDefinedButton( mSegmentsRightDDBtn, QgsLayoutObject::DataDefinedProperty::ScalebarRightSegments );
|
||||
@ -115,6 +129,11 @@ QgsLayoutScaleBarWidget::QgsLayoutScaleBarWidget( QgsLayoutItemScaleBar *scaleBa
|
||||
mUnitsComboBox->addItem( tr( "Millimeters" ), static_cast< int >( Qgis::DistanceUnit::Millimeters ) );
|
||||
mUnitsComboBox->addItem( tr( "Inches" ), static_cast< int >( Qgis::DistanceUnit::Inches ) );
|
||||
|
||||
mMethodCombo->addItem( tr( "Average Top, Middle and Bottom Scales" ), QVariant::fromValue( Qgis::ScaleCalculationMethod::HorizontalAverage ) );
|
||||
mMethodCombo->addItem( tr( "Calculate along Top of Map" ), QVariant::fromValue( Qgis::ScaleCalculationMethod::HorizontalTop ) );
|
||||
mMethodCombo->addItem( tr( "Calculate along Middle of Map" ), QVariant::fromValue( Qgis::ScaleCalculationMethod::HorizontalMiddle ) );
|
||||
mMethodCombo->addItem( tr( "Calculate along Bottom of Map" ), QVariant::fromValue( Qgis::ScaleCalculationMethod::HorizontalBottom ) );
|
||||
|
||||
mLineStyleButton->setSymbolType( Qgis::SymbolType::Line );
|
||||
connect( mLineStyleButton, &QgsSymbolButton::changed, this, &QgsLayoutScaleBarWidget::lineSymbolChanged );
|
||||
|
||||
@ -349,6 +368,8 @@ void QgsLayoutScaleBarWidget::setGuiElements()
|
||||
mMinWidthSpinBox->setValue( mScalebar->minimumBarWidth() );
|
||||
mMaxWidthSpinBox->setValue( mScalebar->maximumBarWidth() );
|
||||
|
||||
mMethodCombo->setCurrentIndex( mMethodCombo->findData( QVariant::fromValue( mScalebar->method() ) ) );
|
||||
|
||||
populateDataDefinedButtons();
|
||||
|
||||
blockMemberSignals( false );
|
||||
@ -745,6 +766,7 @@ void QgsLayoutScaleBarWidget::blockMemberSignals( bool block )
|
||||
mFontButton->blockSignals( block );
|
||||
mMinWidthSpinBox->blockSignals( block );
|
||||
mMaxWidthSpinBox->blockSignals( block );
|
||||
mMethodCombo->blockSignals( block );
|
||||
}
|
||||
|
||||
void QgsLayoutScaleBarWidget::connectUpdateSignal()
|
||||
|
||||
@ -62,14 +62,14 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>566</width>
|
||||
<height>1018</height>
|
||||
<height>1031</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="mainLayout">
|
||||
<item>
|
||||
<widget class="QgsCollapsibleGroupBoxBasic" name="groupBox">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
<enum>Qt::FocusPolicy::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Main Properties</string>
|
||||
@ -122,7 +122,7 @@
|
||||
<item>
|
||||
<widget class="QgsCollapsibleGroupBoxBasic" name="mGroupBoxUnits">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
<enum>Qt::FocusPolicy::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Units</string>
|
||||
@ -134,10 +134,54 @@
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="mUnitLabelLabel">
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="mUnitLabelLineEdit">
|
||||
<property name="toolTip">
|
||||
<string>Text used for labeling the scalebar units, e.g., "m" or "km". This should be matched to reflect the multiplier above.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QPushButton" name="mNumberFormatPushButton">
|
||||
<property name="text">
|
||||
<string>&Label for units</string>
|
||||
<string>Customize</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="mUnitsComboBox">
|
||||
<property name="toolTip">
|
||||
<string>Specifies the underlying units used for scalebar calculations, e.g., "meters" or "feet"</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QgsDoubleSpinBox" name="mMapUnitsPerBarUnitSpinBox">
|
||||
<property name="toolTip">
|
||||
<string>Specifies how many scalebar units per labeled unit. For example, if your scalebar units are set to "meters", a multiplier of 1000 will result in the scalebar labels in kilometers.</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>9999999999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="showClearButton" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="mUnitsLabel">
|
||||
<property name="text">
|
||||
<string>Scalebar units</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="mUnitLabelLabel_2">
|
||||
<property name="text">
|
||||
<string>Number format</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
@ -160,47 +204,10 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QgsDoubleSpinBox" name="mMapUnitsPerBarUnitSpinBox">
|
||||
<property name="toolTip">
|
||||
<string>Specifies how many scalebar units per labeled unit. For example, if your scalebar units are set to "meters", a multiplier of 1000 will result in the scalebar labels in kilometers.</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>9999999999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="showClearButton">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="mUnitsComboBox">
|
||||
<property name="toolTip">
|
||||
<string>Specifies the underlying units used for scalebar calculations, e.g., "meters" or "feet"</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="mUnitsLabel">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="mUnitLabelLabel">
|
||||
<property name="text">
|
||||
<string>Scalebar units</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="mUnitLabelLineEdit">
|
||||
<property name="toolTip">
|
||||
<string>Text used for labeling the scalebar units, e.g., "m" or "km". This should be matched to reflect the multiplier above.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="mUnitLabelLabel_2">
|
||||
<property name="text">
|
||||
<string>Number format</string>
|
||||
<string>&Label for units</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
@ -210,10 +217,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QPushButton" name="mNumberFormatPushButton">
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="mMethodCombo"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Customize</string>
|
||||
<string>Method</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -223,7 +233,7 @@
|
||||
<item>
|
||||
<widget class="QgsCollapsibleGroupBoxBasic" name="mGroupBoxSegments">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
<enum>Qt::FocusPolicy::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Segments</string>
|
||||
@ -505,7 +515,7 @@
|
||||
<property name="maximum">
|
||||
<double>9999999999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="showClearButton">
|
||||
<property name="showClearButton" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
@ -526,7 +536,7 @@
|
||||
<item>
|
||||
<widget class="QgsCollapsibleGroupBoxBasic" name="groupBox_5">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
<enum>Qt::FocusPolicy::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Appearance</string>
|
||||
@ -782,6 +792,7 @@
|
||||
<tabstop>mMapUnitsPerBarUnitSpinBox</tabstop>
|
||||
<tabstop>mUnitLabelLineEdit</tabstop>
|
||||
<tabstop>mNumberFormatPushButton</tabstop>
|
||||
<tabstop>mMethodCombo</tabstop>
|
||||
<tabstop>mGroupBoxSegments</tabstop>
|
||||
<tabstop>mSegmentsLeftSpinBox</tabstop>
|
||||
<tabstop>mSegmentsLeftDDBtn</tabstop>
|
||||
|
||||
@ -65,6 +65,7 @@ class TestQgsLayoutScaleBar : public QgsTest
|
||||
void hollow();
|
||||
void hollowDefaults();
|
||||
void tickSubdivisions();
|
||||
void methodTop();
|
||||
};
|
||||
|
||||
void TestQgsLayoutScaleBar::initTestCase()
|
||||
@ -906,6 +907,175 @@ void TestQgsLayoutScaleBar::tickSubdivisions()
|
||||
QGSVERIFYLAYOUTCHECK( QStringLiteral( "layoutscalebar_tick_subdivisions" ), &l );
|
||||
}
|
||||
|
||||
void TestQgsLayoutScaleBar::methodTop()
|
||||
{
|
||||
QgsLayout l( QgsProject::instance() );
|
||||
l.initializeDefaults();
|
||||
QgsLayoutItemMap *map1 = new QgsLayoutItemMap( &l );
|
||||
map1->attemptSetSceneRect( QRectF( 20, 20, 150, 150 ) );
|
||||
map1->setFrameEnabled( false );
|
||||
map1->setVisibility( false );
|
||||
l.addLayoutItem( map1 );
|
||||
// only scale at center of map can be calculated
|
||||
map1->setExtent( QgsRectangle( -100, -100, 100, 100 ) );
|
||||
map1->setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
|
||||
|
||||
QgsLayoutItemScaleBar *scalebar1 = new QgsLayoutItemScaleBar( &l );
|
||||
scalebar1->attemptSetSceneRect( QRectF( 20, 10, 50, 20 ) );
|
||||
l.addLayoutItem( scalebar1 );
|
||||
scalebar1->setLinkedMap( map1 );
|
||||
scalebar1->setTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont() ) );
|
||||
scalebar1->setUnits( Qgis::DistanceUnit::Kilometers );
|
||||
scalebar1->setUnitsPerSegment( 10000 );
|
||||
scalebar1->setNumberOfSegmentsLeft( 0 );
|
||||
scalebar1->setNumberOfSegments( 2 );
|
||||
scalebar1->setHeight( 5 );
|
||||
scalebar1->setSubdivisionsHeight( 25 ); //ensure subdivisionsHeight is non used in non tick-style scalebars
|
||||
scalebar1->setMethod( Qgis::ScaleCalculationMethod::HorizontalMiddle );
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
scalebar1->setLineWidth( 1.0 );
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar1->numericFormat() ) )->setShowThousandsSeparator( false );
|
||||
scalebar1->setStyle( QStringLiteral( "Single Box" ) );
|
||||
|
||||
QgsLayoutItemScaleBar *scalebar1A = new QgsLayoutItemScaleBar( &l );
|
||||
scalebar1A->attemptSetSceneRect( QRectF( 20, 30, 50, 20 ) );
|
||||
l.addLayoutItem( scalebar1A );
|
||||
scalebar1A->setLinkedMap( map1 );
|
||||
scalebar1A->setTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont() ) );
|
||||
scalebar1A->setUnits( Qgis::DistanceUnit::Kilometers );
|
||||
scalebar1A->setUnitsPerSegment( 10000 );
|
||||
scalebar1A->setNumberOfSegmentsLeft( 0 );
|
||||
scalebar1A->setNumberOfSegments( 2 );
|
||||
scalebar1A->setHeight( 5 );
|
||||
scalebar1A->setSubdivisionsHeight( 25 ); //ensure subdivisionsHeight is non used in non tick-style scalebars
|
||||
scalebar1A->setMethod( Qgis::ScaleCalculationMethod::HorizontalAverage );
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
scalebar1A->setLineWidth( 1.0 );
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar1A->numericFormat() ) )->setShowThousandsSeparator( false );
|
||||
scalebar1A->setStyle( QStringLiteral( "Single Box" ) );
|
||||
|
||||
QgsLayoutItemMap *map2 = new QgsLayoutItemMap( &l );
|
||||
map2->attemptSetSceneRect( QRectF( 20, 20, 150, 150 ) );
|
||||
map2->setFrameEnabled( false );
|
||||
map2->setVisibility( false );
|
||||
l.addLayoutItem( map2 );
|
||||
// only scale at top of map can be calculated
|
||||
map2->setExtent( QgsRectangle( -100, -280, 100, -80 ) );
|
||||
map2->setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
|
||||
|
||||
QgsLayoutItemScaleBar *scalebar2 = new QgsLayoutItemScaleBar( &l );
|
||||
scalebar2->attemptSetSceneRect( QRectF( 20, 50, 50, 20 ) );
|
||||
l.addLayoutItem( scalebar2 );
|
||||
scalebar2->setLinkedMap( map2 );
|
||||
scalebar2->setTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont() ) );
|
||||
scalebar2->setUnits( Qgis::DistanceUnit::Kilometers );
|
||||
scalebar2->setUnitsPerSegment( 1000 );
|
||||
scalebar2->setNumberOfSegmentsLeft( 0 );
|
||||
scalebar2->setNumberOfSegments( 2 );
|
||||
scalebar2->setHeight( 5 );
|
||||
scalebar2->setSubdivisionsHeight( 25 ); //ensure subdivisionsHeight is non used in non tick-style scalebars
|
||||
scalebar2->setMethod( Qgis::ScaleCalculationMethod::HorizontalTop );
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
scalebar2->setLineWidth( 1.0 );
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar2->numericFormat() ) )->setShowThousandsSeparator( false );
|
||||
scalebar2->setStyle( QStringLiteral( "Single Box" ) );
|
||||
|
||||
QgsLayoutItemScaleBar *scalebar2A = new QgsLayoutItemScaleBar( &l );
|
||||
scalebar2A->attemptSetSceneRect( QRectF( 20, 70, 50, 20 ) );
|
||||
l.addLayoutItem( scalebar2A );
|
||||
scalebar2A->setLinkedMap( map2 );
|
||||
scalebar2A->setTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont() ) );
|
||||
scalebar2A->setUnits( Qgis::DistanceUnit::Kilometers );
|
||||
scalebar2A->setUnitsPerSegment( 1000 );
|
||||
scalebar2A->setNumberOfSegmentsLeft( 0 );
|
||||
scalebar2A->setNumberOfSegments( 2 );
|
||||
scalebar2A->setHeight( 5 );
|
||||
scalebar2A->setSubdivisionsHeight( 25 ); //ensure subdivisionsHeight is non used in non tick-style scalebars
|
||||
scalebar2A->setMethod( Qgis::ScaleCalculationMethod::HorizontalAverage );
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
scalebar2A->setLineWidth( 1.0 );
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar2A->numericFormat() ) )->setShowThousandsSeparator( false );
|
||||
scalebar2A->setStyle( QStringLiteral( "Single Box" ) );
|
||||
|
||||
QgsLayoutItemMap *map3 = new QgsLayoutItemMap( &l );
|
||||
map3->attemptSetSceneRect( QRectF( 20, 90, 150, 150 ) );
|
||||
map3->setFrameEnabled( false );
|
||||
map3->setVisibility( false );
|
||||
l.addLayoutItem( map3 );
|
||||
// only scale at bottom of map can be calculated
|
||||
map3->setExtent( QgsRectangle( -100, 80, 100, 280 ) );
|
||||
map3->setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
|
||||
|
||||
QgsLayoutItemScaleBar *scalebar3 = new QgsLayoutItemScaleBar( &l );
|
||||
scalebar3->attemptSetSceneRect( QRectF( 20, 90, 50, 20 ) );
|
||||
l.addLayoutItem( scalebar3 );
|
||||
scalebar3->setLinkedMap( map3 );
|
||||
scalebar3->setTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont() ) );
|
||||
scalebar3->setUnits( Qgis::DistanceUnit::Kilometers );
|
||||
scalebar3->setUnitsPerSegment( 1000 );
|
||||
scalebar3->setNumberOfSegmentsLeft( 0 );
|
||||
scalebar3->setNumberOfSegments( 2 );
|
||||
scalebar3->setHeight( 5 );
|
||||
scalebar3->setSubdivisionsHeight( 25 ); //ensure subdivisionsHeight is non used in non tick-style scalebars
|
||||
scalebar3->setMethod( Qgis::ScaleCalculationMethod::HorizontalBottom );
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
scalebar3->setLineWidth( 1.0 );
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar3->numericFormat() ) )->setShowThousandsSeparator( false );
|
||||
scalebar3->setStyle( QStringLiteral( "Single Box" ) );
|
||||
|
||||
QgsLayoutItemScaleBar *scalebar3A = new QgsLayoutItemScaleBar( &l );
|
||||
scalebar3A->attemptSetSceneRect( QRectF( 20, 110, 50, 20 ) );
|
||||
l.addLayoutItem( scalebar3A );
|
||||
scalebar3A->setLinkedMap( map3 );
|
||||
scalebar3A->setTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont() ) );
|
||||
scalebar3A->setUnits( Qgis::DistanceUnit::Kilometers );
|
||||
scalebar3A->setUnitsPerSegment( 1000 );
|
||||
scalebar3A->setNumberOfSegmentsLeft( 0 );
|
||||
scalebar3A->setNumberOfSegments( 2 );
|
||||
scalebar3A->setHeight( 5 );
|
||||
scalebar3A->setSubdivisionsHeight( 25 ); //ensure subdivisionsHeight is non used in non tick-style scalebars
|
||||
scalebar3A->setMethod( Qgis::ScaleCalculationMethod::HorizontalAverage );
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
scalebar3A->setLineWidth( 1.0 );
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar3A->numericFormat() ) )->setShowThousandsSeparator( false );
|
||||
scalebar3A->setStyle( QStringLiteral( "Single Box" ) );
|
||||
|
||||
QgsLayoutItemMap *map4 = new QgsLayoutItemMap( &l );
|
||||
map4->attemptSetSceneRect( QRectF( 20, 90, 150, 150 ) );
|
||||
map4->setFrameEnabled( false );
|
||||
map4->setVisibility( false );
|
||||
l.addLayoutItem( map4 );
|
||||
// scale is valid everywhere
|
||||
map4->setExtent( QgsRectangle( -80, -80, 80, 80 ) );
|
||||
map4->setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
|
||||
|
||||
QgsLayoutItemScaleBar *scalebar4 = new QgsLayoutItemScaleBar( &l );
|
||||
scalebar4->attemptSetSceneRect( QRectF( 20, 130, 50, 20 ) );
|
||||
l.addLayoutItem( scalebar4 );
|
||||
scalebar4->setLinkedMap( map4 );
|
||||
scalebar4->setTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont() ) );
|
||||
scalebar4->setUnits( Qgis::DistanceUnit::Kilometers );
|
||||
scalebar4->setUnitsPerSegment( 5000 );
|
||||
scalebar4->setNumberOfSegmentsLeft( 0 );
|
||||
scalebar4->setNumberOfSegments( 2 );
|
||||
scalebar4->setHeight( 5 );
|
||||
scalebar4->setSubdivisionsHeight( 25 ); //ensure subdivisionsHeight is non used in non tick-style scalebars
|
||||
scalebar4->setMethod( Qgis::ScaleCalculationMethod::HorizontalAverage );
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
scalebar4->setLineWidth( 1.0 );
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar4->numericFormat() ) )->setShowThousandsSeparator( false );
|
||||
scalebar4->setStyle( QStringLiteral( "Single Box" ) );
|
||||
|
||||
QGSVERIFYLAYOUTCHECK( QStringLiteral( "scalebar_method" ), &l );
|
||||
}
|
||||
|
||||
|
||||
QGSTEST_MAIN( TestQgsLayoutScaleBar )
|
||||
#include "testqgslayoutscalebar.moc"
|
||||
|
||||
BIN
tests/testdata/control_images/layout_scalebar/expected_scalebar_method/expected_scalebar_method.png
vendored
Normal file
BIN
tests/testdata/control_images/layout_scalebar/expected_scalebar_method/expected_scalebar_method.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
Loading…
x
Reference in New Issue
Block a user