Commit 336012a8 authored by Maxime Perrotin's avatar Maxime Perrotin
Browse files

Make sdl state tuneable

parent 8c9fbdd3
......@@ -43,6 +43,9 @@ except ImportError:
# Unicode separator used by Opengeode in the Ada backend
# to build unambiguous names, in particular when using nested states
UNICODE_SEP = u'\u00dc'
CleanName = lambda name: name.replace(UNICODE_SEP, '->')
UnicodeName = lambda name: name.replace('->', UNICODE_SEP)
class SendTC(QUndoCommand):
''' Undo command to send a message to the running system '''
......@@ -57,11 +60,13 @@ class SendTC(QUndoCommand):
''' Undo a send TC: Restore the system state as it was before the TC
was sent - setting back all global variables and internal state '''
self.handler.restore_global_state(self.old_state)
self.handler.update_button_state()
def redo(self):
''' Set the internal variables to the new state '''
if self.new_state != self.handler.current_hash:
self.handler.restore_global_state(self.new_state)
self.handler.update_button_state()
class sdlHandler(QObject):
......@@ -113,7 +118,7 @@ class sdlHandler(QObject):
self.asn1_editor = None
self.tree_items = {}
self.dock_simu = self.start_simu()
self.current_sdl_state = None
self.current_sdl_state = ''
# Handle the state of all timers ({'timerName': 'set'/'unset'})
self.timers = {}
# Keep a state graph to allow undo/redo and state exploration
......@@ -166,19 +171,19 @@ class sdlHandler(QObject):
self.dock_state.setWidget(widgets)
self.dock_state.show()
self.parent.tabifyDockWidget(self.dock_state, self.dock_simu)
# Add the SDL variables to the ASN.1 editor
# Add the state list to the ASN.1 Editor (at row 0)
row = 0
statenames = [CleanName(s) for s in self.proc.mapping.viewkeys()
if not s.endswith(u'START')]
states = {'id': 'Current SDL state', 'type': 'ENUMERATED',
'values': statenames}
self.tree_items['_states'] = self.asn1_editor.setAsn1Model(states, row)
# Add the SDL variables to the ASN.1 editor
row = 1
for var, (sort, _) in self.proc.variables.viewitems():
item = asn1sccToasn1ValueEditorTypes(self.proc.dataview, var, sort)
self.tree_items[var] = self.asn1_editor.setAsn1Model(item, row)
row += 1
# Add the state list to the ASN.1 Editor
statenames = [s.replace(UNICODE_SEP, '->')
for s in self.proc.mapping.viewkeys()
if 'START' not in s]
states = {'id': 'Current SDL state', 'type': 'ENUMERATED',
'values': statenames}
self.tree_items['States'] = self.asn1_editor.setAsn1Model(states, row)
# In the simulation panel, set the buttons to send paramless TC/timers
self.set_paramless_tc()
self.set_paramless_tm()
......@@ -186,7 +191,7 @@ class sdlHandler(QObject):
'{}_state'.format(self.proc.processName))
self.get_sdl_state.restype = ctypes.c_char_p
# Initialization: set current state and internal variables
self.current_sdl_state = None
self.current_sdl_state = ''
self.check_state()
self.init_state = self.current_hash = self.on_event()
self.init_timers()
......@@ -257,24 +262,26 @@ class sdlHandler(QObject):
def change_internal_state(self):
''' When user press the "Apply" button to change the model's internal
state (variables of the SDL model): Create an undo action that
applies the change.
state (variables of the SDL model, or state of the automaton)
Create an undo action that applies the change.
'''
# Create a new global state
new_state = []
# Get the variables values from the asn1_value_editor window
for var, (sort, _) in self.proc.variables.viewitems():
typename = sort.ReferencedTypeName.replace('-', '_')
asn1_type = self.proc.dataview[sort.ReferencedTypeName]
asn1_instance = getattr(ASN1, typename)()
# Fill up the SWIG ASN.1 instance
self.asn1_editor.to_asn1scc_swig(root=self.tree_items[var],
dest=asn1_instance, ASN1Swig=ASN1,
sort=sort,
ASN1_AST=self.proc.dataview)
new_state.append(asn1_instance)
typename = sort.ReferencedTypeName.replace('-', '_')
asn1_type = self.proc.dataview[sort.ReferencedTypeName]
asn1_instance = getattr(ASN1, typename)()
# Fill up the SWIG ASN.1 instance
self.asn1_editor.to_asn1scc_swig(root=self.tree_items[var],
dest=asn1_instance, ASN1Swig=ASN1,
sort=sort,
ASN1_AST=self.proc.dataview)
new_state.append(asn1_instance)
# Add the SDL state to the new global state, create a new hash, save it
new_state.append(self.current_sdl_state)
sdl_state = self.asn1_editor.getVariable(self.tree_items['_states'])
new_sdl_state = sdl_state['Current SDL state']['Enum']
new_state.append(UnicodeName(new_sdl_state))
new_hash = hash(frozenset(new_state))
self.set_of_states[new_hash] = new_state
# Apply the change and create Undo command to restore previous state
......@@ -285,7 +292,9 @@ class sdlHandler(QObject):
self.undo_stack.push(undo_cmd)
def on_event(self, tc_name=None, param=None):
''' Update the list of global states and GUI after a TC has been sent
''' Read the values of internal variables in the dll, update the gui
accordingly (in the "global state" panel), and depending on the
current SDL state, enable/disable the buttons for sending TCs.
This function does not trigger any undoable action '''
complete_state = []
# Read in the DLL the list of internal variables
......@@ -317,6 +326,17 @@ class sdlHandler(QObject):
# And save this new state in the graph, if it was not there yet
new_hash = hash(frozenset(complete_state))
self.set_of_states[new_hash] = complete_state
# Disable the TC buttons the current state does does allow
self.update_button_state(tc_name)
if tc_name:
# Log all TC sent
self.log_area.addItem('Sent {}({})'.format(tc_name,
param or ''))
return new_hash
def update_button_state(self, tc_name=None):
''' Depending on the current SDL state, enable or disable the buttons
for sending TCs '''
# Find the list of allowed TC based on the current state
inputs = self.proc.mapping[self.current_sdl_state.lower()]
allowed_tc = []
......@@ -334,12 +354,6 @@ class sdlHandler(QObject):
self.buttons[tc_name].setEnabled(False)
# Emit the list of allowed TC for the GUI to update other buttons
self.allowed_messages.emit(allowed_tc)
if tc_name:
# Log all TC sent
self.log_area.addItem('Sent {}({})'.format(tc_name,
param or ''))
return new_hash
def start_simu(self):
'''
......@@ -396,7 +410,7 @@ class sdlHandler(QObject):
if self.check_state():
# If state changed, update the MSC
self.add_to_msc('condition', self.current_sdl_state)
self.add_to_msc('condition', CleanName(self.current_sdl_state))
# Update windows, highlight state, enable/disable buttons, etc.
self.current_hash = self.on_event(tc_name=name,
param=param.GSER() if param
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment