Commit 091ca049 authored by Maxime Perrotin's avatar Maxime Perrotin

Add preliminary support of condition boxes

parent 3108bc83
...@@ -38,6 +38,7 @@ from mscmessage import MscMessage ...@@ -38,6 +38,7 @@ from mscmessage import MscMessage
from mscdocument import MscDocument from mscdocument import MscDocument
from mscvisitor import MscVisitor from mscvisitor import MscVisitor
from msctimer import MscTimer from msctimer import MscTimer
from msccondition import MscCondition
from mscinstancekind import MscInstanceKind from mscinstancekind import MscInstanceKind
from mscmessagedecl import MscMessageDecl from mscmessagedecl import MscMessageDecl
import mscregexp as MscRegExp import mscregexp as MscRegExp
...@@ -46,4 +47,4 @@ __version__ = 1.0 ...@@ -46,4 +47,4 @@ __version__ = 1.0
__all__ = ['MscElement', 'MscEvent', 'MscTimer', 'MscInstanceKind', __all__ = ['MscElement', 'MscEvent', 'MscTimer', 'MscInstanceKind',
'MscMessageDecl', 'MscRegExp', 'MscInstance', 'MscMessage', 'MscMessageDecl', 'MscRegExp', 'MscInstance', 'MscMessage',
'BasicMsc', 'MscDocument', 'MscVisitor'] 'BasicMsc', 'MscDocument', 'MscVisitor', 'MscCondition']
...@@ -161,8 +161,6 @@ class CoreToText(MscVisitor): ...@@ -161,8 +161,6 @@ class CoreToText(MscVisitor):
if element.instanceSender() == self.instance: if element.instanceSender() == self.instance:
receiverName = element.instanceReceiver().getName() receiverName = element.instanceReceiver().getName()
# print element.instanceReceiver()
# print element.parent()
if element.instanceReceiver() == element.parent(): # ENV if element.instanceReceiver() == element.parent(): # ENV
receiverName = u'env' receiverName = u'env'
...@@ -192,6 +190,11 @@ class CoreToText(MscVisitor): ...@@ -192,6 +190,11 @@ class CoreToText(MscVisitor):
self._result = timer + " {}{}\n".format(element.getName(), self._result = timer + " {}{}\n".format(element.getName(),
self.end(element)) self.end(element))
def visitorMscCondition(self, element):
u""" Export MscCondition to text """
self._result = "condition '{}'{}\n".format(element.getName(),
self.end(element))
def end(self, element): def end(self, element):
u""" u"""
Return "end" token of element. Return "end" token of element.
...@@ -210,4 +213,4 @@ class CoreToText(MscVisitor): ...@@ -210,4 +213,4 @@ class CoreToText(MscVisitor):
# print lines # print lines
for i in lines[:len(lines) - 1]: for i in lines[:len(lines) - 1]:
text = text + u'{}{}\n'.format(self.INDENT, i) text = text + u'{}{}\n'.format(self.INDENT, i)
return text return text
\ No newline at end of file
#******************************************************************************
#
# TASTE Msc Diagram Editor
# http://taste.tuxfamily.org/
#
# This file is part of TASTE Msc Editor.
#
# TASTE Msc Diagram Editor is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# TASTE Msc Diagram Editor is distributed in the hope that it will be
# useful,(but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with TASTE Msc Diagram Editor. If not, see
# <http://www.gnu.org/licenses/>.
#
# Author: Angel Esquinas <aesquina@datsi.fi.upm.es>
# Author of this module: Maxime Perrotin maxime.perrotin@esa.int
#
# Copyright (c) 2014 European Space Agency
#
#******************************************************************************
u"""
The :class:`msccore.MscCondition` class represents a Condition within the MSC.
:class:`msccore.MscCondition`
"""
from mscelement import MscElement
class MscCondition(MscElement):
u"""
:param unicode name: Text of the condition
:param int orderPos: Absolute pos of timer, when used as event.
:param parent:
:type parent: PySide.QtCore.QObject
"""
TYPE = u"Condition"
def __init__(self, name, orderPos=0, parent=None):
'''
Constructor
'''
super(MscCondition, self).__init__(name, parent, self.TYPE)
self.setAbsPos(orderPos)
def delete(self):
""" Delete is the destructor of MscCondition
The signal 'deleted' is emitted before destroy himself.
"""
self.deleted.emit(self)
self.deleteLater()
#Order/Graphical Pos
def setAbsPos(self, pos):
self._absPos = pos
def absPos(self):
return self._absPos
def accept(self, visitor):
u""" Visitor Pattern"""
visitor.visitorMscCondition(self)
def __str__(self):
return """<<{0}:{1}. Pos {3}>>\n
comment: {4}""".format(self.TYPE, self.getName(),
self.absPos(), self.comment())
...@@ -175,6 +175,7 @@ class MscInstance(MscElement): ...@@ -175,6 +175,7 @@ class MscInstance(MscElement):
* :class:`~msccore.MscMessage` * :class:`~msccore.MscMessage`
* :class:`~msccore.MscTimer` * :class:`~msccore.MscTimer`
* :class:`~msccore.MscCondition`
The created event is returned. The created event is returned.
...@@ -251,6 +252,7 @@ class MscInstance(MscElement): ...@@ -251,6 +252,7 @@ class MscInstance(MscElement):
* :class:`~msccore.MscMessage` * :class:`~msccore.MscMessage`
* :class:`~msccore.MscTimer` * :class:`~msccore.MscTimer`
* :class:`~msccore.MscCondition`
The :meth:`MscElement._contentsChanged` function is called to indicate The :meth:`MscElement._contentsChanged` function is called to indicate
that the content of this basic MSC are changed. that the content of this basic MSC are changed.
......
...@@ -25,10 +25,11 @@ ...@@ -25,10 +25,11 @@
# #
#****************************************************************************** #******************************************************************************
from mscGraphTimer import MscGraphTimer from mscGraphTimer import MscGraphTimer
from mscGraphCondition import MscGraphCondition
from mscGraphInstance import MscGraphInstance from mscGraphInstance import MscGraphInstance
from mscGraphMessage import MscGraphMessage from mscGraphMessage import MscGraphMessage
from mscGraphBMSC import MscGraphBMSC from mscGraphBMSC import MscGraphBMSC
from mscGraphBasicMSCScene import MscGraphBasicMSCScene from mscGraphBasicMSCScene import MscGraphBasicMSCScene
__all__ = ['MscGraphInstance', 'MscGraphBMSC', 'MscGraphMessage', __all__ = ['MscGraphInstance', 'MscGraphBMSC', 'MscGraphMessage',
'MscGraphTimer', 'MscGraphBasicMSCScene'] 'MscGraphTimer', 'MscGraphBasicMSCScene', 'MscGraphCondition']
...@@ -34,6 +34,7 @@ from PySide.QtGui import QMenu ...@@ -34,6 +34,7 @@ from PySide.QtGui import QMenu
from mscGraphInstance import MscGraphInstance from mscGraphInstance import MscGraphInstance
from mscGraphTimer import MscGraphTimer from mscGraphTimer import MscGraphTimer
from mscGraphCondition import MscGraphCondition
from mscGraphBMSC import MscGraphBMSC from mscGraphBMSC import MscGraphBMSC
from mscGraphMessage import MscGraphMessage from mscGraphMessage import MscGraphMessage
from mscgraphics import MscGraphComment from mscgraphics import MscGraphComment
...@@ -45,7 +46,7 @@ logger = logging.getLogger(__name__) ...@@ -45,7 +46,7 @@ logger = logging.getLogger(__name__)
class MscGraphBasicMSCScene(QGraphicsScene): class MscGraphBasicMSCScene(QGraphicsScene):
# Mode of the scene # Mode of the scene
(MoveItem, InsertInstance, InsertMessage, InsertTimer, (MoveItem, InsertInstance, InsertMessage, InsertTimer,
InsertComment) = range(5) InsertComment, InsertCondition) = range(6)
# Signals # Signals
itemInserted = Signal(MscGraphItem) itemInserted = Signal(MscGraphItem)
...@@ -226,6 +227,22 @@ class MscGraphBasicMSCScene(QGraphicsScene): ...@@ -226,6 +227,22 @@ class MscGraphBasicMSCScene(QGraphicsScene):
comment.delete() comment.delete()
self.removeItem(comment) self.removeItem(comment)
#--------------- Conditions
def addCondition(self, instance, pos=None, label=''):
u"""
Add new "condition" to the scene and position it in "pos" if any
"""
condition = MscGraphCondition(label=label, parent=self.bmsc())
instance.addEvent(condition)
if pos is not None:
condition.setPos(pos)
condition.itemSelected.connect(self.itemSelected)
self.itemInserted.emit(condition)
return condition
def removeCondition(self, condition):
condition.delete()
self.removeItem(condition)
#************************************************************************** #**************************************************************************
# Actions # Actions
#************************************************************************** #**************************************************************************
...@@ -291,6 +308,15 @@ class MscGraphBasicMSCScene(QGraphicsScene): ...@@ -291,6 +308,15 @@ class MscGraphBasicMSCScene(QGraphicsScene):
self.addTimer(instance, self.addTimer(instance,
instance.mapFromScene(mouseEvent.scenePos())) instance.mapFromScene(mouseEvent.scenePos()))
# Click to add a Condition
elif self._sceneMode == self.InsertCondition:
items = self.items(mouseEvent.scenePos())
if len(items) > 0:
instance = items[0]
if isinstance(instance, MscGraphInstance):
self.addCondition(instance,
instance.mapFromScene(mouseEvent.scenePos()))
# Click to add Comment # Click to add Comment
elif self._sceneMode == self.InsertComment: elif self._sceneMode == self.InsertComment:
items = self.items(mouseEvent.scenePos()) items = self.items(mouseEvent.scenePos())
......
#******************************************************************************
#
# TASTE Msc Diagram Editor
# http://taste.tuxfamily.org/
#
# This file is part of TASTE Msc Editor.
#
# TASTE Msc Diagram Editor is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# TASTE Msc Diagram Editor is distributed in the hope that it will be
# useful,(but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with TASTE Msc Diagram Editor. If not, see
# <http://www.gnu.org/licenses/>.
#
# Author: Angel Esquinas <aesquina@datsi.fi.upm.es>
# Author of this module: Maxime Perrotin <maxime.perrotin@esa.int>
#
# Copyright (c) 2012 European Space Agency
#
#******************************************************************************
from PySide.QtGui import QPainterPath, QPen
from PySide.QtCore import Qt, Slot
from msccore import MscCondition
from mscgraphics import MscGraphItem
from mscgraphics import MscLabelable
class MscGraphCondition(MscGraphItem):
'''
Class that draws a Condition symbol
'''
DefaultWidth = 100
DefaultHeight = 100
def __init__(self, data=None, y=0, label=None, parent=None):
u"""
Initize
"""
super(MscGraphCondition, self).__init__(parent)
self.setFlag(super(MscGraphCondition, self).ItemIsMovable, True)
if label is None:
label = "Condition"
if data is None:
self.setMscData(MscCondition(name=label))
else:
self.setMscData(data)
self.initilizeGraphics()
self.addLabel()
# Signal when selected
self.setSignalWhenSelected(True)
# Create Path
self.createPath()
#**************************************************************************
# Data Functions
#**************************************************************************
@Slot(str)
def setDataName(self, name):
self.mscData().setName(name)
@Slot()
def readMscData(self):
self.updateLabel()
def delete(self):
u"""
Delete the MscGraphCondition.
Reimplemented from MscGraphItem.
"""
# Ask parentItem to delete the event
# NOTE: This could be implemented with signals
parent = self.parentItem()
if parent != None:
parent.deleteMscEvent(self)
#**************************************************************************
# Graphical Text
#**************************************************************************
def addLabel(self):
self.label = MscLabelable(self.mscData().getName(), self)
self.updateLabelPosition()
self.label.labelChanged.connect(self.setDataName)
def updateLabel(self):
self.label.setTextLabel(self.mscData().getName())
def updateLabelPosition(self):
self.label.setPos(self.width + 10,
-self.label.boundingRect().height() / 2)
#**************************************************************************
# Item Change
#**************************************************************************
def limitsOfItem(self, value):
u""" Check the limits of the event area of parent """
parent = self.parentItem()
if parent == None:
return value
upperY = parent.upperLimit().y()
bottomY = parent.bottomLimit().y()
valueY = value.y()
if valueY < upperY:
valueY = upperY
value.setX(self.pos().x())
value.setY(valueY)
return value
def itemChange(self, change, value):
if (change == super(MscGraphCondition, self).ItemPositionChange):
value = self.limitsOfItem(value)
elif (change == super(MscGraphCondition, self).ItemPositionHasChanged):
self.mscData().setAbsPos(self.mapToScene(0, 0).y())
self.yHasChanged.emit(self)
return MscGraphItem.itemChange(self, change, value)
#**************************************************************************
# Paint Functions
#**************************************************************************
def initilizeGraphics(self):
self.color = Qt.blue
self.pen = QPen(self.color, 1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
def updateBounding(self):
u"""
Update internal drawing coordinates
"""
self.prepareGeometryChange()
rect = self.path.boundingRect()
self.drawOriginX = rect.x()
self.drawOriginY = rect.y()
self.width = rect.width()
self.height = rect.height()
self.updateLabelPosition()
def createPath(self):
u"""
Create the path of Timer
"""
self.path = QPainterPath()
self.path.addRect(-self.DefaultWidth / 2, 0,
self.DefaultWidth, self.DefaultHeight)
# Set correct values of x, y, width and height
self.updateBounding()
def paint(self, painter, option, widget):
painter.setPen(self.pen)
painter.drawPath(self.path)
...@@ -36,6 +36,7 @@ from PySide.QtCore import QPointF ...@@ -36,6 +36,7 @@ from PySide.QtCore import QPointF
from msccore import MscVisitor from msccore import MscVisitor
from msccore import MscMessage from msccore import MscMessage
from msccore import MscTimer from msccore import MscTimer
from msccore import MscCondition
from msccore import MscDocument from msccore import MscDocument
from mscgraphics import MscGraphBMSC from mscgraphics import MscGraphBMSC
...@@ -43,6 +44,7 @@ from mscgraphics import MscGraphBasicMSCScene ...@@ -43,6 +44,7 @@ from mscgraphics import MscGraphBasicMSCScene
from mscgraphics import MscGraphInstance from mscgraphics import MscGraphInstance
from mscgraphics import MscGraphMessage from mscgraphics import MscGraphMessage
from mscgraphics import MscGraphTimer from mscgraphics import MscGraphTimer
from mscgraphics import MscGraphCondition
def coreToGraphics(document): def coreToGraphics(document):
...@@ -145,28 +147,22 @@ class CoreToGraphicsVisitor(MscVisitor): ...@@ -145,28 +147,22 @@ class CoreToGraphicsVisitor(MscVisitor):
found = False found = False
for e in graph.mscData().events(): for e in graph.mscData().events():
#print e.element
event = e.element event = e.element
# Messages # Messages
if isinstance(e.element, MscMessage): if isinstance(event, MscMessage):
coreMsg = e.element coreMsg = event
#msgHash = coreMsg.hash()
#print msgHash
# Look for the message in the table # Look for the message in the table
elem = self.incompleteMsg.pop(coreMsg, None) elem = self.incompleteMsg.pop(coreMsg, None)
if elem != None: if elem is not None:
found = True found = True
# print 'FOUND: {0}'.format(elem)
else: else:
y = (spaceY * (coreMsg.absPos() - 1)) + startY y = (spaceY * (coreMsg.absPos() - 1)) + startY
# print "PUNTO Y: {}".format(y)
elem = MscGraphMessage(graph, graph, data=coreMsg) elem = MscGraphMessage(graph, graph, data=coreMsg)
elem.setPos(elem.pos().x(), y) elem.setPos(elem.pos().x(), y)
if found: if found:
#print "FOUND {}".format(elem)
if coreMsg.instanceSender() == graph.mscData(): if coreMsg.instanceSender() == graph.mscData():
elem.setStartInstance(graph) elem.setStartInstance(graph)
else: else:
...@@ -188,10 +184,9 @@ class CoreToGraphicsVisitor(MscVisitor): ...@@ -188,10 +184,9 @@ class CoreToGraphicsVisitor(MscVisitor):
self.incompleteMsg[coreMsg] = elem self.incompleteMsg[coreMsg] = elem
# Timers # Timers
if isinstance(event, MscTimer): elif isinstance(event, MscTimer):
y = (spaceY * (event.absPos() - 1)) + startY y = (spaceY * (event.absPos() - 1)) + startY
# print "PUNTO Y: {}".format(y)
timer = MscGraphTimer(e.element) timer = MscGraphTimer(e.element)
scene.addTimer2(graph, timer) scene.addTimer2(graph, timer)
...@@ -205,5 +200,22 @@ class CoreToGraphicsVisitor(MscVisitor): ...@@ -205,5 +200,22 @@ class CoreToGraphicsVisitor(MscVisitor):
pos=pos) pos=pos)
c.setCommentText(e.element.comment()) c.setCommentText(e.element.comment())
# Conditions
elif isinstance(event, MscCondition):
y = (spaceY * (event.absPos() - 1)) + startY
condition = MscGraphCondition(event)
scene.addCondition(graph, condition)
condition.setPos(graph.mapFromScene(timer.pos().x(), y))
if event.comment() != u"":
trect = (condition.childrenBoundingRect()
| condition.boundingRect())
pos = QPointF(trect.width() + 10, 0)
pos = elem.mapToScene(pos)
c = scene().addComment(item=condition,
pos=pos)
c.setCommentText(event.comment())
def obtainResult(self): def obtainResult(self):
return self.scenes return self.scenes
...@@ -55,6 +55,7 @@ class MscLexer: ...@@ -55,6 +55,7 @@ class MscLexer:
reserved = { reserved = {
#'begin': 'BEGIN', #'begin': 'BEGIN',
'comment': 'COMMENT', 'comment': 'COMMENT',
'condition': 'CONDITION',
'data': 'DATA', 'data': 'DATA',
'endinstance': 'ENDINSTANCE', 'endinstance': 'ENDINSTANCE',
'endmsc': 'ENDMSC', 'endmsc': 'ENDMSC',
......
...@@ -30,6 +30,7 @@ import logging ...@@ -30,6 +30,7 @@ import logging
import msccore import msccore
from msccore import BasicMsc from msccore import BasicMsc
from msccore import MscTimer from msccore import MscTimer
from msccore import MscCondition
from msccore import MscDocument from msccore import MscDocument
from msccore import MscInstance from msccore import MscInstance
from msccore import MscInstanceKind from msccore import MscInstanceKind
...@@ -567,3 +568,8 @@ class MscMaker(object): ...@@ -567,3 +568,8 @@ class MscMaker(object):
timer = MscTimer(name=name, typeTimer=tt) timer = MscTimer(name=name, typeTimer=tt)
self.newEvent(timer) self.newEvent(timer)
#TODO: Return Error if scope if not instance #TODO: Return Error if scope if not instance
def newCondition(self, name):
u"""Add new Condition to instance in scope"""
condition = MscCondition(name=name)
self.newEvent(condition)
...@@ -272,7 +272,8 @@ class MscParser: ...@@ -272,7 +272,8 @@ class MscParser:
def p_event(self, p): def p_event(self, p):
# Auxiliar rule for have all events together # Auxiliar rule for have all events together
u"""event : message_event u"""event : message_event
| timer_statement""" | timer_statement
| condition_statement"""
#************************************************************************** #**************************************************************************
# 4.2 Instance # 4.2 Instance
...@@ -417,6 +418,13 @@ class MscParser: ...@@ -417,6 +418,13 @@ class MscParser:
u"""timeout : TIMEOUT NAME""" u"""timeout : TIMEOUT NAME"""
self.makerMsc.newTimer(p[2], self.makerMsc.Timeout) self.makerMsc.newTimer(p[2], self.makerMsc.Timeout)
#**************************************************************************
# X.X Conditions (TODO CHECK CHAPTER IN MSC STANDARD)
#**************************************************************************
def p_condition(self, p):
u"""condition_statement : CONDITION 'NAME'"""
self.makerMsc.newCondition(p[2], self.makerMsc.Condition)
#************************************************************************* #*************************************************************************
# 5.2 Syntax interface to external data languages # 5.2 Syntax interface to external data languages
#************************************************************************* #*************************************************************************
......
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