Commit 59a97144 authored by Maxime Perrotin's avatar Maxime Perrotin
Browse files

Merge branch 'master' of gitrepos.estec.esa.int:taste/asn1-value-editor

parents e49f417f de81a6d3
...@@ -32,3 +32,5 @@ Author: Maxime Perrotin ...@@ -32,3 +32,5 @@ Author: Maxime Perrotin
LICENSE: LGPL - see LICENSE file LICENSE: LGPL - see LICENSE file
CHANGELOG:
1.0.7 - fixed bug in value notation parser
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
__author__ = "Maxime Perrotin" __author__ = "Maxime Perrotin"
__license__ = "LGPLv3" __license__ = "LGPLv3"
__version__ = "1.0.6" __version__ = "1.0.7"
__url__ = "http://taste.tuxfamily.org" __url__ = "http://taste.tuxfamily.org"
import sys import sys
...@@ -39,12 +39,14 @@ ASN1TYPE = Qt.UserRole ...@@ -39,12 +39,14 @@ ASN1TYPE = Qt.UserRole
class myTextEdit(QTextEdit): class myTextEdit(QTextEdit):
''' Customized text editor that contains a context menu for loading data from a file ''' ''' Customized text editor that contains a context menu for loading
data from a file '''
def __init__(self, parent=None): def __init__(self, parent=None):
super(myTextEdit, self).__init__(parent) super(myTextEdit, self).__init__(parent)
def contextMenuEvent(self, event): def contextMenuEvent(self, event):
''' When the context menu is open, add the Load from file action and open the menu ''' ''' When the context menu is open, add the Load from file action
and open the menu '''
myMenu = self.createStandardContextMenu() myMenu = self.createStandardContextMenu()
myAction = 'Load data from file' myAction = 'Load data from file'
myMenu.addAction(myAction) myMenu.addAction(myAction)
......
...@@ -264,7 +264,7 @@ class sdlHandler(QObject): ...@@ -264,7 +264,7 @@ class sdlHandler(QObject):
self.proc = root_ast.processes[0] self.proc = root_ast.processes[0]
except IndexError: except IndexError:
raise IOError('SDL Handler failed to initialize') raise IOError('SDL Handler failed to initialize')
opengeode.Helper.flatten(self.proc) #opengeode.Helper.flatten(self.proc)
graph = opengeode.Statechart.create_dot_graph(self.proc, basic=True) graph = opengeode.Statechart.create_dot_graph(self.proc, basic=True)
self.sdl_scene = opengeode.SDL_Scene('statechart') self.sdl_scene = opengeode.SDL_Scene('statechart')
self.sdl_view = opengeode.SDL_View(self.sdl_scene) self.sdl_view = opengeode.SDL_View(self.sdl_scene)
...@@ -317,7 +317,7 @@ class sdlHandler(QObject): ...@@ -317,7 +317,7 @@ class sdlHandler(QObject):
def active_tc(self): def active_tc(self):
''' Yield list of TCs that can be sent (including timeouts) ''' ''' Yield list of TCs that can be sent (including timeouts) '''
# Find the list of allowed TC based on the current state # Find the list of allowed TC based on the current state
st = unicode(self.current_sdl_state.decode('latin1')) st = self.current_sdl_state
inputs = self.proc.mapping[st.replace(UNICODE_SEP, '_').lower()] inputs = self.proc.mapping[st.replace(UNICODE_SEP, '_').lower()]
allowed_tc = (tc for each in inputs for tc in each.inputlist) allowed_tc = (tc for each in inputs for tc in each.inputlist)
for each in allowed_tc: for each in allowed_tc:
...@@ -365,13 +365,44 @@ class sdlHandler(QObject): ...@@ -365,13 +365,44 @@ class sdlHandler(QObject):
self.parent.tabifyDockWidget(self.dock_simu, self.dock_checker) self.parent.tabifyDockWidget(self.dock_simu, self.dock_checker)
# Add the state list to the ASN.1 Editor (at row 0) # Add the state list to the ASN.1 Editor (at row 0)
row = 0 row = 0
statenames = [CleanName(s) for s in self.proc.mapping.viewkeys()
# Build up the list of states, including state compositions
context = self.proc
# get the list of state aggregations
aggregates = opengeode.Helper.state_aggregations(context)
get_statenames = lambda c: [CleanName(s) for s in c.mapping.viewkeys()
if not s.endswith(u'START')] if not s.endswith(u'START')]
statenames = get_statenames(context)
def rec_findstates(context, prefix=''):
for each in context.composite_states:
prefix += each.statename + '__'
for name in get_statenames(each):
yield prefix+name
for substate in rec_findstates(each, prefix):
yield substate
statenames.extend(list(rec_findstates(context)))
states = {'id': 'Current SDL state', 'type': 'ENUMERATED', states = {'id': 'Current SDL state', 'type': 'ENUMERATED',
'values': statenames} 'values': list(statenames)}
self.tree_items['_states'] = self.asn1_editor.setAsn1Model(states, row) self.tree_items['_states'] = self.asn1_editor.setAsn1Model(states, row)
if aggregates:
statenames.append('(not in state)')
# Add state variables for parelle states in aggregations
for agg, substates in aggregates.viewitems():
for each in substates:
row += 1
states = {'id': 'Substate {}.{}'.format(CleanName(agg),
each.statename),
'type': 'ENUMERATED',
'values': list(statenames)}
self.tree_items['substate_{}'.format(each.statename)] = \
self.asn1_editor.setAsn1Model(states, row)
# Add the SDL variables to the ASN.1 editor # Add the SDL variables to the ASN.1 editor
row = 1 row += 1
for var, (sort, _) in self.proc.variables.viewitems(): for var, (sort, _) in self.proc.variables.viewitems():
item = asn1sccToasn1ValueEditorTypes(self.proc.dataview, var, sort) item = asn1sccToasn1ValueEditorTypes(self.proc.dataview, var, sort)
self.tree_items[var] = self.asn1_editor.setAsn1Model(item, row) self.tree_items[var] = self.asn1_editor.setAsn1Model(item, row)
...@@ -387,7 +418,7 @@ class sdlHandler(QObject): ...@@ -387,7 +418,7 @@ class sdlHandler(QObject):
'{}_state'.format(self.proc.processName)) '{}_state'.format(self.proc.processName))
self.get_sdl_state.restype = ctypes.c_char_p self.get_sdl_state.restype = ctypes.c_char_p
# Initialization: set current state and internal variables # Initialization: set current state and internal variables
self.current_sdl_state = '' self.current_sdl_state = u''
self.check_state() self.check_state()
self.init_timers() self.init_timers()
self.init_state = self.current_hash = self.on_event() self.init_state = self.current_hash = self.on_event()
...@@ -472,13 +503,14 @@ class sdlHandler(QObject): ...@@ -472,13 +503,14 @@ class sdlHandler(QObject):
def check_state(self): def check_state(self):
''' Highlight the current state on the statechart diagram ''' Highlight the current state on the statechart diagram
Return True if the state has changed ''' Return True if the state has changed '''
state = self.get_sdl_state() state = self.get_sdl_state().decode('latin1')
if state != self.current_sdl_state: if state != self.current_sdl_state:
self.current_sdl_state = state self.current_sdl_state = state
self.sdl_scene.clear_highlight() self.sdl_scene.clear_highlight()
state = state.decode('latin1') # Recover the unicode chars composition = state.split(UNICODE_SEP)
for each in self.sdl_scene.find_text(u'\\b{}\\b'.format(state)): for each in composition:
self.sdl_scene.highlight(each) for symb in self.sdl_scene.find_text(u'\\b{}\\b'.format(each)):
self.sdl_scene.highlight(symb)
self.log_area.addItem('New state: {}'.format(CleanName(state))) self.log_area.addItem('New state: {}'.format(CleanName(state)))
return True return True
return False return False
...@@ -591,8 +623,12 @@ class sdlHandler(QObject): ...@@ -591,8 +623,12 @@ class sdlHandler(QObject):
# Add the SDL state to the new global state # Add the SDL state to the new global state
complete_state.append(self.current_sdl_state) complete_state.append(self.current_sdl_state)
# Update the SDL state in the global state panel # Update the SDL state in the global state panel
# state_as_pyside = vn.fromValueNotationToPySide('Current SDL state',
# '{}'.format(self.current_sdl_state.lower().replace('_', '-')
# .replace(UNICODE_SEP, '--')))
readable_state = self.current_sdl_state.replace(UNICODE_SEP, '--')
state_as_pyside = vn.fromValueNotationToPySide('Current SDL state', state_as_pyside = vn.fromValueNotationToPySide('Current SDL state',
'{}'.format(self.current_sdl_state.lower().replace('_', '-'))) readable_state.lower().replace('_', '-'))
self.asn1_editor.updateVariable(state_as_pyside, self.asn1_editor.updateVariable(state_as_pyside,
root=self.tree_items['_states']) root=self.tree_items['_states'])
# And save this new state in the graph, if it was not there yet # And save this new state in the graph, if it was not there yet
...@@ -612,24 +648,35 @@ class sdlHandler(QObject): ...@@ -612,24 +648,35 @@ class sdlHandler(QObject):
if check_ppty: if check_ppty:
# When doing undo, dont check propertis again # When doing undo, dont check propertis again
self.check_properties(new_hash) self.check_properties(new_hash)
# TEMP TO TEST self.check_properties(new_hash)
# for name, typedef in self.proc.dataview.viewitems():
# if name != 'MySeq': continue
# print 'All combinations of ', name
# for combi in compute_combinations(typedef, self.proc.dataview):
# print combi
# END TEMP
return new_hash return new_hash
def update_button_state(self, tc_name=None): def update_button_state(self, tc_name=None):
''' Depending on the current SDL state, enable or disable the buttons ''' Depending on the current SDL state, enable or disable the buttons
for sending TCs ''' for sending TCs '''
# Find the list of allowed TC based on the current state # Find the list of allowed TC based on the current state
st = unicode(self.current_sdl_state.decode('latin1')) st = self.current_sdl_state.split(UNICODE_SEP)
inputs = self.proc.mapping[st.replace(UNICODE_SEP, '_').lower()] st_iter = st.pop(0)
allowed_tc = [] context = self.proc
def find_allowed_tc(context, statename):
inputs = context.mapping[statename.lower()]
for each in inputs: for each in inputs:
allowed_tc.extend(each.inputlist) for inp in each.inputlist:
yield inp
allowed_tc = list(find_allowed_tc(context, st_iter))
while len(st):
# Handle state composition
next_st = st.pop(0)
for each in context.composite_states:
if each.statename.lower() == st_iter.lower():
context = each
break
allowed_tc.extend(list(find_allowed_tc(context, next_st)))
st_iter = next_st
# Remove timers from the list # Remove timers from the list
allowed_tc = set(allowed_tc) - set(self.proc.timers) allowed_tc = set(allowed_tc) - set(self.proc.timers)
# Enable/disable the parameterless TC buttons accordingly # Enable/disable the parameterless TC buttons accordingly
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
Parse a string containing an ASN.1 value expressed in GSER Parse a string containing an ASN.1 value expressed in GSER
(also called ASN.1 Value Notation) and return a Python structure that (also called ASN.1 Value Notation) and return a Python structure that
is compatible with the widget of the ASN.1 Value Editor is compatible with the widget of the ASN.1 Value Editor
Copyright (c) 2012-2015 European Space Agency
2) toASN1ValueNotation(val) 2) toASN1ValueNotation(val)
Does the reverse (from Qt widget to ASN.1 Value Notation/GSER) Does the reverse (from Qt widget to ASN.1 Value Notation/GSER)
...@@ -119,14 +118,12 @@ value = (BitStringLiteral ...@@ -119,14 +118,12 @@ value = (BitStringLiteral
namedValue = identifier + value namedValue = identifier + value
# ASN.1 CHOICE # ASN.1 CHOICE
choiceValue << (identifier + ':' + value).setResultsName('CHOICE') choiceValue << (identifier + ':' + value)#.setResultsName('CHOICE')
# ASN.1 SEQUENCE # ASN.1 SEQUENCE
#NAMED_VALUE_LIST << nestedExpr('{','}', delimitedList(namedValue, delim=',')).setResultsName('SEQUENCE', True)
NAMED_VALUE_LIST << LBRACKET + delimitedList(namedValue) + RBRACKET NAMED_VALUE_LIST << LBRACKET + delimitedList(namedValue) + RBRACKET
# ASN.1 SEQUENCE OF # ASN.1 SEQUENCE OF
#VALUE_LIST << nestedExpr('{', '}', delimitedList(value, delim=',')).setResultsName('SEQOF', True)
VALUE_LIST << LBRACKET + Optional(delimitedList(value)) + RBRACKET VALUE_LIST << LBRACKET + Optional(delimitedList(value)) + RBRACKET
# Parse actions allow to modify the AST to be compliant with the ASN.1 Editor input # Parse actions allow to modify the AST to be compliant with the ASN.1 Editor input
...@@ -134,8 +131,23 @@ NAMED_VALUE_LIST.setParseAction(lambda s, l, t: reduce(lambda a, b: a.update(b) ...@@ -134,8 +131,23 @@ NAMED_VALUE_LIST.setParseAction(lambda s, l, t: reduce(lambda a, b: a.update(b)
# below: works only with Python 2.7+ # below: works only with Python 2.7+
#NAMED_VALUE_LIST.setParseAction(lambda s, l, t: {c:a[c] for a in t for c in a.iterkeys()}) #NAMED_VALUE_LIST.setParseAction(lambda s, l, t: {c:a[c] for a in t for c in a.iterkeys()})
VALUE_LIST.setParseAction(lambda s, l, t: [t.asList()]) VALUE_LIST.setParseAction(lambda s, l, t: [t.asList()])
choiceValue.setParseAction(lambda s, l, t: {'Choice': t[0].replace('-', '_'), t[0].replace('-', '_'): t[2]})
valuereference.setParseAction(lambda s, l, t: {'Enum': t[0].replace('-', '_')}) def parseChoiceValue(s, l, t):
''' Parsing CHOICE '''
choice = t[0].replace('-', '_')
return {'Choice': choice, choice: t[2]}
choiceValue.setParseAction(parseChoiceValue)
def parseValueReference(s, l, t):
''' Parsing ENUMERATED Id '''
value = t[0].replace('-', '_')
return {'Enum': value}
valuereference.setParseAction(parseValueReference)
#choiceValue.setParseAction(lambda s, l, t: {'Choice': t[0].replace('-', '_'), t[0].replace('-', '_'): t[2]})
#valuereference.setParseAction(lambda s, l, t: {'Enum': t[0].replace('-', '_')})
namedValue.setParseAction(lambda s, l, t: {t[0].replace('-', '_'): t[1]}) namedValue.setParseAction(lambda s, l, t: {t[0].replace('-', '_'): t[1]})
FloatingPointLiteral.setParseAction(lambda s, l, t: float(t[0])) FloatingPointLiteral.setParseAction(lambda s, l, t: float(t[0]))
INT.setParseAction(lambda s, l, t: int(t[0])) INT.setParseAction(lambda s, l, t: int(t[0]))
......
Markdown is supported
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