Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #2388 from sbrunner/node-tool-select-feature
Allow to select the feature on which the node tool works
  • Loading branch information
m-kuhn committed Nov 7, 2015
2 parents 9172767 + d73ef5b commit 9b192d4
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 12 deletions.
73 changes: 65 additions & 8 deletions src/app/nodetool/qgsmaptoolnodetool.cpp
Expand Up @@ -26,6 +26,7 @@
#include "qgsproject.h"
#include "qgsgeometryrubberband.h"
#include "qgsvectorlayer.h"
#include "qgsvectordataprovider.h"

#include <QMouseEvent>
#include <QRubberBand>
Expand Down Expand Up @@ -168,6 +169,22 @@ void QgsMapToolNodeTool::canvasMoveEvent( QgsMapMouseEvent* e )
}
}

QgsFeature QgsMapToolNodeTool::getFeatureAtPoint( QgsMapMouseEvent* e )
{
QgsFeature feature;
QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() );
if ( vlayer == NULL ) {
return feature;
}

QgsFeatureRequest request;
request.setFilterRect( QgsRectangle( e->mapPoint().x(), e->mapPoint().y(), e->mapPoint().x(), e->mapPoint().y() ) );
QgsFeatureIterator features = vlayer->getFeatures( request );
features.nextFeature( feature );

return feature;
}

void QgsMapToolNodeTool::canvasPressEvent( QgsMapMouseEvent* e )
{
QgsDebugCall;
Expand All @@ -186,14 +203,25 @@ void QgsMapToolNodeTool::canvasPressEvent( QgsMapMouseEvent* e )

if ( snapResults.size() < 1 )
{
emit messageEmitted( tr( "could not snap to a segment on the current layer." ) );
return;
QgsFeature feature = getFeatureAtPoint( e );
if ( feature.geometry() == NULL ) {
emit messageEmitted(tr( "could not snap to a segment on the current layer." ) );
return;
}
else {
// remove previous warning
emit messageDiscarded();
mSelectedFeature = new QgsSelectedFeature( feature.id(), vlayer, mCanvas );
updateSelectFeature();
}
}
else {
// remove previous warning
emit messageDiscarded();

// remove previous warning
emit messageDiscarded();

mSelectedFeature = new QgsSelectedFeature( snapResults[0].snappedAtGeometry, vlayer, mCanvas );
mSelectedFeature = new QgsSelectedFeature( snapResults[0].snappedAtGeometry, vlayer, mCanvas );
updateSelectFeature();
}
connect( QgisApp::instance()->layerTreeView(), SIGNAL( currentLayerChanged( QgsMapLayer* ) ), this, SLOT( currentLayerChanged( QgsMapLayer* ) ) );
connect( mSelectedFeature, SIGNAL( destroyed() ), this, SLOT( selectedFeatureDestroyed() ) );
connect( vlayer, SIGNAL( editingStopped() ), this, SLOT( editingToggled() ) );
Expand Down Expand Up @@ -254,7 +282,7 @@ void QgsMapToolNodeTool::canvasPressEvent( QgsMapMouseEvent* e )
// no near vertex to snap
// unless point layer, try segment
if ( !mIsPoint )
mSnapper.snapToCurrentLayer( e->pos(), snapResults, QgsSnapper::SnapToSegment, tol );
mSnapper.snapToCurrentLayer( e->pos(), snapResults, QgsSnapper::SnapToSegment, tol, QList<QgsPoint>(), true );

if ( snapResults.size() > 0 )
{
Expand Down Expand Up @@ -310,11 +338,35 @@ void QgsMapToolNodeTool::canvasPressEvent( QgsMapMouseEvent* e )
else if ( !ctrlModifier )
{
mSelectedFeature->deselectAllVertexes();

QgsFeature feature = getFeatureAtPoint( e );
if ( feature.geometry() == NULL ) {
return;
}
else {
mAnother = feature.id();
mSelectAnother = true;
}
}
}
}
}

void QgsMapToolNodeTool::updateSelectFeature()
{
if (mSelectRubberBand != NULL) {
delete mSelectRubberBand;
}
mSelectRubberBand = new QgsGeometryRubberBand( mCanvas, mSelectedFeature->geometry()->type() );
mSelectRubberBand->setBrushStyle( Qt::SolidPattern );
mSelectRubberBand->setFillColor( QColor( 255, 0, 0, 50 ) );
QgsAbstractGeometryV2* rbGeom = mSelectedFeature->geometry()->geometry()->clone();
QgsVectorLayer *vlayer = mSelectedFeature->vlayer();
if ( mCanvas->mapSettings().layerTransform( vlayer ) )
rbGeom->transform( *mCanvas->mapSettings().layerTransform( vlayer ) );
mSelectRubberBand->setGeometry( rbGeom );
}

