Skip to content

Commit

Permalink
Fix issue with selection of vertices of locked feature (fixes #21283)
Browse files Browse the repository at this point in the history
When user was coming with mouse to a vertex of the locked feature
from a different feature, it could happen that the vertex would not
get picked by vertex tool - this was because snapToEditableLayer()
keeps the last snap which would belong to a different feature, but
that feature was not allowed (blocking a new snap).

The fix makes sure that with a locked feature its matches always win.

(cherry picked from commit aec87a0)
  • Loading branch information
wonder-sk committed Feb 21, 2019
1 parent 8986c97 commit bdec90c
Showing 1 changed file with 21 additions and 7 deletions.
28 changes: 21 additions & 7 deletions src/app/vertextool/qgsvertextool.cpp
Expand Up @@ -215,19 +215,32 @@ class MatchCollectingFilter : public QgsPointLocator::MatchFilter
/**
* Keeps the best match from a selected feature so that we can possibly use it with higher priority.
* If we do not encounter any selected feature within tolerance, we use the best match as usual.
*
* There are two kinds of "selected" features... if we have a "locked" feature in vertex tool,
* we get a non-null QgsSelectedFeature which has feature's layer and feature id. In such case we
* only allow matches from that feature. The other kind is if some features within layer are
* in the layer's list of selected features - in that case we accept any match from those features
* (but only if we do not have "locked" feature)
*/
class SelectedMatchFilter : public QgsPointLocator::MatchFilter
{
public:
explicit SelectedMatchFilter( double tol )
: mTolerance( tol ) {}
explicit SelectedMatchFilter( double tol, QgsSelectedFeature *selectedFeature )
: mTolerance( tol )
, mSelectedFeature( selectedFeature ) {}

bool acceptMatch( const QgsPointLocator::Match &match ) override
{
if ( match.distance() <= mTolerance && match.layer() && match.layer()->selectedFeatureIds().contains( match.featureId() ) )
if ( match.distance() <= mTolerance && match.layer() )
{
if ( !mBestSelectedMatch.isValid() || match.distance() < mBestSelectedMatch.distance() )
mBestSelectedMatch = match;
// option 1: we have "locked" feature - we consider just a match from that feature
// option 2: we do not have "locked" feature - we consider matches from any selected feature
if ( ( mSelectedFeature && mSelectedFeature->layer() == match.layer() && mSelectedFeature->featureId() == match.featureId() )
|| ( !mSelectedFeature && match.layer()->selectedFeatureIds().contains( match.featureId() ) ) )
{
if ( !mBestSelectedMatch.isValid() || match.distance() < mBestSelectedMatch.distance() )
mBestSelectedMatch = match;
}
}
return true;
}
Expand All @@ -237,6 +250,7 @@ class SelectedMatchFilter : public QgsPointLocator::MatchFilter

private:
double mTolerance;
QgsSelectedFeature *mSelectedFeature; // not null in case of selected (locked) feature
QgsPointLocator::Match mBestSelectedMatch;
};

Expand Down Expand Up @@ -740,7 +754,7 @@ QgsPointLocator::Match QgsVertexTool::snapToEditableLayer( QgsMapMouseEvent *e )
}

snapUtils->setConfig( config );
SelectedMatchFilter filter( tol );
SelectedMatchFilter filter( tol, mSelectedFeature.get() );
m = snapUtils->snapToMap( mapPoint, &filter );

// we give priority to snap matches that are from selected features
Expand All @@ -767,7 +781,7 @@ QgsPointLocator::Match QgsVertexTool::snapToEditableLayer( QgsMapMouseEvent *e )
}

snapUtils->setConfig( config );
SelectedMatchFilter filter( tol );
SelectedMatchFilter filter( tol, mSelectedFeature.get() );
m = snapUtils->snapToMap( mapPoint, &filter );

// we give priority to snap matches that are from selected features
Expand Down

0 comments on commit bdec90c

Please sign in to comment.