def traits_view(self): if self.can_cancel: buttons = ['OK', 'Cancel'] else: buttons = ['OK'] v = View(VGroup( UItem('results', editor=TabularEditor(adapter=ResultsAdapter(), editable=False, selected='controller.selected')), VGroup(UReadonly('controller.selected.description'), show_border=True, label='Description'), VGroup(UReadonly('controller.selected.error'), show_border=True, visible_when='controller.selected.error', label='Error'), VGroup(UReadonly('controller.help_str'), show_border=True, visible_when='controller.help_str')), title='Test Results', buttons=buttons, width=650, kind='livemodal', resizable=True) return v
def traits_view(self): comms_grp = VGroup(UItem('communication_grp', style='custom'), visible_when='comms_visible', show_border=True, label='Communications') scan_grp = VGroup(Item('scan.enabled'), VGroup(Item('scan.graph'), Item('scan.record'), Item('scan.auto_start'), Item('scan.period'), enabled_when='scan.enabled'), UItem('save_button'), show_border=True, label='Scan') v = View(VGroup( HGroup( UReadonly('config_name'), icon_button_editor('save_button', 'document-save', enabled_when='config_path')), comms_grp, scan_grp), height=500, resizable=True) return v
def traits_view(self): auth_grp = VGroup(Item('host'), Item('user'), Item('password'), show_border=True, label='Authentication') v = View(VGroup(auth_grp, HGroup(icon_button_editor('check_status_button', 'database_go_fatcow', tooltip='Check slave status. Equivalent to "Show Slave Status"'), icon_button_editor('start_button', 'start', tooltip='Start replication. Equivalent to "Start Slave"', enabled_when='not running'), icon_button_editor('stop_button', 'stop', tooltip='Stop replication. Equivalent to "Stop Slave"', enabled_when='running'), icon_button_editor('skip_button', 'skip_occurrence', tooltip='Set global skip counter.\n' 'Equivalent to "Stop Slave;' 'Set GLOBAL SQL_SKIP_COUNTER=N;Start Slave;"\n' 'where N is the number of SQL statements to skip'), UItem('skip_count', tooltip='Number of SQL statements to skip')), UItem('status_items', editor=TabularEditor(adapter=StatusItemsAdapter(), editable=False)), VGroup(UReadonly('last_error', height=200, style_sheet='color: red; font-weight: bold'), label='Error', show_border=True), label='Slave', show_border=True)) v.width = 500 return v
def traits_view(self): v = View( VGroup( HGroup(Label('Extraction'), spring, UReadonly('extraction', )), HGroup(Label('Measurement'), spring, UReadonly('measurement', )), HGroup(Label('Skip'), spring, UReadonly('skip', )), HGroup(Label('Success'), spring, UReadonly('success', )), HGroup(Label('Truncated'), spring, UReadonly('truncated', )), HGroup(Label('Canceled'), spring, UReadonly('canceled', )), HGroup(Label('Failed'), spring, UReadonly('failed', )), HGroup(Label('Not Executable'), spring, UReadonly('not_executable', )), HGroup(Label('End After'), spring, UReadonly('end_after', )))) return v
def traits_view(self): gen_grp = VGroup(HGroup(Readonly('nruns', width=150, label='Total Runs'), UReadonly('total_time')), HGroup(Readonly('nruns_finished', width=150, label='Completed'), UReadonly('elapsed')), Readonly('remaining', label='Remaining'), Readonly('etf', label='Est. finish'), show_border=True, label='General') cur_grp = VGroup(Readonly('current_run_duration', ), Readonly('run_elapsed'), show_border=True, label='Current') sel_grp = VGroup(Readonly('start_at'), Readonly('end_at'), Readonly('run_duration'), label='Selection', show_border=True) v = View(VGroup(gen_grp, cur_grp, sel_grp)) return v
def _axis_hgroup_default(self): return HGroup( Item("x", editor=EnumEditor(name="displayable_value_names")), Item("y", editor=EnumEditor(name="displayable_value_names")), UItem("color_options"), VGroup( Item("toggle_automatic_update", label="Axis auto update"), Item("toggle_display_curve", label="Display curve"), UReadonly("_curve_error", visible_when="not _curve_status") ) )
class WorkflowInfo(HasTraits): # ------------------- # Required Attributes # ------------------- #: Filename for the current workflow (if any) workflow_filename = Str() #: A list of the loaded plugins plugins = List(Plugin) #: The factory currently selected in the SetupPane selected_factory_name = Str() #: An error message for the entire workflow error_message = Str() # --------------------- # Dependent Attributes # --------------------- #: The force project logo! Stored at images/Force_Logo.png image = ImageResource('Force_Logo.png') #: Message indicating currently loaded file workflow_filename_message = Str() #: A list of plugin names plugin_names = List(Str) # ----------- # View # ----------- traits_view = View( VGroup( horizontal_centre( Group(UItem('image', editor=ImageEditor(scale=True, allow_upscaling=False, preserve_aspect_ratio=True)), visible_when="selected_factory_name == 'Workflow'")), Group(UReadonly('plugin_names', editor=ListStrEditor(editable=False)), show_border=True, label='Available Plugins', visible_when="selected_factory_name not in ['KPI']"), Group( UReadonly('workflow_filename_message', editor=TextEditor()), show_border=True, label='Workflow Filename', ), Group(UReadonly('error_message', editor=TextEditor()), show_border=True, label='Workflow Errors', visible_when="selected_factory_name == 'Workflow'"), )) # ------------------- # Defaults # ------------------- def _plugin_names_default(self): return [plugin.name for plugin in self.plugins] def _workflow_filename_message_default(self): if self.workflow_filename == '': return 'No File Loaded' return 'Current File: ' + self.workflow_filename
class DataSourceView(HasTraits): """A view for a single data source in a execution layer. Displays traits of BaseDataSourceModel and a tabular representation of the input / output variable slots""" # ------------------- # Required Attributes # ------------------- #: Model of the evaluator (More restrictive than the ModelView model #: attribute) model = Instance(BaseDataSourceModel) #: The index of the layer this data source belongs to. layer_index = Int() #: Registry of the available variables variable_names_registry = Instance(VariableNamesRegistry) # ------------------ # Regular Attributes # ------------------ #: The human readable name of the data source label = Str() #: evaluator object, shouldn't be touched _data_source = Instance(BaseDataSource) #: Input slots representation for the table editor input_slots_representation = List(InputSlotRow) #: Output slots representation for the table editor output_slots_representation = List(OutputSlotRow) # -------------------- # Dependent Attributes # -------------------- #: Currently selected slot in the table #: Listens to: :attr:`input_slots_editor`, :attr:`output_slots_editor` selected_slot_row = Instance(TableRow) #: Event to request a verification check on the workflow #: Listens to: :attr:`input_slots_representation.name #: <input_slots_representation>`, :attr:`output_slots_representation.name #: <output_slots_representation>` verify_workflow_event = Event() #: Defines if the evaluator is valid or not. Updated by #: :func:`verify_tree #: <force_wfmanager.ui.setup.workflow_tree.WorkflowTree.verify_tree>` valid = Bool(True) #: An error message for issues in this modelview. Updated by #: :func:`verify_tree #: <force_wfmanager.ui.setup.workflow_tree.WorkflowTree.verify_tree>` error_message = Str() # ---------------- # Properties # ---------------- #: HTML for the selected slot description selected_slot_description = Property(HTML, depends_on="selected_slot_row") # ------------- # View # ------------- #: Base view for the evaluator traits_view = View( VGroup( VGroup( Item( "input_slots_representation", label="Input variables", editor=input_slots_editor, ), Item( "output_slots_representation", label="Output variables", editor=output_slots_editor, )), VGroup(UReadonly( "selected_slot_description", editor=TextEditor(), ), label="Selected parameter description", show_border=True), ), ) def __init__(self, *args, **kwargs): super(DataSourceView, self).__init__(*args, **kwargs) # Performs private method to set up slots tables on instantiation self._create_slots_tables() # ------------------- # Defaults # ------------------- def _label_default(self): return get_factory_name(self.model.factory) def __data_source_default(self): return self.model.factory.create_data_source() # ------------------- # Listeners # ------------------- # Description update on UI selection change @cached_property def _get_selected_slot_description(self): if self.selected_slot_row is None: return DEFAULT_MESSAGE idx = self.selected_slot_row.index row_type = self.selected_slot_row.type description = self.selected_slot_row.description type_text = ("Input" if isinstance(self.selected_slot_row, InputSlotRow) else "Output") return SLOT_DESCRIPTION.format(row_type, type_text, idx, description) @on_trait_change('model.+verify', 'input_slots_representation.[name,type],' 'output_slots_representation.[name,type]') def data_source_change(self): """Fires :func:`verify_workflow_event` when an input slot or output slot is changed""" self.verify_workflow_event = True # Changed Slots Functions @on_trait_change('model:changes_slots') def _update_slots_tables(self): """ Update the tables of slots when a change on the model triggers a change on the shape of the input/output slots""" #: This synchronization maybe is something that should be moved to the #: model. self.input_slots_representation[:] = [] self.output_slots_representation[:] = [] input_slots, output_slots = self._data_source.slots(self.model) #: Initialize the input slots self.model.input_slot_info = [ InputSlotInfo(name='') for _ in input_slots ] #: Initialize the output slots self.model.output_slot_info = [ OutputSlotInfo(name='') for _ in output_slots ] self._fill_slot_rows(input_slots, output_slots) # Available Variables Functions # Model change functions @on_trait_change('model.input_slot_info.name,model.output_slot_info.name') def update_slot_info_names(self): """Updates the name displayed in a Input/OutputSlotRow if the name changes in the model. """ for info, row in zip(self.model.input_slot_info, self.input_slots_representation): row.name = info.name for info, row in zip(self.model.output_slot_info, self.output_slots_representation): row.name = info.name # ------------------- # Private Methods # ------------------- # Initialization def _create_slots_tables(self): """ Initialize the tables for editing the input and output slots Raises ------ RuntimeError: If the input slots or output slots in the model are not of the right length. This can come from a corrupted file. """ input_slots, output_slots = self._data_source.slots(self.model) # Initialize model.input_slot_info if not initialized yet if len(self.model.input_slot_info) == 0: self.model.input_slot_info = [ InputSlotInfo(name='') for _ in input_slots ] if len(self.model.input_slot_info) != len(input_slots): raise RuntimeError( "The number of input slots ({}) of the {} model doesn't match " "the expected number of slots ({}). This is likely due to a " "corrupted file.".format(len(self.model.input_slot_info), type(self.model).__name__, len(input_slots))) # Initialize model.output_slot_info if not initialized yet if len(self.model.output_slot_info) == 0: self.model.output_slot_info = [ OutputSlotInfo(name="") for _ in output_slots ] if len(self.model.output_slot_info) != len(output_slots): raise RuntimeError( "The number of output slots ({}) of the {} model doesn't " "match the expected number of slots ({}). This is likely due " "to a corrupted file.".format(len(self.model.output_slot_info), type(self.model).__name__, len(output_slots))) self._fill_slot_rows(input_slots, output_slots) def _fill_slot_rows(self, input_slots, output_slots): """ Fill the tables rows according to input_slots and output_slots needed by the evaluator and the model slot values """ input_representations = [] for index, input_slot in enumerate(input_slots): slot_representation = InputSlotRow(model=self.model, index=index) slot_representation.name = self.model.input_slot_info[index].name slot_representation.type = input_slot.type slot_representation.description = input_slot.description input_representations.append(slot_representation) self.input_slots_representation[:] = input_representations output_representation = [] for index, output_slot in enumerate(output_slots): slot_representation = OutputSlotRow(model=self.model, index=index) slot_representation.name = self.model.output_slot_info[index].name slot_representation.type = output_slot.type slot_representation.description = output_slot.description output_representation.append(slot_representation) self.output_slots_representation[:] = output_representation def _available_variables(self): """Returns the available variables for the containing execution layer of this data source """ registry = self.variable_names_registry idx = self.layer_index return registry.available_variables[idx] def _available_variables_by_type(self, variable_type): """Returns the available variables of variable_type for the containing execution layer of this data source Parameters ---------- variable_type: CUBAType Searches for available variables of this type """ registry = self.variable_names_registry idx = self.layer_index if variable_type in registry.available_variables_by_type[idx]: return registry.available_variables_by_type[idx][variable_type] return []
def default_traits_view(self): """The layout of the View for the WorkflowTree""" tree_editor = TreeEditor( nodes=[ # Root node "Workflow" TreeNodeWithStatus(node_for=[WorkflowView], auto_open=True, children='', name='Workflow', label='=Workflow', view=no_view, menu=no_menu, on_select=self.workflow_selected), # Node representing the Process" TreeNode(node_for=[WorkflowView], auto_open=True, children='process_view', name='Process', label='=Process', view=no_view, menu=no_menu, on_select=self.workflow_selected), #: Node representing the Execution layers TreeNode(node_for=[ProcessView], auto_open=True, children='execution_layer_views', label='=Execution Layers', name='Execution Layers', view=no_view, menu=Menu(new_layer_action), on_select=self.process_selected), TreeNodeWithStatus(node_for=[ExecutionLayerView], auto_open=True, children='data_source_views', label='label', name='DataSources', view=no_view, menu=Menu(delete_layer_action), on_select=self.execution_layer_selected), TreeNodeWithStatus(node_for=[DataSourceView], auto_open=True, children='', label='label', name='DataSources', menu=Menu(delete_data_source_action), on_select=self.data_source_selected), # Folder node "MCO" containing the MCO TreeNode( node_for=[WorkflowView], auto_open=True, children='mco_view', label='=MCO', name='MCO', view=no_view, menu=no_menu, on_select=self.mco_selected, ), # Node representing the MCO TreeNodeWithStatus(node_for=[MCOView], auto_open=True, children='mco_options', label='label', name='MCO', view=no_view, menu=Menu(delete_mco_action), on_select=self.mco_optimizer_selected), # Node representing the MCO Parameters TreeNodeWithStatus(node_for=[MCOParameterView], auto_open=True, children='', label='=Parameters', name='Parameters', view=no_view, menu=no_menu, on_select=self.mco_parameters_selected), # Node representing the MCO KPIs TreeNodeWithStatus(node_for=[KPISpecificationView], auto_open=True, children='', label='=KPIs', name='KPIs', view=no_view, menu=no_menu, on_select=self.mco_kpis_selected), TreeNode(node_for=[WorkflowView], auto_open=True, children='communicator_view', name='Communicator', label='=Communicator', view=no_view, menu=no_menu, on_select=self.workflow_selected), TreeNode(node_for=[CommunicatorView], auto_open=True, children='notification_listener_views', label='=Notification Listeners', name='Notification Listeners', view=no_view, menu=no_menu, on_select=self.communicator_selected), # Node representing the Notification Listener TreeNodeWithStatus( node_for=[NotificationListenerView], auto_open=True, children='', label='label', name='Notification Listeners', view=no_view, menu=Menu(delete_notification_listener_action), on_select=self.notification_listener_selected) ], orientation="horizontal", editable=False, selected="object.system_state.selected_view", ) view = View( Group( VGroup( UItem(name='workflow_view', editor=tree_editor, show_label=False), ), VGroup(UReadonly( name='selected_error', editor=TextEditor(), ), label='Workflow Errors', show_border=True), ), width=500, resizable=True, scrollable=True, ) return view
class UISelectModal(HasRequiredTraits): #: A list of contributed UIs received from plugins contributed_uis = List(ContributedUI, required=True) #: A list of available plugins available_plugins = List(Instance(BaseExtensionPlugin), required=True) #: A dictionary of plugin names and versions, generated from #: available_plugins avail_plugin_info = Dict() #: Mapping allowing selection of a UI by its name ui_name_map = Dict(Str, Instance(ContributedUI)) #: The name of the currently selected UI selected_ui_name = Enum(Str, values='_contributed_ui_names') #: List of discovered ContributedUI names _contributed_ui_names = List(Str) #: The currently selected UI selected_ui = Instance(ContributedUI) #: The description for the currently selected UI selected_ui_desc = Str() traits_view = View(VGroup( HGroup( Spring(), Item("selected_ui_name", label="Selected UI "), Spring() ), HGroup( UReadonly( "selected_ui_desc", editor=TextEditor(), visible_when="selected_ui is not None" ) ), ), buttons=OKCancelButtons, handler=UISelectHandler(), kind="livemodal", resizable=True, title="Select Custom UI", width=600, ) def __contributed_ui_names_default(self): return [''] + [ui_name for ui_name in self.ui_name_map] @on_trait_change("selected_ui_name") def select_ui(self): """Set :attr:`selected_ui` and update :attr:`selected_ui_desc` when the user selects a UI from the available UIs combobox.""" if not self.selected_ui_name: self.selected_ui = None else: self.selected_ui = self.ui_name_map[self.selected_ui_name] self.selected_ui_desc = DESCRIPTION_TEMPLATE.format( self.selected_ui.name, self.selected_ui.desc ) def _ui_name_map_default(self): """Convenience mapping from user friendly UI names to the ContributedUI object itself """ duplicate_ui_name_count = defaultdict(lambda: 1) ui_name_map = {} for ui in self.contributed_uis: if self._check_ui_plugins_available(ui): if ui.name not in ui_name_map: ui_name_map[ui.name] = ui else: duplicate_ui_name_count[ui.name] += 1 ui_name_and_index = ( ui.name + f' ({duplicate_ui_name_count[ui.name]})' ) ui_name_map[ui_name_and_index] = ui return ui_name_map def _avail_plugin_info_default(self): return { plugin.id: plugin.version for plugin in self.available_plugins } def _check_ui_plugins_available(self, ui): """Check that all plugins required by a ContributedUI are present. Parameters ---------- ui: ContributedUI The ContributedUI to be checked. """ for plugin_name, plugin_ver in ui.required_plugins.items(): # Check if the plugin has been loaded and that the version number # is greater or equal to the minimum version required. if self.avail_plugin_info.get(plugin_name, -1) < plugin_ver: return False return True