Skip to content

Commit d82a018

Browse files
committedSep 17, 2015
[GRASS] add/delete feature
1 parent e970f4a commit d82a018

File tree

7 files changed

+476
-211
lines changed

7 files changed

+476
-211
lines changed
 

‎src/plugins/grass/qgsgrasseditrenderer.cpp

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,18 @@ QgsGrassEditRenderer::QgsGrassEditRenderer()
3434
, mMarkerRenderer( 0 )
3535
{
3636
QHash<int, QColor> colors;
37-
colors.insert( QgsGrassProvider::TopoUndefined, QColor( 125, 125, 125 ) );
38-
colors.insert( QgsGrassProvider::TopoLine, QColor( Qt::black ) );
39-
colors.insert( QgsGrassProvider::TopoBoundary0, QColor( Qt::red ) );
40-
colors.insert( QgsGrassProvider::TopoBoundary1, QColor( 255, 125, 0 ) );
41-
colors.insert( QgsGrassProvider::TopoBoundary2, QColor( Qt::green ) );
37+
colors.insert( QgsGrassVectorMap::TopoUndefined, QColor( 125, 125, 125 ) );
38+
colors.insert( QgsGrassVectorMap::TopoLine, QColor( Qt::black ) );
39+
colors.insert( QgsGrassVectorMap::TopoBoundary0, QColor( Qt::red ) );
40+
colors.insert( QgsGrassVectorMap::TopoBoundary1, QColor( 255, 125, 0 ) );
41+
colors.insert( QgsGrassVectorMap::TopoBoundary2, QColor( Qt::green ) );
4242

4343
QHash<int, QString> labels;
44-
labels.insert( QgsGrassProvider::TopoUndefined, "Unknown type" );
45-
labels.insert( QgsGrassProvider::TopoLine, "Line" );
46-
labels.insert( QgsGrassProvider::TopoBoundary0, "Boundary (isolated)" );
47-
labels.insert( QgsGrassProvider::TopoBoundary1, "Boundary (area on one side)" );
48-
labels.insert( QgsGrassProvider::TopoBoundary2, "Boundary (areas on both sides)" );
44+
labels.insert( QgsGrassVectorMap::TopoUndefined, "Unknown type" );
45+
labels.insert( QgsGrassVectorMap::TopoLine, "Line" );
46+
labels.insert( QgsGrassVectorMap::TopoBoundary0, "Boundary (isolated)" );
47+
labels.insert( QgsGrassVectorMap::TopoBoundary1, "Boundary (area on one side)" );
48+
labels.insert( QgsGrassVectorMap::TopoBoundary2, "Boundary (areas on both sides)" );
4949

5050
QgsCategoryList categoryList;
5151

@@ -61,15 +61,15 @@ QgsGrassEditRenderer::QgsGrassEditRenderer()
6161
colors.clear();
6262
labels.clear();
6363

64-
colors.insert( QgsGrassProvider::TopoPoint, QColor( 0, 0, 0 ) );
65-
colors.insert( QgsGrassProvider::TopoCentroidIn, QColor( 0, 255, 0 ) );
66-
colors.insert( QgsGrassProvider::TopoCentroidOut, QColor( 255, 0, 0 ) );
67-
colors.insert( QgsGrassProvider::TopoCentroidDupl, QColor( 255, 0, 255 ) );
64+
colors.insert( QgsGrassVectorMap::TopoPoint, QColor( 0, 0, 0 ) );
65+
colors.insert( QgsGrassVectorMap::TopoCentroidIn, QColor( 0, 255, 0 ) );
66+
colors.insert( QgsGrassVectorMap::TopoCentroidOut, QColor( 255, 0, 0 ) );
67+
colors.insert( QgsGrassVectorMap::TopoCentroidDupl, QColor( 255, 0, 255 ) );
6868

69-
labels.insert( QgsGrassProvider::TopoPoint, "Point" );
70-
labels.insert( QgsGrassProvider::TopoCentroidIn, "Centroid in area" );
71-
labels.insert( QgsGrassProvider::TopoCentroidOut, "Centroid outside area" );
72-
labels.insert( QgsGrassProvider::TopoCentroidDupl, "Duplicate centroid" );
69+
labels.insert( QgsGrassVectorMap::TopoPoint, "Point" );
70+
labels.insert( QgsGrassVectorMap::TopoCentroidIn, "Centroid in area" );
71+
labels.insert( QgsGrassVectorMap::TopoCentroidOut, "Centroid outside area" );
72+
labels.insert( QgsGrassVectorMap::TopoCentroidDupl, "Duplicate centroid" );
7373

7474
categoryList.clear();
7575

@@ -104,15 +104,15 @@ QgsSymbolV2* QgsGrassEditRenderer::symbolForFeature( QgsFeature& feature, QgsRen
104104
QgsDebugMsgLevel( QString( "fid = %1 symbolCode = %2" ).arg( feature.id() ).arg( symbolCode ), 3 );
105105

106106
QgsSymbolV2* symbol = 0;
107-
if ( symbolCode == QgsGrassProvider::TopoPoint || symbolCode == QgsGrassProvider::TopoCentroidIn ||
108-
symbolCode == QgsGrassProvider::TopoCentroidOut || symbolCode == QgsGrassProvider::TopoCentroidDupl ||
109-
symbolCode == QgsGrassProvider::TopoNode0 || symbolCode == QgsGrassProvider::TopoNode1 ||
110-
symbolCode == QgsGrassProvider::TopoNode2 )
107+
if ( symbolCode == QgsGrassVectorMap::TopoPoint || symbolCode == QgsGrassVectorMap::TopoCentroidIn ||
108+
symbolCode == QgsGrassVectorMap::TopoCentroidOut || symbolCode == QgsGrassVectorMap::TopoCentroidDupl ||
109+
symbolCode == QgsGrassVectorMap::TopoNode0 || symbolCode == QgsGrassVectorMap::TopoNode1 ||
110+
symbolCode == QgsGrassVectorMap::TopoNode2 )
111111
{
112112
symbol = mMarkerRenderer->symbolForFeature( feature, context );
113113
}
114-
else if ( symbolCode == QgsGrassProvider::TopoLine || symbolCode == QgsGrassProvider::TopoBoundary0 ||
115-
symbolCode == QgsGrassProvider::TopoBoundary1 || symbolCode == QgsGrassProvider::TopoBoundary2 )
114+
else if ( symbolCode == QgsGrassVectorMap::TopoLine || symbolCode == QgsGrassVectorMap::TopoBoundary0 ||
115+
symbolCode == QgsGrassVectorMap::TopoBoundary1 || symbolCode == QgsGrassVectorMap::TopoBoundary2 )
116116
{
117117
symbol = mLineRenderer->symbolForFeature( feature, context );
118118
}

‎src/providers/grass/qgsgrassfeatureiterator.cpp

Lines changed: 91 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -248,39 +248,61 @@ bool QgsGrassFeatureIterator::fetchFeature( QgsFeature& feature )
248248
int type = 0;
249249
int lid = 0;
250250
QgsFeatureId featureId = 0;
251+
QgsAbstractGeometryV2 *oldGeometry = 0;
251252

252253
#ifdef QGISDEBUG
253254
if ( mSource->mEditing )
254255
{
255-
QgsDebugMsg( "newLids:" );
256+
QgsDebugMsgLevel( "newLids:", 3 );
256257
foreach ( int oldLid, mSource->mLayer->map()->newLids().keys() )
257258
{
258-
QgsDebugMsg( QString( "%1 -> %2" ).arg( oldLid ).arg( mSource->mLayer->map()->newLids().value( oldLid ) ) );
259+
QgsDebugMsgLevel( QString( "%1 -> %2" ).arg( oldLid ).arg( mSource->mLayer->map()->newLids().value( oldLid ) ), 3 );
259260
}
260261
}
261262
#endif
262263

263264
if ( filterById )
264265
{
265266
featureId = mRequest.filterFid();
266-
lid = lidFormFid( mRequest.filterFid() );
267+
lid = lidFromFid( mRequest.filterFid() );
268+
QgsDebugMsg( QString( "featureId = %1 lid = %2" ).arg( featureId ).arg( lid ) );
267269

268-
if ( mSource->mLayer->map()->newLids().contains( lid ) )
270+
if ( mSource->mEditing )
269271
{
270-
lid = mSource->mLayer->map()->newLids().value( lid );
271-
QgsDebugMsg( QString( "line %1 rewritten -> real lid = %2" ).arg( lidFormFid( mRequest.filterFid() ) ).arg( lid ) );
272+
// Undo needs the oldes version of geometry, but we also need topo_symbol, so we must read
273+
// topo_symbol from map if the newLine exists read
274+
if ( mSource->mLayer->map()->oldGeometries().contains( lid ) )
275+
{
276+
QgsDebugMsg( QString( "use old geometry for lid = %1" ).arg( lid ) );
277+
oldGeometry = mSource->mLayer->map()->oldGeometries().value( lid );
278+
if ( !oldGeometry )
279+
{
280+
QgsDebugMsg( "oldGeometry is null" );
281+
}
282+
}
283+
if ( mSource->mLayer->map()->newLids().contains( lid ) )
284+
{
285+
// newLid may be 0 if line was deleted, in such case use only the old geometry, topo_symbol cannot be read
286+
int newLid = mSource->mLayer->map()->newLids().value( lid );
287+
QgsDebugMsg( QString( "use newLid = %1 -> lid = %2" ).arg( newLid ).arg( lid ) );
288+
lid = newLid;
289+
}
272290
}
273-
if ( !Vect_line_alive( mSource->map(), lid ) )
291+
292+
if ( lid > 0 )
274293
{
275-
close();
276-
mSource->mLayer->map()->unlockReadWrite();
277-
return false;
278-
}
279-
type = Vect_read_line( mSource->map(), 0, 0, lid );
294+
if ( !Vect_line_alive( mSource->map(), lid ) )
295+
{
296+
close();
297+
mSource->mLayer->map()->unlockReadWrite();
298+
return false;
299+
}
300+
type = Vect_read_line( mSource->map(), 0, 0, lid );
280301

281-
// TODO real cat when line/cat was rewritten?!
282-
cat = catFormFid( mRequest.filterFid() );
283-
QgsDebugMsg( QString( "lid = %1 cat = %2" ).arg( lid ).arg( cat ) );
302+
// TODO real cat when line/cat was rewritten?!
303+
cat = catFromFid( mRequest.filterFid() );
304+
QgsDebugMsg( QString( "lid = %1 cat = %2" ).arg( lid ).arg( cat ) );
305+
}
284306
}
285307
else
286308
{
@@ -304,27 +326,35 @@ bool QgsGrassFeatureIterator::fetchFeature( QgsFeature& feature )
304326
break;
305327
}
306328

307-
int realLid = mNextLid;
308-
if ( mSource->mLayer->map()->newLids().contains( mNextLid ) )
329+
int oldLid = mNextLid;
330+
if ( mSource->mLayer->map()->oldLids().contains( mNextLid ) )
309331
{
310-
realLid = mSource->mLayer->map()->newLids().value( mNextLid );
311-
QgsDebugMsg( QString( "line %1 rewritten -> realLid = %2" ).arg( mNextLid ).arg( realLid ) );
332+
oldLid = mSource->mLayer->map()->oldLids().value( mNextLid );
333+
QgsDebugMsg( QString( "mNextLid = %1 -> oldLid = %2" ).arg( mNextLid ).arg( oldLid ) );
334+
}
335+
336+
if ( oldLid < 0 )
337+
{
338+
QgsDebugMsg( QString( "skip new feature oldLid = %1" ).arg( oldLid ) );
339+
mNextLid++;
340+
continue;
312341
}
313342

314-
if ( !Vect_line_alive( mSource->map(), realLid ) ) // should not be necessary for rewritten lines
343+
if ( !Vect_line_alive( mSource->map(), mNextLid ) ) // should not be necessary for rewritten lines
315344
{
316345
mNextLid++;
317346
continue;
318347
}
319348

320349
struct line_cats *cats = Vect_new_cats_struct();
321-
int tmpType = Vect_read_line( mSource->map(), 0, cats, realLid );
350+
int tmpType = Vect_read_line( mSource->map(), 0, cats, mNextLid );
322351
if ( cats->n_cats == 0 )
323352
{
324-
lid = realLid;
353+
lid = mNextLid;
325354
type = tmpType;
326355
cat = 0;
327-
featureId = makeFeatureId( mNextLid, cat );
356+
357+
featureId = makeFeatureId( oldLid, cat );
328358
mNextLid++;
329359
}
330360
else
@@ -345,10 +375,10 @@ bool QgsGrassFeatureIterator::fetchFeature( QgsFeature& feature )
345375
}
346376
else
347377
{
348-
lid = realLid;
378+
lid = mNextLid;
349379
type = tmpType;
350380
cat = cats->cat[mNextCidx];
351-
featureId = makeFeatureId( mNextLid, cat );
381+
featureId = makeFeatureId( oldLid, cat );
352382
mNextCidx++;
353383
}
354384
}
@@ -417,19 +447,22 @@ bool QgsGrassFeatureIterator::fetchFeature( QgsFeature& feature )
417447
break;
418448
}
419449
}
420-
if ( lid == 0 || lid > mSource->mLayer->map()->numLines() )
421-
{
422-
QgsDebugMsg( QString( "lid = %1 -> close" ).arg( lid ) );
423-
close();
424-
mSource->mLayer->map()->unlockReadWrite();
425-
return false; // No more features
426-
}
427-
if ( type == 0 ) // should not happen
450+
if ( !oldGeometry )
428451
{
429-
QgsDebugMsg( "unknown type" );
430-
close();
431-
mSource->mLayer->map()->unlockReadWrite();
432-
return false;
452+
if ( lid == 0 || lid > mSource->mLayer->map()->numLines() )
453+
{
454+
QgsDebugMsg( QString( "lid = %1 -> close" ).arg( lid ) );
455+
close();
456+
mSource->mLayer->map()->unlockReadWrite();
457+
return false; // No more features
458+
}
459+
if ( type == 0 ) // should not happen
460+
{
461+
QgsDebugMsg( "unknown type" );
462+
close();
463+
mSource->mLayer->map()->unlockReadWrite();
464+
return false;
465+
}
433466
}
434467
QgsDebugMsgLevel( QString( "lid = %1 type = %2 cat = %3 fatureId = %4" ).arg( lid ).arg( type ).arg( cat ).arg( featureId ), 3 );
435468

