Skip to content

Commit

Permalink
manage addFeatures fails (mainly due to geom compatibility check)
Browse files Browse the repository at this point in the history
  • Loading branch information
luipir committed Sep 26, 2017
1 parent 7012c12 commit 016363f
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 41 deletions.
27 changes: 22 additions & 5 deletions src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7176,9 +7176,20 @@ void QgisApp::mergeSelectedFeatures()
vl->deleteFeature( *feature_it );
}

vl->addFeature( newFeature, false );
// addFeature can fail if newFeature has no compatibile geometry
if ( !vl->addFeature( newFeature, false ) )
{
messageBar()->pushMessage(
tr( "Invalid result" ),
tr( "Invalid edit operation see the log for more info" ),
QgsMessageBar::WARNING );

vl->endEditCommand();
vl->destroyEditCommand();
}
else
{
vl->endEditCommand();
}

if ( mapCanvas() )
{
Expand Down Expand Up @@ -7533,8 +7544,14 @@ void QgisApp::editPaste( QgsMapLayer *destinationLayer )
++featureIt;
}

pasteVectorLayer->addFeatures( features );
pasteVectorLayer->endEditCommand();
if ( !pasteVectorLayer->addFeatures( features ) )
{
pasteVectorLayer->destroyEditCommand();
}
else
{
pasteVectorLayer->endEditCommand();
}

int nCopiedFeatures = features.count();
if ( nCopiedFeatures == 0 )
Expand Down Expand Up @@ -7721,7 +7738,7 @@ QgsVectorLayer *QgisApp::pasteToNewMemoryVector()
feature.geometry()->convertToMultiType();
}
}
if ( ! layer->addFeatures( features, false ) || !layer->commitChanges() )
if ( !layer->addFeatures( features, false ) || !layer->commitChanges() )
{
QgsDebugMsg( "Cannot add features or commit changes" );
delete layer;
Expand Down
102 changes: 69 additions & 33 deletions src/core/qgsofflineediting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ extern "C"
#define PROJECT_ENTRY_SCOPE_OFFLINE "OfflineEditingPlugin"
#define PROJECT_ENTRY_KEY_OFFLINE_DB_PATH "/OfflineDbPath"

QgsOfflineEditing::QgsOfflineEditing()
QgsOfflineEditing::QgsOfflineEditing():
syncError( false )
{
connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWasAdded( QgsMapLayer* ) ), this, SLOT( layerAdded( QgsMapLayer* ) ) );
}
Expand Down Expand Up @@ -261,6 +262,7 @@ void QgsOfflineEditing::synchronize()
updateVisibilityPresets( offlineLayer, remoteLayer );

// apply layer edit log
syncError = false;
QString qgisLayerId = layer->id();
QString sql = QString( "SELECT \"id\" FROM 'log_layer_ids' WHERE \"qgis_id\" = '%1'" ).arg( qgisLayerId );
int layerId = sqlQueryInt( db, sql, -1 );
Expand All @@ -276,37 +278,49 @@ void QgsOfflineEditing::synchronize()
QgsDebugMsgLevel( "Apply commits chronologically", 4 );
// apply commits chronologically
applyAttributesAdded( remoteLayer, db, layerId, i );
applyAttributeValueChanges( offlineLayer, remoteLayer, db, layerId, i );
applyGeometryChanges( remoteLayer, db, layerId, i );
if ( !syncError )
applyAttributeValueChanges( offlineLayer, remoteLayer, db, layerId, i );
if ( !syncError )
applyGeometryChanges( remoteLayer, db, layerId, i );
}

applyFeaturesAdded( offlineLayer, remoteLayer, db, layerId );
applyFeaturesRemoved( remoteLayer, db, layerId );
if ( !syncError )
applyFeaturesAdded( offlineLayer, remoteLayer, db, layerId );
if ( !syncError )
applyFeaturesRemoved( remoteLayer, db, layerId );

