|
@@ -8597,70 +8597,35 @@ void QgisApp::pasteFromClipboard( QgsMapLayer *destinationLayer ) |
|
|
pasteVectorLayer->beginEditCommand( tr( "Features pasted" ) ); |
|
|
QgsFeatureList features = clipboard()->transformedCopyOf( pasteVectorLayer->crs(), pasteVectorLayer->fields() ); |
|
|
int nTotalFeatures = features.count(); |
|
|
|
|
|
QHash<int, int> remap; |
|
|
QgsFields fields = clipboard()->fields(); |
|
|
for ( int idx = 0; idx < fields.count(); ++idx ) |
|
|
{ |
|
|
int dst = pasteVectorLayer->fields().lookupField( fields.at( idx ).name() ); |
|
|
if ( dst < 0 ) |
|
|
continue; |
|
|
|
|
|
remap.insert( idx, dst ); |
|
|
} |
|
|
|
|
|
QgsExpressionContext context = pasteVectorLayer->createExpressionContext(); |
|
|
|
|
|
int invalidGeometriesCount = 0; |
|
|
QgsFeatureList compatibleFeatures( QgsVectorLayerUtils::makeFeaturesCompatible( features, pasteVectorLayer ) ); |
|
|
QgsFeatureList newFeatures; |
|
|
QgsFeatureList::const_iterator featureIt = features.constBegin(); |
|
|
while ( featureIt != features.constEnd() ) |
|
|
// Count collapsed geometries |
|
|
int invalidGeometriesCount = 0; |
|
|
|
|
|
for ( const auto &feature : qgis::as_const( compatibleFeatures ) ) |
|
|
{ |
|
|
QgsAttributes srcAttr = featureIt->attributes(); |
|
|
QgsAttributeMap dstAttr; |
|
|
|
|
|
for ( int src = 0; src < srcAttr.count(); ++src ) |
|
|
{ |
|
|
int dst = remap.value( src, -1 ); |
|
|
if ( dst < 0 ) |
|
|
continue; |
|
|
QgsGeometry geom = feature.geometry(); |
|
|
|
|
|
dstAttr[ dst ] = srcAttr.at( src ); |
|
|
} |
|
|
|
|
|
QgsGeometry geom = featureIt->geometry(); |
|
|
bool geomWasInvalid = geom.isEmpty() || geom.isNull( ); |
|
|
if ( featureIt->hasGeometry() ) |
|
|
if ( !( geom.isEmpty() || geom.isNull( ) ) ) |
|
|
{ |
|
|
// convert geometry to match destination layer |
|
|
QgsWkbTypes::GeometryType destType = pasteVectorLayer->geometryType(); |
|
|
bool destIsMulti = QgsWkbTypes::isMultiType( pasteVectorLayer->wkbType() ); |
|
|
if ( pasteVectorLayer->dataProvider() && |
|
|
!pasteVectorLayer->dataProvider()->doesStrictFeatureTypeCheck() ) |
|
|
{ |
|
|
// force destination to multi if provider doesn't do a feature strict check |
|
|
destIsMulti = true; |
|
|
} |
|
|
|
|
|
if ( destType != QgsWkbTypes::UnknownGeometry ) |
|
|
{ |
|
|
QgsGeometry newGeometry = geom.convertToType( destType, destIsMulti ); |
|
|
if ( newGeometry.isNull() ) |
|
|
{ |
|
|
continue; |
|
|
} |
|
|
geom = newGeometry; |
|
|
} |
|
|
// avoid intersection if enabled in digitize settings |
|
|
geom.avoidIntersections( QgsProject::instance()->avoidIntersectionsLayers() ); |
|
|
// Count collapsed geometries |
|
|
if ( geom.isEmpty() || geom.isNull( ) ) |
|
|
invalidGeometriesCount++; |
|
|
} |
|
|
if ( ! geomWasInvalid && ( geom.isEmpty() || geom.isNull( ) ) ) |
|
|
invalidGeometriesCount++; |
|
|
|
|
|
QgsAttributeMap attrMap; |
|
|
for ( int i = 0; i < feature.fields().count(); i++ ) |
|
|
{ |
|
|
attrMap[i] = feature.attribute( i ); |
|
|
} |
|
|
// now create new feature using pasted feature as a template. This automatically handles default |
|
|
// values and field constraints |
|
|
newFeatures << QgsVectorLayerUtils::createFeature( pasteVectorLayer, geom, dstAttr, &context ); |
|
|
++featureIt; |
|
|
newFeatures << QgsVectorLayerUtils::createFeature( pasteVectorLayer, geom, attrMap, &context ); |
|
|
} |
|
|
pasteVectorLayer->addFeatures( newFeatures ); |
|
|
QgsFeatureIds newIds; |
|
|