Skip to content

Commit bec04c1

Browse files
authoredDec 11, 2018
Merge pull request #8600 from signedav/fix_gpkg_order
Offline editing to GPKG attribute order. Fixes #20276
2 parents 54f28df + 8fda2b7 commit bec04c1

File tree

2 files changed

+50
-11
lines changed

2 files changed

+50
-11
lines changed
 

‎src/core/qgsofflineediting.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -762,12 +762,10 @@ QgsVectorLayer *QgsOfflineEditing::copyVectorLayer( QgsVectorLayer *layer, sqlit
762762

763763
// NOTE: SpatiaLite provider ignores position of geometry column
764764
// fill gap in QgsAttributeMap if geometry column is not last (WORKAROUND)
765-
QgsAttributes attrs = f.attributes();
766765
int column = 0;
766+
QgsAttributes attrs = f.attributes();
767767
// on GPKG newAttrs has an addition FID attribute, so we have to add a dummy in the original set
768-
if ( containerType == GPKG )
769-
column++;
770-
QgsAttributes newAttrs( attrs.count() + column );
768+
QgsAttributes newAttrs( containerType == GPKG ? attrs.count() + 1 : attrs.count() );
771769
for ( int it = 0; it < attrs.count(); ++it )
772770
{
773771
newAttrs[column++] = attrs.at( it );
@@ -1139,13 +1137,14 @@ void QgsOfflineEditing::updateLayerOrder( QgsVectorLayer *sourceLayer, QgsVector
11391137
QMap<int, int> QgsOfflineEditing::attributeLookup( QgsVectorLayer *offlineLayer, QgsVectorLayer *remoteLayer )
11401138
{
11411139
const QgsAttributeList &offlineAttrs = offlineLayer->attributeList();
1142-
const QgsAttributeList &remoteAttrs = remoteLayer->attributeList();
11431140

11441141
QMap < int /*offline attr*/, int /*remote attr*/ > attrLookup;
1145-
// NOTE: use size of remoteAttrs, as offlineAttrs can have new attributes not yet synced
1146-
for ( int i = 0; i < remoteAttrs.size(); i++ )
1142+
// NOTE: though offlineAttrs can have new attributes not yet synced, we take the amount of offlineAttrs
1143+
// because we anyway only add mapping for the fields existing in remoteLayer (this because it could contain fid on 0)
1144+
for ( int i = 0; i < offlineAttrs.size(); i++ )
11471145
{
1148-
attrLookup.insert( offlineAttrs.at( i ), remoteAttrs.at( i ) );
1146+
if ( remoteLayer->fields().lookupField( offlineLayer->fields().field( i ).name() ) >= 0 )
1147+
attrLookup.insert( offlineAttrs.at( i ), remoteLayer->fields().indexOf( offlineLayer->fields().field( i ).name() ) );
11491148
}
11501149

11511150
return attrLookup;

‎tests/src/core/testqgsofflineediting.cpp

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class TestQgsOfflineEditing : public QObject
4141
QStringList layerIds;
4242
long numberOfFeatures;
4343
int numberOfFields;
44+
QTemporaryDir tempDir;
4445

4546
private slots:
4647
void initTestCase();// will be called before the first testfunction is executed.
@@ -75,8 +76,12 @@ void TestQgsOfflineEditing::cleanupTestCase()
7576
void TestQgsOfflineEditing::init()
7677
{
7778
QString myFileName( TEST_DATA_DIR ); //defined in CmakeLists.txt
78-
myFileName = myFileName + "/points.shp";
79-
QFileInfo myMapFileInfo( myFileName );
79+
QString myTempDirName = tempDir.path();
80+
QFile::copy( myFileName + "/points.shp", myTempDirName + "/points.shp" );
81+
QFile::copy( myFileName + "/points.shx", myTempDirName + "/points.shx" );
82+
QFile::copy( myFileName + "/points.dbf", myTempDirName + "/points.dbf" );
83+
QString myTempFileName = myTempDirName + "/points.shp";
84+
QFileInfo myMapFileInfo( myTempFileName );
8085
mpLayer = new QgsVectorLayer( myMapFileInfo.filePath(),
8186
myMapFileInfo.completeBaseName(), QStringLiteral( "ogr" ) );
8287
QgsProject::instance()->addMapLayer( mpLayer );
@@ -124,6 +129,9 @@ void TestQgsOfflineEditing::createGeopackageAndSynchronizeBack()
124129
QCOMPARE( mpLayer->name(), QStringLiteral( "points" ) );
125130
QCOMPARE( mpLayer->featureCount(), numberOfFeatures );
126131
QCOMPARE( mpLayer->fields().size(), numberOfFields );
132+
QgsFeature firstFeatureBeforeAction;
133+
QgsFeatureIterator it = mpLayer->getFeatures();
134+
it.nextFeature( firstFeatureBeforeAction );
127135

128136
connect( mOfflineEditing, &QgsOfflineEditing::warning, this, []( const QString & title, const QString & message ) { qDebug() << title << message; } );
129137
//convert
@@ -135,13 +143,45 @@ void TestQgsOfflineEditing::createGeopackageAndSynchronizeBack()
135143
//comparing with the number +1 because GPKG created an fid
136144
QCOMPARE( mpLayer->fields().size(), numberOfFields + 1 );
137145

146+
QgsFeature firstFeatureInAction;
147+
it = mpLayer->getFeatures();
148+
it.nextFeature( firstFeatureInAction );
149+
150+
//compare some values
151+
QCOMPARE( firstFeatureInAction.attribute( QStringLiteral( "Class" ) ).toString(), firstFeatureBeforeAction.attribute( QStringLiteral( "Class" ) ).toString() );
152+
QCOMPARE( firstFeatureInAction.attribute( QStringLiteral( "Heading" ) ).toString(), firstFeatureBeforeAction.attribute( QStringLiteral( "Heading" ) ).toString() );
153+
QCOMPARE( firstFeatureInAction.attribute( QStringLiteral( "Cabin Crew" ) ).toString(), firstFeatureBeforeAction.attribute( QStringLiteral( "Cabin Crew" ) ).toString() );
154+
155+
QgsFeature newFeature( mpLayer->dataProvider()->fields() );
156+
newFeature.setAttribute( QStringLiteral( "Class" ), QStringLiteral( "Superjet" ) );
157+
mpLayer->startEditing();
158+
mpLayer->addFeature( newFeature );
159+
mpLayer->commitChanges();
160+
QCOMPARE( mpLayer->featureCount(), numberOfFeatures + 1 );
161+
138162
//synchronize back
139163
mOfflineEditing->synchronize();
140164

141165
mpLayer = qobject_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayers().first() );
142166
QCOMPARE( mpLayer->name(), QStringLiteral( "points" ) );
143-
QCOMPARE( mpLayer->featureCount(), numberOfFeatures );
167+
QCOMPARE( mpLayer->dataProvider()->featureCount(), numberOfFeatures + 1 );
144168
QCOMPARE( mpLayer->fields().size(), numberOfFields );
169+
//get last feature
170+
QgsFeature f = mpLayer->getFeature( mpLayer->dataProvider()->featureCount() - 1 );
171+
qDebug() << "FID:" << f.id() << "Class:" << f.attribute( "Class" ).toString();
172+
QCOMPARE( f.attribute( QStringLiteral( "Class" ) ).toString(), QStringLiteral( "Superjet" ) );
173+
174+
QgsFeature firstFeatureAfterAction;
175+
it = mpLayer->getFeatures();
176+
it.nextFeature( firstFeatureAfterAction );
177+
178+
QCOMPARE( firstFeatureAfterAction, firstFeatureBeforeAction );
179+
180+
//and delete the feature again
181+
QgsFeatureIds idsToClean;
182+
idsToClean << f.id();
183+
mpLayer->dataProvider()->deleteFeatures( idsToClean );
184+
QCOMPARE( mpLayer->dataProvider()->featureCount(), numberOfFeatures );
145185
}
146186

147187
QGSTEST_MAIN( TestQgsOfflineEditing )

0 commit comments

Comments
 (0)
Please sign in to comment.