def load_list(controller_widget, control_name, control_instance): controller_widget = get_ref(controller_widget) control_instance = get_ref(control_instance) # get widget via a __self__ in a method, because control_instance may # be a weakproxy. widget = control_instance.__repr__.__self__ fname = qt_backend.getOpenFileName( widget, "Open file", "", "", None, QtGui.QFileDialog.DontUseNativeDialog) if fname: parent_controller = controller_widget.controller elem_trait = parent_controller.trait(control_name).inner_traits[0] text = open(fname).read() if fname.endswith('.csv'): format = 'CSV' else: format = 'JSON' value = ListControlWidget.parse_list(text, format, ',', elem_trait) if value is not None: setattr(parent_controller, control_name, value) else: QtGui.QMessageBox.warning(controller_widget, 'Parsing error', 'Could not parse the input file', QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Cancel)
def enter_list(controller_widget, control_name, control_instance): controller_widget = get_ref(controller_widget) widget = ListValuesEditor(controller_widget, controller_widget, control_name) done = False while not done: if widget.exec_(): parent_controller = controller_widget.controller elem_trait \ = parent_controller.trait(control_name).inner_traits[0] value = ListControlWidget.parse_list( widget.textedit.toPlainText(), widget.format_c.currentText(), widget.separator_c.currentText(), elem_trait) if value is not None: setattr(parent_controller, control_name, value) done = True else: r = QtGui.QMessageBox.warning( controller_widget, 'Parsing error', 'Could not parse the text input', QtGui.QMessageBox.Retry | QtGui.QMessageBox.Abort, QtGui.QMessageBox.Retry) if r == QtGui.QMessageBox.Abort: done = True else: done = True
def select_files(controller_widget, control_name, control_instance): control_instance = get_ref(control_instance) parent_controller = controller_widget.controller elem_trait = parent_controller.trait(control_name).inner_traits[0] fnames = None current_dir = os.path.join(os.getcwd(), os.pardir) if isinstance(elem_trait.trait_type, traits.Directory): # Create a dialog to select a directory fdialog = QtGui.QFileDialog( control_instance, "Open directories", current_dir) fdialog.setOptions(QtGui.QFileDialog.ShowDirsOnly | QtGui.QFileDialog.DontUseNativeDialog) fdialog.setFileMode(QtGui.QFileDialog.Directory) fdialog.setModal(True) if fdialog.exec_(): fnames = fdialog.selectedFiles() else: if elem_trait.output: fdialog = QtGui.QFileDialog( control_instance, "Output files", current_dir) fdialog.setOptions(QtGui.QFileDialog.DontUseNativeDialog) fdialog.setFileMode(QtGui.QFileDialog.AnyFile) fdialog.setModal(True) if fdialog.exec_(): fnames = fdialog.selectedFiles() else: fdialog = QtGui.QFileDialog( control_instance, "Open files", current_dir) fdialog.setOptions(QtGui.QFileDialog.DontUseNativeDialog) fdialog.setFileMode(QtGui.QFileDialog.ExistingFiles) fdialog.setModal(True) if fdialog.exec_(): fnames = fdialog.selectedFiles() # Set the selected files to the path sub control if fnames is not None: old_value = getattr(parent_controller, control_name) new_value = old_value + fnames setattr(parent_controller, control_name, new_value)
def edit_elements(controller_widget, control_instance, edit_button): """ Callback to view/edit a 'ListControlWidget'. Parameters ---------- control_instance: QFrame (mandatory) the list widget item edit_button: QToolButton the signal sender """ controller_widget = get_ref(controller_widget) widget = QtGui.QDialog(controller_widget) widget.setModal(True) layout = QtGui.QVBoxLayout() widget.setLayout(layout) #hlayout = QtGui.QHBoxLayout() #layout.addLayout(hlayout) temp_controller = Controller() trait = control_instance.trait temp_controller.add_trait(control_instance.trait_name, trait) if temp_controller.trait(control_instance.trait_name).groups \ is not None: temp_controller.trait(control_instance.trait_name).groups = None value = getattr(controller_widget.controller, control_instance.trait_name) try: setattr(temp_controller, control_instance.trait_name, value) except Exception: # invalid value - don't prevent using the GUI pass control_types = dict(controller_widget._defined_controls) control_types['List'] = ListControlWidget control_types['List_File'] = ListControlWidget temp_controller_widget = ScrollControllerWidget( temp_controller, live=True, override_control_types=control_types, user_data=control_instance.user_data) layout.addWidget(temp_controller_widget) hlayout2 = QtGui.QHBoxLayout() layout.addLayout(hlayout2) hlayout2.addStretch(1) ok = QtGui.QPushButton('OK') cancel = QtGui.QPushButton('Cancel') hlayout2.addWidget(ok) hlayout2.addWidget(cancel) ok.pressed.connect(widget.accept) cancel.pressed.connect(widget.reject) if widget.exec_(): ctrl = temp_controller_widget.controller_widget._controls.get( control_instance.trait_name)[None] ListControlWidget.validate_all_values( temp_controller_widget.controller_widget, ctrl[2]) new_trait_value = getattr(temp_controller, control_instance.trait_name) setattr(controller_widget.controller, control_instance.trait_name, new_trait_value) del temp_controller_widget
def create_widget(parent, control_name, control_value, trait, label_class=None, max_items=0): """ Method to create the list widget. Parameters ---------- parent: QWidget (mandatory) the parent widget control_name: str (mandatory) the name of the control we want to create control_value: list of items (mandatory) the default control value trait: Tait (mandatory) the trait associated to the control label_class: Qt widget class (optional, default: None) the label widget will be an instance of this class. Its constructor will be called using 2 arguments: the label string and the parent widget. max_items: int (optional) display at most this number of items. Defaults to 0: no limit. Returns ------- out: 2-uplet a two element tuple of the form (control widget: , associated labels: (a label QLabel, the tools QWidget)) """ # Get the inner trait: expect only one inner trait # note: trait.inner_traits might be a method (ListInt) or a tuple # (List), whereas trait.handler.inner_trait is always a method if len(trait.handler.inner_traits()) == 1: inner_trait = trait.handler.inner_traits()[0] elif len(trait.handler.inner_traits()) == 0: # maybe a generic list, or a compount trait if hasattr(trait.handler, 'handlers') \ and len(trait.handler.handlers) > 0 \ and hasattr(trait.handler.handlers[0], 'inner_traits') \ and len(trait.handler.handlers[0].inner_traits()) > 0: inner_trait = trait.handler.handlers[0].inner_traits()[0] else: # can't determine type, fallback to string inner_trait = traits.Str() else: raise Exception( "Expect only one inner trait in List control. Trait '{0}' " "inner trait is '{1}'.".format(control_name, trait.handler.inner_traits())) if control_value is traits.Undefined: control_value = [] # Create the list widget: a frame parent = get_ref(parent) frame = QtGui.QFrame(parent=parent) #frame.setFrameShape(QtGui.QFrame.StyledPanel) frame.setFrameShape(QtGui.QFrame.NoFrame) # Create tools to interact with the list widget: expand or collapse - # add a list item - remove a list item tool_widget = QtGui.QWidget(parent) layout = QtGui.QHBoxLayout() layout.addStretch(1) layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(2) tool_widget.setLayout(layout) # Create the tool buttons resize_button = QtGui.QToolButton() add_button = QtGui.QToolButton() delete_button = QtGui.QToolButton() layout.addWidget(resize_button) layout.addWidget(add_button) layout.addWidget(delete_button) # Set the tool icons icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/soma_widgets_icons/add")), QtGui.QIcon.Normal, QtGui.QIcon.Off) add_button.setIcon(icon) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/soma_widgets_icons/delete")), QtGui.QIcon.Normal, QtGui.QIcon.Off) delete_button.setIcon(icon) icon = QtGui.QIcon() icon.addPixmap( QtGui.QPixmap(_fromUtf8(":/soma_widgets_icons/nav_down")), QtGui.QIcon.Normal, QtGui.QIcon.Off) resize_button.setIcon(icon) resize_button.setFixedSize(30, 22) add_button.setFixedSize(40, 22) delete_button.setFixedSize(40, 22) menu = QtGui.QMenu() menu.addAction( 'Enter list', partial(ListControlWidget.enter_list, weak_proxy(parent), control_name, weak_proxy(frame))) menu.addAction( 'Load list', partial(ListControlWidget.load_list, weak_proxy(parent), control_name, weak_proxy(frame))) if isinstance(inner_trait.trait_type, traits.File) \ or isinstance(inner_trait.trait_type, traits.Directory): menu.addAction( 'Select files', partial(ListControlWidget.select_files, weak_proxy(parent), control_name, weak_proxy(frame))) add_button.setMenu(menu) menu = QtGui.QMenu() menu.addAction( 'Clear all', partial(ListControlWidget.clear_all, weak_proxy(parent), control_name, weak_proxy(frame), trait.trait_type.minlen)) delete_button.setMenu(menu) # Create a new controller that contains length 'control_value' inner # trait elements controller = ListController() if inner_trait.groups: del inner_trait.groups n = max_items if n == 0: n = len(control_value) for cnt, inner_control_values in enumerate(control_value[:n]): controller.add_trait(str(cnt), inner_trait) #if inner_trait.groups: #del trait(str(cnt)).groups setattr(controller, str(cnt), inner_control_values) # Create the associated controller widget controller_widget = ControllerWidget(controller, parent=frame, live=True) controller_widget.setObjectName('inner_controller') controller_widget.setStyleSheet( 'ControllerWidget#inner_controller { padding: 0px; }') # Store some parameters in the list widget frame.inner_trait = inner_trait frame.trait = trait frame.controller = controller frame.controller_widget = controller_widget frame.connected = False frame.max_items = max_items # Add the list controller widget to the list widget frame.setLayout(controller_widget.layout()) frame.layout().setContentsMargins(0, 0, 0, 0) frame.setObjectName('inner_frame') frame.setStyleSheet('QFrame#inner_frame { padding: 0px; }') # Set some callback on the list control tools # Resize callback resize_hook = partial(ListControlWidget.expand_or_collapse, weak_proxy(frame), weak_proxy(resize_button)) resize_button.clicked.connect(resize_hook) # Add list item callback add_hook = partial(ListControlWidget.add_list_item, weak_proxy(parent), control_name, weak_proxy(frame)) add_button.clicked.connect(add_hook) # Delete list item callback delete_hook = partial(ListControlWidget.delete_list_item, weak_proxy(parent), control_name, weak_proxy(frame)) delete_button.clicked.connect(delete_hook) # Create the label associated with the list widget control_label = trait.label if control_label is None: control_label = control_name if label_class is None: label_class = QtGui.QLabel if control_label is not None: label = label_class(control_label, parent) else: label = None return (frame, (label, tool_widget))