Skip to content

Commit 038acbc

Browse files
committed
vector feature counts moved to vector layer, enabled feature counts in composer legend, fixes #6237
1 parent 4b789b8 commit 038acbc

12 files changed

+295
-77
lines changed

images/images.qrc

+1
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@
163163
<file>themes/default/mActionSimplify.png</file>
164164
<file>themes/default/mActionSplitFeatures.png</file>
165165
<file>themes/default/mActionSplitFeatures.svg</file>
166+
<file>themes/default/mActionSum.png</file>
166167
<file>themes/default/mActionTextAnnotation.png</file>
167168
<file>themes/default/mActionToggleEditing.png</file>
168169
<file>themes/default/mActionUndo.png</file>

images/themes/default/mActionSum.png

697 Bytes
Loading

src/app/composer/qgscomposerlegendwidget.cpp

+77
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "qgscomposerlegendwidget.h"
1919
#include "qgscomposerlegend.h"
20+
#include "qgscomposerlegenditem.h"
2021
#include "qgscomposerlegenditemdialog.h"
2122
#include "qgscomposerlegendlayersdialog.h"
2223
#include "qgscomposeritemwidget.h"
@@ -26,8 +27,10 @@
2627
#include "qgsapplegendinterface.h"
2728
#include "qgisapp.h"
2829
#include "qgsmapcanvas.h"
30+
#include "qgsmaplayerregistry.h"
2931
#include "qgsmaprenderer.h"
3032
#include "qgsapplication.h"
33+
#include "qgsvectorlayer.h"
3134

3235
#include <QMessageBox>
3336

@@ -41,6 +44,7 @@ QgsComposerLegendWidget::QgsComposerLegendWidget( QgsComposerLegend* legend ): m
4144
mRemoveToolButton->setIcon( QIcon( QgsApplication::iconPath( "symbologyRemove.png" ) ) );
4245
mMoveUpToolButton->setIcon( QIcon( QgsApplication::iconPath( "symbologyUp.png" ) ) );
4346
mMoveDownToolButton->setIcon( QIcon( QgsApplication::iconPath( "symbologyDown.png" ) ) );
47+
mCountToolButton->setIcon( QIcon( QgsApplication::iconPath( "mActionSum.png" ) ) );
4448

4549
//add widget for item properties
4650
QgsComposerItemWidget* itemPropertiesWidget = new QgsComposerItemWidget( this, legend );
@@ -59,6 +63,9 @@ QgsComposerLegendWidget::QgsComposerLegendWidget( QgsComposerLegend* legend ): m
5963

6064
setGuiElements();
6165
connect( mItemTreeView, SIGNAL( itemChanged() ), this, SLOT( setGuiElements() ) );
66+
67+
connect( mItemTreeView->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ),
68+
this, SLOT( selectedChanged( const QModelIndex &, const QModelIndex & ) ) );
6269
}
6370

6471
QgsComposerLegendWidget::QgsComposerLegendWidget(): mLegend( 0 )
@@ -612,6 +619,52 @@ void QgsComposerLegendWidget::on_mUpdatePushButton_clicked()
612619
mLegend->endCommand();
613620
}
614621

622+
void QgsComposerLegendWidget::on_mCountToolButton_clicked( bool checked )
623+
{
624+
QgsDebugMsg( "Entered." );
625+
if ( !mLegend )
626+
{
627+
return;
628+
}
629+
630+
//get current item
631+
QStandardItemModel* itemModel = qobject_cast<QStandardItemModel *>( mItemTreeView->model() );
632+
if ( !itemModel )
633+
{
634+
return;
635+
}
636+
637+
//get current item
638+
QModelIndex currentIndex = mItemTreeView->currentIndex();
639+
if ( !currentIndex.isValid() )
640+
{
641+
return;
642+
}
643+
644+
QStandardItem* currentItem = itemModel->itemFromIndex( currentIndex );
645+
if ( !currentItem )
646+
{
647+
return;
648+
}
649+
650+
QgsComposerLayerItem* layerItem = dynamic_cast<QgsComposerLayerItem *>( currentItem );
651+
652+
if ( !layerItem )
653+
{
654+
return;
655+
}
656+
657+
mLegend->beginCommand( tr( "Legend updated" ) );
658+
layerItem->setShowFeatureCount( checked );
659+
if ( mLegend->model() )
660+
{
661+
mLegend->model()->updateItem( currentItem );
662+
}
663+
mLegend->update();
664+
mLegend->adjustBoxSize();
665+
mLegend->endCommand();
666+
}
667+
615668
void QgsComposerLegendWidget::on_mUpdateAllPushButton_clicked()
616669
{
617670
updateLegend();
@@ -715,3 +768,27 @@ void QgsComposerLegendWidget::showEvent( QShowEvent * event )
715768
refreshMapComboBox();
716769
QWidget::showEvent( event );
717770
}
771+
772+
void QgsComposerLegendWidget::selectedChanged( const QModelIndex & current, const QModelIndex & previous )
773+
{
774+
Q_UNUSED( previous );
775+
QgsDebugMsg( "Entered" );
776+
777+
mCountToolButton->setChecked( false );
778+
mCountToolButton->setEnabled( false );
779+
780+
QStandardItemModel* itemModel = qobject_cast<QStandardItemModel *>( mItemTreeView->model() );
781+
if ( !itemModel ) return;
782+
783+
QStandardItem* currentItem = itemModel->itemFromIndex( current );
784+
if ( !currentItem ) return;
785+
786+
QgsComposerLayerItem* layerItem = dynamic_cast<QgsComposerLayerItem *>( currentItem );
787+
if ( !layerItem ) return;
788+
789+
QgsVectorLayer* vectorLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( layerItem->layerID() ) );
790+
if ( !vectorLayer ) return;
791+
792+
mCountToolButton->setChecked( layerItem->showFeatureCount() );
793+
mCountToolButton->setEnabled( true );
794+
}

