23 #include <QDomElement> 36 QList<QgsVectorLayer*> lst;
47 if ( mark.value( n ) == 1 )
49 if ( mark.value( n ) == 0 )
65 mVectorJoins.push_back( joinInfo );
69 QHash<QgsVectorLayer*, int> markDFS;
73 mVectorJoins.pop_back();
80 cacheJoinLayer( mVectorJoins.last() );
88 connect( vl, SIGNAL( updatedFields() ),
this, SLOT( joinedLayerUpdatedFields() ), Qt::UniqueConnection );
97 for (
int i = 0; i < mVectorJoins.size(); ++i )
99 if ( mVectorJoins.at( i ).joinLayerId == joinLayerId )
101 mVectorJoins.removeAt( i );
106 disconnect( vl, SIGNAL( updatedFields() ),
this, SLOT( joinedLayerUpdatedFields() ) );
139 QVector<int> subsetIndices;
146 if ( !cacheLayerAttrs.contains( joinFieldIndex ) )
147 cacheLayerAttrs.append( joinFieldIndex );
156 QString key = attrs[joinFieldIndex].toString();
160 for (
int i = 0; i < subsetIndices.count(); ++i )
161 subsetAttrs[i] = attrs[ subsetIndices[i] ];
167 attrs2.remove( joinFieldIndex );
177 QVector<int> subsetIndices;
179 for (
int i = 0; i < joinFieldsSubset.count(); ++i )
181 QString joinedFieldName = joinFieldsSubset.
at( i );
185 subsetIndices.append( index );
189 QgsDebugMsg(
"Join layer subset field not found: " + joinedFieldName );
193 return subsetIndices;
200 QList< QgsVectorJoinInfo>::const_iterator joinIt = mVectorJoins.constBegin();
201 for (
int joinIdx = 0 ; joinIt != mVectorJoins.constEnd(); ++joinIt, ++joinIdx )
210 QString joinFieldName;
211 if ( joinIt->joinFieldName.isEmpty() && joinIt->joinFieldIndex >= 0 && joinIt->joinFieldIndex < joinFields.
count() )
212 joinFieldName = joinFields.
field( joinIt->joinFieldIndex ).
name();
214 joinFieldName = joinIt->joinFieldName;
216 QSet<QString> subset;
217 bool hasSubset =
false;
218 if ( joinIt->joinFieldNamesSubset() )
221 subset = QSet<QString>::fromList( *joinIt->joinFieldNamesSubset() );
224 if ( joinIt->prefix.isNull() )
226 prefix = joinLayer->
name() +
"_";
230 prefix = joinIt->prefix;
233 for (
int idx = 0; idx < joinFields.
count(); ++idx )
236 if ( hasSubset && !subset.contains( joinFields[idx].name() ) )
241 if ( hasSubset || joinFields[idx].name() != joinFieldName )
253 QList< QgsVectorJoinInfo >::iterator joinIt = mVectorJoins.begin();
254 for ( ; joinIt != mVectorJoins.end(); ++joinIt )
256 cacheJoinLayer( *joinIt );
260 connect( vl, SIGNAL( updatedFields() ),
this, SLOT( joinedLayerUpdatedFields() ), Qt::UniqueConnection );
267 QDomElement vectorJoinsElem = document.createElement(
"vectorjoins" );
268 layer_node.appendChild( vectorJoinsElem );
269 QList< QgsVectorJoinInfo >::const_iterator joinIt = mVectorJoins.constBegin();
270 for ( ; joinIt != mVectorJoins.constEnd(); ++joinIt )
272 QDomElement joinElem = document.createElement(
"join" );
274 if ( joinIt->targetFieldName.isEmpty() )
275 joinElem.setAttribute(
"targetField", joinIt->targetFieldIndex );
277 joinElem.setAttribute(
"targetFieldName", joinIt->targetFieldName );
279 joinElem.setAttribute(
"joinLayerId", joinIt->joinLayerId );
280 if ( joinIt->joinFieldName.isEmpty() )
281 joinElem.setAttribute(
"joinField", joinIt->joinFieldIndex );
283 joinElem.setAttribute(
"joinFieldName", joinIt->joinFieldName );
285 joinElem.setAttribute(
"memoryCache", !joinIt->cachedAttributes.isEmpty() );
287 if ( joinIt->joinFieldNamesSubset() )
289 QDomElement subsetElem = document.createElement(
"joinFieldsSubset" );
290 foreach ( QString fieldName, *joinIt->joinFieldNamesSubset() )
292 QDomElement fieldElem = document.createElement(
"field" );
293 fieldElem.setAttribute(
"name", fieldName );
294 subsetElem.appendChild( fieldElem );
297 joinElem.appendChild( subsetElem );
300 if ( !joinIt->prefix.isNull() )
302 joinElem.setAttribute(
"customPrefix", joinIt->prefix );
303 joinElem.setAttribute(
"hasCustomPrefix", 1 );
306 vectorJoinsElem.appendChild( joinElem );
312 mVectorJoins.clear();
313 QDomElement vectorJoinsElem = layer_node.firstChildElement(
"vectorjoins" );
314 if ( !vectorJoinsElem.isNull() )
316 QDomNodeList joinList = vectorJoinsElem.elementsByTagName(
"join" );
317 for (
int i = 0; i < joinList.size(); ++i )
319 QDomElement infoElem = joinList.at( i ).toElement();
322 info.
joinLayerId = infoElem.attribute(
"joinLayerId" );
324 info.
memoryCache = infoElem.attribute(
"memoryCache" ).toInt();
329 QDomElement subsetElem = infoElem.firstChildElement(
"joinFieldsSubset" );
330 if ( !subsetElem.isNull() )
332 QStringList* fieldNames =
new QStringList;
333 QDomNodeList fieldNodes = infoElem.elementsByTagName(
"field" );
334 for (
int i = 0; i < fieldNodes.count(); ++i )
335 *fieldNames << fieldNodes.at( i ).toElement().attribute(
"name" );
339 if ( infoElem.attribute(
"hasCustomPrefix" ).toInt() )
340 info.
prefix = infoElem.attribute(
"customPrefix" );
342 info.
prefix = QString::null;
354 int joinIndex = mVectorJoins.indexOf( *info );
355 if ( joinIndex == -1 )
358 for (
int i = 0; i < fields.
count(); ++i )
375 int sourceJoinIndex = originIndex / 1000;
376 sourceFieldIndex = originIndex % 1000;
378 if ( sourceJoinIndex < 0 || sourceJoinIndex >= mVectorJoins.count() )
381 return &( mVectorJoins[sourceJoinIndex] );
387 cloned->mVectorJoins = mVectorJoins;
391 void QgsVectorLayerJoinBuffer::joinedLayerUpdatedFields()
394 Q_ASSERT( joinedLayer );
397 for ( QgsVectorJoinList::iterator it = mVectorJoins.begin(); it != mVectorJoins.end(); ++it )
399 if ( joinedLayer->
id() == it->joinLayerId )
401 it->cachedAttributes.clear();
402 cacheJoinLayer( *it );
const QString & name() const
Gets the name of the field.
Wrapper for iterator of features from vector data provider or vector layer.
const QList< QgsVectorJoinInfo > vectorJoins() const
QString joinFieldName
Join field in the source layer.
field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
QString targetFieldName
Join field in the target layer.
void createJoinCaches()
Calls cacheJoinLayer() for all vector joins.
const QgsField & field(int fieldIdx) const
Get field at particular index (must be in range 0..N-1)
int fieldNameIndex(const QString &fieldName) const
Look up field's index from name also looks up case-insensitive if there is no match otherwise...
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
int joinFieldIndex
Join field index in the source layer.
static QgsMapLayerRegistry * instance()
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
void readXml(const QDomNode &layer_node)
Reads joins from project file.
Container of fields for a vector layer.
QgsVectorLayerJoinBuffer(QgsVectorLayer *layer=0)
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
bool memoryCache
True if the join is cached in virtual memory.
int targetFieldIndex
Join field index in the target layer.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Manages joined fields for a vector layer.
const QgsVectorJoinInfo * joinForFieldIndex(int index, const QgsFields &fields, int &sourceFieldIndex) const
Finds the vector join for a layer field index.
int joinedFieldsOffset(const QgsVectorJoinInfo *info, const QgsFields &fields)
Find out what is the first index of the join within fields.
QgsVectorLayerJoinBuffer * clone() const
Create a copy of the join buffer.
const QString & name() const
Get the display name of the layer.
QString prefix
An optional prefix.
void setJoinFieldNamesSubset(QStringList *fieldNamesSubset)
Set subset of fields to be used from joined layer.
bool addJoin(const QgsVectorJoinInfo &joinInfo)
Joins another vector layer to this layer.
int fieldOriginIndex(int fieldIdx) const
Get field's origin index (its meaning is specific to each type of origin)
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QList< int > QgsAttributeList
const QgsAttributes & attributes() const
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Append a field. The field must have unique name, otherwise it is rejected (returns false) ...
QString id() const
Get this layer's unique ID, this ID is used to access this layer from map layer registry.
int count() const
Return number of items.
Encapsulate a field in an attribute table or data source.
void removeJoin(const QString &joinLayerId)
Removes a vector layer join.
int indexFromName(const QString &name) const
Look up field's index from name. Returns -1 on error.
~QgsVectorLayerJoinBuffer()
void setName(const QString &nam)
Set the field name.
QHash< QString, QgsAttributes > cachedAttributes
Cache for joined attributes to provide fast lookup (size is 0 if no memory caching) ...
void writeXml(QDomNode &layer_node, QDomDocument &document) const
Saves mVectorJoins to xml under the layer node.
static bool _hasCycleDFS(QgsVectorLayer *n, QHash< QgsVectorLayer *, int > &mark)
void updateFields(QgsFields &fields)
Updates field map with joined attributes.
static QList< QgsVectorLayer * > _outEdges(QgsVectorLayer *vl)
static QVector< int > joinSubsetIndices(QgsVectorLayer *joinLayer, const QStringList &joinFieldsSubset)
Return a vector of indices for use in join based on field names from the layer.
FieldOrigin fieldOrigin(int fieldIdx) const
Get field's origin (value from an enumeration)
void joinedFieldsChanged()
Emitted whenever the list of joined fields changes (e.g.
QStringList * joinFieldNamesSubset() const
Get subset of fields to be used from joined layer.
QgsMapLayer * mapLayer(QString theLayerId)
Retrieve a pointer to a loaded layer by id.
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
bool nextFeature(QgsFeature &f)
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Represents a vector layer which manages a vector based data sets.
QgsFeatureRequest & setFlags(Flags flags)
Set flags that affect how features will be fetched.
QString joinLayerId
Source layer.