Skip to content

Commit ae638d2

Browse files
committedMay 29, 2023
Allow setting distance unit for layout elevation profile items
1 parent bb5cfb8 commit ae638d2

File tree

8 files changed

+357
-69
lines changed

8 files changed

+357
-69
lines changed
 

‎python/core/auto_generated/layout/qgslayoutitemelevationprofile.sip.in

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,24 @@ Returns the profile request used to generate the elevation profile.
152152
virtual void paint( QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget );
153153

154154

155+
Qgis::DistanceUnit distanceUnit() const;
156+
%Docstring
157+
Returns the units for the distance axis.
158+
159+
.. seealso:: :py:func:`setDistanceUnit`
160+
161+
.. versionadded:: 3.32
162+
%End
163+
164+
void setDistanceUnit( Qgis::DistanceUnit unit );
165+
%Docstring
166+
Sets the ``unit`` for the distance axis.
167+
168+
.. seealso:: :py:func:`distanceUnit`
169+
170+
.. versionadded:: 3.32
171+
%End
172+
155173
public slots:
156174

157175
virtual void refresh();

‎src/core/layout/qgslayoutitemelevationprofile.cpp

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,13 @@ class QgsLayoutItemElevationProfilePlot : public Qgs2DPlot
5555
if ( mRenderer )
5656
{
5757
rc.painter()->translate( plotArea.left(), plotArea.top() );
58-
mRenderer->render( rc, plotArea.width(), plotArea.height(), xMinimum(), xMaximum(), yMinimum(), yMaximum() );
58+
mRenderer->render( rc, plotArea.width(), plotArea.height(), xMinimum() * xScale, xMaximum() * xScale, yMinimum(), yMaximum() );
5959
rc.painter()->translate( -plotArea.left(), -plotArea.top() );
6060
}
6161
}
6262

63+
double xScale = 1;
64+
6365
private:
6466

