Skip to content
Permalink
Browse files

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
  • Loading branch information
wonder-sk authored and nirvn committed Jan 31, 2019
1 parent f445c26 commit e86785d09fc4c175279ba249f041f5a8af2fee8d
Showing with 78 additions and 0 deletions.
  1. +76 −0 src/app/vertextool/qgsvertextool.cpp
  2. +2 −0 src/app/vertextool/qgsvertextool.h
@@ -463,10 +463,25 @@ void QgsVertexTool::cadCanvasPressEvent( QgsMapMouseEvent *e )
if ( !mSelectionRect && !mDraggingVertex && !mDraggingEdge )
{
QgsPointLocator::Match m = snapToEditableLayer( e );
if ( !m.isValid() )
{
// as the last resort check if we are on top of a feature if there is no vertex or edge snap
m = snapToPolygonInterior( e );
}

if ( m.isValid() && m.layer() )
{
updateVertexEditor( m.layer(), m.featureId() );
}
else
{
// there's really nothing under the cursor - let's deselect any feature we may have
mSelectedFeature.reset();
if ( mVertexEditor )
{
mVertexEditor->updateEditor( nullptr );
}
}
}
}
}
@@ -782,6 +797,61 @@ QgsPointLocator::Match QgsVertexTool::snapToEditableLayer( QgsMapMouseEvent *e )
return m;
}


QgsPointLocator::Match QgsVertexTool::snapToPolygonInterior( QgsMapMouseEvent *e )
{
QgsSnappingUtils *snapUtils = canvas()->snappingUtils();
QgsPointLocator::Match m;

QgsPointXY mapPoint = toMapCoordinates( e->pos() );

// if there is a current layer, it should have priority over other layers
// because sometimes there may be match from multiple layers at one location
// and selecting current layer is an easy way for the user to prioritize a layer
if ( QgsVectorLayer *currentVlayer = currentVectorLayer() )
{
if ( currentVlayer->isEditable() && currentVlayer->geometryType() == QgsWkbTypes::PolygonGeometry )
{
QgsPointLocator::MatchList matchList = snapUtils->locatorForLayer( currentVlayer )->pointInPolygon( mapPoint );
if ( !matchList.isEmpty() )
{
m = matchList.first();
}
}
}

// if there is no match from the current layer, try to use any editable vector layer
if ( !m.isValid() && mMode == AllLayers )
{
const auto layers = canvas()->layers();
for ( QgsMapLayer *layer : layers )
{
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
if ( !vlayer )
continue;

if ( vlayer->isEditable() && vlayer->geometryType() == QgsWkbTypes::PolygonGeometry )
{
QgsPointLocator::MatchList matchList = snapUtils->locatorForLayer( vlayer )->pointInPolygon( mapPoint );
if ( !matchList.isEmpty() )
{
m = matchList.first();
break;
}
}
}
}

// if we don't have anything in the last snap, keep the area match
if ( !mLastSnap && m.isValid() )
{
mLastSnap.reset( new QgsPointLocator::Match( m ) );
}

return m;
}


bool QgsVertexTool::isNearEndpointMarker( const QgsPointXY &mapPoint )
{
if ( !mEndpointMarkerCenter )
@@ -934,6 +1004,12 @@ void QgsVertexTool::mouseMoveNotDragging( QgsMapMouseEvent *e )
mEdgeBand->setVisible( false );
}

if ( !m.isValid() )
{
// as the last resort check if we are on top of a feature if there is no vertex or edge snap
m = snapToPolygonInterior( e );
}

updateFeatureBand( m );
}

@@ -146,6 +146,8 @@ class APP_EXPORT QgsVertexTool : public QgsMapToolAdvancedDigitizing
*/
QgsPointLocator::Match snapToEditableLayer( QgsMapMouseEvent *e );

QgsPointLocator::Match snapToPolygonInterior( QgsMapMouseEvent *e );

//! check whether we are still close to the mEndpointMarker
bool isNearEndpointMarker( const QgsPointXY &mapPoint );

0 comments on commit e86785d

Please sign in to comment.
You can’t perform that action at this time.