Commit 8208ca61 authored by Maxime Perrotin's avatar Maxime Perrotin
Browse files

Fixed png export from command line

parent a753d2c6
...@@ -252,11 +252,15 @@ class Channel(Connection): ...@@ -252,11 +252,15 @@ class Channel(Connection):
def end_point(self): def end_point(self):
''' Compute connection end point - redefined function ''' ''' Compute connection end point - redefined function '''
# Arrow always bumps at the screen edge # Arrow always bumps at the screen edge
view = self.scene().views()[0] try:
view_pos = view.mapToScene( view = self.scene().views()[0]
view_pos = view.mapToScene(
view.viewport().geometry()).boundingRect().topLeft() view.viewport().geometry()).boundingRect().topLeft()
scene_pos_x = self.mapFromScene(view_pos).x() scene_pos_x = self.mapFromScene(view_pos).x()
return QPointF(scene_pos_x, self.start_point.y()) return QPointF(scene_pos_x, self.start_point.y())
except IndexError:
# In case there is no view (e.g. Export PNG from cmd line)
return QPointF(self.start_point.x() - 50, self.start_point.y())
class Controlpoint(QGraphicsPathItem, object): class Controlpoint(QGraphicsPathItem, object):
......
...@@ -47,6 +47,7 @@ def add_to_scene(item, scene): ...@@ -47,6 +47,7 @@ def add_to_scene(item, scene):
if type(item) in scene.allowed_symbols: if type(item) in scene.allowed_symbols:
scene.addItem(item) scene.addItem(item)
else: else:
#print type(item), scene.allowed_symbols, scene.context
raise TypeError('This symbol does not fit the current scene') raise TypeError('This symbol does not fit the current scene')
...@@ -129,10 +130,10 @@ def _automaton(ast, scene): ...@@ -129,10 +130,10 @@ def _automaton(ast, scene):
new_state = render(state, scene=scene, states=ast.states, new_state = render(state, scene=scene, states=ast.states,
terminators=ast.parent.terminators) terminators=ast.parent.terminators)
if new_state.nested_scene: if new_state.nested_scene:
if str(new_state).lower() in nested_states: if unicode(new_state).lower() in nested_states:
new_state.nested_scene = None new_state.nested_scene = None
else: else:
nested_states.append(str(new_state).lower()) nested_states.append(unicode(new_state).lower())
except TypeError: except TypeError:
# Discard terminators (see _state function for explanation) # Discard terminators (see _state function for explanation)
pass pass
......
...@@ -585,6 +585,8 @@ class Symbol(QObject, QGraphicsPathItem, object): ...@@ -585,6 +585,8 @@ class Symbol(QObject, QGraphicsPathItem, object):
def __str__(self): def __str__(self):
''' Print the text inside the symbol ''' ''' Print the text inside the symbol '''
import traceback
print traceback.print_stack()
raise TypeError('Use unicode() not str()') raise TypeError('Use unicode() not str()')
#return str(self.text) or 'no_name' #return str(self.text) or 'no_name'
......
...@@ -751,6 +751,9 @@ class Procedure(object): ...@@ -751,6 +751,9 @@ class Procedure(object):
self.comment = None self.comment = None
# Set of symbols contained in the procedure (type Automaton) # Set of symbols contained in the procedure (type Automaton)
self.content = Automaton(parent=self) self.content = Automaton(parent=self)
# input/output signal lists - unused but for context information
self.input_signals = []
self.output_signals = []
class Process(object): class Process(object):
......
...@@ -1366,7 +1366,7 @@ def expression(root, context): ...@@ -1366,7 +1366,7 @@ def expression(root, context):
elif isinstance(expr, (ogAST.ExprMod, ogAST.ExprRem)): elif isinstance(expr, (ogAST.ExprMod, ogAST.ExprRem)):
attrs = {'Min': right.Min, 'Max': right.Max} attrs = {'Min': right.Min, 'Max': right.Max}
expr.exprType = type('Mod', (basic,), attrs) expr.exprType = type('Mod', (basic,), attrs)
except ValueError: except (ValueError, AttributeError):
errors.append('Check that all your numerical data types have ' errors.append('Check that all your numerical data types have '
'a range constraint') 'a range constraint')
...@@ -2533,7 +2533,7 @@ def outputbody(root, context): ...@@ -2533,7 +2533,7 @@ def outputbody(root, context):
warnings.extend(warn) warnings.extend(warn)
elif child.type == lexer.TO: elif child.type == lexer.TO:
pass pass
# TODO: better support of TO primitive # TODO: better support of TO primitive
else: else:
warnings.append('Unsupported output body type:' + warnings.append('Unsupported output body type:' +
str(child.type)) str(child.type))
...@@ -3298,7 +3298,16 @@ def parseSingleElement(elem='', string=''): ...@@ -3298,7 +3298,16 @@ def parseSingleElement(elem='', string=''):
assert(elem in ('input_part', 'output', 'decision', 'alternative_part', assert(elem in ('input_part', 'output', 'decision', 'alternative_part',
'terminator_statement', 'label', 'task', 'procedure_call', 'end', 'terminator_statement', 'label', 'task', 'procedure_call', 'end',
'text_area', 'state', 'start', 'procedure', 'floating_label', 'text_area', 'state', 'start', 'procedure', 'floating_label',
'connect_part', 'process_definition')) 'connect_part', 'process_definition', 'proc_start', 'state_start'))
# Create a dummy context, needed to place context data
if elem == 'proc_start':
elem = 'start'
context = ogAST.Procedure()
elif elem == 'state_start':
elem = 'start'
context = ogAST.CompositeState()
else:
context = ogAST.Process()
LOG.debug('Parsing string: ' + string + ' with elem ' + elem) LOG.debug('Parsing string: ' + string + ' with elem ' + elem)
parser = parser_init(string=string) parser = parser_init(string=string)
parser_ptr = getattr(parser, elem) parser_ptr = getattr(parser, elem)
...@@ -3318,12 +3327,12 @@ def parseSingleElement(elem='', string=''): ...@@ -3318,12 +3327,12 @@ def parseSingleElement(elem='', string=''):
root = r.tree root = r.tree
root.token_stream = parser.getTokenStream() root.token_stream = parser.getTokenStream()
backend_ptr = eval(elem) backend_ptr = eval(elem)
# Create a dummy process, needed to place context data
context = ogAST.Process()
try: try:
t, semantic_errors, warnings = backend_ptr( t, semantic_errors, warnings = backend_ptr(
root=root, parent=None, context=context) root=root, parent=None, context=context)
except AttributeError: except AttributeError as err:
print str(err)
print (traceback.format_exc())
# Syntax checker has no visibility on variables and types # Syntax checker has no visibility on variables and types
# so we have to discard exceptions sent by e.g. find_variable # so we have to discard exceptions sent by e.g. find_variable
pass pass
......
...@@ -633,9 +633,9 @@ class SDL_Scene(QtGui.QGraphicsScene, object): ...@@ -633,9 +633,9 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
Clipboard.copy(self.selected_symbols()) Clipboard.copy(self.selected_symbols())
except TypeError as error_msg: except TypeError as error_msg:
try: try:
self.messages_window.addItem(str(error_msg)) self.messages_window.addItem(unicode(error_msg))
except AttributeError: except AttributeError:
LOG.error(str(error_msg)) LOG.error(unicode(error_msg))
raise raise
def cut_selected_symbols(self): def cut_selected_symbols(self):
...@@ -662,7 +662,11 @@ class SDL_Scene(QtGui.QGraphicsScene, object): ...@@ -662,7 +662,11 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
try: try:
new_items = Clipboard.paste(parent_item, self) new_items = Clipboard.paste(parent_item, self)
except TypeError as error_msg: except TypeError as error_msg:
self.messages_window.addItem(str(error_msg)) LOG.error(str(error_msg))
try:
self.messages_window.addItem(str(error_msg))
except AttributeError:
pass
else: else:
self.undo_stack.beginMacro('Paste') self.undo_stack.beginMacro('Paste')
for item in new_items: for item in new_items:
...@@ -685,28 +689,6 @@ class SDL_Scene(QtGui.QGraphicsScene, object): ...@@ -685,28 +689,6 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
self.undo_stack.endMacro() self.undo_stack.endMacro()
self.refresh() self.refresh()
# def get_pr_string(self):
# ''' Parse the graphical items and returns a PR string '''
# pr_data = deque()
# for each in self.processes:
# pr_data.append(each.PR())
#
# for item in chain(self.texts, self.procs, self.start):
# pr_data.append(item.PR())
# for item in self.floating_labels:
# pr_data.append(item.PR_floating())
# composite = set(self.composite_states.keys())
# for item in self.states:
# if item.is_composite():
# try:
# composite.remove(unicode(item).lower())
# pr_data.appendleft(item.parse_composite_state())
# except KeyError:
# pass
# pr_data.append(item.PR_state())
#
# return list(pr_data)
def sdl_to_statechart(self): def sdl_to_statechart(self):
''' Create a graphviz representation of the SDL model ''' ''' Create a graphviz representation of the SDL model '''
pr_raw = Pr.parse_scene(self) pr_raw = Pr.parse_scene(self)
...@@ -723,7 +705,7 @@ class SDL_Scene(QtGui.QGraphicsScene, object): ...@@ -723,7 +705,7 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
def export_branch_to_picture(self, symbol, filename, doc_format): def export_branch_to_picture(self, symbol, filename, doc_format):
''' Save a symbol and its followers to a file ''' ''' Save a symbol and its followers to a file '''
temp_scene = SDL_Scene() temp_scene = SDL_Scene(context=self.context)
temp_scene.messages_window = self.messages_window temp_scene.messages_window = self.messages_window
self.clearSelection() self.clearSelection()
symbol.select() symbol.select()
...@@ -746,7 +728,10 @@ class SDL_Scene(QtGui.QGraphicsScene, object): ...@@ -746,7 +728,10 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
# Save in multiple files # Save in multiple files
index = 0 index = 0
for item in self.floating_symb: for item in self.floating_symb:
self.export_branch_to_picture(item, filename + str(index), LOG.info('Saving {ext} file: {name}.{ext}'
.format(ext=doc_format, name=filename + '-' + str(index)))
self.export_branch_to_picture(item,
filename + '-' + str(index),
doc_format) doc_format)
index += 1 index += 1
...@@ -756,12 +741,15 @@ class SDL_Scene(QtGui.QGraphicsScene, object): ...@@ -756,12 +741,15 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
self.clearSelection() self.clearSelection()
self.clear_focus() self.clear_focus()
# Copy in a different scene to get the smallest rectangle # Copy in a different scene to get the smallest rectangle
other_scene = SDL_Scene() other_scene = SDL_Scene(context=self.context)
other_scene.messages_window = self.messages_window other_scene.messages_window = self.messages_window
other_scene.setBackgroundBrush(QtGui.QBrush()) other_scene.setBackgroundBrush(QtGui.QBrush())
for each in self.floating_symb: for each in self.floating_symb:
each.select() each.select()
self.copy_selected_symbols() try:
self.copy_selected_symbols()
except AttributeError as err:
LOG.error(str(err))
other_scene.paste_symbols() other_scene.paste_symbols()
each.select(False) each.select(False)
rect = other_scene.sceneRect() rect = other_scene.sceneRect()
...@@ -1796,9 +1784,9 @@ def parse(files): ...@@ -1796,9 +1784,9 @@ def parse(files):
LOG.info('Checking ' + str(files)) LOG.info('Checking ' + str(files))
ast, warnings, errors = ogParser.parse_pr(files=files) ast, warnings, errors = ogParser.parse_pr(files=files)
LOG.info( LOG.info('Parsing complete. '
'Parsing complete. Summary, found %d warnings and %d errors' % (len(warnings), len(errors)) 'Summary, found {} warnings and {} errors'
) .format(len(warnings), len(errors)))
for warning in warnings: for warning in warnings:
LOG.warning(warning[0]) LOG.warning(warning[0])
for error in errors: for error in errors:
...@@ -1828,11 +1816,14 @@ def generate(process, options): ...@@ -1828,11 +1816,14 @@ def generate(process, options):
LOG.error('LLVM IR generation failed') LOG.error('LLVM IR generation failed')
def export(process, options): def export(ast, options):
''' Export process ''' ''' Export process '''
# Qt must be initialized before using SDL_Scene # Qt must be initialized before using SDL_Scene
init_qt() init_qt()
# Initialize the clipboard
Clipboard.CLIPBOARD = SDL_Scene(context='clipboard')
export_fmt = [] export_fmt = []
if options.png: if options.png:
export_fmt.append('png') export_fmt.append('png')
...@@ -1843,15 +1834,43 @@ def export(process, options): ...@@ -1843,15 +1834,43 @@ def export(process, options):
if not export_fmt: if not export_fmt:
return return
process, = ast.processes
try:
syst, = ast.systems
block, = syst.blocks
if block.processes[0].referenced:
LOG.debug('Process is referenced, fixing')
block.processes = [process]
except ValueError:
# No System/Block hierarchy, creating single block
block = ogAST.Block()
block.processes = [process]
name = process.processName name = process.processName
scene = SDL_Scene(context='process') scene = SDL_Scene(context='block')
scene.render_everything(process) scene.render_everything(block)
# Update connections, placements: # Update connections, placements:
scene.refresh() scene.refresh()
for doc_fmt in export_fmt: scenes = [scene]
LOG.info('Saving {ext} file: {name}.{ext}'.format(ext=doc_fmt, name=name)) def find_nested_scenes(top):
scene.export_img(name, doc_format=doc_fmt, split=options.split) ''' Find all scenes (procedures, states, processes...) '''
for each in top.visible_symb:
if each.nested_scene:
yield each.nested_scene
for deep in find_nested_scenes(each.nested_scene):
yield deep
for each in find_nested_scenes(scene):
if any(each.visible_symb):
scenes.append(each)
for idx, diagram in enumerate(scenes):
for doc_fmt in export_fmt:
LOG.info('Saving {ext} file: {name}.{ext}'
.format(ext=doc_fmt, name=name+str(idx)))
diagram.export_img(name+str(idx),
doc_format=doc_fmt,
split=options.split)
def cli(options): def cli(options):
...@@ -1867,7 +1886,7 @@ def cli(options): ...@@ -1867,7 +1886,7 @@ def cli(options):
return 1 return 1
if options.png or options.pdf or options.svg: if options.png or options.pdf or options.svg:
export(ast.processes[0], options) export(ast, options)
if options.toAda or options.llvm: if options.toAda or options.llvm:
if not errors: if not errors:
...@@ -1879,7 +1898,7 @@ def cli(options): ...@@ -1879,7 +1898,7 @@ def cli(options):
def init_qt(): def init_qt():
''' Initialize QT ''' ''' Initialize Qt '''
app = QtGui.QApplication.instance() app = QtGui.QApplication.instance()
if app is None: if app is None:
app = QtGui.QApplication(sys.argv) app = QtGui.QApplication(sys.argv)
......
...@@ -846,6 +846,7 @@ class ProcedureStart(Start): ...@@ -846,6 +846,7 @@ class ProcedureStart(Start):
# Define reserved keywords for the syntax highlighter # Define reserved keywords for the syntax highlighter
blackbold = SDL_BLACKBOLD blackbold = SDL_BLACKBOLD
redbold = SDL_REDBOLD redbold = SDL_REDBOLD
common_name = 'proc_start'
def set_shape(self, width, height): def set_shape(self, width, height):
''' Compute the polygon to fit in width, height ''' ''' Compute the polygon to fit in width, height '''
...@@ -863,6 +864,7 @@ class StateStart(Start): ...@@ -863,6 +864,7 @@ class StateStart(Start):
''' Composite states can have several named START symbols ''' ''' Composite states can have several named START symbols '''
has_text_area = True has_text_area = True
is_singleton = False is_singleton = False
common_name = 'state_start'
def __unicode__(self): def __unicode__(self):
''' Return the state entry point ''' ''' Return the state entry point '''
......
...@@ -11,8 +11,12 @@ test-ada: ...@@ -11,8 +11,12 @@ test-ada:
#gnatbind -n trafficlight.ali #gnatbind -n trafficlight.ali
#gnatlink -o testcase test.o trafficlight.ali -lgnat -lm #gnatlink -o testcase test.o trafficlight.ali -lgnat -lm
test-export:
../../../opengeode.py --png --pdf --svg trafficlight.pr system_structure.pr
../../../opengeode.py --png --pdf --svg --split trafficlight.pr system_structure.pr
coverage: coverage:
coverage run -p ../../../opengeode.py trafficlight.pr system_structure.pr --toAda coverage run -p ../../../opengeode.py trafficlight.pr system_structure.pr --toAda
clean: clean:
rm -rf *.adb *.ads *.pyc runSpark.sh spark.idx *.o *.ali gnat.cfg examiner bin *.wrn *.gpr test rm -rf *.adb *.ads *.pyc runSpark.sh spark.idx *.o *.ali gnat.cfg examiner bin *.wrn *.gpr *.pdf *.svg *.png test
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