Skip to content
Permalink
Browse files
Raster and plugin layer symbology, show feature count for vectors
  • Loading branch information
wonder-sk committed May 21, 2014
1 parent 69da2b3 commit e1a0c21dec1fafde93843c80b98378e65f0c6ebc
@@ -2217,6 +2217,10 @@ QMenu* QgsAppLayerTreeViewMenuProvider::createContextMenu()
{
menu->addAction( actions->actionZoomToLayer(mCanvas, menu) );
menu->addAction( actions->actionShowInOverview(menu) );

QgsMapLayer* layer = static_cast<QgsLayerTreeLayer*>(node)->layer();
if (layer && layer->type() == QgsMapLayer::VectorLayer)
menu->addAction( actions->actionShowFeatureCount(menu) );
}

menu->addAction( actions->actionRemoveGroupOrLayer(menu) );
@@ -524,6 +524,7 @@ void QgsLayerTreeLayer::registryLayersAdded(QList<QgsMapLayer*> layers)
{
mLayer = l;
disconnect(QgsMapLayerRegistry::instance(), SIGNAL(layersAdded(QList<QgsMapLayer*>)), this, SLOT(registryLayersAdded(QList<QgsMapLayer*>)));
emit layerLoaded();
break;
}
}
@@ -123,6 +123,10 @@ class QgsLayerTreeLayer : public QgsLayerTreeNode
protected slots:
void registryLayersAdded(QList<QgsMapLayer*> layers);

signals:
//! emitted when a previously unavailable layer got loaded
void layerLoaded();

protected:
void attachToLayer();

@@ -304,7 +304,7 @@ void QgsRasterLayer::draw( QPainter * theQPainter,
QgsDebugMsg( QString( "total raster draw time (ms): %1" ).arg( time.elapsed(), 5 ) );
} //end of draw method

