diff --git a/python/core/layertree/qgslayertreemodel.sip b/python/core/layertree/qgslayertreemodel.sip index 3750cd03ebd..1762b0b914b 100644 --- a/python/core/layertree/qgslayertreemodel.sip +++ b/python/core/layertree/qgslayertreemodel.sip @@ -230,6 +230,11 @@ class QgsLayerTreeModel : QAbstractItemModel //! emit dataChanged() for layer tree node items void recursivelyEmitDataChanged( const QModelIndex& index = QModelIndex() ); + + /** Updates layer data for scale dependent layers, should be called when map scale changes. + * Emits dataChanged() for all scale dependent layers. + * @note added in QGIS 2.16 + */ void refreshScaleBasedLayers( const QModelIndex& index = QModelIndex() ); static const QIcon& iconGroup(); diff --git a/python/core/qgsmaplayer.sip b/python/core/qgsmaplayer.sip index 87dfd51da7d..051f080c345 100644 --- a/python/core/qgsmaplayer.sip +++ b/python/core/qgsmaplayer.sip @@ -492,34 +492,42 @@ class QgsMapLayer : QObject */ QgsMapLayerStyleManager* styleManager() const; - /** + /** Tests whether the layer should be visible at the specified scale. + * @param scale scale denominator to test * @returns true if the layer is visible at the given scale. + * @note added in QGIS 2.16 + * @see minimumScale() + * @see maximumScale() + * @see hasScaleBasedVisibility() */ bool isInScaleRange( double scale ) const; /** Returns the minimum scale denominator at which the layer is visible. * Scale based visibility is only used if hasScaleBasedVisibility is true. * @returns minimum scale denominator at which the layer will render - * @see setMinimumScale - * @see maximumScale - * @see hasScaleBasedVisibility + * @see setMinimumScale() + * @see maximumScale() + * @see hasScaleBasedVisibility() + * @see isInScaleRange() */ float minimumScale() const; /** Returns the maximum scale denominator at which the layer is visible. * Scale based visibility is only used if hasScaleBasedVisibility is true. * @returns minimum scale denominator at which the layer will render - * @see setMaximumScale - * @see minimumScale - * @see hasScaleBasedVisibility + * @see setMaximumScale() + * @see minimumScale() + * @see hasScaleBasedVisibility() + * @see isInScaleRange() */ float maximumScale() const; /** Returns whether scale based visibility is enabled for the layer. * @returns true if scale based visibility is enabled - * @see minimumScale - * @see maximumScale - * @see setScaleBasedVisibility + * @see minimumScale() + * @see maximumScale() + * @see setScaleBasedVisibility() + * @see isInScaleRange() */ bool hasScaleBasedVisibility() const; diff --git a/src/app/qgisapp.h b/src/app/qgisapp.h index 45a2474e3a9..aacbc97e219 100644 --- a/src/app/qgisapp.h +++ b/src/app/qgisapp.h @@ -742,8 +742,9 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow void removeLayer(); //! Duplicate map layer(s) in legend void duplicateLayers( const QList& lyrList = QList() ); - //! Set Scale visibility of selected layers + //! Set scale visibility of selected layers void setLayerScaleVisibility(); + //! Zoom to nearest scale such that current layer is visible void zoomToLayerScale(); //! Set CRS of a layer void setLayerCRS(); diff --git a/src/app/qgsapplayertreeviewmenuprovider.cpp b/src/app/qgsapplayertreeviewmenuprovider.cpp index 825201b3912..6c37d4f6fb2 100644 --- a/src/app/qgsapplayertreeviewmenuprovider.cpp +++ b/src/app/qgsapplayertreeviewmenuprovider.cpp @@ -107,10 +107,10 @@ QMenu* QgsAppLayerTreeViewMenuProvider::createContextMenu() menu->addAction( tr( "&Set Layer Scale Visibility" ), QgisApp::instance(), SLOT( setLayerScaleVisibility() ) ); if ( !vlayer->isInScaleRange( mCanvas->scale() ) ) - menu->addAction( tr( "&Zoom to Layer Scale" ), QgisApp::instance(), SLOT( zoomToLayerScale() ) ); + menu->addAction( tr( "Zoom to Layer Scale" ), QgisApp::instance(), SLOT( zoomToLayerScale() ) ); // set layer crs - menu->addAction( QgsApplication::getThemeIcon( "/mActionSetCRS.png" ), tr( "&Set Layer CRS" ), QgisApp::instance(), SLOT( setLayerCRS() ) ); + menu->addAction( QgsApplication::getThemeIcon( "/mActionSetCRS.png" ), tr( "Set Layer CRS" ), QgisApp::instance(), SLOT( setLayerCRS() ) ); // assign layer crs to project menu->addAction( QgsApplication::getThemeIcon( "/mActionSetProjectCRS.png" ), tr( "Set &Project CRS from Layer" ), QgisApp::instance(), SLOT( setProjectCRSFromLayer() ) ); diff --git a/src/core/layertree/qgslayertreemodel.h b/src/core/layertree/qgslayertreemodel.h index 7bb3d3aec5a..e3ed76372b3 100644 --- a/src/core/layertree/qgslayertreemodel.h +++ b/src/core/layertree/qgslayertreemodel.h @@ -254,7 +254,11 @@ class CORE_EXPORT QgsLayerTreeModel : public QAbstractItemModel //! emit dataChanged() for layer tree node items void recursivelyEmitDataChanged( const QModelIndex& index = QModelIndex() ); - //! emit dataChanged() for scale dependent layers + + /** Updates layer data for scale dependent layers, should be called when map scale changes. + * Emits dataChanged() for all scale dependent layers. + * @note added in QGIS 2.16 + */ void refreshScaleBasedLayers( const QModelIndex& index = QModelIndex() ); static const QIcon& iconGroup(); diff --git a/src/core/qgsmaplayer.h b/src/core/qgsmaplayer.h index 8368b732ff8..b130b954e18 100644 --- a/src/core/qgsmaplayer.h +++ b/src/core/qgsmaplayer.h @@ -511,34 +511,42 @@ class CORE_EXPORT QgsMapLayer : public QObject */ QgsMapLayerStyleManager* styleManager() const; - /** + /** Tests whether the layer should be visible at the specified scale. + * @param scale scale denominator to test * @returns true if the layer is visible at the given scale. + * @note added in QGIS 2.16 + * @see minimumScale() + * @see maximumScale() + * @see hasScaleBasedVisibility() */ bool isInScaleRange( double scale ) const; /** Returns the minimum scale denominator at which the layer is visible. * Scale based visibility is only used if hasScaleBasedVisibility is true. * @returns minimum scale denominator at which the layer will render - * @see setMinimumScale - * @see maximumScale - * @see hasScaleBasedVisibility + * @see setMinimumScale() + * @see maximumScale() + * @see hasScaleBasedVisibility() + * @see isInScaleRange() */ float minimumScale() const; /** Returns the maximum scale denominator at which the layer is visible. * Scale based visibility is only used if hasScaleBasedVisibility is true. * @returns minimum scale denominator at which the layer will render - * @see setMaximumScale - * @see minimumScale - * @see hasScaleBasedVisibility + * @see setMaximumScale() + * @see minimumScale() + * @see hasScaleBasedVisibility() + * @see isInScaleRange() */ float maximumScale() const; /** Returns whether scale based visibility is enabled for the layer. * @returns true if scale based visibility is enabled - * @see minimumScale - * @see maximumScale - * @see setScaleBasedVisibility + * @see minimumScale() + * @see maximumScale() + * @see setScaleBasedVisibility() + * @see isInScaleRange() */ bool hasScaleBasedVisibility() const; diff --git a/tests/src/core/testqgsmaplayer.cpp b/tests/src/core/testqgsmaplayer.cpp index 72689b27175..a10ee544fd1 100644 --- a/tests/src/core/testqgsmaplayer.cpp +++ b/tests/src/core/testqgsmaplayer.cpp @@ -62,8 +62,10 @@ class TestQgsMapLayer : public QObject void setBlendMode(); + void isInScaleRange_data(); void isInScaleRange(); + private: QgsMapLayer * mpLayer; }; @@ -119,17 +121,32 @@ void TestQgsMapLayer::setBlendMode() QCOMPARE( mpLayer->blendMode(), QPainter::CompositionMode_Screen ); } +void TestQgsMapLayer::isInScaleRange_data() +{ + QTest::addColumn( "scale" ); + QTest::addColumn( "isInScale" ); + + QTest::newRow( "in the middle" ) << 3000.0f << true; + QTest::newRow( "too low" ) << 1000.0f << false; + QTest::newRow( "too high" ) << 6000.0f << false; + QTest::newRow( "max is not inclusive" ) << 5000.0f << false; + QTest::newRow( "min is inclusive" ) << 2500.0f << true; + QTest::newRow( "min is inclusive even with conversion errors" ) << static_cast< float >( 1.0f / (( float )1.0 / 2500.0 ) ) << true; +} + void TestQgsMapLayer::isInScaleRange() { + QFETCH( float, scale ); + QFETCH( bool, isInScale ); + mpLayer->setMinimumScale( 2500.0f ); mpLayer->setMaximumScale( 5000.0f ); mpLayer->setScaleBasedVisibility( true ); - QCOMPARE( mpLayer->isInScaleRange( 3000.0f ), true ); // In the middle - QCOMPARE( mpLayer->isInScaleRange( 1000.0f ), false ); // Too low - QCOMPARE( mpLayer->isInScaleRange( 6000.0f ), false ); // Too high - QCOMPARE( mpLayer->isInScaleRange( 5000.0f ), false ); // Max is not inclusive - QCOMPARE( mpLayer->isInScaleRange( 2500.0f ), true ); // Min is inclusive - QCOMPARE( mpLayer->isInScaleRange( 1.0f / (( float )1.0 / 2500.0 ) ), true ); // Min is inclusive even with conversion errors + QCOMPARE( mpLayer->isInScaleRange( scale ), isInScale ); + //always in scale range if scale based visibility is false + mpLayer->setScaleBasedVisibility( false ); + QCOMPARE( mpLayer->isInScaleRange( scale ), true ); + } QTEST_MAIN( TestQgsMapLayer )