def create_output_widget(self): """ Method to create the output controller widget built from the class controller output traits """ self.output_controller_widget = ControllerWidget( self.controller, parent=self, name="outputs", live=True, hide_labels=False, select_controls="outputs") self.output_controller_widget.setEnabled(False)
# Set the logging level logging.basicConfig(level=logging.INFO) # Create a qt applicaction app = QtGui.QApplication(sys.argv) # Create the controller we want to parametrized controller = TestControls() # Set some values to the controller parameters controller.s = "" controller.f = 10.2 # Create to controller widget that are synchronized on the fly widget1 = ScrollControllerWidget(controller, live=True) widget2 = ControllerWidget(controller, live=True) widget1.show() widget2.show() # Check if the controller widget is valid before edition print("Controller widget valid before edition: ", end=' ') print(widget1.controller_widget.is_valid()) # Start the qt loop app.exec_() # Check if the controller widget is valid after edition print("Controller widget valid after edition: ", end=' ') print(widget1.controller_widget.is_valid())
class BoardWidget(QtGui.QWidget): """ Class that create a widget to visualize the controller status. """ def __init__(self, controller, parent=None, name=None): """ Method to initilaize the ControllerWidget class. Parameters ---------- controller: derived Controller instance (mandatory) a class derived from the Controller class we want to parametrize with a widget. parent: QtGui.QWidget (optional, default None) the controller widget parent widget. name: (optional, default None) the name of this controller widget """ # Inheritance super(BoardWidget, self).__init__(parent) # Class parameters self.controller = controller # If possilbe, set the widget name if name: self.setObjectName(name) # Create the layout of the board widget # Three item layout: output_controller_widget - board_tree - viewer_tree self._grid_layout = QtGui.QGridLayout() self._grid_layout.setAlignment(QtCore.Qt.AlignTop) self._grid_layout.setSpacing(3) self._grid_layout.setContentsMargins(5, 5, 5, 5) self.setLayout(self._grid_layout) # Create all the controls self.create_output_widget() self.create_viewer_tree() self.create_board_tree() # Fill the grid layout self._grid_layout.addWidget(self.board_tree, 0, 0, 1, 2) self._grid_layout.addWidget(self.output_controller_widget, 1, 0, 1, 1) self._grid_layout.addWidget(self.viewer_tree, 1, 1, 1, 1) # Create the board self._fill_trees() ########################################################################### # Methods ########################################################################### def create_output_widget(self): """ Method to create the output controller widget built from the class controller output traits """ self.output_controller_widget = ControllerWidget( self.controller, parent=self, name="outputs", live=True, hide_labels=False, select_controls="outputs") self.output_controller_widget.setEnabled(False) def create_viewer_tree(self): """ Method to create a tree with two columns (pipeline name - viewers) that will summarize all the available quality control nodes """ # Create the tree widget self.viewer_tree = QtGui.QTreeWidget(parent=self) # Initilize the tree widget self.viewer_tree.setColumnCount(2) self.viewer_tree.headerItem().setText(0, "Pipeline Name") self.viewer_tree.headerItem().setText(1, "Viewers") def create_board_tree(self): """ Method to create a tree with five columns (processings - status - execution time - memory - logs) that will summarize all the available quality control nodes """ # Create the tree widget self.board_tree = QtGui.QTreeWidget(parent=self) # Initilize the tree widget self.board_tree.setColumnCount(5) self.board_tree.headerItem().setText(0, "Processings") self.board_tree.headerItem().setText(1, "Status") self.board_tree.headerItem().setText(2, "Execution Time") self.board_tree.headerItem().setText(3, "Memory") self.board_tree.headerItem().setText(4, "Logs") ########################################################################### # Private methods ########################################################################### def _title_for(self, title): """ Method to tune a title name. Juste replace the '_' character by a blank ' '. Parameters ---------- title: str (mandatory) the title name we want to tune. Returns ------- output: str the tuned name """ return title.replace("_", " ") def _fill_trees(self): """ Method to insert processing parameters in the class trees. """ # Generate structures that contain all viewers and all processings # status - metainforamtion viewers_struct = {} processings_struct = [] # Go through all the controller (pipeline) nodes. for node_name, node in self.controller.nodes.iteritems(): # If the current node is a processing node if node_name is not "" and node.node_type != "view_node": # First browse the current node to get processings and viewers process_nodes = [] view_nodes = [] self.browse_node( node, process_nodes, view_nodes, self.controller) # Set process logs #for process_node in process_nodes: # widget = LogWidget(process_node) # widget.setParent(root.treeWidget()) # child.treeWidget().setItemWidget(child, 3, widget) # Fill the processing structure for processing_node in process_nodes: processings_struct.append({ "name": processing_node.name, "log": processing_node.process.log_file or "No log"}) # Fill the viewer structure for viewer_node, pipeline in view_nodes: # Create a viewer widget (a simple press button) widget = ViewerWidget(viewer_node.name, pipeline, None) #self._study_config) # Store the widget in the corresponding structure title = self._title_for(pipeline.name) if title not in viewers_struct: viewers_struct[title] = [] viewers_struct[title].append(widget) # If the current node is a viewer node elif node.node_type == "view_node": # Create a viewer widget (a simple press button) widget = ViewerWidget(node_name, self.controller, None) #self._study_config) # Store the widget in the corresponding structure title = self._title_for(self.controller.name) if title not in viewers_struct: viewers_struct[title] = [] viewers_struct[title].append(widget) # Fill the viewer tree widget viewer_parent = self.viewer_tree.invisibleRootItem() for pipeline_title, viewer_widgets in viewers_struct.iteritems(): # Create a new tree item viewer_child = QtGui.QTreeWidgetItem(viewer_parent) viewer_child.setText(0, pipeline_title) # Set the viewer widgets in a layout widget_layout = QtGui.QHBoxLayout() widget_layout.setSpacing(0) widget_layout.setSizeConstraint(QtGui.QLayout.SetMinimumSize) widget_layout.setContentsMargins(0, 0, 0, 0) widget_layout.addStretch(1) for widget in viewer_widgets: widget = QtGui.QToolButton() widget_layout.addWidget(widget) # Set the final widget tree item widget = QtGui.QWidget(viewer_child.treeWidget()) widget.setLayout(widget_layout) viewer_child.treeWidget().setItemWidget(viewer_child, 1, widget) # Fill the pboard tree widget board_parent = self.board_tree.invisibleRootItem() for process_info in processings_struct: # Create a new tree item board_child = QtGui.QTreeWidgetItem(board_parent) board_child.setText(0, process_info["name"]) board_child.setText(4, process_info["log"]) def browse_node(self, node, process_nodes, view_nodes, parent_pipeline): """ Find view_node and leaf nodes, ie. Process nodes Parameters ---------- node: Node a capsul node process_nodes: Node node of type processing_node view_nodes: 2-uplet contains the node of type view_node and the pipeline where this node is defined """ # Skip Switch nodes if not isinstance(node, Switch): # Browse recursively pipeline nodes if (isinstance(node.process, Pipeline) and node.node_type != "view_node"): pipeline = node.process for sub_node in pipeline.nodes.values(): if not isinstance(sub_node, PipelineNode): self.browse_node(sub_node, process_nodes, view_nodes, pipeline) # Update the results according to the node type else: if node.node_type == "view_node": view_nodes.append((node, parent_pipeline)) else: process_nodes.append(node)
def create_widget(parent, control_name, control_value, trait, label_class=None): """ Method to create the dict widget. Parameters ---------- parent: QWidget (mandatory) the parent widget control_name: str (mandatory) the name of the control we want to create control_value: dict 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. 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()) != 2: raise Exception( "Expect two inner traits in Dict control. Trait '{0}' " "inner traits are '{1}'.".format( control_name, trait.inner_traits)) inner_trait = trait.handler.inner_traits()[1] # Create the dict widget: a frame frame = QtGui.QFrame(parent=parent) frame.setFrameShape(QtGui.QFrame.StyledPanel) # Create tools to interact with the dict widget: expand or collapse - # add a dict item - remove a dict item tool_widget = QtGui.QWidget(parent) layout = QtGui.QHBoxLayout() layout.addStretch(1) tool_widget.setLayout(layout) # Create the tool buttons resize_button = QtGui.QToolButton() add_button = QtGui.QToolButton() layout.addWidget(resize_button) layout.addWidget(add_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/nav_down")), QtGui.QIcon.Normal, QtGui.QIcon.Off) resize_button.setIcon(icon) resize_button.setFixedSize(30, 22) add_button.setFixedSize(30, 22) # Create a new controller that contains length 'control_value' inner # trait elements controller = DictController() for name, inner_control_values in six.iteritems(control_value): controller.add_trait(str(name), inner_trait) setattr(controller, str(name), inner_control_values) # Create the associated controller widget controller_widget = ControllerWidget(controller, parent=frame, live=True, editable_labels=True) # Store some parameters in the dict widget frame.inner_trait = inner_trait frame.trait = trait frame.controller = controller frame.controller_widget = controller_widget frame.connected = False # Add the dict controller widget to the dict widget frame.setLayout(controller_widget.layout()) # Set some callback on the dict control tools # Resize callback resize_hook = partial( DictControlWidget.expand_or_collapse, weak_proxy(frame), weak_proxy(resize_button)) resize_button.clicked.connect(resize_hook) # Add dict item callback add_hook = partial( DictControlWidget.add_dict_item, parent, control_name, frame) add_button.clicked.connect(add_hook) # Create the label associated with the dict 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 controller_widget.main_controller_def = (DictControlWidget, parent, control_name, frame) return (frame, (label, tool_widget))
def __init__(self, process_with_fom, enable_attr_from_filename=False, enable_load_buttons=False): """ Parameters ---------- process_with_fom: ProcessWithFom instance process with FOM to be displayed enable_attr_from_filename: bool (optional) if enabled, it will be possible to specify an input filename to build FOM attributes from """ super(ProcessWithFomWidget, self).__init__() self.setLayout(QtGui.QVBoxLayout()) self.process_with_fom = process_with_fom if enable_attr_from_filename: c = Controller() c.add_trait('attributes_from_input_filename', File(optional=True)) cw = ControllerWidget(c, live=True) self.layout().addWidget(cw) self.input_filename_controller = c c.on_trait_change(self.on_input_filename_changed, 'attributes_from_input_filename') cw.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) #if self.process_with_fom.study_config.input_fom \ #!= self.process_with_fom.study_config.output_fom: #c.add_trait('attributes_from_output_filename', File()) #c.on_trait_change(self.on_input_filename_changed, #'attributes_from_output_filename') # groupbox area to show attributs attrib_widget = QtGui.QGroupBox('Attributes:') attrib_widget.setAlignment(QtCore.Qt.AlignLeft) attrib_widget.setLayout(QtGui.QVBoxLayout()) self.attrib_widget = attrib_widget self.layout().addWidget(attrib_widget) attrib_widget.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred) hlay = QtGui.QHBoxLayout() self.layout().addLayout(hlay) # CheckBox to foms rules or not self.checkbox_fom = QtGui.QCheckBox('Follow FOM rules') self.checkbox_fom.setChecked(True) self.checkbox_fom.stateChanged.connect(self.on_use_fom_change) hlay.addWidget(self.checkbox_fom) # Button Show/Hide completion self.btn_show_completion = QtGui.QCheckBox('Show completion') self.btn_show_completion.setSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) hlay.addWidget(self.btn_show_completion) self.btn_show_completion.stateChanged.connect(self.on_show_completion) # groupbox area to show completion param_widget = QtGui.QGroupBox('Parameters:') param_widget.setAlignment(QtCore.Qt.AlignLeft) self.layout().addWidget(param_widget) param_widget.setLayout(QtGui.QVBoxLayout()) param_widget.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) # Create controller widget for process and object_attribute process = process_with_fom.process self.controller_widget = ScrollControllerWidget(process, live=True, parent=param_widget) self.controller_widget2 = ScrollControllerWidget(self.process_with_fom, live=True, parent=attrib_widget) self.process_with_fom.on_trait_change( self.process_with_fom.attributes_changed, 'anytrait') # Set controller of attributs and controller of process for each # corresponding area param_widget.layout().addWidget(self.controller_widget) attrib_widget.layout().addWidget(self.controller_widget2) if enable_load_buttons: io_lay = QtGui.QHBoxLayout() self.layout().addLayout(io_lay) self.btn_load_json = QtGui.QPushButton('Load attributes') io_lay.addWidget(self.btn_load_json) self.btn_load_json.clicked.connect(self.on_btn_load_json) self.btn_save_json = QtGui.QPushButton('Save attributes') io_lay.addWidget(self.btn_save_json) self.btn_save_json.clicked.connect(self.on_btn_save_json) self.show_completion(False) # hide file parts
class BoardWidget(QtGui.QWidget): """ Class that create a widget to visualize the controller status. """ def __init__(self, controller, parent=None, name=None): """ Method to initilaize the ControllerWidget class. Parameters ---------- controller: derived Controller instance (mandatory) a class derived from the Controller class we want to parametrize with a widget. parent: QtGui.QWidget (optional, default None) the controller widget parent widget. name: (optional, default None) the name of this controller widget """ # Inheritance super(BoardWidget, self).__init__(parent) # Class parameters self.controller = controller # If possible, set the widget name if name: self.setObjectName(name) # Create the layout of the board widget # Three item layout: output_controller_widget - board_tree - viewer_tree self._grid_layout = QtGui.QGridLayout() self._grid_layout.setAlignment(QtCore.Qt.AlignTop) self._grid_layout.setSpacing(3) self._grid_layout.setContentsMargins(5, 5, 5, 5) self.setLayout(self._grid_layout) # Create all the controls self.create_output_widget() self.create_viewer_tree() self.create_board_tree() # Fill the grid layout self._grid_layout.addWidget(self.board_tree, 0, 0, 1, 2) self._grid_layout.addWidget(self.output_controller_widget, 1, 0, 1, 1) self._grid_layout.addWidget(self.viewer_tree, 1, 1, 1, 1) # Create the board self._fill_trees() ########################################################################### # Methods ########################################################################### def create_output_widget(self): """ Method to create the output controller widget built from the class controller output traits """ self.output_controller_widget = ControllerWidget( self.controller, parent=self, name="outputs", live=True, hide_labels=False, select_controls="outputs") self.output_controller_widget.setEnabled(False) def create_viewer_tree(self): """ Method to create a tree with two columns (pipeline name - viewers) that will summarize all the available quality control nodes """ # Create the tree widget self.viewer_tree = QtGui.QTreeWidget(parent=self) # Initialize the tree widget self.viewer_tree.setColumnCount(2) self.viewer_tree.headerItem().setText(0, "Pipeline Name") self.viewer_tree.headerItem().setText(1, "Viewers") def create_board_tree(self): """ Method to create a tree with five columns (processings - status - execution time - memory - logs) that will summarize all the available quality control nodes """ # Create the tree widget self.board_tree = QtGui.QTreeWidget(parent=self) # Initialize the tree widget self.board_tree.setColumnCount(5) self.board_tree.headerItem().setText(0, "Processings") self.board_tree.headerItem().setText(1, "Status") self.board_tree.headerItem().setText(2, "Execution Time") self.board_tree.headerItem().setText(3, "Memory") self.board_tree.headerItem().setText(4, "Logs") ########################################################################### # Private methods ########################################################################### def _title_for(self, title): """ Method to tune a title name. Juste replace the '_' character by a blank ' '. Parameters ---------- title: str (mandatory) the title name we want to tune. Returns ------- output: str the tuned name """ return title.replace("_", " ") def _fill_trees(self): """ Method to insert processing parameters in the class trees. """ # Generate structures that contain all viewers and all processings # status - metainforamtion viewers_struct = {} processings_struct = [] # Go through all the controller (pipeline) nodes. for node_name, node in six.iteritems(self.controller.nodes): # If the current node is a processing node if node_name != "" and node.node_type != "view_node": # First browse the current node to get processings and viewers process_nodes = [] view_nodes = [] self.browse_node( node, process_nodes, view_nodes, self.controller) # Set process logs #for process_node in process_nodes: # widget = LogWidget(process_node) # widget.setParent(root.treeWidget()) # child.treeWidget().setItemWidget(child, 3, widget) # Fill the processing structure for processing_node in process_nodes: processings_struct.append({ "name": processing_node.name, "log": processing_node.process.log_file or "No log"}) # Fill the viewer structure for viewer_node, pipeline in view_nodes: # Create a viewer widget (a simple press button) widget = ViewerWidget(viewer_node.name, pipeline, None) #self._study_config) # Store the widget in the corresponding structure title = self._title_for(pipeline.name) if title not in viewers_struct: viewers_struct[title] = [] viewers_struct[title].append(widget) # If the current node is a viewer node elif node.node_type == "view_node": # Create a viewer widget (a simple press button) widget = ViewerWidget(node_name, self.controller, None) #self._study_config) # Store the widget in the corresponding structure title = self._title_for(self.controller.name) if title not in viewers_struct: viewers_struct[title] = [] viewers_struct[title].append(widget) # Fill the viewer tree widget viewer_parent = self.viewer_tree.invisibleRootItem() for pipeline_title, viewer_widgets in six.iteritems(viewers_struct): # Create a new tree item viewer_child = QtGui.QTreeWidgetItem(viewer_parent) viewer_child.setText(0, pipeline_title) # Set the viewer widgets in a layout widget_layout = QtGui.QHBoxLayout() widget_layout.setSpacing(0) widget_layout.setSizeConstraint(QtGui.QLayout.SetMinimumSize) widget_layout.setContentsMargins(0, 0, 0, 0) widget_layout.addStretch(1) for widget in viewer_widgets: widget = QtGui.QToolButton() widget_layout.addWidget(widget) # Set the final widget tree item widget = QtGui.QWidget(viewer_child.treeWidget()) widget.setLayout(widget_layout) viewer_child.treeWidget().setItemWidget(viewer_child, 1, widget) # Fill the pboard tree widget board_parent = self.board_tree.invisibleRootItem() for process_info in processings_struct: # Create a new tree item board_child = QtGui.QTreeWidgetItem(board_parent) board_child.setText(0, process_info["name"]) board_child.setText(4, process_info["log"]) def browse_node(self, node, process_nodes, view_nodes, parent_pipeline): """ Find view_node and leaf nodes, ie. Process nodes Parameters ---------- node: Node a capsul node process_nodes: Node node of type processing_node view_nodes: 2-uplet contains the node of type view_node and the pipeline where this node is defined """ # Skip Switch nodes if not isinstance(node, Switch): # Browse recursively pipeline nodes if (isinstance(node.process, Pipeline) and node.node_type != "view_node"): pipeline = node.process for sub_node in pipeline.nodes.values(): if not isinstance(sub_node, PipelineNode): self.browse_node(sub_node, process_nodes, view_nodes, pipeline) # Update the results according to the node type else: if node.node_type == "view_node": view_nodes.append((node, parent_pipeline)) else: process_nodes.append(node)
def __init__(self, attributed_process, enable_attr_from_filename=False, enable_load_buttons=False, override_control_types=None, separate_outputs=True, user_data=None, userlevel=0, scroll=True): """ Parameters ---------- attributed_process: Process instance process with attributes to be displayed enable_attr_from_filename: bool (optional) if enabled, it will be possible to specify an input filename to build attributes from override_control_types: dict (optional) if given, this is a "factory" dict assigning new controller editor types to some traits types in the parameters controller. separate_outputs: bool if True, inputs and outputs (traits with output=True set) will be separated into two boxes. user_data: any type (optional) optional user data that can be accessed by individual control editors userlevel: int the current user level: some traits may be marked with a non-zero userlevel, and will only be visible if the ControllerWidget userlevel is more than (or equal) the trait level. scroll: bool if True, the widget includes scrollbars in the parameters and attributes sections when needed, otherwise it will be a fixed size widget. """ super(AttributedProcessWidget, self).__init__() self.setLayout(QtGui.QVBoxLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.attributed_process = attributed_process self._show_completion = False self.user_data = user_data self.separate_outputs = separate_outputs self._userlevel = userlevel process = attributed_process completion_engine = getattr(process, 'completion_engine', None) if completion_engine is not None: splitter = QtGui.QSplitter(QtCore.Qt.Vertical) self.layout().addWidget(splitter) spl_up = QtGui.QWidget() spl_up.setLayout(QtGui.QVBoxLayout()) splitter.addWidget(spl_up) spl_down = QtGui.QWidget() spl_down.setLayout(QtGui.QVBoxLayout()) splitter.addWidget(spl_down) else: spl_up = self spl_down = self filename_widget = None if enable_attr_from_filename and completion_engine is not None: c = Controller() c.add_trait('attributes_from_input_filename', File(optional=True)) filename_widget = ControllerWidget(c, live=True, user_data=user_data) spl_up.layout().addWidget(filename_widget) self.input_filename_controller = c c.on_trait_change(self.on_input_filename_changed, 'attributes_from_input_filename', dispatch='ui') filename_widget.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) # groupbox area to show attributes attrib_widget = QtGui.QGroupBox('Attributes:') attrib_widget.setFlat(True) attrib_widget.setAlignment(QtCore.Qt.AlignLeft) attrib_widget.setLayout(QtGui.QVBoxLayout()) self.attrib_widget = attrib_widget spl_up.layout().addWidget(attrib_widget) attrib_widget.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred) hlay = QtGui.QHBoxLayout() spl_up.layout().addLayout(hlay) # CheckBox to completion rules or not self.checkbox_fom = QtGui.QCheckBox('Follow completion rules') self.checkbox_fom.setChecked(True) self.checkbox_fom.stateChanged.connect(self.on_use_fom_change) hlay.addWidget(self.checkbox_fom) # Button Show/Hide completion self.btn_show_completion = QtGui.QCheckBox('Show completion') self.btn_show_completion.setSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) hlay.addWidget(self.btn_show_completion) self.btn_show_completion.stateChanged.connect(self.on_show_completion) params = QtGui.QWidget() playout = QtGui.QVBoxLayout() params.setLayout(playout) if scroll: scroll_a = QtGui.QScrollArea() scroll_a.setWidgetResizable(True) scroll_a.setWidget(params) spl_up.layout().addWidget(scroll_a) scroll_a.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) params.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred) CWidgetClass = ScrollControllerWidget else: spl_up.layout().addWidget(params) CWidgetClass = ControllerWidget # groupbox area to show completion if separate_outputs: param_widget = QtGui.QGroupBox('Inputs:') else: param_widget = QtGui.QGroupBox('Parameters:') param_widget.setFlat(True) param_widget.setAlignment(QtCore.Qt.AlignLeft) playout.addWidget(param_widget) param_widget.setLayout(QtGui.QVBoxLayout()) param_widget.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) if separate_outputs: out_widget = QtGui.QGroupBox('Outputs:') out_widget.setFlat(True) out_widget.setAlignment(QtCore.Qt.AlignLeft) playout.addWidget(out_widget) out_widget.setLayout(QtGui.QVBoxLayout()) out_widget.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) # use concise shape for lists GUI from soma.qt_gui.controls import OffscreenListControlWidget control_types_a = {'List': OffscreenListControlWidget} control_types_p = {'List': OffscreenListControlWidget} if override_control_types: control_types_p.update(override_control_types) #ControllerWidget._defined_controls['List'] = OffscreenListControlWidget # Create controller widget for process and object_attribute sel = None if separate_outputs: sel = 'inputs' self.controller_widget = ControllerWidget(process, live=True, parent=param_widget, override_control_types=control_types_p, user_data=user_data, userlevel=userlevel, select_controls=sel) if separate_outputs: self.outputs_cwidget = ControllerWidget(process, live=True, parent=out_widget, override_control_types=control_types_p, user_data=user_data, userlevel=userlevel, select_controls='outputs') show_ce = (completion_engine is not None and len( completion_engine.get_attribute_values().user_traits()) != 0) if completion_engine is not None: self.controller_widget2 = CWidgetClass( completion_engine.get_attribute_values(), live=True, parent=attrib_widget, override_control_types=control_types_a, user_data=user_data, userlevel=userlevel) completion_engine.get_attribute_values().on_trait_change( completion_engine.attributes_changed, 'anytrait') else: self.controller_widget2 = CWidgetClass( Controller(), override_control_types=control_types_a, user_data=user_data, userlevel=userlevel) # Set controller of attributes and controller of process for each # corresponding area param_widget.layout().addWidget(self.controller_widget) if separate_outputs: out_widget.layout().addWidget(self.outputs_cwidget) attrib_widget.layout().addWidget(self.controller_widget2) if enable_load_buttons and completion_engine is not None: io_lay = QtGui.QHBoxLayout() self.layout().addLayout(io_lay) self.btn_load_json = QtGui.QPushButton('Load attributes') io_lay.addWidget(self.btn_load_json) self.btn_load_json.clicked.connect(self.on_btn_load_json) self.btn_save_json = QtGui.QPushButton('Save attributes') io_lay.addWidget(self.btn_save_json) self.btn_save_json.clicked.connect(self.on_btn_save_json) if not show_ce: if filename_widget: filename_widget.hide() attrib_widget.hide() self.checkbox_fom.hide() self.btn_show_completion.hide() if hasattr(self, 'btn_load_json'): self.btn_load_json.hide() self.btn_save_json.hide() self.show_completion(True) # hide file parts else: self.show_completion(False) # hide file parts if completion_engine is not None: completion_engine.on_trait_change( self._completion_progress_changed, 'completion_progress', dispatch='ui')
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))
def create_widget(parent, control_name, control_value, trait, label_class=None): """ Method to create the controller widget. Parameters ---------- parent: QWidget (mandatory) the parent widget control_name: str (mandatory) the name of the control we want to create control_value: instance of Controller (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. Returns ------- out: 2-uplet a two element tuple of the form (control widget: , associated labels: (a label QLabel, the tools QWidget)) """ # Create the list widget: a frame frame = QtGui.QFrame(parent=parent) frame.setFrameShape(QtGui.QFrame.StyledPanel) # 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() layout.addWidget(resize_button) # Set the tool icons 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) editable_labels = False if trait.handler.inner_traits(): editable_labels = True frame.inner_trait = trait.handler.inner_traits()[0] add_button = QtGui.QToolButton() delete_button = QtGui.QToolButton() layout.addWidget(add_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) add_button.setFixedSize(30, 22) delete_button.setFixedSize(30, 22) # Add list item callback add_hook = partial(ControllerControlWidget.add_item, weak_proxy(parent), control_name, weak_proxy(frame)) add_button.clicked.connect(add_hook) # Create the associated controller widget controller_widget = ControllerWidget(control_value, parent=frame, live=True, editable_labels=editable_labels) # Store some parameters in the list widget frame.trait = trait frame.controller = control_value frame.controller_widget = controller_widget frame.connected = False # Add the list controller widget to the list widget frame.setLayout(controller_widget.layout()) # Set some callback on the controller control tools # Resize callback resize_hook = partial(ControllerControlWidget.expand_or_collapse, weak_proxy(frame), weak_proxy(resize_button)) resize_button.clicked.connect(resize_hook) if getattr(trait, 'expanded') is False: ControllerControlWidget.set_expanded(frame, resize_button, False) # Create the label associated with the controller 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))
def __init__(self, attributed_process, enable_attr_from_filename=False, enable_load_buttons=False): """ Parameters ---------- attributed_process: Process instance process with attributes to be displayed enable_attr_from_filename: bool (optional) if enabled, it will be possible to specify an input filename to build attributes from """ super(AttributedProcessWidget, self).__init__() self.setLayout(QtGui.QVBoxLayout()) self.attributed_process = attributed_process self._show_completion = False process = attributed_process completion_engine = getattr(process, 'completion_engine', None) if completion_engine is not None: splitter = QtGui.QSplitter(QtCore.Qt.Vertical) self.layout().addWidget(splitter) spl_up = QtGui.QWidget() spl_up.setLayout(QtGui.QVBoxLayout()) splitter.addWidget(spl_up) spl_down = QtGui.QWidget() spl_down.setLayout(QtGui.QVBoxLayout()) splitter.addWidget(spl_down) else: spl_up = self spl_down = self if enable_attr_from_filename and completion_engine is not None: c = Controller() c.add_trait('attributes_from_input_filename', File(optional=True)) cw = ControllerWidget(c, live=True) spl_up.layout().addWidget(cw) self.input_filename_controller = c c.on_trait_change(self.on_input_filename_changed, 'attributes_from_input_filename', dispatch='ui') cw.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) # groupbox area to show attributs attrib_widget = QtGui.QGroupBox('Attributes:') attrib_widget.setAlignment(QtCore.Qt.AlignLeft) attrib_widget.setLayout(QtGui.QVBoxLayout()) self.attrib_widget = attrib_widget spl_up.layout().addWidget(attrib_widget) attrib_widget.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred) hlay = QtGui.QHBoxLayout() spl_up.layout().addLayout(hlay) # CheckBox to completion rules or not self.checkbox_fom = QtGui.QCheckBox('Follow completion rules') self.checkbox_fom.setChecked(True) self.checkbox_fom.stateChanged.connect(self.on_use_fom_change) hlay.addWidget(self.checkbox_fom) # Button Show/Hide completion self.btn_show_completion = QtGui.QCheckBox('Show completion') self.btn_show_completion.setSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) hlay.addWidget(self.btn_show_completion) self.btn_show_completion.stateChanged.connect(self.on_show_completion) # groupbox area to show completion param_widget = QtGui.QGroupBox('Parameters:') param_widget.setAlignment(QtCore.Qt.AlignLeft) spl_down.layout().addWidget(param_widget) param_widget.setLayout(QtGui.QVBoxLayout()) param_widget.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) # Create controller widget for process and object_attribute self.controller_widget = ScrollControllerWidget(process, live=True, parent=param_widget) if completion_engine is not None: self.controller_widget2 = ScrollControllerWidget( completion_engine.get_attribute_values(), live=True, parent=attrib_widget) completion_engine.get_attribute_values().on_trait_change( completion_engine.attributes_changed, 'anytrait') else: self.controller_widget2 = ScrollControllerWidget(Controller()) # Set controller of attributs and controller of process for each # corresponding area param_widget.layout().addWidget(self.controller_widget) attrib_widget.layout().addWidget(self.controller_widget2) if enable_load_buttons and completion_engine is not None: io_lay = QtGui.QHBoxLayout() self.layout().addLayout(io_lay) self.btn_load_json = QtGui.QPushButton('Load attributes') io_lay.addWidget(self.btn_load_json) self.btn_load_json.clicked.connect(self.on_btn_load_json) self.btn_save_json = QtGui.QPushButton('Save attributes') io_lay.addWidget(self.btn_save_json) self.btn_save_json.clicked.connect(self.on_btn_save_json) if completion_engine is None: attrib_widget.hide() self.checkbox_fom.hide() self.btn_show_completion.hide() self.show_completion(True) # hide file parts else: self.show_completion(False) # hide file parts if completion_engine is not None: completion_engine.on_trait_change( self._completion_progress_changed, 'completion_progress', dispatch='ui')