def assign_notification_root_state_after(self, model, prop_name, info): """ This method is called, when any state, transition, data flow, etc. within the state machine modifications. This then typically requires a redraw of the graphical editor, to display these modifications immediately. :param model: The state machine model :param prop_name: The property that was changed :param info: Information about the change """ # execution_status-changes are not observed if self.busy or info.method_name in BY_EXECUTION_TRIGGERED_OBSERVABLE_STATE_METHODS: return else: overview = NotificationOverview(info) # handle interrupts of action caused by exceptions if overview.get_result() == "CRASH in FUNCTION" or isinstance( overview.get_result(), Exception): if self.count_before == 1: return self._interrupt_active_action(info) pass # modifications of parent are not observed if overview.get_cause() == 'parent': return # decrease counter and finish action when reaching count=0 if self.locked: self.after_count() if self.count_before == 0: self.finish_new_action(overview) else: logger.error( "HISTORY after not count [root_state] -> For every before there should be a after." )
def action_signal_after_complex_action(self, model, prop_name, info): if self.busy: # if proceeding undo or redo return if isinstance(model, AbstractStateModel) and isinstance(info['arg'], ActionSignalMsg) and \ info['arg'].after and info['arg'].action in ['change_root_state_type', 'change_state_type', 'paste', 'cut', 'substitute_state', 'group_states', 'ungroup_state']: overview = NotificationOverview(info) if info['arg'].action in [ 'change_state_type', 'paste', 'cut', 'substitute_state', 'group_states', 'ungroup_state' ]: if self.__buffered_root_state_model is not model: self.relieve_model(model) if isinstance(info['arg'].result, Exception): if self.count_before == 1: return self._interrupt_active_action(info) else: logger.warning("Count is wrong 1 != {0}".format( self.count_before)) # decrease counter and finish action if count_before = 0 if self.locked: self.after_count() if self.count_before == 0: self.finish_new_action(overview) if info['arg'].action == 'change_root_state_type': self._re_initiate_observation() else: logger.error( "HISTORY after not count to 0 [action signal] -> For every before there should be a after." "{0}".format(NotificationOverview(info)))
def assign_notification_states_before(self, model, prop_name, info): if self.busy: # if proceeding undo or redo return else: # avoid to vast computation time if 'kwargs' in info and 'method_name' in info['kwargs'] and \ info['kwargs']['method_name'] in BY_EXECUTION_TRIGGERED_OBSERVABLE_STATE_METHODS: return overview = NotificationOverview(info) # skipped state modifications if not overview.get_change( ) == 'state_change' or overview.get_cause() == 'parent': return # increase counter and generate new action if not locked by action that is performed if self.locked: self.before_count() else: if self.start_new_action(overview): self.before_count() else: logger.error( "FAILED to start NEW HISTORY ELEMENT [states]")
def before_notification_state_machine_observation_control( self, model, prop_name, info): """Check for multi-actions and set respective no update flags. """ overview = NotificationOverview(info) if not overview.caused_modification(): return # do not update while multi-actions self.check_info_on_no_update_flags(info)
def check_no_update_flags_and_return_combined_flag(self, prop_name, info): # avoid updates because of execution status updates overview = NotificationOverview(info) if not overview.caused_modification(): return self.check_info_on_no_update_flags(info) # avoid updates while remove or multi-actions if self.no_update or self.no_update_state_destruction or self.no_update_self_or_parent_state_destruction: return True
def register_new_state_machines(self, model, prop_name, info): """ The method register self as observer newly added StateMachineModels after those were added to the list of state_machines hold by observed StateMachineMangerModel. The method register as observer of observable StateMachineMangerModel.state_machines.""" if info['method_name'] == '__setitem__': self.observe_model(info['args'][1]) self.logger.info(NotificationOverview(info)) elif info['method_name'] == '__delitem__': pass else: self.logger.warning(NotificationOverview(info))
def states_update_before(self, model, prop_name, info): if is_execution_status_update_notification_from_state_machine_model(prop_name, info): return overview = NotificationOverview(info, False, self.__class__.__name__) if overview['prop_name'][-1] == 'state' and \ overview.get_cause() in ["change_state_type"]: changed_model = self._selected_sm_model.get_state_model_by_path(overview['args'][-1][1].get_path()) self.observe_model(changed_model)
def relieve_state_machines(self, model, prop_name, info): """ The method relieves observed models before those get removed from the list of state_machines hold by observed StateMachineMangerModel. The method register as observer of observable StateMachineMangerModel.state_machines.""" if info['method_name'] == '__setitem__': pass elif info['method_name'] == '__delitem__': self.relieve_model(self.state_machine_manager_model.state_machines[info['args'][0]]) self.logger.info(NotificationOverview(info)) else: self.logger.warning(NotificationOverview(info))
def notify_state_name_change(self, model, prop_name, info): """Checks whether the name of a state was changed and change the tab label accordingly """ overview = NotificationOverview(info) # avoid updates or checks because of execution status updates if not overview.caused_modification(): return changed_model = overview.get_affected_model() method_name = overview.get_cause() if isinstance(changed_model, AbstractStateModel) and method_name in ['name', 'script_text']: self.update_tab_label(changed_model)
def notify_state_name_change(self, model, prop_name, info): """Checks whether the name of a state was changed and change the tab label accordingly """ # avoid updates or checks because of execution status updates if is_execution_status_update_notification_from_state_machine_model(prop_name, info): return overview = NotificationOverview(info, False, self.__class__.__name__) changed_model = overview['model'][-1] method_name = overview.get_cause() if isinstance(changed_model, AbstractStateModel) and method_name in ['name', 'script_text']: self.update_tab_label(changed_model)
def states_update(self, model, prop_name, info): overview = NotificationOverview(info) if not overview.caused_modification(): return if overview.get_affected_property() == 'state' and \ overview.get_cause() in ["name"]: # , "add_state", "remove_state"]: self.update_tree_store_row(overview.get_affected_model()) # TODO check the work around for get_library_root_state -> maybe the notifications can be avoided if upper lib elif overview.get_affected_property() == 'state' and not overview.get_affected_model().state.get_next_upper_library_root_state() and \ overview.get_cause() in ["add_state", "remove_state"]: self.update(overview.get_affected_model())
def states_update_before(self, model, prop_name, info): if is_execution_status_update_notification_from_state_machine_model( prop_name, info): return overview = NotificationOverview(info) if overview.get_affected_property() == 'state' and \ overview.get_cause() in ["change_state_type"]: changed_model = self._selected_sm_model.get_state_model_by_path( overview.get_method_args()[1].get_path()) self.observe_model(changed_model)
def after_notification_of_parent_or_state_from_lists(self, model, prop_name, info): # avoid updates because of execution status updates or while multi-actions if self.check_no_update_flags_and_return_combined_flag(prop_name, info): return overview = NotificationOverview(info) # avoid updates because of unimportant methods if overview.get_cause() not in ['name', 'append', '__setitem__', # '__delitem__', 'remove', 'group_states', 'ungroup_state', 'change_data_type', 'from_key', 'to_key', 'from_state', 'to_state', 'modify_origin', 'modify_target']: if self.model.parent: # check for a sibling port change if prop_name == 'states' and overview.get_affected_core_element() is self.model.parent.state and \ (overview.get_affected_core_element() in self.model.parent.state.states and overview.get_cause() in ['add_input_data_port', 'add_output_data_port'] or overview.get_affected_property() in ['data_port', 'scoped_variable'] and overview.get_cause() in ['name', 'change_data_type']): pass else: return else: return try: self.update(initiator=str(overview)) except Exception as e: if self.debug_log: import traceback self.store_debug_log_file(str(overview)) self.store_debug_log_file(str(traceback.format_exc())) logger.error("update of data_flow widget fails while detecting change in state %s %s" % (self.model.state.name, self.model.state.state_id))
def model_changed(self, model, prop_name, info): overview = NotificationOverview(info) if overview.operation_finished() and self.child_model_changed( overview): # The only operations allowed are setting the parent of the state_copy and # changing the state_execution_status if not (info["instance"] == self.state_copy.state and info["method_name"] == "parent" or info["method_name"] == "state_execution_status"): if not self.is_about_to_be_destroyed_recursively: logger.warning( "You have modified core property of an inner state of a library state." ) super(LibraryStateModel, self).model_changed(model, prop_name, info)
def check_info_on_no_update_flags(self, info): """Stop updates while multi-actions""" # TODO that could need a second clean up # avoid updates because of state destruction if 'before' in info and info['method_name'] == "remove_state": if info.instance is self.model.state: self.no_update_state_destruction = True else: # if the state it self is removed lock the widget to never run updates and relieve all models removed_state_id = info.args[1] if len( info.args) > 1 else info.kwargs['state_id'] if removed_state_id == self.model.state.state_id or \ not self.model.state.is_root_state and removed_state_id == self.model.parent.state.state_id: self.no_update_self_or_parent_state_destruction = True self.relieve_all_models() elif 'after' in info and info['method_name'] == "remove_state": if info.instance.state_id == self.model.state.state_id: self.no_update_state_destruction = False # reduce NotificationOverview generations by the fact that after could cause False and before could cause True if not self.no_update_state_destruction and not self.no_update_self_or_parent_state_destruction and \ (not self.no_update and 'before' in info or 'after' in info and self.no_update): return overview = NotificationOverview(info) # The method causing the change raised an exception, thus nothing was changed and updates are allowed if 'after' in info and isinstance(overview.get_result(), Exception): self.no_update = False self.no_update_state_destruction = False # self.no_update_self_or_parent_state_destruction = False return if overview.get_cause() in [ 'group_states', 'ungroup_state', "change_state_type", "change_root_state_type" ]: instance_is_self = self.model.state is overview.get_affected_core_element( ) instance_is_parent = self.model.parent and self.model.parent.state is overview.get_affected_core_element( ) instance_is_parent_parent = self.model.parent and self.model.parent.parent and self.model.parent.parent.state is overview.get_affected_core_element( ) # print("no update flag: ", True if 'before' in info and (instance_is_self or instance_is_parent or instance_is_parent_parent) else False) if instance_is_self or instance_is_parent or instance_is_parent_parent: self.no_update = True if 'before' in info else False if overview.get_affected_property() == 'state' and overview.get_cause() in ["change_state_type"] and \ self.model.get_state_machine_m() is not None: changed_model = self.model.get_state_machine_m( ).get_state_model_by_path( overview.get_method_args()[1].get_path()) if changed_model not in self._model_observed: self.observe_model(changed_model)
def states_update(self, model, prop_name, info): if is_execution_status_update_notification_from_state_machine_model(prop_name, info) or \ self._ongoing_complex_actions: return overview = NotificationOverview(info, False, self.__class__.__name__) if overview['prop_name'][-1] == 'state' and \ overview.get_cause() in ["name"]: # , "add_state", "remove_state"]: self.update_tree_store_row(overview['model'][-1]) # TODO check the work around for get_library_root_state -> maybe the notifications can be avoided if upper lib elif overview['prop_name'][-1] == 'state' and not overview['model'][-1].state.get_next_upper_library_root_state() and \ overview.get_cause() in ["add_state", "remove_state"]: self.update(overview['model'][-1])
def model_changed(self, model, prop_name, info): """This method notifies the model lists and the parent state about changes The method is called each time, the model is changed. This happens, when the state itself changes or one of its children (states, transitions, data flows) changes. Changes of the children cannot be observed directly, therefore children notify their parent about their changes by calling this method. This method then checks, what has been changed by looking at the model that is passed to it. In the following it notifies the list in which the change happened about the change. E.g. one child state changes its name. The model of that state observes itself and notifies the parent ( i.e. this state model) about the change by calling this method with the information about the change. This method recognizes that the model is of type StateModel and therefore triggers a notify on the list of state models. "_notify_method_before" is used as trigger method when the changing function is entered and "_notify_method_after" is used when the changing function returns. This changing function in the example would be the setter of the property name. :param model: The model that was changed :param prop_name: The property that was changed :param info: Information about the change (e.g. the name of the changing function) """ overview = NotificationOverview(info) # if info.method_name == 'change_state_type': # Handled in method 'change_state_type' # return # If this model has been changed (and not one of its child states), then we have to update all child models # This must be done before notifying anybody else, because other may relay on the updated models if not self.child_model_changed(overview): if overview.operation_finished(): self.update_child_models(model, prop_name, info) # if there is and exception set is_about_to_be_destroyed_recursively flag to False again if info.method_name in ["remove_state"] and isinstance( info.result, Exception): state_id = info.kwargs[ 'state_id'] if 'state_id' in info.kwargs else info.args[ 1] self.states[ state_id].is_about_to_be_destroyed_recursively = False elif overview.operation_started(): # while before notification mark all states which get destroyed recursively if info.method_name in ["remove_state"] and \ info.kwargs.get('destroy', True) and info.kwargs.get('recursive', True): state_id = info.kwargs[ 'state_id'] if 'state_id' in info.kwargs else info.args[ 1] self.states[ state_id].is_about_to_be_destroyed_recursively = True # Finally call the method of the base class, to forward changes in ports and outcomes super(ContainerStateModel, self).model_changed(model, prop_name, info)
def state_action_signal(self, model, prop_name, info): if self.busy: # if proceeding undo or redo return if isinstance(model, StateMachineModel) and isinstance(info['arg'], ActionSignalMsg) and \ not info['arg'].after and info['arg'].action in ['change_root_state_type', 'change_state_type', 'paste', 'cut', 'substitute_state', 'group_states', 'ungroup_state']: overview = NotificationOverview(info) if info['arg'].action == 'change_root_state_type': assert info['arg'].action_parent_m is self.state_machine_model self.active_action = StateMachineAction( parent_path=info['arg'].action_parent_m.root_state.state. get_path(), state_machine_model=info['arg'].action_parent_m, overview=overview) else: self.active_action = StateAction( parent_path=info['arg'].action_parent_m.state.get_path(), state_machine_model=self.state_machine_model, overview=overview) self.before_count() if info['arg'].action in ['group_states', 'paste', 'cut']: self.observe_model(info['arg'].action_parent_m) else: self.observe_model(info['arg'].affected_models[0])
def execution_change(self, model, prop_name, info): from rafcon.gui.utils.notification_overview import NotificationOverview overview = NotificationOverview(info) if overview['method_name'][-1] == 'state_execution_status': # print("CURRENT STATE: {0}".format(overview['model'][-1].state.get_path())) self.last_execution_change_at_state = overview['model'][ -1].state.get_path()
def on_state_execution_status_changed_after(self, model, prop_name, info): """ Show current execution status in the widget This function specifies what happens if the state machine execution status of a state changes :param model: the model of the state that has changed (most likely its execution status) :param prop_name: property name that has been changed :param info: notification info dictionary :return: """ from rafcon.gui.utils.notification_overview import NotificationOverview from rafcon.core.states.state import State def name_and_next_state(state): assert isinstance(state, State) if state.is_root_state_of_library: return state.parent.parent, state.parent.name else: return state.parent, state.name def create_path(state, n=3, separator='/'): next_parent, name = name_and_next_state(state) path = separator + name n -= 1 while n > 0 and isinstance(next_parent, State): next_parent, name = name_and_next_state(next_parent) path = separator + name + path n -= 1 if isinstance(next_parent, State): path = separator + '..' + path return path if 'kwargs' in info and 'method_name' in info['kwargs']: overview = NotificationOverview(info) if overview.get_cause() == 'state_execution_status': active_state = overview.get_affected_model().state assert isinstance(active_state, State) path_depth = rafcon.gui.singleton.global_gui_config.get_config_value( "EXECUTION_TICKER_PATH_DEPTH", 3) message = self._fix_text_of_label + create_path( active_state, path_depth) if rafcon.gui.singleton.main_window_controller.view is not None: self.ticker_text_label.set_text(message) else: logger.warning("Not initialized yet")
def all_after_notification(self, model, prop_name, info): """ The method logs all changes that notified recursively trough the hierarchies of the states after the change occurs in the rafcon.core object. The method register as observer of observable StateMachineModel.state_machine of any observed StateMachineModel. :param model: StateMachineModel that is represents the state_machine which has been changed :param prop_name: Name of property that notifies -> here always 'state_machine' :param info: Dictionary that hold recursive notification information like models, property and method names :return: """ self.logger.debug(NotificationOverview(info))
def model_changed(self, model, prop_name, info): """This method notifies the model lists and the parent state about changes The method is called each time, the model is changed. This happens, when the state itself changes or one of its children (outcomes, ports) changes. Changes of the children cannot be observed directly, therefore children notify their parent about their changes by calling this method. This method then checks, what has been changed by looking at the method that caused the change. In the following, it notifies the list in which the change happened about the change. E.g. one input data port changes its name. The model of the port observes itself and notifies the parent ( i.e. the state model) about the change by calling this method with the information about the change. This method recognizes that the method "modify_input_data_port" caused the change and therefore triggers a notify on the list if input data port models. "_notify_method_before" is used as trigger method when the changing function is entered and "_notify_method_after" is used when the changing function returns. This changing function in the example would be "modify_input_data_port". :param model: The model that was changed :param prop_name: The property that was changed :param info: Information about the change (e.g. the name of the changing function) """ overview = NotificationOverview(info) # If this model has been changed (and not one of its child states), then we have to update all child models # This must be done before notifying anybody else, because other may rely on the updated models if overview.operation_finished( ) and not self.child_model_changed(overview): self.update_models(model, prop_name, info) cause, changed_list = self.get_cause_and_affected_model_list(model) if not (cause is None or cause is "income_change" or changed_list is None): if overview.operation_started(): changed_list._notify_method_before(self.state, cause, (self.state, ), info) else: changed_list._notify_method_after(self.state, cause, None, (self.state, ), info) # Notifies parent state super(StateModel, self).model_changed(model, prop_name, info)
def meta_changed_notify_after(self, changed_model, prop_name, info): if not self.with_meta_data_actions: return overview = NotificationOverview(info) if self.busy: return if overview.get_signal_message().origin == 'load_meta_data': return if self.active_action is None or overview.get_signal_message( ).change in ['append_initial_change']: # update last actions after_state_image -> meta-data self.re_initiate_meta_data() elif self.active_action is None or \ overview.get_signal_message().change in ['append_to_last_change'] or \ overview.get_signal_message().origin in ['group_states', 'ungroup_state', 'substitute_state']: # update last actions after_state_image -> meta-data self.active_action.after_state_image = self.active_action.get_state_image( ) self.update_internal_tmp_storage() else: if isinstance(overview.get_affected_model(), AbstractStateModel): changed_parent_model = overview.get_affected_model() else: changed_parent_model = overview.get_affected_model().parent changed_parent_state_path = changed_parent_model.state.get_path() # TODO think about to remove this work around again # ignore meta data changes inside of library states changed_parent_state = self.state_machine_model.get_state_model_by_path( changed_parent_state_path).state if changed_parent_state.get_next_upper_library_root_state(): return if self.count_before == 0: self.active_action = MetaDataAction( changed_parent_model.state.get_path(), state_machine_model=self.state_machine_model, overview=overview) meta_data = self.get_state_element_meta_from_internal_tmp_storage( changed_parent_state_path) state_image = StateImage(meta_data=meta_data) self.active_action.before_state_image = state_image self.finish_new_action(overview) else: logger.info( 'Meta data change signal was emitted while other action was is performed. \n{0}' .format(overview))
def assign_notification_root_state_before(self, model, prop_name, info): # execution_status-changes are not observed if self.busy or info.method_name in BY_EXECUTION_TRIGGERED_OBSERVABLE_STATE_METHODS: return # first element should be prop_name="state_machine", instance=StateMachine and model=StateMachineModel # second element should be Prop_name="states" if root_state child elements are changed # --- for root_state elements it has to be prop_name in ["data_flows", "transitions", "input_data_ports", # "output_data_ports", "scoped_variables"] # third (and last element) should be prop_name in ["data_flow", "transition", ... else: overview = NotificationOverview(info) # modifications of parent are not observed if overview.get_cause() == 'parent': return # increase counter and generate new action if not locked by action that is performed if self.locked: self.before_count() else: if self.start_new_action(overview): self.before_count() else: logger.error( "FAILED to start NEW HISTORY ELEMENT [root_state]")
def after_notification_state(self, model, prop_name, info): # avoid updates because of execution status updates or while multi-actions # logger.info("after_notification_state: ".format(NotificationOverview(info))) if self.check_no_update_flags_and_return_combined_flag(prop_name, info): return overview = NotificationOverview(info, False, self.__class__.__name__) # logger.info("after_notification_state: OK") if overview['method_name'][-1] == 'parent' and overview['instance'][-1] is self.model.state or \ overview['instance'][-1] in [self.model.state, self.model.state.parent] and \ overview['method_name'][-1] in ['name', 'group_states', 'ungroup_state', 'change_data_type', "remove_outcome", "remove_transition"]: # logger.info("after_notification_state: UPDATE") self.update(initiator=str(overview))
def after_notification_of_parent_or_state_from_lists( self, model, prop_name, info): """ Activates the update after update if outcomes, transitions or states list has been changed. """ # avoid updates because of execution status updates or while multi-actions if self.check_no_update_flags_and_return_combined_flag( prop_name, info): return overview = NotificationOverview(info) if overview.get_cause() not in [ 'name', 'append', '__setitem__', # '__delitem__', 'remove' 'from_outcome', 'to_outcome', 'from_state', 'to_state', 'modify_origin', 'modify_target' ]: if self.model.parent: # check for sibling port change if prop_name == 'states' and overview.get_affected_core_element() is self.model.parent.state and \ (overview.get_affected_core_element() in self.model.parent.state.states and overview.get_cause() in ['add_outcome'] or overview.get_affected_property() in ['outcome'] and overview.get_cause() in ['name']): pass else: return else: return try: self.update(initiator=str(overview)) except KeyError as e: if self.debug_log: import traceback self.store_debug_log_file(str(overview)) self.store_debug_log_file(str(traceback.format_exc())) logger.error( "update of transition widget fails while detecting list change of state %s %s %s\n%s" % (self.model.state.name, self.model.state.state_id, e, self))
def after_notification_of_parent_or_state_from_lists( self, model, prop_name, info): """ Activates the update after update if outcomes, transitions or states list has been changed. """ # avoid updates because of execution status updates or while multi-actions # logger.info("after_notification_of_parent_or_state_from_lists: ".format(NotificationOverview(info))) if self.check_no_update_flags_and_return_combined_flag( prop_name, info): return overview = NotificationOverview(info, False, self.__class__.__name__) # print(self, self.model.state.get_path(), overview) # logger.info("after_notification_of_parent_or_state_from_lists: OK") if overview['prop_name'][0] in ['states', 'outcomes', 'transitions'] and \ overview['method_name'][-1] not in ['name', 'append', '__setitem__', # '__delitem__', 'remove' 'from_outcome', 'to_outcome', 'from_state', 'to_state', 'modify_origin', 'modify_target']: if self.model.parent: # check for sibling port change if overview['prop_name'][0] == 'states' and overview['instance'][0] is self.model.parent.state and \ (overview['instance'][-1] in self.model.parent.state.states and overview['method_name'][-1] in ['add_outcome'] or overview['prop_name'][-1] in ['outcome'] and overview['method_name'][-1] in ['name']): pass else: return else: return # print("TUPDATE ", self, overview) try: # logger.info("after_notification_of_parent_or_state_from_lists: UPDATE") self.update(initiator=str(overview)) except KeyError as e: if self.debug_log: import traceback self.store_debug_log_file(str(overview)) self.store_debug_log_file(str(traceback.format_exc())) logger.error( "update of transition widget fails while detecting list change of state %s %s %s\n%s" % (self.model.state.name, self.model.state.state_id, e, self))
def after_notification_of_parent_or_state(self, model, prop_name, info): # avoid updates because of execution status updates or while multi-actions if self.check_no_update_flags_and_return_combined_flag(prop_name, info): return overview = NotificationOverview(info) if overview.get_cause() == 'parent' and overview.get_affected_core_element() is self.model.state or \ overview.get_affected_core_element() in [self.model.state, self.model.state.parent] and \ overview.get_cause() in ['name', 'group_states', 'ungroup_state', 'change_data_type', "remove_input_data_port", "remove_output_data_port", "remove_scoped_variable", "remove_data_flow"]: self.update(initiator=str(overview))
def after_notification_of_parent_or_state_from_lists(self, model, prop_name, info): # avoid updates because of execution status updates or while multi-actions # logger.info("after_notification_of_parent_or_state_from_lists: {1}\n{0}".format(NotificationOverview(info), # self.model.state.get_path())) if self.check_no_update_flags_and_return_combined_flag(prop_name, info): return overview = NotificationOverview(info, False, self.__class__.__name__) # print self, self.model.state.get_path(), overview # logger.info("after_notification_of_parent_or_state_from_lists: OK") # avoid updates because of unimportant methods if overview['prop_name'][0] in ['states', 'input_data_ports', 'output_data_ports', 'scoped_variables', 'data_flows'] and \ overview['method_name'][-1] not in ['name', 'append', '__setitem__', # '__delitem__', 'remove', 'group_states', 'ungroup_state', 'change_data_type', 'from_key', 'to_key', 'from_state', 'to_state', 'modify_origin', 'modify_target']: if self.model.parent: # check for a sibling port change if overview['prop_name'][0] == 'states' and overview['instance'][0] is self.model.parent.state and \ (overview['instance'][-1] in self.model.parent.state.states and overview['method_name'][-1] in ['add_input_data_port', 'add_output_data_port'] or overview['prop_name'][-1] in ['data_port', 'scoped_variable'] and overview['method_name'][-1] in ['name', 'change_data_type']): pass else: return else: return # print "DUPDATE ", self, overview try: # logger.info("after_notification_of_parent_or_state_from_lists: UPDATE") self.update(initiator=str(overview)) except Exception as e: if self.debug_log: import traceback self.store_debug_log_file(str(overview)) self.store_debug_log_file(str(traceback.format_exc())) logger.error("update of data_flow widget fails while detecting change in state %s %s" % (self.model.state.name, self.model.state.state_id))
def model_changed(self, model, prop_name, info): if isinstance(info['result'], Exception): from rafcon.gui.utils.notification_overview import NotificationOverview logger.exception("An '{0}' exception was raised in the core. " "Details about the origin:\n{1}" "".format( type(info['result']).__name__, NotificationOverview(info))) return if info["method_name"] == "add_state_machine": logger.debug("Add new state machine model ... ") sm_id = info['result'] if sm_id in self.state_machine_manager.state_machines and sm_id not in self.state_machines: logger.debug( "Create new state machine model for state machine with id %s", sm_id) sm = self.state_machine_manager.state_machines[sm_id] with sm.modification_lock(): self.state_machines[sm_id] = StateMachineModel(sm) from rafcon.gui.models.abstract_state import AbstractStateModel logger.verbose("Number of created state models {}".format( AbstractStateModel.state_counter)) self.selected_state_machine_id = sm_id else: logger.error( "Model of state machine {0} is supposed to not exist but the state machine object should." "".format(sm_id)) elif info["method_name"] == "remove_state_machine": sm_id_to_delete = info['result'].state_machine_id if sm_id_to_delete is not None: logger.debug( "Delete state machine model for state machine with id %s", sm_id_to_delete) if self.selected_state_machine_id == sm_id_to_delete: self.selected_state_machine_id = None sm_m = self.state_machines[sm_id_to_delete] sm_m.prepare_destruction() del self.state_machines[sm_id_to_delete] sm_m.destroy()