32 #define TEXT_PROVIDER_KEY QStringLiteral( "memory" )    33 #define TEXT_PROVIDER_DESCRIPTION QStringLiteral( "Memory provider" )    35 QgsMemoryProvider::QgsMemoryProvider( 
const QString &uri, 
const ProviderOptions &options )
    40   QUrl url = QUrl::fromEncoded( uri.toUtf8() );
    41   const QUrlQuery query( url );
    43   if ( query.hasQueryItem( QStringLiteral( 
"geometry" ) ) )
    45     geometry = query.queryItemValue( QStringLiteral( 
"geometry" ) );
    49     geometry = url.path();
    52   if ( geometry.compare( QLatin1String( 
"none" ), Qt::CaseInsensitive ) == 0 )
    61   if ( query.hasQueryItem( QStringLiteral( 
"crs" ) ) )
    63     QString crsDef = query.queryItemValue( QStringLiteral( 
"crs" ) );
    64     mCrs.createFromString( crsDef );
    75   setNativeTypes( QList< NativeType >()
   113   if ( query.hasQueryItem( QStringLiteral( 
"field" ) ) )
   115     QList<QgsField> attributes;
   116     QRegExp reFieldDef( 
"\\:"   117                         "(int|integer|long|int8|real|double|string|date|time|datetime|binary|bool|boolean)"    121                         "$", Qt::CaseInsensitive );
   122     QStringList fields = query.allQueryItemValues( QStringLiteral( 
"field" ) );
   123     for ( 
int i = 0; i < fields.size(); i++ )
   125       QString name = QUrl::fromPercentEncoding( fields.at( i ).toUtf8() );
   126       QVariant::Type type = QVariant::String;
   127       QVariant::Type subType = QVariant::Invalid;
   128       QString 
typeName( QStringLiteral( 
"string" ) );
   132       int pos = reFieldDef.indexIn( name );
   135         name = name.mid( 0, pos );
   136         typeName = reFieldDef.cap( 1 ).toLower();
   137         if ( 
typeName == QLatin1String( 
"int" ) || 
typeName == QLatin1String( 
"integer" ) )
   139           type = QVariant::Int;
   140           typeName = QStringLiteral( 
"integer" );
   143         else if ( 
typeName == QLatin1String( 
"int8" ) || 
typeName == QLatin1String( 
"long" ) )
   145           type = QVariant::LongLong;
   146           typeName = QStringLiteral( 
"int8" );
   149         else if ( 
typeName == QLatin1String( 
"real" ) || 
typeName == QLatin1String( 
"double" ) )
   151           type = QVariant::Double;
   152           typeName = QStringLiteral( 
"double" );
   156         else if ( 
typeName == QLatin1String( 
"date" ) )
   158           type = QVariant::Date;
   159           typeName = QStringLiteral( 
"date" );
   162         else if ( 
typeName == QLatin1String( 
"time" ) )
   164           type = QVariant::Time;
   165           typeName = QStringLiteral( 
"time" );
   168         else if ( 
typeName == QLatin1String( 
"datetime" ) )
   170           type = QVariant::DateTime;
   171           typeName = QStringLiteral( 
"datetime" );
   174         else if ( 
typeName == QLatin1String( 
"bool" ) || 
typeName == QLatin1String( 
"boolean" ) )
   176           type = QVariant::Bool;
   177           typeName = QStringLiteral( 
"boolean" );
   180         else if ( 
typeName == QLatin1String( 
"binary" ) )
   182           type = QVariant::ByteArray;
   183           typeName = QStringLiteral( 
"binary" );
   187         if ( !reFieldDef.cap( 2 ).isEmpty() )
   189           length = reFieldDef.cap( 2 ).toInt();
   191         if ( !reFieldDef.cap( 3 ).isEmpty() )
   193           precision = reFieldDef.cap( 3 ).toInt();
   195         if ( !reFieldDef.cap( 4 ).isEmpty() )
   199           type = ( subType == QVariant::String ? QVariant::StringList : QVariant::List );
   202       if ( !name.isEmpty() )
   203         attributes.append( 
QgsField( name, type, 
typeName, length, precision, QString(), subType ) );
   205     addAttributes( attributes );
   208   if ( query.hasQueryItem( QStringLiteral( 
"index" ) ) && query.queryItemValue( QStringLiteral( 
"index" ) ) == QLatin1String( 
"yes" ) )
   210     createSpatialIndex();
   215 QgsMemoryProvider::~QgsMemoryProvider()
   217   delete mSpatialIndex;
   220 QString QgsMemoryProvider::providerKey()
   222   return TEXT_PROVIDER_KEY;
   225 QString QgsMemoryProvider::providerDescription()
   227   return TEXT_PROVIDER_DESCRIPTION;
   230 QgsMemoryProvider *QgsMemoryProvider::createProvider( 
const QString &uri, 
const ProviderOptions &options )
   232   return new QgsMemoryProvider( uri, options );
   237   return new QgsMemoryFeatureSource( 
this );
   240 QString QgsMemoryProvider::dataSourceUri( 
bool expandAuthConfig )
 const   242   Q_UNUSED( expandAuthConfig )
   244   QUrl uri( QStringLiteral( 
"memory" ) );
   247   query.addQueryItem( QStringLiteral( 
"geometry" ), geometry );
   249   if ( mCrs.isValid() )
   252     QString authid = mCrs.authid();
   253     if ( authid.startsWith( QLatin1String( 
"EPSG:" ) ) )
   261     query.addQueryItem( QStringLiteral( 
"crs" ), crsDef );
   265     query.addQueryItem( QStringLiteral( 
"index" ), QStringLiteral( 
"yes" ) );
   269   for ( 
int i = 0; i < attrs.size(); i++ )
   271     QgsField field = mFields.at( attrs[i] );
   272     QString fieldDef = field.
name();
   273     fieldDef.append( QStringLiteral( 
":%2(%3,%4)" ).arg( field.
typeName() ).arg( field.
length() ).arg( field.
precision() ) );
   274     query.addQueryItem( QStringLiteral( 
"field" ), fieldDef );
   276   uri.setQuery( query );
   278   return QString( uri.toEncoded() );
   282 QString QgsMemoryProvider::storageType()
 const   284   return QStringLiteral( 
"Memory storage" );
   289   return QgsFeatureIterator( 
new QgsMemoryFeatureIterator( 
new QgsMemoryFeatureSource( 
this ), 
true, request ) );
   295   if ( mExtent.isEmpty() && !mFeatures.isEmpty() )
   298     if ( mSubsetString.isEmpty() )
   301       const auto constMFeatures = mFeatures;
   302       for ( 
const QgsFeature &feat : constMFeatures )
   304         if ( feat.hasGeometry() )
   305           mExtent.combineExtentWith( feat.geometry().boundingBox() );
   319   else if ( mFeatures.isEmpty() )
   321     mExtent.setMinimal();
   332 long QgsMemoryProvider::featureCount()
 const   334   if ( mSubsetString.isEmpty() )
   335     return mFeatures.count();
   348 QgsFields QgsMemoryProvider::fields()
 const   353 bool QgsMemoryProvider::isValid()
 const   366   if ( QgsMemoryProvider *other = qobject_cast< QgsMemoryProvider * >( source ) )
   369     mFeatures = other->mFeatures;
   370     mNextFeatureId = other->mNextFeatureId;
   371     mExtent = other->mExtent;
   376 bool QgsMemoryProvider::addFeatures( 
QgsFeatureList &flist, Flags )
   380   bool updateExtent = mFeatures.isEmpty() || !mExtent.isEmpty();
   382   int fieldCount = mFields.count();
   385   for ( QgsFeatureList::iterator it = flist.begin(); it != flist.end(); ++it )
   387     it->setId( mNextFeatureId );
   388     it->setValid( 
true );
   389     if ( it->attributes().count() < fieldCount )
   394       for ( 
int i = it->attributes().count(); i < mFields.count(); ++i )
   396         attributes.append( QVariant( mFields.at( i ).type() ) );
   398       it->setAttributes( attributes );
   400     else if ( it->attributes().count() > fieldCount )
   403       pushError( tr( 
"Feature has too many attributes (expecting %1, received %2)" ).arg( fieldCount ).arg( it->attributes().count() ) );
   405       attributes.resize( mFields.count() );
   406       it->setAttributes( attributes );
   416       pushError( tr( 
"Could not add feature with geometry type %1 to layer of type %2" ).arg( 
QgsWkbTypes::displayString( it->geometry().wkbType() ),
   422     mFeatures.insert( mNextFeatureId, *it );
   424     if ( it->hasGeometry() )
   427         mExtent.combineExtentWith( it->geometry().boundingBox() );
   431         mSpatialIndex->addFeature( *it );
   441 bool QgsMemoryProvider::deleteFeatures( 
const QgsFeatureIds &
id )
   443   for ( QgsFeatureIds::const_iterator it = 
id.begin(); it != 
id.end(); ++it )
   445     QgsFeatureMap::iterator fit = mFeatures.find( *it );
   448     if ( fit == mFeatures.end() )
   453       mSpatialIndex->deleteFeature( *fit );
   455     mFeatures.erase( fit );
   464 bool QgsMemoryProvider::addAttributes( 
const QList<QgsField> &attributes )
   466   for ( QList<QgsField>::const_iterator it = attributes.begin(); it != attributes.end(); ++it )
   468     switch ( it->type() )
   471       case QVariant::Double:
   472       case QVariant::String:
   475       case QVariant::DateTime:
   476       case QVariant::LongLong:
   477       case QVariant::StringList:
   480       case QVariant::ByteArray:
   483         QgsDebugMsg( 
"Field type not supported: " + it->typeName() );
   487     mFields.append( *it );
   489     for ( QgsFeatureMap::iterator fit = mFeatures.begin(); fit != mFeatures.end(); ++fit )
   493       attr.append( QVariant() );
   500 bool QgsMemoryProvider::renameAttributes( 
const QgsFieldNameMap &renamedAttributes )
   502   QgsFieldNameMap::const_iterator renameIt = renamedAttributes.constBegin();
   504   for ( ; renameIt != renamedAttributes.constEnd(); ++renameIt )
   506     int fieldIndex = renameIt.key();
   507     if ( fieldIndex < 0 || fieldIndex >= mFields.count() )
   512     if ( mFields.indexFromName( renameIt.value() ) >= 0 )
   519     mFields.rename( fieldIndex, renameIt.value() );
   524 bool QgsMemoryProvider::deleteAttributes( 
const QgsAttributeIds &attributes )
   526   QList<int> attrIdx = attributes.toList();
   527   std::sort( attrIdx.begin(), attrIdx.end(), std::greater<int>() );
   530   for ( QList<int>::const_iterator it = attrIdx.constBegin(); it != attrIdx.constEnd(); ++it )
   533     mFields.remove( idx );
   535     for ( QgsFeatureMap::iterator fit = mFeatures.begin(); fit != mFeatures.end(); ++fit )
   549   for ( QgsChangedAttributesMap::const_iterator it = attr_map.begin(); it != attr_map.end(); ++it )
   551     QgsFeatureMap::iterator fit = mFeatures.find( it.key() );
   552     if ( fit == mFeatures.end() )
   556     for ( QgsAttributeMap::const_iterator it2 = attrs.constBegin(); it2 != attrs.constEnd(); ++it2 )
   557       fit->setAttribute( it2.key(), it2.value() );
   563 bool QgsMemoryProvider::changeGeometryValues( 
const QgsGeometryMap &geometry_map )
   565   for ( QgsGeometryMap::const_iterator it = geometry_map.begin(); it != geometry_map.end(); ++it )
   567     QgsFeatureMap::iterator fit = mFeatures.find( it.key() );
   568     if ( fit == mFeatures.end() )
   573       mSpatialIndex->deleteFeature( *fit );
   575     fit->setGeometry( it.value() );
   579       mSpatialIndex->addFeature( *fit );
   587 QString QgsMemoryProvider::subsetString()
 const   589   return mSubsetString;
   592 bool QgsMemoryProvider::setSubsetString( 
const QString &theSQL, 
bool updateFeatureCount )
   594   Q_UNUSED( updateFeatureCount )
   596   if ( !theSQL.isEmpty() )
   599     if ( tempExpression.hasParserError() )
   603   if ( theSQL == mSubsetString )
   606   mSubsetString = theSQL;
   608   mExtent.setMinimal();
   614 bool QgsMemoryProvider::createSpatialIndex()
   616   if ( !mSpatialIndex )
   621     for ( QgsFeatureMap::iterator it = mFeatures.begin(); it != mFeatures.end(); ++it )
   623       mSpatialIndex->addFeature( *it );
   631   return mSpatialIndex ? SpatialIndexPresent : SpatialIndexNotPresent;
   634 QgsVectorDataProvider::Capabilities QgsMemoryProvider::capabilities()
 const   636   return AddFeatures | DeleteFeatures | ChangeGeometries |
   637          ChangeAttributeValues | AddAttributes | DeleteAttributes | RenameAttributes | CreateSpatialIndex |
   638          SelectAtId | CircularGeometries | FastTruncate;
   641 bool QgsMemoryProvider::truncate()
   645   mExtent.setMinimal();
   649 void QgsMemoryProvider::updateExtents()
   651   mExtent.setMinimal();
   654 QString QgsMemoryProvider::name()
 const   656   return TEXT_PROVIDER_KEY;
   659 QString QgsMemoryProvider::description()
 const   661   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
 
static Type parseType(const QString &wktStr)
Attempts to extract the WKB type from a WKT string. 
 
Container of fields for a vector layer. 
 
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes. 
 
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
 
Full WKT2 string, conforming to ISO 19162:2018 / OGC 18-010, with all possible nodes and new keyword ...
 
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...
 
SpatialIndexPresence
Enumeration of spatial index presence states. 
 
QList< int > QgsAttributeList
 
bool nextFeature(QgsFeature &f)
 
This is the base class for vector data providers.