From 9c2d70186f054b71f1b792d13133f3856c855bf3 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Wed, 16 Sep 2015 05:19:26 +0200 Subject: [PATCH] Node tool without click-click mode --- src/app/nodetool/qgsmaptoolnodetool.cpp | 528 ++++++++++++++++-------- src/app/nodetool/qgsmaptoolnodetool.h | 55 ++- src/app/nodetool/qgsnodeeditor.cpp | 23 +- src/app/nodetool/qgsnodeeditor.h | 1 - src/app/nodetool/qgsselectedfeature.cpp | 53 +-- src/app/nodetool/qgsselectedfeature.h | 3 - 6 files changed, 408 insertions(+), 255 deletions(-) diff --git a/src/app/nodetool/qgsmaptoolnodetool.cpp b/src/app/nodetool/qgsmaptoolnodetool.cpp index 7a3b1e625dd..eaa5d31baf4 100644 --- a/src/app/nodetool/qgsmaptoolnodetool.cpp +++ b/src/app/nodetool/qgsmaptoolnodetool.cpp @@ -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,35 +49,138 @@ QgsMapToolNodeTool::~QgsMapToolNodeTool() cleanTool(); } -void QgsMapToolNodeTool::canvasPressEvent( QgsMapMouseEvent* e ) +void QgsMapToolNodeTool::createTopologyRubberBands() { - removeRubberBands(); - QgsVectorLayer *vlayer = qobject_cast( mCanvas->currentLayer() ); - if ( !vlayer ) + QgsVectorLayer* vlayer = mSelectedFeature->vlayer(); + + foreach ( const QgsVertexEntry* vertexEntry, mSelectedFeature->vertexMap() ) { - return; - } - - bool ctrlModifier = e->modifiers() & Qt::ControlModifier; - QList snapResults; - - QgsFeatureId bkFeatureId = 0; - if ( mSelectedFeature ) - { - bkFeatureId = mSelectedFeature->featureId(); - } - - bool hasVertexSelection = mSelectedFeature && mSelectedFeature->hasSelection(); - - if ( !mSelectedFeature || !hasVertexSelection ) - { - //try to select feature - QgsVectorLayer *vlayer = qobject_cast( mCanvas->currentLayer() ); - if ( !vlayer ) + if ( !vertexEntry->isSelected() ) { - return; + continue; } + // Snap vertex + QMultiMap snapResults; + vlayer->snapWithContext( vertexEntry->pointV1(), ZERO_TOLERANCE, snapResults, QgsSnapper::SnapToVertex ); + 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.geometry()->vertexIdFromVertexNr( snapResult.snappedVertexNr, vid ) ) + { + continue; + } + // Add rubberband if not already added + if ( !mMoveRubberBands.contains( snapFeatureId ) ) + { + 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 ); + } + // 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 || e->buttons() == Qt::NoButton ) + return; + + QgsVectorLayer* vlayer = mSelectedFeature->vlayer(); + Q_ASSERT( vlayer ); + + mSelectAnother = false; + + if ( mMoving ) + { + if ( mMoveRubberBands.empty() ) + { + QgsGeometryRubberBand* rb = new QgsGeometryRubberBand( mCanvas, mSelectedFeature->geometry()->type() ); + rb->setOutlineColor( Qt::blue ); + rb->setBrushStyle( Qt::NoBrush ); + rb->setOutlineWidth( 2 ); + QgsAbstractGeometryV2* rbGeom = mSelectedFeature->geometry()->geometry()->clone(); + if ( mCanvas->mapSettings().layerTransform( vlayer ) ) + rbGeom->transform( *mCanvas->mapSettings().layerTransform( vlayer ) ); + rb->setGeometry( rbGeom ); + mMoveRubberBands.insert( mSelectedFeature->featureId(), rb ); + foreach ( const QgsVertexEntry* vertexEntry, mSelectedFeature->vertexMap() ) + { + if ( vertexEntry->isSelected() ) + mMoveVertices[mSelectedFeature->featureId()].append( qMakePair( vertexEntry->vertexId(), toMapCoordinates( vlayer, vertexEntry->point() ) ) ); + } + if ( QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 ) ) + { + createTopologyRubberBands(); + } + } + else + { + // move rubberband + QList snapResults; + mSnapper.snapToBackgroundLayers( e->pos(), snapResults, QList() << mClosestMapVertex ); + + QgsPoint curPos = snapPointFromResults( snapResults, e->pos() ); + QgsPoint pressPos = snapResults.size() > 0 ? mClosestMapVertex : toMapCoordinates( mPressCoordinates ); + double deltaX = curPos.x() - pressPos.x(); + double deltaY = curPos.y() - pressPos.y(); + + foreach ( const QgsFeatureId& fid, mMoveRubberBands.keys() ) + { + typedef QPair MoveVertex; + foreach ( const MoveVertex& pair, mMoveVertices[fid] ) + { + 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 snapResults; + if ( !mSelectedFeature ) + { + QgsVectorLayer *vlayer = qobject_cast( mCanvas->currentLayer() ); + if ( !vlayer ) + return; + + mSelectAnother = false; mSnapper.snapToCurrentLayer( e->pos(), snapResults, QgsSnapper::SnapToVertexAndSegment, -1 ); if ( snapResults.size() < 1 ) @@ -85,95 +192,123 @@ void QgsMapToolNodeTool::canvasPressEvent( QgsMapMouseEvent* e ) // 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 ); - } - } -} - -void QgsMapToolNodeTool::canvasMoveEvent( QgsMapMouseEvent* e ) -{ - if ( !mSelectedFeature || !mSelectedFeature->hasSelection() ) - { - return; - } - - QgsVectorLayer* vlayer = mSelectedFeature->vlayer(); - if ( !vlayer ) - { - return; - } - - if ( mMoveRubberBands.empty() ) - { - QgsGeometryRubberBand* rb = new QgsGeometryRubberBand( mCanvas, mSelectedFeature->geometry()->type() ); - rb->setOutlineColor( Qt::blue ); - rb->setBrushStyle( Qt::NoBrush ); - rb->setOutlineWidth( 2 ); - QgsAbstractGeometryV2* rbGeom = mSelectedFeature->geometry()->geometry()->clone(); - if ( mCanvas->mapSettings().layerTransform( vlayer ) ) - rbGeom->transform( *mCanvas->mapSettings().layerTransform( vlayer ) ); - rb->setGeometry( rbGeom ); - mMoveRubberBands.insert( mSelectedFeature->featureId(), rb ); - Q_FOREACH ( const QgsVertexEntry* vertexEntry, mSelectedFeature->vertexMap() ) - { - if ( vertexEntry->isSelected() ) - mMoveVertices[mSelectedFeature->featureId()].append( qMakePair( vertexEntry->vertexId(), toMapCoordinates( vlayer, vertexEntry->point() ) ) ); - } - if ( QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 ) ) - { - createTopologyRubberBands(); - } + 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 { - // move rubberband - QList snapResults; - mSnapper.snapToBackgroundLayers( e->pos(), snapResults, QList() << mClosestLayerVertex ); + // remove previous warning + emit messageDiscarded(); - QgsPoint origPos = toMapCoordinates( vlayer, mClosestLayerVertex ); - QgsPoint curPos = snapPointFromResults( snapResults, e->pos() ); - double diffX = curPos.x() - origPos.x(); - double diffY = curPos.y() - origPos.y(); + QgsVectorLayer *vlayer = mSelectedFeature->vlayer(); + Q_ASSERT( vlayer ); - Q_FOREACH ( const QgsFeatureId& fid, mMoveRubberBands.keys() ) + // 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 ) { - typedef QPair MoveVertex; - Q_FOREACH ( const MoveVertex& pair, mMoveVertices[fid] ) + // some vertex selected + mMoving = true; + mClosestMapVertex = toMapCoordinates( vlayer, closestLayerVertex ); + if ( mMoving ) { - QgsPointV2 pos = pair.second; - pos.setX( pos.x() + diffX ); - pos.setY( pos.y() + diffY ); - mMoveRubberBands.value( fid )->moveVertex( pair.first, pos ); + 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::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 snapResults; + mSnapper.snapToBackgroundLayers( e->pos(), snapResults, QList() << 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 &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 currentResultList; QList 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 QListinsertSegmentVerticesForSnap( 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 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 ) ) ) ); - } - } -} diff --git a/src/app/nodetool/qgsmaptoolnodetool.h b/src/app/nodetool/qgsmaptoolnodetool.h index 64c9c4850d2..a1443163e8a 100644 --- a/src/app/nodetool/qgsmaptoolnodetool.h +++ b/src/app/nodetool/qgsmaptoolnodetool.h @@ -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 mMoveRubberBands; + + /** Vertices of features to move */ + QMap > > 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 mMoveRubberBands; - - /** Vertices of features to move */ - QMap > > mMoveVertices; + /** Vertex to deselect on release */ + int mDeselectOnRelease; }; #endif diff --git a/src/app/nodetool/qgsnodeeditor.cpp b/src/app/nodetool/qgsnodeeditor.cpp index f675b10fd11..f4faa2e105f 100644 --- a/src/app/nodetool/qgsnodeeditor.cpp +++ b/src/app/nodetool/qgsnodeeditor.cpp @@ -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( 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 ); } diff --git a/src/app/nodetool/qgsnodeeditor.h b/src/app/nodetool/qgsnodeeditor.h index 7dc638efb75..8a9e5d6f5e2 100644 --- a/src/app/nodetool/qgsnodeeditor.h +++ b/src/app/nodetool/qgsnodeeditor.h @@ -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 diff --git a/src/app/nodetool/qgsselectedfeature.cpp b/src/app/nodetool/qgsselectedfeature.cpp index bdac141c502..8aabb3f7cb2 100644 --- a/src/app/nodetool/qgsselectedfeature.cpp +++ b/src/app/nodetool/qgsselectedfeature.cpp @@ -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::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::const_iterator vertexIt = mVertexMap.constBegin(); - for ( ; vertexIt != mVertexMap.constEnd(); ++vertexIt ) - { - if (( *vertexIt )->isSelected() ) - { - return true; - } - } - return hasSelection; -} diff --git a/src/app/nodetool/qgsselectedfeature.h b/src/app/nodetool/qgsselectedfeature.h index 8183c75b124..fc5878adf15 100644 --- a/src/app/nodetool/qgsselectedfeature.h +++ b/src/app/nodetool/qgsselectedfeature.h @@ -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: