From 7d1939466c1cdc15afb5fea83eb3c9f5deb1f7cc Mon Sep 17 00:00:00 2001 From: Matthieu Dartiailh Date: Thu, 22 Aug 2013 13:51:38 +0200 Subject: [PATCH 1/2] Patch for list_editor in qt4 --- traitsui/qt4/helper.py | 2 +- traitsui/qt4/list_editor.py | 47 +++++++++++++++++++++++++++++-------- traitsui/qt4/menu.py | 16 ++++++------- 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/traitsui/qt4/helper.py b/traitsui/qt4/helper.py index 652fbc4c5..050576add 100644 --- a/traitsui/qt4/helper.py +++ b/traitsui/qt4/helper.py @@ -198,7 +198,7 @@ def __init__(self, icon, slot): self.setFlat(True) self.setFocusPolicy(QtCore.Qt.NoFocus) - QtCore.QObject.connect(self, QtCore.SIGNAL('clicked()'), slot) + self.clicked.connect(slot) #------------------------------------------------------------------------------- # Dock-related stubs. diff --git a/traitsui/qt4/list_editor.py b/traitsui/qt4/list_editor.py index d53b187e5..64a9c2342 100644 --- a/traitsui/qt4/list_editor.py +++ b/traitsui/qt4/list_editor.py @@ -20,7 +20,7 @@ from pyface.api import ImageResource -from traits.api import Str, Any, Bool, Dict +from traits.api import Str, Any, Bool, Dict, List, Instance from traits.trait_base import user_name_for, enumerate, xgetattr # FIXME: ToolkitEditorFactory is a proxy class defined here just for backward @@ -53,6 +53,13 @@ class SimpleEditor ( Editor ): # Is the list of items being edited mutable? mutable = Bool( True ) + #Signal mapper allowing to identify which icon button requested a context + #menu + mapper = Instance(QtCore.QSignalMapper) + + #List of icon button of that list + controls = List(Instance(QtGui.QPushButton),[]) + #--------------------------------------------------------------------------- # Class constants: #--------------------------------------------------------------------------- @@ -105,6 +112,9 @@ def init ( self, parent ): self.control.setFrameShape(QtGui.QFrame.NoFrame) self.control.setWidgetResizable(True) + #Create a mapper to identify which icon button requested a contextmenu + self.mapper = QtCore.QSignalMapper(self.control) + # Create a widget with a grid layout as the container. self._list_pane = QtGui.QWidget() self._list_pane.setSizePolicy(QtGui.QSizePolicy.Expanding, @@ -152,6 +162,9 @@ def update_editor ( self ): """ Updates the editor when the object trait changes externally to the editor. """ + self.mapper = QtCore.QSignalMapper(self.control) + #Cleaning the list of icon buttons + self.controls = [] # Disconnect the editor from any control about to be destroyed: self._dispose_items() @@ -167,6 +180,8 @@ def update_editor ( self ): is_fake = (resizable and (len( self.value ) == 0)) if is_fake: self.empty_list() + else: + self.mapper.mapped.connect(self.popup_menu) editor = self._editor for index, value in enumerate(self.value): @@ -177,7 +192,13 @@ def update_editor ( self ): column = column * 2 if resizable: - control = IconButton('list_editor.png', self.popup_menu) + #Connecting the new button to the mapper + control = IconButton('list_editor.png', self.mapper.map) + self.controls.append(control) + #Setting the mapping and asking it to send the index of the + #sender to the callback method + self.mapper.setMapping(control, index) + layout.addWidget(control, row, column) proxy = ListItemProxy( self.object, self.name, index, item_trait, @@ -232,7 +253,13 @@ def update_editor_item ( self, event ): def empty_list ( self ): """ Creates an empty list entry (so the user can add a new item). """ - control = IconButton('list_editor.png', self.popup_empty_menu) + #Connecting the new button to the mapper + control = IconButton('list_editor.png', self.mapper.map) + self.controls = [control] + #Setting the mapping and asking it to send the index of the + #sender to the callback method + self.mapper.setMapping(control, 0) + self.mapper.mapped.connect(self.popup_empty_menu) control.is_empty = True self._cur_control = control @@ -258,10 +285,11 @@ def get_info ( self ): # Displays the empty list editor popup menu: #--------------------------------------------------------------------------- - def popup_empty_menu ( self ): + def popup_empty_menu ( self , sender_index): """ Displays the empty list editor popup menu. """ - self._cur_control = control = self.control.sender() + #Get the sender from the list of icon button with its index + self._cur_control = control = self.controls[sender_index] menu = MakeMenu( self.empty_list_menu, self, True, control ).menu menu.exec_(control.mapToGlobal(QtCore.QPoint(0, 0))) @@ -269,12 +297,11 @@ def popup_empty_menu ( self ): # Displays the list editor popup menu: #--------------------------------------------------------------------------- - def popup_menu ( self ): + def popup_menu ( self , sender_index): """ Displays the list editor popup menu. """ - layout = self._list_pane.layout() - sender = layout.sender() - + #Get the sender from the list of icon button with its index + sender = self.controls[sender_index] self._cur_control = sender proxy = sender.proxy @@ -569,7 +596,7 @@ def update_editor ( self ): # Remember the page for later deletion processing: self._uis.append([ui.control, ui, view_object, monitoring]) - if self.selected: + if self.selected: self._selected_changed(self.selected) #--------------------------------------------------------------------------- diff --git a/traitsui/qt4/menu.py b/traitsui/qt4/menu.py index 880114cd6..31b0f7437 100644 --- a/traitsui/qt4/menu.py +++ b/traitsui/qt4/menu.py @@ -178,16 +178,16 @@ def parse ( self, menu, indent ): if name: self.names[name] = act setattr(self.owner, name, MakeMenuItem(self, act)) + else: + # Else must be the start of a sub menu: + submenu = QtGui.QMenu(line.strip()) - # Else must be the start of a sub menu: - submenu = QtGui.QMenu(line.strip()) + # Recursively parse the sub-menu: + self.parse(submenu, indented) - # Recursively parse the sub-menu: - self.parse(submenu, indented) - - # Add the menu to its parent: - act = menu.addMenu(submenu) - act.setStatusTip(help) + # Add the menu to its parent: + act = menu.addMenu(submenu) + act.setStatusTip(help) #--------------------------------------------------------------------------- # Returns the body of an inline method: From 2921e7d461989de83bfcccdb21e11d451c4b2040 Mon Sep 17 00:00:00 2001 From: Matthieu Dartiailh Date: Fri, 23 Aug 2013 22:10:20 +0200 Subject: [PATCH 2/2] Replaced the sending of an int as a mean to identify the sender by directly using the sender by providing the mapped signal with [QtCore.QObject] (QtGui.QWidget does not seem to work). --- traitsui/qt4/list_editor.py | 48 ++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/traitsui/qt4/list_editor.py b/traitsui/qt4/list_editor.py index 64a9c2342..9c4d61959 100644 --- a/traitsui/qt4/list_editor.py +++ b/traitsui/qt4/list_editor.py @@ -3,7 +3,8 @@ # All rights reserved. # # This software is provided without warranty under the terms of the BSD license. -# However, when used with the GPL version of PyQt the additional terms described in the PyQt GPL exception also apply +# However, when used with the GPL version of PyQt the additional terms described +# in the PyQt GPL exception also apply # # Author: Riverbank Computing Limited @@ -20,7 +21,7 @@ from pyface.api import ImageResource -from traits.api import Str, Any, Bool, Dict, List, Instance +from traits.api import Str, Any, Bool, Dict, Instance from traits.trait_base import user_name_for, enumerate, xgetattr # FIXME: ToolkitEditorFactory is a proxy class defined here just for backward @@ -53,13 +54,10 @@ class SimpleEditor ( Editor ): # Is the list of items being edited mutable? mutable = Bool( True ) - #Signal mapper allowing to identify which icon button requested a context - #menu + # Signal mapper allowing to identify which icon button requested a context + # menu mapper = Instance(QtCore.QSignalMapper) - #List of icon button of that list - controls = List(Instance(QtGui.QPushButton),[]) - #--------------------------------------------------------------------------- # Class constants: #--------------------------------------------------------------------------- @@ -163,8 +161,6 @@ def update_editor ( self ): editor. """ self.mapper = QtCore.QSignalMapper(self.control) - #Cleaning the list of icon buttons - self.controls = [] # Disconnect the editor from any control about to be destroyed: self._dispose_items() @@ -179,9 +175,10 @@ def update_editor ( self ): is_fake = (resizable and (len( self.value ) == 0)) if is_fake: - self.empty_list() + self.empty_list() else: - self.mapper.mapped.connect(self.popup_menu) + # Asking the mapper to send the sender to the callback method + self.mapper.mapped[QtCore.QObject].connect(self.popup_menu) editor = self._editor for index, value in enumerate(self.value): @@ -192,12 +189,11 @@ def update_editor ( self ): column = column * 2 if resizable: - #Connecting the new button to the mapper + # Connecting the new button to the mapper control = IconButton('list_editor.png', self.mapper.map) - self.controls.append(control) - #Setting the mapping and asking it to send the index of the - #sender to the callback method - self.mapper.setMapping(control, index) + # Setting the mapping and asking it to send the index of the + # sender to the callback method + self.mapper.setMapping(control, control) layout.addWidget(control, row, column) @@ -253,13 +249,12 @@ def update_editor_item ( self, event ): def empty_list ( self ): """ Creates an empty list entry (so the user can add a new item). """ - #Connecting the new button to the mapper + # Connecting the new button to the mapper control = IconButton('list_editor.png', self.mapper.map) - self.controls = [control] - #Setting the mapping and asking it to send the index of the - #sender to the callback method - self.mapper.setMapping(control, 0) - self.mapper.mapped.connect(self.popup_empty_menu) + # Setting the mapping and asking it to send the sender to the + # callback method + self.mapper.setMapping(control, control) + self.mapper.mapped[QtCore.QObject].connect(self.popup_empty_menu) control.is_empty = True self._cur_control = control @@ -285,11 +280,10 @@ def get_info ( self ): # Displays the empty list editor popup menu: #--------------------------------------------------------------------------- - def popup_empty_menu ( self , sender_index): + def popup_empty_menu ( self , sender): """ Displays the empty list editor popup menu. """ - #Get the sender from the list of icon button with its index - self._cur_control = control = self.controls[sender_index] + self._cur_control = control = sender menu = MakeMenu( self.empty_list_menu, self, True, control ).menu menu.exec_(control.mapToGlobal(QtCore.QPoint(0, 0))) @@ -297,11 +291,9 @@ def popup_empty_menu ( self , sender_index): # Displays the list editor popup menu: #--------------------------------------------------------------------------- - def popup_menu ( self , sender_index): + def popup_menu ( self , sender): """ Displays the list editor popup menu. """ - #Get the sender from the list of icon button with its index - sender = self.controls[sender_index] self._cur_control = sender proxy = sender.proxy