[QGIS Commit] r14714 - in trunk/qgis/src: app/legend core/renderer
core/symbology-ng
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Fri Nov 19 08:24:20 EST 2010
Author: mhugent
Date: 2010-11-19 05:24:20 -0800 (Fri, 19 Nov 2010)
New Revision: 14714
Modified:
trunk/qgis/src/app/legend/qgslegend.cpp
trunk/qgis/src/app/legend/qgslegendlayer.cpp
trunk/qgis/src/app/legend/qgslegendlayer.h
trunk/qgis/src/core/renderer/qgsgraduatedsymbolrenderer.h
trunk/qgis/src/core/renderer/qgsrenderer.h
trunk/qgis/src/core/renderer/qgssinglesymbolrenderer.h
trunk/qgis/src/core/renderer/qgsuniquevaluerenderer.h
trunk/qgis/src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp
trunk/qgis/src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp
trunk/qgis/src/core/symbology-ng/qgssinglesymbolrendererv2.cpp
Log:
[FEATURE]: Add possibility to show number of features in legend classes. Accessible via right click legend menu
Modified: trunk/qgis/src/app/legend/qgslegend.cpp
===================================================================
--- trunk/qgis/src/app/legend/qgslegend.cpp 2010-11-19 07:51:19 UTC (rev 14713)
+++ trunk/qgis/src/app/legend/qgslegend.cpp 2010-11-19 13:24:20 UTC (rev 14714)
@@ -849,6 +849,7 @@
{
QDomElement legendlayernode = document.createElement( "legendlayer" );
legendlayernode.setAttribute( "open", isItemExpanded( item ) ? "true" : "false" );
+
Qt::CheckState cstate = item->checkState( 0 );
if ( cstate == Qt::Checked )
{
@@ -900,6 +901,7 @@
// to keep it compatible with older projects
QgsLegendLayer *ll = dynamic_cast<QgsLegendLayer *>( item );
QgsMapLayer* layer = ll->layer();
+ legendlayernode.setAttribute( "showFeatureCount", ll->showFeatureCount() );
QDomElement layerfilegroupnode = document.createElement( "filegroup" );
layerfilegroupnode.setAttribute( "open", isItemExpanded( item ) ? "true" : "false" );
@@ -1060,6 +1062,7 @@
// create the item
QgsLegendLayer* ll = new QgsLegendLayer( theMapLayer );
+ ll->setShowFeatureCount( childelem.attribute( "showFeatureCount", "0" ).toInt(), false );
// load layer's visibility and 'show in overview' flag
ll->setInOverview( atoi( fileElem.attribute( "isInOverview" ).toUtf8() ) );
Modified: trunk/qgis/src/app/legend/qgslegendlayer.cpp
===================================================================
--- trunk/qgis/src/app/legend/qgslegendlayer.cpp 2010-11-19 07:51:19 UTC (rev 14713)
+++ trunk/qgis/src/app/legend/qgslegendlayer.cpp 2010-11-19 13:24:20 UTC (rev 14714)
@@ -27,6 +27,7 @@
#include "qgsapplication.h"
#include "qgsfield.h"
+#include "qgsmapcanvasmap.h"
#include "qgsmaplayerregistry.h"
#include "qgsrasterlayer.h"
#include "qgsrenderer.h"
@@ -50,11 +51,12 @@
#include <QPainter>
#include <QSettings>
#include <QFileDialog>
+#include <QProgressDialog>
QgsLegendLayer::QgsLegendLayer( QgsMapLayer* layer )
: QgsLegendItem( ),
- mLyr( layer )
+ mLyr( layer ), mShowFeatureCount( false )
{
mType = LEGEND_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,12 @@
}
}
+ QMap< QgsSymbol*, int > featureCountMap;
+ if ( mShowFeatureCount )
+ {
+ updateItemListCount( layer, sym, featureCountMap );
+ }
+
for ( QList<QgsSymbol*>::const_iterator it = sym.begin(); it != sym.end(); ++it )
{
QImage img;
@@ -258,6 +267,15 @@
values += label;
}
+ if ( mShowFeatureCount )
+ {
+ 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,12 +288,11 @@
{
QSize iconSize( 16, 16 );
-#if 0 // unused
- QSettings settings;
- bool showClassifiers = settings.value( "/qgis/showLegendClassifiers", false ).toBool();
-#endif
-
SymbologyList itemList = layer->rendererV2()->legendSymbologyItems( iconSize );
+ if ( mShowFeatureCount )
+ {
+ updateItemListCountV2( itemList, layer );
+ }
changeSymbologySettings( layer, itemList );
}
@@ -436,6 +453,12 @@
if ( !vlayer->isEditable() && vlayer->dataProvider()->supportsSubsetString() )
theMenu.addAction( tr( "&Query..." ), QgisApp::instance(), SLOT( layerSubsetString() ) );
+ //show number of features in legend if requested
+ QAction* showNFeaturesAction = new QAction( tr( "Show feature count" ), &theMenu );
+ showNFeaturesAction->setCheckable( true );
+ showNFeaturesAction->setChecked( mShowFeatureCount );
+ QObject::connect( showNFeaturesAction, SIGNAL( toggled( bool ) ), this, SLOT( setShowFeatureCount( bool ) ) );
+ theMenu.addAction( showNFeaturesAction );
theMenu.addSeparator();
}
@@ -503,3 +526,158 @@
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<QString, QPixmap> 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<QgsSymbol*>& sym, QMap< QgsSymbol*, int >& featureCountMap )
+{
+ featureCountMap.clear();
+ QList<QgsSymbol*>::const_iterator symbolIt = sym.constBegin();
+ for ( ; symbolIt != sym.constEnd(); ++symbolIt )
+ {
+ featureCountMap.insert( *symbolIt, 0 );
+ }
+
+ QgsRenderer* renderer = const_cast<QgsRenderer*>( 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 );
+}
+
+void QgsLegendLayer::setShowFeatureCount( bool show, bool update )
+{
+ if ( show != mShowFeatureCount )
+ {
+ mShowFeatureCount = show;
+ if ( update )
+ {
+ updateAfterLayerModification( false );
+ }
+ }
+}
Modified: trunk/qgis/src/app/legend/qgslegendlayer.h
===================================================================
--- trunk/qgis/src/app/legend/qgslegendlayer.h 2010-11-19 07:51:19 UTC (rev 14713)
+++ trunk/qgis/src/app/legend/qgslegendlayer.h 2010-11-19 13:24:20 UTC (rev 14714)
@@ -29,6 +29,7 @@
class QgsLegendPropertyGroup;
class QgsMapLayer;
class QgsRasterLayer;
+class QgsSymbol;
class QgsVectorLayer;
class QTreeWidget;
@@ -87,10 +88,16 @@
/**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 );
+
+ void setShowFeatureCount( bool show, bool update = true );
+ bool showFeatureCount() const { return mShowFeatureCount; }
+
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 +107,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<QgsSymbol*>& sym, QMap< QgsSymbol*, int >& featureCountMap );
+
QPixmap getOriginalPixmap();
private:
@@ -113,6 +125,9 @@
/** layer identified by its layer id */
QgsMapCanvasLayer mLyr;
+
+ /**True if number of features per legend class should is shown in the legend items*/
+ bool mShowFeatureCount;
};
#endif
Modified: trunk/qgis/src/core/renderer/qgsgraduatedsymbolrenderer.h
===================================================================
--- trunk/qgis/src/core/renderer/qgsgraduatedsymbolrenderer.h 2010-11-19 07:51:19 UTC (rev 14713)
+++ trunk/qgis/src/core/renderer/qgsgraduatedsymbolrenderer.h 2010-11-19 13:24:20 UTC (rev 14714)
@@ -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<QgsSymbol*> mSymbols;
- QgsSymbol *symbolForFeature( const QgsFeature* f );
-
/**Cached copy of all underlying symbols required attribute fields*/
QgsAttributeList mSymbolAttributes;
-
-
};
inline void QgsGraduatedSymbolRenderer::addSymbol( QgsSymbol* sy )
Modified: trunk/qgis/src/core/renderer/qgsrenderer.h
===================================================================
--- trunk/qgis/src/core/renderer/qgsrenderer.h 2010-11-19 07:51:19 UTC (rev 14713)
+++ trunk/qgis/src/core/renderer/qgsrenderer.h 2010-11-19 13:24:20 UTC (rev 14714)
@@ -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 );
Modified: trunk/qgis/src/core/renderer/qgssinglesymbolrenderer.h
===================================================================
--- trunk/qgis/src/core/renderer/qgssinglesymbolrenderer.h 2010-11-19 07:51:19 UTC (rev 14713)
+++ trunk/qgis/src/core/renderer/qgssinglesymbolrenderer.h 2010-11-19 13:24:20 UTC (rev 14714)
@@ -64,6 +64,11 @@
const QList<QgsSymbol*> 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;
Modified: trunk/qgis/src/core/renderer/qgsuniquevaluerenderer.h
===================================================================
--- trunk/qgis/src/core/renderer/qgsuniquevaluerenderer.h 2010-11-19 07:51:19 UTC (rev 14713)
+++ trunk/qgis/src/core/renderer/qgsuniquevaluerenderer.h 2010-11-19 13:24:20 UTC (rev 14714)
@@ -67,13 +67,16 @@
@note added in 1.4 */
const QMap<QString, QgsSymbol*> 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<QString, QgsSymbol*> 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
Modified: trunk/qgis/src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp
===================================================================
--- trunk/qgis/src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp 2010-11-19 07:51:19 UTC (rev 14713)
+++ trunk/qgis/src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp 2010-11-19 13:24:20 UTC (rev 14714)
@@ -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 )
{
Modified: trunk/qgis/src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp
===================================================================
--- trunk/qgis/src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp 2010-11-19 07:51:19 UTC (rev 14713)
+++ trunk/qgis/src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp 2010-11-19 13:24:20 UTC (rev 14714)
@@ -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;
}
Modified: trunk/qgis/src/core/symbology-ng/qgssinglesymbolrendererv2.cpp
===================================================================
--- trunk/qgis/src/core/symbology-ng/qgssinglesymbolrendererv2.cpp 2010-11-19 07:51:19 UTC (rev 14713)
+++ trunk/qgis/src/core/symbology-ng/qgssinglesymbolrendererv2.cpp 2010-11-19 13:24:20 UTC (rev 14714)
@@ -12,8 +12,7 @@
#include <QDomElement>
QgsSingleSymbolRendererV2::QgsSingleSymbolRendererV2( QgsSymbolV2* symbol )
- : QgsFeatureRendererV2( "singleSymbol" )
- , mTempSymbol( NULL )
+ : QgsFeatureRendererV2( "singleSymbol" ), mRotationFieldIdx( -1 ), mSizeScaleFieldIdx( -1 ), mTempSymbol( NULL )
{
Q_ASSERT( symbol );
mSymbol = symbol;
More information about the QGIS-commit
mailing list