QGIS API Documentation  2.2.0-Valmiera
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsvectorlayerjoinbuffer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectorlayerjoinbuffer.cpp
3  ----------------------------
4  begin : Feb 09, 2011
5  copyright : (C) 2011 by Marco Hugentobler
6  email : marco dot hugentobler at sourcepole dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
19 
20 #include "qgsmaplayerregistry.h"
21 #include "qgsvectordataprovider.h"
22 
23 #include <QDomElement>
24 
26 {
27 }
28 
30 {
31 }
32 
34 {
35  mVectorJoins.push_back( joinInfo );
36 
37  //cache joined layer to virtual memory if specified by user
38  if ( joinInfo.memoryCache )
39  {
40  cacheJoinLayer( mVectorJoins.last() );
41  }
42 }
43 
44 void QgsVectorLayerJoinBuffer::removeJoin( const QString& joinLayerId )
45 {
46  for ( int i = 0; i < mVectorJoins.size(); ++i )
47  {
48  if ( mVectorJoins.at( i ).joinLayerId == joinLayerId )
49  {
50  mVectorJoins.removeAt( i );
51  }
52  }
53 }
54 
56 {
57  //memory cache not required or already done
58  if ( !joinInfo.memoryCache || joinInfo.cachedAttributes.size() > 0 )
59  {
60  return;
61  }
62 
63  QgsVectorLayer* cacheLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinInfo.joinLayerId ) );
64  if ( cacheLayer )
65  {
66  int joinFieldIndex;
67  if ( joinInfo.joinFieldName.isEmpty() )
68  joinFieldIndex = joinInfo.joinFieldIndex; //for compatibility with 1.x
69  else
70  joinFieldIndex = cacheLayer->pendingFields().indexFromName( joinInfo.joinFieldName );
71 
72  joinInfo.cachedAttributes.clear();
73 
75  QgsFeature f;
76  while ( fit.nextFeature( f ) )
77  {
78  const QgsAttributes& attrs = f.attributes();
79  joinInfo.cachedAttributes.insert( attrs[joinFieldIndex].toString(), attrs );
80  }
81  }
82 }
83 
85 {
86  QList< QgsVectorJoinInfo>::const_iterator joinIt = mVectorJoins.constBegin();
87  for ( int joinIdx = 0 ; joinIt != mVectorJoins.constEnd(); ++joinIt, ++joinIdx )
88  {
89  QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinIt->joinLayerId ) );
90  if ( !joinLayer )
91  {
92  continue;
93  }
94 
95  const QgsFields& joinFields = joinLayer->pendingFields();
96  QString joinFieldName;
97  if ( joinIt->joinFieldName.isEmpty() && joinIt->joinFieldIndex >= 0 && joinIt->joinFieldIndex < joinFields.count() )
98  joinFieldName = joinFields.field( joinIt->joinFieldIndex ).name(); //for compatibility with 1.x
99  else
100  joinFieldName = joinIt->joinFieldName;
101 
102  for ( int idx = 0; idx < joinFields.count(); ++idx )
103  {
104  //skip the join field to avoid double field names (fields often have the same name)
105  if ( joinFields[idx].name() != joinFieldName )
106  {
107  QgsField f = joinFields[idx];
108  f.setName( joinLayer->name() + "_" + f.name() );
109  fields.append( f, QgsFields::OriginJoin, idx + ( joinIdx*1000 ) );
110  }
111  }
112  }
113 }
114 
116 {
117  QList< QgsVectorJoinInfo >::iterator joinIt = mVectorJoins.begin();
118  for ( ; joinIt != mVectorJoins.end(); ++joinIt )
119  {
120  cacheJoinLayer( *joinIt );
121  }
122 }
123 
124 
125 void QgsVectorLayerJoinBuffer::writeXml( QDomNode& layer_node, QDomDocument& document ) const
126 {
127  QDomElement vectorJoinsElem = document.createElement( "vectorjoins" );
128  layer_node.appendChild( vectorJoinsElem );
129  QList< QgsVectorJoinInfo >::const_iterator joinIt = mVectorJoins.constBegin();
130  for ( ; joinIt != mVectorJoins.constEnd(); ++joinIt )
131  {
132  QDomElement joinElem = document.createElement( "join" );
133 
134  if ( joinIt->targetFieldName.isEmpty() )
135  joinElem.setAttribute( "targetField", joinIt->targetFieldIndex ); //for compatibility with 1.x
136  else
137  joinElem.setAttribute( "targetFieldName", joinIt->targetFieldName );
138 
139  joinElem.setAttribute( "joinLayerId", joinIt->joinLayerId );
140  if ( joinIt->joinFieldName.isEmpty() )
141  joinElem.setAttribute( "joinField", joinIt->joinFieldIndex ); //for compatibility with 1.x
142  else
143  joinElem.setAttribute( "joinFieldName", joinIt->joinFieldName );
144 
145  joinElem.setAttribute( "memoryCache", !joinIt->cachedAttributes.isEmpty() );
146  vectorJoinsElem.appendChild( joinElem );
147  }
148 }
149 
150 void QgsVectorLayerJoinBuffer::readXml( const QDomNode& layer_node )
151 {
152  mVectorJoins.clear();
153  QDomElement vectorJoinsElem = layer_node.firstChildElement( "vectorjoins" );
154  if ( !vectorJoinsElem.isNull() )
155  {
156  QDomNodeList joinList = vectorJoinsElem.elementsByTagName( "join" );
157  for ( int i = 0; i < joinList.size(); ++i )
158  {
159  QDomElement infoElem = joinList.at( i ).toElement();
160  QgsVectorJoinInfo info;
161  info.joinFieldName = infoElem.attribute( "joinFieldName" );
162  info.joinLayerId = infoElem.attribute( "joinLayerId" );
163  info.targetFieldName = infoElem.attribute( "targetFieldName" );
164  info.memoryCache = infoElem.attribute( "memoryCache" ).toInt();
165 
166  info.joinFieldIndex = infoElem.attribute( "joinField" ).toInt(); //for compatibility with 1.x
167  info.targetFieldIndex = infoElem.attribute( "targetField" ).toInt(); //for compatibility with 1.x
168 
169  addJoin( info );
170  }
171  }
172 }
173 
174 const QgsVectorJoinInfo* QgsVectorLayerJoinBuffer::joinForFieldIndex( int index, const QgsFields& fields, int& sourceFieldIndex ) const
175 {
176  if ( fields.fieldOrigin( index ) != QgsFields::OriginJoin )
177  return 0;
178 
179  int originIndex = fields.fieldOriginIndex( index );
180  int sourceJoinIndex = originIndex / 1000;
181  sourceFieldIndex = originIndex % 1000;
182 
183  if ( sourceJoinIndex < 0 || sourceJoinIndex >= mVectorJoins.count() )
184  return 0;
185 
186  return &( mVectorJoins[sourceJoinIndex] );
187 }