Skip to content

Commit e1a0c21

Browse files
committed
Raster and plugin layer symbology, show feature count for vectors
1 parent 69da2b3 commit e1a0c21

9 files changed

+228
-31
lines changed

src/app/qgisapp.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2217,6 +2217,10 @@ QMenu* QgsAppLayerTreeViewMenuProvider::createContextMenu()
22172217
{
22182218
menu->addAction( actions->actionZoomToLayer(mCanvas, menu) );
22192219
menu->addAction( actions->actionShowInOverview(menu) );
2220+
2221+
QgsMapLayer* layer = static_cast<QgsLayerTreeLayer*>(node)->layer();
2222+
if (layer && layer->type() == QgsMapLayer::VectorLayer)
2223+
menu->addAction( actions->actionShowFeatureCount(menu) );
22202224
}
22212225

22222226
menu->addAction( actions->actionRemoveGroupOrLayer(menu) );

src/core/layertree/qgslayertreenode.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ void QgsLayerTreeLayer::registryLayersAdded(QList<QgsMapLayer*> layers)
524524
{
525525
mLayer = l;
526526
disconnect(QgsMapLayerRegistry::instance(), SIGNAL(layersAdded(QList<QgsMapLayer*>)), this, SLOT(registryLayersAdded(QList<QgsMapLayer*>)));
527+
emit layerLoaded();
527528
break;
528529
}
529530
}

src/core/layertree/qgslayertreenode.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ class QgsLayerTreeLayer : public QgsLayerTreeNode
123123
protected slots:
124124
void registryLayersAdded(QList<QgsMapLayer*> layers);
125125

126+
signals:
127+
//! emitted when a previously unavailable layer got loaded
128+
void layerLoaded();
129+
126130
protected:
127131
void attachToLayer();
128132

src/core/raster/qgsrasterlayer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ void QgsRasterLayer::draw( QPainter * theQPainter,
304304
QgsDebugMsg( QString( "total raster draw time (ms): %1" ).arg( time.elapsed(), 5 ) );
305305
} //end of draw method
306306

