10

I have a QGIS 2.18.0 plugin which updates a join between two layers (spatial and non-spatial layer).

QGIS crashes when I run the plugin and the attribute table of the joined layer is open. There is no crash when the attribute table is closed or an attribute table of another layer is open.

The last two commands that the plugin runs are:

....
PUNKTE_OS.addJoin(joinObject)
        
PUNKTE_OS.triggerRepaint()
....

If there is no other solution, how can I close the attribute table of the joined layer before the new join is set?

I know, there is the showAttributeTable() method. Is there also a closeAttributeTable() method?

It works when I close the specific attribute table in the def __init__(self, parent): function on Plugin startup. It doesn't work when I close the specific attribute table in the function where I set the joins (setJoin(self)).

Here is a sample of my code:

class mask_n_functions(QDialog, Ui_Dialog):

def __init__(self, parent):
    QDialog.__init__(self, parent)
    self.setupUi(self)
    ...
    attrTables = [d for d in QApplication.instance().allWidgets() if d.objectName() == u'QgsAttributeTableDialog' or d.objectName() == u'AttributeTable' ]
    for x in attrTables:
        if 'attr_table' in x.windowTitle():
            x.close()

def setJoin(self):
    prjpath = QgsProject.instance().fileName()
    ...

2 Answers 2

8

For QGIS 3

  • If only one attribute table is opened:

    from PyQt5.QtWidgets import QApplication
    
    all_widgets = QApplication.instance().allWidgets()
    attribute_table_widgets = [widget for widget in all_widgets if "AttributeTable" in widget.objectName()]
    attribute_table_widgets[0].close()
    
  • If multiple attribute tables are opened:

    from PyQt5.QtWidgets import QApplication
    
    all_widgets = QApplication.instance().allWidgets()
    attribute_table_widgets = [widget for widget in all_widgets if "AttributeTable" in widget.objectName()]
    for attribute_table in attribute_table_widgets:
        attribute_table.close()
    
  • If specific attribute table(s) has to be closed:

    from PyQt5.QtWidgets import QApplication
    
    all_widgets = QApplication.instance().allWidgets()
    attribute_table_widgets = [widget for widget in all_widgets if "AttributeTable" in widget.objectName()]
    for attribute_table in attribute_table_widgets:
        if 'PUNKTE' in attribute_table.objectName():
            attribute_table.close()
    

For QGIS 2

  • If only one attribute table is opened:

    from PyQt4.QtGui import QApplication
    
    all_widgets = QApplication.instance().allWidgets()
    attrTables = [widget for widget in all_widgets if widget.objectName() == u'QgsAttributeTableDialog' or widget.objectName() == u'AttributeTable']
    attrTables[0].close()
    
  • If multiple attribute tables are opened:

    from PyQt4.QtGui import QApplication
    
    all_widgets = QApplication.instance().allWidgets()
    attrTables = [widget for widget in all_widgets if widget.objectName() == u'QgsAttributeTableDialog' or widget.objectName() == u'AttributeTable']
    for attrTable in attrTables:
      attrTable.close()
    
  • If specific attribute table(s) has to be closed:

    from PyQt4.QtGui import QApplication
    
    all_widgets = QApplication.instance().allWidgets()
    attrTables = [widget for widget in all_widgets if widget.objectName() == u'QgsAttributeTableDialog' or widget.objectName() == u'AttributeTable']
    for attrTable in attrTables:
      if 'PUNKTE' in attrTable.windowTitle():
          attrTable.close()
    
7
  • How can I close the attribute table of the layer "PUNKTE"? How can I get the names of the QDialog list attrTables?
    – Stefan
    Commented Mar 10, 2017 at 10:15
  • @Stefan - Edited my post to include an additional method. It's not a very direct method to closing attribute tables so I'm curious to see if there is a more efficient solution :). Note that the last method will close all attribute tables of layers which contains "PUNKTE" in their name. So ideally, you would want your layers to have unique names.
    – Joseph
    Commented Mar 10, 2017 at 10:33
  • I tried a lot of combinations (closing one, multiple or distinct attribute table), but nothing works. There must be a difference between, there is no attribute table open and closing attribute table with the plugin and the methods in your answer. It is strange, closing attribute table this way seems not like closing it "with hand" a priori. I tried also to refresh all layers in the canvas.
    – Stefan
    Commented Mar 14, 2017 at 12:19
  • @Stefan - Perhaps you can edit your question to include the code you used for joining the layers and attempting to remove the attribute table.
    – Joseph
    Commented Mar 15, 2017 at 9:42
  • It works when I close the specific attribute table in the def __init__(self, parent): function (calling plugin with panel). It doesn't work when I close the specific attribute table in the function where I set the joins.
    – Stefan
    Commented Oct 5, 2017 at 7:43
1

a bit shorter:

first a list of all tables for a specific layer:

vlayer = iface.activeLayer()
filtered_widgets = [widget for widget in QApplication.instance().allWidgets() if isinstance(widget,QDialog) and widget.objectName() == f"QgsAttributeTableDialog/{vlayer.id()}"]

then iterate and inspect...

for widget in filtered_widgets:
    print(f"'{widget.objectName()}'\
    \n\t'{type(widget)}'\
    \n\t{isinstance(widget,QDialog)}")

...or iterate and close:

for widget in filtered_widgets:
   widget.close()

Caveat:

Depends on the objectName of the attribute-table "QgsAttributeTableDialog/layer.id()" and the used Qt-Widget-Type QDialog, which might change in future QGis/Qt-Versions...

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.