Commit 9414451d authored by Maxime Perrotin's avatar Maxime Perrotin
Browse files

Nested states minor bugfixes

parent 29c59e1c
......@@ -90,7 +90,8 @@ def copy_branch(top_level_item):
(term.pos_x, term.pos_y, term.width, term.height).center())
for symbol in symbols:
if (isinstance(symbol, sdlSymbols.State) and [c for c in
symbol.childSymbols() if isinstance(c, sdlSymbols.Input)]):
symbol.childSymbols() if isinstance(c, (sdlSymbols.Input,
sdlSymbols.Connect))]):
term_branch, term_inators = copy_branch(symbol)
branch.extend(term_branch)
res_terminators.extend(term_inators)
......
......@@ -338,12 +338,11 @@ def _input(ast, scene, parent, states):
return inp
@render.register(ogAST.Connect)
def _input(ast, scene, parent, states):
def _connect(ast, scene, parent, states):
''' Add connect symbol from the AST to the scene '''
# Note: PROVIDED clause is not supported
conn = sdlSymbols.Connect(parent, ast=ast)
if conn not in scene.items():
scene.addItem(inp)
scene.addItem(conn)
if not parent:
conn.setPos(ast.pos_x, ast.pos_y)
if ast.transition:
......
......@@ -1363,8 +1363,7 @@ def composite_state(root, parent=None, context=None):
context=comp)
errors.extend(err)
warnings.extend(warn)
comp.composite_states.append(comp)
warnings.append('Inner Composite state detected')
comp.composite_states.append(inner_comp)
elif child.type == lexer.STATE:
# STATE - fills up the 'mapping' structure.
newstate, err, warn = state(child, parent=None, context=comp)
......@@ -1943,11 +1942,10 @@ def state(root, parent, context):
errors.append('State {} is not a composite state and cannot '
'be followed by a connect statement'
.format(state_def.statelist[0]))
else:
conn_part, err, warn = connect_part(child, state_def, context)
state_def.connects.append(conn_part)
warnings.extend(warn)
errors.extend(err)
conn_part, err, warn = connect_part(child, state_def, context)
state_def.connects.append(conn_part)
warnings.extend(warn)
errors.extend(err)
elif child.type == lexer.COMMENT:
state_def.comment, _, _ = end(child)
elif child.type == lexer.HYPERLINK:
......@@ -1980,14 +1978,22 @@ def connect_part(root, parent, context):
errors, warnings = [], []
coord = False
conn = ogAST.Connect()
statename = parent.statelist[0].lower()
try:
statename = parent.statelist[0].lower()
except AttributeError:
# Ignore missing parent/statelist to allow local syntax check
statename = ''
id_token = []
# Keep track of the number of terminator statements follow the input
# useful if we want to render graphs from the SDL model
terms = len(context.terminators)
# Retrieve composite state
nested, = (comp for comp in context.composite_states
if comp.statename == statename)
try:
nested, = (comp for comp in context.composite_states
if comp.statename == statename)
except ValueError:
# Ignore unexisting state - to allow local syntax check
nested = ogAST.CompositeState()
for child in root.getChildren():
if child.type == lexer.CIF:
......@@ -2879,7 +2885,7 @@ def parseSingleElement(elem='', string=''):
'terminator_statement', 'label', 'task', 'procedure_call', 'end',
'text_area', 'state', 'start', 'procedure', 'floating_label',
'connect_part'))
LOG.debug('Parsing string: ' + string + 'with elem ' + elem)
LOG.debug('Parsing string: ' + string + ' with elem ' + elem)
parser = parser_init(string=string)
parser_ptr = getattr(parser, elem)
assert(parser_ptr is not None)
......@@ -2903,7 +2909,7 @@ def parseSingleElement(elem='', string=''):
try:
t, semantic_errors, warnings = backend_ptr(
root=root, parent=None, context=context)
except AttributeError:
except AttributeError as err:
# Syntax checker has no visibility on variables and types
# so we have to discard exceptions sent by e.g. find_variable
pass
......
......@@ -300,6 +300,10 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
return (it for it in self.items() if it.isVisible() and not
isinstance(it, (Cornergrabber, Connection, EditableText)))
@property
def floating_symb(self):
''' Return the top level floating items of a scene '''
return (it for it in self.visible_symb if not it.hasParent)
@property
def states(self):
......@@ -328,8 +332,7 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
@property
def floating_labels(self):
''' Return visible floating label components of the scene '''
return (it for it in self.visible_symb if isinstance(it, Label) and
not it.hasParent)
return (it for it in self.floating_symb if isinstance(it, Label))
@property
......@@ -345,6 +348,16 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
return (it for it in self.states if it.is_composite())
@property
def all_nested_scenes(self):
''' Return all nested scenes, recursively '''
for each in self.visible_symb:
if each.nested_scene:
yield each.nested_scene
for sub in each.nested_scene.all_nested_scenes:
yield sub
def quit_scene(self):
''' Called in case of scene switch (e.g. UP button) '''
pass
......@@ -424,6 +437,24 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
except AttributeError:
pass
def translate_to_origin(self):
'''
Translate all items to coordinate system starting at (0,0),
in order to avoid negative coordinates
'''
try:
min_x = min(item.x() for item in self.floating_symb)
min_y = min(item.y() for item in self.floating_symb)
except ValueError:
# No item in the scene
return
delta_x = -min_x if min_x < 0 else 0
delta_y = -min_y if min_y < 0 else 0
for item in self.floating_symb:
item.moveBy(delta_x, delta_y)
return delta_x, delta_y
def selected_symbols(self):
''' Generate the list of selected symbols (excluding grabbers) '''
for selection in self.selectedItems():
......@@ -582,7 +613,7 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
self.undo_stack.beginMacro('Paste')
for item in new_items:
# Allow pasting inputs when input is selected
# Same for decision answers.
# Same for decision answers and connections
if(isinstance(parent_item, genericSymbols.HorizontalSymbol)
and type(parent_item) == type(item)):
parent_item = parent_item.parentItem()
......@@ -699,6 +730,7 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
def export_branch_to_picture(self, symbol, filename, doc_format):
''' Save a symbol and its followers to a file '''
temp_scene = SDL_Scene()
temp_scene.messages_window = self.messages_window
self.clearSelection()
symbol.select()
try:
......@@ -720,12 +752,8 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
if split:
# Save in multiple files
index = 0
items = (item for item in self.items()
if item.isVisible() and not item.hasParent and
isinstance(item, (State, TextSymbol, Procedure, Start, Label)))
for item in items:
self.export_branch_to_picture(item,
filename + str(index),
for item in self.floating_symb:
self.export_branch_to_picture(item, filename + str(index),
doc_format)
index += 1
......@@ -734,14 +762,22 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
self.clearSelection()
self.clear_focus()
old_brush = self.backgroundBrush()
self.setBackgroundBrush(QtGui.QBrush())
rect = self.itemsBoundingRect()
# Copy in a different scene to get the smallest rectangle
other_scene = SDL_Scene()
other_scene.messages_window = self.messages_window
other_scene.setBackgroundBrush(QtGui.QBrush())
for each in self.floating_symb:
each.select()
self.copy_selected_symbols()
other_scene.paste_symbols()
each.select(False)
rect = other_scene.sceneRect()
# enlarge the rect to fit extra pixels due to antialiasing
rect.adjust(-5, -5, 5, 5)
if doc_format == 'png':
device = QtGui.QImage(rect.size().toSize(),
QtGui.QImage.Format_ARGB32)
QtGui.QImage.Format_ARGB32)
device.fill(Qt.transparent)
elif doc_format == 'svg':
device = QtSvg.QSvgGenerator()
......@@ -758,7 +794,7 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
else:
LOG.error('Output format not supported: ' + doc_format)
painter = QtGui.QPainter(device)
self.render(painter, source=rect)
other_scene.render(painter, source=rect)
try:
device.save(filename)
except AttributeError:
......@@ -766,7 +802,6 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
pass
if painter.isActive():
painter.end()
self.setBackgroundBrush(old_brush)
def clear_focus(self):
''' Clear focus from any item on the scene '''
......@@ -1272,9 +1307,18 @@ class SDL_View(QtGui.QGraphicsView, object):
scene = self.parent_scene[0][0]
else:
scene = self.scene()
# Translate scenes to avoid negative coordinates
for each in scene.all_nested_scenes:
each.translate_to_origin()
# XXX don't translate current scene to avoid a jump of scrollbars
#center = self.viewport().rect().center()
#delta_x, delta_y = scene.translate_to_origin()
#center.setX(center.x() + delta_x)
#center.setY(center.y() + delta_y)
#self.centerOn(center)
pr_raw = scene.get_pr_string()
pr_data = str('\n'.join(pr_raw))
#LOG.debug(str(pr_data))
try:
pr_file.write(pr_data)
pr_file.close()
......
......@@ -351,7 +351,7 @@ state_entry_exit_points
composite_state_body
: (text_area | procedure | composite_state)*
start+ (state | floating_label)*;
start* (state | floating_label)*;
state_part
......
# $ANTLR 3.1.3 Mar 17, 2009 19:23:44 sdl92.g 2014-04-10 09:59:44
# $ANTLR 3.1.3 Mar 17, 2009 19:23:44 sdl92.g 2014-04-22 15:38:14
import sys
from antlr3 import *
......
This diff is collapsed.
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