307-
QList< QPair< QString, QColor > > QgsRasterLayer::legendSymbologyItems() const
307+
QgsLegendColorList QgsRasterLayer::legendSymbologyItems() const
308308
{
309309
QList< QPair< QString, QColor > > symbolList;
310310
QgsRasterRenderer *renderer = mPipe.renderer();

src/core/raster/qgsrasterlayer.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ class QLibrary;
5353
class QPixmap;
5454
class QSlider;
5555

56+
typedef QList < QPair< QString, QColor > > QgsLegendColorList;
57+
5658
/** \ingroup core
5759
* This class provides qgis with the ability to render raster datasets
5860
* onto the mapcanvas.
@@ -297,7 +299,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
297299

298300
/**Returns a list with classification items (Text and color)
299301
@note this method was added in version 1.8*/
300-
QList< QPair< QString, QColor > > legendSymbologyItems() const;
302+
QgsLegendColorList legendSymbologyItems() const;
301303

302304
/** \brief Obtain GDAL Metadata for this layer */
303305
QString metadata();

src/gui/layertree/qgslayertreemodel.cpp

Lines changed: 176 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
#include <QTextStream>
77

88
#include "qgsdataitem.h"
9+
#include "qgspluginlayer.h"
10+
#include "qgsrasterlayer.h"
911
#include "qgsrendererv2.h"
12+
#include "qgssymbollayerv2utils.h"
1013
#include "qgsvectorlayer.h"
1114

1215

@@ -36,6 +39,11 @@ void QgsLayerTreeModel::connectToNode(QgsLayerTreeNode* node)
3639
connect(node, SIGNAL(removedChildren(int,int)), this, SLOT(nodeRemovedChildren()));
3740
connect(node, SIGNAL(visibilityChanged(Qt::CheckState)), this, SLOT(nodeVisibilityChanded()));
3841

42+
if (node->nodeType() == QgsLayerTreeNode::NodeLayer && testFlag(ShowSymbology))
43+
{
44+
addSymbologyToLayer(static_cast<QgsLayerTreeLayer*>(node));
45+
}
46+
3947
foreach (QgsLayerTreeNode* child, node->children())
4048
connectToNode(child);
4149
}
@@ -70,8 +78,6 @@ int QgsLayerTreeModel::rowCount(const QModelIndex &parent) const
7078
if (n->nodeType() == QgsLayerTreeNode::NodeLayer)
7179
{
7280
QgsLayerTreeLayer* nL = static_cast<QgsLayerTreeLayer*>(n);
73-
if (testFlag(ShowSymbology) && !mSymbologyNodes.contains(nL))
74-
addSymbologyToLayer(nL);
7581

7682
return mSymbologyNodes[nL].count();
7783
}
@@ -160,7 +166,17 @@ QVariant QgsLayerTreeModel::data(const QModelIndex &index, int role) const
160166
if (node->nodeType() == QgsLayerTreeNode::NodeGroup)
161167
return static_cast<QgsLayerTreeGroup*>(node)->name();
162168
else if (node->nodeType() == QgsLayerTreeNode::NodeLayer)
163-
return static_cast<QgsLayerTreeLayer*>(node)->layerName();
169+
{
170+
QgsLayerTreeLayer* nodeLayer = static_cast<QgsLayerTreeLayer*>(node);
171+
QString name = nodeLayer->layerName();
172+
if (nodeLayer->customProperty("showFeatureCount", 0).toInt() && role == Qt::DisplayRole)
173+
{
174+
QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>(nodeLayer->layer());
175+
if (vlayer && vlayer->pendingFeatureCount() >= 0)
176+
name += QString( " [%1]" ).arg( vlayer->pendingFeatureCount() );
177+
}
178+
return name;
179+
}
164180
}
165181
else if ( role == Qt::DecorationRole && index.column() == 0 )
166182
{
@@ -275,7 +291,7 @@ bool QgsLayerTreeModel::setData(const QModelIndex& index, const QVariant& value,
275291
return QAbstractItemModel::setData(index, value, role);
276292
}
277293

278-
QModelIndex QgsLayerTreeModel::node2index(QgsLayerTreeNode* node)
294+
QModelIndex QgsLayerTreeModel::node2index(QgsLayerTreeNode* node) const
279295
{
280296
if (!node->parent())
281297
return QModelIndex(); // this is the only root item -> invalid index
@@ -335,6 +351,20 @@ QList<QgsLayerTreeNode*> QgsLayerTreeModel::indexes2nodes(const QModelIndexList&
335351
return nodesFinal;
336352
}
337353

354+
void QgsLayerTreeModel::refreshLayerSymbology(QgsLayerTreeLayer* nodeLayer)
355+
{
356+
// update title
357+
QModelIndex idx = node2index(nodeLayer);
358+
emit dataChanged(idx, idx);
359+
360+
// update children
361+
beginRemoveRows(idx, 0, rowCount(idx)-1);
362+
removeSymbologyFromLayer(nodeLayer);
363+
endRemoveRows();
364+
365+
addSymbologyToLayer(nodeLayer);
366+
}
367+
338368
void QgsLayerTreeModel::nodeWillAddChildren(int indexFrom, int indexTo)
339369
{
340370
QgsLayerTreeNode* node = qobject_cast<QgsLayerTreeNode*>(sender());
@@ -379,47 +409,168 @@ void QgsLayerTreeModel::nodeVisibilityChanded()
379409
emit dataChanged(index, index);
380410
}
381411

412+
void QgsLayerTreeModel::nodeLayerLoaded()
413+
{
414+
QgsLayerTreeLayer* nodeLayer = qobject_cast<QgsLayerTreeLayer*>(sender());
415+
if (!nodeLayer)
416+
return;
417+
418+
addSymbologyToLayer(nodeLayer);
419+
}
420+
421+
void QgsLayerTreeModel::layerRendererChanged()
422+
{
423+
QgsMapLayer* layer = qobject_cast<QgsMapLayer*>(sender());
424+
if (!layer)
425+
return;
426+
427+
QgsLayerTreeLayer* nodeLayer = mRootNode->findLayer(layer->id());
428+
if (!nodeLayer)
429+
return;
430+
431+
refreshLayerSymbology(nodeLayer);
432+
}
433+
382434
void QgsLayerTreeModel::removeSymbologyFromSubtree(QgsLayerTreeNode* node)
383435
{
384436
if (node->nodeType() == QgsLayerTreeNode::NodeLayer)
385-
{
386-
QgsLayerTreeLayer* nodeLayer = static_cast<QgsLayerTreeLayer*>(node);
387-
if (mSymbologyNodes.contains(nodeLayer))
388-
{
389-
qDeleteAll(mSymbologyNodes[nodeLayer]);
390-
mSymbologyNodes.remove(nodeLayer);
391-
}
392-
}
437+
removeSymbologyFromLayer(static_cast<QgsLayerTreeLayer*>(node));
393438

394439
foreach (QgsLayerTreeNode* child, node->children())
395440
removeSymbologyFromSubtree(child);
396441
}
397442

398443

399-
void QgsLayerTreeModel::addSymbologyToLayer(QgsLayerTreeLayer* nodeL) const
444+
void QgsLayerTreeModel::removeSymbologyFromLayer(QgsLayerTreeLayer* nodeLayer)
445+
{
446+
if (mSymbologyNodes.contains(nodeLayer))
447+
{
448+
qDeleteAll(mSymbologyNodes[nodeLayer]);
449+
mSymbologyNodes.remove(nodeLayer);
450+
451+
disconnect(nodeLayer->layer(), SIGNAL(rendererChanged()), this, SLOT(layerRendererChanged()));
452+
}
453+
}
454+
455+
456+
void QgsLayerTreeModel::addSymbologyToLayer(QgsLayerTreeLayer* nodeL)
400457
{
401458
if (!nodeL->layer())
402-
return; // skip creation of symbology if the layer is not (yet?) loaded
459+
{
460+
// skip creation of symbology if the layer is not (yet?) loaded
461+
// but keep an eye on it: once loaded, we will add the symbology
462+
connect(nodeL, SIGNAL(layerLoaded()), this, SLOT(nodeLayerLoaded()));
463+
return;
464+
}
465+
466+
if (nodeL->layer()->type() == QgsMapLayer::VectorLayer)
467+
{
468+
addSymbologyToVectorLayer(nodeL);
469+
}
470+
else if (nodeL->layer()->type() == QgsMapLayer::RasterLayer)
471+
{
472+
addSymbologyToRasterLayer(nodeL);
473+
}
474+
else if (nodeL->layer()->type() == QgsMapLayer::PluginLayer)
475+
{
476+
addSymbologyToPluginLayer(nodeL);
477+
}
478+
479+
// be ready for any subsequent changes of the renderer
480+
connect(nodeL->layer(), SIGNAL(rendererChanged()), this, SLOT(layerRendererChanged()));
481+
}
482+
483+
484+
void QgsLayerTreeModel::addSymbologyToVectorLayer(QgsLayerTreeLayer* nodeL)
485+
{
486+
QgsVectorLayer* vlayer = static_cast<QgsVectorLayer*>(nodeL->layer());
487+
QgsFeatureRendererV2* r = vlayer->rendererV2();
488+
if (!r)
489+
return;
403490

404491
QList<QgsLayerTreeModelSymbologyNode*>& lst = mSymbologyNodes[nodeL];
405492

406-
if (nodeL->layer()->type() == QgsMapLayer::VectorLayer)
493+
bool showFeatureCount = nodeL->customProperty("showFeatureCount", 0).toBool();
494+
if (showFeatureCount)
495+
{
496+
vlayer->countSymbolFeatures();
497+
}
498+
QSize iconSize( 16, 16 );
499+
QgsLegendSymbolList items = r->legendSymbolItems();
500+
501+
beginInsertRows(node2index(nodeL), 0, items.count()-1);
502+
503+
typedef QPair<QString, QgsSymbolV2*> XY;
504+
foreach ( XY item, items )
505+
{
506+
QString label = item.first;
507+
QPixmap pix(QgsSymbolLayerV2Utils::symbolPreviewPixmap(item.second, iconSize));
508+
if (showFeatureCount)
509+
label += QString(" [%1]").arg( vlayer->featureCount( item.second ) );
510+
lst << new QgsLayerTreeModelSymbologyNode(nodeL, label, QIcon(pix));
511+
}
512+
513+
endInsertRows();
514+
}
515+
516+
517+
void QgsLayerTreeModel::addSymbologyToRasterLayer(QgsLayerTreeLayer* nodeL)
518+
{
519+
QgsRasterLayer* rlayer = static_cast<QgsRasterLayer*>(nodeL->layer());
520+
521+
QgsLegendColorList rasterItemList = rlayer->legendSymbologyItems();
522+
523+
QList<QgsLayerTreeModelSymbologyNode*>& lst = mSymbologyNodes[nodeL];
524+
525+
// TODO: WMS
526+
527+
// Paletted raster may have many colors, for example UInt16 may have 65536 colors
528+
// and it is very slow, so we limit max count
529+
QSize iconSize(16, 16);
530+
int count = 0;
531+
int max_count = 1000;
532+
int total_count = qMin(max_count+1, rasterItemList.count());
533+
534+
beginInsertRows(node2index(nodeL), 0, total_count-1);
535+
536+
for ( QgsLegendColorList::const_iterator itemIt = rasterItemList.constBegin();
537+
itemIt != rasterItemList.constEnd(); ++itemIt, ++count )
407538
{
408-
QgsFeatureRendererV2* r = static_cast<QgsVectorLayer*>(nodeL->layer())->rendererV2();
409-
if (r)
539+
QPixmap pix( iconSize );
540+
pix.fill( itemIt->second );
541+
lst << new QgsLayerTreeModelSymbologyNode(nodeL, itemIt->first, QIcon(pix));
542+
543+
if ( count == max_count )
410544
{
411-
// TODO: use legend symbol list
412-
//QgsLegendSymbolList syms = r->legendSymbolItems( /* double scaleDenominator = -1, QString rule = "" */ );
413-
QSize iconSize( 16, 16 );
414-
typedef QPair<QString, QPixmap> XY;
415-
foreach ( XY item, r->legendSymbologyItems( iconSize ))
416-
lst << new QgsLayerTreeModelSymbologyNode(nodeL, item.first, QIcon(item.second));
545+
pix.fill( Qt::transparent );
546+
QString label = tr( "following %1 items\nnot displayed" ).arg( rasterItemList.size() - max_count );
547+
lst << new QgsLayerTreeModelSymbologyNode(nodeL, label, QIcon(pix));
548+
break;
417549
}
418550
}
419-
else
551+
552+
endInsertRows();
553+
}
554+
555+
556+
void QgsLayerTreeModel::addSymbologyToPluginLayer(QgsLayerTreeLayer* nodeL)
557+
{
558+
QgsPluginLayer* player = static_cast<QgsPluginLayer*>(nodeL->layer());
559+
560+
QList<QgsLayerTreeModelSymbologyNode*>& lst = mSymbologyNodes[nodeL];
561+
562+
QSize iconSize(16,16);
563+
QgsLegendSymbologyList symbologyList = player->legendSymbologyItems(iconSize);
564+
565+
beginInsertRows(node2index(nodeL), 0, symbologyList.count()-1);
566+
567+
typedef QPair<QString, QPixmap> XY;
568+
foreach (XY item, symbologyList )
420569
{
421-
// TODO: raster / plugin layer
570+
lst << new QgsLayerTreeModelSymbologyNode(nodeL, item.first, QIcon(item.second));
422571
}
572+
573+
endInsertRows();
423574
}
424575

425576

src/gui/layertree/qgslayertreemodel.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ class GUI_EXPORT QgsLayerTreeModel : public QAbstractItemModel
5656
AllowTreeManagement,
5757
ShowSymbology,
5858
AllowVisibilityManagement,
59-
ShowFeatureCounts, // TODO: this is per-layer
6059
};
6160
Q_DECLARE_FLAGS(Flags, Flag)
6261

@@ -69,12 +68,14 @@ class GUI_EXPORT QgsLayerTreeModel : public QAbstractItemModel
6968

7069
QgsLayerTreeNode* index2node(const QModelIndex& index) const;
7170
static QgsLayerTreeModelSymbologyNode* index2symnode(const QModelIndex& index);
72-
QModelIndex node2index(QgsLayerTreeNode* node);
71+
QModelIndex node2index(QgsLayerTreeNode* node) const;
7372

7473
QList<QgsLayerTreeNode*> indexes2nodes(const QModelIndexList& list, bool skipInternal = false) const;
7574

7675
QgsLayerTreeGroup* rootGroup() { return mRootNode; }
7776

77+
void refreshLayerSymbology(QgsLayerTreeLayer* nodeLayer);
78+
7879
signals:
7980

8081
protected slots:
@@ -85,16 +86,23 @@ protected slots:
8586

8687
void nodeVisibilityChanded();
8788

89+
void nodeLayerLoaded();
90+
void layerRendererChanged();
91+
8892
protected:
8993
void connectToNode(QgsLayerTreeNode* node);
9094
void removeSymbologyFromSubtree(QgsLayerTreeNode* node);
91-
void addSymbologyToLayer(QgsLayerTreeLayer* nodeL) const;
95+
void removeSymbologyFromLayer(QgsLayerTreeLayer* nodeLayer);
96+
void addSymbologyToLayer(QgsLayerTreeLayer* nodeL);
97+
void addSymbologyToVectorLayer(QgsLayerTreeLayer* nodeL);
98+
void addSymbologyToRasterLayer(QgsLayerTreeLayer* nodeL);
99+
void addSymbologyToPluginLayer(QgsLayerTreeLayer* nodeL);
92100

93101
protected:
94102
QgsLayerTreeGroup* mRootNode; // not owned!
95103
Flags mFlags;
96104

97-
mutable QMap<QgsLayerTreeLayer*, QList<QgsLayerTreeModelSymbologyNode*> > mSymbologyNodes;
105+
QMap<QgsLayerTreeLayer*, QList<QgsLayerTreeModelSymbologyNode*> > mSymbologyNodes;
98106
};
99107

100108
Q_DECLARE_OPERATORS_FOR_FLAGS(QgsLayerTreeModel::Flags)

0 commit comments

Comments
 (0)