Skip to content

Commit e86785d

Browse files
wonder-sknirvn
authored andcommitted
Improvements to the right-click behavior to pick locked feature
- unlock feature on right-click in an empty area - allow selection of locked feature by right-click on polygon interior (in addition to polygon rings) - highlight polygons when mouse moves in their interior - this should also decrease the blinking effect as the highlight is more consistent
1 parent f445c26 commit e86785d

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

src/app/vertextool/qgsvertextool.cpp

+76
Original file line numberDiff line numberDiff line change
@@ -463,10 +463,25 @@ void QgsVertexTool::cadCanvasPressEvent( QgsMapMouseEvent *e )
463463
if ( !mSelectionRect && !mDraggingVertex && !mDraggingEdge )
464464
{
465465
QgsPointLocator::Match m = snapToEditableLayer( e );
466+
if ( !m.isValid() )
467+
{
468+
// as the last resort check if we are on top of a feature if there is no vertex or edge snap
469+
m = snapToPolygonInterior( e );
470+
}
471+
466472
if ( m.isValid() && m.layer() )
467473
{
468474
updateVertexEditor( m.layer(), m.featureId() );
469475
}
476+
else
477+
{
478+
// there's really nothing under the cursor - let's deselect any feature we may have
479+
mSelectedFeature.reset();
480+
if ( mVertexEditor )
481+
{
482+
mVertexEditor->updateEditor( nullptr );
483+
}
484+
}
470485
}
471486
}
472487
}
@@ -782,6 +797,61 @@ QgsPointLocator::Match QgsVertexTool::snapToEditableLayer( QgsMapMouseEvent *e )
782797
return m;
783798
}
784799

800+
801+
QgsPointLocator::Match QgsVertexTool::snapToPolygonInterior( QgsMapMouseEvent *e )
802+
{
803+
QgsSnappingUtils *snapUtils = canvas()->snappingUtils();
804+
QgsPointLocator::Match m;
805+
806+
QgsPointXY mapPoint = toMapCoordinates( e->pos() );
807+
808+
// if there is a current layer, it should have priority over other layers
809+
// because sometimes there may be match from multiple layers at one location
810+
// and selecting current layer is an easy way for the user to prioritize a layer
811+
if ( QgsVectorLayer *currentVlayer = currentVectorLayer() )
812+
{
813+
if ( currentVlayer->isEditable() && currentVlayer->geometryType() == QgsWkbTypes::PolygonGeometry )
814+
{
815+
QgsPointLocator::MatchList matchList = snapUtils->locatorForLayer( currentVlayer )->pointInPolygon( mapPoint );
816+
if ( !matchList.isEmpty() )
817+
{
818+
m = matchList.first();
819+
}
820+
}
821+
}
822+
823+
// if there is no match from the current layer, try to use any editable vector layer
824+
if ( !m.isValid() && mMode == AllLayers )
825+
{
826+
const auto layers = canvas()->layers();
827+
for ( QgsMapLayer *layer : layers )
828+
{
829+
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
830+
if ( !vlayer )
831+
continue;
832+
833+
if ( vlayer->isEditable() && vlayer->geometryType() == QgsWkbTypes::PolygonGeometry )
834+
{
835+
QgsPointLocator::MatchList matchList = snapUtils->locatorForLayer( vlayer )->pointInPolygon( mapPoint );
836+
if ( !matchList.isEmpty() )
837+
{
838+
m = matchList.first();
839+
break;
840+
}
841+
}
842+
}
843+
}
844+
845+
// if we don't have anything in the last snap, keep the area match
846+
if ( !mLastSnap && m.isValid() )
847+
{
848+
mLastSnap.reset( new QgsPointLocator::Match( m ) );
849+
}
850+
851+
return m;
852+
}
853+
854+
785855
bool QgsVertexTool::isNearEndpointMarker( const QgsPointXY &mapPoint )
786856
{
787857
if ( !mEndpointMarkerCenter )
@@ -934,6 +1004,12 @@ void QgsVertexTool::mouseMoveNotDragging( QgsMapMouseEvent *e )
9341004
mEdgeBand->setVisible( false );
9351005
}
9361006

1007+
if ( !m.isValid() )
1008+
{
1009+
// as the last resort check if we are on top of a feature if there is no vertex or edge snap
1010+
m = snapToPolygonInterior( e );
1011+
}
1012+
9371013
updateFeatureBand( m );
9381014
}
9391015

src/app/vertextool/qgsvertextool.h

+2
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ class APP_EXPORT QgsVertexTool : public QgsMapToolAdvancedDigitizing
146146
*/
147147
QgsPointLocator::Match snapToEditableLayer( QgsMapMouseEvent *e );
148148

149+
QgsPointLocator::Match snapToPolygonInterior( QgsMapMouseEvent *e );
150+
149151
//! check whether we are still close to the mEndpointMarker
150152
bool isNearEndpointMarker( const QgsPointXY &mapPoint );
151153

0 commit comments

Comments
 (0)