Skip to content
Snippets Groups Projects
Select Git revision
  • c8ae8d7d07866cd06009bdb09e88c26f5adef394
  • master default protected
  • cmp_tool-improvement
  • v0.15
  • v0.14
  • v0.13
  • v0.12
  • v0.11
  • v0.09
  • v0.08
  • v0.07
  • v0.06
  • v0.05
13 results

fuzz_data_producer.c

Blame
  • tst.py 48.64 KiB
    #!/usr/bin/env python3
    import json
    import os
    import logging
    import time
    import gi
    gi.require_version('Gtk', '3.0')
    gi.require_version('GtkSource', '3.0')
    from gi.repository import Gtk, Gdk, Gio, GtkSource, GLib, GdkPixbuf
    import confignator
    cfg = confignator.get_config()
    
    import sys
    sys.path.append(cfg.get('paths', 'ccs'))
    import ccs_function_lib as cfl
    cfl.add_tst_import_paths()
    import view
    import data_model
    import file_management
    # import tst_logger
    import generator
    import codeblockreuse
    import connect_apps
    import dbus
    import toolbox
    import tc_management as tcm
    import tm_management as tmm
    import data_pool_tab as dpt
    
    import json_to_barescript
    import json_to_csv
    
    import spec_to_json
    
    
    # creating lists for type and subtype to get rid of duplicate entries, for TC List
    
    
    path_icon = os.path.join(os.path.dirname(__file__), 'style/tst.svg')
    menu_xml = os.path.join(os.path.dirname(__file__), 'app_menu.xml')
    css_file = os.path.join(os.path.dirname(__file__), 'style/style.css')
    style_path = os.path.join(os.path.dirname(__file__), 'style')
    
    logger = logging.getLogger('tst_app_main')
    log_lvl = cfg.get(section='tst-logging', option='level')
    logger.setLevel(level=log_lvl)
    console_hdlr = toolbox.create_console_handler(hdlr_lvl=log_lvl)
    logger.addHandler(hdlr=console_hdlr)
    log_file = cfg.get(section='tst-logging', option='log-file-path')
    file_hdlr = toolbox.create_file_handler(file=log_file)
    logger.addHandler(hdlr=file_hdlr)
    
    
    VERSION = '0.10'
    
    
    class TstApp(Gtk.Application):
    
        def __init__(self, application_id, flags, logger=logger):
            super().__init__(application_id=application_id, flags=flags)
            self.window = None
            self.application_id = application_id
    
            # set up logging
            # tst_logger.setup_logging(level=logging.DEBUG)
            self.logger = logger
    
            self.logger.info('Initiated a instance of the TstApp class')
    
        def do_startup(self):
            Gtk.Application.do_startup(self)
    
            action = Gio.SimpleAction.new('about_us', None)
            action.connect('activate', self._on_about)
            self.add_action(action)
    
            action = Gio.SimpleAction.new('quit', None)
            action.connect('activate', self._on_quit)
            self.add_action(action)
    
            self.create_modules_menu()
    
            # create the menu
            builder = Gtk.Builder.new_from_file(menu_xml)
            self.set_menubar(builder.get_object('app-menu'))
    
        def do_activate(self):
            # only allow a single window and raise any existing ones
            if not self.window:
                # Windows are associated with the application
                # when the last one is closed the application shuts down
                self.window = TstAppWindow(application=self, title='Test Specification Tool', logger=self.logger)
    
                # import DBus_Basic
                # import dbus
                # from dbus.mainloop.glib import DBusGMainLoop
                # dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
                # DBus_Basic.MessageListener(self.window, self.application_id)
    
            self.window.present()
    
        def create_modules_menu(self):
            action = Gio.SimpleAction.new('start_ccs_editor', None)
            action.connect("activate", self._on_start_ccs_editor)
            self.add_action(action)
    
            action = Gio.SimpleAction.new('start_poolviewer', None)
            action.connect("activate", self._on_start_poolviewer)
            self.add_action(action)
    
            action = Gio.SimpleAction.new('start_poolmanager', None)
            action.connect("activate", self._on_start_poolmanager)
            self.add_action(action)
    
            action = Gio.SimpleAction.new('start_plotter', None)
            action.connect("activate", self._on_start_plotter)
            self.add_action(action)
    
            action = Gio.SimpleAction.new('start_monitor', None)
            action.connect("activate", self._on_start_monitor)
            self.add_action(action)
    
            action = Gio.SimpleAction.new('start_config_editor', None)
            action.connect("activate", self._on_start_config_editor)
            self.add_action(action)
    
            action = Gio.SimpleAction.new('start_log_viewer', None)
            action.connect("activate", self._on_start_log_viewer)
            self.add_action(action)
    
        def _on_about(self, action, param):
            about_dialog = Gtk.AboutDialog(transient_for=self.window, modal=True)
            about_dialog.present()
            return
    
        def _on_quit(self, action, param):
            response = self.window.on_delete_event()
            if response:
                return
            self.quit()
            return
    
        def _on_start_ccs_editor(self, *args):
            try:
                cfl.start_editor()
            except Exception as e:
                self.logger.exception(e)
                message = 'Failed to start the CSS-Editor'
                self.add_info_bar(message_type=Gtk.MessageType.ERROR, message=message)
            return
    
        def _on_start_poolviewer(self, *args):
            cfl.start_pv()
            return
    
        def _on_start_poolmanager(self, *args):
            cfl.start_pmgr()
            return
    
        def _on_start_plotter(self, *args):
            cfl.start_plotter()
            return
    
        def _on_start_monitor(self, *args):
            cfl.start_monitor()
            return
    
        def _on_start_config_editor(self, *args):
            cfl.start_config_editor()
            return
    
        def _on_start_log_viewer(self, *args):
            cfl.start_log_viewer()
            return
    
    
    class TestInstance:
        def __init__(self, app, logger=logger, *args, **kwargs):
            self.logger = logger
            self.model = data_model.TestSpecification(logger=logger)
            self._filename = None
            self.view = view.Board(self.model, app, filename=self.filename, logger=self.logger)
    
        @property
        def filename(self):
            return self._filename
    
        @filename.setter
        def filename(self, value):
            self._filename = value
    
    
    class TstAppWindow(Gtk.ApplicationWindow):
    
        def __init__(self, logger=logger, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.logger = logger
            self.logger.info('Initializing an instance of the class TstAppWindow')
            self.product_paths = []
    
            # actions
            action = Gio.SimpleAction.new('make_new_test', None)
            action.connect('activate', self.on_new_test)
            self.add_action(action)
    
            action = Gio.SimpleAction.new('open', None)
            action.connect('activate', self.on_open)
            self.add_action(action)
    
            action = Gio.SimpleAction.new('save', None)
            action.connect('activate', self.on_save)
            self.add_action(action)
    
            action = Gio.SimpleAction.new('save_as', None)
            action.connect('activate', self.on_save_as)
            self.add_action(action)
    
            action = Gio.SimpleAction.new('csv_to_json', None)
            action.connect('activate', self.on_csv_to_json)
            self.add_action(action)
    
            action = Gio.SimpleAction.new('close', None)
            action.connect('activate', self.on_close)
            self.add_action(action)
    
            show_json_view = cfg.getboolean('tst-preferences', 'show-json-view')
            action = Gio.SimpleAction.new_stateful('model_viewer_toggle_hide', None,
                                                   GLib.Variant.new_boolean(show_json_view))
            action.connect('change-state', self.model_viewer_toggle_hide)
            self.add_action(action)
    
            action = Gio.SimpleAction.new('apply_css', None)
            action.connect('activate', self.on_apply_css)
            self.add_action(action)
    
            action = Gio.SimpleAction.new('about_us', None)
            action.connect('activate', self.on_about)
            self.add_action(action)
    
            self.create_make_menu()
    
            self.set_icon_from_file(path_icon)
    
            # GUI
            self.box = Gtk.Box()
            self.box.set_orientation(Gtk.Orientation.VERTICAL)
    
            # toolbar & place for info bar (see function add_info_bar)
            self.btn_new_file = Gtk.ToolButton()
            self.btn_new_file.set_icon_name('document-new')
            self.btn_new_file.set_tooltip_text('New test specification')
            self.btn_new_file.connect('clicked', self.on_new_test)
            self.btn_open_file = Gtk.ToolButton()
            self.btn_open_file.set_icon_name('document-open')
            self.btn_open_file.set_tooltip_text('Open file')
            self.btn_open_file.connect('clicked', self.on_open)
            # self.btn_apply_css = Gtk.ToolButton()
            # self.btn_apply_css.set_icon_name('media-playlist-repeat-symbolic')
            # self.btn_apply_css.set_tooltip_text('Apply CSS')
            # self.btn_apply_css.connect('clicked', self.apply_css)
            self.btn_save = Gtk.ToolButton()
            self.btn_save.set_icon_name('document-save')
            self.btn_save.set_tooltip_text('Save')
            self.btn_save.connect('clicked', self.on_save)
            # self.btn_show_model_viewer = Gtk.ToolButton()
            # self.btn_show_model_viewer.set_icon_name('accessories-dictionary-symbolic')
            # self.btn_show_model_viewer.set_tooltip_text('Show/hide model viewer')
            # self.btn_show_model_viewer.connect('clicked', self.model_viewer_toggle_hide)
            self.btn_generate_products = Gtk.ToolButton()
            self.btn_generate_products.set_label('Generate scripts')
            self.btn_generate_products.set_icon_name('text-x-python')
            self.btn_generate_products.set_tooltip_text('Generate command.py, verification.py and manually.py')
            self.btn_generate_products.connect('clicked', self.on_generate_products)
    
            self.btn_start_ccs_editor = Gtk.ToolButton()
            self.btn_start_ccs_editor.set_label('Start CCS')
            pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
                cfg.get('paths', 'ccs') + '/pixmap/ccs_logo_2.svg', 28, 28)
            icon = Gtk.Image.new_from_pixbuf(pixbuf)
            self.btn_start_ccs_editor.set_icon_widget(icon)
            self.btn_start_ccs_editor.set_tooltip_text('Start CCS-Editor')
            self.btn_start_ccs_editor.connect('clicked', self.on_start_ccs_editor)
    
            self.btn_open_progress_view = Gtk.ToolButton()
            self.btn_open_progress_view.set_label('Start ProgressView')
            self.btn_open_progress_view.set_icon_name('utilities-system-monitor')
            self.btn_open_progress_view.set_tooltip_text('Start ProgressView')
            self.btn_open_progress_view.connect('clicked', self.on_start_progress_viewer)
    
            self.toolbar = Gtk.Toolbar()
            self.toolbar.insert(self.btn_new_file, 0)
            self.toolbar.insert(self.btn_open_file, 1)
            self.toolbar.insert(self.btn_save, 2)
            # self.toolbar.insert(self.btn_show_model_viewer, 2)
            self.toolbar.insert(self.btn_generate_products, 3)
            self.toolbar.insert(self.btn_start_ccs_editor, 4)
            self.toolbar.insert(self.btn_open_progress_view, 5)
            
            # IDB chooser
            self.idb_chooser = Gtk.ToolButton()
    
            label = Gtk.Label()
            label.set_markup('<b>IDB:</b> {}'.format(cfl.scoped_session_idb.bind.url.database))
            self.idb_chooser.set_label_widget(label)
            self.idb_chooser.set_tooltip_text('Select IDB')
            self.idb_chooser.connect('clicked', self.on_set_idb_version)
            self.toolbar.insert(self.idb_chooser, 6)
    
            # separator
            sepa = Gtk.SeparatorToolItem()
            sepa.set_expand(True)
            self.toolbar.insert(sepa, 7)
    
            # logo
            self.unilogo = Gtk.ToolButton()
            pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
                cfg.get('paths', 'ccs') + '/pixmap/Icon_Space_blau_en.png', 32, 32)
            icon = Gtk.Image.new_from_pixbuf(pixbuf)
            self.unilogo.set_icon_widget(icon)
            self.unilogo.connect('clicked', self.on_about)
            self.toolbar.insert(self.unilogo, 8)
            self.box.pack_start(self.toolbar, False, True, 0)
            
            self.info_bar = None
    
            # packing the widgets
            self.work_desk = Gtk.Paned()
            self.work_desk.set_wide_handle(True)
    
            # add the notebook for the test specifications
            self.notebook = Gtk.Notebook()
            self.notebook.connect('switch-page', self.update_model_viewer)
            self.work_desk.pack1(self.notebook)
    
            self.feature_area = Gtk.Notebook()
            self.work_desk.pack2(self.feature_area)
    
            self.codeblockreuse = codeblockreuse.CBRSearch(app_win=self, logger=self.logger)
            self.label_widget_codeblockreuse = Gtk.Label()
            self.label_widget_codeblockreuse.set_text('Code Snippets')
            self.feature_area.append_page(child=self.codeblockreuse, tab_label=self.label_widget_codeblockreuse)
    
            import log_viewer
            self.log_view = log_viewer.LogView(filename=log_file, app_win=self)
            self.label_widget_log_view = Gtk.Label()
            self.label_widget_log_view.set_text('Log View')
            self.feature_area.append_page(child=self.log_view, tab_label=self.label_widget_log_view)
    
            self.json_view = ViewModelAsJson()
            self.update_model_viewer()
            self.label_widget_json_view = Gtk.Label()
            self.label_widget_json_view.set_text('JSON View')
            self.feature_area.append_page(child=self.json_view, tab_label=self.label_widget_json_view)
    
            # command list tab
    
            self.tcm = tcm.TcTable()
            self.label_widget_tcm = Gtk.Label()
            self.label_widget_tcm.set_text('TC Table')
            self.feature_area.insert_page(child=self.tcm, tab_label=self.label_widget_tcm, position=1)
    
            # telemetry list tab
            self.telemetry = tmm.TmTable()
            self.label_widget_telemetry = Gtk.Label()
            self.label_widget_telemetry.set_text('TM Table')
            self.feature_area.insert_page(child=self.telemetry, tab_label=self.label_widget_telemetry, position=2)
    
            # data pool list tab
            self.data_pool_tab = dpt.DataPoolTable()
            self.label_widget_data_pool = Gtk.Label()
            self.label_widget_data_pool.set_text('Data Pool')
            self.feature_area.insert_page(child=self.data_pool_tab, tab_label=self.label_widget_data_pool, position=3)
    
            self.box.pack_start(self.work_desk, True, True, 0)
    
            # # panes for the step grid an so on
            # self.paned = Gtk.Paned.new(Gtk.Orientation.HORIZONTAL)
            #
            # # paned: left pane: CodeBlockReuse
            #
            # self.codeblockreuse = search.Search(None, self)
            # self.paned.pack1(child=self.codeblockreuse, resize=True, shrink=True)
            #
            # # paned: right pane: TestSpecificationEditor
            # self.notebook = Gtk.Notebook()
            # self.paned.pack2(child=self.notebook, resize=True, shrink=False)
            #
            # # add the view to display the data model as JSON
            # self.json_view = ViewModelAsJson()
            # self.update_model_viewer()
            # # self.paned.pack2(child=self.json_view, resize=True, shrink=True)
            #
            # self.box.pack_start(self.paned, True, True, 0)
    
            self.add(self.box)
    
            self.connect('delete-event', self.on_delete_event)
    
            # self.dev_open_example_json_file()
    
            # set the size (width and height) of the main window using the values of the configuration file
            height_from_config = cfg.get('tst-preferences', 'main-window-height')
            width_from_config = cfg.get('tst-preferences', 'main-window-width')
            if height_from_config is not None and width_from_config is not None:
                self.resize(int(width_from_config), int(height_from_config))
            else:
                self.maximize()
            # set the position of the Paned widget using the configuration file
            paned_position = cfg.get('tst-preferences', 'paned-position')
            if paned_position is None:
                paned_position = self.get_size().width * 3 / 5
            self.work_desk.set_position(int(paned_position))
            # # set the position of the paned of the widget self.codeblockreuse
            # paned_position_cbr = cfg.get('tst-preferences', 'paned-position-codeblockreuse')
            # self.codeblockreuse.set_paned_position(int(paned_position_cbr))
    
            self.show_all()
    
            # for styling the application with CSS
            context = self.get_style_context()
            Gtk.StyleContext.add_class(context, 'tst-css')
            self.on_apply_css()
    
        def create_make_menu(self):
            action = Gio.SimpleAction.new('generate_scripts', None)
            action.connect('activate', self.on_generate_products)
            self.add_action(action)
    
            action = Gio.SimpleAction.new('generate_barescript', None)
            action.connect('activate', self.on_generate_barescript)
            self.add_action(action)
    
            action = Gio.SimpleAction.new('generate_csv', None)
            action.connect('activate', self.on_generate_csv)
            self.add_action(action)
    
        def add_info_bar(self, message_type, message):
            """
            Adds a InfoBar and moves it below the toolbar
            :param Gtk.MessageType message_type: type of the message which should be shown
            :param str message: The text of the message
            """
            assert type(message_type) is Gtk.MessageType
            assert type(message) is str
            self.info_bar = Gtk.InfoBar()
            self.info_bar.set_show_close_button(True)
            self.info_bar.set_revealed(True)
            self.info_bar.set_message_type(message_type)
            self.box.pack_start(self.info_bar, False, True, 0)
            # move the info bar below the toolbar:
            self.box.reorder_child(self.info_bar, 1)
            # add the text:
            self.info_bar.get_content_area().pack_start(
                Gtk.Label(message),
                False, False, 0)
            self.info_bar.connect('response', self.remove_info_bar)
            self.show_all()
    
        def remove_info_bar(self, infobar, response_id):
            if response_id == -7:
                infobar.destroy()
    
        def new_test(self):
            new_test = TestInstance(self, logger=self.logger)
            return new_test
    
        def new_page(self, test_instance):
            if test_instance.filename is not None:
                label_text = os.path.basename(test_instance.filename)
                test_instance.view.filename = test_instance.filename
            else:
                label_text = 'New test'
            label = self.notebook_page_label(label_text=label_text)
            page_index = self.notebook.append_page(child=test_instance.view, tab_label=label)
            # reload the data of the widgets, in order to display it
            test_instance.view.update_widget_data()
            self.show_all()
            return page_index
    
        def notebook_page_label(self, label_text):
            box = Gtk.Box()
            box.set_orientation(Gtk.Orientation.HORIZONTAL)
            label = Gtk.Label()
            label.set_text(label_text)
            btn_close = Gtk.Button.new_from_icon_name('window-close-symbolic', Gtk.IconSize.BUTTON)
            btn_close.set_tooltip_text('Close')
            btn_close.connect('clicked', self.on_close_clicked)
            box.pack_start(label, True, True, 0)
            box.pack_start(btn_close, True, True, 0)
            box.show_all()
            return box
    
        def current_test_instance(self):
            test_instance = None
            current_page = self.notebook.get_current_page()
            if not current_page == -1:
                test_instance = self.notebook.get_nth_page(current_page)
            return test_instance
    
        def current_model(self):
            # get the  data model of the current notebook page
            current_model = None
            current_test = self.current_test_instance()
            if current_test is not None:
                current_model = current_test.model
                if not isinstance(current_model, data_model.TestSpecification):
                    raise Exception
            return current_model
    
        def update_model_viewer(self, *args):
            """
            Gets the data of the model and makes a JSON string out of it. Intended to display the model data as plain JSON
            """
            if len(args) == 3:
                nb, _, n = args
                tab = nb.get_nth_page(n)
                self.json_view.update(tab.model)
                return
    
            current_model = self.current_model()
            self.json_view.update(current_model)
    
        def model_viewer_toggle_hide(self, action, value):
            visible = self.json_view.is_visible()
            action.set_state(GLib.Variant.new_boolean(not visible))
            if visible:
                self.json_view.hide()
            else:
                self.json_view.show()
    
        def on_new_test(self, *args):
            # create a new test instance and add a sequence + first step
            test = self.new_test()
            new_seq = test.model.add_sequence()
            new_step = test.model.get_sequence(new_seq).add_step_below()
            # adding a page to the notebook
            self.new_page(test)
            # show the details of the new step
            new_step_widget = test.view.get_step_widget(seq_num=new_seq, step_number=new_step.step_number)
            new_step_widget.on_toggle_detail(None)
            # update the model viewer
            self.update_model_viewer()
    
        def on_close(self, *args):
            """ Closing the current active page """
            current_page = self.notebook.get_current_page()
            if not current_page == -1:
                # check if it should be saved
                # ToDo
                # remove the page from the notebook
                self.notebook.remove_page(current_page)
            self.update_model_viewer()
    
        def on_close_clicked(self, widget):
            """
            Closing the page on which was clicked
            """
            for i in range(0, self.notebook.get_n_pages()):  # Loop over all availabe page numbers
                page = self.notebook.get_nth_page(i)  # Get page widget
                if self.notebook.get_tab_label(
                        page) == widget.get_parent():  # Check if the label widget is the same as for the given widget
                    self.notebook.remove_page(i)  # If so close the page
                    return
    
            # self.notebook.remove_page(widget.get_parent())
    
        def on_open(self, *args):
            dialog = Gtk.FileChooserDialog('Please choose a file',
                                           self,
                                           Gtk.FileChooserAction.OPEN,
                                           (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
            # using the last folder from history
            last_folder = cfg.get('tst-history', 'last-folder')
            if os.path.isdir(last_folder):
                dialog.set_current_folder(last_folder)
            self.add_filters(dialog)
            response = dialog.run()
            if response == Gtk.ResponseType.OK:
                file_selected = dialog.get_filename()
                cfg.save_option_to_file('tst-history', 'last-folder', os.path.dirname(file_selected))
                try:
                    json_type = True
                    data_from_file = file_management.open_file(file_name=file_selected)
                    filename = file_selected
                except json.decoder.JSONDecodeError:
                    # data_from_file = file_management.from_json(spec_to_json.run(specfile=file_selected, gen_cmd=True, save_json=False))
                    data_from_file = spec_to_json.run(specfile=file_selected, gen_cmd=True, save_json=False)
                    filename = file_selected.replace('.' + file_selected.split('.')[-1], '.json')
                    json_type = False
                    if os.path.exists(filename):
                        self.existing_json_warn_dialog(filename)
    
                if data_from_file is not None:
                    self.on_open_create_tab(data_from_file, filename, json_type)
    
            dialog.destroy()
            return
    
        def on_open_create_tab(self, data_from_file, filename, json_type):
            # make a new test instance and notebook page
            self.logger.info('make a new test instance and notebook page for: {}'.format(filename))
            new_test = self.new_test()
            new_test.model.decode_from_json(json_data=data_from_file)
            new_test.filename = filename
            if not json:
                new_test.ask_overwrite = True
            else:
                new_test.ask_overwrite = True
            new_page_index = self.new_page(test_instance=new_test)
            self.update_model_viewer()
            new_test.view.update_widget_data()
            self.notebook.set_current_page(new_page_index)
            return
    
        def on_save(self, *args):
            # get the  data model of the current notebook page
            current_test = self.current_test_instance()
            current_model = self.current_model()
            # current_model2=current_model.serialize(current_model)
            if current_model is not None and current_test.filename is None:
                self.save_as_file_dialog()
            elif current_test and current_test.ask_overwrite and current_test.filename:
                if os.path.exists(current_test.filename):
                    self.overwrite_dialog(current_test)
                else:
                    self.save_as_file_dialog()
            elif current_model is not None:
                file_management.save_file(file_path=current_test.filename, test_spec=current_model, logger=self.logger)
    
        def on_save_as(self, *args):
            self.save_as_file_dialog()
    
        def save_as_file_dialog(self):
            current_test = self.current_test_instance()
            current_name = self.current_model().name
            current_model = self.current_model()
            dialog = Gtk.FileChooserDialog('Please choose a file',
                                           self,
                                           Gtk.FileChooserAction.SAVE,
                                           (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_SAVE, Gtk.ResponseType.OK))
            dialog.set_current_folder(cfg.get(section='tst-history', option='last-folder'))
            dialog.set_current_name('{}-TS-{}.json'.format(current_name, current_model.spec_version))
            self.add_filters(dialog)
            dialog.set_do_overwrite_confirmation(True)
            response = dialog.run()
            if response == Gtk.ResponseType.OK:
                file_selected = dialog.get_filename()
                cfg.save_option_to_file('tst-history', 'last-folder', os.path.dirname(file_selected))
                file_management.save_file(file_path=file_selected, test_spec=current_model, file_extension='json',
                                          logger=self.logger)
                current_test.filename = file_selected
                file_name = file_selected.split('/')[-1]
                # current_model.name = file_selected.split('/')[-1].split('.')[0].split('-TS-')[0]  # Get only the name
                current_test.update_widget_data()
                self.notebook.set_tab_label(current_test, self.notebook_page_label(file_name))  # Update tab label
                self.show_all()
                dialog.destroy()
                return True
            else:
                dialog.destroy()
                return False
    
        def add_filters(self, dialog, filter_json=True):
            if filter_json:
                filter_text = Gtk.FileFilter()
                filter_text.set_name('JSON format')
                filter_text.add_mime_type('application/json')
                filter_text.add_pattern('.json')
                dialog.add_filter(filter_text)
            else:
                filter_text = Gtk.FileFilter()
                filter_text.set_name('Spec Files')
                filter_text.add_mime_type('text/csv')
                filter_text.add_pattern('.csv*')
                dialog.add_filter(filter_text)
    
            filter_any = Gtk.FileFilter()
            filter_any.set_name('Any files')
            filter_any.add_pattern('*')
            dialog.add_filter(filter_any)
    
        def on_csv_to_json(self, *args):
            dialog = Gtk.FileChooserDialog('Please choose a CSV File',
                                           self,
                                           Gtk.FileChooserAction.OPEN,
                                           (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
            # using the last folder from history
            last_folder = cfg.get('tst-history', 'last-folder')
            if os.path.isdir(last_folder):
                dialog.set_current_folder(last_folder)
            # self.add_filters(dialog, filter_json=False)
            response = dialog.run()
            if response == Gtk.ResponseType.OK:
                cfg.save_option_to_file('tst-history', 'last-folder', dialog.get_current_folder())
                file_selected = dialog.get_filename()
                filename = file_selected.replace('.' + file_selected.split('.')[-1], '.json')
                data_from_file = spec_to_json.run(specfile=file_selected, gen_cmd=True, save_json=False)
                self.on_open_create_tab(data_from_file, filename, json_type=False)
                # self.on_open_create_tab(data_from_file, filename, json_type=False)
                dialog.destroy()
    
                self.save_as_file_dialog()
            else:
                dialog.destroy()
    
            return
    
        def overwrite_dialog(self, current_test):
            filepath = current_test.filename
            filename = filepath.split('/')[-1]
            folder = filepath[:-len(filename)-1]
            dialog = Gtk.MessageDialog()
            dialog.add_buttons(Gtk.STOCK_YES, Gtk.ResponseType.YES, Gtk.STOCK_NO, Gtk.ResponseType.NO)
            dialog.set_markup('Overwrite existing File?')
            dialog.format_secondary_text('{} at {} already exists'.format(filename, folder))
            response = dialog.run()
    
            if response == Gtk.ResponseType.YES:
                current_test.ask_overwrite = False
                dialog.destroy()
                self.on_save()
            else:
                dialog.destroy()
    
            return
    
        def existing_json_warn_dialog(self, filepath):
            filename = filepath.split('/')[-1]
            folder = filepath[:-len(filename)-1]
            dialog = Gtk.MessageDialog()
            dialog.add_buttons(Gtk.STOCK_OK, Gtk.ResponseType.OK)
            dialog.set_markup('CSV converted Json File already Exists'.format(filename))
            dialog.format_secondary_text('{} at {} already exists, temporarily saved in TST \nBe careful during saving'.format(filename, folder))
            dialog.run()
            dialog.destroy()
            return True
    
        def unsaved_changes_overwrite_dialog(self, current_test):
            filepath = current_test.filename
            filename = filepath.split('/')[-1]
            folder = filepath[:-len(filename)-1]
            dialog = Gtk.MessageDialog()
            dialog.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_YES, Gtk.ResponseType.YES, Gtk.STOCK_NO, Gtk.ResponseType.NO)
            dialog.set_markup('Unsaved changes in {}, Overwrite?'.format(filename))
            dialog.format_secondary_text('{} at {} already exists'.format(filename, folder))
            response = dialog.run()
            if response == Gtk.ResponseType.YES:
                current_test.ask_overwrite = False
                dialog.destroy()
                self.on_save()
            elif response == Gtk.ResponseType.CANCEL:
                dialog.destroy()
                return False
            else:
                dialog.destroy()
    
            return True
    
        def unsaved_changes_newfile_dialog(self, current_test):
            filepath = current_test.filename
            if filepath:
                filename = filepath.split('/')[-1]
            else:
                filename = 'New Test'
            dialog = Gtk.MessageDialog()
            dialog.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_YES, Gtk.ResponseType.YES, Gtk.STOCK_NO, Gtk.ResponseType.NO)
            dialog.set_markup('Unsaved file {}, save?'.format(filename))
            # dialog.format_secondary_text('{} at {} is unsaved'.format(filename, folder))
            response = dialog.run()
    
            if response == Gtk.ResponseType.YES:
                current_test.ask_overwrite = False
                dialog.destroy()
                response = self.save_as_file_dialog()
                if response:
                    return True
                else:
                    return False
            elif response == Gtk.ResponseType.CANCEL:
                dialog.destroy()
                return False
            else:
                dialog.destroy()
    
            return True
    
        def on_delete_event(self, *args):
            self.logger.info('save preferences')
            # saving the height and width of the main window
            cfg.save_option_to_file('tst-preferences', 'main-window-height', str(self.get_size().height))
            cfg.save_option_to_file('tst-preferences', 'main-window-width', str(self.get_size().width))
            # save the position of the paned widget
            cfg.save_option_to_file('tst-preferences', 'paned-position', str(self.work_desk.get_position()))
            # save the preferences of the CodeReuseFeature
            self.codeblockreuse.save_panes_positions()
            self.logger.info('Check for Unsaved Buffer')
            response = self._check_unsaved_buffer()
            if not response:
                return True
            return False
    
        def _check_unsaved_buffer(self):
            for test_instance in self.notebook:
                filename = test_instance.filename
                tst_json = json.loads(test_instance.model.encode_to_json())
                if filename and os.path.exists(filename):
                    file_json = file_management.open_file(filename)
                    if not tst_json == file_json:
                        response = self.unsaved_changes_overwrite_dialog(test_instance)
                        if not response:
                            return False
                else:
                    response = self.unsaved_changes_newfile_dialog(test_instance)
                    if not response:
                        return False
    
            return True
    
        def on_generate_products(self, *args):
            """
            This function generates out of the current test script model the command script, the verification script and
            the documentation file. If it succeeded, a dialog box will be triggered.
            """
            # ToDo: remove the reloading, when developing is finished
            # import importlib
            # importlib.reload(generator)
            model = self.current_model()
            if not model:
                logger.info('Test Files can not be generated without Steps')
                logger.error('Please add at least one test step')
                return
            elif not model.name:
                logger.info('Test Files can not be generated if Test has no name!')
                logger.error('Please give the test a name')
                return
            self.product_paths = generator.make_all(model=model)
            # triggering the dialog after generation
            self.on_generate_products_message_dialog(paths=self.product_paths)
    
        def on_generate_barescript(self, *args):
            """
            Generates a small python test file without all the additional stuff from on_generate_scripts
            """
            dialog = Gtk.FileChooserDialog(
                title="Save Script AS", parent=self, action=Gtk.FileChooserAction.SAVE)
            dialog.add_buttons(
                Gtk.STOCK_CANCEL,
                Gtk.ResponseType.CANCEL,
                Gtk.STOCK_SAVE,
                Gtk.ResponseType.OK, )
    
            if self.current_test_instance():
                # current_json_filename = self.current_test_instance().filename
                current_model = self.current_model()
            else:
                logger.error('Small Script can not be generated without json file')
                return
    
            outfile_basic = '{}-TS-{}.py'.format(current_model.name, current_model.spec_version)
            dialog.set_current_name(outfile_basic)
            dialog.set_current_folder(cfg.get('tst-history', 'last-folder'))
    
            response = dialog.run()
            if response == Gtk.ResponseType.OK:
                json_to_barescript.run(current_model.encode_to_json(), dialog.get_filename())
                cfg.save_option_to_file('tst-history', 'last-folder', dialog.get_current_folder())
    
            dialog.destroy()
            return
    
        def on_generate_csv(self, *args):
            """
            Generates a CSV Test Specification file
            """
            dialog = Gtk.FileChooserDialog(
                title="Save CSV AS", parent=self, action=Gtk.FileChooserAction.SAVE)
            dialog.add_buttons(
                Gtk.STOCK_CANCEL,
                Gtk.ResponseType.CANCEL,
                Gtk.STOCK_SAVE,
                Gtk.ResponseType.OK, )
    
            if self.current_test_instance():
                # current_json_filename = self.current_test_instance().filename
                current_model = self.current_model()
            else:
                logger.info('CSV File can not be generated without json file')
                return
    
            outfile_basic = '{}-IASW-{}-TS-{}.csv_PIPE'.format(current_model.name, current_model.iasw_version, current_model.spec_version)
            dialog.set_current_name(outfile_basic)
            dialog.set_current_folder(cfg.get('tst-history', 'last-folder'))
    
            response = dialog.run()
            if response == Gtk.ResponseType.OK:
                json_to_csv.run(current_model.encode_to_json(), dialog.get_filename())
                cfg.save_option_to_file('tst-history', 'last-folder', dialog.get_current_folder())
    
            dialog.destroy()
            return
    
        def connect_to_ccs_editor(self):
            # get the DBus connection to the CCS-Editor
            editor = connect_apps.connect_to_editor()
            if editor is None:
                self.logger.warning('Failed to connect to the CCS-Editor via DBus')
                self.on_start_ccs_editor(False)
    
            editor = connect_apps.connect_to_app('editor')
            '''     
            k = 0
            while k < 3:
                # try again to connect to the CCS-Editor
                self.logger.info('Trying to connect to the CCS-Editor via DBus.')
                time.sleep(1)
                editor = connect_apps.connect_to_editor()
                if editor is not None:
                    self.logger.info('Successfully connected to the CCS-Editor via DBus.')
                    break
                k += 1'''
            return editor
    
        def connect_progress_viewer(self):
            # get the DBus connection to the CCS-Editor
            try:
                connect_apps.connect_to_progress_viewer(logger=self.logger)
            except dbus.exceptions.DBusException:
                self.logger.warning('could not connect to ProgressViewer, starting it')
                cfl.start_progress_view()
            k = 0
            while k < 10:
                # try again to connect to the CCS-Editor
                self.logger.info('trying to connect to the ProgressViewer via DBus.')
                time.sleep(0.2)
                try:
                    prog = connect_apps.connect_to_progress_viewer(logger=self.logger)
                    if prog is not None:
                        self.logger.info('Successfully connected to the ProgressViewer via DBus.')
                        return prog
                except dbus.exceptions.DBusException:
                    self.logger.warning('could not connect to ProgressViewer')
                k += 1
    
        def ccs_editor_open_files(self, editor, file_list):
            if editor is not None:
                # open the files in the CCS-Editor
                for pth in file_list:
                    pth = os.path.abspath(pth)
                    try:
                        self.logger.info('Opening file {} in the CCS-Editor'.format(pth))
                        editor.Functions('open_file', pth)
                    except dbus.exceptions.DBusException as e:
                        message = 'Could not find the file: {}'.format(pth)
                        self.logger.error(message)
                        self.logger.exception(e)
                        self.add_info_bar(message_type=Gtk.MessageType.ERROR, message=message)
    
        def on_generate_products_message_dialog(self, paths):
            """
            After the successful generation of the products, a dialog is shown and asks if the files should be opened in the
            CCS-editor.
            :param list paths: List of the paths of the product files
            """
            dialog = Gtk.MessageDialog(self,
                                       0,
                                       Gtk.MessageType.QUESTION,
                                       Gtk.ButtonsType.YES_NO,
                                       'Scripts were generated')
            message = 'Generated files:\n'
            for entry in paths:
                message += os.path.basename(entry) + '\n'
            paths.append(os.path.join(os.path.realpath(os.path.join(os.path.dirname(__file__), '..')), 'prep_test_env.py'))
            message += 'Do you want to open them in CCS?'
            dialog.format_secondary_text(message)
            response = dialog.run()
            if response == Gtk.ResponseType.YES:
                # get a Dbus connection to the CCS-Editor
                editor = self.connect_to_ccs_editor()
                # open files in the CCS-Editor
                if editor is not None:
                    self.ccs_editor_open_files(editor, paths)
            elif response == Gtk.ResponseType.NO:
                pass
            dialog.destroy()
    
        def get_log_file_paths_from_json_file_name(self):
            from testlib import testing_logger
            paths = {}
            current_instance = self.current_test_instance()
            if not current_instance:
                self.logger.warning('Progress Viewer started without running Test')
                return ''
            try:
                current_file_name = os.path.basename(current_instance.filename)
                path_test_specs = cfg.get(section='tst-paths', option='tst_products')
                path_test_runs = cfg.get(section='tst-logging', option='test_run')
    
                json_file_path = os.path.join(path_test_specs, current_file_name)
                paths['json_file_path'] = json_file_path
    
                name = generator.strip_file_extension(current_file_name)
                cmd_log_file_path = os.path.join(path_test_runs, name + testing_logger.cmd_log_auxiliary)
                paths['cmd_log_file_path'] = cmd_log_file_path
    
                vrc_log_file_path = os.path.join(path_test_runs, name + testing_logger.vrc_log_auxiliary)
                paths['vrc_log_file_path'] = vrc_log_file_path
            except Exception as e:
                self.logger.warning('Json or Log Files could not be found')
                return ''
            return paths
    
        def on_make_desktop_entry(self):
            # ToDo: create a file for the desktop entry
            pass
    
        def on_start_progress_viewer(self, *args):
    
            self.logger.info('Starting ProgressViewer')
    
            progress_viewer = self.connect_progress_viewer()
            file_names = self.get_log_file_paths_from_json_file_name()
            try:
                progress_viewer.Activate('open-test-files', [file_names], [])
            except Exception as e:
                message = 'Could not start ProgressViewer application.'
                self.logger.error(message)
                self.logger.exception(e)
                # add a info bar message that the starting of the CCS-Editor failed.
                self.add_info_bar(message_type=Gtk.MessageType.ERROR, message=message)
    
        def on_start_ccs_editor(self, *args):
            try:
                self.logger.info('Starting CCS-Editor application.')
                cfl.start_editor()
            except Exception as e:
                message = 'Could not start CCS-Editor.'
                self.logger.error(message)
                self.logger.exception(e)
                # add a info bar message that the starting of the CCS-Editor failed.
                self.add_info_bar(message_type=Gtk.MessageType.ERROR, message=message)
    
        def on_apply_css(self, *args):
            style_provider = Gtk.CssProvider()
            css = open(css_file, 'rb')  # rb needed for python 3 support
            css_data = css.read()
            css.close()
            style_provider.load_from_data(css_data)
            Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
                                                     style_provider,
                                                     Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
            Gtk.StyleContext.reset_widgets(Gdk.Screen.get_default())
    
        def on_about(self, *args):
            about_dialog = Gtk.AboutDialog(transient_for=self, modal=True)
            about_dialog.set_authors(['Stefan Winkler', 'Dominik Möslinger', 'Sebastian Miksch', 'Marko Mecina'])
            about_dialog.set_website('https://space.univie.ac.at/en')
            about_dialog.set_website_label('space.univie.ac.at')
            about_dialog.set_version(VERSION)
            pixbuf = GdkPixbuf.Pixbuf.new_from_file(style_path + '/tst.png')
            about_dialog.set_logo(pixbuf)
            about_dialog.set_program_name('Test Specification Tool')
            about_dialog.set_copyright('UVIE 08/2022')
            about_dialog.set_license_type(Gtk.License.MPL_2_0)
            about_dialog.present()
            return
    
        def on_set_idb_version(self, *args):
            self.reconnect_mib()
            dialog = IDBChooser()
            dialog.set_transient_for(self)
    
            response = dialog.run()
            if response == Gtk.ResponseType.OK:
                model, it = dialog.selection.get_selected()
                idb = model[it][0]
                cfl.set_scoped_session_idb_version(idb_version=idb)
                label = self.idb_chooser.get_label_widget()
                label.set_markup('<b>IDB:</b> {}'.format(cfl.scoped_session_idb.bind.url.database))
                self.feature_area.freeze_child_notify()
                page = self.feature_area.get_current_page()
                self.reload_tc_table()
                self.reload_tm_table()
                self.reload_dp_table()
                self.feature_area.set_current_page(page)
                self.feature_area.thaw_child_notify()
                dialog.destroy()
            else:
                dialog.destroy()
    
        def reload_tc_table(self):
            self.feature_area.remove_page(self.feature_area.page_num(self.tcm))
            tcm.reload_tc_data()
            self.tcm = tcm.TcTable()
            self.feature_area.insert_page(self.tcm, self.label_widget_tcm, 1)
    
        def reload_tm_table(self):
            self.feature_area.remove_page(self.feature_area.page_num(self.telemetry))
            tmm.reload_tm_data()
            self.telemetry = tmm.TmTable()
            self.feature_area.insert_page(self.telemetry, self.label_widget_telemetry, 2)
    
        def reload_dp_table(self):
            self.feature_area.remove_page(self.feature_area.page_num(self.data_pool_tab))
            dpt.reload_dp_data()
            self.data_pool_tab = dpt.DataPoolTable()
            self.feature_area.insert_page(self.data_pool_tab, self.label_widget_data_pool, 3)
    
        @staticmethod
        def reconnect_mib():
            cfl.scoped_session_idb.close()
    
    
    class IDBChooser(Gtk.Dialog):
        def __init__(self):
            super(IDBChooser, self).__init__(title='Select MIB')
            self.add_buttons(Gtk.STOCK_OK, Gtk.ResponseType.OK, Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)
            self.set_size_request(300, 200)
    
            idb_selection = Gtk.ListStore(str)
            mibs = cfl.scoped_session_idb.execute('show databases').fetchall()
    
            for m, in mibs:
                if m.count('mib'):
                    idb_selection.append([m])
    
            tv = Gtk.TreeView(model=idb_selection)
            self.selection = tv.get_selection()
            self.selection.set_mode(Gtk.SelectionMode.SINGLE)
    
            col = Gtk.TreeViewColumn('SCHEMA NAME', Gtk.CellRendererText(), text=0)
            tv.append_column(col)
    
            scr = Gtk.ScrolledWindow()
            scr.add(tv)
    
            box = self.get_content_area()
            box.pack_start(scr, True, True, 0)
    
            self.show_all()
    
    
    class ViewModelAsJson(Gtk.Box):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.set_orientation(Gtk.Orientation.VERTICAL)
    
            # options area
            self.box_h = Gtk.Box.new(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
            self.style_manager = GtkSource.StyleSchemeManager.get_default()
            self.style_manager.append_search_path(style_path)
            self.chooser_button = GtkSource.StyleSchemeChooserButton()
            self.chooser_button.set_style_scheme(self.style_manager.get_scheme('darcula'))
            self.chooser_button.connect('notify', self._update_style)
            img = Gtk.Image.new_from_icon_name('applications-system-symbolic', Gtk.IconSize.BUTTON)
            self.chooser_button.set_image(img)
            self.chooser_button.set_label('')
            self.current_scheme = self.chooser_button.get_style_scheme()
            self.chooser_button.set_tooltip_text('style: ' + self.current_scheme.get_name())
            self.box_h.pack_end(self.chooser_button, False, False, 0)
            self.pack_start(self.box_h, False, True, 0)
    
            # the view of the json
            self.scrolled_window = Gtk.ScrolledWindow()
            self.model_viewer = GtkSource.View()
            self.model_viewer.set_editable(False)
            self.model_viewer_buffer = self.model_viewer.get_buffer()
            self.lm = GtkSource.LanguageManager()
            self.model_viewer_buffer.set_language(self.lm.get_language('json'))
            self.model_viewer_buffer.set_style_scheme(self.current_scheme)
            self.scrolled_window.add(self.model_viewer)
            self.pack_start(self.scrolled_window, True, True, 0)
    
        def _update_style(self, widget, spec):
            if spec.name == 'style-scheme':
                self.current_scheme = self.chooser_button.get_style_scheme()
                self.model_viewer_buffer.set_style_scheme(self.current_scheme)
                self.chooser_button.set_label('')
                self.chooser_button.set_tooltip_text('style: ' + self.current_scheme.get_name())
    
        def options_toggle_hide(self, button):
            visible = self.box_h.is_visible()
            if visible:
                self.box_h.hide()
            else:
                self.box_h.show()
    
        def update(self, model):
            """
            Gets the data of the model and makes a JSON string out of it. Intended to display the model data as plain JSON
            :param data_model.TestSpecification model: a instance of the TestSpecification class
            :param data_model.TestSequence model: a instance of the TestSpecification class
            """
            assert isinstance(model, data_model.TestSpecification) or model is None
            if model is not None:
                json_str = json.dumps(model, sort_keys=True, indent=8, default=model.serialize)
                self.model_viewer_buffer.set_text(json_str)
            else:
                self.model_viewer_buffer.set_text('{}')
    
    
    def run():
        bus_name = cfg.get('dbus_names', 'tst')
        dbus.validate_bus_name(bus_name)
    
        applica = TstApp(bus_name, Gio.ApplicationFlags.FLAGS_NONE, logger=logger)
        applica.run()
    
    
    if __name__ == '__main__':
        run()