QList< QPair< QString, QColor > > QgsRasterLayer::legendSymbologyItems() const
QgsLegendColorList QgsRasterLayer::legendSymbologyItems() const
{
QList< QPair< QString, QColor > > symbolList;
QgsRasterRenderer *renderer = mPipe.renderer();
@@ -53,6 +53,8 @@ class QLibrary;
class QPixmap;
class QSlider;

typedef QList < QPair< QString, QColor > > QgsLegendColorList;

/** \ingroup core
* This class provides qgis with the ability to render raster datasets
* onto the mapcanvas.
@@ -297,7 +299,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer

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

/** \brief Obtain GDAL Metadata for this layer */
QString metadata();
@@ -6,7 +6,10 @@
#include <QTextStream>

#include "qgsdataitem.h"
#include "qgspluginlayer.h"
#include "qgsrasterlayer.h"
#include "qgsrendererv2.h"
#include "qgssymbollayerv2utils.h"
#include "qgsvectorlayer.h"


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

if (node->nodeType() == QgsLayerTreeNode::NodeLayer && testFlag(ShowSymbology))
{
addSymbologyToLayer(static_cast<QgsLayerTreeLayer*>(node));
}

foreach (QgsLayerTreeNode* child, node->children())
connectToNode(child);
}
@@ -70,8 +78,6 @@ int QgsLayerTreeModel::rowCount(const QModelIndex &parent) const
if (n->nodeType() == QgsLayerTreeNode::NodeLayer)
{
QgsLayerTreeLayer* nL = static_cast<QgsLayerTreeLayer*>(n);
if (testFlag(ShowSymbology) && !mSymbologyNodes.contains(nL))
addSymbologyToLayer(nL);

return mSymbologyNodes[nL].count();
}
@@ -160,7 +166,17 @@ QVariant QgsLayerTreeModel::data(const QModelIndex &index, int role) const
if (node->nodeType() == QgsLayerTreeNode::NodeGroup)
return static_cast<QgsLayerTreeGroup*>(node)->name();
else if (node->nodeType() == QgsLayerTreeNode::NodeLayer)
return static_cast<QgsLayerTreeLayer*>(node)->layerName();
{
QgsLayerTreeLayer* nodeLayer = static_cast<QgsLayerTreeLayer*>(node);
QString name = nodeLayer->layerName();
if (nodeLayer->customProperty("showFeatureCount", 0).toInt() && role == Qt::DisplayRole)
{
QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>(nodeLayer->layer());
if (vlayer && vlayer->pendingFeatureCount() >= 0)
name += QString( " [%1]" ).arg( vlayer->pendingFeatureCount() );
}
return name;
}
}
else if ( role == Qt::DecorationRole && index.column() == 0 )
{
@@ -275,7 +291,7 @@ bool QgsLayerTreeModel::setData(const QModelIndex& index, const QVariant& value,
return QAbstractItemModel::setData(index, value, role);
}

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

void QgsLayerTreeModel::refreshLayerSymbology(QgsLayerTreeLayer* nodeLayer)
{
// update title
QModelIndex idx = node2index(nodeLayer);
emit dataChanged(idx, idx);

// update children
beginRemoveRows(idx, 0, rowCount(idx)-1);
removeSymbologyFromLayer(nodeLayer);
endRemoveRows();

addSymbologyToLayer(nodeLayer);
}

void QgsLayerTreeModel::nodeWillAddChildren(int indexFrom, int indexTo)
{
QgsLayerTreeNode* node = qobject_cast<QgsLayerTreeNode*>(sender());
@@ -379,47 +409,168 @@ void QgsLayerTreeModel::nodeVisibilityChanded()
emit dataChanged(index, index);
}

void QgsLayerTreeModel::nodeLayerLoaded()
{
QgsLayerTreeLayer* nodeLayer = qobject_cast<QgsLayerTreeLayer*>(sender());
if (!nodeLayer)
return;

addSymbologyToLayer(nodeLayer);
}

void QgsLayerTreeModel::layerRendererChanged()
{
QgsMapLayer* layer = qobject_cast<QgsMapLayer*>(sender());
if (!layer)
return;

QgsLayerTreeLayer* nodeLayer = mRootNode->findLayer(layer->id());
if (!nodeLayer)
return;

refreshLayerSymbology(nodeLayer);
}

void QgsLayerTreeModel::removeSymbologyFromSubtree(QgsLayerTreeNode* node)
{
if (node->nodeType() == QgsLayerTreeNode::NodeLayer)
{
QgsLayerTreeLayer* nodeLayer = static_cast<QgsLayerTreeLayer*>(node);
if (mSymbologyNodes.contains(nodeLayer))
{
qDeleteAll(mSymbologyNodes[nodeLayer]);
mSymbologyNodes.remove(nodeLayer);
}
}
removeSymbologyFromLayer(static_cast<QgsLayerTreeLayer*>(node));

foreach (QgsLayerTreeNode* child, node->children())
removeSymbologyFromSubtree(child);
}


void QgsLayerTreeModel::addSymbologyToLayer(QgsLayerTreeLayer* nodeL) const
void QgsLayerTreeModel::removeSymbologyFromLayer(QgsLayerTreeLayer* nodeLayer)
{
if (mSymbologyNodes.contains(nodeLayer))
{
qDeleteAll(mSymbologyNodes[nodeLayer]);
mSymbologyNodes.remove(nodeLayer);

disconnect(nodeLayer->layer(), SIGNAL(rendererChanged()), this, SLOT(layerRendererChanged()));
}
}


void QgsLayerTreeModel::addSymbologyToLayer(QgsLayerTreeLayer* nodeL)
{
if (!nodeL->layer())
return; // skip creation of symbology if the layer is not (yet?) loaded
{
// skip creation of symbology if the layer is not (yet?) loaded
// but keep an eye on it: once loaded, we will add the symbology
connect(nodeL, SIGNAL(layerLoaded()), this, SLOT(nodeLayerLoaded()));
return;
}

if (nodeL->layer()->type() == QgsMapLayer::VectorLayer)
{
addSymbologyToVectorLayer(nodeL);
}
else if (nodeL->layer()->type() == QgsMapLayer::RasterLayer)
{
addSymbologyToRasterLayer(nodeL);
}
else if (nodeL->layer()->type() == QgsMapLayer::PluginLayer)
{
addSymbologyToPluginLayer(nodeL);
}

// be ready for any subsequent changes of the renderer
connect(nodeL->layer(), SIGNAL(rendererChanged()), this, SLOT(layerRendererChanged()));
}


void QgsLayerTreeModel::addSymbologyToVectorLayer(QgsLayerTreeLayer* nodeL)
{
QgsVectorLayer* vlayer = static_cast<QgsVectorLayer*>(nodeL->layer());
QgsFeatureRendererV2* r = vlayer->rendererV2();
if (!r)
return;

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

if (nodeL->layer()->type() == QgsMapLayer::VectorLayer)
bool showFeatureCount = nodeL->customProperty("showFeatureCount", 0).toBool();
if (showFeatureCount)
{
vlayer->countSymbolFeatures();
}
QSize iconSize( 16, 16 );
QgsLegendSymbolList items = r->legendSymbolItems();

beginInsertRows(node2index(nodeL), 0, items.count()-1);

typedef QPair<QString, QgsSymbolV2*> XY;
foreach ( XY item, items )
{
QString label = item.first;
QPixmap pix(QgsSymbolLayerV2Utils::symbolPreviewPixmap(item.second, iconSize));
if (showFeatureCount)
label += QString(" [%1]").arg( vlayer->featureCount( item.second ) );
lst << new QgsLayerTreeModelSymbologyNode(nodeL, label, QIcon(pix));
}

endInsertRows();
}


void QgsLayerTreeModel::addSymbologyToRasterLayer(QgsLayerTreeLayer* nodeL)
{
QgsRasterLayer* rlayer = static_cast<QgsRasterLayer*>(nodeL->layer());

QgsLegendColorList rasterItemList = rlayer->legendSymbologyItems();

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

// TODO: WMS

// Paletted raster may have many colors, for example UInt16 may have 65536 colors
// and it is very slow, so we limit max count
QSize iconSize(16, 16);
int count = 0;
int max_count = 1000;
int total_count = qMin(max_count+1, rasterItemList.count());

beginInsertRows(node2index(nodeL), 0, total_count-1);

for ( QgsLegendColorList::const_iterator itemIt = rasterItemList.constBegin();
itemIt != rasterItemList.constEnd(); ++itemIt, ++count )
{
QgsFeatureRendererV2* r = static_cast<QgsVectorLayer*>(nodeL->layer())->rendererV2();
if (r)
QPixmap pix( iconSize );
pix.fill( itemIt->second );
lst << new QgsLayerTreeModelSymbologyNode(nodeL, itemIt->first, QIcon(pix));

if ( count == max_count )
{
// TODO: use legend symbol list
//QgsLegendSymbolList syms = r->legendSymbolItems( /* double scaleDenominator = -1, QString rule = "" */ );
QSize iconSize( 16, 16 );
typedef QPair<QString, QPixmap> XY;
foreach ( XY item, r->legendSymbologyItems( iconSize ))
lst << new QgsLayerTreeModelSymbologyNode(nodeL, item.first, QIcon(item.second));
pix.fill( Qt::transparent );
QString label = tr( "following %1 items\nnot displayed" ).arg( rasterItemList.size() - max_count );
lst << new QgsLayerTreeModelSymbologyNode(nodeL, label, QIcon(pix));
break;
}
}
else

endInsertRows();
}


void QgsLayerTreeModel::addSymbologyToPluginLayer(QgsLayerTreeLayer* nodeL)
{
QgsPluginLayer* player = static_cast<QgsPluginLayer*>(nodeL->layer());

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

QSize iconSize(16,16);
QgsLegendSymbologyList symbologyList = player->legendSymbologyItems(iconSize);

beginInsertRows(node2index(nodeL), 0, symbologyList.count()-1);

typedef QPair<QString, QPixmap> XY;
foreach (XY item, symbologyList )
{
// TODO: raster / plugin layer
lst << new QgsLayerTreeModelSymbologyNode(nodeL, item.first, QIcon(item.second));
}

endInsertRows();
}


@@ -56,7 +56,6 @@ class GUI_EXPORT QgsLayerTreeModel : public QAbstractItemModel
AllowTreeManagement,
ShowSymbology,
AllowVisibilityManagement,
ShowFeatureCounts, // TODO: this is per-layer
};
Q_DECLARE_FLAGS(Flags, Flag)

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