@@ -440,36 +473,22 @@ bool QgsGrassFeatureIterator::fetchFeature( QgsFeature& feature )
440473

441474
if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) )
442475
{
443-
// TODO ???
444-
#if 0
445-
// Changed geometry are always read from cache
446-
if ( mSource->mEditing && mSource->mChangedFeatures.contains( mRequest.filterFid() ) )
476+
if ( oldGeometry )
447477
{
448-
QgsDebugMsg( QString( "filterById = %1 mRequest.filterFid() = %2 mSource->mChangedFeatures.size() = %3" ).arg( filterById ).arg( mRequest.filterFid() ).arg( mSource->mChangedFeatures.size() ) );
449-
QgsFeature f = mSource->mChangedFeatures.value( mRequest.filterFid() );
450-
QgsDebugMsg( QString( "return features from mChangedFeatures id = %1" ).arg( f.id() ) );
451-
feature.setFeatureId( f.id() );
452-
feature.initAttributes( mSource->mFields.count() );
453-
feature.setFields( &( mSource->mFields ) ); // allow name-based attribute lookups
454-
feature.setAttributes( f.attributes() );
455-
feature.setGeometry( new QgsGeometry( *( f.geometry() ) ) );
456-
feature.setValid( true );
457-
mSource->mLayer->map()->unlockReadWrite();
458-
return true;
478+
feature.setGeometry( new QgsGeometry( oldGeometry->clone() ) );
459479
}
460480
else
461481
{
482+
setFeatureGeometry( feature, lid, type );
462483
}
463-
#endif
464-
setFeatureGeometry( feature, lid, type );
465484
}
466485

