3

I have a file with many overlapping polygons that outlines different datasets. In the attribute table I have an absolute Windows path to mapinfo tab files. I would like to define an action on the layer that uses this field to present a list of files and when pressed the file gets loaded into QGIS 3.8.

How is this possible?

I have gotten as far as getting a popup but I get an error when I run the action and also it does not give me the names of the layer in the popup, only the rowid number (I think).

I have this Python script running fine in the console and it executes fine:

location = r"Z:\02 Data Library\Geology\AUSTRALIA\QUEENSLAND\GA 2.5M\GEOL_QLD_Geol_2500k_Ln.TAB"
iface.addVectorLayer(location,"","ogr")

But when I reformat it to use the path column in the attribute table for the layer and actions, I have inserted this code and get the below error:

location = r[%Path%]
iface.addVectorLayer(location,"","ogr")

Error:

An error occurred during execution of following code:
location = rZ:\02 Data Library\Geology\AUSTRALIA\QUEENSLAND\GA 2.5M\GEOL_QLD_Geol_2500k_Ln.TAB 
iface.addVectorLayer(location,"","ogr")

traceback.print_exception() failed

Python version:

QGIS version:
3.8.3-Zanzibar 'Zanzibar', 685d8b15d2

Python path:

What am I doing wrong here?

I do not know how to show the "FileName" field when I get the list after clicking on the overlapping polygons in the layer (figure 2)

Actions

example

Browser

0

1 Answer 1

4

Firstly I must admit I have never really delved into Actions before now, so based on discussions in comments below and my own experimentations, I have heavily revised my original answer.

My test layer contains overlapping polygons. A sample of the attribute table looks like this:

enter image description here

For what it's worth, I can get the files to load as a Python action using the following code snippet in the action editor:

from qgis.utils import iface

layer_id = '[%@layer_id%]'
fid = [%$id%]
layer_obj = QgsProject().instance().mapLayer(layer_id)
feat = layer_obj.getFeature(fid)
path = feat['Path']
iface.addVectorLayer(path, '', 'ogr')

The Action settings looks like this:

enter image description here

Result:

enter image description here

However, I have not yet found any way to show the filenames instead of feature ids in the pop up list which shows when you click on overlapping features.

Given that, I would suggest implementing a custom map tool which subclasses QgsMapToolIdentifyFeature.

Try copying the script below into an editor in the Python console.

*Note- you just have to change the following line. Replace 'Layer_Name' with the name of your overlapping polygon layer. The script will set this layer as active and ensure that the custom identify tool only identifies features in this layer. This will avoid any errors which would occur if features were identified from other layers which didn't contain a field called 'FileName'.

self.lyr = QgsProject().instance().mapLayersByName('Layer_Name')[0]

Once you have done that, simply run the script.

To deactivate the tool, just select a different map tool from the toolbar.

You can save this script locally as a .py file so you can load and run it from the console anytime you like. You could also make it a plugin easily enough.

class LoadLayerTool(QgsMapToolIdentifyFeature):

    def __init__(self, canvas):
        self.canvas = canvas
        self.lyr = QgsProject().instance().mapLayersByName('Layer_Name')[0] # change to name of your polygon layer
        iface.setActiveLayer(self.lyr)
        self.vlayer = iface.activeLayer()
        self.ids = None
        QgsMapToolIdentifyFeature.__init__(self, self.canvas)
        self.setLayer(self.vlayer)

    def canvasPressEvent(self, event):
        results = self.identify(event.x(), event.y())
        self.ids = [f.mFeature.id() for f in results]
        if self.ids:
            self.W = Dlg(self.vlayer, self.ids)
            self.W.show()
            self.W.setGeometry(event.x(), event.y(), 300, 100)


class Dlg(QDialog):
    def __init__(self, layer, ids):
        self.layer = layer
        self.ids = ids
        QDialog.__init__(self)
        self.layout = QVBoxLayout(self)
        self.cb1 = QComboBox(self)
        self.btn1 = QPushButton('Load File as vector layer', self)
        self.layout.addWidget(self.cb1)
        self.layout.addWidget(self.btn1)
        self.layer = iface.activeLayer()
        self.file_names = []
        for f in self.layer.getFeatures(self.ids):
            self.file_names.append(str(f['FileName']))
        self.cb1.addItems(self.file_names)
        self.btn1.clicked.connect(self.load_layer)

    def load_layer(self):
        fpath = []
        for f in self.layer.getFeatures():
            if f['FileName'] == self.cb1.currentText():
                fpath.append(f['Path'])
        iface.addVectorLayer(fpath[0], '', 'ogr')
        iface.setActiveLayer(self.layer)
        self.close()

c = iface.mapCanvas()
t = LoadLayerTool(c)
c.setMapTool(t)

Result:

enter image description here

6
  • Thanks @ben-w, that closer however there is a couple of problems, the layer i have has overlapping polygons for the various datasets. however when i use your scrip it doesn't matter if i select an area that has one polygon or 20 it shows all the whole table in the dropdown. is there a way yo filter to only polygons under the selection? also in addion i still get a list of all the ID's pop up every time i click Oct 27, 2019 at 23:45
  • No worries @Christian. I think that using an action, you will always get that list popping up whenever you click on overlapping features. I have updated my answer- hopefully this is more what you are after.
    – Ben W
    Oct 28, 2019 at 5:07
  • Thanks @ben-w I will have to test it tomorrow when I'm back in the office. It's a pity Qgis does not have something similar to the Mapinfo hotlink tool. I thought actions was the answer. Have a look here: pitneybowes.com/us/support/connection/… this is the function I'm after in QGIS Oct 28, 2019 at 6:19
  • @Christian, I have updated my answer again! I can get the layers to load from the 'Path' attribute in a Python action, but I can't find any way to show the file name instead of the id number in the pop up list when clicking on overlapping features. I think the custom map tool solution is more user friendly and gives you another option. I encourage you to keep monitoring this thread. If I find a solution with actions I will post it- or someone else may post a better answer.
    – Ben W
    Oct 29, 2019 at 4:45
  • thanks for that i didn't get a chance to try it out with my data. It's an awsome solution just wish there was better documentation around the actions. Thanks for all your work. Oct 29, 2019 at 8:51

Your Answer

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

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