Skip to content

Commit

Permalink
Merge pull request #9203 from elpaso/bugfix-21305-paste-slow-no-provider
Browse files Browse the repository at this point in the history
Cache unique values when creating features
  • Loading branch information
elpaso committed Feb 21, 2019
2 parents 4d5dad8 + 4250ef2 commit 17280c3
Show file tree
Hide file tree
Showing 10 changed files with 442 additions and 77 deletions.
58 changes: 58 additions & 0 deletions python/core/auto_generated/qgsvectorlayerutils.sip.in
Expand Up @@ -57,6 +57,40 @@ Returns the duplicated features in the given layer


}; };


class QgsFeatureData
{
%Docstring
Encapsulate geometry and attributes for new features, to be passed to createFeatures

.. seealso:: :py:func:`createFeatures`

.. versionadded:: 3.6
%End

%TypeHeaderCode
#include "qgsvectorlayerutils.h"
%End
public:

QgsFeatureData( const QgsGeometry &geometry = QgsGeometry(), const QgsAttributeMap &attributes = QgsAttributeMap() );
%Docstring
Constructs a new QgsFeatureData with given ``geometry`` and ``attributes``
%End

QgsGeometry geometry() const;
%Docstring
Returns geometry
%End

QgsAttributeMap attributes() const;
%Docstring
Returns attributes
%End

};

typedef QList<QgsVectorLayerUtils::QgsFeatureData> QgsFeaturesDataList;

static QgsFeatureIterator getValuesIterator( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly ); static QgsFeatureIterator getValuesIterator( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly );
%Docstring %Docstring
Create a feature iterator for a specified field name or expression. Create a feature iterator for a specified field name or expression.
Expand Down Expand Up @@ -122,6 +156,15 @@ Returns a new attribute value for the specified field index which is guaranteed
value can be used as a basis for generated values. value can be used as a basis for generated values.


.. seealso:: :py:func:`valueExists` .. seealso:: :py:func:`valueExists`
%End

static QVariant createUniqueValueFromCache( const QgsVectorLayer *layer, int fieldIndex, const QSet<QVariant> &existingValues, const QVariant &seed = QVariant() );
%Docstring
Returns a new attribute value for the specified field index which is guaranteed to
be unique within regard to ``existingValues``.
The optional seed value can be used as a basis for generated values.

.. versionadded:: 3.6
%End %End


static bool validateAttribute( const QgsVectorLayer *layer, const QgsFeature &feature, int attributeIndex, QStringList &errors /Out/, static bool validateAttribute( const QgsVectorLayer *layer, const QgsFeature &feature, int attributeIndex, QStringList &errors /Out/,
Expand All @@ -143,6 +186,21 @@ Creates a new feature ready for insertion into a layer. Default values and const
passed for the new feature to copy as many attribute values as possible from the map, passed for the new feature to copy as many attribute values as possible from the map,
assuming that they respect the layer's constraints. Note that the created feature is not assuming that they respect the layer's constraints. Note that the created feature is not
automatically inserted into the layer. automatically inserted into the layer.

.. seealso:: :py:func:`createFeatures`
%End

static QgsFeatureList createFeatures( const QgsVectorLayer *layer,
const QgsFeaturesDataList &featuresData,
QgsExpressionContext *context = 0 );
%Docstring
Creates a set of new features ready for insertion into a layer. Default values and constraints
(e.g., unique constraints) will automatically be handled. Note that the created features are not
automatically inserted into the layer.

.. seealso:: :py:func:`createFeature`

.. versionadded:: 3.6
%End %End


static QgsFeature duplicateFeature( QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, int depth, QgsDuplicateFeatureContext &duplicateFeatureContext /Out/ ); static QgsFeature duplicateFeature( QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, int depth, QgsDuplicateFeatureContext &duplicateFeatureContext /Out/ );
Expand Down
14 changes: 8 additions & 6 deletions src/app/qgisapp.cpp
Expand Up @@ -8996,11 +8996,12 @@ void QgisApp::pasteFromClipboard( QgsMapLayer *destinationLayer )
QgsExpressionContext context = pasteVectorLayer->createExpressionContext(); QgsExpressionContext context = pasteVectorLayer->createExpressionContext();


QgsFeatureList compatibleFeatures( QgsVectorLayerUtils::makeFeaturesCompatible( features, pasteVectorLayer ) ); QgsFeatureList compatibleFeatures( QgsVectorLayerUtils::makeFeaturesCompatible( features, pasteVectorLayer ) );
QgsFeatureList newFeatures; QgsVectorLayerUtils::QgsFeaturesDataList newFeaturesDataList;
newFeaturesDataList.reserve( compatibleFeatures.size() );

// Count collapsed geometries // Count collapsed geometries
int invalidGeometriesCount = 0; int invalidGeometriesCount = 0;


newFeatures.reserve( compatibleFeatures.size() );
for ( const auto &feature : qgis::as_const( compatibleFeatures ) ) for ( const auto &feature : qgis::as_const( compatibleFeatures ) )
{ {


Expand All @@ -9020,10 +9021,12 @@ void QgisApp::pasteFromClipboard( QgsMapLayer *destinationLayer )
{ {
attrMap[i] = feature.attribute( i ); attrMap[i] = feature.attribute( i );
} }
// now create new feature using pasted feature as a template. This automatically handles default newFeaturesDataList << QgsVectorLayerUtils::QgsFeatureData( geom, attrMap );
// values and field constraints
newFeatures << QgsVectorLayerUtils::createFeature( pasteVectorLayer, geom, attrMap, &context );
} }

// now create new feature using pasted feature as a template. This automatically handles default
// values and field constraints
QgsFeatureList newFeatures {QgsVectorLayerUtils::createFeatures( pasteVectorLayer, newFeaturesDataList, &context )};
pasteVectorLayer->addFeatures( newFeatures ); pasteVectorLayer->addFeatures( newFeatures );
QgsFeatureIds newIds; QgsFeatureIds newIds;
newIds.reserve( newFeatures.size() ); newIds.reserve( newFeatures.size() );
Expand All @@ -9032,7 +9035,6 @@ void QgisApp::pasteFromClipboard( QgsMapLayer *destinationLayer )
newIds << f.id(); newIds << f.id();
} }



pasteVectorLayer->selectByIds( newIds ); pasteVectorLayer->selectByIds( newIds );
pasteVectorLayer->endEditCommand(); pasteVectorLayer->endEditCommand();
pasteVectorLayer->updateExtents(); pasteVectorLayer->updateExtents();
Expand Down
2 changes: 1 addition & 1 deletion src/app/qgsattributesformproperties.cpp
Expand Up @@ -277,7 +277,7 @@ void QgsAttributesFormProperties::loadAttributeTypeDialog()


void QgsAttributesFormProperties::storeAttributeTypeDialog() void QgsAttributesFormProperties::storeAttributeTypeDialog()
{ {
if ( mAttributeTypeDialog->fieldIdx() < 0 ) if ( mAttributeTypeDialog->fieldIdx() < 0 || mAttributeTypeDialog->fieldIdx() >= mLayer->fields().count() )
return; return;


FieldConfig cfg; FieldConfig cfg;
Expand Down

0 comments on commit 17280c3

Please sign in to comment.