def register(self):
        """
        Change the state machine that is observed for new selected states to the selected state machine.
        :return:
        """
        # logger.debug("StateMachineEditionChangeHistory register state_machine old/new sm_id %s/%s" %
        #              (self.__my_selected_sm_id, self.model.selected_state_machine_id))

        # relieve old models
        if self.__my_selected_sm_id is not None:  # no old models available
            self.relieve_model(self._selected_sm_model.history)

        if self.model.selected_state_machine_id is not None and global_gui_config.get_config_value('HISTORY_ENABLED'):

            # set own selected state machine id
            self.__my_selected_sm_id = self.model.selected_state_machine_id

            # observe new models
            self._selected_sm_model = self.model.state_machines[self.__my_selected_sm_id]
            if self._selected_sm_model.history:
                self.observe_model(self._selected_sm_model.history)
                self.update(None, None, None)
            else:
                logger.warning("The history is enabled but not generated {0}. {1}"
                               "".format(self._selected_sm_model.state_machine.state_machine_id,
                                         self._selected_sm_model.state_machine.file_system_path))
        else:
            if self.__my_selected_sm_id is not None:
                self.doing_update = True
                self.history_tree_store.clear()
                self.doing_update = False
            self.__my_selected_sm_id = None
            self._selected_sm_model = None
Example #2
0
 def prepare_recently_opened_state_machines_list_for_storage(self):
     """ Reduce number of paths in the recent opened state machines to limit from gui config """
     from rafcon.gui.singleton import global_gui_config
     num = global_gui_config.get_config_value(
         'NUMBER_OF_RECENT_OPENED_STATE_MACHINES_STORED')
     state_machine_paths = self.get_config_value(
         'recently_opened_state_machines', [])
     self.set_config_value('recently_opened_state_machines',
                           state_machine_paths[:num])
Example #3
0
    def open_externally_clicked(self, button):
        prefer_external_editor = global_gui_config.get_config_value(
            "PREFER_EXTERNAL_EDITOR")
        file_system_path = self.model.state.file_system_path
        if file_system_path is None:
            file_system_path = self.model.state.get_temp_file_system_path()
            logger.info(
                "External source editor uses temporary storage path {0}.".
                format(file_system_path))

        def set_editor_lock_inline(lock):
            if lock:
                button.set_label(
                    'Reload' if prefer_external_editor else 'Unlock')
            else:
                button.set_label('Open externally')
            button.set_active(lock)
            self.set_editor_lock(lock)

        if button.get_active():
            # Get the specified "Editor" as in shell command from the gui config yaml
            external_editor = global_gui_config.get_config_value(
                'DEFAULT_EXTERNAL_EDITOR', None)

            def open_file_in_editor(cmd_to_open_editor, test_command=False):
                self.save_file_data(file_system_path)
                script_file_path = os.path.join(file_system_path,
                                                self.get_file_name())
                if not self.execute_shell_command_with_path(
                        cmd_to_open_editor, script_file_path) and test_command:
                    # If a text field exists destroy it. Errors can occur with a specified editor as well
                    # e.g Permission changes or sth.
                    global_gui_config.set_config_value(
                        'DEFAULT_EXTERNAL_EDITOR', None)
                    global_gui_config.save_configuration()
                    set_editor_lock_inline(False)
                    return
                # Set the text on the button to 'Unlock' instead of 'Open externally'
                set_editor_lock_inline(True)

            def open_text_window():
                markup_text = "No external editor specified. Please specify a shell command to open scripts externally"
                # create a new RAFCONButtonInputDialog, add a checkbox and add the text 'remember' to it
                text_input = RAFCONInputDialog(markup_text,
                                               ["Apply", "Cancel"],
                                               checkbox_text='remember')
                # Run the text_input Dialog until a response is emitted. The apply button and the 'activate' signal of
                # the text input send response 1
                if text_input.run() == 1:
                    # If the response emitted from the Dialog is 1 than handle the 'OK'
                    # If the checkbox is activated, also save the text input into the config
                    if text_input.get_checkbox_state():
                        global_gui_config.set_config_value(
                            'DEFAULT_EXTERNAL_EDITOR',
                            text_input.get_entry_text())
                        global_gui_config.save_configuration()
                    open_file_in_editor(text_input.get_entry_text(),
                                        test_command=True)
                else:
                    # If Dialog is canceled either by the button or the cross, toggle back the button again
                    # and revert the lock, which is not implemented yet
                    set_editor_lock_inline(False)
                text_input.destroy()

            if not external_editor:
                # If no external editor is specified in the gui_config.yaml, open the Dialog and let the user choose
                # a shell command to apply to the file path
                open_text_window()
            else:
                # If an editor is specified, open the path with the specified command. Also text_field is None, there is
                # no active text field in the case of an already specified editor. Its needed for the SyntaxError catch
                open_file_in_editor(external_editor, test_command=True)
        else:
            # If button is clicked after one open a file in the external editor, unlock the internal editor to reload
            set_editor_lock_inline(False)
            # Load file contents after unlocking
            self.load_and_set_file_content(file_system_path)
            # After reload internal editor and external editor is preferred lock internal editor again
            set_editor_lock_inline(prefer_external_editor)
Example #4
0
 def __init__(self, model, view, dialog_widget=None):
     super(StateSubstituteChooseLibraryDialogTreeController,
           self).__init__(model, view)
     self.dialog_widget = dialog_widget
     self.keep_name = global_gui_config.get_config_value(
         'SUBSTITUTE_STATE_KEEPS_STATE_NAME')
