Add fixed range width option to QgsElevationControllerWidget

This commit is contained in:
Nyall Dawson 2024-03-14 14:54:43 +10:00
parent 2da02f22c1
commit ecc71b4479
5 changed files with 104 additions and 1 deletions

View File

@ -59,6 +59,15 @@ Returns a reference to the slider component of the widget.
%Docstring %Docstring
Returns a reference to the widget's configuration menu, which can be used Returns a reference to the widget's configuration menu, which can be used
to add actions to the menu. to add actions to the menu.
%End
double fixedRangeWidth() const;
%Docstring
Returns the fixed range width, or -1 if no fixed width is set.
A fixed width forces the selected elevation range to have a matching width.
.. seealso:: :py:func:`setFixedRangeWidth`
%End %End
public slots: public slots:
@ -77,6 +86,15 @@ Sets the current visible ``range`` for the widget.
Sets the limits of the elevation range which can be selected by the widget. Sets the limits of the elevation range which can be selected by the widget.
.. seealso:: :py:func:`rangeLimits` .. seealso:: :py:func:`rangeLimits`
%End
void setFixedRangeWidth( double width );
%Docstring
Sets the fixed range ``width``. Set to -1 if no fixed width is desired.
A fixed width forces the selected elevation range to have a matching width.
.. seealso:: :py:func:`fixedRangeWidth`
%End %End
signals: signals:

View File

@ -59,6 +59,15 @@ Returns a reference to the slider component of the widget.
%Docstring %Docstring
Returns a reference to the widget's configuration menu, which can be used Returns a reference to the widget's configuration menu, which can be used
to add actions to the menu. to add actions to the menu.
%End
double fixedRangeWidth() const;
%Docstring
Returns the fixed range width, or -1 if no fixed width is set.
A fixed width forces the selected elevation range to have a matching width.
.. seealso:: :py:func:`setFixedRangeWidth`
%End %End
public slots: public slots:
@ -77,6 +86,15 @@ Sets the current visible ``range`` for the widget.
Sets the limits of the elevation range which can be selected by the widget. Sets the limits of the elevation range which can be selected by the widget.
.. seealso:: :py:func:`rangeLimits` .. seealso:: :py:func:`rangeLimits`
%End
void setFixedRangeWidth( double width );
%Docstring
Sets the fixed range ``width``. Set to -1 if no fixed width is desired.
A fixed width forces the selected elevation range to have a matching width.
.. seealso:: :py:func:`fixedRangeWidth`
%End %End
signals: signals:

View File

@ -102,7 +102,20 @@ QgsDoubleRange QgsElevationControllerWidget::range() const
if ( snappedLower == mSlider->lowerValue() && snappedUpper == mSlider->upperValue() ) if ( snappedLower == mSlider->lowerValue() && snappedUpper == mSlider->upperValue() )
return mCurrentRange; return mCurrentRange;
return QgsDoubleRange( mSlider->lowerValue() / mSliderPrecision, mSlider->upperValue() / mSliderPrecision ); const QgsDoubleRange sliderRange( mSlider->lowerValue() / mSliderPrecision, mSlider->upperValue() / mSliderPrecision );
if ( mFixedRangeWidth >= 0 )
{
// adjust range so that it has exactly the fixed width (given slider int precision the slider range
// will not have the exact fixed width)
if ( sliderRange.upper() + mFixedRangeWidth <= mRangeLimits.upper() )
return QgsDoubleRange( sliderRange.lower(), sliderRange.lower() + mFixedRangeWidth );
else
return QgsDoubleRange( sliderRange.upper() - mFixedRangeWidth, sliderRange.upper() );
}
else
{
return sliderRange;
}
} }
QgsDoubleRange QgsElevationControllerWidget::rangeLimits() const QgsDoubleRange QgsElevationControllerWidget::rangeLimits() const
@ -180,6 +193,27 @@ void QgsElevationControllerWidget::updateWidgetMask()
setMask( reg ); setMask( reg );
} }
double QgsElevationControllerWidget::fixedRangeWidth() const
{
return mFixedRangeWidth;
}
void QgsElevationControllerWidget::setFixedRangeWidth( double width )
{
if ( width == mFixedRangeWidth )
return;
mFixedRangeWidth = width;
if ( mFixedRangeWidth < 0 )
{
mSlider->setFixedRangeWidth( -1 );
}
else
{
mSlider->setFixedRangeWidth( static_cast< int >( std::round( mFixedRangeWidth * mSliderPrecision ) ) );
}
}
// //
// QgsElevationControllerLabels // QgsElevationControllerLabels
// //

View File

@ -97,6 +97,15 @@ class GUI_EXPORT QgsElevationControllerWidget : public QWidget
*/ */
QMenu *menu(); QMenu *menu();
/**
* Returns the fixed range width, or -1 if no fixed width is set.
*
* A fixed width forces the selected elevation range to have a matching width.
*
* \see setFixedRangeWidth()
*/
double fixedRangeWidth() const;
public slots: public slots:
/** /**
@ -114,6 +123,15 @@ class GUI_EXPORT QgsElevationControllerWidget : public QWidget
*/ */
void setRangeLimits( const QgsDoubleRange &limits ); void setRangeLimits( const QgsDoubleRange &limits );
/**
* Sets the fixed range \a width. Set to -1 if no fixed width is desired.
*
* A fixed width forces the selected elevation range to have a matching width.
*
* \see fixedRangeWidth()
*/
void setFixedRangeWidth( double width );
signals: signals:
/** /**
@ -134,6 +152,7 @@ class GUI_EXPORT QgsElevationControllerWidget : public QWidget
QgsElevationControllerLabels *mSliderLabels = nullptr; QgsElevationControllerLabels *mSliderLabels = nullptr;
QgsDoubleRange mRangeLimits; QgsDoubleRange mRangeLimits;
QgsDoubleRange mCurrentRange; QgsDoubleRange mCurrentRange;
double mFixedRangeWidth = -1;
int mBlockSliderChanges = 0; int mBlockSliderChanges = 0;
double mSliderPrecision = 100; double mSliderPrecision = 100;

View File

@ -108,6 +108,20 @@ class TestQgsElevationControllerWidget(QgisTestCase):
self.assertAlmostEqual(w.range().lower(), 459.644, 3) self.assertAlmostEqual(w.range().lower(), 459.644, 3)
self.assertAlmostEqual(w.range().upper(), 729.495, 3) self.assertAlmostEqual(w.range().upper(), 729.495, 3)
def testFixedRangeWidth(self):
"""
Test that fixed range width is correctly handled
"""
w = QgsElevationControllerWidget()
w.setRangeLimits(QgsDoubleRange(100.5, 1000))
w.setFixedRangeWidth(10.0001)
self.assertEqual(w.fixedRangeWidth(), 10.0001)
w.setRange(QgsDoubleRange(130.3, 920.6))
self.assertAlmostEqual(w.range().upper() - w.range().lower(), 10.0001, 6)
w.slider().setLowerValue(50)
self.assertAlmostEqual(w.range().upper() - w.range().lower(), 10.0001, 6)
def test_project_interaction(self): def test_project_interaction(self):
""" """
Test interaction of widget with project Test interaction of widget with project