|
QGIS API Documentation
master-28efcda
|
00001 /*************************************************************************** 00002 qgsvectorlayerjoinbuffer.cpp 00003 ---------------------------- 00004 begin : Feb 09, 2011 00005 copyright : (C) 2011 by Marco Hugentobler 00006 email : marco dot hugentobler at sourcepole dot ch 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #include "qgsvectorlayerjoinbuffer.h" 00019 00020 #include "qgsmaplayerregistry.h" 00021 #include "qgsvectordataprovider.h" 00022 00023 #include <QDomElement> 00024 00025 QgsVectorLayerJoinBuffer::QgsVectorLayerJoinBuffer() 00026 { 00027 } 00028 00029 QgsVectorLayerJoinBuffer::~QgsVectorLayerJoinBuffer() 00030 { 00031 } 00032 00033 void QgsVectorLayerJoinBuffer::addJoin( const QgsVectorJoinInfo& joinInfo ) 00034 { 00035 mVectorJoins.push_back( joinInfo ); 00036 00037 //cache joined layer to virtual memory if specified by user 00038 if ( joinInfo.memoryCache ) 00039 { 00040 cacheJoinLayer( mVectorJoins.last() ); 00041 } 00042 } 00043 00044 void QgsVectorLayerJoinBuffer::removeJoin( const QString& joinLayerId ) 00045 { 00046 for ( int i = 0; i < mVectorJoins.size(); ++i ) 00047 { 00048 if ( mVectorJoins.at( i ).joinLayerId == joinLayerId ) 00049 { 00050 mVectorJoins.removeAt( i ); 00051 } 00052 } 00053 } 00054 00055 void QgsVectorLayerJoinBuffer::cacheJoinLayer( QgsVectorJoinInfo& joinInfo ) 00056 { 00057 //memory cache not required or already done 00058 if ( !joinInfo.memoryCache || joinInfo.cachedAttributes.size() > 0 ) 00059 { 00060 return; 00061 } 00062 00063 QgsVectorLayer* cacheLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinInfo.joinLayerId ) ); 00064 if ( cacheLayer ) 00065 { 00066 int joinFieldIndex; 00067 if ( joinInfo.joinFieldName.isEmpty() ) 00068 joinFieldIndex = joinInfo.joinFieldIndex; //for compatibility with 1.x 00069 else 00070 joinFieldIndex = cacheLayer->pendingFields().indexFromName( joinInfo.joinFieldName ); 00071 00072 joinInfo.cachedAttributes.clear(); 00073 00074 QgsFeatureIterator fit = cacheLayer->getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ) ); 00075 QgsFeature f; 00076 while ( fit.nextFeature( f ) ) 00077 { 00078 const QgsAttributes& attrs = f.attributes(); 00079 joinInfo.cachedAttributes.insert( attrs[joinFieldIndex].toString(), attrs ); 00080 } 00081 } 00082 } 00083 00084 void QgsVectorLayerJoinBuffer::updateFields( QgsFields& fields ) 00085 { 00086 QList< QgsVectorJoinInfo>::const_iterator joinIt = mVectorJoins.constBegin(); 00087 for ( int joinIdx = 0 ; joinIt != mVectorJoins.constEnd(); ++joinIt, ++joinIdx ) 00088 { 00089 QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinIt->joinLayerId ) ); 00090 if ( !joinLayer ) 00091 { 00092 continue; 00093 } 00094 00095 const QgsFields& joinFields = joinLayer->pendingFields(); 00096 QString joinFieldName; 00097 if ( joinIt->joinFieldName.isEmpty() && joinIt->joinFieldIndex >= 0 && joinIt->joinFieldIndex < joinFields.count() ) 00098 joinFieldName = joinFields.field( joinIt->joinFieldIndex ).name(); //for compatibility with 1.x 00099 else 00100 joinFieldName = joinIt->joinFieldName; 00101 00102 for ( int idx = 0; idx < joinFields.count(); ++idx ) 00103 { 00104 //skip the join field to avoid double field names (fields often have the same name) 00105 if ( joinFields[idx].name() != joinFieldName ) 00106 { 00107 QgsField f = joinFields[idx]; 00108 f.setName( joinLayer->name() + "_" + f.name() ); 00109 fields.append( f, QgsFields::OriginJoin, idx + ( joinIdx*1000 ) ); 00110 } 00111 } 00112 } 00113 } 00114 00115 void QgsVectorLayerJoinBuffer::createJoinCaches() 00116 { 00117 QList< QgsVectorJoinInfo >::iterator joinIt = mVectorJoins.begin(); 00118 for ( ; joinIt != mVectorJoins.end(); ++joinIt ) 00119 { 00120 cacheJoinLayer( *joinIt ); 00121 } 00122 } 00123 00124 00125 void QgsVectorLayerJoinBuffer::writeXml( QDomNode& layer_node, QDomDocument& document ) const 00126 { 00127 QDomElement vectorJoinsElem = document.createElement( "vectorjoins" ); 00128 layer_node.appendChild( vectorJoinsElem ); 00129 QList< QgsVectorJoinInfo >::const_iterator joinIt = mVectorJoins.constBegin(); 00130 for ( ; joinIt != mVectorJoins.constEnd(); ++joinIt ) 00131 { 00132 QDomElement joinElem = document.createElement( "join" ); 00133 00134 if ( joinIt->targetFieldName.isEmpty() ) 00135 joinElem.setAttribute( "targetField", joinIt->targetFieldIndex ); //for compatibility with 1.x 00136 else 00137 joinElem.setAttribute( "targetFieldName", joinIt->targetFieldName ); 00138 00139 joinElem.setAttribute( "joinLayerId", joinIt->joinLayerId ); 00140 if ( joinIt->joinFieldName.isEmpty() ) 00141 joinElem.setAttribute( "joinField", joinIt->joinFieldIndex ); //for compatibility with 1.x 00142 else 00143 joinElem.setAttribute( "joinFieldName", joinIt->joinFieldName ); 00144 00145 joinElem.setAttribute( "memoryCache", !joinIt->cachedAttributes.isEmpty() ); 00146 vectorJoinsElem.appendChild( joinElem ); 00147 } 00148 } 00149 00150 void QgsVectorLayerJoinBuffer::readXml( const QDomNode& layer_node ) 00151 { 00152 mVectorJoins.clear(); 00153 QDomElement vectorJoinsElem = layer_node.firstChildElement( "vectorjoins" ); 00154 if ( !vectorJoinsElem.isNull() ) 00155 { 00156 QDomNodeList joinList = vectorJoinsElem.elementsByTagName( "join" ); 00157 for ( int i = 0; i < joinList.size(); ++i ) 00158 { 00159 QDomElement infoElem = joinList.at( i ).toElement(); 00160 QgsVectorJoinInfo info; 00161 info.joinFieldName = infoElem.attribute( "joinFieldName" ); 00162 info.joinLayerId = infoElem.attribute( "joinLayerId" ); 00163 info.targetFieldName = infoElem.attribute( "targetFieldName" ); 00164 info.memoryCache = infoElem.attribute( "memoryCache" ).toInt(); 00165 00166 info.joinFieldIndex = infoElem.attribute( "joinField" ).toInt(); //for compatibility with 1.x 00167 info.targetFieldIndex = infoElem.attribute( "targetField" ).toInt(); //for compatibility with 1.x 00168 00169 addJoin( info ); 00170 } 00171 } 00172 } 00173 00174 const QgsVectorJoinInfo* QgsVectorLayerJoinBuffer::joinForFieldIndex( int index, const QgsFields& fields, int& sourceFieldIndex ) const 00175 { 00176 if ( fields.fieldOrigin( index ) != QgsFields::OriginJoin ) 00177 return 0; 00178 00179 int originIndex = fields.fieldOriginIndex( index ); 00180 int sourceJoinIndex = originIndex / 1000; 00181 sourceFieldIndex = originIndex % 1000; 00182 00183 if ( sourceJoinIndex < 0 || sourceJoinIndex >= mVectorJoins.count() ) 00184 return 0; 00185 00186 return &( mVectorJoins[sourceJoinIndex] ); 00187 }