mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-05 00:09:32 -04:00
Add option to invert the elevation filter widget
If checked, this option reverse the slider in the elevation filter so that the widget goes from high values at the bottom to low values at the top. See justification in https://github.com/qgis/QGIS/issues/56995 Fixes #56995
This commit is contained in:
parent
1698bd3391
commit
6ee262f401
@ -84,20 +84,6 @@ elevation limits associated with the project.
|
||||
.. seealso:: :py:func:`elevationRangeChanged`
|
||||
|
||||
|
||||
.. versionadded:: 3.38
|
||||
%End
|
||||
|
||||
void setElevationFilterRangeSize( double size );
|
||||
%Docstring
|
||||
Sets the fixed size for elevation range filtering in the project, used when interactively filtering by elevation.
|
||||
|
||||
Set to -1 if no fixed elevation range size is desired.
|
||||
|
||||
A fixed size forces the selected elevation range to have a matching difference between
|
||||
the upper and lower elevation.
|
||||
|
||||
.. seealso:: :py:func:`elevationFilterRangeSize`
|
||||
|
||||
.. versionadded:: 3.38
|
||||
%End
|
||||
|
||||
@ -112,6 +98,15 @@ the upper and lower elevation.
|
||||
|
||||
.. seealso:: :py:func:`setElevationFilterRangeSize`
|
||||
|
||||
.. versionadded:: 3.38
|
||||
%End
|
||||
|
||||
bool invertElevationFilter() const;
|
||||
%Docstring
|
||||
Returns ``True`` if the elevation range filter slider should be inverted for this project.
|
||||
|
||||
.. seealso:: :py:func:`setInvertElevationFilter`
|
||||
|
||||
.. versionadded:: 3.38
|
||||
%End
|
||||
|
||||
@ -132,6 +127,29 @@ elevation limits associated with the project.
|
||||
.. seealso:: :py:func:`elevationRangeChanged`
|
||||
|
||||
|
||||
.. versionadded:: 3.38
|
||||
%End
|
||||
|
||||
void setElevationFilterRangeSize( double size );
|
||||
%Docstring
|
||||
Sets the fixed size for elevation range filtering in the project, used when interactively filtering by elevation.
|
||||
|
||||
Set to -1 if no fixed elevation range size is desired.
|
||||
|
||||
A fixed size forces the selected elevation range to have a matching difference between
|
||||
the upper and lower elevation.
|
||||
|
||||
.. seealso:: :py:func:`elevationFilterRangeSize`
|
||||
|
||||
.. versionadded:: 3.38
|
||||
%End
|
||||
|
||||
void setInvertElevationFilter( bool invert );
|
||||
%Docstring
|
||||
Sets whether the elevation range filter slider should be inverted for this project.
|
||||
|
||||
.. seealso:: :py:func:`invertElevationFilter`
|
||||
|
||||
.. versionadded:: 3.38
|
||||
%End
|
||||
|
||||
|
@ -114,6 +114,13 @@ the upper and lower elevation.
|
||||
.. seealso:: :py:func:`fixedRangeSize`
|
||||
|
||||
.. seealso:: :py:func:`fixedRangeSizeChanged`
|
||||
%End
|
||||
|
||||
void setInverted( bool inverted );
|
||||
%Docstring
|
||||
Sets whether the elevation slider should be inverted.
|
||||
|
||||
.. seealso:: :py:func:`invertedChanged`
|
||||
%End
|
||||
|
||||
signals:
|
||||
@ -134,6 +141,13 @@ Emitted when the fixed range size is changed from the widget.
|
||||
.. seealso:: :py:func:`fixedRangeSize`
|
||||
|
||||
.. seealso:: :py:func:`setFixedRangeSize`
|
||||
%End
|
||||
|
||||
void invertedChanged( bool inverted );
|
||||
%Docstring
|
||||
Emitted when the elevation filter slider is inverted.
|
||||
|
||||
.. seealso:: :py:func:`setInverted`
|
||||
%End
|
||||
|
||||
};
|
||||
|
@ -84,20 +84,6 @@ elevation limits associated with the project.
|
||||
.. seealso:: :py:func:`elevationRangeChanged`
|
||||
|
||||
|
||||
.. versionadded:: 3.38
|
||||
%End
|
||||
|
||||
void setElevationFilterRangeSize( double size );
|
||||
%Docstring
|
||||
Sets the fixed size for elevation range filtering in the project, used when interactively filtering by elevation.
|
||||
|
||||
Set to -1 if no fixed elevation range size is desired.
|
||||
|
||||
A fixed size forces the selected elevation range to have a matching difference between
|
||||
the upper and lower elevation.
|
||||
|
||||
.. seealso:: :py:func:`elevationFilterRangeSize`
|
||||
|
||||
.. versionadded:: 3.38
|
||||
%End
|
||||
|
||||
@ -112,6 +98,15 @@ the upper and lower elevation.
|
||||
|
||||
.. seealso:: :py:func:`setElevationFilterRangeSize`
|
||||
|
||||
.. versionadded:: 3.38
|
||||
%End
|
||||
|
||||
bool invertElevationFilter() const;
|
||||
%Docstring
|
||||
Returns ``True`` if the elevation range filter slider should be inverted for this project.
|
||||
|
||||
.. seealso:: :py:func:`setInvertElevationFilter`
|
||||
|
||||
.. versionadded:: 3.38
|
||||
%End
|
||||
|
||||
@ -132,6 +127,29 @@ elevation limits associated with the project.
|
||||
.. seealso:: :py:func:`elevationRangeChanged`
|
||||
|
||||
|
||||
.. versionadded:: 3.38
|
||||
%End
|
||||
|
||||
void setElevationFilterRangeSize( double size );
|
||||
%Docstring
|
||||
Sets the fixed size for elevation range filtering in the project, used when interactively filtering by elevation.
|
||||
|
||||
Set to -1 if no fixed elevation range size is desired.
|
||||
|
||||
A fixed size forces the selected elevation range to have a matching difference between
|
||||
the upper and lower elevation.
|
||||
|
||||
.. seealso:: :py:func:`elevationFilterRangeSize`
|
||||
|
||||
.. versionadded:: 3.38
|
||||
%End
|
||||
|
||||
void setInvertElevationFilter( bool invert );
|
||||
%Docstring
|
||||
Sets whether the elevation range filter slider should be inverted for this project.
|
||||
|
||||
.. seealso:: :py:func:`invertElevationFilter`
|
||||
|
||||
.. versionadded:: 3.38
|
||||
%End
|
||||
|
||||
|
@ -114,6 +114,13 @@ the upper and lower elevation.
|
||||
.. seealso:: :py:func:`fixedRangeSize`
|
||||
|
||||
.. seealso:: :py:func:`fixedRangeSizeChanged`
|
||||
%End
|
||||
|
||||
void setInverted( bool inverted );
|
||||
%Docstring
|
||||
Sets whether the elevation slider should be inverted.
|
||||
|
||||
.. seealso:: :py:func:`invertedChanged`
|
||||
%End
|
||||
|
||||
signals:
|
||||
@ -134,6 +141,13 @@ Emitted when the fixed range size is changed from the widget.
|
||||
.. seealso:: :py:func:`fixedRangeSize`
|
||||
|
||||
.. seealso:: :py:func:`setFixedRangeSize`
|
||||
%End
|
||||
|
||||
void invertedChanged( bool inverted );
|
||||
%Docstring
|
||||
Emitted when the elevation filter slider is inverted.
|
||||
|
||||
.. seealso:: :py:func:`setInverted`
|
||||
%End
|
||||
|
||||
};
|
||||
|
@ -68,6 +68,11 @@ void QgsAppCanvasFiltering::setupElevationControllerAction( QAction *action, Qgs
|
||||
{
|
||||
QgsProject::instance()->elevationProperties()->setElevationFilterRangeSize( size );
|
||||
} );
|
||||
controller->setInverted( QgsProject::instance()->elevationProperties()->invertElevationFilter() );
|
||||
connect( controller, &QgsElevationControllerWidget::invertedChanged, this, []( bool inverted )
|
||||
{
|
||||
QgsProject::instance()->elevationProperties()->setInvertElevationFilter( inverted );
|
||||
} );
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -80,6 +80,8 @@ bool QgsProjectElevationProperties::readXml( const QDomElement &element, const Q
|
||||
if ( !ok )
|
||||
mElevationFilterRangeSize = -1;
|
||||
|
||||
mInvertElevationFilter = element.attribute( QStringLiteral( "FilterInvertSlider" ), QStringLiteral( "0" ) ).toInt();
|
||||
|
||||
emit changed();
|
||||
emit elevationRangeChanged( mElevationRange );
|
||||
return true;
|
||||
@ -106,6 +108,8 @@ QDomElement QgsProjectElevationProperties::writeXml( QDomDocument &document, con
|
||||
{
|
||||
element.setAttribute( QStringLiteral( "FilterRangeSize" ), mElevationFilterRangeSize );
|
||||
}
|
||||
element.setAttribute( QStringLiteral( "FilterInvertSlider" ), mInvertElevationFilter ? "1" : "0" );
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
@ -135,6 +139,15 @@ void QgsProjectElevationProperties::setElevationFilterRangeSize( double size )
|
||||
emit changed();
|
||||
}
|
||||
|
||||
void QgsProjectElevationProperties::setInvertElevationFilter( bool invert )
|
||||
{
|
||||
if ( mInvertElevationFilter == invert )
|
||||
return;
|
||||
|
||||
mInvertElevationFilter = invert;
|
||||
emit changed();
|
||||
}
|
||||
|
||||
void QgsProjectElevationProperties::setElevationRange( const QgsDoubleRange &range )
|
||||
{
|
||||
if ( mElevationRange == range )
|
||||
|
@ -100,20 +100,6 @@ class CORE_EXPORT QgsProjectElevationProperties : public QObject
|
||||
*/
|
||||
QgsDoubleRange elevationRange() const { return mElevationRange; }
|
||||
|
||||
/**
|
||||
* Sets the fixed size for elevation range filtering in the project, used when interactively filtering by elevation.
|
||||
*
|
||||
* Set to -1 if no fixed elevation range size is desired.
|
||||
*
|
||||
* A fixed size forces the selected elevation range to have a matching difference between
|
||||
* the upper and lower elevation.
|
||||
*
|
||||
* \see elevationFilterRangeSize()
|
||||
*
|
||||
* \since QGIS 3.38
|
||||
*/
|
||||
void setElevationFilterRangeSize( double size );
|
||||
|
||||
/**
|
||||
* Returns the fixed size for elevation range filtering in the project, used when interactively filtering by elevation.
|
||||
*
|
||||
@ -128,6 +114,15 @@ class CORE_EXPORT QgsProjectElevationProperties : public QObject
|
||||
*/
|
||||
double elevationFilterRangeSize() const { return mElevationFilterRangeSize; }
|
||||
|
||||
/**
|
||||
* Returns TRUE if the elevation range filter slider should be inverted for this project.
|
||||
*
|
||||
* \see setInvertElevationFilter()
|
||||
*
|
||||
* \since QGIS 3.38
|
||||
*/
|
||||
bool invertElevationFilter() const { return mInvertElevationFilter; }
|
||||
|
||||
public slots:
|
||||
|
||||
/**
|
||||
@ -144,6 +139,29 @@ class CORE_EXPORT QgsProjectElevationProperties : public QObject
|
||||
*/
|
||||
void setElevationRange( const QgsDoubleRange &range );
|
||||
|
||||
/**
|
||||
* Sets the fixed size for elevation range filtering in the project, used when interactively filtering by elevation.
|
||||
*
|
||||
* Set to -1 if no fixed elevation range size is desired.
|
||||
*
|
||||
* A fixed size forces the selected elevation range to have a matching difference between
|
||||
* the upper and lower elevation.
|
||||
*
|
||||
* \see elevationFilterRangeSize()
|
||||
*
|
||||
* \since QGIS 3.38
|
||||
*/
|
||||
void setElevationFilterRangeSize( double size );
|
||||
|
||||
/**
|
||||
* Sets whether the elevation range filter slider should be inverted for this project.
|
||||
*
|
||||
* \see invertElevationFilter()
|
||||
*
|
||||
* \since QGIS 3.38
|
||||
*/
|
||||
void setInvertElevationFilter( bool invert );
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
@ -169,6 +187,7 @@ class CORE_EXPORT QgsProjectElevationProperties : public QObject
|
||||
std::unique_ptr< QgsAbstractTerrainProvider > mTerrainProvider;
|
||||
QgsDoubleRange mElevationRange;
|
||||
double mElevationFilterRangeSize = -1;
|
||||
bool mInvertElevationFilter = false;
|
||||
|
||||
};
|
||||
|
||||
|
@ -51,6 +51,9 @@ QgsElevationControllerWidget::QgsElevationControllerWidget( QWidget *parent )
|
||||
|
||||
mSettingsAction = new QgsElevationControllerSettingsAction( mMenu );
|
||||
mMenu->addAction( mSettingsAction );
|
||||
mInvertDirectionAction = new QAction( tr( "Invert Direction" ), this );
|
||||
mInvertDirectionAction->setCheckable( true );
|
||||
mMenu->addAction( mInvertDirectionAction );
|
||||
|
||||
mSettingsAction->sizeSpin()->clear();
|
||||
connect( mSettingsAction->sizeSpin(), qOverload< double >( &QgsDoubleSpinBox::valueChanged ), this, [this]( double size )
|
||||
@ -96,6 +99,14 @@ QgsElevationControllerWidget::QgsElevationControllerWidget( QWidget *parent )
|
||||
mSliderLabels->setRange( range() );
|
||||
} );
|
||||
|
||||
connect( mInvertDirectionAction, &QAction::toggled, this, [this]()
|
||||
{
|
||||
mSlider->setFlippedDirection( !mInvertDirectionAction->isChecked() );
|
||||
mSliderLabels->setInverted( mInvertDirectionAction->isChecked() );
|
||||
|
||||
emit invertedChanged( mInvertDirectionAction->isChecked() );
|
||||
} );
|
||||
|
||||
// default initial value to full range
|
||||
setRange( rangeLimits() );
|
||||
mSliderLabels->setRange( rangeLimits() );
|
||||
@ -230,6 +241,11 @@ void QgsElevationControllerWidget::setFixedRangeSize( double size )
|
||||
emit fixedRangeSizeChanged( mFixedRangeSize );
|
||||
}
|
||||
|
||||
void QgsElevationControllerWidget::setInverted( bool inverted )
|
||||
{
|
||||
mInvertDirectionAction->setChecked( inverted );
|
||||
}
|
||||
|
||||
//
|
||||
// QgsElevationControllerLabels
|
||||
//
|
||||
@ -269,14 +285,26 @@ void QgsElevationControllerLabels::paintEvent( QPaintEvent * )
|
||||
const double limitRange = mLimits.upper() - mLimits.lower();
|
||||
const double lowerFraction = ( mRange.lower() - mLimits.lower() ) / limitRange;
|
||||
const double upperFraction = ( mRange.upper() - mLimits.lower() ) / limitRange;
|
||||
const int lowerY = std::min( static_cast< int >( std::round( rect().bottom() - sliderHeight * 0.5 - ( rect().height() - sliderHeight ) * lowerFraction + fm.ascent() ) ),
|
||||
rect().bottom() - fm.descent() );
|
||||
const int upperY = std::max( static_cast< int >( std::round( rect().bottom() - sliderHeight * 0.5 - ( rect().height() - sliderHeight ) * upperFraction - fm.descent() ) ),
|
||||
rect().top() + fm.ascent() );
|
||||
const int lowerY = !mInverted
|
||||
? ( std::min( static_cast< int >( std::round( rect().bottom() - sliderHeight * 0.5 - ( rect().height() - sliderHeight ) * lowerFraction + fm.ascent() ) ),
|
||||
rect().bottom() - fm.descent() ) )
|
||||
: ( std::max( static_cast< int >( std::round( rect().top() + sliderHeight * 0.5 + ( rect().height() - sliderHeight ) * lowerFraction - fm.descent() ) ),
|
||||
rect().top() + fm.ascent() ) );
|
||||
const int upperY = !mInverted ?
|
||||
( std::max( static_cast< int >( std::round( rect().bottom() - sliderHeight * 0.5 - ( rect().height() - sliderHeight ) * upperFraction - fm.descent() ) ),
|
||||
rect().top() + fm.ascent() ) )
|
||||
: ( std::min( static_cast< int >( std::round( rect().top() + sliderHeight * 0.5 + ( rect().height() - sliderHeight ) * upperFraction + fm.ascent() ) ),
|
||||
rect().bottom() - fm.descent() ) );
|
||||
|
||||
const bool lowerIsCloseToLimit = lowerY + fm.height() > rect().bottom() - fm.descent();
|
||||
const bool upperIsCloseToLimit = upperY - fm.height() < rect().top() + fm.ascent();
|
||||
const bool lowerIsCloseToUpperLimit = lowerY - fm.height() < rect().top() + fm.ascent();
|
||||
const bool lowerIsCloseToLimit = !mInverted
|
||||
? ( lowerY + fm.height() > rect().bottom() - fm.descent() )
|
||||
: ( lowerY - fm.height() < rect().top() + fm.ascent() ) ;
|
||||
const bool upperIsCloseToLimit = !mInverted
|
||||
? ( upperY - fm.height() < rect().top() + fm.ascent() )
|
||||
: ( upperY + fm.height() > rect().bottom() - fm.descent() ) ;
|
||||
const bool lowerIsCloseToUpperLimit = !mInverted
|
||||
? ( lowerY - fm.height() < rect().top() + fm.ascent() )
|
||||
: ( lowerY + fm.height() > rect().bottom() - fm.descent() );
|
||||
|
||||
QLocale locale;
|
||||
|
||||
@ -293,7 +321,7 @@ void QgsElevationControllerLabels::paintEvent( QPaintEvent * )
|
||||
f.setBold( true );
|
||||
path.addText( left, lowerY, f, locale.toString( mRange.lower() ) );
|
||||
f.setBold( false );
|
||||
path.addText( left, rect().bottom() - fm.descent(), f, locale.toString( mLimits.lower() ) );
|
||||
path.addText( left, !mInverted ? ( rect().bottom() - fm.descent() ) : ( rect().top() + fm.ascent() ), f, locale.toString( mLimits.lower() ) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,7 +332,7 @@ void QgsElevationControllerLabels::paintEvent( QPaintEvent * )
|
||||
if ( !lowerIsCloseToUpperLimit )
|
||||
{
|
||||
f.setBold( false );
|
||||
path.addText( left, rect().top() + fm.ascent(), f, locale.toString( mLimits.upper() ) );
|
||||
path.addText( left, !mInverted ? ( rect().top() + fm.ascent() ) : ( rect().bottom() - fm.descent() ), f, locale.toString( mLimits.upper() ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -319,7 +347,7 @@ void QgsElevationControllerLabels::paintEvent( QPaintEvent * )
|
||||
f.setBold( true );
|
||||
path.addText( left, upperY, f, locale.toString( mRange.upper() ) );
|
||||
f.setBold( false );
|
||||
path.addText( left, rect().top() + fm.ascent(), f, locale.toString( mLimits.upper() ) );
|
||||
path.addText( left, !mInverted ? ( rect().top() + fm.ascent() ) : ( rect().bottom() - fm.descent() ), f, locale.toString( mLimits.upper() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -364,6 +392,15 @@ void QgsElevationControllerLabels::setRange( const QgsDoubleRange &range )
|
||||
update();
|
||||
}
|
||||
|
||||
void QgsElevationControllerLabels::setInverted( bool inverted )
|
||||
{
|
||||
if ( inverted == mInverted )
|
||||
return;
|
||||
|
||||
mInverted = inverted;
|
||||
update();
|
||||
}
|
||||
|
||||
//
|
||||
// QgsElevationControllerSettingsAction
|
||||
//
|
||||
|
@ -43,11 +43,13 @@ class GUI_EXPORT QgsElevationControllerLabels : public QWidget SIP_SKIP
|
||||
|
||||
void setLimits( const QgsDoubleRange &limits );
|
||||
void setRange( const QgsDoubleRange &range );
|
||||
void setInverted( bool inverted );
|
||||
|
||||
private:
|
||||
|
||||
QgsDoubleRange mLimits;
|
||||
QgsDoubleRange mRange;
|
||||
bool mInverted = false;
|
||||
|
||||
};
|
||||
|
||||
@ -153,6 +155,13 @@ class GUI_EXPORT QgsElevationControllerWidget : public QWidget
|
||||
*/
|
||||
void setFixedRangeSize( double size );
|
||||
|
||||
/**
|
||||
* Sets whether the elevation slider should be inverted.
|
||||
*
|
||||
* \see invertedChanged()
|
||||
*/
|
||||
void setInverted( bool inverted );
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
@ -171,6 +180,13 @@ class GUI_EXPORT QgsElevationControllerWidget : public QWidget
|
||||
*/
|
||||
void fixedRangeSizeChanged( double size );
|
||||
|
||||
/**
|
||||
* Emitted when the elevation filter slider is inverted.
|
||||
*
|
||||
* \see setInverted()
|
||||
*/
|
||||
void invertedChanged( bool inverted );
|
||||
|
||||
private:
|
||||
|
||||
void updateWidgetMask();
|
||||
@ -178,6 +194,7 @@ class GUI_EXPORT QgsElevationControllerWidget : public QWidget
|
||||
QToolButton *mConfigureButton = nullptr;
|
||||
QgsElevationControllerSettingsAction *mSettingsAction = nullptr;
|
||||
QMenu *mMenu = nullptr;
|
||||
QAction *mInvertDirectionAction = nullptr;
|
||||
QgsRangeSlider *mSlider = nullptr;
|
||||
QgsElevationControllerLabels *mSliderLabels = nullptr;
|
||||
QgsDoubleRange mRangeLimits;
|
||||
|
Loading…
x
Reference in New Issue
Block a user