467486
if ( !QgsGrassProvider::isTopoType( mSource->mLayerType ) )
468487
{
469-
QgsGrassProvider::TopoSymbol symbol = QgsGrassProvider::TopoUndefined;
470-
if ( mSource->mEditing )
488+
QgsGrassVectorMap::TopoSymbol symbol = QgsGrassVectorMap::TopoUndefined;
489+
if ( mSource->mEditing && lid > 0 )
471490
{
472-
symbol = topoSymbol( lid, type );
491+
symbol = mSource->mLayer->map()->topoSymbol( lid );
473492
}
474493

475494
if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes )
@@ -528,9 +547,6 @@ bool QgsGrassFeatureIterator::fetchFeature( QgsFeature& feature )
528547
return true;
529548
}
530549

531-
532-
533-
534550
bool QgsGrassFeatureIterator::rewind()
535551
{
536552
if ( mClosed )
@@ -569,27 +585,7 @@ void QgsGrassFeatureIterator::setFeatureGeometry( QgsFeature& feature, int id, i
569585
QgsAbstractGeometryV2 *geometry = 0;
570586
if ( type & ( GV_POINTS | GV_LINES | GV_FACE ) )
571587
{
572-
if ( mSource->mEditing )
573-
{
574-
// Use original geometry because QgsVectorLayerUndoCommandChangeGeometry::undo() needs that
575-
if ( mSource->mLayer->map()->oldLids().contains( id ) )
576-
{
577-
int oldLid = mSource->mLayer->map()->oldLids().value( id );
578-
QgsDebugMsg( QString( "oldLid = %1 -> use old geometry" ).arg( oldLid ) );
579-
if ( mSource->mLayer->map()->oldGeometries().contains( oldLid ) )
580-
{
581-
geometry = mSource->mLayer->map()->oldGeometries().value( oldLid )->clone();
582-
}
583-
else
584-
{
585-
QgsDebugMsg( "geometry not found in oldGeometries" );
586-
}
587-
}
588-
}
589-
if ( !geometry )
590-
{
591-
geometry = mSource->mLayer->map()->lineGeometry( id );
592-
}
588+
geometry = mSource->mLayer->map()->lineGeometry( id );
593589
}
594590
else if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE )
595591
{
@@ -613,59 +609,28 @@ QgsFeatureId QgsGrassFeatureIterator::makeFeatureId( int grassId, int cat )
613609
return ( QgsFeatureId )grassId * 1000000000 + cat;
614610
}
615611

616-
int QgsGrassFeatureIterator::lidFormFid( QgsFeatureId fid )
612+
int QgsGrassFeatureIterator::lidFromFid( QgsFeatureId fid )
617613
{
614+
// New features have negative fid, we take such fid as (still negative) lid
615+
// it is only used for mapping from fid to real lid
616+
if ( FID_IS_NEW( fid ) )
617+
{
618+
return fid;
619+
}
618620
return fid / 1000000000;
619621
}
620622

621-
int QgsGrassFeatureIterator::catFormFid( QgsFeatureId fid )
623+
int QgsGrassFeatureIterator::catFromFid( QgsFeatureId fid )
622624
{
623-
return fid % 1000000000;
624-
}
625-
626-
QgsGrassProvider::TopoSymbol QgsGrassFeatureIterator::topoSymbol( int lid, int type )
627-
{
628-
QgsGrassProvider::TopoSymbol symbol = QgsGrassProvider::TopoUndefined;
629-
if ( type == GV_POINT )
630-
{
631-
symbol = QgsGrassProvider::TopoPoint;
632-
}
633-
else if ( type == GV_CENTROID )
634-
{
635-
int area = Vect_get_centroid_area( mSource->map(), lid );
636-
if ( area == 0 )
637-
symbol = QgsGrassProvider::TopoCentroidOut;
638-
else if ( area > 0 )
639-
symbol = QgsGrassProvider::TopoCentroidIn;
640-
else
641-
symbol = QgsGrassProvider::TopoCentroidDupl; /* area < 0 */
642-
}
643-
else if ( type == GV_LINE )
644-
{
645-
symbol = QgsGrassProvider::TopoLine;
646-
}
647-
else if ( type == GV_BOUNDARY )
625+
if ( FID_IS_NEW( fid ) )
648626
{
649-
int left, right;
650-
Vect_get_line_areas( mSource->map(), lid, &left, &right );
651-
if ( left != 0 && right != 0 )
652-
{
653-
symbol = QgsGrassProvider::TopoBoundary2;
654-
}
655-
else if ( left == 0 && right == 0 )
656-
{
657-
symbol = QgsGrassProvider::TopoBoundary0;
658-
}
659-
else
660-
{
661-
symbol = QgsGrassProvider::TopoBoundary1;
662-
}
627+
// TODO: keep track of cats for new features
628+
return 0;
663629
}
664-
QgsDebugMsgLevel( QString( "lid = %1 type = %2 symbol = %3" ).arg( lid ).arg( type ).arg( symbol ), 3 );
665-
return symbol;
630+
return fid % 1000000000;
666631
}
667632

668-
void QgsGrassFeatureIterator::setFeatureAttributes( int cat, QgsFeature *feature, QgsGrassProvider::TopoSymbol symbol )
633+
void QgsGrassFeatureIterator::setFeatureAttributes( int cat, QgsFeature *feature, QgsGrassVectorMap::TopoSymbol symbol )
669634
{
670635
QgsDebugMsgLevel( QString( "setFeatureAttributes cat = %1" ).arg( cat ), 3 );
671636
QgsAttributeList attlist;
@@ -684,7 +649,7 @@ void QgsGrassFeatureIterator::setFeatureAttributes( int cat, QgsFeature *feature
684649
return setFeatureAttributes( cat, feature, attlist, symbol );
685650
}
686651

687-
void QgsGrassFeatureIterator::setFeatureAttributes( int cat, QgsFeature *feature, const QgsAttributeList& attlist, QgsGrassProvider::TopoSymbol symbol )
652+
void QgsGrassFeatureIterator::setFeatureAttributes( int cat, QgsFeature *feature, const QgsAttributeList& attlist, QgsGrassVectorMap::TopoSymbol symbol )
688653
{
689654
QgsDebugMsgLevel( QString( "setFeatureAttributes cat = %1 symbol = %2" ).arg( cat ).arg( symbol ), 3 );
690655
int nFields = mSource->mLayer->fields().size();

‎src/providers/grass/qgsgrassfeatureiterator.h

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,10 @@ class QgsGrassFeatureIterator : public QObject, public QgsAbstractFeatureIterato
8888
static QgsFeatureId makeFeatureId( int grassId, int cat );
8989

9090
// Get GRASS line id from QGIS fid
91-
static int lidFormFid( QgsFeatureId fid );
91+
static int lidFromFid( QgsFeatureId fid );
9292

9393
// Get GRASS cat from QGIS fid
94-
static int catFormFid( QgsFeatureId fid );
94+
static int catFromFid( QgsFeatureId fid );
9595

9696
public slots:
9797
/** Cancel iterator, iterator will be closed on next occasion, probably when next getFeature() gets called.
@@ -115,19 +115,14 @@ class QgsGrassFeatureIterator : public QObject, public QgsAbstractFeatureIterato
115115
* @param feature
116116
* @param cat category number
117117
*/
118-
void setFeatureAttributes( int cat, QgsFeature *feature, QgsGrassProvider::TopoSymbol symbol );
118+
void setFeatureAttributes( int cat, QgsFeature *feature, QgsGrassVectorMap::TopoSymbol symbol );
119119

120120
/** Set feature attributes.
121121
* @param feature
122122
* @param cat category number
123123
* @param attlist a list containing the index number of the fields to set
124124
*/
125-
void setFeatureAttributes( int cat, QgsFeature *feature, const QgsAttributeList & attlist, QgsGrassProvider::TopoSymbol symbol );
126-
127-
/** Get topology symbol code
128-
* @param lid line or area number
129-
* @param type geometry type */
130-
QgsGrassProvider::TopoSymbol topoSymbol( int lid, int type );
125+
void setFeatureAttributes( int cat, QgsFeature *feature, const QgsAttributeList & attlist, QgsGrassVectorMap::TopoSymbol symbol );
131126

132127
/** Canceled -> close when possible */
133128
bool mCanceled;

‎src/providers/grass/qgsgrassprovider.cpp

Lines changed: 284 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
#include "qgsdataprovider.h"
2626
#include "qgsfeature.h"
2727
#include "qgsfield.h"
28+
#include "qgslinestringv2.h"
29+
#include "qgspointv2.h"
30+
#include "qgspolygonv2.h"
2831
#include "qgsrectangle.h"
2932
#include "qgsvectorlayer.h"
3033
#include "qgsvectorlayereditbuffer.h"
@@ -238,8 +241,7 @@ int QgsGrassProvider::capabilities() const
238241
// for now, only one map may be edited at time
239242
if ( mEditBuffer || ( mLayer && mLayer->map() && !mLayer->map()->isEdited() ) )
240243
{
241-
//return AddFeatures | DeleteFeatures | ChangeAttributeValues | AddAttributes | DeleteAttributes | ChangeGeometries;
242-
return ChangeGeometries;
244+
return AddFeatures | DeleteFeatures | ChangeGeometries ;
243245
}
244246
return 0;
245247
}
@@ -1265,7 +1267,12 @@ void QgsGrassProvider::startEditing( QgsVectorLayer *vectorLayer )
12651267
mLayer->map()->startEdit();
12661268

12671269
mEditBuffer = vectorLayer->editBuffer();
1268-
connect( mEditBuffer, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry & ) ), SLOT( bufferGeometryChanged( QgsFeatureId, QgsGeometry & ) ) );
1270+
connect( mEditBuffer, SIGNAL( featureAdded( QgsFeatureId ) ), SLOT( onFeatureAdded( QgsFeatureId ) ) );
1271+
connect( mEditBuffer, SIGNAL( featureDeleted( QgsFeatureId ) ), SLOT( onFeatureDeleted( QgsFeatureId ) ) );
1272+
connect( mEditBuffer, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry & ) ), SLOT( onGeometryChanged( QgsFeatureId, QgsGeometry & ) ) );
1273+
connect( mEditBuffer, SIGNAL( attributeValueChanged( QgsFeatureId, int, const QVariant & ) ), SLOT( onAttributeValueChanged( QgsFeatureId, int, const QVariant & ) ) );
1274+
connect( mEditBuffer, SIGNAL( attributeAdded( int ) ), SLOT( onAttributeAdded( int ) ) );
1275+
connect( mEditBuffer, SIGNAL( attributeDeleted( int ) ), SLOT( onAttributeDeleted( int ) ) );
12691276
connect( vectorLayer, SIGNAL( beforeCommitChanges() ), SLOT( onBeforeCommitChanges() ) );
12701277
connect( vectorLayer, SIGNAL( editingStopped() ), SLOT( onEditingStopped() ) );
12711278

