[GIS] Moving layers in QGIS Table of Contents via PyQGIS

pyqgistable of contents

I have loaded two layers in canvas and would like to move the layers using the following code in TOC, but it is not moving the layers to the position based on the index given.

from PyQt4.QtCore import *
from PyQt4.QtGui import *

from qgis.core import *
from qgis.gui import *
import qgis.utils

canvas = qgis.utils.iface.mapCanvas()
layers = canvas.layers()

for i in layers:
  if i.name() == "Layer2":
    alayer = i
  elif i.name() == "Layer1":
    blayer = i

qgis.utils.iface.legendInterface().moveLayer(alayer, 0)
qgis.utils.iface.legendInterface().moveLayer(blayer, 1)
canvas.refresh()

How can I do that?

Best Answer

With the new (since QGIS v.2.4) Layer tree by Martin Dobias, you can do this:

alayer = QgsProject.instance().mapLayersByName("Layer2")[0]
blayer = QgsProject.instance().mapLayersByName("Layer1")[0]

root = QgsProject.instance().layerTreeRoot()

# Move alayer
myalayer = root.findLayer(alayer.id())
myClone = myalayer.clone()
parent = myalayer.parent()
parent.insertChildNode(0, myClone)
parent.removeChildNode(myalayer)

# Move blayer
myblayer = root.findLayer(blayer.id())
myClone = myblayer.clone()
parent = myblayer.parent()
parent.insertChildNode(1, myClone)
parent.removeChildNode(myblayer)

As you see, to move the layer alayer you first clone it, insert the clone at the desired position*, and remove the original.

You can see more on Layer tree handling here and here.

Note that if your original layer is at the position 0 and you want to move it to 1, you would need to insert it at the position 2 (instead of 1), because when the clone is inserted, the original layer is still there, so its index must be taken into account.

Related Question