6

In QGIS, by pressing shift or ctrl keys, a user can select multiple layers in toc.

How can a Python script iterate over selected layers?

I'd expect an iface.selectedLayers() but I can find only iface.activeLayer() which returns only one layer.

4 Answers 4

5

The most up to date solution is to get the current QgsLayerTreeView (it inherits from QTreeView)

selected_layers = iface.layerTreeView().selectedLayers()

for layer in selected_layers:
    print layer.name()
4

I have added a QgsLegend::selectedLayers() binding to QgsLegendInterface in master branch. You can now do the following when using a current master build (might have to wait a day or two, unless compiling yourself; not going to be backported to QGIS 1.8):

# iface.legendInterface().selectedLayers(bool inDrawOrder)
# param inDrawOrder False returns QTreeWidget::selectedItems() order
#                   True returns render drawing order (Legend or Layer Order)
# returns list of selected QgsMapLayer(s), or empty list

from qgis.utils import iface
li = iface.legendInterface()
sl = li.selectedLayers(True)
for lyr in sl:
    print lyr.name()
1
  • Since Python 3, the print function now needs parentheses, for example print( lyr.name() )
    – kbjshop
    Commented May 31, 2022 at 19:00
1

The TOC is implemented as a QTreeView and can be queried directly.

The model attached to this view stores both the Display Name and Source for the layer, however neither of these can be relied upon to be unique.

How best to handle this ambiguity would depend on your application.

The following is an implementation that uses the layer source for cross referencing, considers the first hit to be final, and collates a non-repeating list of layers.

from PyQt4.QtGui import *
iface = qgis.utils.iface

layersTreeView = iface.mainWindow().findChild(QTreeView, "theMapLegend")
selectedIndexes = layersTreeView.selectedIndexes()

if len(selectedIndexes) == 0:
  selectedLayers = []
elif len(selectedIndexes) == 1:
  selectedLayers = [iface.activeLayer()]
else:
  layersModel = layersTreeView.model()
  allLayers = iface.legendInterface().layers()
  selectedLayers = []
  for modelIndex in selectedIndexes:
    itemData = layersModel.itemData(modelIndex)
    layerSource = itemData[3].toString()
    for layer in allLayers:
      if layer.source() == layerSource:
        if layer not in selectedLayers:
          selectedLayers.append(layer)
        break

On further thought is should be possible to connect to iface.currentLayerChanged and use this signal to maintain list of layers sorted by when they were most recently selected.

This list could then be used to remove the ambiguity mentioned above.

0

If you're interested in the selected nodes (including groups) rather than the underlying map layers, then see iface.layerTreeView().selectedNodes().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.