Skip to content

Commit 31b6b58

Browse files
committedSep 8, 2017
Node tool: give priority to the current layer when selecting vertex
1 parent 7a62746 commit 31b6b58

File tree

2 files changed

+83
-10
lines changed

2 files changed

+83
-10
lines changed
 

‎src/app/nodetool/qgsnodetool.cpp

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,10 @@ void QgsNodeTool::removeTemporaryRubberBands()
596596

597597
QgsPointLocator::Match QgsNodeTool::snapToEditableLayer( QgsMapMouseEvent *e )
598598
{
599+
QgsSnappingUtils *snapUtils = canvas()->snappingUtils();
600+
QgsSnappingConfig oldConfig = snapUtils->config();
601+
QgsPointLocator::Match m;
602+
599603
QgsPointXY mapPoint = toMapCoordinates( e->pos() );
600604
double tol = QgsTolerance::vertexSearchRadius( canvas()->mapSettings() );
601605

@@ -604,21 +608,44 @@ QgsPointLocator::Match QgsNodeTool::snapToEditableLayer( QgsMapMouseEvent *e )
604608
config.setMode( QgsSnappingConfig::AdvancedConfiguration );
605609
config.setIntersectionSnapping( false ); // only snap to layers
606610

607-
Q_FOREACH ( QgsMapLayer *layer, canvas()->layers() )
611+
// if there is a current layer, it should have priority over other layers
612+
// because sometimes there may be match from multiple layers at one location
613+
// and selecting current layer is an easy way for the user to prioritize a layer
614+
if ( QgsVectorLayer *currentVlayer = currentVectorLayer() )
608615
{
609-
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
610-
if ( !vlayer )
611-
continue;
616+
if ( currentVlayer->isEditable() )
617+
{
618+
Q_FOREACH ( QgsMapLayer *layer, canvas()->layers() )
619+
{
620+
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
621+
if ( !vlayer )
622+
continue;
623+
624+
config.setIndividualLayerSettings( vlayer, QgsSnappingConfig::IndividualLayerSettings(
625+
vlayer == currentVlayer, QgsSnappingConfig::VertexAndSegment, tol, QgsTolerance::ProjectUnits ) );
626+
}
612627

613-
config.setIndividualLayerSettings( vlayer, QgsSnappingConfig::IndividualLayerSettings(
614-
vlayer->isEditable(), QgsSnappingConfig::VertexAndSegment, tol, QgsTolerance::ProjectUnits ) );
628+
snapUtils->setConfig( config );
629+
m = snapUtils->snapToMap( mapPoint );
630+
}
615631
}
616632

617-
QgsSnappingUtils *snapUtils = canvas()->snappingUtils();
618-
QgsSnappingConfig oldConfig = snapUtils->config();
619-
snapUtils->setConfig( config );
633+
// if there is no match from the current layer, try to use any editable vector layer
634+
if ( !m.isValid() )
635+
{
636+
Q_FOREACH ( QgsMapLayer *layer, canvas()->layers() )
637+
{
638+
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
639+
if ( !vlayer )
640+
continue;
620641

621-
QgsPointLocator::Match m = snapUtils->snapToMap( mapPoint );
642+
config.setIndividualLayerSettings( vlayer, QgsSnappingConfig::IndividualLayerSettings(
643+
vlayer->isEditable(), QgsSnappingConfig::VertexAndSegment, tol, QgsTolerance::ProjectUnits ) );
644+
}
645+
646+
snapUtils->setConfig( config );
647+
m = snapUtils->snapToMap( mapPoint );
648+
}
622649

623650
// try to stay snapped to previously used feature
624651
// so the highlight does not jump around at nodes where features are joined

‎tests/src/app/testqgsnodetool.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class TestQgsNodeTool : public QObject
6363
void testMoveMultipleVertices();
6464
void testMoveVertexTopo();
6565
void testDeleteVertexTopo();
66+
void testActiveLayerPriority();
6667

6768
private:
6869
QPoint mapToScreen( double mapX, double mapY )
@@ -532,5 +533,50 @@ void TestQgsNodeTool::testDeleteVertexTopo()
532533
QgsProject::instance()->setTopologicalEditing( false );
533534
}
534535

536+
void TestQgsNodeTool::testActiveLayerPriority()
537+
{
538+
// check that features from current layer get priority when picking points
539+
540+
// create a temporary line layer that has a common vertex with existing line layer at (1, 1)
541+
QgsVectorLayer *layerLine2 = new QgsVectorLayer( "LineString?crs=EPSG:27700", "layer line 2", "memory" );
542+
QVERIFY( layerLine2->isValid() );
543+
QgsPolyline line1;
544+
line1 << QgsPointXY( 0, 1 ) << QgsPointXY( 1, 1 ) << QgsPointXY( 1, 0 );
545+
QgsFeature lineF1;
546+
lineF1.setGeometry( QgsGeometry::fromPolyline( line1 ) );
547+
layerLine2->startEditing();
548+
layerLine2->addFeature( lineF1 );
549+
QgsFeatureId fidLineF1 = lineF1.id();
550+
QCOMPARE( layerLine2->featureCount(), ( long )1 );
551+
QgsProject::instance()->addMapLayer( layerLine2 );
552+
mCanvas->setLayers( QList<QgsMapLayer *>() << mLayerLine << mLayerPolygon << mLayerPoint << layerLine2 );
553+
554+
// make one layer active and check its vertex is used
555+
556+
mCanvas->setCurrentLayer( mLayerLine );
557+
558+
mouseClick( 1, 1, Qt::LeftButton );
559+
mouseClick( 0, 0, Qt::LeftButton );
560+
561+
QCOMPARE( mLayerLine->getFeature( mFidLineF1 ).geometry(), QgsGeometry::fromWkt( "LINESTRING(2 1, 0 0, 1 3)" ) );
562+
QCOMPARE( layerLine2->getFeature( fidLineF1 ).geometry(), QgsGeometry::fromWkt( "LINESTRING(0 1, 1 1, 1 0)" ) );
563+
mLayerLine->undoStack()->undo();
564+
565+
// make the other layer active and check its vertex is used
566+
567+
mCanvas->setCurrentLayer( layerLine2 );
568+
569+
mouseClick( 1, 1, Qt::LeftButton );
570+
mouseClick( 0, 0, Qt::LeftButton );
571+
572+
QCOMPARE( mLayerLine->getFeature( mFidLineF1 ).geometry(), QgsGeometry::fromWkt( "LINESTRING(2 1, 1 1, 1 3)" ) );
573+
QCOMPARE( layerLine2->getFeature( fidLineF1 ).geometry(), QgsGeometry::fromWkt( "LINESTRING(0 1, 0 0, 1 0)" ) );
574+
layerLine2->undoStack()->undo();
575+
576+
// get rid of the temporary layer
577+
mCanvas->setLayers( QList<QgsMapLayer *>() << mLayerLine << mLayerPolygon << mLayerPoint );
578+
QgsProject::instance()->removeMapLayer( layerLine2 );
579+
}
580+
535581
QGSTEST_MAIN( TestQgsNodeTool )
536582
#include "testqgsnodetool.moc"

0 commit comments

Comments
 (0)
Please sign in to comment.