From 94cf023ca57896ec2131c5c3185906496270adde Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dominik=20M=C3=B6slinger?= <dominik.moeslinger@univie.ac.at>
Date: Tue, 20 Jul 2021 14:24:52 +0200
Subject: [PATCH] TST: Homeoffice Transfer

---
 .../testlib/analyse_command_log.py            |  19 ++
 .../testlib/analyse_test_run.py               |  96 +++++++--
 Tst/tst/data_model.py                         |  36 ++--
 Tst/tst/generator.py                          |  11 +-
 Tst/tst/generator_templates/co_step.py        |   2 +-
 Tst/tst/generator_templates/run_step.py       |   2 +-
 Tst/tst/generator_templates/ver_step.py       |   2 +-
 Tst/tst/view.py                               | 202 ++++++++++++++++--
 8 files changed, 316 insertions(+), 54 deletions(-)

diff --git a/Tst/testing_library/testlib/analyse_command_log.py b/Tst/testing_library/testlib/analyse_command_log.py
index 119ee0d..39010f6 100644
--- a/Tst/testing_library/testlib/analyse_command_log.py
+++ b/Tst/testing_library/testlib/analyse_command_log.py
@@ -181,6 +181,25 @@ def get_steps_and_commands(filename):
 
     return steps_start
 
+def get_general_run_info(filename, run_id=None):
+    """
+    Get all lines with general run information, those are logged if whole test is executed, returns all found lines, or
+    only 1 if run_id is specified
+    :param filename: path to the log file
+    :return: all found general step infomations
+    :rtype: list of dict
+    """
+    general_infos = []
+    with open(filename, 'r') as fileobject:
+        for line in fileobject:
+            if report.key_word_found(line, report.cmd_test_start_keyword):
+                general_run_info = report.parse_step_from_json_string(line, report.cmd_test_start_keyword)
+                if not run_id:
+                    general_infos.append(general_run_info)
+                elif general_run_info['run_id'] == run_id:
+                    general_infos.append(general_run_info)
+
+    return general_infos
 
 if __name__ == '__main__':
     example_log_file = '../logs_test_runs/simple_example_command.log'
diff --git a/Tst/testing_library/testlib/analyse_test_run.py b/Tst/testing_library/testlib/analyse_test_run.py
index 6234ef1..d44fb4e 100644
--- a/Tst/testing_library/testlib/analyse_test_run.py
+++ b/Tst/testing_library/testlib/analyse_test_run.py
@@ -10,12 +10,15 @@ from os import listdir
 from os.path import isfile, join
 import os, os.path
 import errno
+import logging
+
 
 import sys
 sys.path.append(confignator.get_option('paths', 'ccs'))
 import ccs_function_lib as cfl
 cfl.add_tst_import_paths()
 
+import toolbox
 from testlib import analyse_verification_log
 from testlib import analyse_command_log
 
@@ -25,18 +28,29 @@ cmd_log_file_end = '_command.log'
 vrc_log_file_end = '_verification.log'
 basic_log_file_path = confignator.get_option('tst-logging', 'test_run')
 basic_output_file_path = confignator.get_option('tst-logging', 'output-file-path')
+basic_json_file_path = confignator.get_option('tst-paths', 'tst_products')
 output_file_header = ['Item', 'Description', 'Verification', 'TestResult']
 
-def save_result_to_file(test_name, log_file_path=None, output_file_path=None, run_id=None):
+def save_result_to_file(test_name, log_file_path=None, output_file_path=None, json_file_path=None, run_id=None, logger=False):
     """
-    Analyses the command and verification log file and creates a csv output table
+    Analyses the command and verification log file and creates a txt output table
     :param str test_name: the name of the test and of its log files
     :param str log_file_path: Path to the log files, None if basic one should be used
     """
+    # Logger is only used, if function is called from a different file (Progres Viewer), therefore a logger and a file
+    # are already set up, if file is called standalone, messages are printed
+    if logger:
+        logger = logging.getLogger(__name__)
+        logger.setLevel(level=logging.DEBUG)
+        console_hdlr = toolbox.create_console_handler(hdlr_lvl=logging.DEBUG)
+        logger.addHandler(hdlr=console_hdlr)
+
     if not log_file_path:
         log_file_path = basic_log_file_path
     if not output_file_path:
         output_file_path = basic_output_file_path
+    if not json_file_path:
+        json_file_path = basic_json_file_path + test_name + '.json'
 
     cmd_log_file = log_file_path + test_name + cmd_log_file_end
     vrc_log_file = log_file_path + test_name + vrc_log_file_end
