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 )
40 QUrl url = QUrl::fromEncoded( uri.toUtf8() );
42 if ( url.hasQueryItem( QStringLiteral(
"geometry" ) ) )
44 geometry = url.queryItemValue( QStringLiteral(
"geometry" ) );
48 geometry = url.path();
51 if ( geometry.toLower() == QLatin1String(
"none" ) )
60 if ( url.hasQueryItem( QStringLiteral(
"crs" ) ) )
62 QString crsDef = url.queryItemValue( QStringLiteral(
"crs" ) );
63 mCrs.createFromString( crsDef );
68 setNativeTypes( QList< NativeType >()
99 if ( url.hasQueryItem( QStringLiteral(
"field" ) ) )
101 QList<QgsField> attributes;
102 QRegExp reFieldDef(
"\\:" 103 "(int|integer|long|int8|real|double|string|date|time|datetime)" 107 "$", Qt::CaseInsensitive );
108 QStringList fields = url.allQueryItemValues( QStringLiteral(
"field" ) );
109 for (
int i = 0; i < fields.size(); i++ )
111 QString name = fields.at( i );
112 QVariant::Type type = QVariant::String;
113 QVariant::Type subType = QVariant::Invalid;
114 QString typeName( QStringLiteral(
"string" ) );
118 int pos = reFieldDef.indexIn( name );
121 name = name.mid( 0, pos );
122 typeName = reFieldDef.cap( 1 ).toLower();
123 if ( typeName == QLatin1String(
"int" ) || typeName == QLatin1String(
"integer" ) )
125 type = QVariant::Int;
126 typeName = QStringLiteral(
"integer" );
129 else if ( typeName == QLatin1String(
"int8" ) || typeName == QLatin1String(
"long" ) )
131 type = QVariant::LongLong;
132 typeName = QStringLiteral(
"int8" );
135 else if ( typeName == QLatin1String(
"real" ) || typeName == QLatin1String(
"double" ) )
137 type = QVariant::Double;
138 typeName = QStringLiteral(
"double" );
142 else if ( typeName == QLatin1String(
"date" ) )
144 type = QVariant::Date;
145 typeName = QStringLiteral(
"date" );
148 else if ( typeName == QLatin1String(
"time" ) )
150 type = QVariant::Time;
151 typeName = QStringLiteral(
"time" );
154 else if ( typeName == QLatin1String(
"datetime" ) )
156 type = QVariant::DateTime;
157 typeName = QStringLiteral(
"datetime" );
161 if ( !reFieldDef.cap( 2 ).isEmpty() )
163 length = reFieldDef.cap( 2 ).toInt();
165 if ( !reFieldDef.cap( 3 ).isEmpty() )
167 precision = reFieldDef.cap( 3 ).toInt();
169 if ( !reFieldDef.cap( 4 ).isEmpty() )
173 type = ( subType == QVariant::String ? QVariant::StringList : QVariant::List );
176 if ( !name.isEmpty() )
177 attributes.append(
QgsField( name, type, typeName, length, precision, QLatin1String(
"" ), subType ) );
179 addAttributes( attributes );
182 if ( url.hasQueryItem( QStringLiteral(
"index" ) ) && url.queryItemValue( QStringLiteral(
"index" ) ) == QLatin1String(
"yes" ) )
184 createSpatialIndex();
189 QgsMemoryProvider::~QgsMemoryProvider()
191 delete mSpatialIndex;
194 QString QgsMemoryProvider::providerKey()
196 return TEXT_PROVIDER_KEY;
199 QString QgsMemoryProvider::providerDescription()
201 return TEXT_PROVIDER_DESCRIPTION;
204 QgsMemoryProvider *QgsMemoryProvider::createProvider(
const QString &uri )
206 return new QgsMemoryProvider( uri );
211 return new QgsMemoryFeatureSource(
this );
214 QString QgsMemoryProvider::dataSourceUri(
bool expandAuthConfig )
const 216 Q_UNUSED( expandAuthConfig )
218 QUrl uri( QStringLiteral(
"memory" ) );
220 uri.addQueryItem( QStringLiteral(
"geometry" ), geometry );
222 if ( mCrs.isValid() )
224 QString crsDef( QLatin1String(
"" ) );
225 QString authid = mCrs.authid();
226 if ( authid.startsWith( QLatin1String(
"EPSG:" ) ) )
232 int srid = mCrs.postgisSrid();
235 crsDef = QStringLiteral(
"postgis:%1" ).arg( srid );
239 crsDef = QStringLiteral(
"wkt:%1" ).arg( mCrs.toWkt() );
242 uri.addQueryItem( QStringLiteral(
"crs" ), crsDef );
246 uri.addQueryItem( QStringLiteral(
"index" ), QStringLiteral(
"yes" ) );
249 QgsAttributeList attrs =
const_cast<QgsMemoryProvider *
>( this )->attributeIndexes();
250 for (
int i = 0; i < attrs.size(); i++ )
252 QgsField field = mFields.at( attrs[i] );
253 QString fieldDef = field.
name();
254 fieldDef.append( QStringLiteral(
":%2(%3,%4)" ).arg( field.
typeName() ).arg( field.
length() ).arg( field.
precision() ) );
255 uri.addQueryItem( QStringLiteral(
"field" ), fieldDef );
258 return QString( uri.toEncoded() );
262 QString QgsMemoryProvider::storageType()
const 264 return QStringLiteral(
"Memory storage" );
269 return QgsFeatureIterator(
new QgsMemoryFeatureIterator(
new QgsMemoryFeatureSource(
this ),
true, request ) );
275 if ( mExtent.isEmpty() && !mFeatures.isEmpty() )
278 if ( mSubsetString.isEmpty() )
281 Q_FOREACH (
const QgsFeature &feat, mFeatures )
298 else if ( mFeatures.isEmpty() )
300 mExtent.setMinimal();
311 long QgsMemoryProvider::featureCount()
const 313 if ( mSubsetString.isEmpty() )
314 return mFeatures.count();
327 QgsFields QgsMemoryProvider::fields()
const 332 bool QgsMemoryProvider::isValid()
const 344 bool QgsMemoryProvider::addFeatures(
QgsFeatureList &flist, Flags )
348 bool updateExtent = mFeatures.isEmpty() || !mExtent.isEmpty();
350 int fieldCount = mFields.count();
353 for ( QgsFeatureList::iterator it = flist.begin(); it != flist.end(); ++it )
355 it->setId( mNextFeatureId );
356 it->setValid(
true );
357 if ( it->attributes().count() < fieldCount )
362 for (
int i = it->attributes().count(); i < mFields.count(); ++i )
364 attributes.append( QVariant( mFields.at( i ).type() ) );
366 it->setAttributes( attributes );
368 else if ( it->attributes().count() > fieldCount )
371 pushError( tr(
"Feature has too many attributes (expecting %1, received %2)" ).arg( fieldCount ).arg( it->attributes().count() ) );
373 attributes.resize( mFields.count() );
374 it->setAttributes( attributes );
384 pushError( tr(
"Could not add feature with geometry type %1 to layer of type %2" ).arg(
QgsWkbTypes::displayString( it->geometry().wkbType() ),
390 mFeatures.insert( mNextFeatureId, *it );
392 if ( it->hasGeometry() )
395 mExtent.combineExtentWith( it->geometry().boundingBox() );
399 mSpatialIndex->insertFeature( *it );
408 bool QgsMemoryProvider::deleteFeatures(
const QgsFeatureIds &
id )
410 for ( QgsFeatureIds::const_iterator it =
id.begin(); it !=
id.end(); ++it )
412 QgsFeatureMap::iterator fit = mFeatures.find( *it );
415 if ( fit == mFeatures.end() )
420 mSpatialIndex->deleteFeature( *fit );
422 mFeatures.erase( fit );
430 bool QgsMemoryProvider::addAttributes(
const QList<QgsField> &attributes )
432 for ( QList<QgsField>::const_iterator it = attributes.begin(); it != attributes.end(); ++it )
434 switch ( it->type() )
437 case QVariant::Double:
438 case QVariant::String:
441 case QVariant::DateTime:
442 case QVariant::LongLong:
443 case QVariant::StringList:
447 QgsDebugMsg(
"Field type not supported: " + it->typeName() );
451 mFields.append( *it );
453 for ( QgsFeatureMap::iterator fit = mFeatures.begin(); fit != mFeatures.end(); ++fit )
457 attr.append( QVariant() );
464 bool QgsMemoryProvider::renameAttributes(
const QgsFieldNameMap &renamedAttributes )
466 QgsFieldNameMap::const_iterator renameIt = renamedAttributes.constBegin();
468 for ( ; renameIt != renamedAttributes.constEnd(); ++renameIt )
470 int fieldIndex = renameIt.key();
471 if ( fieldIndex < 0 || fieldIndex >= mFields.count() )
476 if ( mFields.indexFromName( renameIt.value() ) >= 0 )
483 mFields[ fieldIndex ].setName( renameIt.value() );
488 bool QgsMemoryProvider::deleteAttributes(
const QgsAttributeIds &attributes )
490 QList<int> attrIdx = attributes.toList();
491 std::sort( attrIdx.begin(), attrIdx.end(), std::greater<int>() );
494 for ( QList<int>::const_iterator it = attrIdx.constBegin(); it != attrIdx.constEnd(); ++it )
497 mFields.remove( idx );
499 for ( QgsFeatureMap::iterator fit = mFeatures.begin(); fit != mFeatures.end(); ++fit )
512 for ( QgsChangedAttributesMap::const_iterator it = attr_map.begin(); it != attr_map.end(); ++it )
514 QgsFeatureMap::iterator fit = mFeatures.find( it.key() );
515 if ( fit == mFeatures.end() )
519 for ( QgsAttributeMap::const_iterator it2 = attrs.constBegin(); it2 != attrs.constEnd(); ++it2 )
520 fit->setAttribute( it2.key(), it2.value() );
525 bool QgsMemoryProvider::changeGeometryValues(
const QgsGeometryMap &geometry_map )
527 for ( QgsGeometryMap::const_iterator it = geometry_map.begin(); it != geometry_map.end(); ++it )
529 QgsFeatureMap::iterator fit = mFeatures.find( it.key() );
530 if ( fit == mFeatures.end() )
535 mSpatialIndex->deleteFeature( *fit );
537 fit->setGeometry( it.value() );
541 mSpatialIndex->insertFeature( *fit );
549 QString QgsMemoryProvider::subsetString()
const 551 return mSubsetString;
554 bool QgsMemoryProvider::setSubsetString(
const QString &theSQL,
bool updateFeatureCount )
556 Q_UNUSED( updateFeatureCount );
558 if ( !theSQL.isEmpty() )
560 QgsExpression tempExpression( theSQL );
561 if ( tempExpression.hasParserError() )
565 mSubsetString = theSQL;
567 mExtent.setMinimal();
573 bool QgsMemoryProvider::createSpatialIndex()
575 if ( !mSpatialIndex )
580 for ( QgsFeatureMap::const_iterator it = mFeatures.constBegin(); it != mFeatures.constEnd(); ++it )
582 mSpatialIndex->insertFeature( *it );
588 QgsVectorDataProvider::Capabilities QgsMemoryProvider::capabilities()
const 590 return AddFeatures | DeleteFeatures | ChangeGeometries |
591 ChangeAttributeValues | AddAttributes | DeleteAttributes | RenameAttributes | CreateSpatialIndex |
592 SelectAtId | CircularGeometries;
596 void QgsMemoryProvider::updateExtents()
598 mExtent.setMinimal();
601 QString QgsMemoryProvider::name()
const 603 return TEXT_PROVIDER_KEY;
606 QString QgsMemoryProvider::description()
const 608 return TEXT_PROVIDER_DESCRIPTION;
Wrapper for iterator of features from vector data provider or vector layer.
QMap< QgsFeatureId, QgsGeometry > QgsGeometryMap
A rectangle specified with double values.
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
QSet< QgsFeatureId > QgsFeatureIds
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...
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.
QgsGeometry geometry() const
Returns the geometry associated with this feature.
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.