mirror of
https://github.com/qgis/QGIS.git
synced 2025-03-01 00:46:20 -05:00
Merge pull request #2315 from mhugent/nodetool_no_clickclick
Node tool without click-click mode
This commit is contained in:
commit
ed57c783ce
@ -34,8 +34,12 @@ QgsMapToolNodeTool::QgsMapToolNodeTool( QgsMapCanvas* canvas )
|
||||
: QgsMapToolEdit( canvas )
|
||||
, mSelectedFeature( 0 )
|
||||
, mNodeEditor( 0 )
|
||||
, mMoving( true )
|
||||
, mSelectAnother( false )
|
||||
, mSelectionRubberBand( 0 )
|
||||
, mRect( 0 )
|
||||
, mIsPoint( false )
|
||||
, mDeselectOnRelease( -1 )
|
||||
{
|
||||
mSnapper.setMapCanvas( canvas );
|
||||
}
|
||||
@ -45,94 +49,66 @@ QgsMapToolNodeTool::~QgsMapToolNodeTool()
|
||||
cleanTool();
|
||||
}
|
||||
|
||||
void QgsMapToolNodeTool::canvasPressEvent( QgsMapMouseEvent* e )
|
||||
void QgsMapToolNodeTool::createTopologyRubberBands()
|
||||
{
|
||||
removeRubberBands();
|
||||
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() );
|
||||
if ( !vlayer )
|
||||
QgsVectorLayer* vlayer = mSelectedFeature->vlayer();
|
||||
|
||||
foreach ( const QgsVertexEntry* vertexEntry, mSelectedFeature->vertexMap() )
|
||||
{
|
||||
return;
|
||||
if ( !vertexEntry->isSelected() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool ctrlModifier = e->modifiers() & Qt::ControlModifier;
|
||||
QList<QgsSnappingResult> snapResults;
|
||||
|
||||
QgsFeatureId bkFeatureId = 0;
|
||||
if ( mSelectedFeature )
|
||||
// Snap vertex
|
||||
QMultiMap<double, QgsSnappingResult> snapResults;
|
||||
vlayer->snapWithContext( vertexEntry->pointV1(), ZERO_TOLERANCE, snapResults, QgsSnapper::SnapToVertex );
|
||||
foreach ( const QgsSnappingResult& snapResult, snapResults.values() )
|
||||
{
|
||||
bkFeatureId = mSelectedFeature->featureId();
|
||||
// Get geometry of snapped feature
|
||||
QgsFeatureId snapFeatureId = snapResult.snappedAtGeometry;
|
||||
QgsFeature feature;
|
||||
if ( !vlayer->getFeatures( QgsFeatureRequest( snapFeatureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( feature ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool hasVertexSelection = mSelectedFeature && mSelectedFeature->hasSelection();
|
||||
|
||||
if ( !mSelectedFeature || !hasVertexSelection )
|
||||
// Get VertexId of snapped vertex
|
||||
QgsVertexId vid;
|
||||
if ( !feature.geometry()->vertexIdFromVertexNr( snapResult.snappedVertexNr, vid ) )
|
||||
{
|
||||
//try to select feature
|
||||
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() );
|
||||
if ( !vlayer )
|
||||
{
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
mSnapper.snapToCurrentLayer( e->pos(), snapResults, QgsSnapper::SnapToVertexAndSegment, -1 );
|
||||
|
||||
if ( snapResults.size() < 1 )
|
||||
// Add rubberband if not already added
|
||||
if ( !mMoveRubberBands.contains( snapFeatureId ) )
|
||||
{
|
||||
emit messageEmitted( tr( "could not snap to a segment on the current layer." ) );
|
||||
return;
|
||||
QgsGeometryRubberBand* rb = new QgsGeometryRubberBand( mCanvas, feature.geometry()->type() );
|
||||
rb->setOutlineColor( Qt::blue );
|
||||
rb->setBrushStyle( Qt::NoBrush );
|
||||
rb->setOutlineWidth( 2 );
|
||||
QgsAbstractGeometryV2* rbGeom = feature.geometry()->geometry()->clone();
|
||||
if ( mCanvas->mapSettings().layerTransform( vlayer ) )
|
||||
rbGeom->transform( *mCanvas->mapSettings().layerTransform( vlayer ) );
|
||||
rb->setGeometry( rbGeom );
|
||||
mMoveRubberBands.insert( snapFeatureId, rb );
|
||||
}
|
||||
|
||||
// remove previous warning
|
||||
emit messageDiscarded();
|
||||
|
||||
if ( !mSelectedFeature || snapResults[0].snappedAtGeometry != mSelectedFeature->featureId() )
|
||||
{
|
||||
delete mSelectedFeature;
|
||||
mSelectedFeature = new QgsSelectedFeature( snapResults[0].snappedAtGeometry, vlayer, mCanvas );
|
||||
connect( QgisApp::instance()->layerTreeView(), SIGNAL( currentLayerChanged( QgsMapLayer* ) ), this, SLOT( currentLayerChanged( QgsMapLayer* ) ) );
|
||||
connect( mSelectedFeature, SIGNAL( destroyed() ), this, SLOT( selectedFeatureDestroyed() ) );
|
||||
connect( mSelectedFeature, SIGNAL( lastVertexChanged( const QgsPointV2& ) ), this, SLOT( changeLastVertex( const QgsPointV2& ) ) );
|
||||
connect( vlayer, SIGNAL( editingStopped() ), this, SLOT( editingToggled() ) );
|
||||
mIsPoint = vlayer->geometryType() == QGis::Point;
|
||||
mNodeEditor = new QgsNodeEditor( vlayer, mSelectedFeature, mCanvas );
|
||||
QgisApp::instance()->addDockWidget( Qt::LeftDockWidgetArea, mNodeEditor );
|
||||
}
|
||||
}
|
||||
|
||||
//select or move vertices if selected feature has not been changed
|
||||
QgsPoint layerPoint = toLayerCoordinates( vlayer, e->mapPoint() );
|
||||
if ( mSelectedFeature->featureId() == bkFeatureId )
|
||||
{
|
||||
if ( mSelectedFeature->hasSelection() && !ctrlModifier ) //move vertices
|
||||
{
|
||||
QgsPoint targetCoords = layerPoint;
|
||||
mSelectedFeature->moveSelectedVertexes( targetCoords - mClosestLayerVertex );
|
||||
mCanvas->refresh();
|
||||
mSelectedFeature->deselectAllVertexes();
|
||||
}
|
||||
else //add vertex selection
|
||||
{
|
||||
int atVertex, beforeVertex, afterVertex;
|
||||
double dist;
|
||||
QgsPoint closestLayerVertex = mSelectedFeature->geometry()->closestVertex( layerPoint, atVertex, beforeVertex, afterVertex, dist );
|
||||
mSelectedFeature->selectVertex( atVertex );
|
||||
// Add to list of vertices to be moved
|
||||
mMoveVertices[snapFeatureId].append( qMakePair( vid, toMapCoordinates( vlayer, feature.geometry()->geometry()->vertexAt( vid ) ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsMapToolNodeTool::canvasMoveEvent( QgsMapMouseEvent* e )
|
||||
{
|
||||
if ( !mSelectedFeature || !mSelectedFeature->hasSelection() )
|
||||
{
|
||||
if ( !mSelectedFeature || e->buttons() == Qt::NoButton )
|
||||
return;
|
||||
}
|
||||
|
||||
QgsVectorLayer* vlayer = mSelectedFeature->vlayer();
|
||||
if ( !vlayer )
|
||||
{
|
||||
return;
|
||||
}
|
||||
Q_ASSERT( vlayer );
|
||||
|
||||
mSelectAnother = false;
|
||||
|
||||
if ( mMoving )
|
||||
{
|
||||
if ( mMoveRubberBands.empty() )
|
||||
{
|
||||
QgsGeometryRubberBand* rb = new QgsGeometryRubberBand( mCanvas, mSelectedFeature->geometry()->type() );
|
||||
@ -144,7 +120,7 @@ void QgsMapToolNodeTool::canvasMoveEvent( QgsMapMouseEvent* e )
|
||||
rbGeom->transform( *mCanvas->mapSettings().layerTransform( vlayer ) );
|
||||
rb->setGeometry( rbGeom );
|
||||
mMoveRubberBands.insert( mSelectedFeature->featureId(), rb );
|
||||
Q_FOREACH ( const QgsVertexEntry* vertexEntry, mSelectedFeature->vertexMap() )
|
||||
foreach ( const QgsVertexEntry* vertexEntry, mSelectedFeature->vertexMap() )
|
||||
{
|
||||
if ( vertexEntry->isSelected() )
|
||||
mMoveVertices[mSelectedFeature->featureId()].append( qMakePair( vertexEntry->vertexId(), toMapCoordinates( vlayer, vertexEntry->point() ) ) );
|
||||
@ -158,22 +134,181 @@ void QgsMapToolNodeTool::canvasMoveEvent( QgsMapMouseEvent* e )
|
||||
{
|
||||
// move rubberband
|
||||
QList<QgsSnappingResult> snapResults;
|
||||
mSnapper.snapToBackgroundLayers( e->pos(), snapResults, QList<QgsPoint>() << mClosestLayerVertex );
|
||||
mSnapper.snapToBackgroundLayers( e->pos(), snapResults, QList<QgsPoint>() << mClosestMapVertex );
|
||||
|
||||
QgsPoint origPos = toMapCoordinates( vlayer, mClosestLayerVertex );
|
||||
QgsPoint curPos = snapPointFromResults( snapResults, e->pos() );
|
||||
double diffX = curPos.x() - origPos.x();
|
||||
double diffY = curPos.y() - origPos.y();
|
||||
QgsPoint pressPos = snapResults.size() > 0 ? mClosestMapVertex : toMapCoordinates( mPressCoordinates );
|
||||
double deltaX = curPos.x() - pressPos.x();
|
||||
double deltaY = curPos.y() - pressPos.y();
|
||||
|
||||
Q_FOREACH ( const QgsFeatureId& fid, mMoveRubberBands.keys() )
|
||||
foreach ( const QgsFeatureId& fid, mMoveRubberBands.keys() )
|
||||
{
|
||||
typedef QPair<QgsVertexId, QgsPointV2> MoveVertex;
|
||||
Q_FOREACH ( const MoveVertex& pair, mMoveVertices[fid] )
|
||||
foreach ( const MoveVertex& pair, mMoveVertices[fid] )
|
||||
{
|
||||
QgsPointV2 pos = pair.second;
|
||||
pos.setX( pos.x() + diffX );
|
||||
pos.setY( pos.y() + diffY );
|
||||
mMoveRubberBands.value( fid )->moveVertex( pair.first, pos );
|
||||
QgsPointV2 newPos( pair.second.x() + deltaX, pair.second.y() + deltaY );
|
||||
mMoveRubberBands.value( fid )->moveVertex( pair.first, newPos );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !mRect )
|
||||
{
|
||||
mSelectionRubberBand = new QRubberBand( QRubberBand::Rectangle, mCanvas );
|
||||
mRect = new QRect();
|
||||
mRect->setTopLeft( mPressCoordinates );
|
||||
}
|
||||
mRect->setBottomRight( e->pos() );
|
||||
QRect normalizedRect = mRect->normalized();
|
||||
mSelectionRubberBand->setGeometry( normalizedRect );
|
||||
mSelectionRubberBand->show();
|
||||
}
|
||||
}
|
||||
|
||||
void QgsMapToolNodeTool::canvasPressEvent( QgsMapMouseEvent* e )
|
||||
{
|
||||
QgsDebugCall;
|
||||
|
||||
mPressCoordinates = e->pos();
|
||||
bool ctrlModifier = e->modifiers() & Qt::ControlModifier;
|
||||
QList<QgsSnappingResult> snapResults;
|
||||
if ( !mSelectedFeature )
|
||||
{
|
||||
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() );
|
||||
if ( !vlayer )
|
||||
return;
|
||||
|
||||
mSelectAnother = false;
|
||||
mSnapper.snapToCurrentLayer( e->pos(), snapResults, QgsSnapper::SnapToVertexAndSegment, -1 );
|
||||
|
||||
if ( snapResults.size() < 1 )
|
||||
{
|
||||
emit messageEmitted( tr( "could not snap to a segment on the current layer." ) );
|
||||
return;
|
||||
}
|
||||
|
||||
// remove previous warning
|
||||
emit messageDiscarded();
|
||||
|
||||
mSelectedFeature = new QgsSelectedFeature( snapResults[0].snappedAtGeometry, vlayer, mCanvas );
|
||||
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() ) );
|
||||
mIsPoint = vlayer->geometryType() == QGis::Point;
|
||||
mNodeEditor = new QgsNodeEditor( vlayer, mSelectedFeature, mCanvas );
|
||||
QgisApp::instance()->addDockWidget( Qt::LeftDockWidgetArea, mNodeEditor );
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove previous warning
|
||||
emit messageDiscarded();
|
||||
|
||||
QgsVectorLayer *vlayer = mSelectedFeature->vlayer();
|
||||
Q_ASSERT( vlayer );
|
||||
|
||||
// some feature already selected
|
||||
QgsPoint layerCoordPoint = toLayerCoordinates( vlayer, e->pos() );
|
||||
|
||||
double tol = QgsTolerance::vertexSearchRadius( vlayer, mCanvas->mapSettings() );
|
||||
|
||||
// get geometry and find if snapping is near it
|
||||
int atVertex, beforeVertex, afterVertex;
|
||||
double dist;
|
||||
QgsPoint closestLayerVertex = mSelectedFeature->geometry()->closestVertex( layerCoordPoint, atVertex, beforeVertex, afterVertex, dist );
|
||||
dist = sqrt( dist );
|
||||
|
||||
mSnapper.snapToCurrentLayer( e->pos(), snapResults, QgsSnapper::SnapToVertex, tol );
|
||||
if ( dist <= tol )
|
||||
{
|
||||
// some vertex selected
|
||||
mMoving = true;
|
||||
mClosestMapVertex = toMapCoordinates( vlayer, closestLayerVertex );
|
||||
if ( mMoving )
|
||||
{
|
||||
if ( mSelectedFeature->isSelected( atVertex ) )
|
||||
{
|
||||
mDeselectOnRelease = atVertex;
|
||||
}
|
||||
else if ( ctrlModifier )
|
||||
{
|
||||
mSelectedFeature->invertVertexSelection( atVertex );
|
||||
}
|
||||
else
|
||||
{
|
||||
mSelectedFeature->deselectAllVertexes();
|
||||
mSelectedFeature->selectVertex( atVertex );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// select another feature
|
||||
mAnother = snapResults.first().snappedAtGeometry;
|
||||
mSelectAnother = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no near vertex to snap
|
||||
// unless point layer, try segment
|
||||
if ( !mIsPoint )
|
||||
mSnapper.snapToCurrentLayer( e->pos(), snapResults, QgsSnapper::SnapToSegment, tol );
|
||||
|
||||
if ( snapResults.size() > 0 )
|
||||
{
|
||||
// need to check all if there is a point in the feature
|
||||
mAnother = snapResults.first().snappedAtGeometry;
|
||||
mSelectAnother = true;
|
||||
QList<QgsSnappingResult>::iterator it = snapResults.begin();
|
||||
QgsSnappingResult snapResult;
|
||||
for ( ; it != snapResults.end(); ++it )
|
||||
{
|
||||
if ( it->snappedAtGeometry == mSelectedFeature->featureId() )
|
||||
{
|
||||
snapResult = *it;
|
||||
mAnother = 0;
|
||||
mSelectAnother = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !mSelectAnother )
|
||||
{
|
||||
mMoving = true;
|
||||
mClosestMapVertex = toMapCoordinates( vlayer, closestLayerVertex );
|
||||
|
||||
if ( mIsPoint )
|
||||
{
|
||||
if ( !ctrlModifier )
|
||||
{
|
||||
mSelectedFeature->deselectAllVertexes();
|
||||
mSelectedFeature->selectVertex( snapResult.snappedVertexNr );
|
||||
}
|
||||
else
|
||||
{
|
||||
mSelectedFeature->invertVertexSelection( snapResult.snappedVertexNr );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !ctrlModifier )
|
||||
{
|
||||
mSelectedFeature->deselectAllVertexes();
|
||||
mSelectedFeature->selectVertex( snapResult.afterVertexNr );
|
||||
mSelectedFeature->selectVertex( snapResult.beforeVertexNr );
|
||||
}
|
||||
else
|
||||
{
|
||||
mSelectedFeature->invertVertexSelection( snapResult.afterVertexNr );
|
||||
mSelectedFeature->invertVertexSelection( snapResult.beforeVertexNr );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( !ctrlModifier )
|
||||
{
|
||||
mSelectedFeature->deselectAllVertexes();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -198,15 +333,129 @@ void QgsMapToolNodeTool::editingToggled()
|
||||
cleanTool();
|
||||
}
|
||||
|
||||
void QgsMapToolNodeTool::canvasReleaseEvent( QgsMapMouseEvent* e )
|
||||
{
|
||||
if ( !mSelectedFeature )
|
||||
return;
|
||||
|
||||
removeRubberBands();
|
||||
|
||||
QgsVectorLayer *vlayer = mSelectedFeature->vlayer();
|
||||
Q_ASSERT( vlayer );
|
||||
|
||||
bool ctrlModifier = e->modifiers() & Qt::ControlModifier;
|
||||
|
||||
if ( mRect )
|
||||
{
|
||||
delete mSelectionRubberBand;
|
||||
mSelectionRubberBand = 0;
|
||||
delete mRect;
|
||||
mRect = 0;
|
||||
}
|
||||
|
||||
if ( mPressCoordinates == e->pos() )
|
||||
{
|
||||
if ( mSelectAnother )
|
||||
{
|
||||
// select another feature
|
||||
mSelectedFeature->setSelectedFeature( mAnother, vlayer, mCanvas );
|
||||
mIsPoint = vlayer->geometryType() == QGis::Point;
|
||||
mSelectAnother = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( mMoving )
|
||||
{
|
||||
mMoving = false;
|
||||
|
||||
QList<QgsSnappingResult> snapResults;
|
||||
mSnapper.snapToBackgroundLayers( e->pos(), snapResults, QList<QgsPoint>() << mClosestMapVertex );
|
||||
|
||||
QgsPoint releaseLayerCoords = toLayerCoordinates( vlayer, snapPointFromResults( snapResults, e->pos() ) );
|
||||
|
||||
QgsPoint pressLayerCoords;
|
||||
if ( snapResults.size() > 0 )
|
||||
{
|
||||
pressLayerCoords = toLayerCoordinates( vlayer, mClosestMapVertex );
|
||||
|
||||
int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 );
|
||||
if ( topologicalEditing )
|
||||
{
|
||||
insertSegmentVerticesForSnap( snapResults, vlayer );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pressLayerCoords = toLayerCoordinates( vlayer, mPressCoordinates );
|
||||
}
|
||||
|
||||
mSelectedFeature->moveSelectedVertexes( releaseLayerCoords - pressLayerCoords );
|
||||
mCanvas->refresh();
|
||||
}
|
||||
else // selecting vertexes by rubberband
|
||||
{
|
||||
// coordinates has to be coordinates from layer not canvas
|
||||
QgsRectangle r( toLayerCoordinates( vlayer, mPressCoordinates ),
|
||||
toLayerCoordinates( vlayer, e->pos() ) );
|
||||
|
||||
QList<QgsVertexEntry*> &vertexMap = mSelectedFeature->vertexMap();
|
||||
if ( !ctrlModifier )
|
||||
{
|
||||
mSelectedFeature->deselectAllVertexes();
|
||||
}
|
||||
|
||||
for ( int i = 0; i < vertexMap.size(); i++ )
|
||||
{
|
||||
if ( r.contains( vertexMap[i]->pointV1() ) )
|
||||
{
|
||||
// inverting selection is enough because all were deselected if ctrl is not pressed
|
||||
mSelectedFeature->invertVertexSelection( i );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mMoving = false;
|
||||
|
||||
if ( mDeselectOnRelease != -1 )
|
||||
{
|
||||
if ( ctrlModifier )
|
||||
{
|
||||
mSelectedFeature->invertVertexSelection( mDeselectOnRelease );
|
||||
}
|
||||
else
|
||||
{
|
||||
mSelectedFeature->deselectAllVertexes();
|
||||
mSelectedFeature->selectVertex( mDeselectOnRelease );
|
||||
}
|
||||
|
||||
mDeselectOnRelease = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void QgsMapToolNodeTool::deactivate()
|
||||
{
|
||||
cleanTool();
|
||||
|
||||
mSelectionRubberBand = 0;
|
||||
mSelectAnother = false;
|
||||
mMoving = true;
|
||||
|
||||
QgsMapTool::deactivate();
|
||||
}
|
||||
|
||||
void QgsMapToolNodeTool::removeRubberBands()
|
||||
{
|
||||
qDeleteAll( mMoveRubberBands );
|
||||
mMoveRubberBands.clear();
|
||||
mMoveVertices.clear();
|
||||
}
|
||||
|
||||
void QgsMapToolNodeTool::cleanTool( bool deleteSelectedFeature )
|
||||
{
|
||||
removeRubberBands();
|
||||
|
||||
if ( mSelectedFeature )
|
||||
{
|
||||
QgsVectorLayer *vlayer = mSelectedFeature->vlayer();
|
||||
@ -238,6 +487,7 @@ void QgsMapToolNodeTool::canvasDoubleClickEvent( QgsMapMouseEvent* e )
|
||||
QMultiMap<double, QgsSnappingResult> currentResultList;
|
||||
|
||||
QList<QgsSnappingResult> snapResults;
|
||||
mMoving = false;
|
||||
double tol = QgsTolerance::vertexSearchRadius( vlayer, mCanvas->mapSettings() );
|
||||
mSnapper.snapToCurrentLayer( e->pos(), snapResults, QgsSnapper::SnapToSegment, tol );
|
||||
if ( snapResults.size() < 1 ||
|
||||
@ -286,6 +536,7 @@ void QgsMapToolNodeTool::keyPressEvent( QKeyEvent* e )
|
||||
return;
|
||||
|
||||
mSelectedFeature->deleteSelectedVertexes();
|
||||
safeSelectVertex( firstSelectedIndex );
|
||||
mCanvas->refresh();
|
||||
|
||||
// Override default shortcut management in MapCanvas
|
||||
@ -334,10 +585,6 @@ void QgsMapToolNodeTool::safeSelectVertex( int vertexNr )
|
||||
if ( mSelectedFeature )
|
||||
{
|
||||
int n = mSelectedFeature->vertexMap().size();
|
||||
if ( n < 1 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
mSelectedFeature->selectVertex(( vertexNr + n ) % n );
|
||||
}
|
||||
}
|
||||
@ -374,64 +621,3 @@ int QgsMapToolNodeTool::insertSegmentVerticesForSnap( const QList<QgsSnappingRes
|
||||
|
||||
return editedLayer->insertSegmentVerticesForSnap( transformedSnapResults );
|
||||
}
|
||||
|
||||
void QgsMapToolNodeTool::changeLastVertex( const QgsPointV2& pt )
|
||||
{
|
||||
mClosestLayerVertex.setX( pt.x() );
|
||||
mClosestLayerVertex.setY( pt.y() );
|
||||
}
|
||||
|
||||
void QgsMapToolNodeTool::removeRubberBands()
|
||||
{
|
||||
qDeleteAll( mMoveRubberBands );
|
||||
mMoveRubberBands.clear();
|
||||
mMoveVertices.clear();
|
||||
}
|
||||
|
||||
void QgsMapToolNodeTool::createTopologyRubberBands()
|
||||
{
|
||||
QgsVectorLayer* vlayer = mSelectedFeature->vlayer();
|
||||
|
||||
Q_FOREACH ( const QgsVertexEntry* vertexEntry, mSelectedFeature->vertexMap() )
|
||||
{
|
||||
if ( !vertexEntry->isSelected() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Snap vertex
|
||||
QMultiMap<double, QgsSnappingResult> snapResults;
|
||||
vlayer->snapWithContext( vertexEntry->pointV1(), ZERO_TOLERANCE, snapResults, QgsSnapper::SnapToVertex );
|
||||
Q_FOREACH ( const QgsSnappingResult& snapResult, snapResults.values() )
|
||||
{
|
||||
// Get geometry of snapped feature
|
||||
QgsFeatureId snapFeatureId = snapResult.snappedAtGeometry;
|
||||
QgsFeature feature;
|
||||
if ( !vlayer->getFeatures( QgsFeatureRequest( snapFeatureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( feature ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Get VertexId of snapped vertex
|
||||
QgsVertexId vid;
|
||||
if ( !feature.constGeometry()->vertexIdFromVertexNr( snapResult.snappedVertexNr, vid ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Add rubberband if not already added
|
||||
if ( !mMoveRubberBands.contains( snapFeatureId ) )
|
||||
{
|
||||
QgsGeometryRubberBand* rb = new QgsGeometryRubberBand( mCanvas, feature.constGeometry()->type() );
|
||||
rb->setOutlineColor( Qt::blue );
|
||||
rb->setBrushStyle( Qt::NoBrush );
|
||||
rb->setOutlineWidth( 2 );
|
||||
QgsAbstractGeometryV2* rbGeom = feature.constGeometry()->geometry()->clone();
|
||||
if ( mCanvas->mapSettings().layerTransform( vlayer ) )
|
||||
rbGeom->transform( *mCanvas->mapSettings().layerTransform( vlayer ) );
|
||||
rb->setGeometry( rbGeom );
|
||||
mMoveRubberBands.insert( snapFeatureId, rb );
|
||||
}
|
||||
// Add to list of vertices to be moved
|
||||
mMoveVertices[snapFeatureId].append( qMakePair( vid, toMapCoordinates( vlayer, feature.constGeometry()->geometry()->vertexAt( vid ) ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,18 +34,18 @@ class QgsMapToolNodeTool: public QgsMapToolEdit
|
||||
QgsMapToolNodeTool( QgsMapCanvas* canvas );
|
||||
virtual ~QgsMapToolNodeTool();
|
||||
|
||||
void canvasDoubleClickEvent( QgsMapMouseEvent* e ) override;
|
||||
|
||||
//! mouse press event in map coordinates (eventually filtered) to be redefined in subclass
|
||||
void canvasPressEvent( QgsMapMouseEvent* e ) override;
|
||||
|
||||
//! mouse move event in map coordinates (eventually filtered) to be redefined in subclass
|
||||
void canvasMoveEvent( QgsMapMouseEvent* e ) override;
|
||||
|
||||
void keyPressEvent( QKeyEvent* e ) override;
|
||||
void canvasDoubleClickEvent( QgsMapMouseEvent* e ) override;
|
||||
|
||||
void canvasPressEvent( QgsMapMouseEvent* e ) override;
|
||||
|
||||
void canvasReleaseEvent( QgsMapMouseEvent* e ) override;
|
||||
|
||||
void keyPressEvent( QKeyEvent* e );
|
||||
|
||||
//! called when map tool is being deactivated
|
||||
void deactivate() override;
|
||||
void deactivate();
|
||||
|
||||
public slots:
|
||||
void selectedFeatureDestroyed();
|
||||
@ -60,19 +60,12 @@ class QgsMapToolNodeTool: public QgsMapToolEdit
|
||||
*/
|
||||
void editingToggled();
|
||||
|
||||
void changeLastVertex( const QgsPointV2& pt );
|
||||
|
||||
private:
|
||||
/**
|
||||
* Deletes the rubber band pointers and clears mRubberBands
|
||||
*/
|
||||
void removeRubberBands();
|
||||
|
||||
/**
|
||||
* Creates rubber bands for ther features when topology editing is enabled
|
||||
*/
|
||||
void createTopologyRubberBands();
|
||||
|
||||
/**
|
||||
* Disconnects signals and clears objects
|
||||
*/
|
||||
@ -86,6 +79,11 @@ class QgsMapToolNodeTool: public QgsMapToolEdit
|
||||
*/
|
||||
bool checkCorrectnessOfFeature( QgsVectorLayer* vlayer );
|
||||
|
||||
/**
|
||||
* Creates rubber bands for ther features when topology editing is enabled
|
||||
*/
|
||||
void createTopologyRubberBands();
|
||||
|
||||
/**
|
||||
* Returns the index of first selected vertex, -1 when all unselected
|
||||
*/
|
||||
@ -114,17 +112,35 @@ class QgsMapToolNodeTool: public QgsMapToolEdit
|
||||
and applies it to the map canvas*/
|
||||
QgsMapCanvasSnapper mSnapper;
|
||||
|
||||
/** Rubber bands during node move */
|
||||
QMap<QgsFeatureId, QgsGeometryRubberBand*> mMoveRubberBands;
|
||||
|
||||
/** Vertices of features to move */
|
||||
QMap<QgsFeatureId, QList< QPair<QgsVertexId, QgsPointV2> > > mMoveVertices;
|
||||
|
||||
/** Object containing selected feature and it's vertexes */
|
||||
QgsSelectedFeature *mSelectedFeature;
|
||||
|
||||
/** Dock widget which allows to edit vertices */
|
||||
QgsNodeEditor* mNodeEditor;
|
||||
|
||||
/** Flag if moving of vertexes is occuring */
|
||||
bool mMoving;
|
||||
|
||||
/** Flag if selection of another feature can occur */
|
||||
bool mSelectAnother;
|
||||
|
||||
/** Feature id of another feature where user clicked */
|
||||
QgsFeatureId mAnother;
|
||||
|
||||
/** Stored position of last press down action to count how much vertexes should be moved */
|
||||
QPoint mPressCoordinates;
|
||||
|
||||
/** Closest vertex to click in map coordinates */
|
||||
QgsPoint mClosestLayerVertex;
|
||||
QgsPoint mClosestMapVertex;
|
||||
|
||||
/** Active rubberband for selecting vertexes */
|
||||
QRubberBand *mSelectionRubberBand;
|
||||
|
||||
/** Rectangle defining area for selecting vertexes */
|
||||
QRect* mRect;
|
||||
@ -132,11 +148,8 @@ class QgsMapToolNodeTool: public QgsMapToolEdit
|
||||
/** Flag to tell if edition points */
|
||||
bool mIsPoint;
|
||||
|
||||
/** Rubber bands during node move */
|
||||
QMap<QgsFeatureId, QgsGeometryRubberBand*> mMoveRubberBands;
|
||||
|
||||
/** Vertices of features to move */
|
||||
QMap<QgsFeatureId, QList< QPair<QgsVertexId, QgsPointV2> > > mMoveVertices;
|
||||
/** Vertex to deselect on release */
|
||||
int mDeselectOnRelease;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -36,15 +36,13 @@ static const int MinRadiusRole = Qt::UserRole + 1;
|
||||
class CoordinateItemDelegate : public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
|
||||
QString displayText( const QVariant & value, const QLocale & locale ) const override
|
||||
QString displayText( const QVariant & value, const QLocale & locale ) const
|
||||
{
|
||||
return locale.toString( value.toDouble(), 'f', 4 );
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
QWidget* createEditor( QWidget * parent, const QStyleOptionViewItem &, const QModelIndex & index ) const override
|
||||
QWidget* createEditor( QWidget * parent, const QStyleOptionViewItem & /*option*/, const QModelIndex & index ) const
|
||||
{
|
||||
QLineEdit* lineEdit = new QLineEdit( parent );
|
||||
QDoubleValidator* validator = new QDoubleValidator();
|
||||
@ -53,8 +51,7 @@ class CoordinateItemDelegate : public QStyledItemDelegate
|
||||
lineEdit->setValidator( validator );
|
||||
return lineEdit;
|
||||
}
|
||||
|
||||
void setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const override
|
||||
void setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
|
||||
{
|
||||
QLineEdit* lineEdit = qobject_cast<QLineEdit*>( editor );
|
||||
if ( lineEdit->hasAcceptableInput() )
|
||||
@ -112,7 +109,7 @@ void QgsNodeEditor::rebuildTable()
|
||||
mTableWidget->setRowCount( 0 );
|
||||
int row = 0;
|
||||
bool hasR = false;
|
||||
Q_FOREACH ( const QgsVertexEntry* entry, mSelectedFeature->vertexMap() )
|
||||
foreach ( const QgsVertexEntry* entry, mSelectedFeature->vertexMap() )
|
||||
{
|
||||
mTableWidget->insertRow( row );
|
||||
|
||||
@ -170,8 +167,8 @@ void QgsNodeEditor::rebuildTable()
|
||||
|
||||
++row;
|
||||
}
|
||||
mTableWidget->setColumnHidden( 3, mSelectedFeature->vertexMap().size() < 1 || !mSelectedFeature->vertexMap()[0]->point().is3D() );
|
||||
mTableWidget->setColumnHidden( 4, mSelectedFeature->vertexMap().size() < 1 || !mSelectedFeature->vertexMap()[0]->point().isMeasure() );
|
||||
mTableWidget->setColumnHidden( 3, !mSelectedFeature->vertexMap()[0]->point().is3D() );
|
||||
mTableWidget->setColumnHidden( 4, !mSelectedFeature->vertexMap()[0]->point().isMeasure() );
|
||||
mTableWidget->setColumnHidden( 5, !hasR );
|
||||
mTableWidget->resizeColumnToContents( 0 );
|
||||
mTableWidget->blockSignals( false );
|
||||
@ -228,14 +225,12 @@ void QgsNodeEditor::updateTableSelection()
|
||||
|
||||
void QgsNodeEditor::updateNodeSelection()
|
||||
{
|
||||
disconnect( mSelectedFeature, SIGNAL( selectionChanged() ), this, SLOT( updateTableSelection() ) );
|
||||
|
||||
mSelectedFeature->blockSignals( true );
|
||||
mSelectedFeature->deselectAllVertexes();
|
||||
Q_FOREACH ( const QModelIndex& index, mTableWidget->selectionModel()->selectedRows() )
|
||||
foreach ( const QModelIndex& index, mTableWidget->selectionModel()->selectedRows() )
|
||||
{
|
||||
int nodeIdx = mTableWidget->item( index.row(), 0 )->data( Qt::DisplayRole ).toInt();
|
||||
mSelectedFeature->selectVertex( nodeIdx );
|
||||
}
|
||||
|
||||
connect( mSelectedFeature, SIGNAL( selectionChanged() ), this, SLOT( updateTableSelection() ) );
|
||||
mSelectedFeature->blockSignals( false );
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ class QgsSelectedFeature;
|
||||
class QgsVectorLayer;
|
||||
class QTableWidget;
|
||||
|
||||
/** A widget to select and edit the vertex coordinates of a geometry numerically*/
|
||||
class QgsNodeEditor : public QDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -77,10 +77,8 @@ void QgsSelectedFeature::updateGeometry( QgsGeometry *geom )
|
||||
if ( !geom )
|
||||
{
|
||||
QgsFeature f;
|
||||
if ( mVlayer->getFeatures( QgsFeatureRequest().setFilterFid( mFeatureId ) ).nextFeature( f ) )
|
||||
{
|
||||
mGeometry = new QgsGeometry( *f.constGeometry() );
|
||||
}
|
||||
mVlayer->getFeatures( QgsFeatureRequest().setFilterFid( mFeatureId ) ).nextFeature( f );
|
||||
mGeometry = new QgsGeometry( *f.geometry() );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -232,7 +230,7 @@ void QgsSelectedFeature::validationFinished()
|
||||
void QgsSelectedFeature::deleteSelectedVertexes()
|
||||
{
|
||||
int nSelected = 0;
|
||||
Q_FOREACH ( QgsVertexEntry *entry, mVertexMap )
|
||||
foreach ( QgsVertexEntry *entry, mVertexMap )
|
||||
{
|
||||
if ( entry->isSelected() )
|
||||
nSelected++;
|
||||
@ -304,7 +302,7 @@ void QgsSelectedFeature::deleteSelectedVertexes()
|
||||
void QgsSelectedFeature::moveSelectedVertexes( const QgsVector &v )
|
||||
{
|
||||
int nUpdates = 0;
|
||||
Q_FOREACH ( QgsVertexEntry *entry, mVertexMap )
|
||||
foreach ( QgsVertexEntry *entry, mVertexMap )
|
||||
{
|
||||
if ( entry->isSelected() )
|
||||
nUpdates++;
|
||||
@ -377,7 +375,7 @@ void QgsSelectedFeature::replaceVertexMap()
|
||||
|
||||
void QgsSelectedFeature::deleteVertexMap()
|
||||
{
|
||||
Q_FOREACH ( QgsVertexEntry *entry, mVertexMap )
|
||||
foreach ( QgsVertexEntry *entry, mVertexMap )
|
||||
{
|
||||
delete entry;
|
||||
}
|
||||
@ -405,7 +403,7 @@ void QgsSelectedFeature::createVertexMap()
|
||||
updateGeometry( 0 );
|
||||
}
|
||||
|
||||
if ( !mGeometry || !mGeometry->geometry() )
|
||||
if ( !mGeometry )
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -433,7 +431,6 @@ void QgsSelectedFeature::selectVertex( int vertexNr )
|
||||
entry->setSelected();
|
||||
|
||||
emit selectionChanged();
|
||||
emit lastVertexChanged( entry->point() );
|
||||
}
|
||||
|
||||
void QgsSelectedFeature::deselectVertex( int vertexNr )
|
||||
@ -443,23 +440,8 @@ void QgsSelectedFeature::deselectVertex( int vertexNr )
|
||||
|
||||
QgsVertexEntry *entry = mVertexMap[vertexNr];
|
||||
entry->setSelected( false );
|
||||
|
||||
emit selectionChanged();
|
||||
|
||||
//todo: take another selected vertex as 'lastVertexChanged'
|
||||
QList<QgsVertexEntry*>::const_iterator vIt = mVertexMap.constBegin();
|
||||
for ( ; vIt != mVertexMap.constEnd(); ++vIt )
|
||||
{
|
||||
if (( *vIt )->isSelected() )
|
||||
{
|
||||
emit lastVertexChanged(( *vIt )->point() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( vIt == mVertexMap.constEnd() )
|
||||
{
|
||||
emit lastVertexChanged( QgsPointV2() ); //no selection anymore
|
||||
}
|
||||
}
|
||||
|
||||
void QgsSelectedFeature::deselectAllVertexes()
|
||||
@ -469,7 +451,6 @@ void QgsSelectedFeature::deselectAllVertexes()
|
||||
mVertexMap[i]->setSelected( false );
|
||||
}
|
||||
emit selectionChanged();
|
||||
emit lastVertexChanged( QgsPointV2() );
|
||||
}
|
||||
|
||||
void QgsSelectedFeature::invertVertexSelection( int vertexNr )
|
||||
@ -483,15 +464,11 @@ void QgsSelectedFeature::invertVertexSelection( int vertexNr )
|
||||
|
||||
entry->setSelected( selected );
|
||||
emit selectionChanged();
|
||||
if ( selected )
|
||||
{
|
||||
emit lastVertexChanged( entry->point() );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsSelectedFeature::updateVertexMarkersPosition()
|
||||
{
|
||||
Q_FOREACH ( QgsVertexEntry* vertexEntry, mVertexMap )
|
||||
foreach ( QgsVertexEntry* vertexEntry, mVertexMap )
|
||||
{
|
||||
vertexEntry->placeMarker();
|
||||
}
|
||||
@ -511,17 +488,3 @@ QgsVectorLayer* QgsSelectedFeature::vlayer()
|
||||
{
|
||||
return mVlayer;
|
||||
}
|
||||
|
||||
bool QgsSelectedFeature::hasSelection() const
|
||||
{
|
||||
bool hasSelection = false;
|
||||
QList<QgsVertexEntry*>::const_iterator vertexIt = mVertexMap.constBegin();
|
||||
for ( ; vertexIt != mVertexMap.constEnd(); ++vertexIt )
|
||||
{
|
||||
if (( *vertexIt )->isSelected() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return hasSelection;
|
||||
}
|
||||
|
@ -129,11 +129,8 @@ class QgsSelectedFeature: public QObject
|
||||
void beginGeometryChange();
|
||||
void endGeometryChange();
|
||||
|
||||
bool hasSelection() const;
|
||||
|
||||
signals:
|
||||
void selectionChanged();
|
||||
void lastVertexChanged( const QgsPointV2& pt );
|
||||
void vertexMapChanged();
|
||||
|
||||
public slots:
|
||||
|
Loading…
x
Reference in New Issue
Block a user