@@ -59,6 +73,16 @@ def save_result_to_file(test_name, log_file_path=None, output_file_path=None, ru
         cmd_steps = cmd_steps_filtered
         vrc_steps = vrc_steps_filtered
 
+    # Get the general run information, and the description
+    general_run_infos = analyse_command_log.get_general_run_info(cmd_log_file, run_id=run_id)
+
+    if run_id and len(general_run_infos) != 1:
+        if logger:
+            logger.error('Multiple Runs found with the same given Run ID')
+        else:
+            print('Multiple Runs found with the same given Run ID')
+        return
+
     name_start = '{}-TS-{}-TR-'.format(test_name, cmd_steps[0]['version'])
     file_versions = []
     try:
@@ -69,7 +93,10 @@ def save_result_to_file(test_name, log_file_path=None, output_file_path=None, ru
         file_versions.sort()
         file_count = file_versions[-1] + 1 if file_versions else 1
     except FileNotFoundError:
-        print('Used Folder: "{}" does not yet exist, is now created'.format(output_file_path))
+        if logger:
+            logger.info('Used Folder: "{}" does not yet exist, is now created'.format(output_file_path))
+        else:
+            print('Used Folder: "{}" does not yet exist, is now created'.format(output_file_path))
         file_count = 1
         os.makedirs(output_file_path)
 
@@ -81,22 +108,24 @@ def save_result_to_file(test_name, log_file_path=None, output_file_path=None, ru
         # write the header
         writer.writerow(output_file_header)
 
-        # write the general info line
-        description = analyse_command_log.get_test_description(cmd_log_file)
-        version = get_version(cmd_steps)
-        writer.writerow([test_name, 'Test Description', version, 'Test Rep. Version: ' + f'{file_count:03d}'])  # TODO: Multiple versions/descriptions what to do?
+        # write the general info line, if multiple descriptions/versions are found all are written to the output file
+        version = get_version(cmd_steps, logger)
+        description = get_description(general_run_infos, logger)
+        writer.writerow([test_name, description, 'Test Spec. Version: ' + version, 'Test Rep. Version: ' + f'{file_count:03d}'])
 
         # write date line
         date_format = '%Y-%m-%d'
-        exec_date = datetime.datetime.strftime(cmd_steps[0]['exec_date'], date_format)
-        time_now = datetime.datetime.strftime(datetime.datetime.now(), date_format)
-        writer.writerow(['Date', '', exec_date, time_now])  # TODO: Make sure which dates should be shown, ok to take time from first step?
+        exec_date = datetime.datetime.fromtimestamp(os.stat(json_file_path).st_mtime) if os.path.isfile() else '---'  # When was the last time the json file was changed?
+        time_now = datetime.datetime.strftime(datetime.datetime.now(), date_format)  # TODO: Check which time should be shown here
+        writer.writerow(['Date', '', exec_date, time_now])  # TODO: Make sure which dates should be shown, ok to take time from first step? Only checking left
 
         # write Precon line
         writer.writerow(['Precon.', 'This has still to be solved', '', ''])  # TODO: What should be shown of the Precon
 
-        # write comment line
-        writer.writerow(['Comment', 'This is NOT a comment, still working on it', '', ''])  # TODO: Where is the comment given?
+        # write the general comment line
+        general_comment = get_general_comment(general_run_infos, logger)
+        if general_comment:
+            writer.writerow(['Comment', general_comment, '', ''])
 
         # write step line
         for step in cmd_steps:
@@ -114,7 +143,25 @@ def save_result_to_file(test_name, log_file_path=None, output_file_path=None, ru
         # write Postcon line
         writer.writerow(['Postcon.', 'This has still to be solved', '', ''])  # TODO: What should be shown of the Postcon
 
-def get_version(steps):
+def get_description(general_run_infos, logger):
+    """
+    Get a string of the different description that could be found
+    :param list of dicts general_run_infos: all the general run information that were found
+    :return str description: A string that contains all found versions
+    """
+    for count, run_info in enumerate(general_run_infos):
+        if count == 0:
+            description = run_info['descr']
+        else:
+            description += ' / ' + run_info['descr']
+            if logger:
+                logger.warning('More than one Description was found in the command log File')
+            else:
+                print('More than one Description was found in the command log File')
+
+    return description
+
+def get_version(steps, logger):
     """
     Get a string of the different version that could be found
     :param list of dicts steps: all the steps from the log file
@@ -129,9 +176,30 @@ def get_version(steps):
             version_final = version
         else:
             version_final += ' / ' + version
-            print('More than one Version was found in the command log File')
+            if logger:
+                logger.warning('More than one Version was found in the command log File')
+            else:
+                print('More than one Version was found in the command log File')
     return version_final
 
+def get_general_comment(general_run_infos, logger):
+    """
+    Get a string of the different general comment that could be found
+    :param list of dicts general_run_infos: all the general run information that were found
+    :return str general_comment: A string that contains all found gerneral comments
+    """
+    for count, run_info in enumerate(general_run_infos):
+        if count == 0:
+            general_comment = run_info['comment']
+        else:
+            general_comment += ' / ' + run_info['comment']
+            if logger:
+                logger.warning('More than one General Comment was found in the command log File')
+            else:
+                print('More than one General Comment was found in the command log File')
+
+    return general_comment
+
 def show_basic_results(test_name, log_file_path=None):
     """
     Analyses the command and verification log file and prints a basic overview of the results
diff --git a/Tst/tst/data_model.py b/Tst/tst/data_model.py
index cfcf234..0ce76a5 100644
--- a/Tst/tst/data_model.py
+++ b/Tst/tst/data_model.py
@@ -111,9 +111,10 @@ class Step:
         self._secondary_counter = 0
         self._step_number = ''
         self._description = ''
-        self._comment = ''
         self._command_code = ''
+        self._command_comment = ''
         self._verification_code = ''
+        self._verification_comment = ''
         self._is_active = True
         self._verified_item = []
         self._start_sequence = None
@@ -141,9 +142,10 @@ class Step:
         new_step.primary_counter = copy.copy(self.primary_counter)
         new_step.secondary_counter = copy.copy(self.secondary_counter)
         new_step.description = copy.copy(self.description)
-        new_step.comment = copy.copy(self.comment)
         new_step.command_code = copy.copy(self.command_code)
+        new_step.command_comment = copy.copy(self.command_comment)
         new_step.verification_code = copy.copy(self.verification_code)
+        new_step.verification_comment = copy.copy(self.verification_comment)
         new_step.is_active = copy.copy(self.is_active)
         new_step.start_sequence = copy.copy(self.start_sequence)
         new_step.stop_sequence = copy.copy(self.stop_sequence)
@@ -204,15 +206,6 @@ class Step:
         assert isinstance(value, str)
         self._description = value
 
-    @property
-    def comment(self):
-        return self._comment
-
-    @comment.setter
-    def comment(self, value: str):
-        assert isinstance(value, str)
-        self._comment = value
-
     @property
     def command_code(self):
         return self._command_code
@@ -222,6 +215,15 @@ class Step:
         assert isinstance(value, str)
         self._command_code = value
 
+    @property
+    def command_comment(self):
+        return self._command_comment
+
+    @command_comment.setter
+    def command_comment(self, value: str):
+        assert isinstance(value, str)
+        self._command_comment = value
+
     @property
     def verification_code(self):
         return self._verification_code
@@ -231,6 +233,15 @@ class Step:
         assert isinstance(value, str)
         self._verification_code = value
 
+    @property
+    def verification_comment(self):
+        return self._verification_comment
+
+    @verification_comment.setter
+    def verification_comment(self, value: str):
+        assert isinstance(value, str)
+        self._verification_comment = value
+
     @property
     def is_active(self):
         return self._is_active
@@ -275,9 +286,10 @@ class Step:
             self.primary_counter = step['_primary_counter']
             self.secondary_counter = step['_secondary_counter']
             self.description = step['_description']
-            self.comment = step['_comment']
             self.command_code = step['_command_code']
+            self.command_comment = step['_command_comment']
             self.verification_code = step['_verification_code']
+            self.verification_comment = step['_verification_comment']
             self.is_active = step['_is_active']
         except KeyError as error:
             self.logger.error('KeyError: no {} could be found in the loaded data'.format(error))
diff --git a/Tst/tst/generator.py b/Tst/tst/generator.py
index 8a46c41..d120115 100644
--- a/Tst/tst/generator.py
+++ b/Tst/tst/generator.py
@@ -139,8 +139,8 @@ def make_command_script(model, model_spec):
                                    testSpecName=model_spec.name,
                                    testSpecDescription=model_spec.description,
                                    testSpecVersion=model_spec.version,
-                                   testPreCondition=model_spec.comment,
-                                   testPostCondition=model_spec.comment,
+                                   testPreCondition=model_spec.precon,
+                                   testPostCondition=model_spec.postcon,
                                    testComment=model_spec.comment)
         # add the header string
         content += '\n\n' + cls
@@ -181,7 +181,7 @@ def make_command_script(model, model_spec):
                 command_code_w_indents = 'pass'
             step = step_str.substitute(testStepNumber=step.step_number_test_format,
                                        testStepDescription=step.description,
-                                       testStepComment=step.comment,
+                                       testStepCommandComment=step.command_comment,
                                        testStepCommandCode=command_code_w_indents,
                                        testSpecFileName=create_file_name(model_spec.name),
                                        testSpecClassName=create_class_name(model_spec.name))
@@ -266,8 +266,7 @@ def make_command_run_script(model, model_spec):
             #                           testStepDescription=model.steps[step].description,
             #                           testStepComment=model.steps[step].comment)
             step = step_str.substitute(testStepNumber=step.step_number_test_format,
-                                       testStepDescription=step.description,
-                                       testStepComment=step.comment)
+                                       testStepDescription=step.description)
             # add the string for a steps
             content += '\n' + step
 
@@ -331,7 +330,7 @@ def make_verification_script(model, model_spec):
             #                           testStepVerificationCode=verification_code_w_indents)
             step = step_str.substitute(testStepNumber=step.step_number_test_format,
                                        testStepDescription=step.description,
-                                       testStepComment=step.comment,
+                                       testStepVerificationComment=step.verification_comment,
                                        testStepVerificationCode=verification_code_w_indents)
             # add the string for a steps
             content += '\n' + step
diff --git a/Tst/tst/generator_templates/co_step.py b/Tst/tst/generator_templates/co_step.py
index 87902bf..ba1a755 100644
--- a/Tst/tst/generator_templates/co_step.py
+++ b/Tst/tst/generator_templates/co_step.py
@@ -3,7 +3,7 @@
         param = {
             'step_no': '$testStepNumber',
             'descr': '$testStepDescription',
-            'comment': '$testStepComment'
+            'comment': '$testStepCommandComment'
         }
         step_start_cuc, summary, step_id = self.begin_steps(pool_name=pool_name, param=param)
 
diff --git a/Tst/tst/generator_templates/run_step.py b/Tst/tst/generator_templates/run_step.py
index 24e7565..c8da314 100644
--- a/Tst/tst/generator_templates/run_step.py
+++ b/Tst/tst/generator_templates/run_step.py
@@ -1,3 +1,3 @@
     #! CCS.BREAKPOINT
-    # Step $testStepNumber: $testStepDescription Comment: $testStepComment
+    # Step $testStepNumber: $testStepDescription
     threading.Thread(target=testinstance.step_$testStepNumber, kwargs={'pool_name': pool_name}, daemon=True).start()
diff --git a/Tst/tst/generator_templates/ver_step.py b/Tst/tst/generator_templates/ver_step.py
index 33b7364..b5a3370 100644
--- a/Tst/tst/generator_templates/ver_step.py
+++ b/Tst/tst/generator_templates/ver_step.py
@@ -4,7 +4,7 @@
         param = {
             'step_no': '$testStepNumber',
             'descr': '$testStepDescription',
-            'comment': '$testStepComment'
+            'comment': '$testStepVerificationComment'
         }
         self.vrc_step_begin(pool_name=pool_name, param=param, run_id=run_id, step_id=step_id)
 
diff --git a/Tst/tst/view.py b/Tst/tst/view.py
index 1f918f5..ae44695 100644
--- a/Tst/tst/view.py
+++ b/Tst/tst/view.py
@@ -153,11 +153,29 @@ class Board(Gtk.Box):
         self.test_meta_data_pre_post_con_edit.pack_start(self.precon_edit_button, False, True, 17)
         self.test_meta_data_pre_post_con_edit.pack_start(self.postcon_edit_button, False, True, 0)
 
+        self.test_comment_box = Gtk.Box()
+        self.test_comment_box.set_orientation(Gtk.Orientation.VERTICAL)
+        self.lbl_box_comment = Gtk.Box()
+        self.lbl_box_comment.set_orientation(Gtk.Orientation.HORIZONTAL)
+        self.label_comment = Gtk.Label.new()
+        self.label_comment.set_text(_('Comment'))
+        self.lbl_box_comment.pack_start(self.label_comment, False, False, 0)
+        # Make the area where the real command is entered
+        self.comment_scrolled_window = Gtk.ScrolledWindow()
+        #self.commands_comment_scrolled_window.set_size_request(200, 100)
+        self.test_meta_data_comment = Gtk.TextView.new()
+        self.comment_scrolled_window.add(self.test_meta_data_comment)
+
+        self.test_comment_box.pack_start(self.lbl_box_comment, True, True, 0)
+        self.test_comment_box.pack_start(self.comment_scrolled_window, True, True, 0)
+
+
         # add the meta data
         self.test_meta_data_box.pack_start(self.test_meta_data_labels, False, True, 0)
         self.test_meta_data_box.pack_start(self.test_meta_data_entries, False, True, 0)
         self.test_meta_data_box.pack_start(self.test_meta_data_pre_post_con, False, True, 0)
         self.test_meta_data_box.pack_start(self.test_meta_data_pre_post_con_edit, False, True, 0)
+        self.test_meta_data_box.pack_start(self.test_comment_box, True, True, 0)
         self.pack_start(self.test_meta_data_box, False, True, 0)
 
         # making the toolbar
@@ -170,14 +188,14 @@ class Board(Gtk.Box):
         self.btn_expand_all_steps = Gtk.ToolButton()
         self.btn_expand_all_steps.set_label(_('Expand all steps'))
         self.btn_expand_all_steps.connect('clicked', self.expand_all_steps)
-        self.btn_add_parallel = Gtk.ToolButton()
-        self.btn_add_parallel.set_label(_('Add parallel sequence'))
-        self.btn_add_parallel.connect('clicked', self.on_btn_clicked_add_parallel)
+        #self.btn_add_parallel = Gtk.ToolButton()
+        #self.btn_add_parallel.set_label(_('Add parallel sequence'))
+        #self.btn_add_parallel.connect('clicked', self.on_btn_clicked_add_parallel)
         self.toolbar = Gtk.Toolbar()
         self.toolbar.insert(self.btn_add_step, 0)
         self.toolbar.insert(self.btn_collapse_all_steps, 1)
         self.toolbar.insert(self.btn_expand_all_steps, 2)
-        self.toolbar.insert(self.btn_add_parallel, 3)
+        #self.toolbar.insert(self.btn_add_parallel, 3)
         self.pack_start(self.toolbar, False, True, 0)
 
         # add the grid for steps
@@ -197,6 +215,7 @@ class Board(Gtk.Box):
         self.test_meta_data_desc.connect('changed', self.on_test_desc_change)
         self.test_meta_data_version.connect('changed', self.on_test_version_change)
         self.text_meta_data_test_is_locked.connect('toggled', self.on_test_locked_toggled)
+        self.test_meta_data_comment.get_buffer().connect('changed', self.on_comment_change)
 
     @property
     def test_is_locked(self):
@@ -261,6 +280,9 @@ class Board(Gtk.Box):
                 self.app.add_info_bar(message_type=Gtk.MessageType.INFO, message=msg)
                 self.on_postcon_changed(self.precon_selection)
 
+        # Set the test comment
+        self.test_meta_data_comment.get_buffer().set_text(self.model.comment)
+
 
     def collapse_all_steps(self, button):
         """ Close all expander of the steps """
@@ -405,6 +427,18 @@ class Board(Gtk.Box):
         # update the data model viewer
         self.app.update_model_viewer()
 
+    def on_comment_change(self, widget):
+        """ if the name of test specification is changed update the model and the model viewer
+
+        :param: Gtk.Widget widget: widget
+        """
+        # get the name out of the widget
+        comment = widget.get_text(widget.get_start_iter(), widget.get_end_iter(), True)
+        # update the model
+        self.model.comment = comment
+        # update the data model viewer
+        self.app.update_model_viewer()
+
     def destroy_all_step_widgets(self):
         """
         Destroys all StepWidgets of the current grid
@@ -557,6 +591,7 @@ class StepWidget(Gtk.EventBox):
         self.detail_box = Gtk.Box()
         self.detail_box.set_orientation(Gtk.Orientation.VERTICAL)
         self.detail_box.connect('show', self.on_detail_box_show)
+        #self.detail_box.set_homogeneous(True)
         Gtk.StyleContext.add_class(self.detail_box.get_style_context(), 'step-detail-box')  # for CSS styling
 
         self.vbox.pack_start(self.detail_box, True, True, 0)
@@ -564,36 +599,49 @@ class StepWidget(Gtk.EventBox):
         self.set_hexpand(True)
 
         # field for the description
+        self.desc_box = Gtk.Box()
+        self.desc_box.set_orientation(Gtk.Orientation.VERTICAL)
         self.lbl_box_desc = Gtk.Box()
         self.lbl_box_desc.set_orientation(Gtk.Orientation.HORIZONTAL)
         self.desc_label = Gtk.Label.new()
         self.desc_label.set_text(_('Description'))
         self.lbl_box_desc.pack_start(self.desc_label, False, True, 0)
-        self.detail_box.pack_start(self.lbl_box_desc, True, True, 0)
+        #self.detail_box.pack_start(self.lbl_box_desc, True, True, 0)
         self.desc_scrolled_window = Gtk.ScrolledWindow()
         #self.desc_scrolled_window.set_size_request(50, 100)
-        self.detail_box.pack_start(self.desc_scrolled_window, False, True, 0)
+        #self.detail_box.pack_start(self.desc_scrolled_window, False, True, 0)
         self.desc_text_view = Gtk.TextView.new()
         self.desc_text_view.set_wrap_mode(Gtk.WrapMode.WORD)
         self.desc_text_view.set_accepts_tab(False)
         self.desc_scrolled_window.add(self.desc_text_view)
         self.desc_text_buffer = self.desc_text_view.get_buffer()
 
+        self.desc_box.pack_start(self.lbl_box_desc, True, True, 0)
+        self.desc_box.pack_start(self.desc_scrolled_window, True, True, 0)
+        self.detail_box.pack_start(self.desc_box, True, True, 0)
+
         # fields for commands and verification
         lm = GtkSource.LanguageManager()
 
         # area for the commands
+        self.whole_commands_box = Gtk.Grid()
+        self.whole_commands_box.set_column_homogeneous(True)
+        #self.whole_commands_box.set_orientation(Gtk.Orientation.HORIZONTAL)
+
+        # Left side of the commands area, where the commands a entered
+        # Make the label, inside a own Box to show it on the left side
         self.lbl_box_commands = Gtk.Box()
         self.lbl_box_commands.set_orientation(Gtk.Orientation.HORIZONTAL)
         self.commands_label = Gtk.Label.new()
         self.commands_label.set_text(_('Commands'))
-        self.btn_exec_commands = Gtk.Button.new_from_icon_name(icon_name='media-playback-start', size=Gtk.IconSize.BUTTON)
-        self.btn_exec_commands.connect('clicked', self.on_exec_commands)
         self.lbl_box_commands.pack_start(self.commands_label, False, False, 0)
+        # self.btn_exec_commands = Gtk.Button.new_from_icon_name(icon_name='media-playback-start', size=Gtk.IconSize.BUTTON)
+        # self.btn_exec_commands.connect('clicked', self.on_exec_commands)
         # self.lbl_box_commands.pack_start(self.btn_exec_commands, False, False, 0)
-        self.detail_box.pack_start(self.lbl_box_commands, True, True, 0)
+        # Make the area where the real command is entered
+        # self.detail_box.pack_start(self.lbl_box_commands, True, True, 0)
         self.commands_scrolled_window = Gtk.ScrolledWindow()
-        self.commands_scrolled_window.set_size_request(50, 100)
+        #self.commands_scrolled_window.set_size_request(50, 100)
         self.commands_view = GtkSource.View()
         self.commands_view.set_auto_indent(True)
         self.commands_view.set_show_line_numbers(False)
@@ -602,24 +650,53 @@ class StepWidget(Gtk.EventBox):
         self.commands_view.set_indent_on_tab(True)
         self.commands_view.set_insert_spaces_instead_of_tabs(True)
         self.commands_buffer = self.commands_view.get_buffer()
-
         self.commands_buffer.set_language(lngg)
         # self.commands_buffer.set_style_scheme(self.board.current_scheme)
         self.commands_scrolled_window.add(self.commands_view)
-        self.detail_box.pack_start(self.commands_scrolled_window, True, True, 0)
 
-        # field for the verification
+        # Right side of the commands area, the comment box
+        # Make the label, inside a own Box to show it on the left end
+        self.lbl_box_commands_comment = Gtk.Box()
+        self.lbl_box_commands_comment.set_orientation(Gtk.Orientation.HORIZONTAL)
+        self.commands_label_comment = Gtk.Label.new()
+        self.commands_label_comment.set_text(_('Comment'))
+        self.lbl_box_commands_comment.pack_start(self.commands_label_comment, False, False, 0)
+        # Make the area where the real command is entered
+        self.commands_comment_scrolled_window = Gtk.ScrolledWindow()
+        #self.commands_comment_scrolled_window.set_size_request(200, 100)
+        self.commands_comment_view = GtkSource.View()
+        self.commands_comment_view.set_show_line_numbers(False)
+        self.commands_comment_scrolled_window.add(self.commands_comment_view)
+        self.commands_comment_buffer = self.commands_comment_view.get_buffer()
+
+        #self.commands_comment_box.pack_start(self.lbl_box_commands_comment, True, True, 0)
+        #self.commands_comment_box.pack_start(self.commands_comment_scrolled_window, True, True, 0)
+
+        #ADD everything to the whole grid
+        self.whole_commands_box.set_column_spacing(10)
+        self.whole_commands_box.attach(self.lbl_box_commands, 0, 0, 3, 1)
+        self.whole_commands_box.attach(self.commands_scrolled_window, 0, 1, 3, 5)
+        self.whole_commands_box.attach_next_to(self.lbl_box_commands_comment, self.lbl_box_commands, Gtk.PositionType.RIGHT, 1, 1)
+        self.whole_commands_box.attach_next_to(self.commands_comment_scrolled_window, self.commands_scrolled_window, Gtk.PositionType.RIGHT, 1, 5)
+        self.detail_box.pack_start(self.whole_commands_box, True, True, 0)
+
+        # area for the verification
+        self.whole_verification_box = Gtk.Grid()
+        self.whole_verification_box.set_column_homogeneous(True)
+
+        # Left side of the verification area, where the verification-commands a entered
+        # Make the label, inside a own Box to show it on the left side
         self.lbl_box_verification = Gtk.Box()
         self.lbl_box_verification.set_orientation(Gtk.Orientation.HORIZONTAL)
         self.verification_label = Gtk.Label.new()
         self.verification_label.set_text(_('Verification'))
-        self.btn_exec_verification = Gtk.Button.new_from_icon_name(icon_name='media-playback-start', size=Gtk.IconSize.BUTTON)
-        self.btn_exec_verification.connect('clicked', self.on_exec_verification)
+        #self.btn_exec_verification = Gtk.Button.new_from_icon_name(icon_name='media-playback-start', size=Gtk.IconSize.BUTTON)
+        #self.btn_exec_verification.connect('clicked', self.on_exec_verification)
         self.lbl_box_verification.pack_start(self.verification_label, False, False, 0)
         # self.lbl_box_verification.pack_start(self.btn_exec_verification, False, False, 0)
-        self.detail_box.pack_start(self.lbl_box_verification, True, True, 0)
+        #self.detail_box.pack_start(self.lbl_box_verification, True, True, 0)
         self.verification_scrolled_window = Gtk.ScrolledWindow()
-        self.verification_scrolled_window.set_size_request(50, 100)
+        #self.verification_scrolled_window.set_size_request(50, 100)
         self.verification_view = GtkSource.View()
         self.verification_view.set_auto_indent(True)
         self.verification_view.set_show_line_numbers(False)
@@ -631,7 +708,29 @@ class StepWidget(Gtk.EventBox):
         self.verification_buffer.set_language(lngg)
         # self.verification_buffer.set_style_scheme(self.board.current_scheme)
         self.verification_scrolled_window.add(self.verification_view)
-        self.detail_box.pack_start(self.verification_scrolled_window, True, False, 0)
+
+        # Right side of the verification area, the comment box
+        # Make the label, inside a own Box to show it on the left end
+        self.lbl_box_verification_comment = Gtk.Box()
+        self.lbl_box_verification_comment.set_orientation(Gtk.Orientation.HORIZONTAL)
+        self.verification_label_comment = Gtk.Label.new()
+        self.verification_label_comment.set_text(_('Comment'))
+        self.lbl_box_verification_comment.pack_start(self.verification_label_comment, False, False, 0)
+        # Make the area where the real command is entered
+        self.verification_comment_scrolled_window = Gtk.ScrolledWindow()
+        #self.commands_comment_scrolled_window.set_size_request(200, 100)
+        self.verification_comment_view = GtkSource.View()
+        self.verification_comment_view.set_show_line_numbers(False)
+        self.verification_comment_scrolled_window.add(self.verification_comment_view)
+        self.verification_comment_buffer = self.verification_comment_view.get_buffer()
+
+        #ADD everything to the whole grid
+        self.whole_verification_box.set_column_spacing(10)
+        self.whole_verification_box.attach(self.lbl_box_verification, 0, 0, 3, 1)
+        self.whole_verification_box.attach(self.verification_scrolled_window, 0, 1, 3, 5)
+        self.whole_verification_box.attach_next_to(self.lbl_box_verification_comment, self.lbl_box_verification, Gtk.PositionType.RIGHT, 1, 1)
+        self.whole_verification_box.attach_next_to(self.verification_comment_scrolled_window, self.verification_scrolled_window, Gtk.PositionType.RIGHT, 1, 5)
+        self.detail_box.pack_start(self.whole_verification_box, True, True, 0)
 
         # fill the step with data before connecting the signals (!)
         self.set_data_in_widget()
@@ -665,7 +764,9 @@ class StepWidget(Gtk.EventBox):
         # connect the signals
         self.desc_text_buffer.connect('changed', self.on_description_buffer_changed)
         self.commands_buffer.connect('changed', self.on_commands_buffer_changed)
+        self.commands_comment_buffer.connect('changed', self.on_commands_comment_buffer_changed)
         self.verification_buffer.connect('changed', self.on_verification_buffer_changed)
+        self.verification_comment_buffer.connect('changed', self.on_verification_comment_buffer_changed)
 
         Gtk.StyleContext.add_class(self.get_style_context(), 'step-widget')
 
@@ -760,8 +861,10 @@ class StepWidget(Gtk.EventBox):
     def set_data_in_widget(self):
         self.set_is_active_in_widget()
         self.set_description_in_widget()
-        self.set_commands_in_widget()
+        self.set_commands_in_widget()#
+        self.set_commands_comment_in_widget()
         self.set_verification_in_widget()
+        self.set_verification_comment_in_widget()
         self.set_start_sequence_in_widget()
         self.set_stop_sequence_in_widget()
         return
@@ -792,6 +895,13 @@ class StepWidget(Gtk.EventBox):
         self.commands_buffer.set_text(commands)
         return
 
+    def set_commands_comment_in_widget(self):
+        """ gets the commands comment from the model and sets it in the commands comment buffer in order to display it """
+        stp_ndx = self.model.get_sequence(self.sequence).get_step_index(self.step_number)
+        commands_comment = self.model.get_sequence(self.sequence).steps[stp_ndx].command_comment
+        self.commands_comment_buffer.set_text(commands_comment)
+        return
+
     def set_verification_in_widget(self):
         """ gets the commands from the model and sets it in the commands buffer in order to display it """
         stp_ndx = self.model.get_sequence(self.sequence).get_step_index(self.step_number)
@@ -799,6 +909,13 @@ class StepWidget(Gtk.EventBox):
         self.verification_buffer.set_text(verification)
         return
 
+    def set_verification_comment_in_widget(self):
+        """ gets the commands comment from the model and sets it in the commands comment buffer in order to display it """
+        stp_ndx = self.model.get_sequence(self.sequence).get_step_index(self.step_number)
+        verification_comment = self.model.get_sequence(self.sequence).steps[stp_ndx].verification_comment
+        self.verification_comment_buffer.set_text(verification_comment)
+        return
+
     def set_start_sequence_in_widget(self):
         stp_ndx = self.model.get_sequence(self.sequence).get_step_index(self.step_number)
         step = self.model.get_sequence(self.sequence).steps[stp_ndx]
@@ -939,6 +1056,7 @@ class StepWidget(Gtk.EventBox):
         data_string = selection_data.get_text()
         data = dnd_data_parser.read_datastring(data_string, logger=self.logger)
         drag_source_type = data['data_type']
+        #print(drag_source_type)
         if drag_source_type == dnd_data_parser.data_type_snippet:  # data gets copied
             if y < widget_height * widget_grip_upper:  # upper quarter
                 # add a step above
@@ -999,6 +1117,15 @@ class StepWidget(Gtk.EventBox):
         # get the description out of the text buffer of the widget
         # description = self.get_description_from_widget()
         self.step_description = self.read_out_text_buffer(text_buffer)
+        # Setting the description string for a step in the data model
+        # find the correct step within the data model
+        stp_ndx = self.model.get_sequence(self.sequence).get_step_index(self.step_number)
+        step_in_data_model = self.model.get_sequence(self.sequence).steps[stp_ndx]
+        # use the setter of the data model
+        if isinstance(step_in_data_model, data_model.Step):
+            step_in_data_model.command_code = self.step_description
+        else:
+            self.logger('step with the step number {} could not be found'.format(self.step_number))
         # update the model
         # ToDo
         # update the data model viewer
@@ -1024,6 +1151,24 @@ class StepWidget(Gtk.EventBox):
         # update the data model viewer
         self.app.update_model_viewer()
 
+    def on_commands_comment_buffer_changed(self, text_buffer):
+        """
+        Signal 'changed' for the commands comment buffer
+        """
+        # get the text of the commands comment out of the buffer of the widget
+        commands_comment = self.read_out_text_buffer(text_buffer)
+        # Setting the commands string for a step in the data model
+        # find the correct step within the data model
+        stp_ndx = self.model.get_sequence(self.sequence).get_step_index(self.step_number)
+        step_in_data_model = self.model.get_sequence(self.sequence).steps[stp_ndx]
+        # use the setter of the data model
+        if isinstance(step_in_data_model, data_model.Step):
+            step_in_data_model.command_comment = commands_comment
+        else:
+            self.logger('step with the step number {} could not be found'.format(self.step_number))
+        # update the data model viewer
+        self.app.update_model_viewer()
+
     def on_verification_buffer_changed(self, text_buffer):
         """
         Signal 'changed' for the verification source buffer
@@ -1042,6 +1187,24 @@ class StepWidget(Gtk.EventBox):
         # update the data model viewer
         self.app.update_model_viewer()
 
+    def on_verification_comment_buffer_changed(self, text_buffer):
+        """
+        Signal 'changed' for the verification comment buffer
+        """
+        # get the code of the verification out of the buffer of the widget
+        verification_comment = self.read_out_text_buffer(text_buffer)
+        # Setting the verification string for a step in the data model
+        # find the correct step within the data model
+        stp_ndx = self.model.get_sequence(self.sequence).get_step_index(self.step_number)
+        step_in_data_model = self.model.get_sequence(self.sequence).steps[stp_ndx]
+        # use the setter of the data model
+        if isinstance(step_in_data_model, data_model.Step):
+            step_in_data_model.verification_comment = verification_comment
+        else:
+            self.logger('step with the step number {} could not be found'.format(self.step_number))
+        # update the data model viewer
+        self.app.update_model_viewer()
+
     def on_exec_commands(self, button):
         # get the code of the commands out of the buffer of the widget
         commands = str(self.get_commands_from_widget())
@@ -1109,6 +1272,7 @@ class InterStepWidget(Gtk.Box):
         self.app = app
         self.board = board
         self.logger = logger
+        self.sequence = seq_num
 
         # add the drawing area for the arrow
         self.drawingarea = Gtk.DrawingArea()
-- 
GitLab