6567
QgsProfilePlotRenderer *mRenderer = nullptr;
@@ -641,7 +643,9 @@ void QgsLayoutItemElevationProfile::paint( QPainter *painter, const QStyleOption
641643
layoutSize *= dotsPerMM; // output size will be in dots (pixels)
642644
painter->scale( 1 / dotsPerMM, 1 / dotsPerMM ); // scale painter from mm to dots
643645

644-
const double mapUnitsPerPixel = static_cast<double>( mPlot->xMaximum() - mPlot->xMinimum() ) / layoutSize.width();
646+
mPlot->xScale = QgsUnitTypes::fromUnitToUnitFactor( mDistanceUnit, mCrs.mapUnits() );
647+
648+
const double mapUnitsPerPixel = static_cast<double>( mPlot->xMaximum() - mPlot->xMinimum() ) * mPlot->xScale / layoutSize.width();
645649
rc.setMapToPixel( QgsMapToPixel( mapUnitsPerPixel ) );
646650

647651
QList< QgsAbstractProfileSource * > sources;
@@ -653,6 +657,7 @@ void QgsLayoutItemElevationProfile::paint( QPainter *painter, const QStyleOption
653657

654658
QgsProfilePlotRenderer renderer( sources, profileRequest() );
655659

660+
656661
// TODO
657662
// we should be able to call renderer.start()/renderer.waitForFinished() here and
658663
// benefit from parallel source generation. BUT
@@ -722,6 +727,8 @@ bool QgsLayoutItemElevationProfile::writePropertiesToElement( QDomElement &layou
722727
layoutProfileElem.appendChild( plotElement );
723728
}
724729

730+
layoutProfileElem.setAttribute( QStringLiteral( "distanceUnit" ), qgsEnumValueToKey( mDistanceUnit ) );
731+
725732
layoutProfileElem.setAttribute( QStringLiteral( "tolerance" ), mTolerance );
726733
layoutProfileElem.setAttribute( QStringLiteral( "atlasDriven" ), mAtlasDriven ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
727734
if ( mCrs.isValid() )
@@ -768,6 +775,8 @@ bool QgsLayoutItemElevationProfile::readPropertiesFromElement( const QDomElement
768775
}
769776
mCrs = crs;
770777

778+
setDistanceUnit( qgsEnumKeyToValue( itemElem.attribute( QStringLiteral( "distanceUnit" ) ), mCrs.mapUnits() ) );
779+
771780
const QDomNodeList curveNodeList = itemElem.elementsByTagName( QStringLiteral( "curve" ) );
772781
if ( !curveNodeList.isEmpty() )
773782
{
@@ -892,7 +901,9 @@ void QgsLayoutItemElevationProfile::profileGenerationFinished()
892901

893902
QgsRenderContext rc = QgsLayoutUtils::createRenderContextForLayout( mLayout, mPainter.get() );
894903

895-
const double mapUnitsPerPixel = static_cast< double >( mPlot->xMaximum() - mPlot->xMinimum() ) /
904+
mPlot->xScale = QgsUnitTypes::fromUnitToUnitFactor( mDistanceUnit, mCrs.mapUnits() );
905+
906+
const double mapUnitsPerPixel = static_cast< double >( mPlot->xMaximum() - mPlot->xMinimum() ) * mPlot->xScale /
896907
mCacheRenderingImage->size().width();
897908
rc.setMapToPixel( QgsMapToPixel( mapUnitsPerPixel ) );
898909

@@ -911,3 +922,36 @@ void QgsLayoutItemElevationProfile::profileGenerationFinished()
911922
update();
912923
}
913924

925+
Qgis::DistanceUnit QgsLayoutItemElevationProfile::distanceUnit() const
926+
{
927+
return mDistanceUnit;
928+
}
929+
930+
void QgsLayoutItemElevationProfile::setDistanceUnit( Qgis::DistanceUnit unit )
931+
{
932+
mDistanceUnit = unit;
933+
934+
switch ( mDistanceUnit )
935+
{
936+
case Qgis::DistanceUnit::Meters:
937+
case Qgis::DistanceUnit::Kilometers:
938+
case Qgis::DistanceUnit::Feet:
939+
case Qgis::DistanceUnit::NauticalMiles:
940+
case Qgis::DistanceUnit::Yards:
941+
case Qgis::DistanceUnit::Miles:
942+
case Qgis::DistanceUnit::Centimeters:
943+
case Qgis::DistanceUnit::Millimeters:
944+
case Qgis::DistanceUnit::Inches:
945+
mPlot->xAxis().setLabelSuffix( QgsUnitTypes::toAbbreviatedString( mDistanceUnit ) );
946+
break;
947+
948+
case Qgis::DistanceUnit::Degrees:
949+
mPlot->xAxis().setLabelSuffix( QObject::tr( "°" ) );
950+
break;
951+
952+
case Qgis::DistanceUnit::Unknown:
953+
mPlot->xAxis().setLabelSuffix( QString() );
954+
break;
955+
}
956+
}
957+

‎src/core/layout/qgslayoutitemelevationprofile.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,22 @@ class CORE_EXPORT QgsLayoutItemElevationProfile: public QgsLayoutItem
167167

168168
void paint( QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget ) override;
169169

170+
/**
171+
* Returns the units for the distance axis.
172+
*
173+
* \see setDistanceUnit()
174+
* \since QGIS 3.32
175+
*/
176+
Qgis::DistanceUnit distanceUnit() const;
177+
178+
/**
179+
* Sets the \a unit for the distance axis.
180+
*
181+
* \see distanceUnit()
182+
* \since QGIS 3.32
183+
*/
184+
void setDistanceUnit( Qgis::DistanceUnit unit );
185+
170186
public slots:
171187

172188
void refresh() override;
@@ -188,6 +204,7 @@ class CORE_EXPORT QgsLayoutItemElevationProfile: public QgsLayoutItem
188204
QList< QgsMapLayerRef > mLayers;
189205

190206
QgsCoordinateReferenceSystem mCrs;
207+
Qgis::DistanceUnit mDistanceUnit = Qgis::DistanceUnit::Unknown;
191208
std::unique_ptr< QgsCurve> mCurve;
192209
bool mAtlasDriven = false;
193210

‎src/gui/elevation/qgselevationprofilecanvas.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ class QgsElevationProfilePlotItem : public Qgs2DPlot, public QgsPlotCanvasItem
227227
}
228228

229229
QgsProject *mProject = nullptr;
230-
double mXScaleFactor = 1.0 / 1000;
230+
double mXScaleFactor = 1.0;
231231

232232
Qgis::DistanceUnit mDistanceUnit = Qgis::DistanceUnit::Unknown;
233233

‎src/gui/layout/qgslayoutelevationprofilewidget.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "qgscurve.h"
3333
#include "qgslayoutatlas.h"
3434
#include "qgslayoutreportcontext.h"
35+
#include "qgsgui.h"
3536
#include <QMenu>
3637

3738
std::function< void( QgsLayoutElevationProfileWidget *, QMenu * ) > QgsLayoutElevationProfileWidget::sBuildCopyMenuFunction = []( QgsLayoutElevationProfileWidget *, QMenu * ) {};
@@ -437,6 +438,62 @@ QgsLayoutElevationProfileWidget::QgsLayoutElevationProfileWidget( QgsLayoutItemE
437438
mProfile->endCommand();
438439
} );
439440

441+
for ( Qgis::DistanceUnit unit :
442+
{
443+
Qgis::DistanceUnit::Kilometers,
444+
Qgis::DistanceUnit::Meters,
445+
Qgis::DistanceUnit::Centimeters,
446+
Qgis::DistanceUnit::Millimeters,
447+
Qgis::DistanceUnit::Miles,
448+
Qgis::DistanceUnit::NauticalMiles,
449+
Qgis::DistanceUnit::Yards,
450+
Qgis::DistanceUnit::Feet,
451+
Qgis::DistanceUnit::Inches,
452+
Qgis::DistanceUnit::Degrees,
453+
} )
454+
{
455+
QString title;
456+
if ( ( QgsGui::higFlags() & QgsGui::HigDialogTitleIsTitleCase ) )
457+
{
458+
title = QgsStringUtils::capitalize( QgsUnitTypes::toString( unit ), Qgis::Capitalization::TitleCase );
459+
}
460+
else
461+
{
462+
title = QgsUnitTypes::toString( unit );
463+
}
464+
mDistanceUnitCombo->addItem( title, QVariant::fromValue( unit ) );
465+
}
466+
467+
connect( mDistanceUnitCombo, qOverload< int >( &QComboBox::currentIndexChanged ), this, [ = ]( int )
468+
{
469+
if ( !mProfile || mBlockChanges )
470+
return;
471+
472+
mProfile->beginCommand( tr( "Change Profile Chart Units" ) );
473+
mProfile->setDistanceUnit( mDistanceUnitCombo->currentData().value< Qgis::DistanceUnit >() );
474+
mProfile->invalidateCache();
475+
mProfile->update();
476+
mProfile->endCommand();
477+
} );
478+
479+
mDistanceLabelsCombo->addItem( tr( "None" ), QVariant::fromValue( Qgis::PlotAxisSuffixPlacement::NoLabels ) );
480+
mDistanceLabelsCombo->addItem( tr( "Every Value" ), QVariant::fromValue( Qgis::PlotAxisSuffixPlacement::EveryLabel ) );
481+
mDistanceLabelsCombo->addItem( tr( "First Value" ), QVariant::fromValue( Qgis::PlotAxisSuffixPlacement::FirstLabel ) );
482+
mDistanceLabelsCombo->addItem( tr( "Last Value" ), QVariant::fromValue( Qgis::PlotAxisSuffixPlacement::LastLabel ) );
483+
mDistanceLabelsCombo->addItem( tr( "First and Last Values" ), QVariant::fromValue( Qgis::PlotAxisSuffixPlacement::FirstAndLastLabels ) );
484+
connect( mDistanceLabelsCombo, qOverload< int >( &QComboBox::currentIndexChanged ), this, [ = ]( int )
485+
{
486+
if ( !mProfile || mBlockChanges )
487+
return;
488+
489+
mProfile->beginCommand( tr( "Change Profile Chart Label Placement" ) );
490+
mProfile->plot()->xAxis().setLabelSuffixPlacement( mDistanceLabelsCombo->currentData().value< Qgis::PlotAxisSuffixPlacement >() );
491+
mProfile->invalidateCache();
492+
mProfile->update();
493+
mProfile->endCommand();
494+
} );
495+
496+
440497
registerDataDefinedButton( mDDBtnTolerance, QgsLayoutObject::ElevationProfileTolerance );
441498
registerDataDefinedButton( mDDBtnMinDistance, QgsLayoutObject::ElevationProfileMinimumDistance );
442499
registerDataDefinedButton( mDDBtnMaxDistance, QgsLayoutObject::ElevationProfileMaximumDistance );
@@ -542,6 +599,12 @@ void QgsLayoutElevationProfileWidget::copySettingsFromProfileCanvas( QgsElevatio
542599
mSpinTolerance->setValue( canvas->tolerance() );
543600
mProfile->setTolerance( canvas->tolerance() );
544601

602+
mProfile->setDistanceUnit( canvas->distanceUnit() );
603+
mDistanceUnitCombo->setCurrentIndex( mDistanceUnitCombo->findData( QVariant::fromValue( canvas->distanceUnit() ) ) );
604+
605+
mProfile->plot()->xAxis().setLabelSuffixPlacement( canvas->plot().xAxis().labelSuffixPlacement() );
606+
mDistanceLabelsCombo->setCurrentIndex( mDistanceLabelsCombo->findData( QVariant::fromValue( canvas->plot().xAxis().labelSuffixPlacement() ) ) );
607+
545608
if ( const QgsCurve *curve = canvas->profileCurve() )
546609
mProfile->setProfileCurve( curve->clone() );
547610

@@ -656,6 +719,9 @@ void QgsLayoutElevationProfileWidget::setGuiElementValues()
656719
mDistanceAxisLabelFontButton->setTextFormat( mProfile->plot()->xAxis().textFormat() );
657720
mElevationAxisLabelFontButton->setTextFormat( mProfile->plot()->yAxis().textFormat() );
658721

722+
mDistanceUnitCombo->setCurrentIndex( mDistanceUnitCombo->findData( QVariant::fromValue( mProfile->distanceUnit() ) ) );
723+
mDistanceLabelsCombo->setCurrentIndex( mDistanceLabelsCombo->findData( QVariant::fromValue( mProfile->plot()->xAxis().labelSuffixPlacement() ) ) );
724+
659725
mDistanceAxisMajorIntervalSpin->setValue( mProfile->plot()->xAxis().gridIntervalMajor() );
660726
mDistanceAxisMinorIntervalSpin->setValue( mProfile->plot()->xAxis().gridIntervalMinor() );
661727
mDistanceAxisLabelIntervalSpin->setValue( mProfile->plot()->xAxis().labelInterval() );

‎src/ui/layout/qgslayoutelevationprofilewidgetbase.ui

Lines changed: 128 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,9 @@
7777
<property name="geometry">
7878
<rect>
7979
<x>0</x>
80-
<y>0</y>
80+
<y>-51</y>
8181
<width>548</width>
82-
<height>1375</height>
82+
<height>1439</height>
8383
</rect>
8484
</property>
8585
<property name="sizePolicy">
@@ -265,81 +265,88 @@
265265
<string>Distance Axis</string>
266266
</property>
267267
<layout class="QGridLayout" name="gridLayout_2" columnstretch="1,0,2,0">
268-
<item row="6" column="2" colspan="2">
269-
<widget class="QgsFontButton" name="mDistanceAxisLabelFontButton">
268+
<item row="5" column="3">
269+
<widget class="QgsPropertyOverrideButton" name="mDDBtnDistanceLabelInterval">
270+
<property name="text">
271+
<string>…</string>
272+
</property>
273+
</widget>
274+
</item>
275+
<item row="2" column="2" colspan="2">
276+
<widget class="QgsSymbolButton" name="mDistanceAxisMajorLinesSymbolButton">
270277
<property name="sizePolicy">
271-
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
278+
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
272279
<horstretch>0</horstretch>
273280
<verstretch>0</verstretch>
274281
</sizepolicy>
275282
</property>
276283
<property name="text">
277-
<string>Font</string>
284+
<string>Change…</string>
278285
</property>
279286
</widget>
280287
</item>
281-
<item row="1" column="0">
282-
<widget class="QLabel" name="label_4">
288+
<item row="6" column="2" colspan="2">
289+
<widget class="QPushButton" name="mDistanceAxisLabelFormatButton">
283290
<property name="text">
284-
<string>Major grid lines</string>
291+
<string>Customize</string>
285292
</property>
286293
</widget>
287294
</item>
288-
<item row="5" column="2" colspan="2">
289-
<widget class="QPushButton" name="mDistanceAxisLabelFormatButton">
290-
<property name="text">
291-
<string>Customize</string>
295+
<item row="1" column="2">
296+
<widget class="QgsDoubleSpinBox" name="mDistanceAxisMajorIntervalSpin">
297+
<property name="decimals">
298+
<number>6</number>
299+
</property>
300+
<property name="minimum">
301+
<double>0.000001000000000</double>
302+
</property>
303+
<property name="maximum">
304+
<double>999999999999.000000000000000</double>
292305
</property>
293306
</widget>
294307
</item>
295-
<item row="0" column="0">
296-
<widget class="QLabel" name="label_6">
308+
<item row="5" column="0" colspan="2">
309+
<widget class="QLabel" name="label_8">
297310
<property name="text">
298-
<string>Major interval</string>
311+
<string>Label interval</string>
299312
</property>
300313
</widget>
301314
</item>
302-
<item row="2" column="3">
303-
<widget class="QgsPropertyOverrideButton" name="mDDBtnDistanceMinorInterval">
315+
<item row="0" column="0">
316+
<widget class="QLabel" name="label_26">
304317
<property name="text">
305-
<string></string>
318+
<string>Unit</string>
306319
</property>
307320
</widget>
308321
</item>
309-
<item row="1" column="2" colspan="2">
310-
<widget class="QgsSymbolButton" name="mDistanceAxisMajorLinesSymbolButton">
311-
<property name="sizePolicy">
312-
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
313-
<horstretch>0</horstretch>
314-
<verstretch>0</verstretch>
315-
</sizepolicy>
316-
</property>
322+
<item row="7" column="0">
323+
<widget class="QLabel" name="label_9">
317324
<property name="text">
318-
<string>Change…</string>
325+
<string>Label font</string>
319326
</property>
320327
</widget>
321328
</item>
322-
<item row="2" column="2">
323-
<widget class="QgsDoubleSpinBox" name="mDistanceAxisMinorIntervalSpin">
324-
<property name="decimals">
325-
<number>6</number>
326-
</property>
327-
<property name="minimum">
328-
<double>0.000001000000000</double>
329-
</property>
330-
<property name="maximum">
331-
<double>999999999999.000000000000000</double>
329+
<item row="4" column="0">
330+
<widget class="QLabel" name="label_5">
331+
<property name="text">
332+
<string>Minor grid lines</string>
332333
</property>
333334
</widget>
334335
</item>
335-
<item row="4" column="3">
336-
<widget class="QgsPropertyOverrideButton" name="mDDBtnDistanceLabelInterval">
336+
<item row="7" column="2" colspan="2">
337+
<widget class="QgsFontButton" name="mDistanceAxisLabelFontButton">
338+
<property name="sizePolicy">
339+
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
340+
<horstretch>0</horstretch>
341+
<verstretch>0</verstretch>
342+
</sizepolicy>
343+
</property>
337344
<property name="text">
338-
<string></string>
345+
<string>Font</string>
339346
</property>
340347
</widget>
341348
</item>
342-
<item row="3" column="2" colspan="2">
349+
<item row="4" column="2" colspan="2">
343350
<widget class="QgsSymbolButton" name="mDistanceAxisMinorLinesSymbolButton">
344351
<property name="sizePolicy">
345352
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@@ -352,8 +359,8 @@
352359
</property>
353360
</widget>
354361
</item>
355-
<item row="4" column="2">
356-
<widget class="QgsDoubleSpinBox" name="mDistanceAxisLabelIntervalSpin">
362+
<item row="3" column="2">
363+
<widget class="QgsDoubleSpinBox" name="mDistanceAxisMinorIntervalSpin">
357364
<property name="decimals">
358365
<number>6</number>
359366
</property>
@@ -365,15 +372,29 @@
365372
</property>
366373
</widget>
367374
</item>
368-
<item row="2" column="0" colspan="2">
375+
<item row="1" column="0">
376+
<widget class="QLabel" name="label_6">
377+
<property name="text">
378+
<string>Major interval</string>
379+
</property>
380+
</widget>
381+
</item>
382+
<item row="1" column="3">
383+
<widget class="QgsPropertyOverrideButton" name="mDDBtnDistanceMajorInterval">
384+
<property name="text">
385+
<string>…</string>
386+
</property>
387+
</widget>
388+
</item>
389+
<item row="3" column="0" colspan="2">
369390
<widget class="QLabel" name="label_7">
370391
<property name="text">
371392
<string>Minor interval</string>
372393
</property>
373394
</widget>
374395
</item>
375-
<item row="0" column="2">
376-
<widget class="QgsDoubleSpinBox" name="mDistanceAxisMajorIntervalSpin">
396+
<item row="5" column="2">
397+
<widget class="QgsDoubleSpinBox" name="mDistanceAxisLabelIntervalSpin">
377398
<property name="decimals">
378399
<number>6</number>
379400
</property>
@@ -385,41 +406,40 @@
385406
</property>
386407
</widget>
387408
</item>
388-
<item row="0" column="3">
389-
<widget class="QgsPropertyOverrideButton" name="mDDBtnDistanceMajorInterval">
390-
<property name="text">
391-
<string>…</string>
392-
</property>
393-
</widget>
394-
</item>
395409
<item row="6" column="0">
396-
<widget class="QLabel" name="label_9">
410+
<widget class="QLabel" name="label_10">
397411
<property name="text">
398-
<string>Label font</string>
412+
<string>Label format</string>
399413
</property>
400414
</widget>
401415
</item>
402-
<item row="5" column="0">
403-
<widget class="QLabel" name="label_10">
416+
<item row="0" column="2" colspan="2">
417+
<widget class="QComboBox" name="mDistanceUnitCombo"/>
418+
</item>
419+
<item row="3" column="3">
420+
<widget class="QgsPropertyOverrideButton" name="mDDBtnDistanceMinorInterval">
404421
<property name="text">
405-
<string>Label format</string>
422+
<string></string>
406423
</property>
407424
</widget>
408425
</item>
409-
<item row="3" column="0">
410-
<widget class="QLabel" name="label_5">
426+
<item row="2" column="0">
427+
<widget class="QLabel" name="label_4">
411428
<property name="text">
412-
<string>Minor grid lines</string>
429+
<string>Major grid lines</string>
413430
</property>
414431
</widget>
415432
</item>
416-
<item row="4" column="0" colspan="2">
417-
<widget class="QLabel" name="label_8">
433+
<item row="8" column="0">
434+
<widget class="QLabel" name="label_28">
418435
<property name="text">
419-
<string>Label interval</string>
436+
<string>Distance labels</string>
420437
</property>
421438
</widget>
422439
</item>
440+
<item row="8" column="2" colspan="2">
441+
<widget class="QComboBox" name="mDistanceLabelsCombo"/>
442+
</item>
423443
</layout>
424444
</widget>
425445
</item>
@@ -787,6 +807,49 @@
787807
</customwidgets>
788808
<tabstops>
789809
<tabstop>scrollArea</tabstop>
810+
<tabstop>mSpinTolerance</tabstop>
811+
<tabstop>mDDBtnTolerance</tabstop>
812+
<tabstop>mCheckControlledByAtlas</tabstop>
813+
<tabstop>mSpinMinElevation</tabstop>
814+
<tabstop>mSpinMinDistance</tabstop>
815+
<tabstop>mSpinMaxDistance</tabstop>
816+
<tabstop>mSpinMaxElevation</tabstop>
817+
<tabstop>mDDBtnMinDistance</tabstop>
818+
<tabstop>mDDBtnMaxDistance</tabstop>
819+
<tabstop>mDDBtnMinElevation</tabstop>
820+
<tabstop>mDistanceUnitCombo</tabstop>
821+
<tabstop>mDistanceAxisMajorIntervalSpin</tabstop>
822+
<tabstop>mDDBtnDistanceMajorInterval</tabstop>
823+
<tabstop>mDistanceAxisMajorLinesSymbolButton</tabstop>
824+
<tabstop>mDistanceAxisMinorIntervalSpin</tabstop>
825+
<tabstop>mDDBtnDistanceMinorInterval</tabstop>
826+
<tabstop>mDistanceAxisMinorLinesSymbolButton</tabstop>
827+
<tabstop>mDistanceAxisLabelIntervalSpin</tabstop>
828+
<tabstop>mDDBtnDistanceLabelInterval</tabstop>
829+
<tabstop>mDistanceAxisLabelFormatButton</tabstop>
830+
<tabstop>mDistanceAxisLabelFontButton</tabstop>
831+
<tabstop>mDistanceLabelsCombo</tabstop>
832+
<tabstop>mElevationAxisMajorIntervalSpin</tabstop>
833+
<tabstop>mDDBtnElevationMajorInterval</tabstop>
834+
<tabstop>mElevationAxisMajorLinesSymbolButton</tabstop>
835+
<tabstop>mElevationAxisMinorIntervalSpin</tabstop>
836+
<tabstop>mDDBtnElevationMinorInterval</tabstop>
837+
<tabstop>mElevationAxisMinorLinesSymbolButton</tabstop>
838+
<tabstop>mElevationAxisLabelIntervalSpin</tabstop>
839+
<tabstop>mDDBtnElevationLabelInterval</tabstop>
840+
<tabstop>mElevationAxisLabelFormatButton</tabstop>
841+
<tabstop>mElevationAxisLabelFontButton</tabstop>
842+
<tabstop>mChartBackgroundSymbolButton</tabstop>
843+
<tabstop>mChartBorderSymbolButton</tabstop>
844+
<tabstop>mSpinLeftMargin</tabstop>
845+
<tabstop>mDDBtnLeftMargin</tabstop>
846+
<tabstop>mSpinTopMargin</tabstop>
847+
<tabstop>mDDBtnTopMargin</tabstop>
848+
<tabstop>mSpinRightMargin</tabstop>
849+
<tabstop>mDDBtnRightMargin</tabstop>
850+
<tabstop>mSpinBottomMargin</tabstop>
851+
<tabstop>mDDBtnBottomMargin</tabstop>
852+
<tabstop>mDDBtnMaxElevation</tabstop>
790853
</tabstops>
791854
<resources>
792855
<include location="../../../images/images.qrc"/>

‎tests/src/python/test_qgslayoutelevationprofile.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ def test_settings(self):
122122
profile.setTolerance(101)
123123
self.assertEqual(profile.tolerance(), 101)
124124

125+
profile.setDistanceUnit(Qgis.DistanceUnit.Kilometers)
126+
125127
# test that settings are written/restored
126128
with tempfile.TemporaryDirectory() as temp_dir:
127129
self.assertTrue(project.write(os.path.join(temp_dir, 'p.qgs')))
@@ -135,6 +137,7 @@ def test_settings(self):
135137
self.assertEqual(profile2.crs(), QgsCoordinateReferenceSystem('EPSG:3857'))
136138
self.assertEqual(profile2.tolerance(), 101)
137139
self.assertEqual(profile2.profileCurve().asWkt(), 'LineString (0 0, 10 10)')
140+
self.assertEqual(profile2.distanceUnit(), Qgis.DistanceUnit.Kilometers)
138141

139142
def test_request(self):
140143
"""
@@ -240,6 +243,83 @@ def test_draw(self):
240243
'vector_layer', layout
241244
))
242245

246+
def test_draw_distance_units(self):
247+
"""
248+
Test rendering the layout profile item with distance unit change
249+
"""
250+
vl = QgsVectorLayer('PolygonZ?crs=EPSG:27700', 'lines', 'memory')
251+
self.assertTrue(vl.isValid())
252+
253+
for line in [
254+
'PolygonZ ((321829.48893365426920354 129991.38697145861806348 1, 321847.89668515208177269 129996.63588572069420479 1, 321848.97131609614007175 129979.22330882755341008 1, 321830.31725845142500475 129978.07136809575604275 1, 321829.48893365426920354 129991.38697145861806348 1))',
255+
'PolygonZ ((321920.00953056826256216 129924.58260190498549491 2, 321924.65299345907988027 129908.43546159457764588 2, 321904.78543491888558492 129903.99811821122420952 2, 321900.80605239619035274 129931.39860145389684476 2, 321904.84799937985371798 129931.71552911199978553 2, 321908.93646715773502365 129912.90030360443051904 2, 321914.20495146053144708 129913.67693978428724222 2, 321911.30165811872575432 129923.01272751353099011 2, 321920.00953056826256216 129924.58260190498549491 2))',
256+
'PolygonZ ((321923.10517279652412981 129919.61521573827485554 3, 321922.23537852568551898 129928.3598982143739704 3, 321928.60423935484141111 129934.22530528216157109 3, 321929.39881197665818036 129923.29054521876969375 3, 321930.55804549407912418 129916.53248518184409477 3, 321923.10517279652412981 129919.61521573827485554 3))',
257+
'PolygonZ ((321990.47451346553862095 129909.63588680300745182 4, 321995.04325810901354998 129891.84052284323843196 4, 321989.66826330573530868 129890.5092018858413212 4, 321990.78512359503656626 129886.49917887404444627 4, 321987.37291929306229576 129885.64982962771318853 4, 321985.2254804756375961 129893.81317058412241749 4, 321987.63158903241856024 129894.41078495365218259 4, 321984.34022761805681512 129907.57450046355370432 4, 321990.47451346553862095 129909.63588680300745182 4))',
258+
'PolygonZ ((322103.03910495212767273 129795.91051736124791205 5, 322108.25568856322206557 129804.76113295342656784 5, 322113.29666162584908307 129803.9285887333098799 5, 322117.78645010641776025 129794.48194090687320568 5, 322103.03910495212767273 129795.91051736124791205 5))']:
259+
f = QgsFeature()
260+
f.setGeometry(QgsGeometry.fromWkt(line))
261+
self.assertTrue(vl.dataProvider().addFeature(f))
262+
263+
vl.elevationProperties().setClamping(Qgis.AltitudeClamping.Absolute)
264+
vl.elevationProperties().setExtrusionEnabled(True)
265+
vl.elevationProperties().setExtrusionHeight(7)
266+
fill_symbol = QgsFillSymbol.createSimple({'color': '#ff00ff', 'outline_style': 'no'})
267+
vl.elevationProperties().setRespectLayerSymbology(False)
268+
vl.elevationProperties().setProfileFillSymbol(fill_symbol)
269+
270+
p = QgsProject()
271+
p.addMapLayer(vl)
272+
layout = QgsLayout(p)
273+
layout.initializeDefaults()
274+
275+
profile_item = QgsLayoutItemElevationProfile(layout)
276+
layout.addLayoutItem(profile_item)
277+
profile_item.attemptSetSceneRect(QRectF(10, 10, 180, 180))
278+
279+
curve = QgsLineString()
280+
curve.fromWkt(
281+
'LineString (321897.18831187387695536 129916.86947759155009408, 321942.11597351566888392 129924.94403429214435164)')
282+
283+
profile_item.setProfileCurve(curve)
284+
profile_item.setCrs(vl.crs())
285+
286+
profile_item.plot().setXMaximum(curve.length() / 1000)
287+
profile_item.plot().setYMaximum(14)
288+
289+
profile_item.setDistanceUnit(Qgis.DistanceUnit.Kilometers)
290+
profile_item.plot().xAxis().setLabelSuffixPlacement(Qgis.PlotAxisSuffixPlacement.LastLabel)
291+
profile_item.plot().xAxis().setGridIntervalMajor(0.010)
292+
profile_item.plot().xAxis().setGridIntervalMinor(0.005)
293+
profile_item.plot().xAxis().setGridMajorSymbol(QgsLineSymbol.createSimple({'color': '#ffaaff', 'width': 2}))
294+
profile_item.plot().xAxis().setGridMinorSymbol(
295+
QgsLineSymbol.createSimple({'color': '#ffffaa', 'width': 2}))
296+
297+
format = QgsTextFormat()
298+
format.setFont(QgsFontUtils.getStandardTestFont("Bold"))
299+
format.setSize(20)
300+
format.setNamedStyle("Bold")
301+
format.setColor(QColor(0, 0, 0))
302+
profile_item.plot().xAxis().setTextFormat(format)
303+
profile_item.plot().xAxis().setLabelInterval(0.020)
304+
305+
profile_item.plot().yAxis().setGridIntervalMajor(10)
306+
profile_item.plot().yAxis().setGridIntervalMinor(5)
307+
profile_item.plot().yAxis().setGridMajorSymbol(QgsLineSymbol.createSimple({'color': '#ffffaa', 'width': 2}))
308+
profile_item.plot().yAxis().setGridMinorSymbol(
309+
QgsLineSymbol.createSimple({'color': '#aaffaa', 'width': 2}))
310+
311+
profile_item.plot().yAxis().setTextFormat(format)
312+
profile_item.plot().yAxis().setLabelInterval(10)
313+
314+
profile_item.plot().setChartBorderSymbol(
315+
QgsFillSymbol.createSimple({'style': 'no', 'color': '#aaffaa', 'width_border': 2}))
316+
317+
profile_item.setLayers([vl])
318+
319+
self.assertTrue(self.render_layout_check(
320+
'distance_units', layout
321+
))
322+
243323
def test_draw_map_units(self):
244324
"""
245325
Test rendering the layout profile item using symbols with map unit sizes

0 commit comments

Comments
 (0)
Please sign in to comment.