@@ -1274,65 +1281,306 @@ void QgsGrassProvider::startEditing( QgsVectorLayer *vectorLayer )
12741281
QgsDebugMsg( "edit started" );
12751282
}
12761283

1277-
void QgsGrassProvider::bufferGeometryChanged( QgsFeatureId fid, QgsGeometry &geom )
1284+
void QgsGrassProvider::setPoints( struct line_pnts *points, const QgsAbstractGeometryV2 * geometry )
12781285
{
1279-
int oldLid = QgsGrassFeatureIterator::lidFormFid( fid );
1286+
if ( !points )
1287+
{
1288+
return;
1289+
}
1290+
Vect_reset_line( points );
1291+
if ( !geometry )
1292+
{
1293+
return;
1294+
}
1295+
if ( geometry->wkbType() == QgsWKBTypes::Point )
1296+
{
1297+
const QgsPointV2* point = dynamic_cast<const QgsPointV2*>( geometry );
1298+
if ( point )
1299+
{
1300+
Vect_append_point( points, point->x(), point->y(), point->z() );
1301+
QgsDebugMsg( QString( "x = %1 y = %2" ).arg( point->x() ).arg( point->y() ) );
1302+
}
1303+
}
1304+
else if ( geometry->wkbType() == QgsWKBTypes::LineString )
1305+
{
1306+
const QgsLineStringV2* lineString = dynamic_cast<const QgsLineStringV2*>( geometry );
1307+
if ( lineString )
1308+
{
1309+
for ( int i = 0; i < lineString->numPoints(); i++ )
1310+
{
1311+
QgsPointV2 point = lineString->pointN( i );
1312+
Vect_append_point( points, point.x(), point.y(), point.z() );
1313+
}
1314+
}
1315+
}
1316+
else if ( geometry->wkbType() == QgsWKBTypes::Polygon )
1317+
{
1318+
const QgsPolygonV2* polygon = dynamic_cast<const QgsPolygonV2*>( geometry );
1319+
if ( polygon && polygon->exteriorRing() )
1320+
{
1321+
QList<QgsPointV2> pointsList;
1322+
polygon->exteriorRing()->points( pointsList );
1323+
Q_FOREACH ( QgsPointV2 point, pointsList )
1324+
{
1325+
Vect_append_point( points, point.x(), point.y(), point.z() );
1326+
}
1327+
}
1328+
}
1329+
else
1330+
{
1331+
QgsDebugMsg( "unknown type : " + geometry->geometryType() );
1332+
}
1333+
}
1334+
1335+
void QgsGrassProvider::onFeatureAdded( QgsFeatureId fid )
1336+
{
1337+
// fid is negative for new features
1338+
1339+
int lid = QgsGrassFeatureIterator::lidFromFid( fid );
1340+
int cat = QgsGrassFeatureIterator::catFromFid( fid );
1341+
QgsDebugMsg( QString( "fid = %1 lid = %2 cat = %3" ).arg( fid ).arg( lid ).arg( cat ) );
1342+
1343+
const QgsAbstractGeometryV2 *geometry = 0;
1344+
if ( FID_IS_NEW( fid ) )
1345+
{
1346+
if ( !mEditBuffer->addedFeatures().contains( fid ) )
1347+
{
1348+
QgsDebugMsg( "the feature is missing in buffer addedFeatures :" );
1349+
Q_FOREACH ( QgsFeatureId id, mEditBuffer->addedFeatures().keys() )
1350+
{
1351+
QgsDebugMsg( QString( "addedFeatures : id = %1" ).arg( id ) );
1352+
}
1353+
return;
1354+
}
1355+
QgsFeature feature = mEditBuffer->addedFeatures().value( fid );
1356+
if ( feature.geometry() )
1357+
{
1358+
geometry = feature.geometry()->geometry();
1359+
}
1360+
}
1361+
else // old deleted feature undo
1362+
{
1363+
// If it is not new feature, we should have the geometry in oldGeometries
1364+
if ( mLayer->map()->oldGeometries().contains( lid ) )
1365+
{
1366+
geometry = mLayer->map()->oldGeometries().value( lid );
1367+
}
1368+
else
1369+
{
1370+
QgsDebugMsg( "geometry of old, previously deleted feature not found" );
1371+
}
1372+
}
1373+
1374+
if ( !geometry )
1375+
{
1376+
QgsDebugMsg( "geometry is null" );
1377+
}
1378+
else
1379+
{
1380+
struct line_pnts *points = Vect_new_line_struct();
1381+
struct line_cats *cats = Vect_new_cats_struct();
1382+
1383+
setPoints( points, geometry );
1384+
// TODO: get also old type if it is feature previously deleted
1385+
int type = 0;
1386+
QgsWKBTypes::Type wkbType = QgsWKBTypes::flatType( geometry->wkbType() );
1387+
if ( wkbType == QgsWKBTypes::Point )
1388+
{
1389+
type = GV_POINT;
1390+
}
1391+
else if ( wkbType == QgsWKBTypes::LineString )
1392+
{
1393+
type = GV_LINE;
1394+
}
1395+
else if ( wkbType == QgsWKBTypes::Polygon )
1396+
{
1397+
type = GV_BOUNDARY;
1398+
}
1399+
else
1400+
{
1401+
QgsDebugMsg( QString( "unknown type %1" ).arg( wkbType ) );
1402+
}
1403+
1404+
if ( cat > 0 )
1405+
{
1406+
// TODO: orig field, maybe different
1407+
int field = mLayerField;
1408+
Vect_cat_set( cats, field, cat );
1409+
}
1410+
1411+
if ( type > 0 && points->n_points > 0 )
1412+
{
1413+
mLayer->map()->lockReadWrite();
1414+
int newLid = Vect_write_line( map(), type, points, cats );
1415+
mLayer->map()->unlockReadWrite();
1416+
1417+
QgsDebugMsg( QString( "newLine = %1" ).arg( newLid ) );
1418+
1419+
// fid may be new (negative) or old, if this is delete undo
1420+
int oldLid = QgsGrassFeatureIterator::lidFromFid( fid );
1421+
1422+
mLayer->map()->oldLids()[newLid] = oldLid;
1423+
mLayer->map()->newLids()[oldLid] = newLid;
1424+
QgsDebugMsg( QString( "oldLid = %1 newLine = %2" ).arg( oldLid ).arg( newLid ) );
1425+
1426+
QgsDebugMsg( QString( "oldLids : %1 -> %2" ).arg( newLid ).arg( oldLid ) );
1427+
mLayer->map()->oldLids()[newLid] = oldLid;
1428+
QgsDebugMsg( QString( "newLids : %1 -> %2" ).arg( oldLid ).arg( newLid ) );
1429+
mLayer->map()->newLids()[oldLid] = newLid;
1430+
1431+
if ( FID_IS_NEW( fid ) )
1432+
{
1433+
// Set topo symbol attribute
1434+
int symbol = mLayer->map()->topoSymbol( newLid );
1435+
QgsDebugMsg( QString( "symbol = %1" ).arg( symbol ) );
1436+
// TODO attribute index
1437+
int idx = mLayer->fields().size() - 1;
1438+
QgsFeatureMap & addedFeatures = const_cast<QgsFeatureMap&>( mEditBuffer->addedFeatures() );
1439+
addedFeatures[fid].setAttribute( idx, QVariant( symbol ) );
1440+
}
1441+
}
1442+
1443+
Vect_destroy_line_struct( points );
1444+
Vect_destroy_cats_struct( cats );
1445+
}
1446+
}
1447+
1448+
void QgsGrassProvider::onFeatureDeleted( QgsFeatureId fid )
1449+
{
1450+
QgsDebugMsg( QString( "fid = %1" ).arg( fid ) );
1451+
1452+
int oldLid = QgsGrassFeatureIterator::lidFromFid( fid );
12801453
int realLine = oldLid;
12811454
if ( mLayer->map()->newLids().contains( oldLid ) ) // if it was changed already
12821455
{
12831456
realLine = mLayer->map()->newLids().value( oldLid );
12841457
}
12851458
QgsDebugMsg( QString( "fid = %1 oldLid = %2 realLine = %3" ).arg( fid ).arg( oldLid ).arg( realLine ) );
12861459

1287-
struct line_pnts *points = Vect_new_line_struct();
1288-
struct line_cats *cats = Vect_new_cats_struct();
1289-
1290-
int type = Vect_read_line( map(), points, cats, realLine );
1291-
QgsDebugMsg( QString( "type = %1 n_points = %2" ).arg( type ).arg( points->n_points ) );
1292-
1293-
// store only the first original geometry, changed geometries are stored in the buffer
1294-
if ( !mLayer->map()->oldGeometries().contains( oldLid ) )
1460+
// store only the first original geometry if it is not new feature, changed geometries are stored in the buffer
1461+
if ( oldLid > 0 && !mLayer->map()->oldGeometries().contains( oldLid ) )
12951462
{
12961463
QgsAbstractGeometryV2 *geometry = mLayer->map()->lineGeometry( oldLid );
1297-
mLayer->map()->oldGeometries().insert( oldLid, geometry );
1464+
if ( geometry )
1465+
{
1466+
QgsDebugMsg( QString( "save old geometry of oldLid = %1" ).arg( oldLid ) );
1467+
mLayer->map()->oldGeometries().insert( oldLid, geometry );
1468+
}
1469+
else
1470+
{
1471+
QgsDebugMsg( QString( "cannot read geometry of oldLid = %1" ).arg( oldLid ) );
1472+
}
12981473
}
12991474

1300-
if ( type == GV_POINT || type == GV_CENTROID )
1301-
{
1302-
QgsPoint point = geom.asPoint();
1303-
points->x[0] = point.x();
1304-
points->y[0] = point.y();
1305-
QgsDebugMsg( QString( "x = %1 y = %2" ).arg( point.x() ).arg( point.y() ) );
1306-
}
1307-
else if ( type == GV_LINE || type == GV_BOUNDARY )
1475+
mLayer->map()->lockReadWrite();
1476+
G_TRY
13081477
{
1309-
QgsPolyline polyline = geom.asPolyline();
1310-
for ( int i = 0; i < points->n_points; i++ )
1478+
Vect_delete_line( map(), realLine );
1479+
// oldLids are maping to the very first, original version (used by undo)
1480+
int oldestLid = oldLid;
1481+
if ( mLayer->map()->oldLids().contains( oldLid ) )
13111482
{
1312-
points->x[i] = polyline.value( i ).x();
1313-
points->y[i] = polyline.value( i ).y();
1483+
oldestLid = mLayer->map()->oldLids().value( oldLid );
13141484
}
1485+
QgsDebugMsg( QString( "oldLid = %1 oldestLid = %2" ).arg( oldLid ).arg( oldestLid ) );
1486+
QgsDebugMsg( QString( "newLids : %1 -> 0" ).arg( oldestLid ) );
1487+
mLayer->map()->newLids()[oldestLid] = 0;
13151488
}
1316-
else
1489+
G_CATCH( QgsGrass::Exception &e )
1490+
{
1491+
QgsDebugMsg( QString( "Cannot delete line : %1" ).arg( e.what() ) );
1492+
}
1493+
mLayer->map()->unlockReadWrite();
1494+
}
1495+
1496+
void QgsGrassProvider::onGeometryChanged( QgsFeatureId fid, QgsGeometry &geom )
1497+
{
1498+
int oldLid = QgsGrassFeatureIterator::lidFromFid( fid );
1499+
int realLine = oldLid;
1500+
if ( mLayer->map()->newLids().contains( oldLid ) ) // if it was changed already
13171501
{
1318-
QgsDebugMsg( "unknown type" );
1502+
realLine = mLayer->map()->newLids().value( oldLid );
1503+
}
1504+
QgsDebugMsg( QString( "fid = %1 oldLid = %2 realLine = %3" ).arg( fid ).arg( oldLid ).arg( realLine ) );
1505+
1506+
struct line_pnts *points = Vect_new_line_struct();
1507+
struct line_cats *cats = Vect_new_cats_struct();
1508+
1509+
int type;
1510+
G_TRY
1511+
{
1512+
type = Vect_read_line( map(), points, cats, realLine );
1513+
}
1514+
G_CATCH( QgsGrass::Exception &e )
1515+
{
1516+
QgsDebugMsg( QString( "Cannot read line : %1" ).arg( e.what() ) );
1517+
Vect_destroy_line_struct( points );
1518+
Vect_destroy_cats_struct( cats );
13191519
return;
13201520
}
1521+
QgsDebugMsg( QString( "type = %1 n_points = %2" ).arg( type ).arg( points->n_points ) );
1522+
1523+
// store only the first original geometry if it is not new feature, changed geometries are stored in the buffer
1524+
if ( oldLid > 0 && !mLayer->map()->oldGeometries().contains( oldLid ) )
1525+
{
1526+
QgsAbstractGeometryV2 *geometry = mLayer->map()->lineGeometry( oldLid );
1527+
if ( geometry )
1528+
{
1529+
QgsDebugMsg( QString( "save old geometry of oldLid = %1" ).arg( oldLid ) );
1530+
mLayer->map()->oldGeometries().insert( oldLid, geometry );
1531+
}
1532+
else
1533+
{
1534+
QgsDebugMsg( QString( "cannot read geometry of oldLid = %1" ).arg( oldLid ) );
1535+
}
1536+
}
1537+
1538+
setPoints( points, geom.geometry() );
13211539

13221540
mLayer->map()->lockReadWrite();
13231541
// Vect_rewrite_line may delete/write the line with a new id
13241542
int newLid = Vect_rewrite_line( map(), realLine, type, points, cats );
1325-
mLayer->map()->unlockReadWrite();
1543+
G_TRY
1544+
{
1545+
newLid = Vect_rewrite_line( map(), realLine, type, points, cats );
13261546

1327-
QgsDebugMsg( QString( "oldLid = %1 newLine = %2" ).arg( oldLid ).arg( newLid ) );
1328-
// oldLids are maping to the very first, original version (used by undo)
1329-
int oldestLid = oldLid;
1330-
if ( mLayer->map()->oldLids().contains( oldLid ) )
1547+
// oldLids are maping to the very first, original version (used by undo)
1548+
int oldestLid = oldLid;
1549+
if ( mLayer->map()->oldLids().contains( oldLid ) )
1550+
{
1551+
oldestLid = mLayer->map()->oldLids().value( oldLid );
1552+
}
1553+
QgsDebugMsg( QString( "oldLid = %1 oldestLid = %2 newLine = %3" ).arg( oldLid ).arg( oldestLid ).arg( newLid ) );
1554+
QgsDebugMsg( QString( "oldLids : %1 -> %2" ).arg( newLid ).arg( oldestLid ) );
1555+
mLayer->map()->oldLids()[newLid] = oldestLid;
1556+
QgsDebugMsg( QString( "newLids : %1 -> %2" ).arg( oldestLid ).arg( newLid ) );
1557+
mLayer->map()->newLids()[oldestLid] = newLid;
1558+
}
1559+
G_CATCH( QgsGrass::Exception &e )
13311560
{
1332-
oldestLid = mLayer->map()->oldLids().value( oldLid );
1561+
QgsDebugMsg( QString( "Cannot write line : %1" ).arg( e.what() ) );
13331562
}
1334-
mLayer->map()->oldLids()[newLid] = oldestLid;
1335-
mLayer->map()->newLids()[oldLid] = newLid;
1563+
mLayer->map()->unlockReadWrite();
1564+
1565+
Vect_destroy_line_struct( points );
1566+
Vect_destroy_cats_struct( cats );
1567+
1568+
1569+
}
1570+
1571+
void QgsGrassProvider::onAttributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value )
1572+
{
1573+
QgsDebugMsg( QString( "fid = %1 idx = %2 value = %3" ).arg( fid ).arg( idx ).arg( value.toString() ) );
1574+
}
1575+
1576+
void QgsGrassProvider::onAttributeAdded( int idx )
1577+
{
1578+
QgsDebugMsg( QString( "idx = %1" ).arg( idx ) );
1579+
}
1580+
1581+
void QgsGrassProvider::onAttributeDeleted( int idx )
1582+
{
1583+
QgsDebugMsg( QString( "idx = %1" ).arg( idx ) );
13361584
}
13371585

