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