5

I have a problem related to this question and the script. I can add some functionalities to Attribute Table (AT) by the script in the post. But according to the post, I have to open the AT using showAttributeTable method, because the method returns the reference of the AT created/opened. Of course, I can get all references of the ATs opened, using the following line.

tables = [t for t in qApp.allWidgets() if t.objectName() == 'AttributeTable']

Let's say, I want to add a button to all AT to be opened later. Somehow, I think I need to catch "the AT's opening event" or "a widget/child was added to the iface.mainWindow()" etc. I have looked at Qt documentation, but I couldn't find anything or I missed.

Briefly, I need to the reference of any AT while/before it is opening.

7

Interesting question! I couldn't find any native signal emitted when an attribute table is opened or closed so I would call this solution a fairly inelegant workaround but it seems to work well enough. I found that QApplication has a focusChanged(old, new) signal which is emitted whenever the widget focus changes e.g. opening/ closing dialogs or clicking between non-modal windows etc. and returns the old and new widget objects.

class addAttributeTableAction(object):

    def __init__(self, app):
        self.app = app
        self.app.focusChanged.connect(self.attribute_dialog_opened)

    def __del__(self):
        self.app.focusChanged.disconnect(self.attribute_dialog_opened)

    def attribute_dialog_opened(self, old, new):
        if isinstance(new, QTableView):
            #I don't like the line below but I could't think of a better/quicker way to
            #return the Dialog object from the QTableView object returned by the 'new' parameter
            #of the focusChanged signal
            table_dialog = new.parent().parent().parent().parent()
            toolbar = [c for c in table_dialog.children() if isinstance(c, QToolBar)][0]
            # check if action has already been added to toolbar
            already_exists = [a for a in toolbar.actions() if a.objectName() == 'TestAction']
            if not already_exists:
                new_button = QAction('Test', table_dialog)
                new_button.setObjectName('TestAction')
                toolbar.addAction(new_button)
                new_button.triggered.connect(self.run_action)

    def run_action(self):
        '''Simple method to test action'''
        layer = iface.activeLayer()
        layer.selectByIds([1])

Test = addAttributeTableAction(qApp)
#Uncomment below andcomment above to stop listening for focusChanged signal
#del Test

Quick demo:

enter image description here

  • Thank you for your answer. But in this case, I still have to focus on the attribute table to get its reference. Adding a button is just an example. if I want to maximize the AT on second screen and sort by a specific column etc. without focusing, what should I do then? You've got a point after all. – Kadir Şahbaz Dec 3 '19 at 9:08

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.