QGIS API Documentation  master-28efcda
src/core/qgsvectorlayerjoinbuffer.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines