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
from mscdocument import MscDocument
from mscvisitor import MscVisitor
from msctimer import MscTimer
from msccondition import MscCondition
from mscinstancekind import MscInstanceKind
from mscmessagedecl import MscMessageDecl
import mscregexp as MscRegExp
......@@ -46,4 +47,4 @@ __version__ = 1.0
__all__ = ['MscElement', 'MscEvent', 'MscTimer', 'MscInstanceKind',
'MscMessageDecl', 'MscRegExp', 'MscInstance', 'MscMessage',
'BasicMsc', 'MscDocument', 'MscVisitor']
'BasicMsc', 'MscDocument', 'MscVisitor', 'MscCondition']
......@@ -161,8 +161,6 @@ class CoreToText(MscVisitor):
if element.instanceSender() == self.instance:
receiverName = element.instanceReceiver().getName()
# print element.instanceReceiver()
# print element.parent()
if element.instanceReceiver() == element.parent(): # ENV
receiverName = u'env'
......@@ -192,6 +190,11 @@ class CoreToText(MscVisitor):
self._result = timer + " {}{}\n".format(element.getName(),
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):
u"""
Return "end" token of element.
......@@ -210,4 +213,4 @@ class CoreToText(MscVisitor):
# print lines
for i in lines[:len(lines) - 1]:
text = text + u'{}{}\n'.format(self.INDENT, i)
return text
\ No newline at end of file
return text
#******************************************************************************
#
# 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):
* :class:`~msccore.MscMessage`
* :class:`~msccore.MscTimer`
* :class:`~msccore.MscCondition`
The created event is returned.
......@@ -251,6 +252,7 @@ class MscInstance(MscElement):
* :class:`~msccore.MscMessage`
* :class:`~msccore.MscTimer`
* :class:`~msccore.MscCondition`
The :meth:`MscElement._contentsChanged` function is called to indicate
that the content of this basic MSC are changed.
......
......@@ -25,10 +25,11 @@
#
#******************************************************************************
from mscGraphTimer import MscGraphTimer
from mscGraphCondition import MscGraphCondition
from mscGraphInstance import MscGraphInstance
from mscGraphMessage import MscGraphMessage
from mscGraphBMSC import MscGraphBMSC
from mscGraphBasicMSCScene import MscGraphBasicMSCScene
__all__ = ['MscGraphInstance', 'MscGraphBMSC', 'MscGraphMessage',
'MscGraphTimer', 'MscGraphBasicMSCScene']
'MscGraphTimer', 'MscGraphBasicMSCScene', 'MscGraphCondition']
......@@ -34,6 +34,7 @@ from PySide.QtGui import QMenu
from mscGraphInstance import MscGraphInstance
from mscGraphTimer import MscGraphTimer
from mscGraphCondition import MscGraphCondition
from mscGraphBMSC import MscGraphBMSC
from mscGraphMessage import MscGraphMessage
from mscgraphics import MscGraphComment
......@@ -45,7 +46,7 @@ logger = logging.getLogger(__name__)
class MscGraphBasicMSCScene(QGraphicsScene):
# Mode of the scene
(MoveItem, InsertInstance, InsertMessage, InsertTimer,
InsertComment) = range(5)
InsertComment, InsertCondition) = range(6)
# Signals
itemInserted = Signal(MscGraphItem)
......@@ -226,6 +227,22 @@ class MscGraphBasicMSCScene(QGraphicsScene):
comment.delete()
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
#**************************************************************************
......@@ -291,6 +308,15 @@ class MscGraphBasicMSCScene(QGraphicsScene):
self.addTimer(instance,
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
elif self._sceneMode == self.InsertComment:
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
from msccore import MscVisitor
from msccore import MscMessage
from msccore import MscTimer
from msccore import MscCondition
from msccore import MscDocument
from mscgraphics import MscGraphBMSC
......@@ -43,6 +44,7 @@ from mscgraphics import MscGraphBasicMSCScene
from mscgraphics import MscGraphInstance
from mscgraphics import MscGraphMessage
from mscgraphics import MscGraphTimer
from mscgraphics import MscGraphCondition
def coreToGraphics(document):
......@@ -145,28 +147,22 @@ class CoreToGraphicsVisitor(MscVisitor):
found = False
for e in graph.mscData().events():
#print e.element
event = e.element
# Messages
if isinstance(e.element, MscMessage):
coreMsg = e.element
#msgHash = coreMsg.hash()
#print msgHash
if isinstance(event, MscMessage):
coreMsg = event
# Look for the message in the table
elem = self.incompleteMsg.pop(coreMsg, None)
if elem != None:
if elem is not None:
found = True
# print 'FOUND: {0}'.format(elem)
else:
y = (spaceY * (coreMsg.absPos() - 1)) + startY
# print "PUNTO Y: {}".format(y)
elem = MscGraphMessage(graph, graph, data=coreMsg)
elem.setPos(elem.pos().x(), y)
if found:
#print "FOUND {}".format(elem)
if coreMsg.instanceSender() == graph.mscData():
elem.setStartInstance(graph)
else:
......@@ -188,10 +184,9 @@ class CoreToGraphicsVisitor(MscVisitor):
self.incompleteMsg[coreMsg] = elem
# Timers
if isinstance(event, MscTimer):
elif isinstance(event, MscTimer):
y = (spaceY * (event.absPos() - 1)) + startY
# print "PUNTO Y: {}".format(y)
timer = MscGraphTimer(e.element)
scene.addTimer2(graph, timer)
......@@ -205,5 +200,22 @@ class CoreToGraphicsVisitor(MscVisitor):
pos=pos)
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):
return self.scenes
......@@ -55,6 +55,7 @@ class MscLexer:
reserved = {
#'begin': 'BEGIN',
'comment': 'COMMENT',
'condition': 'CONDITION',
'data': 'DATA',
'endinstance': 'ENDINSTANCE',
'endmsc': 'ENDMSC',
......
......@@ -30,6 +30,7 @@ import logging
import msccore
from msccore import BasicMsc
from msccore import MscTimer
from msccore import MscCondition
from msccore import MscDocument
from msccore import MscInstance
from msccore import MscInstanceKind
......@@ -567,3 +568,8 @@ class MscMaker(object):
timer = MscTimer(name=name, typeTimer=tt)
self.newEvent(timer)
#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:
def p_event(self, p):
# Auxiliar rule for have all events together
u"""event : message_event
| timer_statement"""
| timer_statement
| condition_statement"""
#**************************************************************************
# 4.2 Instance
......@@ -417,6 +418,13 @@ class MscParser:
u"""timeout : TIMEOUT NAME"""
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
#*************************************************************************
......
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