diff --git a/python/core/qgssnappingutils.sip b/python/core/qgssnappingutils.sip index 83bd64798b8..fc8bcd02042 100644 --- a/python/core/qgssnappingutils.sip +++ b/python/core/qgssnappingutils.sip @@ -37,8 +37,9 @@ class QgsSnappingUtils : QObject //! modes for "snap to background" enum SnapToMapMode { - SnapCurrentLayer, //!< snap just to current layer (tolerance+type from QSettings) - SnapPerLayerConfig, //!< snap according to the configuration set in setLayers() + SnapCurrentLayer, //!< snap just to current layer (tolerance and type from defaultSettings()) + SnapAllLayers, //!< snap to all rendered layers (tolerance and type from defaultSettings()) + SnapAdvanced, //!< snap according to the configuration set in setLayers() }; /** Set how the snapping to map is done */ diff --git a/src/app/qgssnappingdialog.cpp b/src/app/qgssnappingdialog.cpp index e99cb037201..ebf3a338013 100644 --- a/src/app/qgssnappingdialog.cpp +++ b/src/app/qgssnappingdialog.cpp @@ -167,7 +167,7 @@ void QgsSnappingDialog::on_cbxEnableIntersectionSnappingCheckBox_stateChanged( i void QgsSnappingDialog::onSnappingModeIndexChanged( int index ) { - if ( index == 0 ) + if ( index == 0 || index == 1 ) mStackedWidget->setCurrentIndex( 0 ); else mStackedWidget->setCurrentIndex( 1 ); @@ -203,7 +203,13 @@ void QgsSnappingDialog::closeEvent( QCloseEvent* event ) void QgsSnappingDialog::apply() { - QString snapMode = mSnapModeComboBox->currentIndex() == 0 ? "current_layer" : "advanced"; + QString snapMode; + switch ( mSnapModeComboBox->currentIndex() ) + { + case 0: snapMode = "current_layer"; break; + case 1: snapMode = "all_layers"; break; + default: snapMode = "advanced"; break; + } QgsProject::instance()->writeEntry( "Digitizing", "/SnappingMode", snapMode ); QString snapType = mDefaultSnapToComboBox->itemData( mDefaultSnapToComboBox->currentIndex() ).toString(); @@ -486,7 +492,9 @@ void QgsSnappingDialog::setSnappingMode() QString snapMode = QgsProject::instance()->readEntry( "Digitizing", "/SnappingMode" ); if ( snapMode == "current_layer" ) mSnapModeComboBox->setCurrentIndex( 0 ); - else // "advanced" or empty (backward compatibility) + else if ( snapMode == "all_layers" ) mSnapModeComboBox->setCurrentIndex( 1 ); + else // "advanced" or empty (backward compatibility) + mSnapModeComboBox->setCurrentIndex( 2 ); } diff --git a/src/core/qgssnappingutils.cpp b/src/core/qgssnappingutils.cpp index 6475d5bd355..8ff3b0018eb 100644 --- a/src/core/qgssnappingutils.cpp +++ b/src/core/qgssnappingutils.cpp @@ -225,7 +225,7 @@ QgsPointLocator::Match QgsSnappingUtils::snapToMap( const QgsPoint& pointMap, Qg return bestMatch; } - else if ( mSnapToMapMode == SnapPerLayerConfig ) + else if ( mSnapToMapMode == SnapAdvanced ) { QgsPointLocator::Match bestMatch; QgsPointLocator::MatchList edges; // for snap on intersection @@ -251,6 +251,35 @@ QgsPointLocator::Match QgsSnappingUtils::snapToMap( const QgsPoint& pointMap, Qg return bestMatch; } + else if ( mSnapToMapMode == SnapAllLayers ) + { + // data from project + double tolerance = QgsTolerance::toleranceInMapUnits( mDefaultTolerance, mMapSettings, mDefaultUnit ); + int type = mDefaultType; + + QgsPointLocator::MatchList edges; // for snap on intersection + QgsPointLocator::Match bestMatch; + + foreach( const QString& layerID, mMapSettings.layers() ) + { + QgsVectorLayer* vl = qobject_cast( QgsMapLayerRegistry::instance()->mapLayer( layerID ) ); + if ( !vl ) + continue; + + if ( QgsPointLocator* loc = locatorForLayerUsingStrategy( vl, pointMap, tolerance ) ) + { + _updateBestMatch( bestMatch, pointMap, loc, type, tolerance, filter ); + + if ( mSnapOnIntersection ) + edges << loc->edgesInRect( pointMap, tolerance ); + } + } + + if ( mSnapOnIntersection ) + _replaceIfBetter( bestMatch, _findClosestSegmentIntersection( pointMap, edges ), tolerance ); + + return bestMatch; + } return QgsPointLocator::Match(); } @@ -346,8 +375,10 @@ void QgsSnappingUtils::readConfigFromProject() // Use snapping information from the project if ( snapMode == "current_layer" ) mSnapToMapMode = SnapCurrentLayer; + else if ( snapMode == "all_layers" ) + mSnapToMapMode = SnapAllLayers; else // either "advanced" or empty (for background compatibility) - mSnapToMapMode = SnapPerLayerConfig; + mSnapToMapMode = SnapAdvanced; diff --git a/src/core/qgssnappingutils.h b/src/core/qgssnappingutils.h index 2e2861e07b3..6e7f2d89250 100644 --- a/src/core/qgssnappingutils.h +++ b/src/core/qgssnappingutils.h @@ -73,8 +73,9 @@ class CORE_EXPORT QgsSnappingUtils : public QObject //! modes for "snap to background" enum SnapToMapMode { - SnapCurrentLayer, //!< snap just to current layer (tolerance+type from QSettings) - SnapPerLayerConfig, //!< snap according to the configuration set in setLayers() + SnapCurrentLayer, //!< snap just to current layer (tolerance and type from defaultSettings()) + SnapAllLayers, //!< snap to all rendered layers (tolerance and type from defaultSettings()) + SnapAdvanced, //!< snap according to the configuration set in setLayers() }; /** Set how the snapping to map is done */ diff --git a/src/ui/qgssnappingdialogbase.ui b/src/ui/qgssnappingdialogbase.ui index 8c9e2d62b3e..76a1f389363 100644 --- a/src/ui/qgssnappingdialogbase.ui +++ b/src/ui/qgssnappingdialogbase.ui @@ -36,6 +36,11 @@ Current layer + + + All layers + + Advanced diff --git a/tests/src/core/testqgssnappingutils.cpp b/tests/src/core/testqgssnappingutils.cpp index 96ef06afa58..34d6b464f7a 100644 --- a/tests/src/core/testqgssnappingutils.cpp +++ b/tests/src/core/testqgssnappingutils.cpp @@ -111,7 +111,7 @@ class TestQgsSnappingUtils : public QObject QVERIFY( !m3.isValid() ); } - void testSnapModePerLayer() + void testSnapModeAll() { QgsMapSettings mapSettings; mapSettings.setOutputSize( QSize( 100, 100 ) ); @@ -120,7 +120,32 @@ class TestQgsSnappingUtils : public QObject QgsSnappingUtils u; u.setMapSettings( mapSettings ); - u.setSnapToMapMode( QgsSnappingUtils::SnapPerLayerConfig ); + u.setSnapToMapMode( QgsSnappingUtils::SnapAllLayers ); + + // right now there are no layers in map settings - snapping will fail + + QgsPointLocator::Match m = u.snapToMap( QPoint( 100, 100 ) ); + QVERIFY( !m.isValid() ); + + // now check with our layer + mapSettings.setLayers( QStringList() << mVL->id() ); + u.setMapSettings( mapSettings ); + + QgsPointLocator::Match m2 = u.snapToMap( QPoint( 100, 100 ) ); + QVERIFY( m2.isValid() ); + QCOMPARE( m2.point(), QgsPoint( 1, 0 ) ); + } + + void testSnapModeAdvanced() + { + QgsMapSettings mapSettings; + mapSettings.setOutputSize( QSize( 100, 100 ) ); + mapSettings.setExtent( QgsRectangle( 0, 0, 1, 1 ) ); + QVERIFY( mapSettings.hasValidSettings() ); + + QgsSnappingUtils u; + u.setMapSettings( mapSettings ); + u.setSnapToMapMode( QgsSnappingUtils::SnapAdvanced ); QList layers; layers << QgsSnappingUtils::LayerConfig( mVL, QgsPointLocator::Vertex, 10, QgsTolerance::Pixels ); u.setLayers( layers ); @@ -135,6 +160,7 @@ class TestQgsSnappingUtils : public QObject QgsPointLocator::Match m2 = u.snapToMap( QPoint( 100, 100 ), &myFilter ); QVERIFY( !m2.isValid() ); } + }; QTEST_MAIN( TestQgsSnappingUtils )