src/app/composer/qgscomposerlegendwidget.h

+3
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,13 @@ class QgsComposerLegendWidget: public QWidget, private Ui::QgsComposerLegendWidg
6161
void on_mRemoveToolButton_clicked();
6262
void on_mAddToolButton_clicked();
6363
void on_mEditPushButton_clicked();
64+
void on_mCountToolButton_clicked( bool checked );
6465
void on_mUpdatePushButton_clicked();
6566
void on_mUpdateAllPushButton_clicked();
6667
void on_mAddGroupButton_clicked();
6768

69+
void selectedChanged( const QModelIndex & current, const QModelIndex & previous );
70+
6871
protected:
6972
void showEvent( QShowEvent * event );
7073

src/app/legend/qgslegendlayer.cpp

+13-55
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ QgsLegendLayer::QgsLegendLayer( QgsMapLayer* layer )
5151
, mLyr( layer )
5252
, mDrawingOrder( -1 )
5353
, mShowFeatureCount( false )
54-
, mFeatureCount( -1 )
5554
{
5655
mType = LEGEND_LAYER;
5756

@@ -558,12 +557,13 @@ QgsMapCanvasLayer& QgsLegendLayer::canvasLayer()
558557
return mLyr;
559558
}
560559

561-
QString QgsLegendLayer::label() const
560+
QString QgsLegendLayer::label()
562561
{
563562
QString name = mLyr.layer()->name();
564-
if ( mShowFeatureCount && mFeatureCount >= 0 )
563+
QgsVectorLayer *vlayer = dynamic_cast<QgsVectorLayer *>( mLyr.layer() );
564+
if ( mShowFeatureCount && vlayer && vlayer->featureCount() >= 0 )
565565
{
566-
name += QString( " [%1]" ).arg( mFeatureCount );
566+
name += QString( " [%1]" ).arg( vlayer->featureCount() );
567567
}
568568
return name;
569569
}
@@ -585,7 +585,7 @@ void QgsLegendLayer::afterEdit()
585585
layerNameChanged();
586586
}
587587

