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
Returns a reference to the widget's configuration menu, which can be used
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
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.
.. 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
signals:

View File

@ -59,6 +59,15 @@ Returns a reference to the slider component of the widget.
%Docstring
Returns a reference to the widget's configuration menu, which can be used
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
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.
.. 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
signals:

View File

@ -102,7 +102,20 @@ QgsDoubleRange QgsElevationControllerWidget::range() const
if ( snappedLower == mSlider->lowerValue() && snappedUpper == mSlider->upperValue() )
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
@ -180,6 +193,27 @@ void QgsElevationControllerWidget::updateWidgetMask()
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
//

View File

@ -97,6 +97,15 @@ class GUI_EXPORT QgsElevationControllerWidget : public QWidget
*/
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:
/**
@ -114,6 +123,15 @@ class GUI_EXPORT QgsElevationControllerWidget : public QWidget
*/
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:
/**
@ -134,6 +152,7 @@ class GUI_EXPORT QgsElevationControllerWidget : public QWidget
QgsElevationControllerLabels *mSliderLabels = nullptr;
QgsDoubleRange mRangeLimits;
QgsDoubleRange mCurrentRange;
double mFixedRangeWidth = -1;
int mBlockSliderChanges = 0;
double mSliderPrecision = 100;

View File

@ -108,6 +108,20 @@ class TestQgsElevationControllerWidget(QgisTestCase):
self.assertAlmostEqual(w.range().lower(), 459.644, 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):
"""
Test interaction of widget with project