15
15
16
16
#include " qgsmaptooldeletepart.h"
17
17
18
+ #include " qgisapp.h"
18
19
#include " qgsmapcanvas.h"
19
20
#include " qgsvertexmarker.h"
20
21
#include " qgsvectorlayer.h"
22
+ #include " qgsmessagebar.h"
23
+ #include " qgsgeometry.h"
21
24
22
25
#include < QMouseEvent>
23
26
#include < QMessageBox>
24
27
25
28
QgsMapToolDeletePart::QgsMapToolDeletePart ( QgsMapCanvas* canvas )
26
- : QgsMapToolVertexEdit ( canvas ), mCross( 0 )
29
+ : QgsMapToolEdit ( canvas ), mCross( 0 )
27
30
{
28
31
}
29
32
30
33
QgsMapToolDeletePart::~QgsMapToolDeletePart ()
31
34
{
32
- delete mCross ;
33
35
}
34
36
35
37
void QgsMapToolDeletePart::canvasMoveEvent ( QMouseEvent *e )
@@ -40,92 +42,144 @@ void QgsMapToolDeletePart::canvasMoveEvent( QMouseEvent *e )
40
42
41
43
void QgsMapToolDeletePart::canvasPressEvent ( QMouseEvent *e )
42
44
{
43
- delete mCross ;
44
- mCross = 0 ;
45
45
46
46
mRecentSnappingResults .clear ();
47
47
// do snap -> new recent snapping results
48
48
if ( mSnapper .snapToCurrentLayer ( e->pos (), mRecentSnappingResults , QgsSnapper::SnapToVertexAndSegment ) != 0 )
49
49
{
50
50
// error
51
51
}
52
-
53
- if ( mRecentSnappingResults .size () > 0 )
54
- {
55
- // remove previous warning
56
- emit messageDiscarded ();
57
-
58
- QgsPoint markerPoint = mRecentSnappingResults .begin ()->snappedVertex ;
59
-
60
- // show vertex marker
61
- mCross = new QgsVertexMarker ( mCanvas );
62
- mCross ->setIconType ( QgsVertexMarker::ICON_X );
63
- mCross ->setCenter ( markerPoint );
64
- }
65
- else
66
- {
67
- emit messageEmitted ( tr ( " could not snap to a part on the current layer." ) );
68
- }
69
52
}
70
53
71
54
void QgsMapToolDeletePart::canvasReleaseEvent ( QMouseEvent *e )
72
55
{
73
56
Q_UNUSED ( e );
74
- delete mCross ;
75
- mCross = 0 ;
76
57
77
58
QgsMapLayer* currentLayer = mCanvas ->currentLayer ();
78
59
if ( !currentLayer )
79
60
return ;
80
61
81
- QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer *>( currentLayer );
62
+ vlayer = qobject_cast<QgsVectorLayer *>( currentLayer );
82
63
if ( !vlayer )
64
+ {
65
+ notifyNotVectorLayer ();
83
66
return ;
67
+ }
84
68
85
- if ( mRecentSnappingResults . size () > 0 )
69
+ if ( !vlayer-> isEditable () )
86
70
{
87
- QList<QgsSnappingResult>::iterator sr_it = mRecentSnappingResults .begin ();
88
- for ( ; sr_it != mRecentSnappingResults .end (); ++sr_it )
89
- {
90
- if ( sr_it->snappedVertexNr != -1 )
91
- deletePart ( sr_it->snappedAtGeometry , sr_it->snappedVertexNr , vlayer );
92
- else if ( sr_it->beforeVertexNr != -1 )
93
- deletePart ( sr_it->snappedAtGeometry , sr_it->beforeVertexNr , vlayer );
94
- else if ( sr_it->afterVertexNr != -1 )
95
- deletePart ( sr_it->snappedAtGeometry , sr_it->afterVertexNr , vlayer );
96
- }
71
+ notifyNotEditableLayer ();
72
+ return ;
97
73
}
98
-
99
- }
100
-
101
-
102
- void QgsMapToolDeletePart::deletePart ( QgsFeatureId fId , int beforeVertexNr, QgsVectorLayer* vlayer )
103
- {
74
+ QgsGeometry* g;
104
75
QgsFeature f;
105
- vlayer->getFeatures ( QgsFeatureRequest ().setFilterFid ( fId ) ).nextFeature ( f );
106
-
107
- // find out the part number
108
- QgsGeometry* g = f.geometry ();
109
- if ( !g->isMultipart () )
76
+ int partNum;
77
+ switch ( vlayer->geometryType () )
110
78
{
111
- QMessageBox::information ( mCanvas , tr ( " Delete part" ), tr ( " This isn't a multipart geometry." ) );
112
- return ;
79
+ case QGis::Point:
80
+ case QGis::Line:
81
+ {
82
+ if ( mRecentSnappingResults .size () == 0 )
83
+ {
84
+ return ;
85
+ }
86
+ QgsSnappingResult sr = mRecentSnappingResults .first ();
87
+ vlayer->getFeatures ( QgsFeatureRequest ().setFilterFid ( sr.snappedAtGeometry ) ).nextFeature ( f );
88
+ g = f.geometry ();
89
+ if ( !g )
90
+ return ;
91
+ if ( ( g->type () == QGis::Point && g->asMultiPoint ().size () == 1 ) ||
92
+ ( g->type () == QGis::Line && g->asMultiPolyline ().size () == 1 ) )
93
+ {
94
+ notifySinglePart ();
95
+ return ;
96
+ }
97
+ int vertex = sr.snappedVertexNr ;
98
+ if ( vertex == -1 )
99
+ {
100
+ vertex = sr.beforeVertexNr ;
101
+ }
102
+ partNum = partNumberOfVertex ( g, vertex );
103
+ break ;
104
+ }
105
+ case QGis::Polygon:
106
+ {
107
+ QgsPoint p = mCanvas ->getCoordinateTransform ()->toMapCoordinates ( e->x (),e->y ());
108
+ p = toLayerCoordinates (vlayer, p);
109
+ f = featureUnderPoint (p);
110
+ g = f.geometry ();
111
+ if ( !g )
112
+ return ;
113
+ if ( g->asMultiPolygon ().size () == 1 )
114
+ {
115
+ notifySinglePart ();
116
+ return ;
117
+ }
118
+ partNum = partNumberOfPoint ( g, p );
119
+ if ( partNum < 0 )
120
+ return ;
121
+ break ;
122
+ }
123
+ default :
124
+ {
125
+ QgsDebugMsg (" Unknown geometry type" );
126
+ return ;
127
+ }
113
128
}
114
-
115
- int partNum = partNumberOfVertex ( g, beforeVertexNr );
116
-
117
129
if ( g->deletePart ( partNum ) )
118
130
{
119
131
vlayer->beginEditCommand ( tr ( " Part of multipart feature deleted" ) );
120
- vlayer->changeGeometry ( fId , g );
132
+ vlayer->changeGeometry ( f. id () , g );
121
133
vlayer->endEditCommand ();
122
134
mCanvas ->refresh ();
123
135
}
124
136
else
125
137
{
126
- QMessageBox::information ( mCanvas , tr ( " Delete part" ), tr ( " Couldn't remove the selected part." ) );
138
+ QgisApp::instance ()->messageBar ()->pushMessage (
139
+ tr ( " Delete part" ),
140
+ tr ( " Couldn't remove the selected part." ),
141
+ QgsMessageBar::WARNING,
142
+ QgisApp::instance ()->messageTimeout () );
127
143
}
144
+ return ;
145
+ }
128
146
147
+ QgsFeature QgsMapToolDeletePart::featureUnderPoint (QgsPoint p)
148
+ {
149
+ QgsRectangle r;
150
+ double searchRadius = mCanvas ->extent ().width ()/100 ;
151
+ r.setXMinimum ( p.x () - searchRadius );
152
+ r.setXMaximum ( p.x () + searchRadius );
153
+ r.setYMinimum ( p.y () - searchRadius );
154
+ r.setYMaximum ( p.y () + searchRadius );
155
+ QgsFeatureIterator fit = vlayer->getFeatures ( QgsFeatureRequest ().setFilterRect ( r ) );
156
+ QgsFeature f;
157
+ fit.nextFeature ( f );
158
+ return f;
159
+ }
160
+
161
+
162
+ int QgsMapToolDeletePart::partNumberOfPoint (QgsGeometry *g, QgsPoint point)
163
+ {
164
+ int part;
165
+ switch ( g->wkbType () )
166
+ {
167
+ case QGis::WKBMultiPolygon25D:
168
+ case QGis::WKBMultiPolygon:
169
+ {
170
+ QgsMultiPolygon mpolygon = g->asMultiPolygon ();
171
+ for ( part = 0 ; part < mpolygon.count (); part++ ) // go through the polygons
172
+ {
173
+ const QgsPolygon& polygon = mpolygon[part];
174
+ QgsGeometry* partGeo = QgsGeometry::fromPolygon (polygon);
175
+ if ( partGeo->contains ( &point ) )
176
+ return part;
177
+ }
178
+ return -1 ; // not found
179
+ }
180
+ default :
181
+ return -1 ;
182
+ }
129
183
}
130
184
131
185
int QgsMapToolDeletePart::partNumberOfVertex ( QgsGeometry* g, int beforeVertexNr )
@@ -134,6 +188,14 @@ int QgsMapToolDeletePart::partNumberOfVertex( QgsGeometry* g, int beforeVertexNr
134
188
135
189
switch ( g->wkbType () )
136
190
{
191
+ case QGis::WKBLineString25D:
192
+ case QGis::WKBLineString:
193
+ case QGis::WKBPoint25D:
194
+ case QGis::WKBPoint:
195
+ case QGis::WKBPolygon25D:
196
+ case QGis::WKBPolygon:
197
+ return 1 ;
198
+
137
199
case QGis::WKBMultiPoint25D:
138
200
case QGis::WKBMultiPoint:
139
201
if ( beforeVertexNr < g->asMultiPoint ().count () )
@@ -178,12 +240,17 @@ int QgsMapToolDeletePart::partNumberOfVertex( QgsGeometry* g, int beforeVertexNr
178
240
}
179
241
}
180
242
181
-
182
243
void QgsMapToolDeletePart::deactivate ()
183
244
{
184
- delete mCross ;
185
- mCross = 0 ;
186
-
187
245
QgsMapTool::deactivate ();
188
246
}
189
247
248
+ void QgsMapToolDeletePart::notifySinglePart ()
249
+ {
250
+ QgisApp::instance ()->messageBar ()->pushMessage (
251
+ tr ( " Cannot use delete part" ),
252
+ tr ( " The Delete part tool cannot be used on single part features." ),
253
+ QgsMessageBar::INFO,
254
+ QgisApp::instance ()->messageTimeout () );
255
+ return ;
256
+ }
0 commit comments