1

I am creating a temporary plugin for QGIS using the QGIS plugin builder plugin. Aim is to learn how to make plugins in QGIS. I have added two comboBoxes that allows the user to select a vector layer and a raster layer respectively. The plugin will process the data specified by the user in these comboboxes. For that I need to extract the entire path and name of the layers selected by the user. This might probably seem quite a basic post but I tried looking up for this, and failed to find a solution even after playing around with several codes. Below is the code for the comboBoxes:

    # Getting the loaded raster layers
    layerlist_rst = ['<Select a raster layer>']
    layers_rst = QgsProject.instance().mapLayers().values()
    for layer in layers_rst:
        if layer.type() == QgsMapLayer.RasterLayer:
            layerlist_rst.append(layer.name())

    # Getting the loaded vector layers
    layerlist_vect = ['<Select a vector layer>']
    layers_vect = QgsProject.instance().mapLayers().values()
    for layer in layers_vect:
        if layer.type() == QgsMapLayer.VectorLayer:
            layerlist_vect.append(layer.name())        

    #Clear contents of the comboBox from previous runs
    self.dlg.comboBox_rst.clear() #This combobox loads raster layers
    #Populate the comboBox with names of all the loaded raster layers
    self.dlg.comboBox_rst.addItems(layerlist_rst)      
    #Clear contents of the comboBox from previous runs
    self.dlg.comboBox_vect.clear() #This combobox loads the vector layers
    self.dlg.comboBox_vect.addItems(layerlist_vect)

Now I need to get the names and path of the selected layers as text. Example: If the layer added by user is 'C\Users\XYZ\Rstr.tif' I want to assign this path to a variable that can be used later in the plugin like: raster = r'C\Users\XYZ\Rstr.tif'

1

Since you are populating your combo boxes with layers which are loaded in the current project, in the context of a QGIS plugin you will probably find that it is easier in most instances to work directly with the map layer object than the source file.

For example, you can get a map layer object from your combo box (e.g. in run() method) like this:

raster_name = self.dlg.comboBox_rst.currentText()
raster_layer = QgsProject().instance().mapLayersByName(raster_name)[0]
#Do something with raster_layer

Then, if you do need to get the path to the source file, just call source() on the QgsMapLayer object:

path = raster_layer.source()

However, for selecting QGIS specific items like layers, fields etc. I would recommend looking at using custom QGIS widgets like QgsMapLayerComboBox and QgsFieldComboBox.

These are available in the Qt Designer which comes with QGIS. If you installed with OSGeo4W installer, you should find a batch file in C:\OSGeo4W64\bin (it looks like you are on Windows) with the name qgis-designer or qgis-ltr-designer. Double clicking this batch file should launch Qt Designer complete with QGIS custom widgets.

Say your self.dlg.comboBox_rst object is a QgsMapLayerComboBox instead of a regular QComboBox, you will now get the nice little raster and vector icons next to the layer names. You don't have to create a list of loaded layers and add them as items to the combo box- a QgsMapLayerComboBox contains all project layers by default, but you can easily apply a filter to show only raster or vector layers:

self.dlg.comboBox_rst.setFilters(QgsMapLayerProxyModel.RasterLayer)
self.dlg.comboBox_vect.setFilters(QgsMapLayerProxyModel.VectorLayer)

Or show the layer CRS:

self.dlg.comboBox_rst.setShowCrs(True)
self.dlg.comboBox_vect.setShowCrs(True)

Which will give you a result like:

enter image description here

Getting the map layer object from the combo box is as easy as:

raster_layer = self.dlg.comboBox_rst.currentLayer()

By the way, if you are unable to access the custom widgets through Designer for any reason, a workaround is to just add an empty layout in Designer then create and add custom widgets to it later e.g. by modifying your plugin dialog file.

#Add to import statements
from qgis.gui import QgsMapLayerComboBox

#Add to __init__() method after setupUi
self.comboBox_rst = QgsMapLayerComboBox(self)
self.verticalLayout_1.addWidget(self.comboBox_rst)

You can then access these widgets as usual in the initGui() method of your main plugin file:

self.dlg.cb_rast.setFilters(QgsMapLayerProxyModel.RasterLayer)
self.dlg.cb_vect.setFilters(QgsMapLayerProxyModel.VectorLayer)
self.dlg.cb_rast.setShowCrs(True)
self.dlg.cb_vect.setShowCrs(True)

And finally, just as a bit of food for thought- if your aim is to teach yourself plugin development then by all means, go for it and have fun!! But for most practical purposes, if it's a processing task that's required, then a QGIS processing script is the way to go. They are actually quicker and easier to develop once you get your head around the basics, and can be added to the processing toolbox which means they can be used in models etc.

You can even package a collection of custom scripts into a processing plugin which will add a new provider to the tool box.

Here are some links to get you going:

https://docs.qgis.org/3.4/en/docs/user_manual/processing/scripts.html

https://www.qgistutorials.com/en/docs/3/processing_python_scripts.html

https://anitagraser.com/2018/03/25/processing-script-template-for-qgis3/

https://anitagraser.com/2019/03/02/easy-processing-scripts-comeback-in-qgis-3-6/

  • Thanks for all the details! It really helped a lot. – E_123 Oct 27 '19 at 17:43
  • You're welcome! – Ben W Oct 27 '19 at 20:50

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.