Example #5
0
def restore_session_from_runtime_config():
    """ Restore stored tabs from runtime config

    The method checks if the last status of a state machine is in the backup or in tis original path and loads it
    from there. The original path of these state machines are also insert into the recently opened state machines
    list.
    """
    # TODO add a dirty lock for a crashed rafcon instance also into backup session feature
    # TODO in case a dialog is needed to give the user control
    # TODO combine this and auto-backup in one structure/controller/observer
    from rafcon.gui.singleton import state_machine_manager_model, global_runtime_config, global_gui_config
    from rafcon.gui.models.auto_backup import recover_state_machine_from_backup
    from rafcon.gui.singleton import main_window_controller
    # check if session storage exists
    open_tabs = global_runtime_config.get_config_value('open_tabs', None)
    if open_tabs is None:
        logger.info("No session found for recovery")
        return

    # load and restore state machines like they were opened before
    open_sm = []
    for idx, tab_meta_dict in enumerate(open_tabs):
        start_time = time.time()
        backup_meta_dict = tab_meta_dict['backup_meta']
        from_backup_path = None
        open_sm.append(None)
        # TODO do this decision before storing or maybe store the last stored time in the auto backup?!
        # pick folder name dependent on time, and backup meta data existence
        # problem is that the backup time is maybe not the best choice
        if 'last_backup' in backup_meta_dict:
            last_backup_time = storage_utils.get_float_time_for_string(backup_meta_dict['last_backup']['time'])
            if 'last_saved' in backup_meta_dict:
                last_save_time = storage_utils.get_float_time_for_string(backup_meta_dict['last_saved']['time'])
                backup_marked_dirty = backup_meta_dict['last_backup']['marked_dirty']
                if last_backup_time > last_save_time and backup_marked_dirty:
                    from_backup_path = backup_meta_dict['last_backup']['file_system_path']
            else:
                from_backup_path = backup_meta_dict['last_backup']['file_system_path']
        elif 'last_saved' in backup_meta_dict:
            # print "### open last saved", sm_meta_dict['last_saved']['file_system_path']
            pass
        else:
            logger.error("A tab was stored into session storage dictionary {0} without any recovery path"
                         "".format(backup_meta_dict))
            continue

        # check in case that the backup folder is valid or use last saved path
        if from_backup_path is not None and not os.path.isdir(from_backup_path):
            logger.warning("The backup of tab {0} from backup path {1} was not possible. "
                           "The last saved path will be used for recovery, which could result is loss of changes."
                           "".format(idx, from_backup_path))
            from_backup_path = None

        # open state machine
        if from_backup_path is not None:
            # open state machine, recover mark dirty flags, cleans dirty lock files
            logger.info("Restoring from backup {0}".format(from_backup_path))
            state_machine_m = recover_state_machine_from_backup(from_backup_path)
        else:
            if 'last_saved' not in backup_meta_dict or backup_meta_dict['last_saved']['file_system_path'] is None:
                continue
            path = backup_meta_dict['last_saved']['file_system_path']
            if not os.path.isdir(path):
                logger.warning("The tab can not be open. The backup of tab {0} from common path {1} was not "
                               "possible.".format(idx, path))
                continue
            # logger.info("backup from last saved", path, sm_meta_dict)
            state_machine = storage.load_state_machine_from_path(path)
            state_machine_manager_model.state_machine_manager.add_state_machine(state_machine)
            wait_for_gui()
            state_machine_m = state_machine_manager_model.state_machines[state_machine.state_machine_id]

        duration = time.time() - start_time
        stat = state_machine_m.state_machine.root_state.get_states_statistics(0)
        logger.info("It took {0:.3}s to restore {1} states with {2} hierarchy levels.".format(duration, stat[0], stat[1]))

        open_sm[idx] = state_machine_m

    global_runtime_config.extend_recently_opened_by_current_open_state_machines()

    if global_gui_config.get_config_value('GAPHAS_EDITOR'):
        wait_for_gui()

    # restore all state machine selections separate to avoid states-editor and state editor creation problems
    for idx, tab_meta_dict in enumerate(open_tabs):
        state_machine_m = open_sm[idx]
        if state_machine_m is None:  # state machine could not be open
            return

        # restore state machine selection
        selected_model_set = []
        for core_element_identifier in tab_meta_dict['selection']:
            selected_model_set.append(state_machine_m.get_state_model_by_path(core_element_identifier))
        state_machine_m.selection.set(selected_model_set)

    # restore backup-ed tab selection
    selected_page_number = global_runtime_config.get_config_value('selected_state_machine_page_number', None)
    if selected_page_number is not None:
        selected_state_machine_page_number = selected_page_number
        if selected_state_machine_page_number is None:
            return
        state_machines_editor_ctrl = main_window_controller.get_controller('state_machines_editor_ctrl')
        if not state_machines_editor_ctrl.view['notebook'].get_n_pages() >= selected_page_number:
            logger.warning("Page id {0} does not exist so session restore can not re-create selection."
                           "".format(selected_page_number))
            return
        notebook = state_machines_editor_ctrl.view['notebook']
        page = state_machines_editor_ctrl.on_switch_page(notebook, None, selected_page_number)
        selected_sm_id = state_machine_manager_model.selected_state_machine_id
        if not selected_sm_id == state_machines_editor_ctrl.get_state_machine_id_for_page(page):
            logger.warning("Selection of page was not set correctly so session restore can not re-create selection.")
            return