Quantum GIS API Documentation  1.7.4
src/core/composer/qgscomposerattributetable.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                          qgscomposerattributetable.cpp
00003                          -----------------------------
00004     begin                : April 2010
00005     copyright            : (C) 2010 by Marco Hugentobler
00006     email                : marco at hugis dot net
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 "qgscomposerattributetable.h"
00019 #include "qgscomposermap.h"
00020 #include "qgsmaplayerregistry.h"
00021 #include "qgsvectorlayer.h"
00022 
00023 QgsComposerAttributeTableCompare::QgsComposerAttributeTableCompare(): mCurrentSortColumn( 0 ), mAscending( true )
00024 {
00025 }
00026 
00027 
00028 bool QgsComposerAttributeTableCompare::operator()( const QgsAttributeMap& m1, const QgsAttributeMap& m2 )
00029 {
00030   QVariant v1 = m1[mCurrentSortColumn];
00031   QVariant v2 = m2[mCurrentSortColumn];
00032 
00033   bool less = false;
00034   if ( v1.type() == QVariant::String && v2.type() == QVariant::String )
00035   {
00036     less = v1.toString() < v2.toString();
00037   }
00038   else
00039   {
00040     less = v1.toDouble() < v2.toDouble();
00041   }
00042   return ( mAscending ? less : !less );
00043 }
00044 
00045 
00046 QgsComposerAttributeTable::QgsComposerAttributeTable( QgsComposition* composition ): QgsComposerTable( composition ), mVectorLayer( 0 ), mComposerMap( 0 ), \
00047     mMaximumNumberOfFeatures( 5 ), mShowOnlyVisibleFeatures( true )
00048 {
00049   //set first vector layer from layer registry as default one
00050   QMap<QString, QgsMapLayer*> layerMap =  QgsMapLayerRegistry::instance()->mapLayers();
00051   QMap<QString, QgsMapLayer*>::const_iterator mapIt = layerMap.constBegin();
00052   for ( ; mapIt != layerMap.constEnd(); ++mapIt )
00053   {
00054     QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( mapIt.value() );
00055     if ( vl )
00056     {
00057       mVectorLayer = vl;
00058       break;
00059     }
00060   }
00061   connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( removeLayer( const QString& ) ) );
00062 }
00063 
00064 QgsComposerAttributeTable::~QgsComposerAttributeTable()
00065 {
00066 
00067 }
00068 
00069 void QgsComposerAttributeTable::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget )
00070 {
00071   if ( mComposerMap && mComposerMap->isDrawing() )
00072   {
00073     return;
00074   }
00075   QgsComposerTable::paint( painter, itemStyle, pWidget );
00076 }
00077 
00078 void QgsComposerAttributeTable::initializeAliasMap()
00079 {
00080   mFieldAliasMap.clear();
00081   if ( mVectorLayer )
00082   {
00083     QgsFieldMap fieldMap = mVectorLayer->pendingFields();
00084     QgsFieldMap::const_iterator it = fieldMap.constBegin();
00085     for ( ; it != fieldMap.constEnd(); ++it )
00086     {
00087       QString currentAlias = mVectorLayer->attributeAlias( it.key() );
00088       if ( !currentAlias.isEmpty() )
00089       {
00090         mFieldAliasMap.insert( it.key(), currentAlias );
00091       }
00092     }
00093   }
00094 }
00095 
00096 void QgsComposerAttributeTable::setVectorLayer( QgsVectorLayer* vl )
00097 {
00098   if ( vl != mVectorLayer )
00099   {
00100     mDisplayAttributes.clear();
00101     mVectorLayer = vl;
00102     initializeAliasMap();
00103   }
00104 }
00105 
00106 void QgsComposerAttributeTable::setComposerMap( const QgsComposerMap* map )
00107 {
00108   if ( mComposerMap )
00109   {
00110     QObject::disconnect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( repaint() ) );
00111   }
00112   mComposerMap = map;
00113   if ( mComposerMap )
00114   {
00115     QObject::connect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( repaint() ) );
00116   }
00117 }
00118 
00119 bool QgsComposerAttributeTable::getFeatureAttributes( QList<QgsAttributeMap>& attributes )
00120 {
00121   if ( !mVectorLayer )
00122   {
00123     return false;
00124   }
00125   attributes.clear();
00126 
00127   QgsRectangle selectionRect;
00128   if ( mComposerMap && mShowOnlyVisibleFeatures )
00129   {
00130     selectionRect = mComposerMap->extent();
00131   }
00132 
00133   if ( mDisplayAttributes.size() < 1 )
00134   {
00135     mVectorLayer->select( mVectorLayer->pendingAllAttributesList(), selectionRect, mShowOnlyVisibleFeatures, mShowOnlyVisibleFeatures );
00136   }
00137   else
00138   {
00139     mVectorLayer->select( mDisplayAttributes.toList(), selectionRect, mShowOnlyVisibleFeatures, mShowOnlyVisibleFeatures );
00140   }
00141   QgsFeature f;
00142   int counter = 0;
00143   while ( mVectorLayer->nextFeature( f ) && counter < mMaximumNumberOfFeatures )
00144   {
00145     attributes.push_back( f.attributeMap() );
00146     ++counter;
00147   }
00148 
00149   //sort the list, starting with the last attribute
00150   QgsComposerAttributeTableCompare c;
00151   for ( int i = mSortInformation.size() - 1; i >= 0; --i )
00152   {
00153     c.setSortColumn( mSortInformation.at( i ).first );
00154     c.setAscending( mSortInformation.at( i ).second );
00155     qStableSort( attributes.begin(), attributes.end(), c );
00156   }
00157   return true;
00158 }
00159 
00160 QMap<int, QString> QgsComposerAttributeTable::getHeaderLabels() const
00161 {
00162   QMap<int, QString> header;
00163   if ( mVectorLayer )
00164   {
00165     QgsFieldMap vectorFields = mVectorLayer->pendingFields();
00166     QgsFieldMap::const_iterator fieldIt = vectorFields.constBegin();
00167     for ( ; fieldIt != vectorFields.constEnd(); ++fieldIt )
00168     {
00169       if ( mDisplayAttributes.size() > 0 && !mDisplayAttributes.contains( fieldIt.key() ) )
00170       {
00171         continue;
00172       }
00173       header.insert( fieldIt.key(), attributeDisplayName( fieldIt.key(), fieldIt.value().name() ) );
00174     }
00175   }
00176   return header;
00177 }
00178 
00179 QString QgsComposerAttributeTable::attributeDisplayName( int attributeIndex, const QString& name ) const
00180 {
00181   QMap<int, QString>::const_iterator it = mFieldAliasMap.find( attributeIndex );
00182   if ( it != mFieldAliasMap.constEnd() )
00183   {
00184     return it.value();
00185   }
00186   else
00187   {
00188     return name;
00189   }
00190 }
00191 
00192 void QgsComposerAttributeTable::removeLayer( QString layerId )
00193 {
00194   if ( mVectorLayer )
00195   {
00196     if ( layerId == mVectorLayer->id() )
00197     {
00198       mVectorLayer = 0;
00199     }
00200   }
00201 }
00202 
00203 void QgsComposerAttributeTable::setSceneRect( const QRectF& rectangle )
00204 {
00205   double titleHeight =  2 * mGridStrokeWidth + 2 * mLineTextDistance + fontAscentMillimeters( mHeaderFont );
00206   double attributeHeight = mGridStrokeWidth + 2 * mLineTextDistance + fontAscentMillimeters( mContentFont );
00207   if (( rectangle.height() - titleHeight ) > 0 )
00208   {
00209     mMaximumNumberOfFeatures = ( rectangle.height() - titleHeight ) / attributeHeight;
00210   }
00211   else
00212   {
00213     mMaximumNumberOfFeatures = 0;
00214   }
00215   QgsComposerItem::setSceneRect( rectangle );
00216   emit maximumNumerOfFeaturesChanged( mMaximumNumberOfFeatures );
00217 }
00218 
00219 bool QgsComposerAttributeTable::writeXML( QDomElement& elem, QDomDocument & doc ) const
00220 {
00221   QDomElement composerTableElem = doc.createElement( "ComposerAttributeTable" );
00222   composerTableElem.setAttribute( "showOnlyVisibleFeatures", mShowOnlyVisibleFeatures );
00223 
00224   if ( mComposerMap )
00225   {
00226     composerTableElem.setAttribute( "composerMap", mComposerMap->id() );
00227   }
00228   else
00229   {
00230     composerTableElem.setAttribute( "composerMap", -1 );
00231   }
00232   if ( mVectorLayer )
00233   {
00234     composerTableElem.setAttribute( "vectorLayer", mVectorLayer->id() );
00235   }
00236 
00237   //display attributes
00238   QDomElement displayAttributesElem = doc.createElement( "displayAttributes" );
00239   QSet<int>::const_iterator attIt = mDisplayAttributes.constBegin();
00240   for ( ; attIt != mDisplayAttributes.constEnd(); ++attIt )
00241   {
00242     QDomElement attributeIndexElem = doc.createElement( "attributeEntry" );
00243     attributeIndexElem.setAttribute( "index", *attIt );
00244     displayAttributesElem.appendChild( attributeIndexElem );
00245   }
00246   composerTableElem.appendChild( displayAttributesElem );
00247 
00248   //alias map
00249   QDomElement aliasMapElem = doc.createElement( "attributeAliasMap" );
00250   QMap<int, QString>::const_iterator aliasIt = mFieldAliasMap.constBegin();
00251   for ( ; aliasIt != mFieldAliasMap.constEnd(); ++aliasIt )
00252   {
00253     QDomElement mapEntryElem = doc.createElement( "aliasEntry" );
00254     mapEntryElem.setAttribute( "key", aliasIt.key() );
00255     mapEntryElem.setAttribute( "value", aliasIt.value() );
00256     aliasMapElem.appendChild( mapEntryElem );
00257   }
00258   composerTableElem.appendChild( aliasMapElem );
00259 
00260   //sort info
00261   QDomElement sortColumnsElem = doc.createElement( "sortColumns" );
00262   QList< QPair<int, bool> >::const_iterator sortIt = mSortInformation.constBegin();
00263   for ( ; sortIt != mSortInformation.constEnd(); ++sortIt )
00264   {
00265     QDomElement columnElem = doc.createElement( "column" );
00266     columnElem.setAttribute( "index", QString::number( sortIt->first ) );
00267     columnElem.setAttribute( "ascending", sortIt->second == true ? "true" : "false" );
00268     sortColumnsElem.appendChild( columnElem );
00269   }
00270   composerTableElem.appendChild( sortColumnsElem );
00271   elem.appendChild( composerTableElem );
00272   bool ok = tableWriteXML( composerTableElem, doc );
00273   return ok;
00274 }
00275 
00276 bool QgsComposerAttributeTable::readXML( const QDomElement& itemElem, const QDomDocument& doc )
00277 {
00278   if ( itemElem.isNull() )
00279   {
00280     return false;
00281   }
00282 
00283   mMaximumNumberOfFeatures = itemElem.attribute( "maxFeatures", "5" ).toInt();
00284   mShowOnlyVisibleFeatures = itemElem.attribute( "showOnlyVisibleFeatures", "1" ).toInt();
00285 
00286   //composer map
00287   int composerMapId = itemElem.attribute( "composerMap", "-1" ).toInt();
00288   if ( composerMapId == -1 )
00289   {
00290     mComposerMap = 0;
00291   }
00292 
00293   if ( composition() )
00294   {
00295     mComposerMap = composition()->getComposerMapById( composerMapId );
00296   }
00297   else
00298   {
00299     mComposerMap = 0;
00300   }
00301 
00302   //vector layer
00303   QString layerId = itemElem.attribute( "vectorLayer", "not_existing" );
00304   if ( layerId == "not_existing" )
00305   {
00306     mVectorLayer = 0;
00307   }
00308   else
00309   {
00310     QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer( layerId );
00311     if ( ml )
00312     {
00313       mVectorLayer = dynamic_cast<QgsVectorLayer*>( ml );
00314     }
00315   }
00316 
00317   //restore display attribute map
00318   mDisplayAttributes.clear();
00319   QDomNodeList displayAttributeList = itemElem.elementsByTagName( "displayAttributes" );
00320   if ( displayAttributeList.size() > 0 )
00321   {
00322     QDomElement displayAttributesElem =  displayAttributeList.at( 0 ).toElement();
00323     QDomNodeList attributeEntryList = displayAttributesElem.elementsByTagName( "attributeEntry" );
00324     for ( int i = 0; i < attributeEntryList.size(); ++i )
00325     {
00326       QDomElement attributeEntryElem = attributeEntryList.at( i ).toElement();
00327       int index = attributeEntryElem.attribute( "index", "-1" ).toInt();
00328       if ( index != -1 )
00329       {
00330         mDisplayAttributes.insert( index );
00331       }
00332     }
00333   }
00334 
00335   //restore alias map
00336   mFieldAliasMap.clear();
00337   QDomNodeList aliasMapNodeList = itemElem.elementsByTagName( "attributeAliasMap" );
00338   if ( aliasMapNodeList.size() > 0 )
00339   {
00340     QDomElement attributeAliasMapElem = aliasMapNodeList.at( 0 ).toElement();
00341     QDomNodeList aliasMepEntryList = attributeAliasMapElem.elementsByTagName( "aliasEntry" );
00342     for ( int i = 0; i < aliasMepEntryList.size(); ++i )
00343     {
00344       QDomElement aliasEntryElem = aliasMepEntryList.at( i ).toElement();
00345       int key = aliasEntryElem.attribute( "key", "-1" ).toInt();
00346       QString value = aliasEntryElem.attribute( "value", "" );
00347       mFieldAliasMap.insert( key, value );
00348     }
00349   }
00350 
00351   //restore sort columns
00352   mSortInformation.clear();
00353   QDomElement sortColumnsElem = itemElem.firstChildElement( "sortColumns" );
00354   if ( !sortColumnsElem.isNull() )
00355   {
00356     QDomNodeList columns = sortColumnsElem.elementsByTagName( "column" );
00357     for ( int i = 0; i < columns.size(); ++i )
00358     {
00359       QDomElement columnElem = columns.at( i ).toElement();
00360       int attribute = columnElem.attribute( "index" ).toInt();
00361       bool ascending = columnElem.attribute( "ascending" ) == "true" ? true : false;
00362       mSortInformation.push_back( qMakePair( attribute, ascending ) );
00363     }
00364   }
00365   bool success = tableReadXML( itemElem, doc );
00366   emit itemChanged();
00367   return success;
00368 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines