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.toLower() == QLatin1String(
"none" ) )
59 if ( url.hasQueryItem( QStringLiteral(
"crs" ) ) )
61 QString crsDef = url.queryItemValue( QStringLiteral(
"crs" ) );
62 mCrs.createFromString( crsDef );
67 setNativeTypes( QList< NativeType >()
98 if ( url.hasQueryItem( QStringLiteral(
"field" ) ) )
100 QList<QgsField> attributes;
101 QRegExp reFieldDef(
"\\:" 102 "(int|integer|long|int8|real|double|string|date|time|datetime)" 106 "$", Qt::CaseInsensitive );
107 QStringList fields = url.allQueryItemValues( QStringLiteral(
"field" ) );
108 for (
int i = 0; i < fields.size(); i++ )
110 QString name = QUrl::fromPercentEncoding( fields.at( i ).toUtf8() );
111 QVariant::Type type = QVariant::String;
112 QVariant::Type subType = QVariant::Invalid;
113 QString typeName( QStringLiteral(
"string" ) );
117 int pos = reFieldDef.indexIn( name );
120 name = name.mid( 0, pos );
121 typeName = reFieldDef.cap( 1 ).toLower();
122 if ( typeName == QLatin1String(
"int" ) || typeName == QLatin1String(
"integer" ) )
124 type = QVariant::Int;
125 typeName = QStringLiteral(
"integer" );
128 else if ( typeName == QLatin1String(
"int8" ) || typeName == QLatin1String(
"long" ) )
130 type = QVariant::LongLong;
131 typeName = QStringLiteral(
"int8" );
134 else if ( typeName == QLatin1String(
"real" ) || typeName == QLatin1String(
"double" ) )
136 type = QVariant::Double;
137 typeName = QStringLiteral(
"double" );
141 else if ( typeName == QLatin1String(
"date" ) )
143 type = QVariant::Date;
144 typeName = QStringLiteral(
"date" );
147 else if ( typeName == QLatin1String(
"time" ) )
149 type = QVariant::Time;
150 typeName = QStringLiteral(
"time" );
153 else if ( typeName == QLatin1String(
"datetime" ) )
155 type = QVariant::DateTime;
156 typeName = QStringLiteral(
"datetime" );
160 if ( !reFieldDef.cap( 2 ).isEmpty() )
162 length = reFieldDef.cap( 2 ).toInt();
164 if ( !reFieldDef.cap( 3 ).isEmpty() )
166 precision = reFieldDef.cap( 3 ).toInt();
168 if ( !reFieldDef.cap( 4 ).isEmpty() )
172 type = ( subType == QVariant::String ? QVariant::StringList : QVariant::List );
175 if ( !name.isEmpty() )
176 attributes.append(
QgsField( name, type, typeName, length, precision, QLatin1String(
"" ), subType ) );
178 addAttributes( attributes );
181 if ( url.hasQueryItem( QStringLiteral(
"index" ) ) && url.queryItemValue( QStringLiteral(
"index" ) ) == QLatin1String(
"yes" ) )
183 createSpatialIndex();
188 QgsMemoryProvider::~QgsMemoryProvider()
190 delete mSpatialIndex;
193 QString QgsMemoryProvider::providerKey()
195 return TEXT_PROVIDER_KEY;
198 QString QgsMemoryProvider::providerDescription()
200 return TEXT_PROVIDER_DESCRIPTION;
203 QgsMemoryProvider *QgsMemoryProvider::createProvider(
const QString &uri,
const ProviderOptions &options )
205 return new QgsMemoryProvider( uri, options );
210 return new QgsMemoryFeatureSource(
this );
213 QString QgsMemoryProvider::dataSourceUri(
bool expandAuthConfig )
const 215 Q_UNUSED( expandAuthConfig )
217 QUrl uri( QStringLiteral(
"memory" ) );
219 uri.addQueryItem( QStringLiteral(
"geometry" ), geometry );
221 if ( mCrs.isValid() )
223 QString crsDef( QLatin1String(
"" ) );
224 QString authid = mCrs.authid();
225 if ( authid.startsWith( QLatin1String(
"EPSG:" ) ) )
231 int srid = mCrs.postgisSrid();
234 crsDef = QStringLiteral(
"postgis:%1" ).arg( srid );
238 crsDef = QStringLiteral(
"wkt:%1" ).arg( mCrs.toWkt() );
241 uri.addQueryItem( QStringLiteral(
"crs" ), crsDef );
245 uri.addQueryItem( QStringLiteral(
"index" ), QStringLiteral(
"yes" ) );
248 QgsAttributeList attrs =
const_cast<QgsMemoryProvider *
>( this )->attributeIndexes();
249 for (
int i = 0; i < attrs.size(); i++ )
251 QgsField field = mFields.at( attrs[i] );
252 QString fieldDef = field.
name();
253 fieldDef.append( QStringLiteral(
":%2(%3,%4)" ).arg( field.
typeName() ).arg( field.
length() ).arg( field.
precision() ) );
254 uri.addQueryItem( QStringLiteral(
"field" ), fieldDef );
257 return QString( uri.toEncoded() );
261 QString QgsMemoryProvider::storageType()
const 263 return QStringLiteral(
"Memory storage" );
268 return QgsFeatureIterator(
new QgsMemoryFeatureIterator(
new QgsMemoryFeatureSource(
this ),
true, request ) );
274 if ( mExtent.isEmpty() && !mFeatures.isEmpty() )
277 if ( mSubsetString.isEmpty() )
280 Q_FOREACH (
const QgsFeature &feat, mFeatures )
297 else if ( mFeatures.isEmpty() )
299 mExtent.setMinimal();
310 long QgsMemoryProvider::featureCount()
const 312 if ( mSubsetString.isEmpty() )
313 return mFeatures.count();
326 QgsFields QgsMemoryProvider::fields()
const 331 bool QgsMemoryProvider::isValid()
const 343 bool QgsMemoryProvider::addFeatures(
QgsFeatureList &flist, Flags )
347 bool updateExtent = mFeatures.isEmpty() || !mExtent.isEmpty();
349 int fieldCount = mFields.count();
352 for ( QgsFeatureList::iterator it = flist.begin(); it != flist.end(); ++it )
354 it->setId( mNextFeatureId );
355 it->setValid(
true );
356 if ( it->attributes().count() < fieldCount )
361 for (
int i = it->attributes().count(); i < mFields.count(); ++i )
363 attributes.append( QVariant( mFields.at( i ).type() ) );
365 it->setAttributes( attributes );
367 else if ( it->attributes().count() > fieldCount )
370 pushError( tr(
"Feature has too many attributes (expecting %1, received %2)" ).arg( fieldCount ).arg( it->attributes().count() ) );
372 attributes.resize( mFields.count() );
373 it->setAttributes( attributes );
383 pushError( tr(
"Could not add feature with geometry type %1 to layer of type %2" ).arg(
QgsWkbTypes::displayString( it->geometry().wkbType() ),
389 mFeatures.insert( mNextFeatureId, *it );
391 if ( it->hasGeometry() )
394 mExtent.combineExtentWith( it->geometry().boundingBox() );
398 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 );
431 bool QgsMemoryProvider::addAttributes(
const QList<QgsField> &attributes )
433 for ( QList<QgsField>::const_iterator it = attributes.begin(); it != attributes.end(); ++it )
435 switch ( it->type() )
438 case QVariant::Double:
439 case QVariant::String:
442 case QVariant::DateTime:
443 case QVariant::LongLong:
444 case QVariant::StringList:
448 QgsDebugMsg(
"Field type not supported: " + it->typeName() );
452 mFields.append( *it );
454 for ( QgsFeatureMap::iterator fit = mFeatures.begin(); fit != mFeatures.end(); ++fit )
458 attr.append( QVariant() );
465 bool QgsMemoryProvider::renameAttributes(
const QgsFieldNameMap &renamedAttributes )
467 QgsFieldNameMap::const_iterator renameIt = renamedAttributes.constBegin();
469 for ( ; renameIt != renamedAttributes.constEnd(); ++renameIt )
471 int fieldIndex = renameIt.key();
472 if ( fieldIndex < 0 || fieldIndex >= mFields.count() )
477 if ( mFields.indexFromName( renameIt.value() ) >= 0 )
484 mFields[ fieldIndex ].setName( renameIt.value() );
489 bool QgsMemoryProvider::deleteAttributes(
const QgsAttributeIds &attributes )
491 QList<int> attrIdx = attributes.toList();
492 std::sort( attrIdx.begin(), attrIdx.end(), std::greater<int>() );
495 for ( QList<int>::const_iterator it = attrIdx.constBegin(); it != attrIdx.constEnd(); ++it )
498 mFields.remove( idx );
500 for ( QgsFeatureMap::iterator fit = mFeatures.begin(); fit != mFeatures.end(); ++fit )
514 for ( QgsChangedAttributesMap::const_iterator it = attr_map.begin(); it != attr_map.end(); ++it )
516 QgsFeatureMap::iterator fit = mFeatures.find( it.key() );
517 if ( fit == mFeatures.end() )
521 for ( QgsAttributeMap::const_iterator it2 = attrs.constBegin(); it2 != attrs.constEnd(); ++it2 )
522 fit->setAttribute( it2.key(), it2.value() );
528 bool QgsMemoryProvider::changeGeometryValues(
const QgsGeometryMap &geometry_map )
530 for ( QgsGeometryMap::const_iterator it = geometry_map.begin(); it != geometry_map.end(); ++it )
532 QgsFeatureMap::iterator fit = mFeatures.find( it.key() );
533 if ( fit == mFeatures.end() )
538 mSpatialIndex->deleteFeature( *fit );
540 fit->setGeometry( it.value() );
544 mSpatialIndex->insertFeature( *fit );
552 QString QgsMemoryProvider::subsetString()
const 554 return mSubsetString;
557 bool QgsMemoryProvider::setSubsetString(
const QString &theSQL,
bool updateFeatureCount )
559 Q_UNUSED( updateFeatureCount );
561 if ( !theSQL.isEmpty() )
564 if ( tempExpression.hasParserError() )
568 if ( theSQL == mSubsetString )
571 mSubsetString = theSQL;
573 mExtent.setMinimal();
579 bool QgsMemoryProvider::createSpatialIndex()
581 if ( !mSpatialIndex )
586 for ( QgsFeatureMap::const_iterator it = mFeatures.constBegin(); it != mFeatures.constEnd(); ++it )
588 mSpatialIndex->insertFeature( *it );
594 QgsVectorDataProvider::Capabilities QgsMemoryProvider::capabilities()
const 596 return AddFeatures | DeleteFeatures | ChangeGeometries |
597 ChangeAttributeValues | AddAttributes | DeleteAttributes | RenameAttributes | CreateSpatialIndex |
598 SelectAtId | CircularGeometries;
602 void QgsMemoryProvider::updateExtents()
604 mExtent.setMinimal();
607 QString QgsMemoryProvider::name()
const 609 return TEXT_PROVIDER_KEY;
612 QString QgsMemoryProvider::description()
const 614 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.
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.