if ( remoteLayer->commitChanges() )
if ( !syncError )
{
// update fid lookup
updateFidLookup( remoteLayer, db, layerId );

// clear edit log for this layer
sql = QString( "DELETE FROM 'log_added_attrs' WHERE \"layer_id\" = %1" ).arg( layerId );
sqlExec( db, sql );
sql = QString( "DELETE FROM 'log_added_features' WHERE \"layer_id\" = %1" ).arg( layerId );
sqlExec( db, sql );
sql = QString( "DELETE FROM 'log_removed_features' WHERE \"layer_id\" = %1" ).arg( layerId );
sqlExec( db, sql );
sql = QString( "DELETE FROM 'log_feature_updates' WHERE \"layer_id\" = %1" ).arg( layerId );
sqlExec( db, sql );
sql = QString( "DELETE FROM 'log_geometry_updates' WHERE \"layer_id\" = %1" ).arg( layerId );
sqlExec( db, sql );

// reset commitNo
QString sql = QString( "UPDATE 'log_indices' SET 'last_index' = 0 WHERE \"name\" = 'commit_no'" );
sqlExec( db, sql );
if ( remoteLayer->commitChanges() )
{
// update fid lookup
updateFidLookup( remoteLayer, db, layerId );

// clear edit log for this layer
sql = QString( "DELETE FROM 'log_added_attrs' WHERE \"layer_id\" = %1" ).arg( layerId );
sqlExec( db, sql );
sql = QString( "DELETE FROM 'log_added_features' WHERE \"layer_id\" = %1" ).arg( layerId );
sqlExec( db, sql );
sql = QString( "DELETE FROM 'log_removed_features' WHERE \"layer_id\" = %1" ).arg( layerId );
sqlExec( db, sql );
sql = QString( "DELETE FROM 'log_feature_updates' WHERE \"layer_id\" = %1" ).arg( layerId );
sqlExec( db, sql );
sql = QString( "DELETE FROM 'log_geometry_updates' WHERE \"layer_id\" = %1" ).arg( layerId );
sqlExec( db, sql );

// reset commitNo
QString sql = QString( "UPDATE 'log_indices' SET 'last_index' = 0 WHERE \"name\" = 'commit_no'" );
sqlExec( db, sql );
}
else
{
showWarning( remoteLayer->commitErrors().join( "\n" ) );
}
}
else
{
showWarning( remoteLayer->commitErrors().join( "\n" ) );
remoteLayer->rollBack();
showWarning( tr( "Syncronization failed. see log for more details" ) );
}
}
else
Expand Down Expand Up @@ -688,7 +702,11 @@ QgsVectorLayer* QgsOfflineEditing::copyVectorLayer( QgsVectorLayer* layer, sqlit
f.geometry()->setGeometry( geom );
}

newLayer->addFeature( f, false );
if ( !newLayer->addFeature( f, false ) )
{
showWarning( tr( "Invalid edit operation see the log for more info" ) );
return nullptr;
}

