7

Related to the following question but looking for a PyQGIS method:

QGIS Layer Order Panel - add layers at top of layer order


The following is a simple setup containing a group with three layers.

Simple setup

The code I use adds a new layer at the end of this group:

root = QgsProject.instance().layerTreeRoot()
group = root.findGroup('Main group')

vlayer = QgsVectorLayer('LineString?crs=epsg:27700', 'vlayer', 'memory')
QgsMapLayerRegistry.instance().addMapLayer(vlayer, False)
group.insertChildNode(-1, QgsLayerTreeLayer(vlayer))  

New layer added at end of group

In the Layer Order Panel, the newly added layer is at the end.

Layer Order Panel


Is it possible to move this to the top without moving the layer in the Layers Panel?

6

You can set layer order in the Layer Order Panel "manually" using QgsLayerTreeCanvasBridge.setCustomLayerOrder() method, which receives an ordered list of layer ids. For instance (assuming you just loaded vlayer):

bridge = iface.layerTreeCanvasBridge() 
order = bridge.customLayerOrder()
order.insert( 0, order.pop( order.index( vlayer.id() ) ) ) # vlayer to the top
bridge.setCustomLayerOrder( order )

To automatically move newly added layers to the top of Layer Order Panel, you could use the legendLayersAdded SIGNAL (this signal is appropriate because it's emitted after the Layer Order Panel gets the new layer) from QgsMapLayerRegistry and reorder layers in this way:

def rearrange( layers ):
    order = iface.layerTreeCanvasBridge().customLayerOrder()
    for layer in layers: # How many layers we need to move
        order.insert( 0, order.pop() ) # Last layer to first position
    iface.layerTreeCanvasBridge().setCustomLayerOrder( order )

QgsMapLayerRegistry.instance().legendLayersAdded.connect( rearrange )

NOTE: Since you're loading your vlayer calling QgsMapLayerRegistry.instance().addMapLayer(vlayer, False), that False parameter prevents the legendLayersAdded SIGNAL from being emitted. So, the automatic approach won't work for your case and you will need to rearrange layers manually (first approach of this answer).

  • I'm inexperienced using Python in QGIS- Where do you enter this script text? Is it saved to the specific QGIS project file? – Theo F Nov 14 '17 at 16:54
  • It is intended to be executed in the QGIS Python Console. If you need it to be more perdurable, check this answer to see how a code snippet can be executed each time QGIS is open or each time a particular QGIS project is open: gis.stackexchange.com/questions/194055/… – Germán Carrillo Nov 14 '17 at 18:18
4

Hi sorry I can't comment, but the method "bridge.customLayerOrder()" doesn't exist in QGis 3.x

I've found maybe a substitute command:

bridge = iface.layerTreeCanvasBridge() 
bridge.rootGroup().customLayerOrder()

From https://qgis.org/api/classQgsLayerTree.html#aab7a55f2e61f0ff1dbea6ceb89e8b366:

The order in which layers will be rendered on the canvas. Will only be used if the property hasCustomLayerOrder is true. If you need the current layer order that is active, prefer using layerOrder().

Hope to be useful to others.

Riccardo

1

I am not so familiar with pyqgis, but when I changed the line in your code from

group.insertChildNode(-1, QgsLayerTreeLayer(vlayer)) 

to

group.insertChildNode(0, QgsLayerTreeLayer(vlayer)) 

It was intserted at the top of the group, not the bottom.

  • 1
    Thanks for your answer, you are correct in that replacing -1 with 0 places the layer at the top of the Layers Panel but not in the Layer Order Panel. Also, I would like the new layer to be added to the bottom of the Layers Panel :) – Joseph Feb 23 '17 at 11:03
  • 1
    You are right, I missed that. – ahmadhanb Feb 23 '17 at 11:05
  • 1
    It would be somewhat of a workaround to add the layer at the top of the group and disable the Control rendering order as this would place the layer at the top of the Layer Order Panel. But for my use-case, it wouldn't be tidy :) – Joseph Feb 23 '17 at 11:08
  • 1
    I am sure someone with more experience than me in pyqgis will find a solution for you. – ahmadhanb Feb 23 '17 at 11:50
1

Based on this (old) question and some other research, I've successfully added a handler to my QGIS 3.10 project to move all newly added layers to the top of the custom layer order. Here's the relevant project macro code with v3 object references.

from qgis.core import QgsProject
from qgis.utils import iface

def openProject():
    def layersToTopHandler( layers ):
        # moves last len(layers) layers to top of custom layer order
        # note pays no attention to what is in the list given, always moves bottom layers
        # intended as a legendLayersAdded signal handler so the new layers have just been put at bottom! 
        rg = iface.layerTreeCanvasBridge().rootGroup()
        if rg.hasCustomLayerOrder():
            # Only do anything if custom layer order is turned on
            order = rg.customLayerOrder()
            for layer in layers: # How many layers we need to move
                order.insert( 0, order.pop() ) # Last layer to first position
            rg.setCustomLayerOrder( order )
    QgsProject.instance().legendLayersAdded.connect( layersToTopHandler )

def saveProject():
    pass

def closeProject():
    QgsProject.instance().legendLayersAdded.disconnect()
    # not sure this is strictly necessary 
  • Thank you for your answer, this will be useful to know when I port over the relevant code to QGIS 3 :) – Joseph Nov 8 '19 at 14:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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