@@ -8634,69 +8634,36 @@ void QgisApp::pasteFromClipboard( QgsMapLayer *destinationLayer )
8634
8634
pasteVectorLayer->beginEditCommand( tr( "Features pasted" ) );
8635
8635
QgsFeatureList features = clipboard()->transformedCopyOf( pasteVectorLayer->crs(), pasteVectorLayer->fields() );
8636
8636
int nTotalFeatures = features.count();
8637
-
8638
- QHash<int, int> remap;
8639
- QgsFields fields = clipboard()->fields();
8640
- for ( int idx = 0; idx < fields.count(); ++idx )
8641
- {
8642
- int dst = pasteVectorLayer->fields().lookupField( fields.at( idx ).name() );
8643
- if ( dst < 0 )
8644
- continue;
8645
-
8646
- remap.insert( idx, dst );
8647
- }
8648
-
8649
8637
QgsExpressionContext context = pasteVectorLayer->createExpressionContext();
8650
8638
8651
-
8639
+ QgsFeatureList compatibleFeatures( QgsVectorLayerUtils::makeFeaturesCompatible( features, pasteVectorLayer ) );
8652
8640
QgsFeatureList newFeatures;
8653
- QgsFeatureList::const_iterator featureIt = features.constBegin();
8654
- while ( featureIt != features.constEnd() )
8655
- {
8656
- QgsAttributes srcAttr = featureIt->attributes();
8657
- QgsAttributeMap dstAttr;
8641
+ // Count collapsed geometries
8642
+ int invalidGeometriesCount = 0;
8658
8643
8659
- for ( int src = 0; src < srcAttr.count(); ++src )
8660
- {
8661
- int dst = remap.value( src, -1 );
8662
- if ( dst < 0 )
8663
- continue;
8644
+ for ( const auto &feature : qgis::as_const( compatibleFeatures ) )
8645
+ {
8664
8646
8665
- dstAttr[ dst ] = srcAttr.at( src );
8666
- }
8647
+ QgsGeometry geom = feature.geometry();
8667
8648
8668
- QgsGeometry geom = featureIt->geometry();
8669
- if ( featureIt->hasGeometry() )
8649
+ if ( !( geom.isEmpty() || geom.isNull( ) ) )
8670
8650
{
8671
- // convert geometry to match destination layer
8672
- QgsWkbTypes::GeometryType destType = pasteVectorLayer->geometryType();
8673
- bool destIsMulti = QgsWkbTypes::isMultiType( pasteVectorLayer->wkbType() );
8674
- if ( pasteVectorLayer->dataProvider() &&
8675
- !pasteVectorLayer->dataProvider()->doesStrictFeatureTypeCheck() )
8676
- {
8677
- // force destination to multi if provider doesn't do a feature strict check
8678
- destIsMulti = true;
8679
- }
8680
-
8681
- if ( destType != QgsWkbTypes::UnknownGeometry )
8682
- {
8683
- QgsGeometry newGeometry = geom.convertToType( destType, destIsMulti );
8684
- if ( newGeometry.isNull() )
8685
- {
8686
- continue;
8687
- }
8688
- geom = newGeometry;
8689
- }
8690
8651
// avoid intersection if enabled in digitize settings
8691
8652
geom.avoidIntersections( QgsProject::instance()->avoidIntersectionsLayers() );
8653
+ // Count collapsed geometries
8654
+ if ( geom.isEmpty() || geom.isNull( ) )
8655
+ invalidGeometriesCount++;
8692
8656
}
8693
8657
8658
+ QgsAttributeMap attrMap;
8659
+ for ( int i = 0; i < feature.fields().count(); i++ )
8660
+ {
8661
+ attrMap[i] = feature.attribute( i );
8662
+ }
8694
8663
// now create new feature using pasted feature as a template. This automatically handles default
8695
8664
// values and field constraints
8696
- newFeatures << QgsVectorLayerUtils::createFeature( pasteVectorLayer, geom, dstAttr, &context );
8697
- ++featureIt;
8665
+ newFeatures << QgsVectorLayerUtils::createFeature( pasteVectorLayer, geom, attrMap, &context );
8698
8666
}
8699
-
8700
8667
pasteVectorLayer->addFeatures( newFeatures );
8701
8668
QgsFeatureIds newIds;
8702
8669
for ( const QgsFeature &f : qgis::as_const( newFeatures ) )
@@ -8710,26 +8677,31 @@ void QgisApp::pasteFromClipboard( QgsMapLayer *destinationLayer )
8710
8677
pasteVectorLayer->updateExtents();
8711
8678
8712
8679
int nCopiedFeatures = features.count();
8680
+ Qgis::MessageLevel level = ( nCopiedFeatures == 0 || nCopiedFeatures < nTotalFeatures || invalidGeometriesCount > 0 ) ? Qgis::Warning : Qgis::Info;
8681
+ QString message;
8713
8682
if ( nCopiedFeatures == 0 )
8714
8683
{
8715
- messageBar()->pushMessage( tr( "Paste features" ),
8716
- tr( "no features could be successfully pasted." ),
8717
- Qgis::Warning, messageTimeout() );
8718
-
8684
+ message = tr( "No features could be successfully pasted." );
8719
8685
}
8720
8686
else if ( nCopiedFeatures == nTotalFeatures )
8721
8687
{
8722
- messageBar()->pushMessage( tr( "Paste features" ),
8723
- tr( "%1 features were successfully pasted." ).arg( nCopiedFeatures ),
8724
- Qgis::Info, messageTimeout() );
8688
+ message = tr( "%1 features were successfully pasted." ).arg( nCopiedFeatures );
8725
8689
}
8726
8690
else
8727
8691
{
8728
- messageBar()->pushMessage( tr( "Paste features" ),
8729
- tr( "%1 of %2 features could be successfully pasted." ).arg( nCopiedFeatures ).arg( nTotalFeatures ),
8730
- Qgis::Warning, messageTimeout() );
8692
+ message = tr( "%1 of %2 features could be successfully pasted." ).arg( nCopiedFeatures ).arg( nTotalFeatures );
8731
8693
}
8732
8694
8695
+ // warn the user if the pasted features have invalid geometries
8696
+ if ( invalidGeometriesCount > 0 )
8697
+ message += invalidGeometriesCount == 1 ? tr( " Geometry collapsed due to intersection avoidance." ) :
8698
+ tr( "%1 geometries collapsed due to intersection avoidance." )
8699
+ .arg( invalidGeometriesCount );
8700
+
8701
+ messageBar()->pushMessage( tr( "Paste features" ),
8702
+ message,
8703
+ level, messageTimeout() );
8704
+
8733
8705
pasteVectorLayer->triggerRepaint();
8734
8706
}
8735
8707
0 commit comments