|
6 | 6 | #include <QTextStream>
|
7 | 7 |
|
8 | 8 | #include "qgsdataitem.h"
|
| 9 | +#include "qgspluginlayer.h" |
| 10 | +#include "qgsrasterlayer.h" |
9 | 11 | #include "qgsrendererv2.h"
|
| 12 | +#include "qgssymbollayerv2utils.h" |
10 | 13 | #include "qgsvectorlayer.h"
|
11 | 14 |
|
12 | 15 |
|
@@ -36,6 +39,11 @@ void QgsLayerTreeModel::connectToNode(QgsLayerTreeNode* node)
|
36 | 39 | connect(node, SIGNAL(removedChildren(int,int)), this, SLOT(nodeRemovedChildren()));
|
37 | 40 | connect(node, SIGNAL(visibilityChanged(Qt::CheckState)), this, SLOT(nodeVisibilityChanded()));
|
38 | 41 |
|
| 42 | + if (node->nodeType() == QgsLayerTreeNode::NodeLayer && testFlag(ShowSymbology)) |
| 43 | + { |
| 44 | + addSymbologyToLayer(static_cast<QgsLayerTreeLayer*>(node)); |
| 45 | + } |
| 46 | + |
39 | 47 | foreach (QgsLayerTreeNode* child, node->children())
|
40 | 48 | connectToNode(child);
|
41 | 49 | }
|
@@ -70,8 +78,6 @@ int QgsLayerTreeModel::rowCount(const QModelIndex &parent) const
|
70 | 78 | if (n->nodeType() == QgsLayerTreeNode::NodeLayer)
|
71 | 79 | {
|
72 | 80 | QgsLayerTreeLayer* nL = static_cast<QgsLayerTreeLayer*>(n);
|
73 |
| - if (testFlag(ShowSymbology) && !mSymbologyNodes.contains(nL)) |
74 |
| - addSymbologyToLayer(nL); |
75 | 81 |
|
76 | 82 | return mSymbologyNodes[nL].count();
|
77 | 83 | }
|
@@ -160,7 +166,17 @@ QVariant QgsLayerTreeModel::data(const QModelIndex &index, int role) const
|
160 | 166 | if (node->nodeType() == QgsLayerTreeNode::NodeGroup)
|
161 | 167 | return static_cast<QgsLayerTreeGroup*>(node)->name();
|
162 | 168 | 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 | + } |
164 | 180 | }
|
165 | 181 | else if ( role == Qt::DecorationRole && index.column() == 0 )
|
166 | 182 | {
|
@@ -275,7 +291,7 @@ bool QgsLayerTreeModel::setData(const QModelIndex& index, const QVariant& value,
|
275 | 291 | return QAbstractItemModel::setData(index, value, role);
|
276 | 292 | }
|
277 | 293 |
|
278 |
| -QModelIndex QgsLayerTreeModel::node2index(QgsLayerTreeNode* node) |
| 294 | +QModelIndex QgsLayerTreeModel::node2index(QgsLayerTreeNode* node) const |
279 | 295 | {
|
280 | 296 | if (!node->parent())
|
281 | 297 | return QModelIndex(); // this is the only root item -> invalid index
|
@@ -335,6 +351,20 @@ QList<QgsLayerTreeNode*> QgsLayerTreeModel::indexes2nodes(const QModelIndexList&
|
335 | 351 | return nodesFinal;
|
336 | 352 | }
|
337 | 353 |
|
| 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 | + |
338 | 368 | void QgsLayerTreeModel::nodeWillAddChildren(int indexFrom, int indexTo)
|
339 | 369 | {
|
340 | 370 | QgsLayerTreeNode* node = qobject_cast<QgsLayerTreeNode*>(sender());
|
@@ -379,47 +409,168 @@ void QgsLayerTreeModel::nodeVisibilityChanded()
|
379 | 409 | emit dataChanged(index, index);
|
380 | 410 | }
|
381 | 411 |
|
| 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 | + |
382 | 434 | void QgsLayerTreeModel::removeSymbologyFromSubtree(QgsLayerTreeNode* node)
|
383 | 435 | {
|
384 | 436 | 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)); |
393 | 438 |
|
394 | 439 | foreach (QgsLayerTreeNode* child, node->children())
|
395 | 440 | removeSymbologyFromSubtree(child);
|
396 | 441 | }
|
397 | 442 |
|
398 | 443 |
|
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) |
400 | 457 | {
|
401 | 458 | 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; |
403 | 490 |
|
404 | 491 | QList<QgsLayerTreeModelSymbologyNode*>& lst = mSymbologyNodes[nodeL];
|
405 | 492 |
|
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 ) |
407 | 538 | {
|
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 ) |
410 | 544 | {
|
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; |
417 | 549 | }
|
418 | 550 | }
|
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 ) |
420 | 569 | {
|
421 |
| - // TODO: raster / plugin layer |
| 570 | + lst << new QgsLayerTreeModelSymbologyNode(nodeL, item.first, QIcon(item.second)); |
422 | 571 | }
|
| 572 | + |
| 573 | + endInsertRows(); |
423 | 574 | }
|
424 | 575 |
|
425 | 576 |
|
|
0 commit comments