588-
QString QgsLegendLayer::layerName() const
588+
QString QgsLegendLayer::layerName()
589589
{
590590
// The text could be edited (Rename), in that case we have to return the new name
591591
if ( text( 0 ) != label() && text( 0 ) != mLyr.layer()->name() )
@@ -618,7 +618,6 @@ void QgsLegendLayer::updateAfterLayerModification( bool onlyGeomChanged )
618618

619619
void QgsLegendLayer::updateItemListCountV2( SymbologyList& itemList, QgsVectorLayer* layer )
620620
{
621-
mFeatureCount = -1;
622621
if ( !layer )
623622
{
624623
return;
@@ -629,70 +628,29 @@ void QgsLegendLayer::updateItemListCountV2( SymbologyList& itemList, QgsVectorLa
629628
{
630629
return;
631630
}
632-
QgsRenderContext dummyContext;
633-
renderer->startRender( dummyContext, layer );
634631

635-
//create map holding the symbol count
636-
QMap< QgsSymbolV2*, int > symbolCountMap;
637-
QgsLegendSymbolList symbolList = renderer->legendSymbolItems();
638-
QgsLegendSymbolList::const_iterator symbolIt = symbolList.constBegin();
639-
for ( ; symbolIt != symbolList.constEnd(); ++symbolIt )
640-
{
641-
symbolCountMap.insert( symbolIt->second, 0 );
642-
}
643-
644-
//go through all features and count the number of occurrences
645-
int nFeatures = layer->pendingFeatureCount();
646-
QProgressDialog p( tr( "Updating feature count for layer %1" ).arg( layer->name() ), tr( "Abort" ), 0, nFeatures );
647-
p.setWindowModality( Qt::WindowModal );
648-
int featuresCounted = 0;
649-
650-
layer->select( layer->pendingAllAttributesList(), QgsRectangle(), false, false );
651-
QgsFeature f;
652-
653-
// Renderer (rule based) may depend on context scale, with scale is ignored if 0
654-
QgsRenderContext renderContext;
655-
renderContext.setRendererScale( 0 );
656-
renderer->startRender( renderContext, layer );
657-
658-
while ( layer->nextFeature( f ) )
632+
// Count features
633+
if ( !layer->countSymbolFeatures() )
659634
{
660-
QgsSymbolV2List symbolList = renderer->symbolsForFeature( f );
661-
for ( QgsSymbolV2List::iterator symbolIt = symbolList.begin(); symbolIt != symbolList.end(); ++symbolIt )
662-
{
663-
symbolCountMap[*symbolIt] += 1;
664-
}
665-
++featuresCounted;
666-
if ( featuresCounted % 50 == 0 )
667-
{
668-
if ( featuresCounted > nFeatures ) //sometimes the feature count is not correct
669-
{
670-
p.setMaximum( 0 );
671-
}
672-
p.setValue( featuresCounted );
673-
if ( p.wasCanceled() )
674-
{
675-
mFeatureCount = -1;
676-
return;
677-
}
678-
}
679-
mFeatureCount++;
635+
QgsDebugMsg( "Cannot get feature counts" );
636+
return;
680637
}
681-
renderer->stopRender( renderContext );
682-
p.setValue( nFeatures );
683638

684639
QMap<QString, QPixmap> itemMap;
685640
SymbologyList::const_iterator symbologyIt = itemList.constBegin();
686641
for ( ; symbologyIt != itemList.constEnd(); ++ symbologyIt )
687642
{
688643
itemMap.insert( symbologyIt->first, symbologyIt->second );
689644
}
645+
690646
itemList.clear();
691647

648+
QgsLegendSymbolList symbolList = renderer->legendSymbolItems();
649+
QgsLegendSymbolList::const_iterator symbolIt = symbolList.constBegin();
692650
symbolIt = symbolList.constBegin();
693651
for ( ; symbolIt != symbolList.constEnd(); ++symbolIt )
694652
{
695-
itemList.push_back( qMakePair( symbolIt->first + " [" + QString::number( symbolCountMap[symbolIt->second] ) + "]", itemMap[symbolIt->first] ) );
653+
itemList.push_back( qMakePair( symbolIt->first + " [" + QString::number( layer->featureCount( symbolIt->second ) ) + "]", itemMap[symbolIt->first] ) );
696654
}
697655
}
698656

src/app/legend/qgslegendlayer.h

+2-5
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class QgsLegendLayer : public QgsLegendItem
7676
int drawingOrder() const { return mDrawingOrder; }
7777

7878
/** Get layer name currently set in legend */
79-
QString layerName() const;
79+
QString layerName();
8080

8181
/**Called before edit*/
8282
void beforeEdit();
@@ -130,7 +130,7 @@ class QgsLegendLayer : public QgsLegendItem
130130
void setupFont();
131131

132132
/** Label, may be layer name or layer name + [feature count] */
133-
QString label() const;
133+
QString label();
134134

135135
protected:
136136

@@ -142,9 +142,6 @@ class QgsLegendLayer : public QgsLegendItem
142142

143143
/**True if number of features per legend class should is shown in the legend items*/
144144
bool mShowFeatureCount;
145-
146-
/** Last vector features count, -1 if not counted */
147-
int mFeatureCount;
148145
};
149146

150147
#endif

src/core/composer/qgscomposerlegenditem.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -288,10 +288,12 @@ void QgsComposerRasterSymbolItem::readXML( const QDomElement& itemElem, bool xSe
288288
////////////////////QgsComposerLayerItem
289289

290290
QgsComposerLayerItem::QgsComposerLayerItem(): QgsComposerLegendItem()
291+
, mShowFeatureCount( false )
291292
{
292293
}
293294

294295
QgsComposerLayerItem::QgsComposerLayerItem( const QString& text ): QgsComposerLegendItem( text )
296+
, mShowFeatureCount( false )
295297
{
296298
}
297299

@@ -312,6 +314,7 @@ void QgsComposerLayerItem::writeXML( QDomElement& elem, QDomDocument& doc ) cons
312314
QDomElement layerItemElem = doc.createElement( "LayerItem" );
313315
layerItemElem.setAttribute( "layerId", mLayerID );
314316
layerItemElem.setAttribute( "text", text() );
317+
layerItemElem.setAttribute( "showFeatureCount", showFeatureCount() );
315318
writeXMLChildren( layerItemElem, doc );
316319
elem.appendChild( layerItemElem );
317320
}
@@ -324,6 +327,7 @@ void QgsComposerLayerItem::readXML( const QDomElement& itemElem, bool xServerAva
324327
}
325328
setText( itemElem.attribute( "text", "" ) );
326329
setLayerID( itemElem.attribute( "layerId", "" ) );
330+
setShowFeatureCount( itemElem.attribute( "showFeatureCount", "" ) == "1" ? true : false );
327331

328332
//now call readXML for all the child items
329333
QDomNodeList childList = itemElem.childNodes();

src/core/composer/qgscomposerlegenditem.h

+5
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,13 @@ class CORE_EXPORT QgsComposerLayerItem: public QgsComposerLegendItem
148148
void setLayerID( const QString& id ) { mLayerID = id; }
149149
QString layerID() const { return mLayerID; }
150150

151+
void setShowFeatureCount( bool show ) { mShowFeatureCount = show; }
152+
bool showFeatureCount() const { return mShowFeatureCount; }
153+
151154
private:
152155
QString mLayerID;
156+
// Show vector feature counts
157+
bool mShowFeatureCount;
153158
};
154159

155160
class CORE_EXPORT QgsComposerGroupItem: public QgsComposerLegendItem

src/core/composer/qgslegendmodel.cpp

+26-4
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,9 @@ QStandardItem* QgsLegendModel::addGroup( QString text, int position )
136136

137137
int QgsLegendModel::addVectorLayerItemsV2( QStandardItem* layerItem, QgsVectorLayer* vlayer )
138138
{
139-
if ( !layerItem || !vlayer )
139+
QgsComposerLayerItem* lItem = dynamic_cast<QgsComposerLayerItem*>( layerItem );
140+
141+
if ( !layerItem || !lItem || !vlayer )
140142
{
141143
return 1;
142144
}
@@ -147,11 +149,24 @@ int QgsLegendModel::addVectorLayerItemsV2( QStandardItem* layerItem, QgsVectorLa
147149
return 2;
148150
}
149151

152+
if ( lItem->showFeatureCount() )
153+
{
154+
if ( !vlayer->countSymbolFeatures() )
155+
{
156+
QgsDebugMsg( "Cannot get feature counts" );
157+
}
158+
}
159+
150160
QgsLegendSymbolList lst = renderer->legendSymbolItems();
151161
QgsLegendSymbolList::const_iterator symbolIt = lst.constBegin();
152162
for ( ; symbolIt != lst.constEnd(); ++symbolIt )
153163
{
154-
QgsComposerSymbolV2Item* currentSymbolItem = new QgsComposerSymbolV2Item( symbolIt->first );
164+
QString label = symbolIt->first;
165+
if ( lItem->showFeatureCount() )
166+
{
167+
label += QString( " [%1]" ).arg( vlayer->featureCount( symbolIt->second ) );
168+
}
169+
QgsComposerSymbolV2Item* currentSymbolItem = new QgsComposerSymbolV2Item( label );
155170
currentSymbolItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
156171
if ( symbolIt->second )
157172
{
@@ -282,6 +297,7 @@ void QgsLegendModel::updateItem( QStandardItem* item )
282297

283298
void QgsLegendModel::updateLayer( QStandardItem* layerItem )
284299
{
300+
QgsDebugMsg( "Entered." );
285301
QgsComposerLayerItem* lItem = dynamic_cast<QgsComposerLayerItem*>( layerItem );
286302
if ( lItem )
287303
{
@@ -295,10 +311,16 @@ void QgsLegendModel::updateLayer( QStandardItem* layerItem )
295311
lItem->removeRow( i );
296312
}
297313

314+
QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer*>( mapLayer );
315+
298316
//set layer name as item text
299-
layerItem->setText( mapLayer->name() );
317+
QString label = mapLayer->name();
318+
if ( vLayer && lItem->showFeatureCount() )
319+
{
320+
label += QString( " [%1]" ).arg( vLayer->featureCount() );
321+
}
322+
layerItem->setText( label );
300323

301-
QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer*>( mapLayer );
302324
if ( vLayer )
303325
{
304326
if ( vLayer->isUsingRendererV2() )

0 commit comments

Comments
 (0)