31 static const QString TEXT_PROVIDER_KEY = QStringLiteral(
"memory" );
32 static const QString TEXT_PROVIDER_DESCRIPTION = QStringLiteral(
"Memory provider" );
34 QgsMemoryProvider::QgsMemoryProvider(
const QString &uri,
const ProviderOptions &options )
39 QUrl url = QUrl::fromEncoded( uri.toUtf8() );
41 if ( url.hasQueryItem( QStringLiteral(
"geometry" ) ) )
43 geometry = url.queryItemValue( QStringLiteral(
"geometry" ) );
47 geometry = url.path();
50 if ( geometry.compare( QLatin1String(
"none" ), Qt::CaseInsensitive ) == 0 )
59 if ( url.hasQueryItem( QStringLiteral(
"crs" ) ) )
61 QString crsDef = url.queryItemValue( QStringLiteral(
"crs" ) );
62 mCrs.createFromString( crsDef );
73 setNativeTypes( QList< NativeType >()
111 if ( url.hasQueryItem( QStringLiteral(
"field" ) ) )
113 QList<QgsField> attributes;
114 QRegExp reFieldDef(
"\\:" 115 "(int|integer|long|int8|real|double|string|date|time|datetime|binary|bool|boolean)" 119 "$", Qt::CaseInsensitive );
120 QStringList fields = url.allQueryItemValues( QStringLiteral(
"field" ) );
121 for (
int i = 0; i < fields.size(); i++ )
123 QString name = QUrl::fromPercentEncoding( fields.at( i ).toUtf8() );
124 QVariant::Type type = QVariant::String;
125 QVariant::Type subType = QVariant::Invalid;
126 QString
typeName( QStringLiteral(
"string" ) );
130 int pos = reFieldDef.indexIn( name );
133 name = name.mid( 0, pos );
134 typeName = reFieldDef.cap( 1 ).toLower();
135 if (
typeName == QLatin1String(
"int" ) ||
typeName == QLatin1String(
"integer" ) )
137 type = QVariant::Int;
138 typeName = QStringLiteral(
"integer" );
141 else if (
typeName == QLatin1String(
"int8" ) ||
typeName == QLatin1String(
"long" ) )
143 type = QVariant::LongLong;
144 typeName = QStringLiteral(
"int8" );
147 else if (
typeName == QLatin1String(
"real" ) ||
typeName == QLatin1String(
"double" ) )
149 type = QVariant::Double;
150 typeName = QStringLiteral(
"double" );
154 else if (
typeName == QLatin1String(
"date" ) )
156 type = QVariant::Date;
157 typeName = QStringLiteral(
"date" );
160 else if (
typeName == QLatin1String(
"time" ) )
162 type = QVariant::Time;
163 typeName = QStringLiteral(
"time" );
166 else if (
typeName == QLatin1String(
"datetime" ) )
168 type = QVariant::DateTime;
169 typeName = QStringLiteral(
"datetime" );
172 else if (
typeName == QLatin1String(
"bool" ) ||
typeName == QLatin1String(
"boolean" ) )
174 type = QVariant::Bool;
175 typeName = QStringLiteral(
"boolean" );
178 else if (
typeName == QLatin1String(
"binary" ) )
180 type = QVariant::ByteArray;
181 typeName = QStringLiteral(
"binary" );
185 if ( !reFieldDef.cap( 2 ).isEmpty() )
187 length = reFieldDef.cap( 2 ).toInt();
189 if ( !reFieldDef.cap( 3 ).isEmpty() )
191 precision = reFieldDef.cap( 3 ).toInt();
193 if ( !reFieldDef.cap( 4 ).isEmpty() )
197 type = ( subType == QVariant::String ? QVariant::StringList : QVariant::List );
200 if ( !name.isEmpty() )
201 attributes.append(
QgsField( name, type,
typeName, length, precision, QString(), subType ) );
203 addAttributes( attributes );
206 if ( url.hasQueryItem( QStringLiteral(
"index" ) ) && url.queryItemValue( QStringLiteral(
"index" ) ) == QLatin1String(
"yes" ) )
208 createSpatialIndex();
213 QgsMemoryProvider::~QgsMemoryProvider()
215 delete mSpatialIndex;
218 QString QgsMemoryProvider::providerKey()
220 return TEXT_PROVIDER_KEY;
223 QString QgsMemoryProvider::providerDescription()
225 return TEXT_PROVIDER_DESCRIPTION;
228 QgsMemoryProvider *QgsMemoryProvider::createProvider(
const QString &uri,
const ProviderOptions &options )
230 return new QgsMemoryProvider( uri, options );
235 return new QgsMemoryFeatureSource(
this );
238 QString QgsMemoryProvider::dataSourceUri(
bool expandAuthConfig )
const 240 Q_UNUSED( expandAuthConfig )
242 QUrl uri( QStringLiteral(
"memory" ) );
244 uri.addQueryItem( QStringLiteral(
"geometry" ), geometry );
246 if ( mCrs.isValid() )
249 QString authid = mCrs.authid();
250 if ( authid.startsWith( QLatin1String(
"EPSG:" ) ) )
256 int srid = mCrs.postgisSrid();
259 crsDef = QStringLiteral(
"postgis:%1" ).arg( srid );
263 crsDef = QStringLiteral(
"wkt:%1" ).arg( mCrs.toWkt() );
266 uri.addQueryItem( QStringLiteral(
"crs" ), crsDef );
270 uri.addQueryItem( QStringLiteral(
"index" ), QStringLiteral(
"yes" ) );
274 for (
int i = 0; i < attrs.size(); i++ )
276 QgsField field = mFields.at( attrs[i] );
277 QString fieldDef = field.
name();
278 fieldDef.append( QStringLiteral(
":%2(%3,%4)" ).arg( field.
typeName() ).arg( field.
length() ).arg( field.
precision() ) );
279 uri.addQueryItem( QStringLiteral(
"field" ), fieldDef );
282 return QString( uri.toEncoded() );
286 QString QgsMemoryProvider::storageType()
const 288 return QStringLiteral(
"Memory storage" );
293 return QgsFeatureIterator(
new QgsMemoryFeatureIterator(
new QgsMemoryFeatureSource(
this ),
true, request ) );
299 if ( mExtent.isEmpty() && !mFeatures.isEmpty() )
302 if ( mSubsetString.isEmpty() )
305 const auto constMFeatures = mFeatures;
306 for (
const QgsFeature &feat : constMFeatures )
308 if ( feat.hasGeometry() )
309 mExtent.combineExtentWith( feat.geometry().boundingBox() );
323 else if ( mFeatures.isEmpty() )
325 mExtent.setMinimal();
336 long QgsMemoryProvider::featureCount()
const 338 if ( mSubsetString.isEmpty() )
339 return mFeatures.count();
352 QgsFields QgsMemoryProvider::fields()
const 357 bool QgsMemoryProvider::isValid()
const 370 if ( QgsMemoryProvider *other = qobject_cast< QgsMemoryProvider * >( source ) )
373 mFeatures = other->mFeatures;
374 mNextFeatureId = other->mNextFeatureId;
375 mExtent = other->mExtent;
380 bool QgsMemoryProvider::addFeatures(
QgsFeatureList &flist, Flags )
384 bool updateExtent = mFeatures.isEmpty() || !mExtent.isEmpty();
386 int fieldCount = mFields.count();
389 for ( QgsFeatureList::iterator it = flist.begin(); it != flist.end(); ++it )
391 it->setId( mNextFeatureId );
392 it->setValid(
true );
393 if ( it->attributes().count() < fieldCount )
398 for (
int i = it->attributes().count(); i < mFields.count(); ++i )
400 attributes.append( QVariant( mFields.at( i ).type() ) );
402 it->setAttributes( attributes );
404 else if ( it->attributes().count() > fieldCount )
407 pushError( tr(
"Feature has too many attributes (expecting %1, received %2)" ).arg( fieldCount ).arg( it->attributes().count() ) );
409 attributes.resize( mFields.count() );
410 it->setAttributes( attributes );
420 pushError( tr(
"Could not add feature with geometry type %1 to layer of type %2" ).arg(
QgsWkbTypes::displayString( it->geometry().wkbType() ),
426 mFeatures.insert( mNextFeatureId, *it );
428 if ( it->hasGeometry() )
431 mExtent.combineExtentWith( it->geometry().boundingBox() );
435 mSpatialIndex->addFeature( *it );
445 bool QgsMemoryProvider::deleteFeatures(
const QgsFeatureIds &
id )
447 for ( QgsFeatureIds::const_iterator it =
id.begin(); it !=
id.end(); ++it )
449 QgsFeatureMap::iterator fit = mFeatures.find( *it );
452 if ( fit == mFeatures.end() )
457 mSpatialIndex->deleteFeature( *fit );
459 mFeatures.erase( fit );
468 bool QgsMemoryProvider::addAttributes(
const QList<QgsField> &attributes )
470 for ( QList<QgsField>::const_iterator it = attributes.begin(); it != attributes.end(); ++it )
472 switch ( it->type() )
475 case QVariant::Double:
476 case QVariant::String:
479 case QVariant::DateTime:
480 case QVariant::LongLong:
481 case QVariant::StringList:
484 case QVariant::ByteArray:
487 QgsDebugMsg(
"Field type not supported: " + it->typeName() );
491 mFields.append( *it );
493 for ( QgsFeatureMap::iterator fit = mFeatures.begin(); fit != mFeatures.end(); ++fit )
497 attr.append( QVariant() );
504 bool QgsMemoryProvider::renameAttributes(
const QgsFieldNameMap &renamedAttributes )
506 QgsFieldNameMap::const_iterator renameIt = renamedAttributes.constBegin();
508 for ( ; renameIt != renamedAttributes.constEnd(); ++renameIt )
510 int fieldIndex = renameIt.key();
511 if ( fieldIndex < 0 || fieldIndex >= mFields.count() )
516 if ( mFields.indexFromName( renameIt.value() ) >= 0 )
523 mFields[ fieldIndex ].setName( renameIt.value() );
528 bool QgsMemoryProvider::deleteAttributes(
const QgsAttributeIds &attributes )
530 QList<int> attrIdx = attributes.toList();
531 std::sort( attrIdx.begin(), attrIdx.end(), std::greater<int>() );
534 for ( QList<int>::const_iterator it = attrIdx.constBegin(); it != attrIdx.constEnd(); ++it )
537 mFields.remove( idx );
539 for ( QgsFeatureMap::iterator fit = mFeatures.begin(); fit != mFeatures.end(); ++fit )
553 for ( QgsChangedAttributesMap::const_iterator it = attr_map.begin(); it != attr_map.end(); ++it )
555 QgsFeatureMap::iterator fit = mFeatures.find( it.key() );
556 if ( fit == mFeatures.end() )
560 for ( QgsAttributeMap::const_iterator it2 = attrs.constBegin(); it2 != attrs.constEnd(); ++it2 )
561 fit->setAttribute( it2.key(), it2.value() );
567 bool QgsMemoryProvider::changeGeometryValues(
const QgsGeometryMap &geometry_map )
569 for ( QgsGeometryMap::const_iterator it = geometry_map.begin(); it != geometry_map.end(); ++it )
571 QgsFeatureMap::iterator fit = mFeatures.find( it.key() );
572 if ( fit == mFeatures.end() )
577 mSpatialIndex->deleteFeature( *fit );
579 fit->setGeometry( it.value() );
583 mSpatialIndex->addFeature( *fit );
591 QString QgsMemoryProvider::subsetString()
const 593 return mSubsetString;
596 bool QgsMemoryProvider::setSubsetString(
const QString &theSQL,
bool updateFeatureCount )
598 Q_UNUSED( updateFeatureCount )
600 if ( !theSQL.isEmpty() )
603 if ( tempExpression.hasParserError() )
607 if ( theSQL == mSubsetString )
610 mSubsetString = theSQL;
612 mExtent.setMinimal();
618 bool QgsMemoryProvider::createSpatialIndex()
620 if ( !mSpatialIndex )
625 for ( QgsFeatureMap::iterator it = mFeatures.begin(); it != mFeatures.end(); ++it )
627 mSpatialIndex->addFeature( *it );
633 QgsVectorDataProvider::Capabilities QgsMemoryProvider::capabilities()
const 635 return AddFeatures | DeleteFeatures | ChangeGeometries |
636 ChangeAttributeValues | AddAttributes | DeleteAttributes | RenameAttributes | CreateSpatialIndex |
637 SelectAtId | CircularGeometries | FastTruncate;
640 bool QgsMemoryProvider::truncate()
644 mExtent.setMinimal();
648 void QgsMemoryProvider::updateExtents()
650 mExtent.setMinimal();
653 QString QgsMemoryProvider::name()
const 655 return TEXT_PROVIDER_KEY;
658 QString QgsMemoryProvider::description()
const 660 return TEXT_PROVIDER_DESCRIPTION;
Class for parsing and evaluation of expressions (formerly called "search strings").
Wrapper for iterator of features from vector data provider or vector layer.
QMap< QgsFeatureId, QgsGeometry > QgsGeometryMap
A rectangle specified with double values.
QSet< QgsFeatureId > QgsFeatureIds
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
QList< QgsFeature > QgsFeatureList
Container of fields for a vector layer.
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
static Type parseType(const QString &wktStr)
Attempts to extract the WKB type from a WKT string.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
const QgsCoordinateReferenceSystem & crs
const QgsAttributeList & attributeIndexes
bool hasGeometry() const
Returns true if the feature has an associated geometry.
QSet< int > QgsAttributeIds
Type
The WKB type describes the number of dimensions a geometry has.
QString typeName() const
Gets the field type.
QMap< int, QVariant > QgsAttributeMap
static GeometryType geometryType(Type type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
This class wraps a request for features to a vector layer (or directly its vector data provider)...
Encapsulate a field in an attribute table or data source.
Base class that can be used for any class that is capable of returning features.
QMap< int, QString > QgsFieldNameMap
A spatial index for QgsFeature objects.
QMap< QgsFeatureId, QgsAttributeMap > QgsChangedAttributesMap
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
This class represents a coordinate reference system (CRS).
static QString displayString(Type type)
Returns a display string type for a WKB type, e.g., the geometry name used in WKT geometry representa...
QList< int > QgsAttributeList
bool nextFeature(QgsFeature &f)
This is the base class for vector data providers.