13381586
void QgsGrassProvider::onUndoIndexChanged( int index )

‎src/providers/grass/qgsgrassprovider.h

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -57,21 +57,6 @@ class GRASS_LIB_EXPORT QgsGrassProvider : public QgsVectorDataProvider
5757
Q_OBJECT
5858

5959
public:
60-
enum TopoSymbol
61-
{
62-
TopoUndefined = 0,
63-
TopoPoint,
64-
TopoLine,
65-
TopoBoundary0,
66-
TopoBoundary1,
67-
TopoBoundary2,
68-
TopoCentroidIn,
69-
TopoCentroidOut,
70-
TopoCentroidDupl,
71-
TopoNode0,
72-
TopoNode1,
73-
TopoNode2
74-
};
7560

7661
QgsGrassProvider( QString uri = QString() );
7762

@@ -439,7 +424,12 @@ class GRASS_LIB_EXPORT QgsGrassProvider : public QgsVectorDataProvider
439424
};
440425

441426
public slots:
442-
void bufferGeometryChanged( QgsFeatureId fid, QgsGeometry &geom );
427+
void onFeatureAdded( QgsFeatureId fid );
428+
void onFeatureDeleted( QgsFeatureId fid );
429+
void onGeometryChanged( QgsFeatureId fid, QgsGeometry &geom );
430+
void onAttributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value );
431+
void onAttributeAdded( int idx );
432+
void onAttributeDeleted( int idx );
443433
void onBeforeCommitChanges();
444434
void onEditingStopped();
445435
void onUndoIndexChanged( int index );
@@ -495,6 +485,8 @@ class GRASS_LIB_EXPORT QgsGrassProvider : public QgsVectorDataProvider
495485

