Index: src/app/legend/qgslegendlayer.cpp =================================================================== --- src/app/legend/qgslegendlayer.cpp (Revision 14708) +++ src/app/legend/qgslegendlayer.cpp (Arbeitskopie) @@ -27,6 +27,7 @@ #include "qgsapplication.h" #include "qgsfield.h" +#include "qgsmapcanvasmap.h" #include "qgsmaplayerregistry.h" #include "qgsrasterlayer.h" #include "qgsrenderer.h" @@ -50,6 +51,7 @@ #include #include #include +#include QgsLegendLayer::QgsLegendLayer( QgsMapLayer* layer ) @@ -91,6 +93,7 @@ QgsDebugMsg( "Connecting signals for updating icons, layer " + layer->name() ); connect( layer, SIGNAL( editingStarted() ), this, SLOT( updateIcon() ) ); connect( layer, SIGNAL( editingStopped() ), this, SLOT( updateIcon() ) ); + connect( layer, SIGNAL( layerModified( bool ) ), this, SLOT( updateAfterLayerModification( bool ) ) ); } connect( layer, SIGNAL( layerNameChanged() ), this, SLOT( layerNameChanged() ) ); @@ -184,7 +187,7 @@ -void QgsLegendLayer::vectorLayerSymbology( const QgsVectorLayer* layer, double widthScale ) +void QgsLegendLayer::vectorLayerSymbology( QgsVectorLayer* layer, double widthScale ) { if ( !layer ) { @@ -219,6 +222,13 @@ } } + bool countFeatures = settings.value( "/qgis/showNumberOfFeaturesInLegend", false ).toBool(); + QMap< QgsSymbol*, int > featureCountMap; + if ( countFeatures ) + { + updateItemListCount( layer, sym, featureCountMap ); + } + for ( QList::const_iterator it = sym.begin(); it != sym.end(); ++it ) { QImage img; @@ -258,6 +268,15 @@ values += label; } + if ( countFeatures ) + { + int fCount = featureCountMap[*it]; + if ( fCount >= 0 ) + { + values += ( " (" + QString::number( fCount ) + ")" ); + } + } + QPixmap pix = QPixmap::fromImage( img ); // convert to pixmap itemList.append( qMakePair( values, pix ) ); } @@ -270,13 +289,13 @@ { QSize iconSize( 16, 16 ); -#if 0 // unused + SymbologyList itemList = layer->rendererV2()->legendSymbologyItems( iconSize ); QSettings settings; - bool showClassifiers = settings.value( "/qgis/showLegendClassifiers", false ).toBool(); -#endif + if ( settings.value( "/qgis/showNumberOfFeaturesInLegend", false ).toBool() ) + { + updateItemListCountV2( itemList, layer ); + } - SymbologyList itemList = layer->rendererV2()->legendSymbologyItems( iconSize ); - changeSymbologySettings( layer, itemList ); } @@ -503,3 +522,146 @@ QString name = mLyr.layer()->name(); setText( 0, name ); } + +void QgsLegendLayer::updateAfterLayerModification( bool onlyGeomChanged ) +{ + if ( onlyGeomChanged ) + { + return; + } + + double widthScale = 1.0; + QgsMapCanvas* canvas = QgisApp::instance()->mapCanvas(); + if ( canvas && canvas->map() ) + { + widthScale = canvas->map()->paintDevice().logicalDpiX() / 25.4; + } + refreshSymbology( mLyr.layer()->getLayerID(), widthScale ); +} + +void QgsLegendLayer::updateItemListCountV2( SymbologyList& itemList, QgsVectorLayer* layer ) +{ + if ( !layer ) + { + return; + } + + QgsFeatureRendererV2* renderer = layer->rendererV2(); + if ( !renderer ) + { + return; + } + QgsRenderContext dummyContext; + renderer->startRender( dummyContext, layer ); + + //create map holding the symbol count + QMap< QgsSymbolV2*, int > mSymbolCountMap; + QgsLegendSymbolList symbolList = renderer->legendSymbolItems(); + QgsLegendSymbolList::const_iterator symbolIt = symbolList.constBegin(); + for ( ; symbolIt != symbolList.constEnd(); ++symbolIt ) + { + mSymbolCountMap.insert( symbolIt->second, 0 ); + } + + //go through all features and count the number of occurrences + int nFeatures = layer->pendingFeatureCount(); + QProgressDialog p( tr( "Updating feature count for layer " ) + layer->name(), tr( "Abort" ), 0, nFeatures ); + p.setWindowModality( Qt::WindowModal ); + int featuresCounted = 0; + + + layer->select( layer->pendingAllAttributesList(), QgsRectangle(), false, false ); + QgsFeature f; + QgsSymbolV2* currentSymbol = 0; + + while ( layer->nextFeature( f ) ) + { + currentSymbol = renderer->symbolForFeature( f ); + mSymbolCountMap[currentSymbol] += 1; + ++featuresCounted; + if ( featuresCounted % 50 == 0 ) + { + if ( featuresCounted > nFeatures ) //sometimes the feature count is not correct + { + p.setMaximum( 0 ); + } + p.setValue( featuresCounted ); + if ( p.wasCanceled() ) + { + return; + } + } + } + p.setValue( nFeatures ); + + QMap itemMap; + SymbologyList::const_iterator symbologyIt = itemList.constBegin(); + for ( ; symbologyIt != itemList.constEnd(); ++ symbologyIt ) + { + itemMap.insert( symbologyIt->first, symbologyIt->second ); + } + itemList.clear(); + + // + symbolIt = symbolList.constBegin(); + for ( ; symbolIt != symbolList.constEnd(); ++symbolIt ) + { + QgsSymbolV2* debug = symbolIt->second; + itemList.push_back( qMakePair( symbolIt->first + " (" + QString::number( mSymbolCountMap[symbolIt->second] ) + ")", itemMap[symbolIt->first] ) ); + } +} + +void QgsLegendLayer::updateItemListCount( QgsVectorLayer* layer, const QList& sym, QMap< QgsSymbol*, int >& featureCountMap ) +{ + featureCountMap.clear(); + QList::const_iterator symbolIt = sym.constBegin(); + for ( ; symbolIt != sym.constEnd(); ++symbolIt ) + { + featureCountMap.insert( *symbolIt, 0 ); + } + + QgsRenderer* renderer = const_cast( layer->renderer() ); + if ( !renderer ) + { + return; + } + + //go through all features and count the number of occurrences + int nFeatures = layer->pendingFeatureCount(); + QProgressDialog p( tr( "Updating feature count for layer " ) + layer->name(), tr( "Abort" ), 0, nFeatures ); + p.setWindowModality( Qt::WindowModal ); + int featuresCounted = 0; + + layer->select( layer->pendingAllAttributesList(), QgsRectangle(), false, false ); + QgsFeature f; + QgsSymbol* currentSymbol = 0; + + while ( layer->nextFeature( f ) ) + { + currentSymbol = renderer->symbolForFeature( &f ); + if ( currentSymbol ) + { + featureCountMap[currentSymbol] += 1; + } + ++featuresCounted; + + if ( featuresCounted % 50 == 0 ) + { + if ( featuresCounted > nFeatures ) //sometimes the feature count is not correct + { + p.setMaximum( 0 ); + } + p.setValue( featuresCounted ); + if ( p.wasCanceled() ) //set all entries to -1 (= invalid) + { + QMap< QgsSymbol*, int >::iterator cIt = featureCountMap.begin(); + for ( ; cIt != featureCountMap.end(); ++cIt ) + { + cIt.value() = -1; + } + return; + } + } + } + p.setValue( nFeatures ); +} Index: src/app/legend/qgslegendlayer.h =================================================================== --- src/app/legend/qgslegendlayer.h (Revision 14708) +++ src/app/legend/qgslegendlayer.h (Arbeitskopie) @@ -29,6 +29,7 @@ class QgsLegendPropertyGroup; class QgsMapLayer; class QgsRasterLayer; +class QgsSymbol; class QgsVectorLayer; class QTreeWidget; @@ -87,10 +88,13 @@ /**Layer name has changed - set it also in legend*/ void layerNameChanged(); + /**Update symbology (e.g. to update feature count in the legend after editing operations)*/ + void updateAfterLayerModification( bool onlyGeomChanged ); + protected: /** Prepare and change symbology for vector layer */ - void vectorLayerSymbology( const QgsVectorLayer* mapLayer, double widthScale = 1.0 ); + void vectorLayerSymbology( QgsVectorLayer* mapLayer, double widthScale = 1.0 ); void vectorLayerSymbologyV2( QgsVectorLayer* vlayer ); @@ -100,6 +104,11 @@ /** Removes the symbology items of a layer and adds new ones. */ void changeSymbologySettings( const QgsMapLayer* mapLayer, const SymbologyList& newSymbologyItems ); + /**Adds feature counts to the symbology items (for symbology v2)*/ + void updateItemListCountV2( SymbologyList& itemList, QgsVectorLayer* layer ); + /**Calculates feature count for the individual symbols (old symbology)*/ + void updateItemListCount( QgsVectorLayer* layer, const QList& sym, QMap< QgsSymbol*, int >& featureCountMap ); + QPixmap getOriginalPixmap(); private: Index: src/app/qgsoptions.cpp =================================================================== --- src/app/qgsoptions.cpp (Revision 14708) +++ src/app/qgsoptions.cpp (Arbeitskopie) @@ -246,6 +246,7 @@ chkUseQPixmap->setChecked( !( settings.value( "/qgis/use_qimage_to_render", true ).toBool() ) ); chkAddedVisibility->setChecked( settings.value( "/qgis/new_layers_visible", true ).toBool() ); cbxLegendClassifiers->setChecked( settings.value( "/qgis/showLegendClassifiers", false ).toBool() ); + cbxNFeaturesLegend->setChecked( settings.value( "/qgis/showNumberOfFeaturesInLegend", false ).toBool() ); cbxHideSplash->setChecked( settings.value( "/qgis/hideSplash", false ).toBool() ); cbxAttributeTableDocked->setChecked( settings.value( "/qgis/dockAttributeTable", false ).toBool() ); cbxIdentifyResultsDocked->setChecked( settings.value( "/qgis/dockIdentifyResults", false ).toBool() ); @@ -478,7 +479,7 @@ settings.setValue( "proxy/proxyType", mProxyTypeComboBox->currentText() ); settings.setValue( "cache/directory", mCacheDirectory->text() ); - settings.setValue( "cache/size", QVariant::fromValue( mCacheSize->value()*1024L ) ); + settings.setValue( "cache/size", QVariant::fromValue( mCacheSize->value() * 1024L ) ); //url to exclude from proxys QString proxyExcludeString; @@ -502,6 +503,7 @@ settings.setValue( "/Map/identifyAutoFeatureForm", cbxAutoFeatureForm->isChecked() ); settings.setValue( "/Map/identifyRadius", spinBoxIdentifyValue->value() ); settings.setValue( "/qgis/showLegendClassifiers", cbxLegendClassifiers->isChecked() ); + settings.setValue( "/qgis/showNumberOfFeaturesInLegend", cbxNFeaturesLegend->isChecked() ); settings.setValue( "/qgis/hideSplash", cbxHideSplash->isChecked() ); settings.setValue( "/qgis/dockAttributeTable", cbxAttributeTableDocked->isChecked() ); settings.setValue( "/qgis/attributeTableBehaviour", cmbAttrTableBehaviour->currentIndex() ); Index: src/core/renderer/qgssinglesymbolrenderer.h =================================================================== --- src/core/renderer/qgssinglesymbolrenderer.h (Revision 14708) +++ src/core/renderer/qgssinglesymbolrenderer.h (Arbeitskopie) @@ -64,6 +64,11 @@ const QList symbols() const; /**Returns a deep copy of this renderer*/ QgsRenderer* clone() const; + + /**Returns renderer symbol for a feature + @note: this method was added in version 1.6*/ + QgsSymbol* symbolForFeature( const QgsFeature* f ) { return mSymbol0; } + protected: /**Object containing symbology information*/ QgsSymbol *mSymbol0; Index: src/core/renderer/qgsrenderer.h =================================================================== --- src/core/renderer/qgsrenderer.h (Revision 14708) +++ src/core/renderer/qgsrenderer.h (Arbeitskopie) @@ -112,6 +112,10 @@ This is a hint for QgsVectorLayer to not use the transparency setting on layer level in this cases*/ virtual bool usesTransparency() const {return false;} + /**Returns renderer symbol for a feature. + @note: this method was added in version 1.6*/ + virtual QgsSymbol* symbolForFeature( const QgsFeature* f ) { return 0;} + /**Scales a brush to a given raster scale factor (e.g. for printing)*/ static void scaleBrush( QBrush& b, double rasterScaleFactor ); Index: src/core/renderer/qgsuniquevaluerenderer.h =================================================================== --- src/core/renderer/qgsuniquevaluerenderer.h (Revision 14708) +++ src/core/renderer/qgsuniquevaluerenderer.h (Arbeitskopie) @@ -67,13 +67,16 @@ @note added in 1.4 */ const QMap symbolMap() const { return mSymbols; } QgsRenderer* clone() const; + + /**Returns the symbol for a feature or 0 if there isn't any*/ + QgsSymbol *symbolForFeature( const QgsFeature* f ); + protected: /**Field index used for classification*/ int mClassificationField; /**Symbols for the unique values*/ QMap mSymbols; - /**Returns the symbol for a feature or 0 if there isn't any*/ - QgsSymbol *symbolForFeature( const QgsFeature* f ); + /**Cached copy of all underlying symbols required attribute fields*/ QgsAttributeList mSymbolAttributes; bool mSymbolAttributesDirty; // insertValue was called Index: src/core/renderer/qgsgraduatedsymbolrenderer.h =================================================================== --- src/core/renderer/qgsgraduatedsymbolrenderer.h (Revision 14708) +++ src/core/renderer/qgsgraduatedsymbolrenderer.h (Arbeitskopie) @@ -107,6 +107,8 @@ /**Returns a copy of the renderer (a deep copy on the heap)*/ QgsRenderer* clone() const; + QgsSymbol *symbolForFeature( const QgsFeature* f ); + protected: /** The graduation mode */ Mode mMode; @@ -117,12 +119,8 @@ /**List holding the symbols for the individual classes*/ QList mSymbols; - QgsSymbol *symbolForFeature( const QgsFeature* f ); - /**Cached copy of all underlying symbols required attribute fields*/ QgsAttributeList mSymbolAttributes; - - }; inline void QgsGraduatedSymbolRenderer::addSymbol( QgsSymbol* sy ) Index: src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp =================================================================== --- src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp (Revision 14708) +++ src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp (Arbeitskopie) @@ -75,7 +75,9 @@ mAttrName( attrName ), mCategories( categories ), mSourceSymbol( NULL ), - mSourceColorRamp( NULL ) + mSourceColorRamp( NULL ), + mRotationFieldIdx( -1 ), + mSizeScaleFieldIdx( -1 ) { for ( int i = 0; i < mCategories.count(); ++i ) { Index: src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp =================================================================== --- src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp (Revision 14708) +++ src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp (Arbeitskopie) @@ -100,7 +100,9 @@ mRanges( ranges ), mMode( Custom ), mSourceSymbol( NULL ), - mSourceColorRamp( NULL ) + mSourceColorRamp( NULL ), + mRotationFieldIdx( -1 ), + mSizeScaleFieldIdx( -1 ) { // TODO: check ranges for sanity (NULL symbols, invalid ranges) } @@ -421,13 +423,13 @@ double base = pow( 10.0, floor( log10( cell ) ) ); double unit = base; - if (( 2 * base ) - cell < h * ( cell - unit ) ) + if (( 2 * base ) - cell < h *( cell - unit ) ) { unit = 2.0 * base; - if (( 5 * base ) - cell < adjustBias * ( cell - unit ) ) + if (( 5 * base ) - cell < adjustBias *( cell - unit ) ) { unit = 5.0 * base; - if (( 10.0 * base ) - cell < h * ( cell - unit ) ) + if (( 10.0 * base ) - cell < h *( cell - unit ) ) { unit = 10.0 * base; } Index: src/core/symbology-ng/qgssinglesymbolrendererv2.cpp =================================================================== --- src/core/symbology-ng/qgssinglesymbolrendererv2.cpp (Revision 14708) +++ src/core/symbology-ng/qgssinglesymbolrendererv2.cpp (Arbeitskopie) @@ -12,8 +12,7 @@ #include QgsSingleSymbolRendererV2::QgsSingleSymbolRendererV2( QgsSymbolV2* symbol ) - : QgsFeatureRendererV2( "singleSymbol" ) - , mTempSymbol( NULL ) + : QgsFeatureRendererV2( "singleSymbol" ), mRotationFieldIdx( -1 ), mSizeScaleFieldIdx( -1 ), mTempSymbol( NULL ) { Q_ASSERT( symbol ); mSymbol = symbol; Index: src/ui/qgsoptionsbase.ui =================================================================== --- src/ui/qgsoptionsbase.ui (Revision 14708) +++ src/ui/qgsoptionsbase.ui (Arbeitskopie) @@ -59,9 +59,9 @@ 0 - 0 - 746 - 545 + -29 + 744 + 508 @@ -226,6 +226,13 @@ + + + Show number of features in legend + + + + Create raster icons in legend @@ -344,8 +351,8 @@ 0 0 - 596 - 466 + 744 + 475 @@ -515,8 +522,8 @@ 0 0 - 507 - 480 + 760 + 458 @@ -795,8 +802,8 @@ 0 0 - 264 - 86 + 760 + 458 @@ -870,8 +877,8 @@ 0 0 - 724 - 438 + 760 + 458 @@ -1200,8 +1207,8 @@ 0 0 - 371 - 557 + 744 + 519 @@ -1296,8 +1303,8 @@ 0 0 - 519 - 545 + 744 + 546 @@ -1387,8 +1394,8 @@ 0 0 - 329 - 531 + 744 + 520