|
29 | 29 | #include "qgsvectorlayer.h"
|
30 | 30 | #include "qgsvertexmarker.h"
|
31 | 31 |
|
| 32 | +#include "qgisapp.h" |
| 33 | +#include "qgsselectedfeature.h" |
| 34 | +#include "qgsnodeeditor.h" |
| 35 | +#include "qgsvertexentry.h" |
| 36 | + |
| 37 | +#include <QMenu> |
32 | 38 | #include <QRubberBand>
|
33 | 39 |
|
| 40 | + |
34 | 41 | uint qHash( const Vertex &v )
|
35 | 42 | {
|
36 | 43 | return qHash( v.layer ) ^ qHash( v.fid ) ^ qHash( v.vertexId );
|
@@ -225,6 +232,7 @@ void QgsNodeTool2::deactivate()
|
225 | 232 | {
|
226 | 233 | setHighlightedNodes( QList<Vertex>() );
|
227 | 234 | removeTemporaryRubberBands();
|
| 235 | + cleanupNodeEditor(); |
228 | 236 | QgsMapToolAdvancedDigitizing::deactivate();
|
229 | 237 | }
|
230 | 238 |
|
@@ -300,6 +308,8 @@ void QgsNodeTool2::clearDragBands()
|
300 | 308 |
|
301 | 309 | void QgsNodeTool2::cadCanvasPressEvent( QgsMapMouseEvent *e )
|
302 | 310 | {
|
| 311 | + cleanupNodeEditor(); |
| 312 | + |
303 | 313 | if ( !mDraggingVertex && !mSelectedNodes.isEmpty() )
|
304 | 314 | {
|
305 | 315 | // only remove highlight if not clicked on one of highlighted nodes
|
@@ -339,6 +349,20 @@ void QgsNodeTool2::cadCanvasPressEvent( QgsMapMouseEvent *e )
|
339 | 349 | if ( !mDraggingVertex && !mDraggingEdge )
|
340 | 350 | mSelectionRectStartPos.reset( new QPoint( e->pos() ) );
|
341 | 351 | }
|
| 352 | + |
| 353 | + if ( e->button() == Qt::RightButton ) |
| 354 | + { |
| 355 | + if ( !mSelectionRect && !mDraggingVertex && !mDraggingEdge ) |
| 356 | + { |
| 357 | + // show popup menu - if we are on top of a feature |
| 358 | + if ( mLastMouseMoveMatch.isValid() && mLastMouseMoveMatch.layer() ) |
| 359 | + { |
| 360 | + QMenu menu; |
| 361 | + menu.addAction( "Node editor", this, &QgsNodeTool2::showNodeEditor ); |
| 362 | + menu.exec( mCanvas->mapToGlobal( e->pos() ) ); |
| 363 | + } |
| 364 | + } |
| 365 | + } |
342 | 366 | }
|
343 | 367 |
|
344 | 368 | void QgsNodeTool2::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
|
@@ -645,6 +669,8 @@ void QgsNodeTool2::mouseMoveNotDragging( QgsMapMouseEvent *e )
|
645 | 669 | // do not use snap from mouse event, use our own with any editable layer
|
646 | 670 | QgsPointLocator::Match m = snapToEditableLayer( e );
|
647 | 671 |
|
| 672 | + mLastMouseMoveMatch = m; |
| 673 | + |
648 | 674 | // possibility to move a node
|
649 | 675 | if ( m.type() == QgsPointLocator::Vertex )
|
650 | 676 | {
|
@@ -827,6 +853,74 @@ void QgsNodeTool2::onCachedGeometryDeleted( QgsFeatureId fid )
|
827 | 853 | layerCache.remove( fid );
|
828 | 854 | }
|
829 | 855 |
|
| 856 | + |
| 857 | +void QgsNodeTool2::showNodeEditor() |
| 858 | +{ |
| 859 | + QgsPointLocator::Match m = mLastMouseMoveMatch; |
| 860 | + if ( !m.isValid() || !m.layer() ) |
| 861 | + return; |
| 862 | + |
| 863 | + mSelectedFeature.reset( new QgsSelectedFeature( m.featureId(), m.layer(), mCanvas ) ); |
| 864 | + mNodeEditor.reset( new QgsNodeEditor( m.layer(), mSelectedFeature.get(), mCanvas ) ); |
| 865 | + QgisApp::instance()->addDockWidget( Qt::LeftDockWidgetArea, mNodeEditor.get() ); |
| 866 | + connect( mNodeEditor.get(), &QgsNodeEditor::deleteSelectedRequested, this, &QgsNodeTool2::deleteNodeEditorSelection ); |
| 867 | +} |
| 868 | + |
| 869 | +void QgsNodeTool2::cleanupNodeEditor() |
| 870 | +{ |
| 871 | + mSelectedFeature.reset(); |
| 872 | + mNodeEditor.reset(); |
| 873 | +} |
| 874 | + |
| 875 | +static int _firstSelectedVertex( QgsSelectedFeature &selectedFeature ) |
| 876 | +{ |
| 877 | + QList<QgsVertexEntry *> &vertexMap = selectedFeature.vertexMap(); |
| 878 | + for ( int i = 0, n = vertexMap.size(); i < n; ++i ) |
| 879 | + { |
| 880 | + if ( vertexMap[i]->isSelected() ) |
| 881 | + { |
| 882 | + return i; |
| 883 | + } |
| 884 | + } |
| 885 | + return -1; |
| 886 | +} |
| 887 | + |
| 888 | +static void _safeSelectVertex( QgsSelectedFeature &selectedFeature, int vertexNr ) |
| 889 | +{ |
| 890 | + int n = selectedFeature.vertexMap().size(); |
| 891 | + selectedFeature.selectVertex( ( vertexNr + n ) % n ); |
| 892 | +} |
| 893 | + |
| 894 | +void QgsNodeTool2::deleteNodeEditorSelection() |
| 895 | +{ |
| 896 | + if ( !mSelectedFeature ) |
| 897 | + return; |
| 898 | + |
| 899 | + int firstSelectedIndex = _firstSelectedVertex( *mSelectedFeature ); |
| 900 | + if ( firstSelectedIndex == -1 ) |
| 901 | + return; |
| 902 | + |
| 903 | + mSelectedFeature->deleteSelectedVertexes(); |
| 904 | + |
| 905 | + if ( mSelectedFeature->geometry()->isNull() ) |
| 906 | + { |
| 907 | + emit messageEmitted( tr( "Geometry has been cleared. Use the add part tool to set geometry for this feature." ) ); |
| 908 | + } |
| 909 | + else |
| 910 | + { |
| 911 | + int nextVertexToSelect = firstSelectedIndex; |
| 912 | + if ( mSelectedFeature->geometry()->type() == QgsWkbTypes::LineGeometry ) |
| 913 | + { |
| 914 | + // for lines we don't wrap around vertex selection when deleting nodes from end of line |
| 915 | + nextVertexToSelect = qMin( nextVertexToSelect, mSelectedFeature->geometry()->geometry()->nCoordinates() - 1 ); |
| 916 | + } |
| 917 | + |
| 918 | + _safeSelectVertex( *mSelectedFeature, nextVertexToSelect ); |
| 919 | + } |
| 920 | + mSelectedFeature->vlayer()->triggerRepaint(); |
| 921 | +} |
| 922 | + |
| 923 | + |
830 | 924 | void QgsNodeTool2::startDragging( QgsMapMouseEvent *e )
|
831 | 925 | {
|
832 | 926 | QgsPoint mapPoint = toMapCoordinates( e->pos() );
|
|
0 commit comments