QgsLayerTreeNode* index2node(const QModelIndex& index) const;
static QgsLayerTreeModelSymbologyNode* index2symnode(const QModelIndex& index);
QModelIndex node2index(QgsLayerTreeNode* node);
QModelIndex node2index(QgsLayerTreeNode* node) const;

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

QgsLayerTreeGroup* rootGroup() { return mRootNode; }

void refreshLayerSymbology(QgsLayerTreeLayer* nodeLayer);

signals:

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

void nodeVisibilityChanded();

void nodeLayerLoaded();
void layerRendererChanged();

protected:
void connectToNode(QgsLayerTreeNode* node);
void removeSymbologyFromSubtree(QgsLayerTreeNode* node);
void addSymbologyToLayer(QgsLayerTreeLayer* nodeL) const;
void removeSymbologyFromLayer(QgsLayerTreeLayer* nodeLayer);
void addSymbologyToLayer(QgsLayerTreeLayer* nodeL);
void addSymbologyToVectorLayer(QgsLayerTreeLayer* nodeL);
void addSymbologyToRasterLayer(QgsLayerTreeLayer* nodeL);
void addSymbologyToPluginLayer(QgsLayerTreeLayer* nodeL);

protected:
QgsLayerTreeGroup* mRootNode; // not owned!
Flags mFlags;

mutable QMap<QgsLayerTreeLayer*, QList<QgsLayerTreeModelSymbologyNode*> > mSymbologyNodes;
QMap<QgsLayerTreeLayer*, QList<QgsLayerTreeModelSymbologyNode*> > mSymbologyNodes;
};

Q_DECLARE_OPERATORS_FOR_FLAGS(QgsLayerTreeModel::Flags)

0 comments on commit e1a0c21

Please sign in to comment.