emit progressUpdated( featureCount++ );
}
Expand Down Expand Up @@ -762,7 +780,11 @@ void QgsOfflineEditing::applyAttributesAdded( QgsVectorLayer* remoteLayer, sqlit
{
QString typeName = typeNameLookup[ field.type()];
field.setTypeName( typeName );
remoteLayer->addAttribute( field );
if ( !remoteLayer->addAttribute( field ) )
{
this->syncError = true;
return;
}
}
else
{
Expand Down Expand Up @@ -830,7 +852,11 @@ void QgsOfflineEditing::applyFeaturesAdded( QgsVectorLayer* offlineLayer, QgsVec

f.setAttributes( newAttrs );

remoteLayer->addFeature( f, false );
if ( !remoteLayer->addFeature( f, false ) )
{
this->syncError = true;
return;
}

emit progressUpdated( i++ );
}
Expand All @@ -847,7 +873,11 @@ void QgsOfflineEditing::applyFeaturesRemoved( QgsVectorLayer* remoteLayer, sqlit
for ( QgsFeatureIds::const_iterator it = values.begin(); it != values.end(); ++it )
{
QgsFeatureId fid = remoteFid( db, layerId, *it );
remoteLayer->deleteFeature( fid );
if ( !remoteLayer->deleteFeature( fid ) )
{
this->syncError = true;
return;
}

emit progressUpdated( i++ );
}
Expand All @@ -866,7 +896,11 @@ void QgsOfflineEditing::applyAttributeValueChanges( QgsVectorLayer* offlineLayer
{
QgsFeatureId fid = remoteFid( db, layerId, values.at( i ).fid );
QgsDebugMsgLevel( QString( "Offline changeAttributeValue %1 = %2" ).arg( QString( attrLookup[ values.at( i ).attr ] ), values.at( i ).value ), 4 );
remoteLayer->changeAttributeValue( fid, attrLookup[ values.at( i ).attr ], values.at( i ).value );
if ( !remoteLayer->changeAttributeValue( fid, attrLookup[ values.at( i ).attr ], values.at( i ).value ) )
{
this->syncError = true;
return;
}

emit progressUpdated( i + 1 );
}
Expand All @@ -882,9 +916,11 @@ void QgsOfflineEditing::applyGeometryChanges( QgsVectorLayer* remoteLayer, sqlit
for ( int i = 0; i < values.size(); i++ )
{
QgsFeatureId fid = remoteFid( db, layerId, values.at( i ).fid );
// TODO: check if changeGeometry success and find a way to
// interrupt applyGeometryChanges if it fail
remoteLayer->changeGeometry( fid, QgsGeometry::fromWkt( values.at( i ).geom_wkt ) );
if ( !remoteLayer->changeGeometry( fid, QgsGeometry::fromWkt( values.at( i ).geom_wkt ) ) )
{
this->syncError = true;
return;
}

emit progressUpdated( i + 1 );
}
Expand Down
5 changes: 5 additions & 0 deletions src/core/qgsofflineediting.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ class CORE_EXPORT QgsOfflineEditing : public QObject
};
typedef QList<GeometryChange> GeometryChanges;
GeometryChanges sqlQueryGeometryChanges( sqlite3* db, const QString& sql );
/**
* in case of sync error the flag is set to true
*/
bool syncError;


private slots:
void layerAdded( QgsMapLayer* layer );
Expand Down
3 changes: 2 additions & 1 deletion src/core/qgsvectorlayereditutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,8 @@ int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPoint>& splitLine, bo


//now add the new features to this vectorlayer
L->editBuffer()->addFeatures( newFeatures );
if ( !L->editBuffer()->addFeatures( newFeatures ) )
returnCode = 7; // "No feature split done" + "The geometry is invalid. Please repair before trying to split it."

return returnCode;
}
Expand Down
1 change: 1 addition & 0 deletions src/gui/qgsrelationeditorwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ void QgsRelationEditorWidget::linkFeature()
newFeatures << linkFeature;
}

// TODO: what to do in case of addFeature fail?
mRelation.referencingLayer()->addFeatures( newFeatures );

updateUi();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,11 @@ bool QgsGeometryCheckerResultTab::exportErrorsDo( const QString& file )
f.setAttribute( fieldFeatureId, error->featureId() );
f.setAttribute( fieldErrDesc, error->description() );
f.setGeometry( new QgsGeometry( error->location().clone() ) );
layer->dataProvider()->addFeatures( QgsFeatureList() << f );
if ( !layer->dataProvider()->addFeatures( QgsFeatureList() << f ) )
{
delete layer;
return false;
}
}

// Remove existing layer with same uri
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,11 @@ void QgsGeometryCheckerSetupTab::runChecks()
features.append( feature );
}
}
newlayer->dataProvider()->addFeatures( features );
if ( !newlayer->dataProvider()->addFeatures( features ) )
{
QMessageBox::critical( this, tr( "Populate output Layer" ), tr( "See message log. Can not add features to output layer: %1." ).arg( filename ) );
return;
}

// Set selected features
newlayer->selectByIds( selectedFeatures );
Expand Down

0 comments on commit 016363f

Please sign in to comment.