Skip to content

Commit aec87a0

Browse files
committed
Fix issue with selection of vertices of locked feature (fixes #21283)
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.
1 parent 7831f3e commit aec87a0

File tree

1 file changed

+21
-7
lines changed

1 file changed

+21
-7
lines changed

src/app/vertextool/qgsvertextool.cpp

+21-7
Original file line numberDiff line numberDiff line change
@@ -215,19 +215,32 @@ class MatchCollectingFilter : public QgsPointLocator::MatchFilter
215215
/**
216216
* Keeps the best match from a selected feature so that we can possibly use it with higher priority.
217217
* If we do not encounter any selected feature within tolerance, we use the best match as usual.
218+
*
219+
* There are two kinds of "selected" features... if we have a "locked" feature in vertex tool,
220+
* we get a non-null QgsSelectedFeature which has feature's layer and feature id. In such case we
221+
* only allow matches from that feature. The other kind is if some features within layer are
222+
* in the layer's list of selected features - in that case we accept any match from those features
223+
* (but only if we do not have "locked" feature)
218224
*/
219225
class SelectedMatchFilter : public QgsPointLocator::MatchFilter
220226
{
221227
public:
222-
explicit SelectedMatchFilter( double tol )
223-
: mTolerance( tol ) {}
228+
explicit SelectedMatchFilter( double tol, QgsSelectedFeature *selectedFeature )
229+
: mTolerance( tol )
230+
, mSelectedFeature( selectedFeature ) {}
224231

225232
bool acceptMatch( const QgsPointLocator::Match &match ) override
226233
{
227-
if ( match.distance() <= mTolerance && match.layer() && match.layer()->selectedFeatureIds().contains( match.featureId() ) )
234+
if ( match.distance() <= mTolerance && match.layer() )
228235
{
229-
if ( !mBestSelectedMatch.isValid() || match.distance() < mBestSelectedMatch.distance() )
230-
mBestSelectedMatch = match;
236+
// option 1: we have "locked" feature - we consider just a match from that feature
237+
// option 2: we do not have "locked" feature - we consider matches from any selected feature
238+
if ( ( mSelectedFeature && mSelectedFeature->layer() == match.layer() && mSelectedFeature->featureId() == match.featureId() )
239+
|| ( !mSelectedFeature && match.layer()->selectedFeatureIds().contains( match.featureId() ) ) )
240+
{
241+
if ( !mBestSelectedMatch.isValid() || match.distance() < mBestSelectedMatch.distance() )
242+
mBestSelectedMatch = match;
243+
}
231244
}
232245
return true;
233246
}
@@ -237,6 +250,7 @@ class SelectedMatchFilter : public QgsPointLocator::MatchFilter
237250

238251
private:
239252
double mTolerance;
253+
QgsSelectedFeature *mSelectedFeature; // not null in case of selected (locked) feature
240254
QgsPointLocator::Match mBestSelectedMatch;
241255
};
242256

@@ -740,7 +754,7 @@ QgsPointLocator::Match QgsVertexTool::snapToEditableLayer( QgsMapMouseEvent *e )
740754
}
741755

742756
snapUtils->setConfig( config );
743-
SelectedMatchFilter filter( tol );
757+
SelectedMatchFilter filter( tol, mSelectedFeature.get() );
744758
m = snapUtils->snapToMap( mapPoint, &filter );
745759

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

769783
snapUtils->setConfig( config );
770-
SelectedMatchFilter filter( tol );
784+
SelectedMatchFilter filter( tol, mSelectedFeature.get() );
771785
m = snapUtils->snapToMap( mapPoint, &filter );
772786

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

0 commit comments

Comments
 (0)