496486
void setTopoFields();
497487

488+
void setPoints( struct line_pnts *points, const QgsAbstractGeometryV2 * geometry );
489+
498490
/** Fields used for topo layers */
499491
QgsFields mTopoFields;
500492

‎src/providers/grass/qgsgrassvectormap.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,3 +683,47 @@ QgsGrassVectorMap * QgsGrassVectorMapStore::openMap( const QgsGrassObject & gras
683683
mMutex.unlock();
684684
return map;
685685
}
686+
687+
QgsGrassVectorMap::TopoSymbol QgsGrassVectorMap::topoSymbol( int lid )
688+
{
689+
int type = Vect_read_line( mMap, 0, 0, lid );
690+
691+
TopoSymbol symbol = TopoUndefined;
692+
if ( type == GV_POINT )
693+
{
694+
symbol = TopoPoint;
695+
}
696+
else if ( type == GV_CENTROID )
697+
{
698+
int area = Vect_get_centroid_area( mMap, lid );
699+
if ( area == 0 )
700+
symbol = TopoCentroidOut;
701+
else if ( area > 0 )
702+
symbol = TopoCentroidIn;
703+
else
704+
symbol = TopoCentroidDupl; /* area < 0 */
705+
}
706+
else if ( type == GV_LINE )
707+
{
708+
symbol = TopoLine;
709+
}
710+
else if ( type == GV_BOUNDARY )
711+
{
712+
int left, right;
713+
Vect_get_line_areas( mMap, lid, &left, &right );
714+
if ( left != 0 && right != 0 )
715+
{
716+
symbol = TopoBoundary2;
717+
}
718+
else if ( left == 0 && right == 0 )
719+
{
720+
symbol = TopoBoundary0;
721+
}
722+
else
723+
{
724+
symbol = TopoBoundary1;
725+
}
726+
}
727+
QgsDebugMsgLevel( QString( "lid = %1 type = %2 symbol = %3" ).arg( lid ).arg( type ).arg( symbol ), 3 );
728+
return symbol;
729+
}

