Something went wrong on our end
-
Christopher Granabetter authoredChristopher Granabetter authored
view.py 88.54 KiB
import os
import logging
import gettext
import gi
import time
import db_interaction
gi.require_version('Gtk', '3.0')
gi.require_version('GtkSource', '3.0')
from gi.repository import Gtk, Gdk, GtkSource, GdkPixbuf
# -------------------------------------------
import data_model
import dnd_data_parser
import toolbox
import cairo
import sys
import confignator
ccs_path = confignator.get_option('paths', 'ccs')
sys.path.append(ccs_path)
import ccs_function_lib as cfl
lm = GtkSource.LanguageManager()
lngg = lm.get_language('python')
logger = logging.getLogger(__name__)
logger.setLevel(level=logging.WARNING)
console_hdlr = toolbox.create_console_handler()
logger.addHandler(hdlr=console_hdlr)
# using gettext for internationalization (i18n)
localedir = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'locale')
translate = gettext.translation('handroll', localedir, fallback=True)
_ = translate.gettext
style_path = os.path.join(os.path.dirname(__file__), 'style')
widget_grip_upper = 1 / 4
widget_grip_lower = 3 / 4
class Board(Gtk.Box):
"""
A sketch desk consists out of a toolbar and a grid where the StepWidgets are placed.
Features
* data model functions
* change of the number of a step triggers renumbering and reordering of all steps
* drag and drop
* reorder the steps
* drag the 'Add step' button and insert a new step
* drop a step before or after a existing step. Highlight the associated border
* select multiple steps and move them as a block
* adding a parallel thread
* place the start before, within or after an existing step
* place the end before, within or after an existing step
* loop over steps
* select multiple steps add loop over them till a break condition is reached (ToDo)
"""
def __init__(self, model, app, filename=None, logger=logger):
"""
When an instance is initialized:
* a data model instance is created
* the toolbar is created
* a instance of a grid is added
* drag and drop is set up
"""
# assert isinstance(model, data_model.TestSpecification)
self.model = model
self.app = app
self._filename = filename
self.logger = logger
self._test_is_locked = None
# Save Button in TST clicked for first time, Always do save_as to not overwrite something, used in tst.py
self._ask_overwrite = True
# Gtk.Box.__init__(self)
super(Board, self).__init__()
self.set_orientation(Gtk.Orientation.VERTICAL)
# test meta data
self.test_meta_data_box = Gtk.Box(margin=5)
self.test_meta_data_box.set_orientation(Gtk.Orientation.HORIZONTAL)
self.test_meta_data_info = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.test_meta_data_pre_post_con = Gtk.Box(margin_start=10)
self.test_meta_data_pre_post_con.set_orientation(Gtk.Orientation.VERTICAL)
self.test_meta_data_pre_post_con_edit = Gtk.Box()
self.test_meta_data_pre_post_con_edit.set_orientation(Gtk.Orientation.VERTICAL)
# name of the test
self.test_meta_data_name_label = Gtk.Label()
self.test_meta_data_name_label.set_text('Name of the test:')
self.test_meta_data_name = Gtk.Entry(width_chars=25)
self.test_meta_data_name.set_placeholder_text('< name of the test >')
self.test_meta_data_name_box = Gtk.Box(spacing=5, orientation=Gtk.Orientation.HORIZONTAL)
self.test_meta_data_name_box.pack_start(self.test_meta_data_name_label, False, False, 4)
self.test_meta_data_name_box.pack_end(self.test_meta_data_name, False, False, 0)
self.test_meta_data_info.pack_start(self.test_meta_data_name_box, True, True, 0)
# test description
self.test_meta_data_desc_label = Gtk.Label()
self.test_meta_data_desc_label.set_text('Short description:')
self.test_meta_data_desc = Gtk.Entry(width_chars=25)
self.test_meta_data_desc.set_placeholder_text('< description of the test >')
self.test_meta_data_desc_box = Gtk.Box(spacing=5, orientation=Gtk.Orientation.HORIZONTAL)
self.test_meta_data_desc_box.pack_start(self.test_meta_data_desc_label, False, False, 4)
self.test_meta_data_desc_box.pack_end(self.test_meta_data_desc, False, False, 0)
self.test_meta_data_info.pack_start(self.test_meta_data_desc_box, True, True, 0)
# spec_version
self.test_meta_data_spec_version_label = Gtk.Label()
self.test_meta_data_spec_version_label.set_text('Spec. version:')
self.test_meta_data_spec_version = Gtk.Entry(width_chars=25)
self.test_meta_data_spec_version.set_placeholder_text('< spec version >')
self.test_meta_data_spec_box = Gtk.Box(spacing=5, orientation=Gtk.Orientation.HORIZONTAL)
self.test_meta_data_spec_box.pack_start(self.test_meta_data_spec_version_label, False, False, 4)
self.test_meta_data_spec_box.pack_end(self.test_meta_data_spec_version, False, False, 0)
self.test_meta_data_info.pack_start(self.test_meta_data_spec_box, True, True, 0)
# IASW Software Version
self.test_meta_data_iasw_version_label = Gtk.Label()
self.test_meta_data_iasw_version_label.set_text('IASW version:')
self.test_meta_data_iasw_version = Gtk.Entry(width_chars=25)
self.test_meta_data_iasw_version.set_placeholder_text('< IASW version >')
self.test_meta_data_iasw_box = Gtk.Box(spacing=5, orientation=Gtk.Orientation.HORIZONTAL)
self.test_meta_data_iasw_box.pack_start(self.test_meta_data_iasw_version_label, False, False, 4)
self.test_meta_data_iasw_box.pack_end(self.test_meta_data_iasw_version, False, False, 0)
self.test_meta_data_info.pack_start(self.test_meta_data_iasw_box, True, True, 0)
# IASW Software Version
self.test_meta_data_req_label = Gtk.Label()
self.test_meta_data_req_label.set_text('Requirements:')
self.test_meta_data_req = Gtk.Entry(width_chars=25)
self.test_meta_data_req.set_placeholder_text('< Requirements >')
self.test_meta_data_req_box = Gtk.Box(spacing=5, orientation=Gtk.Orientation.HORIZONTAL)
self.test_meta_data_req_box.pack_start(self.test_meta_data_req_label, False, False, 4)
self.test_meta_data_req_box.pack_end(self.test_meta_data_req, False, False, 0)
self.test_meta_data_info.pack_start(self.test_meta_data_req_box, True, True, 0)
# checkbox for locking the step numbers
self.test_is_locked_label = Gtk.Label()
self.test_is_locked_label.set_text(_('Lock step enumeration:'))
self.text_meta_data_test_is_locked = Gtk.CheckButton()
self.test_meta_data_is_locked_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
self.test_meta_data_is_locked_box.pack_start(self.test_is_locked_label, False, False, 4)
self.test_meta_data_is_locked_box.pack_start(self.text_meta_data_test_is_locked, True, True, 4)
self.test_meta_data_info.pack_start(self.test_meta_data_is_locked_box, True, True, 15)
# Add pre post condition selections
# Pre conditions
self.precon_selection_label = Gtk.Label()
self.precon_selection_label.set_text('Pre-conditions:')
self.precon_selection = Gtk.ComboBoxText()
self.set_precon_model()
self.precon_selection.connect("changed", self.on_precon_changed)
# Post conditions
self.postcon_selection_label = Gtk.Label()
self.postcon_selection_label.set_text('Post-conditions:')
self.postcon_selection = Gtk.ComboBoxText()
self.set_postcon_model()
self.postcon_selection.connect("changed", self.on_postcon_changed)
# Add Edit Buttons
self.precon_edit_button = Gtk.Button.new_with_label('Edit')
self.precon_edit_button.connect("clicked", self.precon_edit_clicked)
self.postcon_edit_button = Gtk.Button.new_with_label('Edit')
self.postcon_edit_button.connect("clicked", self.postcon_edit_clicked)
precon_line = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
precon_line.pack_start(self.precon_selection, False, True, 0)
precon_line.pack_start(self.precon_edit_button, False, True, 0)
postcon_line = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
postcon_line.pack_start(self.postcon_selection, False, True, 0)
postcon_line.pack_start(self.postcon_edit_button, False, True, 0)
# add to pre post box
self.test_meta_data_pre_post_con.pack_start(self.precon_selection_label, False, True, 0)
self.test_meta_data_pre_post_con.pack_start(precon_line, False, True, 2)
self.test_meta_data_pre_post_con.pack_start(self.postcon_selection_label, False, True, 2)
self.test_meta_data_pre_post_con.pack_start(postcon_line, False, True, 0)
self.test_meta_data_box.set_spacing(10)
self.test_comment_box = Gtk.Box(spacing=2, margin_end=5)
self.test_comment_box.set_orientation(Gtk.Orientation.VERTICAL)
self.label_comment = Gtk.Label()
self.label_comment.set_halign(Gtk.Align.START)
self.label_comment.set_text(_('Test comment:'))
# Make the area where the real command is entered
self.comment_scrolled_window = Gtk.ScrolledWindow()
self.comment_scrolled_window.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
# self.comment_scrolled_window.set_size_request(200, 100)
self.test_meta_data_comment = Gtk.TextView.new()
self.test_meta_data_comment.set_wrap_mode(Gtk.WrapMode.WORD)
Gtk.StyleContext.add_class(self.test_meta_data_comment.get_style_context(), 'text-view')
self.comment_scrolled_window.add(self.test_meta_data_comment)
self.test_comment_box.pack_start(self.label_comment, False, False, 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_info, 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)
# add a custom init code block
self.custom_import_box = Gtk.Box(spacing=5, margin_start=10, margin_end=10)
self.custom_import_box.set_orientation(Gtk.Orientation.VERTICAL)
self.bar_custom_import = Gtk.Box()
self.bar_custom_import.set_orientation(Gtk.Orientation.HORIZONTAL)
self.bar_custom_import.set_tooltip_text('Statements that are executed at the beginning of a test.\n'
'Define imports and variables used throughout the test here.')
self.label_custom_import = Gtk.Label()
self.label_custom_import.set_halign(Gtk.Align.START)
self.label_custom_import.set_markup('<b>Init code</b>')
self.button_custom_import = Gtk.ToolButton()
self.button_custom_import.set_icon_name('pan-down-symbolic')
self.button_custom_import.connect('clicked', self.on_init_code_toggle)
self.bar_custom_import.pack_start(self.button_custom_import, False, True, 0)
self.bar_custom_import.pack_start(self.label_custom_import, False, True, 0)
self.custom_import_scrolled_window = Gtk.ScrolledWindow()
self.custom_import_scrolled_window.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
self.custom_import_scrolled_window.set_size_request(-1, 200)
self.test_custom_import = GtkSource.View()
self.test_custom_import.set_auto_indent(True)
self.test_custom_import.set_wrap_mode(Gtk.WrapMode.WORD)
self.test_custom_import.set_show_line_numbers(True)
self.test_custom_import.set_monospace(True)
self.test_custom_import.set_highlight_current_line(True)
self.test_custom_import.set_indent_on_tab(True)
self.test_custom_import.set_insert_spaces_instead_of_tabs(True)
self.test_custom_import.set_indent_width(4)
self.test_custom_import.set_auto_indent(True)
self.custom_import_buffer = self.test_custom_import.get_buffer()
self.custom_import_buffer.set_language(lngg)
# self.custom_import_buffer.set_style_scheme(self.board.current_scheme)
self.custom_import_scrolled_window.add(self.test_custom_import)
self.custom_import_box.pack_start(self.bar_custom_import, False, False, 0)
self.custom_import_box.pack_start(self.custom_import_scrolled_window, True, True, 0)
self.pack_start(self.custom_import_box, False, True, 0)
# making the toolbar
self.btn_add_step = Gtk.ToolButton()
self.btn_add_step.set_label(_('Add step'))
self.btn_add_step.set_tooltip_text(_('Add step'))
self.btn_add_step.set_icon_name('list-add')
self.btn_add_step.connect('clicked', self.on_btn_clicked_add_step)
self.btn_collapse_all_steps = Gtk.ToolButton()
self.btn_collapse_all_steps.set_label(_('Collapse all steps'))
self.btn_collapse_all_steps.set_tooltip_text(_('Collapse all steps'))
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(ccs_path + '/pixmap/collapse.svg', 24, 24)
icon = Gtk.Image.new_from_pixbuf(pixbuf)
self.btn_collapse_all_steps.set_icon_widget(icon)
self.btn_collapse_all_steps.connect('clicked', self.collapse_all_steps)
self.btn_expand_all_steps = Gtk.ToolButton()
self.btn_expand_all_steps.set_label(_('Expand all steps'))
self.btn_expand_all_steps.set_tooltip_text(_('Expand all steps'))
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(ccs_path + '/pixmap/expand.svg', 24, 24)
icon = Gtk.Image.new_from_pixbuf(pixbuf)
self.btn_expand_all_steps.set_icon_widget(icon)
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.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.pack_start(self.toolbar, False, True, 0)
# add the grid for steps
self.scrolled_window = Gtk.ScrolledWindow()
self.grid = Gtk.Grid()
# self.grid.set_row_spacing(20)
self.scrolled_window.add(self.grid)
self.pack_start(self.scrolled_window, True, True, 0)
# scheme for the GtkSource Views
self.style_manager = GtkSource.StyleSchemeManager.get_default()
self.style_manager.append_search_path(style_path)
self.current_scheme = self.style_manager.get_scheme('darcula')
# connect signals
self.test_meta_data_name.connect('changed', self.on_test_name_change)
self.test_meta_data_desc.connect('changed', self.on_test_desc_change)
self.test_meta_data_spec_version.connect('changed', self.on_test_spec_version_change)
self.test_meta_data_iasw_version.connect('changed', self.on_test_iasw_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)
self.custom_import_buffer.connect('changed', self.on_custom_import_change)
Gtk.StyleContext.add_class(self.get_style_context(), 'board')
@property
def test_is_locked(self):
return self._test_is_locked
@test_is_locked.setter
def test_is_locked(self, value):
assert isinstance(value, bool)
self._test_is_locked = value
@property
def filename(self):
return self._filename
@filename.setter
def filename(self, value):
self._filename = value
@property
def ask_overwrite(self):
return self._ask_overwrite
@ask_overwrite.setter
def ask_overwrite(self, value):
self._ask_overwrite = value
def update_widget_data(self):
"""
Updates the grid with the steps. All widgets of the grid are destroyed. The grid is build new from the model.
"""
# update the meta data of the test spec
self.set_test_spec_metadata()
# update the steps grid
self.destroy_all_step_widgets()
self.build_all_steps()
# refresh all widgets
self.show_all()
def set_test_spec_metadata(self):
""" Update the displayed data of the test specification using the data from the model """
# set the name of the test specification using the data from the model
self.test_meta_data_name.set_text(self.model.name)
# set the description of the test specification using the data from the model
self.test_meta_data_desc.set_text(self.model.description)
# set the Specification version of the test specification from the data model
self.test_meta_data_spec_version.set_text(self.model.spec_version)
# set the Software version of the test specification from the data model
self.test_meta_data_iasw_version.set_text(self.model.iasw_version)
# set the pre-condition name
if self.model.precon_name:
found = False
for index, precon_name in enumerate(self.precon_selection.get_model()):
if precon_name[0] == self.model.precon_name:
found = True
self.precon_selection.set_active(index)
if not found:
msg = 'Given Pre-Condition Name could not be found/loaded'
self.logger.warning(msg)
# self.app.add_info_bar(message_type=Gtk.MessageType.INFO, message=msg)
self.on_precon_changed(self.precon_selection)
# set the post-condition name
if self.model.postcon_name:
found = False
for index, postcon_name in enumerate(self.postcon_selection.get_model()):
if postcon_name[0] == self.model.postcon_name:
found = True
self.postcon_selection.set_active(index)
if not found:
msg = 'Given Post-Condition Name could not be found/loaded'
self.logger.warning(msg)
# 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)
# Set the Locked STep numeration
self.text_meta_data_test_is_locked.set_active(self.model.primary_counter_locked)
# Set the init code block
self.custom_import_buffer.set_text(self.model.custom_imports)
def on_init_code_toggle(self, widget):
if self.custom_import_scrolled_window.is_visible():
self.custom_import_scrolled_window.set_visible(False)
widget.set_icon_name('pan-end-symbolic')
else:
self.custom_import_scrolled_window.set_visible(True)
widget.set_icon_name('pan-down-symbolic')
def collapse_all_steps(self, button):
""" Close all expander of the steps """
steps = self.grid.get_children()
for child in steps:
child.step_detail_visible = False
def expand_all_steps(self, button):
""" Expand all step widgets """
steps = self.grid.get_children()
for child in steps:
child.step_detail_visible = True
def build_step(self, step_number):
""" Create a new step widget and add it to the grid
:param: step_number: number of a step
"""
step_to_add = StepWidget(model=self.model, step_number=step_number, app=self.app, board=self, logger=self.logger) # TODO: seq_num parameter??
# find the next free grid cell
number_of_existing_steps = len(self.view.grid.get_children())
row = number_of_existing_steps - 1
self.grid.attach(step_to_add, 0, row, 1, 1)
def on_btn_clicked_add_step(self, button):
""" add a step to the model, then add a StepWidget to the steps grid and update the model viewer
:param: button: button widget which was clicked
"""
# ToDo
# self.model.get_sequence(self.sequence)add_step_below()
self.model.get_sequence(0).add_step_below()
# ToDo
self.update_widget_data()
self.app.update_model_viewer()
def on_btn_clicked_add_parallel(self, button):
""" Add the first step of a new sequence. Add the step to start the sequence.
:param: button: Gtk.Button widget which was clicked
"""
# create the new sequence in the data model
new_seq_num = self.model.add_sequence()
# create the step to start the sequence (only the 1st sequence can start further ones)
new_step = data_model.create_start_sequence_step(new_seq_num)
self.model.get_sequence(0).add_step_below(step_instance=new_step)
# create first step of the new sequence
self.model.get_sequence(new_seq_num).add_step_below()
# update the view
self.update_widget_data()
self.app.update_model_viewer()
def set_precon_model(self, active_name=None):
section_dict = db_interaction.get_pre_post_con(None)
active_nbr = 0
for count, condition in enumerate(section_dict):
self.precon_selection.append_text(condition.name)
if active_name == condition.name:
active_nbr = count
self.precon_selection.set_active(active_nbr)
self.on_precon_changed(self.precon_selection)
return
def on_precon_changed(self, widget):
# get the name out of the widget
precon_name = widget.get_active_text()
# update the model
self.model.precon_name = precon_name
# Set the Precon Description
section_dict = db_interaction.get_pre_post_con(None)
for condition in section_dict:
if condition.name == precon_name:
self.model.precon_descr = condition.description
self.model.precon_code = condition.condition
# update the data model viewer
self.app.update_model_viewer()
def set_postcon_model(self, active_name=None):
section_dict = db_interaction.get_pre_post_con(None)
active_nbr = 0
for count, condition in enumerate(section_dict):
self.postcon_selection.append_text(condition.name)
if active_name == condition.name:
active_nbr = count
self.postcon_selection.set_active(active_nbr)
self.on_postcon_changed(self.postcon_selection)
return
def on_postcon_changed(self, widget):
# get the name out of the widget
postcon_name = widget.get_active_text()
# update the model
self.model.postcon_name = postcon_name
# Set the Postcon Description
section_dict = db_interaction.get_pre_post_con(None)
for condition in section_dict:
if condition.name == postcon_name:
self.model.postcon_descr = condition.description
self.model.postcon_code = condition.condition
# update the data model viewer
self.app.update_model_viewer()
def precon_edit_clicked(self, widget):
dialog = Edit_Pre_Post_Con_Dialog(self, 'pre', self.precon_selection.get_active())
response = dialog.run()
if response == Gtk.ResponseType.OK:
self.precon_selection.remove_all()
self.set_precon_model(dialog.selection.get_active_text())
dialog.destroy()
elif response == Gtk.ResponseType.CANCEL:
dialog.destroy()
def postcon_edit_clicked(self, widget):
dialog = Edit_Pre_Post_Con_Dialog(self, 'post', self.postcon_selection.get_active())
response = dialog.run()
if response == Gtk.ResponseType.OK:
self.postcon_selection.remove_all()
self.set_postcon_model(dialog.selection.get_active_text())
dialog.destroy()
elif response == Gtk.ResponseType.CANCEL:
dialog.destroy()
def on_test_name_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
name = widget.get_text()
# update the model
self.model.name = name
# update the data model viewer
self.app.update_model_viewer()
def on_test_desc_change(self, widget):
# get the text out of the buffer
content = widget.get_text()
# set the test description in the model
self.model.description = content
# update the data model viewer
self.app.update_model_viewer()
def on_test_spec_version_change(self, widget):
# get the Specification Version out of the text buffer of the widget
spec_version = widget.get_text()
# update the model
self.model.spec_version = spec_version
# update the data model viewer
self.app.update_model_viewer()
def on_test_iasw_version_change(self, widget):
# get the IASW Version out of the text buffer of the widget
iasw_version = widget.get_text()
# update the model
self.model.iasw_version = iasw_version
# update the data model viewer
self.app.update_model_viewer()
def on_test_locked_toggled(self, *args):
# toggle the value in the widget
self.test_is_locked = not self.test_is_locked
# write it back to the data model
self.model.primary_counter_locked = self.test_is_locked
# 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 on_custom_import_change(self, widget):
"""
update model if buffer changes
:param widget:
:return:
"""
custom_code = widget.get_text(widget.get_start_iter(), widget.get_end_iter(), True)
self.model.custom_imports = custom_code
self.app.update_model_viewer()
def destroy_all_step_widgets(self):
"""
Destroys all StepWidgets of the current grid
"""
steps = self.grid.get_children()
for child in steps:
child.destroy()
def build_all_steps(self):
"""
Creates for every step in the instance of TestSequence a StepWidget-Widget and adds it to the grid.
"""
def get_top_attach_seq_start(grid, seq_num):
y = None
for child in grid.get_children():
if isinstance(child, StepWidget):
if hasattr(child, 'start_sequence'):
if child.start_sequence == seq_num:
y = grid.child_get_property(child, 'top-attach')
return y
def count_seq_children(grid, seq_num):
count = 0
for child in grid.get_children():
x = grid.child_get_property(child, 'left-attach')
if x == seq_num:
count += 1
return count
for seq in self.model.sequences:
assert isinstance(seq, data_model.TestSequence)
seq_num = seq.sequence
for step in seq.steps:
number = step.step_number
step_to_add = StepWidget(model=self.model, seq_num=seq_num, step_number=number, app=self.app, board=self, logger=self.logger)
inter_step = InterStepWidget(model=self.model, seq_num=seq_num, app=self.app, board=self, logger=self.logger)
# the top-attach value is calculated from:
# position where the sequence starts + already placed steps of this sequence
nchilds = count_seq_children(grid=self.grid, seq_num=seq_num)
if seq_num == 0:
# the first step starts at the top-attach position 0, because there is no start sequence step
top_attach = nchilds
else:
# get the top-attach value of the start sequence step which starts this sequence
top_attach_start_seq = get_top_attach_seq_start(grid=self.grid, seq_num=seq_num)
top_attach = top_attach_start_seq + nchilds
self.grid.attach(step_to_add, seq_num, top_attach, 1, 1)
self.grid.attach(inter_step, seq_num, top_attach+1, 1, 1)
def get_grid_columns(grid):
cols = 0
for child in grid.get_children():
x = grid.child_get_property(child, 'left-attach')
width = grid.child_get_property(child, 'width')
cols = max(cols, x + width)
return cols
n_col = get_grid_columns(self.grid)
return
def get_step_widget(self, seq_num, step_number):
step_widget = None
for child in self.grid.get_children():
if isinstance(child, StepWidget):
if child.sequence == seq_num:
primary, secondary = data_model.parse_step_number(step_number)
step_num = data_model.create_step_number(primary, secondary)
if child.step_number == step_num:
step_widget = child
return step_widget
class StepWidget(Gtk.EventBox):
""" StepWidget is a composite widget to represent one step of a test specification. """
def __init__(self, model, step_number, seq_num, app, board, logger):
super().__init__()
assert isinstance(model, data_model.TestSpecification)
self.model = model
self.sequence = seq_num
self.app = app
self.board = board
self.logger = logger
self._step_number = None
self._step_description = None
self._short_description = None
# self._command_code = None
# self._verification_code = None
self._step_detail_visible = None
self._start_sequence = None
self._stop_sequence = None
self.frame = Gtk.Frame()
self.add(self.frame)
self.vbox = Gtk.Box()
self.vbox.set_orientation(Gtk.Orientation.VERTICAL)
self.frame.add(self.vbox)
# toolbar
self.tbox = Gtk.Box()
self.tbox.set_orientation(Gtk.Orientation.HORIZONTAL)
self.btn_toggle_detail = Gtk.ToolButton()
self.btn_toggle_detail.set_tooltip_text(_('Show step details'))
self.btn_toggle_detail.connect('clicked', self.on_toggle_detail)
self.label_event_box = Gtk.EventBox()
self.label_event_box.set_visible_window(False)
self.label_event_box.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
self.label_event_box.connect('button-release-event', self.on_toggle_detail)
self.label_step_number = Gtk.Label()
self.label_event_box.add(self.label_step_number)
self.step_number = step_number
self.is_active = Gtk.CheckButton()
self.is_active.set_active(True)
self.is_active.set_tooltip_text(_('Set if the step is active'))
self.is_active.connect('clicked', self.on_toggled_is_active)
self.btn_execute_step = Gtk.ToolButton()
self.btn_execute_step.set_icon_name('media-playback-start-symbolic')
self.btn_execute_step.set_tooltip_text(_('Execute step'))
self.btn_execute_step.connect('clicked', self.on_execute_step)
self.text_label_event_box = Gtk.EventBox()
self.text_label_event_box.set_visible_window(False)
self.text_label_event_box.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
self.text_label_event_box.connect('button-release-event', self.on_toggle_detail)
self.text_label = Gtk.Label()
self.text_label.set_alignment(0, 0.5)
self.text_label_event_box.add(self.text_label)
self.btn_delete_step = Gtk.ToolButton()
self.btn_delete_step.set_icon_name('edit-delete-symbolic')
self.btn_delete_step.set_tooltip_text(_('Delete this step'))
self.btn_delete_step.connect('clicked', self.on_delete_step)
self.tbox.pack_start(self.btn_toggle_detail, False, False, 0)
self.tbox.pack_start(self.label_event_box, False, False, 0)
self.tbox.pack_start(self.text_label_event_box, True, True, 0)
self.tbox.pack_end(self.btn_delete_step, False, False, 0)
self.tbox.pack_end(self.is_active, False, False, 0)
self.tbox.pack_end(self.btn_execute_step, False, False, 0)
self.vbox.pack_start(self.tbox, True, True, 0)
# detail area
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)
self.set_hexpand(True)
# area for the commands
self.whole_description_box = Gtk.Grid()
self.whole_description_box.set_column_homogeneous(True)
# self.whole_commands_box.set_orientation(Gtk.Orientation.HORIZONTAL)
# field for the description
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.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.desc_text_view = Gtk.TextView.new()
Gtk.StyleContext.add_class(self.desc_text_view.get_style_context(), 'text-view')
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()
# Step Comment Area
# Make the label, inside a own Box to show it on the left end
self.lbl_box_step_comment = Gtk.Box()
self.lbl_box_step_comment.set_orientation(Gtk.Orientation.HORIZONTAL)
self.step_label_comment = Gtk.Label.new()
self.step_label_comment.set_text(_('Step Comment'))
self.lbl_box_step_comment.pack_start(self.step_label_comment, False, False, 0)
# Make the area where the real command is entered
self.step_comment_scrolled_window = Gtk.ScrolledWindow()
# self.step_comment_scrolled_window.set_size_request(200, 100)
self.step_comment_view = GtkSource.View()
Gtk.StyleContext.add_class(self.step_comment_view.get_style_context(), 'text-view')
self.step_comment_view.set_wrap_mode(Gtk.WrapMode.WORD)
self.step_comment_view.set_show_line_numbers(False)
self.step_comment_scrolled_window.add(self.step_comment_view)
self.step_comment_buffer = self.step_comment_view.get_buffer()
# ADD everything to the whole grid
self.whole_description_box.set_column_spacing(10)
self.whole_description_box.attach(self.lbl_box_desc, 0, 0, 3, 1)
self.whole_description_box.attach(self.desc_scrolled_window, 0, 1, 3, 5)
self.whole_description_box.attach_next_to(self.lbl_box_step_comment, self.lbl_box_desc, Gtk.PositionType.RIGHT, 3, 1)
self.whole_description_box.attach_next_to(self.step_comment_scrolled_window, self.desc_scrolled_window, Gtk.PositionType.RIGHT, 3, 5)
self.detail_box.pack_start(self.whole_description_box, True, True, 0)
# fields for commands and verification
# lm = GtkSource.LanguageManager()
# Area for the commands
self.whole_commands_box = Gtk.Box()
self.whole_commands_box.set_orientation(Gtk.Orientation.VERTICAL)
# 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.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)
# 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(-1, 200)
self.commands_view = GtkSource.View()
self.commands_view.set_auto_indent(True)
self.commands_view.set_wrap_mode(Gtk.WrapMode.WORD)
self.commands_view.set_show_line_numbers(True)
# self.commands_view.set_show_right_margin(True)
self.commands_view.set_monospace(True)
self.commands_view.set_highlight_current_line(True)
self.commands_view.set_indent_on_tab(True)
self.commands_view.set_insert_spaces_instead_of_tabs(True)
self.commands_view.set_indent_width(4)
self.commands_view.set_auto_indent(True)
self.commands_buffer = self.commands_view.get_buffer()
# draganddrop here
"""
self.commands_view.drag_dest_set(Gtk.DestDefaults.ALL, [], Gdk.DragAction.COPY)
self.commands_view.drag_dest_set_target_list(None)
self.commands_view.drag_dest_add_text_targets()
self.commands_view.connect("drag-motion", self.on_drag_motion_2)
self.commands_view.connect("drag-leave", self.on_drag_leave)
"""
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.whole_commands_box.pack_start(self.lbl_box_commands, False, False, 0)
self.whole_commands_box.pack_start(self.commands_scrolled_window, True, True, 0)
self.detail_box.pack_start(self.whole_commands_box, True, True, 0)
# Area for TM/TC
self.whole_tmtc_box = Gtk.Box()
self.whole_tmtc_box.set_orientation(Gtk.Orientation.VERTICAL)
# box for TM/TC
self.tmtc_box = Gtk.Box()
self.tmtc_box.set_orientation(Gtk.Orientation.HORIZONTAL)
self.tmtc_label = Gtk.Label.new()
self.tmtc_label.set_text(_('TM/TC'))
self.tmtc_box.pack_start(self.tmtc_label, False, False, 0)
self.tmtc_scrolled_window = Gtk.ScrolledWindow()
self.tmtc_scrolled_window.set_size_request(-1, 10)
self.tmtc_view = GtkSource.View()
self.tmtc_view.set_auto_indent(True)
self.tmtc_view.set_wrap_mode(Gtk.WrapMode.WORD)
self.tmtc_view.set_show_line_numbers(True)
# self.tmtc_view.set_show_right_margin(True)
self.tmtc_view.set_monospace(True)
self.tmtc_view.set_highlight_current_line(True)
self.tmtc_view.set_indent_on_tab(True)
self.tmtc_view.set_insert_spaces_instead_of_tabs(True)
self.tmtc_view.set_indent_width(4)
self.tmtc_view.set_auto_indent(True)
self.tmtc_buffer = self.tmtc_view.get_buffer()
# draganddrop here
"""
self.tmtc_view.drag_dest_set(Gtk.DestDefaults.ALL, [], Gdk.DragAction.COPY)
self.tmtc_view.drag_dest_set_target_list(None)
self.tmtc_view.drag_dest_add_text_targets()
self.tmtc_view.connect("drag-motion", self.on_drag_motion_2)
self.tmtc_view.connect("drag-leave", self.on_drag_leave)
"""
self.tmtc_buffer.set_language(lngg)
# self.tmtc_buffer.set_style_scheme(self.board.current_scheme)
self.tmtc_scrolled_window.add(self.tmtc_view)
self.whole_tmtc_box.pack_start(self.tmtc_box, False, False, 0)
self.whole_tmtc_box.pack_start(self.tmtc_scrolled_window, True, True, 0)
self.detail_box.pack_start(self.whole_tmtc_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 an 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 Code'))
self.verification_label.set_tooltip_text(_('The verification code-block must define a variable "result" that is TRUE/FALSE'))
# 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.verification_scrolled_window = Gtk.ScrolledWindow()
self.verification_scrolled_window.set_size_request(-1, 125)
self.verification_view = GtkSource.View()
self.verification_view.set_auto_indent(True)
self.verification_view.set_show_line_numbers(True)
self.verification_view.set_wrap_mode(Gtk.WrapMode.WORD)
# self.verification_view.set_show_right_margin(True)
self.verification_view.set_monospace(True)
self.verification_view.set_highlight_current_line(True)
self.verification_view.set_indent_on_tab(True)
self.verification_view.set_insert_spaces_instead_of_tabs(True)
self.verification_view.set_indent_width(4)
self.verification_view.set_auto_indent(True)
self.verification_buffer = self.verification_view.get_buffer()
self.verification_buffer.set_language(lngg)
# self.verification_buffer.set_style_scheme(self.board.current_scheme)
self.verification_scrolled_window.add(self.verification_view)
# 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_description = Gtk.Box()
self.lbl_box_verification_description.set_orientation(Gtk.Orientation.HORIZONTAL)
self.verification_label_description = Gtk.Label.new()
self.verification_label_description.set_text(_('Verification Description'))
self.lbl_box_verification_description.pack_start(self.verification_label_description, False, False, 0)
# Make the area where the real command is entered
self.verification_description_scrolled_window = Gtk.ScrolledWindow()
#self.verification_comment_scrolled_window.set_size_request(200, 100)
self.verification_description_view = GtkSource.View()
Gtk.StyleContext.add_class(self.verification_description_view.get_style_context(), 'text-view')
self.verification_description_view.set_show_line_numbers(False)
self.verification_description_view.set_wrap_mode(Gtk.WrapMode.WORD)
self.verification_description_scrolled_window.add(self.verification_description_view)
self.verification_description_buffer = self.verification_description_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_description, self.lbl_box_verification, Gtk.PositionType.RIGHT, 3, 1)
self.whole_verification_box.attach_next_to(self.verification_description_scrolled_window, self.verification_scrolled_window, Gtk.PositionType.RIGHT, 3, 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()
# default behavior: step details are hidden
self.step_detail_visible = False
# drag and drop: the StepWidget as a drag source
self.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, [], Gdk.DragAction.COPY)
self.drag_source_set_target_list(None)
# drag and drop: the StepWidget as a drag destination
self.drag_dest_set(Gtk.DestDefaults.ALL, [], Gdk.DragAction.COPY)
self.drag_dest_set_target_list(None)
self.drag_dest_add_text_targets()
self.drag_source_add_text_targets()
self.connect('drag-data-received', self.on_drag_data_received)
self.connect('drag-motion', self.on_drag_motion)
self.connect('drag-leave', self.on_drag_leave)
self.connect('drag-begin', self.on_drag_begin)
self.connect('drag-data-get', self.on_drag_data_get)
self.connect('drag-drop', self.on_drag_drop)
# right click menu (context menu)
self.menu = StepRightClickMenu(step_widget=self)
self.connect('button-press-event', self.on_button_press)
# 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.step_comment_buffer.connect('changed', self.on_step_comment_buffer_changed)
self.verification_buffer.connect('changed', self.on_verification_buffer_changed)
self.verification_description_buffer.connect('changed', self.on_verification_description_buffer_changed)
Gtk.StyleContext.add_class(self.get_style_context(), 'step-widget')
@property
def step_detail_visible(self):
return self._step_detail_visible
@step_detail_visible.setter
def step_detail_visible(self, value: bool):
assert isinstance(value, bool)
self._step_detail_visible = value
# set the visibility status of the widget
self.detail_box.set_visible(self.step_detail_visible)
if self.step_detail_visible is True:
self.btn_toggle_detail.set_icon_name('pan-down-symbolic')
else:
self.btn_toggle_detail.set_icon_name('pan-end-symbolic')
@property
def step_number(self):
return self._step_number
@step_number.setter
def step_number(self, value: str):
""" If the attribute step_description is set, other actions are triggered."""
assert isinstance(value, (str, int, float))
stp_nmbr_pri, stp_nmbr_sec = data_model.parse_step_number(value)
stp_nmbr = data_model.create_step_number(stp_nmbr_pri, stp_nmbr_sec)
self._step_number = stp_nmbr
# set the text in the step number label
self.label_step_number.set_text('{} {}: '.format(_('Step'), str(self.step_number)))
@property
def start_sequence(self):
return self._start_sequence
@start_sequence.setter
def start_sequence(self, value: int):
assert isinstance(value, int) or value is None
self._start_sequence = value
@property
def stop_sequence(self):
return self._stop_sequence
@stop_sequence.setter
def stop_sequence(self, value: int):
assert isinstance(value, int) or value is None
self._stop_sequence = value
@property
def step_description(self):
return self._step_description
@step_description.setter
def step_description(self, value: str):
""" If the attribute step_description is set, other actions are triggered."""
assert isinstance(value, str)
self._step_description = value
# Setting the description 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.description = self.step_description
else:
self.logger('step with the step number {} could not be found'.format(self.step_number))
# set the short description attribute
self.short_description = self.step_description
@property
def short_description(self):
return self._short_description
@short_description.setter
def short_description(self, value: str):
""" Creates the short description of the step out of the description. Sets the text in the StepWidget toolbar
label
"""
assert isinstance(value, str)
len_short_desc = 42
if len(value) > len_short_desc:
short_d = value[0:len_short_desc] + '...'
else:
short_d = value
self._short_description = short_d
# update the text of the label
self.text_label.set_text(self.short_description)
self.text_label.set_tooltip_text(self.step_description)
def set_data_in_widget(self):
self.set_is_active_in_widget()
self.set_description_in_widget()
self.set_commands_in_widget()
self.set_step_comment_in_widget()
self.set_verification_in_widget()
self.set_verification_description_in_widget()
self.set_start_sequence_in_widget()
self.set_stop_sequence_in_widget()
return
def set_is_active_in_widget(self):
""" Toggles the checkbox"""
# Change the active state of a step in the data model
stp_ndx = self.model.get_sequence(self.sequence).get_step_index(self.step_number)
state = self.model.get_sequence(self.sequence).steps[stp_ndx].is_active
self.is_active.set_active(state)
return
def set_description_in_widget(self):
"""
copy the description of the step from the model to the text view buffer and make a short description for
the StepWidget toolbar
"""
stp_ndx = self.model.get_sequence(self.sequence).get_step_index(self.step_number)
desc = self.model.get_sequence(self.sequence).steps[stp_ndx].description
self.desc_text_buffer.set_text(desc)
self.step_description = desc
return
def set_commands_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)
commands = self.model.get_sequence(self.sequence).steps[stp_ndx].command_code
self.commands_buffer.set_text(commands)
return
def set_step_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)
step_comment = self.model.get_sequence(self.sequence).steps[stp_ndx].step_comment
self.step_comment_buffer.set_text(step_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)
verification = self.model.get_sequence(self.sequence).steps[stp_ndx].verification_code
self.verification_buffer.set_text(verification)
return
def set_verification_description_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_description = self.model.get_sequence(self.sequence).steps[stp_ndx].verification_description
self.verification_description_buffer.set_text(verification_description)
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]
if hasattr(step, 'start_sequence'):
self.start_sequence = step.start_sequence
return
def set_stop_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]
if hasattr(step, 'stop_sequence'):
self.stop_sequence = step.stop_sequence
return
@staticmethod
def read_out_text_buffer(buffer: Gtk.TextBuffer):
"""
Reads out the text buffer
:rtype: str
"""
assert isinstance(buffer, Gtk.TextBuffer)
content = buffer.get_text(start=buffer.get_start_iter(),
end=buffer.get_end_iter(),
include_hidden_chars=True)
return content
def get_commands_from_widget(self):
"""
Reads out the source buffer of the commands
:return: The code of the commands of the step
:rtype: str
"""
commands_buffer = self.commands_buffer
content = commands_buffer.get_text(start=commands_buffer.get_start_iter(),
end=commands_buffer.get_end_iter(),
include_hidden_chars=True)
return content
def get_verification_from_widget(self):
"""
Reads out the source buffer for the verification
:return: The code of the verification of the step
:rtype: str
"""
verification_buffer = self.verification_buffer
content = verification_buffer.get_text(start=verification_buffer.get_start_iter(),
end=verification_buffer.get_end_iter(),
include_hidden_chars=True)
return content
def get_active_state_from_widget(self):
"""
Get the current status of the checkbox if a step is active.
:return: state of the toggle button
:rtype: bool
"""
return self.is_active.get_active()
def on_drag_begin(self, widget, drag_context):
pass
def on_drag_data_get(self, widget, drag_context, data, info, time):
"""
Collect data about the step that is dragged. Set it as the selection-data in order to transfer it to the receiving widget.
"""
step_index = self.model.get_sequence(self.sequence).get_step_index(self.step_number)
step = self.model.get_sequence(self.sequence).steps[step_index]
assert isinstance(step, data_model.Step)
step_number = step.step_number
description = step.description
comment = step.step_comment
command_code = step.command_code
verification_code = step.verification_code
verification_descr = step.verification_description
data_type = dnd_data_parser.data_type_step if (verification_descr or verification_code) else dnd_data_parser.data_type_snippet
data_string = dnd_data_parser.create_datastring(data_type,
self.sequence,
step_number,
description,
comment,
command_code,
verification_code,
verification_descr,
logger=self.logger)
# set the text in the selection data object
data.set_text(data_string, -1)
def on_drag_motion(self, widget, drag_context, x, y, time):
# get the widget position in the grid, the widget below and above
grid = self.get_parent()
left = grid.child_get_property(self, 'left-attach')
top = grid.child_get_property(self, 'top-attach')
widget_above = grid.get_child_at(left, top - 1)
widget_below = grid.get_child_at(left, top + 1)
# decide if the cursor position is in he upper or lower quarter of the widget
widget_height = widget.get_allocated_height()
if y < widget_height * widget_grip_upper: # upper quarter
# highlight the widget above
if widget_above is not None:
Gtk.StyleContext.add_class(widget_above.get_style_context(), 'highlight')
if widget_below is not None:
Gtk.StyleContext.remove_class(widget_below.get_style_context(), 'highlight')
Gtk.StyleContext.remove_class(widget.get_style_context(), 'highlight')
elif y > widget_height * widget_grip_lower: # lower quarter
# highlight the widget below
if widget_below is not None:
Gtk.StyleContext.add_class(widget_below.get_style_context(), 'highlight')
if widget_above is not None:
Gtk.StyleContext.remove_class(widget_above.get_style_context(), 'highlight')
Gtk.StyleContext.remove_class(widget.get_style_context(), 'highlight')
else:
# highlight the widget itself
Gtk.StyleContext.add_class(widget.get_style_context(), 'highlight')
if widget_above is not None:
Gtk.StyleContext.remove_class(widget_above.get_style_context(), 'highlight')
if widget_below is not None:
Gtk.StyleContext.remove_class(widget_below.get_style_context(), 'highlight')
widget.show_all()
def on_drag_leave(self, widget, drag_context, time):
# removing the highlighting which was done in on_drag_motion
Gtk.StyleContext.remove_class(widget.get_style_context(), 'highlight')
widget.show_all()
def on_drag_drop(self, widget, drag_context, x, y, timestamp, *args):
pass
def on_drag_data_received(self, widget, drag_context, x, y, selection_data, info, time):
"""
Depending on the source of the drag operation, the widget shows different behavior.
If the drag source was another step widget the order of the steps should be changed,
thus an indicator for inserting above/below is shown.
If the drag source was and entry in the codereuse-feature, the step should be highlighted, indicating to insert
a description and code.
Also the drop position will influence what happens.
"""
# decide if the cursor position is in he upper or lower quarter of the widget
widget_height = widget.get_allocated_height()
# parse the received data
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
step = self.model.get_sequence(self.sequence).add_step_above(reference_step_position=self.step_number)
elif y > widget_height * widget_grip_lower: # lower quarter
# add a step below
step = self.model.get_sequence(self.sequence).add_step_below(reference_step_position=self.step_number)
else:
step = self.model.get_sequence(self.sequence).get_step(self.step_number)
# set the data into the test script data model
step.description = data['description']
step.command_code = data['command_code']
step.step_comment = data['comment']
step.verification_code = data['verification_code']
step.verification_description = data['verification_descr']
if drag_source_type == dnd_data_parser.data_type_step: # a step is moved
step_number = data['step_number']
dragged_step_idx = self.model.get_sequence(self.sequence).get_step_index(step_number)
dropped_on_step_idx = self.model.get_sequence(self.sequence).get_step_index(self.step_number)
widget_height = self.get_allocated_height()
if y < widget_height * widget_grip_upper:
if dragged_step_idx < dropped_on_step_idx:
self.model.get_sequence(self.sequence).move_step(dragged_step_idx, dropped_on_step_idx-1)
elif dragged_step_idx > dropped_on_step_idx:
self.model.get_sequence(self.sequence).move_step(dragged_step_idx, dropped_on_step_idx)
elif y > widget_height * widget_grip_lower:
if dragged_step_idx < dropped_on_step_idx:
self.model.get_sequence(self.sequence).move_step(dragged_step_idx, dropped_on_step_idx)
elif dragged_step_idx > dropped_on_step_idx:
self.model.get_sequence(self.sequence).move_step(dragged_step_idx, dropped_on_step_idx+1)
# update the board
self.board.update_widget_data()
# update the model view
self.app.update_model_viewer()
def on_delete_step(self, button):
""" Deletes the step from the data model (TestSequence)
:param button: the button widget
"""
# deletes the step from the data model (TestSequence)
self.model.get_sequence(self.sequence).remove_step(self.step_number)
# update the board
self.board.update_widget_data()
# update the model view
self.app.update_model_viewer()
def on_toggled_is_active(self, toggled_button):
"""
Signal if the checkbox of a steps active status was toggled.
"""
current_state = self.get_active_state_from_widget()
stp_ndx = self.model.get_sequence(self.sequence).get_step_index(self.step_number)
self.model.get_sequence(self.sequence).steps[stp_ndx].is_active = current_state
self.app.update_model_viewer()
def on_description_buffer_changed(self, text_buffer):
"""
Signal 'changed' for the description text buffer. For example the user typed.
"""
# 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.description = 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
self.app.update_model_viewer()
# update short desc
# self.update_short_description()
def on_commands_buffer_changed(self, text_buffer):
"""
Signal 'changed' for the commands source buffer
"""
# get the code of the commands out of the buffer of the widget
commands = self.get_commands_from_widget()
# 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_code = commands
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_step_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
step_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.step_comment = step_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
"""
# get the code of the verification out of the buffer of the widget
verification = self.get_verification_from_widget()
# 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_code = verification
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_description_buffer_changed(self, text_buffer):
"""
Signal 'changed' for the verification description buffer
"""
# get the code of the verification out of the buffer of the widget
verification_description = 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_description = verification_description
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())
#Check if CCS is open
if not cfl.is_open('editor'):
print('CCS-Editor has to be started first')
logger.info('CCS-Editor has to be running if a step should be executed')
return
# Connect to the editor and send the commands to the terminal via D-Bus
ed = cfl.dbus_connection('editor')
cfl.Functions(ed, '_to_console_via_socket', commands)
#import editor
#x = editor.CcsEditor()
#x._to_console_via_socket(commands)
def on_exec_verification(self, button):
# get the code of the commands out of the buffer of the widget
verification = self.get_verification_from_widget()
#ack = misc.to_console_via_socket(verification)
#print(ack)
def on_execute_step(self, *args):
if not cfl.is_open('editor'):
print('CCS-Editor has to be started first')
logger.info('CCS-Editor has to be running if a step should be executed')
return
commands = str(self.get_commands_from_widget())
if len(commands) == 0:
return
ed = cfl.dbus_connection('editor')
cfl.Functions(ed, '_to_console_via_socket', commands)
def on_toggle_detail(self, toolbutton, *args):
"""
The button to show/hide the step details was clicked.
The visible status of the detail area is inverted and the button icon is changed.
:param Gtk.ToolButton toolbutton: the button widget which was clicked
"""
self.step_detail_visible = not self.detail_box.is_visible()
# if showing the detail view, set the cursor into the description field
if self.step_detail_visible is True:
self.do_grab_focus(self.desc_text_view)
return False
def on_detail_box_show(self, *args):
self.step_detail_visible = self.step_detail_visible
def on_button_press(self, widget, event, *args):
if event.button == 3: # right mouse button clicked
# show the right-click context menu
widget.menu.popup_at_pointer()
class InterStepWidget(Gtk.Box):
"""
This widget is used to be put between two steps.
It is used to highlight if a step is dragged over it and draw an arrow between two steps.
"""
def __init__(self, model, seq_num, app, board, logger=logger):
super().__init__()
Gtk.StyleContext.add_class(self.get_style_context(), 'inter-step-widget')
self.model = model
self.app = app
self.board = board
self.logger = logger
self.sequence = seq_num
# add the drawing area for the arrow
self.drawingarea = Gtk.DrawingArea()
self.drawingarea_height = 16
self.hovered_over = False
self.drawingarea.set_size_request(10, self.drawingarea_height)
self.pack_start(self.drawingarea, True, True, 0)
self.drawingarea.connect('draw', self.draw)
# self.drawingarea.connect('realize', self.realize)
# self.drawingarea.connect('size-allocate', self.size_allocate)
# drag and drop: make this widget a drag destination
self.drag_dest_set(Gtk.DestDefaults.ALL, [], Gdk.DragAction.COPY)
self.drag_dest_set_target_list(None)
self.drag_dest_add_text_targets()
self.connect('drag-data-received', self.on_drag_data_received)
self.connect('drag-motion', self.on_drag_motion)
self.connect('drag-leave', self.on_drag_leave)
self.connect('drag-drop', self.on_drag_drop)
# def draw_arrow(self, ctx, x, y, size):
# """
# Uses cairo context functions to draw the arrow.
# """
# ctx.save()
# ctx.new_path()
#
# # draw the arrow (construction of the path)
# ctx.move_to(x, y)
# ctx.rel_line_to(0, 1/3*size)
# ctx.rel_line_to(-1/3*size, 0)
# ctx.rel_line_to(1/3*size, 2/3*size)
# ctx.rel_line_to(1/3*size, -2/3*size)
# ctx.rel_line_to(-1/3*size, 0)
# ctx.close_path()
#
# # draw the path and fill it
# ctx.stroke_preserve()
# ctx.fill()
# ctx.restore()
# return
def draw_arrow_head(self, ctx, x, y, size):
"""
Uses cairo context functions to draw the arrow.
"""
ctx.save()
ctx.new_path()
# draw the arrow (construction of the path)
ctx.move_to(x, y+size)
ctx.rel_line_to(-1/2*size, -size)
ctx.rel_line_to(1*size, 0)
ctx.rel_line_to(-1/2*size, size)
ctx.close_path()
# draw the path and fill it
ctx.stroke_preserve()
ctx.fill()
ctx.restore()
return
def draw_insert_here_arrows(self, ctx, x, y, size):
"""
Uses cairo context functions to draw the arrow.
"""
ctx.save()
ctx.new_path()
size = size/2
# draw the arrow (construction of the path)
ctx.move_to(x, y+size)
ctx.rel_line_to(-1/2*size, -size)
ctx.rel_line_to(1*size, 0)
ctx.rel_line_to(-1/2*size, size)
ctx.move_to(0, y+size)
ctx.rel_line_to(2*x, 0)
ctx.move_to(x, y+size)
ctx.rel_line_to(-1/2*size, size)
ctx.rel_line_to(1*size, 0)
ctx.rel_line_to(-1/2*size, -1*size)
ctx.close_path()
# draw the path and fill it
ctx.stroke_preserve()
ctx.fill()
ctx.restore()
return
# def realize(self, *args):
# pass
#
# def size_allocate(self, *args):
# """
# Resize the drawing area: figure out the height of a step widget, with no details shown (for the length of the
# arrow) and resize the drawing area.
# """
# for child in self.board.grid.get_children():
# if isinstance(child, StepWidget):
# if not child.step_detail_visible:
# # height = child.get_allocated_height()
# # width = child.get_allocated_width()
# natural_height = child.get_preferred_height()[1]
# natural_width = child.get_preferred_width()[1]
# width = self.get_allocated_width()
# # self.drawingarea.set_size_request(width, natural_height)
# self.drawingarea.set_size_request(10, 10)
def draw(self, da, ctx, *args):
"""
Draws an arrow if:
* a step is below this interstep-widget (vertical arrows)
* another sequence is started (horizontal arrows)
The arrows are drawn:
starting point is the half width of the widget, because in the grid all are the same width
The length of the arrow is determined by the height of a step widget with no details shown.
"""
width = self.get_allocated_width()
# for child in self.board.grid.get_children():
# if isinstance(child, InterStepWidget):
# print('{}, {}'.format(self.board.grid.child_get_property(child, 'left-attach'),
# self.board.grid.child_get_property(child, 'top-attach')))
# print('*****')
# figure out the height of a step widget, with do details shown (for the length of the arrow)
for child in self.board.grid.get_children():
if isinstance(child, StepWidget):
if not child.step_detail_visible:
# height = child.get_allocated_height()
height = child.get_preferred_height()[1]
# figure out the top-attach of this widget
for child in self.board.grid.get_children():
if child is self:
self.top_attach = self.board.grid.child_get_property(child, 'top-attach')
self.left_attach = self.board.grid.child_get_property(child, 'left-attach')
# figure out, if there comes another step after this InterStep widget
another_step_follows = False
for child in self.board.grid.get_children():
if isinstance(child, StepWidget):
child_top_attach = self.board.grid.child_get_property(child, 'top-attach')
child_left_attach = self.board.grid.child_get_property(child, 'left-attach')
if child_left_attach == self.left_attach: # only widgets in the same column are considered
if child_top_attach > self.top_attach:
another_step_follows = True
# figure out, if there is another step in front this InterStep widget
another_step_in_front = False
for child in self.board.grid.get_children():
if isinstance(child, StepWidget):
child_top_attach = self.board.grid.child_get_property(child, 'top-attach')
child_left_attach = self.board.grid.child_get_property(child, 'left-attach')
if child_left_attach == self.left_attach: # only widgets in the same column are considered
if child_top_attach < self.top_attach:
another_step_in_front = True
# draw the arrow if another step follows
ctx.set_source_rgb(0, 0, 0)
ctx.set_line_width(self.drawingarea_height / 10)
ctx.set_tolerance(0.1)
ctx.set_line_join(cairo.LINE_JOIN_ROUND)
if self.hovered_over:
self.draw_insert_here_arrows(ctx, width/2, 0, self.drawingarea_height)
else:
if another_step_follows:
self.draw_arrow_head(ctx, width/2, 0, self.drawingarea_height)
return
def on_drag_motion(self, widget, drag_context, x, y, time):
self.hovered_over = True
self.drawingarea.queue_draw()
Gtk.StyleContext.add_class(widget.get_style_context(), 'highlight-2')
widget.show_all()
def on_drag_leave(self, widget, drag_context, time):
self.hovered_over = False
# removing the highlighting which was done in on_drag_motion
Gtk.StyleContext.remove_class(widget.get_style_context(), 'highlight-2')
widget.show_all()
def on_drag_drop(self, widget, drag_context, x, y, timestamp, *args):
pass
def on_drag_data_received(self, widget, drag_context, x, y, selection_data, info, time):
self.hovered_over = False
# figure out what was the source of the drag operation
data_string = selection_data.get_text()
data = dnd_data_parser.read_datastring(data_string, logger=self.logger)
drag_source_type = data['data_type']
# get the widget above
grid = self.get_parent()
left = grid.child_get_property(self, 'left-attach')
top = grid.child_get_property(self, 'top-attach')
widget_above = grid.get_child_at(left, top - 1)
# create a new step and fill it with data
if drag_source_type == dnd_data_parser.data_type_snippet:
# add a step below the position of the widget above
if isinstance(widget_above, StepWidget):
dest_step_above_number = widget_above.step_number
new_step = self.model.get_sequence(self.sequence).add_step_below(reference_step_position=dest_step_above_number)
# set the data into the test script data model
new_step.description = data['description']
new_step.step_comment = data['comment']
new_step.command_code = data['command_code']
new_step.verification_code = data['verification_code']
new_step.verification_description = data['verification_descr']
if drag_source_type == dnd_data_parser.data_type_step: # a step is moved
source_sequence = int(data['sequence'])
source_step_number = data['step_number']
source_step_idx = self.model.get_sequence(source_sequence).get_step_index(source_step_number)
if isinstance(widget_above, StepWidget):
dest_step_above_number = widget_above.step_number
dest_step_above_sequence = widget_above.sequence
dest_step_above_idx = self.model.get_sequence(dest_step_above_sequence).get_step_index(dest_step_above_number)
if source_sequence == dest_step_above_sequence: # moving the step within the same sequence
if source_step_idx < dest_step_above_idx:
self.model.get_sequence(dest_step_above_sequence).move_step(source_step_idx, dest_step_above_idx)
elif source_step_idx > dest_step_above_idx:
self.model.get_sequence(dest_step_above_sequence).move_step(source_step_idx, dest_step_above_idx+1)
else:
# the step is moved to another sequence:
# add the step within the new sequence and remove it from the old sequence
seq = self.model.get_sequence(dest_step_above_sequence)
new_step = self.model.get_sequence(dest_step_above_sequence).add_step_below(reference_step_position=dest_step_above_number)
# set the data into the test script data model
new_step.description = data['description']
new_step.step_comment = data['comment']
new_step.command_code = data['command_code']
new_step.verification_code = data['verification_code']
new_step.verification_description = data['verification_descr']
# ToDo
# remove it from the old sequence
dragged_from_seq = self.model.get_sequence(source_sequence)
dragged_from_seq.remove_step(step_number=source_step_number)
# update the board
self.board.update_widget_data()
# update the model view
self.app.update_model_viewer()
class StepRightClickMenu(Gtk.Menu):
def __init__(self, step_widget):
super().__init__()
self.step_widget = step_widget
entry_1 = Gtk.MenuItem('Insert step above')
self.attach(entry_1, 0, 1, 0, 1)
entry_1.show()
entry_1.connect('activate', self.on_insert_step_above, self.step_widget)
entry_2 = Gtk.MenuItem('Insert step below')
self.attach(entry_2, 0, 1, 1, 2)
entry_2.show()
entry_2.connect('activate', self.on_insert_step_below, self.step_widget)
def on_insert_step_above(self, menu_item, step_widget, *args):
step_clicked_on = step_widget.step_number
step_widget.model.get_sequence(step_widget.sequence).add_step_above(reference_step_position=step_clicked_on)
self.step_widget.board.update_widget_data()
def on_insert_step_below(self, menu_item, step_widget, *args):
step_clicked_on = step_widget.step_number
step_widget.model.get_sequence(step_widget.sequence).add_step_below(reference_step_position=step_clicked_on)
self.step_widget.board.update_widget_data()
class Edit_Pre_Post_Con_Dialog(Gtk.Dialog):
def __init__(self, parent, pre_post, selection):
# Gtk.Dialog.__init__(self, title=pre_post.upper() + ' -Conditions')
super(Edit_Pre_Post_Con_Dialog, self).__init__(title=pre_post.upper() + '-conditions')
self.add_buttons(
Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OK, Gtk.ResponseType.OK
)
self.set_default_size(400, 400)
self.first_entry = selection
self.win = parent
self.file_path = os.path.join(confignator.get_option('paths', 'tst'),
'tst/generator_templates/co_'+pre_post+'_condition_entry.py')
# self.pre_post = pre_post
self.pre_post = None
self.make_section_dict()
self.view()
self.show_all()
def make_section_dict(self):
# if self.pre_post == 'pre':
# self.section_dict = db_interaction.get_pre_post_con('pre')
# else:
# self.section_dict = db_interaction.get_pre_post_con('post')
self.section_dict = db_interaction.get_pre_post_con(None)
def view(self):
# self.main_box = Gtk.Box()
# self.main_box.set_orientation(Gtk.Orientation.VERTICAL)
self.selection_box = Gtk.Box()
self.selection_box.set_orientation(Gtk.Orientation.HORIZONTAL)
self.make_description_viewer()
self.make_text_viewer()
self.selection = Gtk.ComboBoxText.new_with_entry()
self.make_con_sections_model()
self.selection.connect("changed", self.on_name_combo_changed)
self.selection.set_entry_text_column(0)
self.selection.set_active(self.first_entry)
self.save_button = Gtk.Button.new_with_label('Save')
self.save_button.connect("clicked", self.on_save_button)
self.delete_button = Gtk.Button.new_with_label('Delete')
self.delete_button.connect("clicked", self.on_delete_button)
self.selection_box.pack_start(self.selection, False, True, 0)
self.selection_box.pack_start(self.save_button, False, True, 0)
self.selection_box.pack_start(self.delete_button, False, True, 0)
box = self.get_content_area()
# Gtk.StyleContext.add_class(box.get_style_context(), 'cond-dialog')
# box.set_margin_top(5)
# box.set_margin_bottom(5)
# box.set_margin_left(5)
# box.set_margin_right(5)
box.pack_start(self.selection_box, False, True, 3)
box.pack_start(self.descr_lbl_box, False, False, 0)
box.pack_start(self.descr_scrolled_window, False, False, 0)
box.pack_start(self.con_lbl_box, False, False, 0)
box.pack_start(self.con_scrolled_window, True, True, 0)
# box.add(self.selection_box)
# box.pack_end(self.scrolled_window, True, True, 0)
def make_con_sections_model(self):
for condition in self.section_dict:
self.selection.append_text(condition.name)
return
def on_name_combo_changed(self, widget):
name = widget.get_active_text()
if name:
for condition in self.section_dict:
if condition.name == name:
self.descr_textview.get_buffer().set_text(condition.description)
self.con_buffer.set_text(condition.condition)
else:
self.descr_textview.get_buffer().set_text('')
self.con_buffer.set_text('')
return
def on_save_button(self, widget):
descr_buffer = self.descr_textview.get_buffer()
name = self.selection.get_active_text()
if not name:
return
descr = descr_buffer.get_text(descr_buffer.get_start_iter(), descr_buffer.get_end_iter(), True)
condition = self.con_buffer.get_text(self.con_buffer.get_start_iter(), self.con_buffer.get_end_iter(), True)
db_interaction.write_into_pre_post_con(code_type=self.pre_post, name=name, description=descr, code_block=condition)
time.sleep(0.1) # Sleep shorty so the condition can be written to the database
# Refresh the combo box entries
self.make_section_dict()
self.selection.remove_all()
self.make_con_sections_model()
return
def on_delete_button(self, widget):
name = self.selection.get_active_text()
for con in self.section_dict:
if con.name == name:
db_interaction.delete_db_row_pre_post(con.id)
time.sleep(0.1) # Sleep shorty so the condition can be deleted from the database
# Refresh the combo box entries
self.make_section_dict()
self.selection.remove_all()
self.make_con_sections_model()
self.selection.set_active(0)
return
def make_description_viewer(self):
# Label in a Box to have it on the left boarder
self.descr_lbl_box = Gtk.HBox()
descr_lbl = Gtk.Label()
descr_lbl.set_text('Description')
self.descr_lbl_box.pack_start(descr_lbl, False, False, 0)
# a scrollbar for the child widget (that is going to be the textview)
self.descr_scrolled_window = Gtk.ScrolledWindow()
self.descr_scrolled_window.set_border_width(5)
# we scroll only if needed
self.descr_scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
# a text buffer (stores text)
buffer = Gtk.TextBuffer()
# a textview (displays the buffer)
self.descr_textview = Gtk.TextView(buffer=buffer)
# wrap the text, if needed, breaking lines in between words
self.descr_textview.set_wrap_mode(Gtk.WrapMode.WORD)
# textview is scrolled
self.descr_scrolled_window.add(self.descr_textview)
def make_text_viewer(self):
# Label in a Box to have it on the left boarder
self.con_lbl_box = Gtk.HBox()
con_lbl = Gtk.Label()
con_lbl.set_text('Condition')
self.con_lbl_box.pack_start(con_lbl, False, False, 0)
self.con_scrolled_window = Gtk.ScrolledWindow()
self.con_scrolled_window.set_tooltip_text('Set variable "success" to True/False to check if conditon is fulfilled')
#self.commands_scrolled_window.set_size_request(50, 100)
self.con_view = GtkSource.View()
self.con_view.set_auto_indent(True)
self.con_view.set_show_line_numbers(False)
# self.commands_view.set_show_right_margin(True)
self.con_view.set_highlight_current_line(True)
self.con_view.set_indent_on_tab(True)
self.con_view.set_insert_spaces_instead_of_tabs(True)
self.con_buffer = self.con_view.get_buffer()
self.con_buffer.set_language(lngg)
# self.commands_buffer.set_style_scheme(self.board.current_scheme)
self.con_scrolled_window.add(self.con_view)