void QgsMapToolNodeTool::selectedFeatureDestroyed()
{
QgsDebugCall;
Expand Down Expand Up @@ -361,6 +413,7 @@ void QgsMapToolNodeTool::canvasReleaseEvent( QgsMapMouseEvent* e )
{
// select another feature
mSelectedFeature->setSelectedFeature( mAnother, vlayer, mCanvas );
updateSelectFeature();
mIsPoint = vlayer->geometryType() == QGis::Point;
mSelectAnother = false;
}
Expand Down Expand Up @@ -459,6 +512,10 @@ void QgsMapToolNodeTool::cleanTool( bool deleteSelectedFeature )
{
removeRubberBands();

if ( mSelectRubberBand != NULL ) {
delete mSelectRubberBand;
mSelectRubberBand = NULL;
}
if ( mSelectedFeature )
{
QgsVectorLayer *vlayer = mSelectedFeature->vlayer();
Expand All @@ -469,7 +526,7 @@ void QgsMapToolNodeTool::cleanTool( bool deleteSelectedFeature )
disconnect( vlayer, SIGNAL( editingStopped() ), this, SLOT( editingToggled() ) );

if ( deleteSelectedFeature ) delete mSelectedFeature;
mSelectedFeature = 0;
mSelectedFeature = NULL;
}
if ( mNodeEditor )
{
Expand Down
13 changes: 13 additions & 0 deletions src/app/nodetool/qgsmaptoolnodetool.h
Expand Up @@ -61,6 +61,16 @@ class QgsMapToolNodeTool: public QgsMapToolEdit
void editingToggled();

private:
/**
* Get the feature on the mouse click
*/
QgsFeature getFeatureAtPoint( QgsMapMouseEvent* e );

/**
* Update select feature rubber band
*/
void updateSelectFeature();

/**
* Deletes the rubber band pointers and clears mRubberBands
*/
Expand Down Expand Up @@ -116,6 +126,9 @@ class QgsMapToolNodeTool: public QgsMapToolEdit
/** Rubber bands during node move */
QMap<QgsFeatureId, QgsGeometryRubberBand*> mMoveRubberBands;

/** Rubber band for selected feature */
QgsGeometryRubberBand* mSelectRubberBand;

/** Vertices of features to move */
QMap<QgsFeatureId, QList< QPair<QgsVertexId, QgsPointV2> > > mMoveVertices;

Expand Down
9 changes: 7 additions & 2 deletions src/gui/qgsmapcanvassnapper.cpp
Expand Up @@ -62,7 +62,8 @@ void QgsMapCanvasSnapper::setMapCanvas( QgsMapCanvas* canvas )
int QgsMapCanvasSnapper::snapToCurrentLayer( const QPoint& p, QList<QgsSnappingResult>& results,
QgsSnapper::SnappingType snap_to,
double snappingTol,
const QList<QgsPoint>& excludePoints )
const QList<QgsPoint>& excludePoints,
bool allResutInTolerance )
{
results.clear();

Expand All @@ -71,7 +72,11 @@ int QgsMapCanvasSnapper::snapToCurrentLayer( const QPoint& p, QList<QgsSnappingR

//topological editing on?
int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 );
if ( topologicalEditing == 0 )
if ( allResutInTolerance )
{
mSnapper->setSnapMode( QgsSnapper::SnapWithResultsWithinTolerances);
}
else if ( topologicalEditing == 0 )
{
mSnapper->setSnapMode( QgsSnapper::SnapWithOneResult );
}
Expand Down
6 changes: 4 additions & 2 deletions src/gui/qgsmapcanvassnapper.h
Expand Up @@ -50,8 +50,10 @@ class GUI_EXPORT QgsMapCanvasSnapper
@param results list to which the results are appended
@param snap_to snap to vertex or to segment
@param snappingTol snapping tolerance. -1 means that the search radius for vertex edits is taken
@param excludePoints a list with (map coordinate) points that should be excluded in the snapping result. Useful e.g. for vertex moves where a vertex should not be snapped to its original position*/
int snapToCurrentLayer( const QPoint& p, QList<QgsSnappingResult>& results, QgsSnapper::SnappingType snap_to, double snappingTol = -1, const QList<QgsPoint>& excludePoints = QList<QgsPoint>() );
@param excludePoints a list with (map coordinate) points that should be excluded in the snapping result. Useful e.g. for vertex moves where a vertex should not be snapped to its original position
@param allResutInTolerance return all thew results in the tollerance
*/
int snapToCurrentLayer( const QPoint& p, QList<QgsSnappingResult>& results, QgsSnapper::SnappingType snap_to, double snappingTol = -1, const QList<QgsPoint>& excludePoints = QList<QgsPoint>(), bool allResutInTolerance = false );
/** Snaps to the background layers. This method is useful to align the features of the
edited layers to those of other layers (as described in the project properties).
Uses snap mode QgsSnapper::SnapWithOneResult. Therefore, only the
Expand Down

1 comment on commit 9b192d4

@oper4
Copy link

@oper4 oper4 commented on 9b192d4 Nov 8, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi!

I'm the author of "bug" report (https://hub.qgis.org/issues/13793) - maybe it wolud be better in case of polygons just to show "semitransparent red" outline?
That's my point of view against "red semitransparent background" - when I edit common boundary of two polygons (snapping options/enable topological editing) using Node tool now only one of them has that red background - so it's weird. Second thing - during editing if I move the feature I still see its old position as a red trace... it's on screencast:
https://www.dropbox.com/s/o9ixhygs87jb2v2/clip4.mp4?dl=0

Currently all the time I digitize sth from rasters and wms's - that's why all my polygon layers have transparent background - and now it's useless to use Node tool as it appears sth on the screen.

Thanks

Piotr Kania

Please sign in to comment.