‎src/providers/grass/qgsgrassvectormap.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,22 @@ class GRASS_LIB_EXPORT QgsGrassVectorMap : public QObject
2929
{
3030
Q_OBJECT
3131
public:
32+
enum TopoSymbol
33+
{
34+
TopoUndefined = 0,
35+
TopoPoint,
36+
TopoLine,
37+
TopoBoundary0,
38+
TopoBoundary1,
39+
TopoBoundary2,
40+
TopoCentroidIn,
41+
TopoCentroidOut,
42+
TopoCentroidDupl,
43+
TopoNode0,
44+
TopoNode1,
45+
TopoNode2
46+
};
47+
3248
QgsGrassVectorMap( const QgsGrassObject & grassObject );
3349
~QgsGrassVectorMap();
3450

@@ -111,6 +127,11 @@ class GRASS_LIB_EXPORT QgsGrassVectorMap : public QObject
111127
/** Map descripton for debugging */
112128
QString toString();
113129

130+
/** Get topology symbol code
131+
* @param lid line or area number
132+
* @param type geometry type */
133+
TopoSymbol topoSymbol( int lid );
134+
114135
signals:
115136
/** Ask all iterators to cancel iteration when possible. Connected to iterators with
116137
* Qt::DirectConnection (non blocking) */

0 commit comments

Comments
 (0)
Please sign in to comment.