Quantum GIS API Documentation
1.8
|
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 }