|
Quantum GIS API Documentation
master-ce49b66
|
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 QgsAttributes& m1, const QgsAttributes& 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 const QgsFields& fields = mVectorLayer->pendingFields(); 00085 for ( int idx = 0; idx < fields.count(); ++idx ) 00086 { 00087 QString currentAlias = mVectorLayer->attributeAlias( idx ); 00088 if ( !currentAlias.isEmpty() ) 00089 { 00090 mFieldAliasMap.insert( idx, 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<QgsAttributes>& 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 if ( mVectorLayer && mComposerMap->mapRenderer() 00132 && mComposerMap->mapRenderer()->hasCrsTransformEnabled() ) 00133 { 00134 //transform back to layer CRS 00135 QgsCoordinateTransform coordTransform( mVectorLayer->crs(), mComposerMap->mapRenderer()->destinationCrs() ); 00136 try 00137 { 00138 selectionRect = coordTransform.transformBoundingBox( selectionRect, QgsCoordinateTransform::ReverseTransform ); 00139 } 00140 catch ( QgsCsException &cse ) 00141 { 00142 Q_UNUSED( cse ); 00143 return false; 00144 } 00145 } 00146 } 00147 00148 QgsFeatureRequest req; 00149 if ( !selectionRect.isEmpty() ) 00150 { 00151 req.setFilterRect( selectionRect ); 00152 } 00153 req.setFlags( mShowOnlyVisibleFeatures ? QgsFeatureRequest::ExactIntersect : QgsFeatureRequest::NoGeometry ); 00154 if ( mDisplayAttributes.size() > 0 ) 00155 req.setSubsetOfAttributes( mDisplayAttributes.toList() ); 00156 00157 QgsFeature f; 00158 int counter = 0; 00159 QgsFeatureIterator fit = mVectorLayer->getFeatures( req ); 00160 while ( fit.nextFeature( f ) && counter < mMaximumNumberOfFeatures ) 00161 { 00162 attributes.push_back( f.attributes() ); 00163 ++counter; 00164 } 00165 00166 //sort the list, starting with the last attribute 00167 QgsComposerAttributeTableCompare c; 00168 for ( int i = mSortInformation.size() - 1; i >= 0; --i ) 00169 { 00170 c.setSortColumn( mSortInformation.at( i ).first ); 00171 c.setAscending( mSortInformation.at( i ).second ); 00172 qStableSort( attributes.begin(), attributes.end(), c ); 00173 } 00174 return true; 00175 } 00176 00177 QMap<int, QString> QgsComposerAttributeTable::getHeaderLabels() const 00178 { 00179 QMap<int, QString> header; 00180 if ( mVectorLayer ) 00181 { 00182 const QgsFields& vectorFields = mVectorLayer->pendingFields(); 00183 for ( int idx = 0; idx < vectorFields.count(); ++idx ) 00184 { 00185 if ( mDisplayAttributes.size() > 0 && !mDisplayAttributes.contains( idx ) ) 00186 { 00187 continue; 00188 } 00189 header.insert( idx, attributeDisplayName( idx, vectorFields[idx].name() ) ); 00190 } 00191 } 00192 return header; 00193 } 00194 00195 QString QgsComposerAttributeTable::attributeDisplayName( int attributeIndex, const QString& name ) const 00196 { 00197 QMap<int, QString>::const_iterator it = mFieldAliasMap.find( attributeIndex ); 00198 if ( it != mFieldAliasMap.constEnd() ) 00199 { 00200 return it.value(); 00201 } 00202 else 00203 { 00204 return name; 00205 } 00206 } 00207 00208 void QgsComposerAttributeTable::removeLayer( QString layerId ) 00209 { 00210 if ( mVectorLayer ) 00211 { 00212 if ( layerId == mVectorLayer->id() ) 00213 { 00214 mVectorLayer = 0; 00215 } 00216 } 00217 } 00218 00219 void QgsComposerAttributeTable::setSceneRect( const QRectF& rectangle ) 00220 { 00221 double titleHeight = 2 * mGridStrokeWidth + 2 * mLineTextDistance + fontAscentMillimeters( mHeaderFont ); 00222 double attributeHeight = mGridStrokeWidth + 2 * mLineTextDistance + fontAscentMillimeters( mContentFont ); 00223 if (( rectangle.height() - titleHeight ) > 0 ) 00224 { 00225 mMaximumNumberOfFeatures = ( rectangle.height() - titleHeight ) / attributeHeight; 00226 } 00227 else 00228 { 00229 mMaximumNumberOfFeatures = 0; 00230 } 00231 QgsComposerItem::setSceneRect( rectangle ); 00232 emit maximumNumberOfFeaturesChanged( mMaximumNumberOfFeatures ); 00233 } 00234 00235 bool QgsComposerAttributeTable::writeXML( QDomElement& elem, QDomDocument & doc ) const 00236 { 00237 QDomElement composerTableElem = doc.createElement( "ComposerAttributeTable" ); 00238 composerTableElem.setAttribute( "showOnlyVisibleFeatures", mShowOnlyVisibleFeatures ); 00239 composerTableElem.setAttribute( "maxFeatures", mMaximumNumberOfFeatures ); 00240 00241 if ( mComposerMap ) 00242 { 00243 composerTableElem.setAttribute( "composerMap", mComposerMap->id() ); 00244 } 00245 else 00246 { 00247 composerTableElem.setAttribute( "composerMap", -1 ); 00248 } 00249 if ( mVectorLayer ) 00250 { 00251 composerTableElem.setAttribute( "vectorLayer", mVectorLayer->id() ); 00252 } 00253 00254 //display attributes 00255 QDomElement displayAttributesElem = doc.createElement( "displayAttributes" ); 00256 QSet<int>::const_iterator attIt = mDisplayAttributes.constBegin(); 00257 for ( ; attIt != mDisplayAttributes.constEnd(); ++attIt ) 00258 { 00259 QDomElement attributeIndexElem = doc.createElement( "attributeEntry" ); 00260 attributeIndexElem.setAttribute( "index", *attIt ); 00261 displayAttributesElem.appendChild( attributeIndexElem ); 00262 } 00263 composerTableElem.appendChild( displayAttributesElem ); 00264 00265 //alias map 00266 QDomElement aliasMapElem = doc.createElement( "attributeAliasMap" ); 00267 QMap<int, QString>::const_iterator aliasIt = mFieldAliasMap.constBegin(); 00268 for ( ; aliasIt != mFieldAliasMap.constEnd(); ++aliasIt ) 00269 { 00270 QDomElement mapEntryElem = doc.createElement( "aliasEntry" ); 00271 mapEntryElem.setAttribute( "key", aliasIt.key() ); 00272 mapEntryElem.setAttribute( "value", aliasIt.value() ); 00273 aliasMapElem.appendChild( mapEntryElem ); 00274 } 00275 composerTableElem.appendChild( aliasMapElem ); 00276 00277 //sort info 00278 QDomElement sortColumnsElem = doc.createElement( "sortColumns" ); 00279 QList< QPair<int, bool> >::const_iterator sortIt = mSortInformation.constBegin(); 00280 for ( ; sortIt != mSortInformation.constEnd(); ++sortIt ) 00281 { 00282 QDomElement columnElem = doc.createElement( "column" ); 00283 columnElem.setAttribute( "index", QString::number( sortIt->first ) ); 00284 columnElem.setAttribute( "ascending", sortIt->second == true ? "true" : "false" ); 00285 sortColumnsElem.appendChild( columnElem ); 00286 } 00287 composerTableElem.appendChild( sortColumnsElem ); 00288 elem.appendChild( composerTableElem ); 00289 bool ok = tableWriteXML( composerTableElem, doc ); 00290 return ok; 00291 } 00292 00293 bool QgsComposerAttributeTable::readXML( const QDomElement& itemElem, const QDomDocument& doc ) 00294 { 00295 if ( itemElem.isNull() ) 00296 { 00297 return false; 00298 } 00299 00300 mShowOnlyVisibleFeatures = itemElem.attribute( "showOnlyVisibleFeatures", "1" ).toInt(); 00301 00302 //composer map 00303 int composerMapId = itemElem.attribute( "composerMap", "-1" ).toInt(); 00304 if ( composerMapId == -1 ) 00305 { 00306 mComposerMap = 0; 00307 } 00308 00309 if ( composition() ) 00310 { 00311 mComposerMap = composition()->getComposerMapById( composerMapId ); 00312 } 00313 else 00314 { 00315 mComposerMap = 0; 00316 } 00317 00318 //vector layer 00319 QString layerId = itemElem.attribute( "vectorLayer", "not_existing" ); 00320 if ( layerId == "not_existing" ) 00321 { 00322 mVectorLayer = 0; 00323 } 00324 else 00325 { 00326 QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer( layerId ); 00327 if ( ml ) 00328 { 00329 mVectorLayer = dynamic_cast<QgsVectorLayer*>( ml ); 00330 } 00331 } 00332 00333 //restore display attribute map 00334 mDisplayAttributes.clear(); 00335 QDomNodeList displayAttributeList = itemElem.elementsByTagName( "displayAttributes" ); 00336 if ( displayAttributeList.size() > 0 ) 00337 { 00338 QDomElement displayAttributesElem = displayAttributeList.at( 0 ).toElement(); 00339 QDomNodeList attributeEntryList = displayAttributesElem.elementsByTagName( "attributeEntry" ); 00340 for ( int i = 0; i < attributeEntryList.size(); ++i ) 00341 { 00342 QDomElement attributeEntryElem = attributeEntryList.at( i ).toElement(); 00343 int index = attributeEntryElem.attribute( "index", "-1" ).toInt(); 00344 if ( index != -1 ) 00345 { 00346 mDisplayAttributes.insert( index ); 00347 } 00348 } 00349 } 00350 00351 //restore alias map 00352 mFieldAliasMap.clear(); 00353 QDomNodeList aliasMapNodeList = itemElem.elementsByTagName( "attributeAliasMap" ); 00354 if ( aliasMapNodeList.size() > 0 ) 00355 { 00356 QDomElement attributeAliasMapElem = aliasMapNodeList.at( 0 ).toElement(); 00357 QDomNodeList aliasMepEntryList = attributeAliasMapElem.elementsByTagName( "aliasEntry" ); 00358 for ( int i = 0; i < aliasMepEntryList.size(); ++i ) 00359 { 00360 QDomElement aliasEntryElem = aliasMepEntryList.at( i ).toElement(); 00361 int key = aliasEntryElem.attribute( "key", "-1" ).toInt(); 00362 QString value = aliasEntryElem.attribute( "value", "" ); 00363 mFieldAliasMap.insert( key, value ); 00364 } 00365 } 00366 00367 //restore sort columns 00368 mSortInformation.clear(); 00369 QDomElement sortColumnsElem = itemElem.firstChildElement( "sortColumns" ); 00370 if ( !sortColumnsElem.isNull() ) 00371 { 00372 QDomNodeList columns = sortColumnsElem.elementsByTagName( "column" ); 00373 for ( int i = 0; i < columns.size(); ++i ) 00374 { 00375 QDomElement columnElem = columns.at( i ).toElement(); 00376 int attribute = columnElem.attribute( "index" ).toInt(); 00377 bool ascending = columnElem.attribute( "ascending" ) == "true" ? true : false; 00378 mSortInformation.push_back( qMakePair( attribute, ascending ) ); 00379 } 00380 } 00381 bool success = tableReadXML( itemElem, doc ); 00382 00383 //must be done here because tableReadXML->setSceneRect changes mMaximumNumberOfFeatures 00384 mMaximumNumberOfFeatures = itemElem.attribute( "maxFeatures", "5" ).toInt(); 00385 00386 emit itemChanged(); 00387 return success; 00388 }