def _create_group_widget(self, group): group_widget = QtGui.QGroupBox() last_row = self._grid_layout.rowCount() self._grid_layout.addWidget(group_widget, last_row, 0, 1, 2) lay1 = QtGui.QVBoxLayout() lay1.setContentsMargins(0, 0, 0, 0) lay2 = QtGui.QHBoxLayout() lay1.addLayout(lay2) lay2.setContentsMargins(10, 0, 0, 0) lay2.addWidget(QtGui.QLabel('<html><em>%s</em></html>' % group)) lay2.addStretch(1) icon = QtGui.QIcon() icon.addPixmap( QtGui.QPixmap(_fromUtf8(":/soma_widgets_icons/nav_down")), QtGui.QIcon.Normal, QtGui.QIcon.Off) group_widget.fold_button = QtGui.QPushButton(icon, '') group_widget.fold_button.setFixedSize(30, 20) lay2.addWidget(group_widget.fold_button) widget = QtGui.QWidget() group_widget.setLayout(lay1) lay1.addWidget(widget) group_widget.hideable_widget = widget layout = QtGui.QGridLayout() widget.setLayout(layout) layout.setAlignment(QtCore.Qt.AlignTop) layout.setSpacing(3) layout.setContentsMargins(5, 5, 5, 5) group_widget.setAlignment(QtCore.Qt.AlignLeft) visible_groups = getattr(self.controller, 'visible_groups', set()) if group in visible_groups: show = True else: show = False group_widget.hideable_widget.setVisible(show) if not show: icon = QtGui.QIcon() icon.addPixmap( QtGui.QPixmap(_fromUtf8(":/soma_widgets_icons/nav_right")), QtGui.QIcon.Normal, QtGui.QIcon.Off) group_widget.fold_button.setIcon(icon) #group_widget.fold_button.clicked.connect(SomaPartial( #self._toggle_group_visibility, group)) # FIXME: if we use this, self gets deleted somewhere. This is not # normal. group_widget.fold_button.clicked.connect( partial(self.__class__._toggle_group_visibility, weak_proxy(self), group)) return group_widget
def inlineGUI(self, values, pview, parent, externalRunButton=False): from soma.qt_gui.qt_backend import QtGui from brainvisa.processing.qtgui import neuroProcessesGUI vb = QtGui.QWidget() lay = QtGui.QVBoxLayout(vb) lay.addWidget( neuroProcessesGUI.ProcessView.defaultInlineGUI(pview, vb, externalRunButton, None)) lay.addWidget( QtGui.QLabel( _t_('The SPM paths have not been setup in the configuration.\nCurrently, processes using SPM might not work,\nand the SPM database (normalization templates...) cannot be used.\nThis process can try to detect it and set it in the configuration.\nYou should re-open any process depending on SPM afterwards.' ), vb)) return vb
def _completion_progress_changed(self, obj, name, old, new): completion_engine = getattr(self.attributed_process, 'completion_engine', None) if completion_engine is not None: if not hasattr(self, 'progressdialog'): self.progressdialog = QtGui.QWidget() self.layout().insertWidget(1, self.progressdialog) layout = QtGui.QHBoxLayout() self.progressdialog.setLayout(layout) layout.addWidget(QtGui.QLabel('Completion progress:')) self.progressbar = QtGui.QProgressBar() layout.addWidget(self.progressbar) self.progressbar.setRange(0, 100) value = int(round(100 * completion_engine.completion_progress / completion_engine.completion_progress_total)) self.progressbar.setValue(value) if value != 100: self.progressdialog.show() QtGui.qApp.processEvents() else: self.progressdialog.hide()
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 create_widget(parent, control_name, control_value, trait, label_class=None): """ Method to create the file widget. Parameters ---------- parent: QWidget (mandatory) the parent widget control_name: str (mandatory) the name of the control we want to create control_value: str (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: QWidget with two elements, a QLineEdit in the 'path' parameter and a browse button in the 'browse' parameter, associated label: QLabel) """ # Create the widget that will be used to select a file widget = QtGui.QWidget(parent) layout = QtGui.QHBoxLayout() layout.setSpacing(0) layout.setSizeConstraint(QtGui.QLayout.SetMinimumSize) layout.setContentsMargins(0, 0, 0, 0) widget.setLayout(layout) # Create a widget to print the file path path = TimeredQLineEdit(widget) layout.addWidget(path) widget.path = path # Create a browse button button = QtGui.QPushButton("...", widget) button.setObjectName('file_button') button.setStyleSheet('QPushButton#file_button ' '{padding: 2px 10px 2px 10px; margin: 0px;}') layout.addWidget(button) widget.browse = button # Add a widget parameter to tell us if the widget is already connected widget.connected = False # Add a parameter to tell us if the widget is optional widget.optional = trait.optional widget.output = trait.output # Set a callback on the browse button control_class = parent.get_control_class(trait) browse_hook = partial(control_class.onBrowseClicked, weak_proxy(widget)) widget.browse.clicked.connect(browse_hook) # Create the label associated with the string 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 (widget, label)
def create_widget(parent, control_name, control_value, trait, label_class=None, user_data=None): """ 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. 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: raise Exception( "Expect only one inner trait in List control. Trait '{0}' " "inner trait is '{1}'.".format(control_name, trait.handler.inner_traits())) inner_trait = trait.handler.inner_traits()[0] # Create the widget frame = QtGui.QFrame() frame.setFrameShape(QtGui.QFrame.StyledPanel) frame.user_data = user_data layout = QtGui.QHBoxLayout() layout.setContentsMargins(0, 0, 0, 0) frame.setLayout(layout) #item = QtGui.QLabel('<list of %s>' #% str(inner_trait.trait_type.__class__.__name__)) #item.setTextInteractionFlags(QtCore.Qt.TextSelectableByKeyboard | #QtCore.Qt.TextSelectableByMouse) #item.setFrameStyle(QtGui.QFrame.StyledPanel | QtGui.QFrame.Sunken) #layout.addWidget(item) # 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.addWidget(tool_widget) layout = QtGui.QHBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(2) tool_widget.setLayout(layout) # Store some parameters in the list widget frame.inner_trait = inner_trait frame.trait = trait frame.connected = False if control_value is traits.Undefined: control_value = [] elif not isinstance(control_value, (list, tuple)): # in nipype MultiPath, single values are not in a list control_value = [control_value] frame.trait_name = control_name # 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 frame.label_class = label_class # view the model items = OffscreenListControlWidget.partial_view_widget( weak_proxy(parent), weak_proxy(frame), control_value) layout.addWidget(items) #layout.addWidget(QtGui.QLabel('...')) frame.control_widget = items frame.controller = items.control_widget.controller frame.controller_widget = items.control_widget.controller_widget # Create the tool buttons edit_button = QtGui.QToolButton() layout.addWidget(edit_button) # Set the tool icons icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/soma_widgets_icons/add")), QtGui.QIcon.Normal, QtGui.QIcon.Off) edit_button.setIcon(icon) edit_button.setFixedSize(30, 22) #layout.addStretch(1) # Set some callback on the list control tools # Resize callback edit_hook = partial(OffscreenListControlWidget.edit_elements, weak_proxy(parent), weak_proxy(frame), weak_proxy(edit_button)) edit_button.clicked.connect(edit_hook) return (frame, label)
def __init__(self, missing_inputs, overwritten_outputs, parent=None): super(PipelineFileWarningWidget, self).__init__( QtCore.Qt.Vertical, parent) """ Builds the check widget. Parameters ---------- missing_inputs: mapping iterable (mandatory) a dict node: (list of pairs (param_name, file_name)) as output of :py:func:`capsul.pipeline_tools.nodes_with_missing_inputs` overwritten_outputs: mapping iterable (mandatory) a dict node: (list of pairs (param_name, file_name)) as output of :py:func:`capsul.pipeline_tools.nodes_with_existing_outputs` parent: QWidget (optional) parent widget """ splitter = self widget1 = QtGui.QWidget(splitter) layout1 = QtGui.QVBoxLayout(widget1) widget2 = QtGui.QWidget(splitter) layout2 = QtGui.QVBoxLayout(widget2) label = QtGui.QLabel() layout1.addWidget(label) text = '<h1>Pipeline file parameters problems</h1>\n' if len(missing_inputs) == 0: text += '<h2>Inputs: OK</h2>\n' \ '<p>All input file are present.</p>\n' label.setText(text) else: text += '<h2>Inputs: missing files</h2>\n' label.setText(text) table = QtGui.QTableWidget() layout1.addWidget(table) table.setColumnCount(3) sizes = [len(l) for node, l in six.iteritems(missing_inputs)] table.setRowCount(sum(sizes)) table.setHorizontalHeaderLabels( ['node', 'parameter', 'filename']) row = 0 for node_name, items in six.iteritems(missing_inputs): for param_name, file_name in items: if not file_name or file_name is traits.Undefined: file_name = '<temp. file>' table.setItem(row, 0, QtGui.QTableWidgetItem(node_name)) table.setItem(row, 1, QtGui.QTableWidgetItem(param_name)) table.setItem(row, 2, QtGui.QTableWidgetItem(file_name)) row += 1 table.setSortingEnabled(True) table.resizeColumnsToContents() label_out = QtGui.QLabel() layout2.addWidget(label_out) if len(overwritten_outputs) == 0: text = '<h2>Outputs: OK</h2>\n' \ '<p>No output file will be overwritten.</p>\n' label_out.setText(text) else: text = '<h2>Outputs: overwritten files</h2>\n' label_out.setText(text) table = QtGui.QTableWidget() layout2.addWidget(table) table.setColumnCount(3) sizes = [len(l) for node, l in six.iteritems(overwritten_outputs)] table.setRowCount(sum(sizes)) table.setHorizontalHeaderLabels( ['node', 'parameter', 'filename']) row = 0 for node_name, items in six.iteritems(overwritten_outputs): for param_name, file_name in items: if not file_name or file_name is traits.Undefined: file_name = '<temp. file>' table.setItem(row, 0, QtGui.QTableWidgetItem(node_name)) table.setItem(row, 1, QtGui.QTableWidgetItem(param_name)) table.setItem(row, 2, QtGui.QTableWidgetItem(file_name)) row += 1 table.setSortingEnabled(True) table.resizeColumnsToContents()
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 __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')