Merge pull request #2388 from sbrunner/node-tool-select-feature

Allow to select the feature on which the node tool works
This commit is contained in:
Matthias Kuhn 2015-11-07 20:19:28 +00:00
commit 9b192d4184
4 changed files with 89 additions and 12 deletions

View File

@ -26,6 +26,7 @@
#include "qgsproject.h" #include "qgsproject.h"
#include "qgsgeometryrubberband.h" #include "qgsgeometryrubberband.h"
#include "qgsvectorlayer.h" #include "qgsvectorlayer.h"
#include "qgsvectordataprovider.h"
#include <QMouseEvent> #include <QMouseEvent>
#include <QRubberBand> #include <QRubberBand>
@ -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 ) void QgsMapToolNodeTool::canvasPressEvent( QgsMapMouseEvent* e )
{ {
QgsDebugCall; QgsDebugCall;
@ -186,14 +203,25 @@ void QgsMapToolNodeTool::canvasPressEvent( QgsMapMouseEvent* e )
if ( snapResults.size() < 1 ) if ( snapResults.size() < 1 )
{ {
emit messageEmitted( tr( "could not snap to a segment on the current layer." ) ); QgsFeature feature = getFeatureAtPoint( e );
return; 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 mSelectedFeature = new QgsSelectedFeature( snapResults[0].snappedAtGeometry, vlayer, mCanvas );
emit messageDiscarded(); updateSelectFeature();
}
mSelectedFeature = new QgsSelectedFeature( snapResults[0].snappedAtGeometry, vlayer, mCanvas );
connect( QgisApp::instance()->layerTreeView(), SIGNAL( currentLayerChanged( QgsMapLayer* ) ), this, SLOT( currentLayerChanged( QgsMapLayer* ) ) ); connect( QgisApp::instance()->layerTreeView(), SIGNAL( currentLayerChanged( QgsMapLayer* ) ), this, SLOT( currentLayerChanged( QgsMapLayer* ) ) );
connect( mSelectedFeature, SIGNAL( destroyed() ), this, SLOT( selectedFeatureDestroyed() ) ); connect( mSelectedFeature, SIGNAL( destroyed() ), this, SLOT( selectedFeatureDestroyed() ) );
connect( vlayer, SIGNAL( editingStopped() ), this, SLOT( editingToggled() ) ); connect( vlayer, SIGNAL( editingStopped() ), this, SLOT( editingToggled() ) );
@ -254,7 +282,7 @@ void QgsMapToolNodeTool::canvasPressEvent( QgsMapMouseEvent* e )
// no near vertex to snap // no near vertex to snap
// unless point layer, try segment // unless point layer, try segment
if ( !mIsPoint ) 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 ) if ( snapResults.size() > 0 )
{ {
@ -310,11 +338,35 @@ void QgsMapToolNodeTool::canvasPressEvent( QgsMapMouseEvent* e )
else if ( !ctrlModifier ) else if ( !ctrlModifier )
{ {
mSelectedFeature->deselectAllVertexes(); 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() void QgsMapToolNodeTool::selectedFeatureDestroyed()
{ {
QgsDebugCall; QgsDebugCall;
@ -361,6 +413,7 @@ void QgsMapToolNodeTool::canvasReleaseEvent( QgsMapMouseEvent* e )
{ {
// select another feature // select another feature
mSelectedFeature->setSelectedFeature( mAnother, vlayer, mCanvas ); mSelectedFeature->setSelectedFeature( mAnother, vlayer, mCanvas );
updateSelectFeature();
mIsPoint = vlayer->geometryType() == QGis::Point; mIsPoint = vlayer->geometryType() == QGis::Point;
mSelectAnother = false; mSelectAnother = false;
} }
@ -459,6 +512,10 @@ void QgsMapToolNodeTool::cleanTool( bool deleteSelectedFeature )
{ {
removeRubberBands(); removeRubberBands();
if ( mSelectRubberBand != NULL ) {
delete mSelectRubberBand;
mSelectRubberBand = NULL;
}
if ( mSelectedFeature ) if ( mSelectedFeature )
{ {
QgsVectorLayer *vlayer = mSelectedFeature->vlayer(); QgsVectorLayer *vlayer = mSelectedFeature->vlayer();
@ -469,7 +526,7 @@ void QgsMapToolNodeTool::cleanTool( bool deleteSelectedFeature )
disconnect( vlayer, SIGNAL( editingStopped() ), this, SLOT( editingToggled() ) ); disconnect( vlayer, SIGNAL( editingStopped() ), this, SLOT( editingToggled() ) );
if ( deleteSelectedFeature ) delete mSelectedFeature; if ( deleteSelectedFeature ) delete mSelectedFeature;
mSelectedFeature = 0; mSelectedFeature = NULL;
} }
if ( mNodeEditor ) if ( mNodeEditor )
{ {

View File

@ -61,6 +61,16 @@ class QgsMapToolNodeTool: public QgsMapToolEdit
void editingToggled(); void editingToggled();
private: 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 * Deletes the rubber band pointers and clears mRubberBands
*/ */
@ -116,6 +126,9 @@ class QgsMapToolNodeTool: public QgsMapToolEdit
/** Rubber bands during node move */ /** Rubber bands during node move */
QMap<QgsFeatureId, QgsGeometryRubberBand*> mMoveRubberBands; QMap<QgsFeatureId, QgsGeometryRubberBand*> mMoveRubberBands;
/** Rubber band for selected feature */
QgsGeometryRubberBand* mSelectRubberBand;
/** Vertices of features to move */ /** Vertices of features to move */
QMap<QgsFeatureId, QList< QPair<QgsVertexId, QgsPointV2> > > mMoveVertices; QMap<QgsFeatureId, QList< QPair<QgsVertexId, QgsPointV2> > > mMoveVertices;

View File

@ -62,7 +62,8 @@ void QgsMapCanvasSnapper::setMapCanvas( QgsMapCanvas* canvas )
int QgsMapCanvasSnapper::snapToCurrentLayer( const QPoint& p, QList<QgsSnappingResult>& results, int QgsMapCanvasSnapper::snapToCurrentLayer( const QPoint& p, QList<QgsSnappingResult>& results,
QgsSnapper::SnappingType snap_to, QgsSnapper::SnappingType snap_to,
double snappingTol, double snappingTol,
const QList<QgsPoint>& excludePoints ) const QList<QgsPoint>& excludePoints,
bool allResutInTolerance )
{ {
results.clear(); results.clear();
@ -71,7 +72,11 @@ int QgsMapCanvasSnapper::snapToCurrentLayer( const QPoint& p, QList<QgsSnappingR
//topological editing on? //topological editing on?
int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 ); 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 ); mSnapper->setSnapMode( QgsSnapper::SnapWithOneResult );
} }

View File

@ -50,8 +50,10 @@ class GUI_EXPORT QgsMapCanvasSnapper
@param results list to which the results are appended @param results list to which the results are appended
@param snap_to snap to vertex or to segment @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 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*/ @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 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 /** 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). edited layers to those of other layers (as described in the project properties).
Uses snap mode QgsSnapper::SnapWithOneResult. Therefore, only the Uses snap mode QgsSnapper::SnapWithOneResult. Therefore, only the