pythonpyqtpyqt5signals-slotsqsignalmapper

How to use QSignalMapper with QActions created dynamically?


I'd like to create a dynamic menu which enumerates all QDockWidget from my QMainWindow and allows to show/hide the QDockWidgets, so far I got this code:

class PluginActionsViewDocks():

    def __init__(self, main_window):
        self.main_window = main_window

        mapper = QSignalMapper(self.main_window)

        self.actions = []
        for dock in main_window.findChildren(QtWidgets.QDockWidget):
            action = create_action(
                main_window, dock.windowTitle(),
                slot=mapper.map,
                tooltip='Show {0} dock'.format(dock.windowTitle())
            )
            mapper.setMapping(action, dock)
            self.actions.append(action)

        mapper.mapped.connect(self.toggle_dock_widget)
        help_menu = main_window.menuBar().addMenu('&View')
        setattr(help_menu, "no_toolbar_policy", True)
        add_actions(help_menu, tuple(self.actions))

    def toggle_dock_widget(self, dock_widget):
        print("toggle_dock_widget")

The menu is populated with all QDockWidget windowTitles but when i press each of them the slot toggle_dock_widget is not called. create_action is a helper which creates the QAction and connect the triggered signal to slot.

The thing is, I don't really understand quite well how QSignalMapper works but my intuition tells me it's the right choice for this particular problem.

What could I be missing here?


Solution

  • There's aleady a built-in dock-widget menu. Just right-click any dock title-bar, or any tool-bar or menu-bar. See: QMainWindow::createPopupMenu.

    PS:

    The reason why your QSignalMapper code doesn't work is probably because you are connecting to the wrong overload of the mapped signal. Try this instead:

        mapper.mapped[QtWidgets.QWidget].connect(self.toggle_dock_widget)