Salome HOME
Merge from V6_main 01/04/2013
[modules/yacs.git] / src / pyqt / gui / CItems.py
1 # Copyright (C) 2006-2013  CEA/DEN, EDF R&D
2 #
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU Lesser General Public
5 # License as published by the Free Software Foundation; either
6 # version 2.1 of the License.
7 #
8 # This library is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 # Lesser General Public License for more details.
12 #
13 # You should have received a copy of the GNU Lesser General Public
14 # License along with this library; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 #
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 #
19
20 import sys,traceback
21 from qt import *
22 from qtcanvas import *
23 import pilot
24 import pypilot
25 import Item
26 import math
27
28 dispatcher=pilot.Dispatcher.getDispatcher()
29
30 class TextItem(QCanvasText):
31   """A text in a composite object"""
32   def __init__(self,obj,canvas):
33     QCanvasText.__init__(self,canvas)
34     self.obj=obj
35     self.item=None
36   def getObj(self):
37     """The composite object which contains the text"""
38     return self.obj
39   def moveBy(self,dx,dy):
40     """Request the text move by x,y"""
41     if self.obj:
42       #the text is a part of a composite object
43       self.obj.moveBy(dx,dy)
44     else:
45       #the text is independant
46       self.myMove(dx,dy)
47   def myMove(self,dx,dy):
48     """The real move"""
49     QCanvasText.moveBy(self,dx,dy)
50   def selected(self):
51     """The canvas item has been selected"""
52     if self.obj:
53       self.obj.selected()
54
55 class PointItem(QCanvasEllipse):
56   def __init__(self,obj,x,y,canvas):
57     """Create a point contained in a composite line (obj)"""
58     QCanvasEllipse.__init__(self,6,6,canvas)
59     self.obj=obj
60     self.item=None
61     self.inline=None
62     self.outline=None
63     self.setPen(QPen(Qt.black))
64     self.setBrush(QBrush(Qt.red))
65     self.setX(x)
66     self.setY(y)
67     self.setVisible(True)
68
69   def setInline(self,inline):
70     self.inline=inline
71     if inline.z() >= self.z():
72       self.setZ(inline.z()+1)
73   def setOutline(self,outline):
74     self.outline=outline
75     if outline.z() >= self.z():
76       self.setZ(outline.z()+1)
77
78   def moveBy(self,dx,dy):
79     """Request the point move by x,y"""
80     self.myMove(dx,dy)
81
82   def myMove(self,dx,dy):
83     """The real move"""
84     QCanvasEllipse.moveBy(self,dx,dy)
85     if self.outline:
86       self.outline.setFromPoint( int(self.x()), int(self.y()) )
87     if self.inline:
88       self.inline.setToPoint( int(self.x()), int(self.y()) )
89
90   def getObj(self):
91     """The object which contains the point"""
92     return self.obj
93
94   def handleDoubleClick(self,pos):
95     self.obj.deletePoint(self,pos)
96
97   #def __del__(self):
98   #  print "PointItem.__del__"
99
100   def clear(self):
101     """To remove from canvas"""
102     self.setCanvas(None)
103     self.obj=None
104     self.inline=None
105     self.outline=None
106
107   def selected(self):
108     """The canvas item has been selected"""
109
110 class LineItem(QCanvasLine):
111   """A line between 2 points"""
112   def __init__(self,obj,fromPoint, toPoint,canvas):
113     QCanvasLine.__init__(self,canvas)
114     self.obj=obj
115     self.item=None
116     self.fromPoint=fromPoint
117     self.toPoint=toPoint
118     self.setPen(QPen(Qt.black))
119     self.setBrush(QBrush(Qt.red))
120     self.setPoints(int(fromPoint.x()),int(fromPoint.y()), int(toPoint.x()), int(toPoint.y()))
121     self.setZ(min(fromPoint.z(),toPoint.z())-1)
122     self.setVisible(True)
123     self.arrow = QCanvasPolygon(self.canvas())
124     self.arrow.setBrush(QBrush(Qt.black))
125     self.setArrow()
126     self.arrow.show()
127
128   def setFromPoint(self,x,y):
129     self.setPoints(x,y,self.endPoint().x(),self.endPoint().y())
130     self.setArrow()
131   def setToPoint(self,x,y):
132     self.setPoints(self.startPoint().x(), self.startPoint().y(),x,y)
133     self.setArrow()
134   def moveBy(self,dx,dy):
135     """Disable line move"""
136     pass
137
138   def setArrow(self):
139     x1,y1=self.startPoint().x(),self.startPoint().y()
140     x2,y2=self.endPoint().x(),self.endPoint().y()
141     d=math.hypot(x2-x1,y2-y1)
142     sina=(y2-y1)/d
143     cosa=(x2-x1)/d
144     x=(x1+x2)/2.
145     y=(y1+y2)/2.
146     l,e=6,3 
147     pa=QPointArray(3)
148     pa.setPoint(0, QPoint(x+l*cosa,y+l*sina))
149     pa.setPoint(1, QPoint(x-e*sina,y+e*cosa))
150     pa.setPoint(2, QPoint(x+e*sina,y-e*cosa))
151     self.arrow.setPoints(pa)
152
153   def getObj(self):
154     """The object which contains the line"""
155     return self.obj
156   def handleDoubleClick(self,pos):
157     #split the line
158     self.obj.splitline(self,pos)
159
160   #def __del__(self):
161   #  print "LineItem.__del__"
162
163   def clear(self):
164     """To remove from canvas"""
165     self.setCanvas(None)
166     self.fromPoint=None
167     self.toPoint=None
168     self.obj=None
169     self.arrow.setCanvas(None)
170     self.arrow=None
171
172   def selected(self):
173     """The canvas item has been selected"""
174
175 class LinkItem:
176   def __init__(self,fromPort, toPort,canvas):
177     self.fromPort=fromPort
178     self.toPort=toPort
179     self.canvas=canvas
180     self.item=None
181     fromPort.addOutLink(self)
182     toPort.addInLink(self)
183     self.lines=[]
184     self.points=[]
185     self.lines.append(LineItem(self,fromPort, toPort,canvas))
186
187   def deletePoint(self,point,pos):
188     """Delete intermediate point"""
189     if point not in self.points:
190       return
191     self.points.remove(point)
192     inline=point.inline
193     outline=point.outline
194     inline.toPoint=outline.toPoint
195     inline.setToPoint(outline.toPoint.x(),outline.toPoint.y())
196     self.lines.remove(outline)
197     if inline.toPoint in self.points:
198       inline.toPoint.setInline(inline)
199     #remove from canvas
200     point.clear()
201     outline.clear()
202
203   def clearPoints(self):
204     #make a copy as deletePoint modify self.points
205     for point in self.points[:]:
206       self.deletePoint(point,0)
207
208   def splitline(self,line,pos):
209     self.splitLine(line,pos.x(),pos.y())
210
211   def splitLine(self,line,x,y):
212     """Split line at position x,y"""
213     #The new point
214     point=PointItem(self,x,y,self.canvas)
215     self.points.append(point)
216     i=self.lines.index(line)
217
218     newline=LineItem(self,point,line.toPoint,self.canvas)
219     if line.toPoint in self.points:
220       #line not connected to port : reconnect newline
221       line.toPoint.setInline(newline)
222     self.lines.insert(i+1,newline)
223
224     line.setToPoint(x,y)
225     line.toPoint=point
226     point.setInline(line)
227     point.setOutline(newline)
228
229   def setFromPoint(self,x,y):
230     first=self.lines[0]
231     first.setFromPoint(x,y)
232
233   def setToPoint(self,x,y):
234     last=self.lines[-1]
235     last.setToPoint(x,y)
236
237   def moveBy(self,dx,dy):
238     pass
239
240   def popup(self,canvasView):
241     menu=QPopupMenu()
242     caption = QLabel( "<font color=darkblue><u><b>Link Menu</b></u></font>",menu )
243     caption.setAlignment( Qt.AlignCenter )
244     menu.insertItem( caption )
245     menu.insertItem("Delete", self.delete)
246     return menu
247
248   def delete(self):
249     print "delete link"
250
251   def tooltip(self,view,pos):
252     r = QRect(pos.x(), pos.y(), pos.x()+10, pos.y()+10)
253     s = QString( "link: "+self.fromPort.port.getNode().getName() +":"+self.fromPort.port.getName()+"->"+self.toPort.port.getNode().getName()+":"+self.toPort.port.getName()  )
254     view.tip( r, s )
255
256   def selected(self):
257     """The canvas item has been selected"""
258
259 class ControlLinkItem(LinkItem):
260   def tooltip(self,view,pos):
261     r = QRect(pos.x(), pos.y(), pos.x()+10, pos.y()+10)
262     s = QString( "link: "+self.fromPort.port.getNode().getName()+"->"+self.toPort.port.getNode().getName())
263     view.tip( r, s )
264     #QToolTip(view).tip( r, s )
265
266 class ControlItem(QCanvasRectangle):
267   def __init__(self,node,port,canvas):
268     QCanvasRectangle.__init__(self,canvas)
269     self.setSize(6,6)
270     self.port=port
271     self.setPen(QPen(Qt.black))
272     self.setBrush(QBrush(Qt.red))
273     self.setZ(node.z()+1)
274     self.node=node
275     self.item=Item.adapt(self.port)
276
277   def moveBy(self,dx,dy):
278     self.node.moveBy(dx,dy)
279
280   def myMove(self,dx,dy):
281     QCanvasRectangle.moveBy(self,dx,dy)
282
283   def getObj(self):
284     return self
285
286   def popup(self,canvasView):
287     self.context=canvasView
288     menu=QPopupMenu()
289     caption = QLabel( "<font color=darkblue><u><b>Port Menu</b></u></font>",menu )
290     caption.setAlignment( Qt.AlignCenter )
291     menu.insertItem( caption )
292     menu.insertItem("Connect", self.connect)
293     return menu
294
295   def connect(self):
296     print "ControlItem.connect",self.context
297     print self.port
298     item=Item.adapt(self.port)
299     print item
300     item.connect()
301     self.context.connecting(item)
302     #self.context.connecting(self)
303
304   def link(self,obj):
305     #Protocol to link 2 objects (ports, at first)
306     #First, notify the canvas View (or any view that can select) we are connecting (see method connect above)
307     #Second (and last) make the link in the link method of object that was declared connecting
308     print "link:",obj
309
310   def tooltip(self,view,pos):
311     r = QRect(pos.x(), pos.y(), self.width(), self.height())
312     s = QString( "gate:")
313     view.tip( r, s )
314
315   def selected(self):
316     """The canvas item has been selected"""
317     #print "control port selected"
318     item=Item.adapt(self.port)
319     item.selected()
320
321 class InControlItem(ControlItem):
322   def __init__(self,node,port,canvas):
323     ControlItem.__init__(self,node,port,canvas)
324     self.__inList=[]
325
326   def myMove(self,dx,dy):
327     ControlItem.myMove(self,dx,dy)
328     for link in self.__inList:
329       link.setToPoint( int(self.x()), int(self.y()) )
330
331   def link(self,obj):
332     #Here we create the link between self and obj.
333     #self has been declared connecting in connect method
334     print "link:",obj
335     if isinstance(obj,OutControlItem):
336       #Connection possible
337       l=LinkItem(obj,self,self.canvas())
338
339   def addInLink(self,link):
340     self.__inList.append(link)
341
342   def tooltip(self,view,pos):
343     r = QRect(pos.x(), pos.y(), self.width(), self.height())
344     s = QString( "ingate:")
345     view.tip( r, s )
346     #QToolTip(view).tip( r, s )
347
348 class OutControlItem(ControlItem):
349   def __init__(self,node,port,canvas):
350     ControlItem.__init__(self,node,port,canvas)
351     self.__outList=[]
352
353   def myMove(self,dx,dy):
354     ControlItem.myMove(self,dx,dy)
355     for link in self.__outList:
356       link.setFromPoint( int(self.x()), int(self.y()) )
357
358   def link(self,obj):
359     #Here we create the link between self and obj.
360     #self has been declared connecting in connect method
361     print "link:",obj
362     if isinstance(obj,InControlItem):
363       #Connection possible
364       l=LinkItem(self,obj,self.canvas())
365
366   def addOutLink(self,link):
367     self.__outList.append(link)
368
369   def tooltip(self,view,pos):
370     r = QRect(pos.x(), pos.y(), self.width(), self.height())
371     s = QString( "outgate:")
372     view.tip( r, s )
373     #QToolTip(view).tip( r, s )
374
375   def links(self):
376     return self.__outList
377
378 class PortItem(QCanvasEllipse):
379   def __init__(self,node,port,canvas):
380     QCanvasEllipse.__init__(self,6,6,canvas)
381     self.port=port
382     self.item=None
383     self.item=Item.adapt(self.port)
384     self.setPen(QPen(Qt.black))
385     self.setBrush(QBrush(Qt.red))
386     self.setZ(node.z()+1)
387     self.node=node
388
389   def moveBy(self,dx,dy):
390     self.node.moveBy(dx,dy)
391
392   def myMove(self,dx,dy):
393     QCanvasEllipse.moveBy(self,dx,dy)
394
395   def getObj(self):
396     return self
397
398   def popup(self,canvasView):
399     self.context=canvasView
400     menu=QPopupMenu()
401     caption = QLabel( "<font color=darkblue><u><b>Port Menu</b></u></font>",menu )
402     caption.setAlignment( Qt.AlignCenter )
403     menu.insertItem( caption )
404     menu.insertItem("Connect", self.connect)
405     return menu
406
407   def connect(self):
408     print "PortItem.connect",self.context
409     print self.port
410     item=Item.adapt(self.port)
411     print item
412     self.context.connecting(item)
413     #self.context.connecting(self)
414
415   def link(self,obj):
416     print "PortItem.link:",obj
417
418   def tooltip(self,view,pos):
419     r = QRect(pos.x(),pos.y(),self.width(), self.height())
420     t=self.port.edGetType()
421     s = QString( "port: " + self.port.getName() + ":" + t.name())
422     view.tip( r, s )
423
424   def selected(self):
425     """The canvas item has been selected"""
426     #print "port selected"
427     item=Item.adapt(self.port)
428     item.selected()
429
430 class InPortItem(PortItem):
431   def __init__(self,node,port,canvas):
432     PortItem.__init__(self,node,port,canvas)
433     self.__inList=[]
434
435   def myMove(self,dx,dy):
436     PortItem.myMove(self,dx,dy)
437     for link in self.__inList:
438       link.setToPoint( int(self.x()), int(self.y()) )
439
440   def link(self,obj):
441     #Here we create the link between self and obj.
442     #self has been declared connecting in connect method
443     print "link:",obj
444     if isinstance(obj,OutPortItem):
445       #Connection possible
446       l=LinkItem(obj,self,self.canvas())
447
448   def addInLink(self,link):
449     self.__inList.append(link)
450
451 class OutPortItem(PortItem):
452   def __init__(self,node,port,canvas):
453     PortItem.__init__(self,node,port,canvas)
454     self.__outList=[]
455
456   def myMove(self,dx,dy):
457     PortItem.myMove(self,dx,dy)
458     for link in self.__outList:
459       link.setFromPoint( int(self.x()), int(self.y()) )
460
461   def link(self,obj):
462     #Here we create the link between self and obj.
463     #self has been declared connecting in connect method
464     print "link:",obj
465     if isinstance(obj,InPortItem):
466       #Connection possible
467       l=LinkItem(self,obj,self.canvas())
468
469   def addOutLink(self,link):
470     self.__outList.append(link)
471
472   def links(self):
473     return self.__outList
474
475 class InStreamItem(InPortItem):
476   def __init__(self,node,port,canvas):
477     InPortItem.__init__(self,node,port,canvas)
478     self.setBrush(QBrush(Qt.green))
479
480 class OutStreamItem(OutPortItem):
481   def __init__(self,node,port,canvas):
482     OutPortItem.__init__(self,node,port,canvas)
483     self.setBrush(QBrush(Qt.green))
484
485 class Cell(QCanvasRectangle,pypilot.PyObserver):
486   colors={
487       "pink":Qt.cyan,
488       "green":Qt.green,
489       "magenta":Qt.magenta,
490       "purple":Qt.darkMagenta,
491       "blue":Qt.blue,
492       "red":Qt.red,
493       "orange":Qt.yellow,
494       "grey":Qt.gray,
495       "white":Qt.white,
496     }
497
498   def __init__(self,node,canvas):
499     QCanvasRectangle.__init__(self,canvas)
500     pypilot.PyObserver.__init__(self)
501     self.inports=[]
502     self.outports=[]
503     self.setSize(50,50)
504     #node is an instance of YACS::ENGINE::Node
505     self.node=node
506     self.item=Item.adapt(self.node)
507     dispatcher.addObserver(self,node,"status")
508     self.label=TextItem(self,canvas)
509     self.label.setText(self.node.getName())
510     self.label.setFont(QFont("Helvetica",8))
511     rect=self.label.boundingRect()
512     self.label.setZ(self.z()+1)
513     self.label.myMove(self.x()+self.width()/2-rect.width()/2,self.y()+self.height()/2-rect.height()/2)
514     color= self.colors.get(node.getColorState(node.getEffectiveState()),Qt.white)
515     self.setBrush(QBrush(color))
516
517     dy=6
518     y=0
519     for inport in self.node.getSetOfInputPort():
520       p=InPortItem(self,inport,canvas)
521       y=y+dy
522       p.myMove(0,y)
523       self.inports.append(p)
524
525     for instream in self.node.getSetOfInputDataStreamPort():
526       p=InStreamItem(self,instream,canvas)
527       y=y+dy
528       p.myMove(0,y)
529       self.inports.append(p)
530
531     ymax=y
532
533     dy=6
534     y=0
535     for outport in self.node.getSetOfOutputPort():
536       p=OutPortItem(self,outport,canvas)
537       y=y+dy
538       p.myMove(50,y)
539       self.outports.append(p)
540
541     for outstream in self.node.getSetOfOutputDataStreamPort():
542       p=OutStreamItem(self,outstream,canvas)
543       y=y+dy
544       p.myMove(50,y)
545       self.outports.append(p)
546
547     ymax=max(y,ymax)
548
549     #Control ports
550     y=ymax+dy
551     if y < 44:y=44
552     p=InControlItem(self,self.node.getInGate(),canvas)
553     p.myMove(0,y)
554     self.inports.append(p)
555     self.ingate=p
556     p=OutControlItem(self,self.node.getOutGate(),canvas)
557     p.myMove(44,y)
558     self.outports.append(p)
559     self.outgate=p
560     y=y+dy
561     self.setSize(50,y)
562
563
564   events={
565       "status":QEvent.User+1,
566       }
567
568   def pynotify(self,object,event):
569     #print "pynotify",event,object
570     try:
571       evType=self.events[event]
572       ev=QCustomEvent(evType)
573       ev.setData(self)
574       ev.yacsEvent=event
575       QApplication.postEvent(self.canvas(), ev)
576       #request immediate processing (deadlock risk ???)
577       #QApplication.sendPostedEvents(self.canvas(), evType)
578       #print "pynotify end"
579     except:
580       #traceback.print_exc()
581       raise
582
583   def customEvent(self,event):
584     if event.yacsEvent=="status":
585       object=self.node
586       state=object.getEffectiveState()
587       color=object.getColorState(state)
588       color= self.colors.get(color,Qt.white)
589       self.setBrush(QBrush(color))
590     else:
591       print "Unknown custom event type:", event.type()
592
593   def moveBy(self,dx,dy):
594     QCanvasRectangle.moveBy(self,dx,dy)
595     self.label.myMove(dx,dy)
596     for p in self.inports:
597       p.myMove(dx,dy)
598     for p in self.outports:
599       p.myMove(dx,dy)
600
601   def show(self):
602     QCanvasRectangle.show(self)
603     self.label.show()
604     for p in self.inports:
605       p.show()
606     for p in self.outports:
607       p.show()
608
609   def getObj(self):
610     return self
611
612   def popup(self,canvasView):
613     menu=QPopupMenu()
614     caption = QLabel( "<font color=darkblue><u><b>Node Menu</b></u></font>",menu )
615     caption.setAlignment( Qt.AlignCenter )
616     menu.insertItem( caption )
617     menu.insertItem("Browse", self.browse)
618     return menu
619
620   def tooltip(self,view,pos):
621     r = QRect(pos.x(), pos.y(), self.width(), self.height())
622     s = QString( "node: " + self.node.getName())
623     view.tip( r, s )
624     #QToolTip(view).tip( r, s )
625
626   def browse(self):
627     print "browse"
628
629   def selected(self):
630     """The canvas item has been selected"""
631     #print "node selected"
632     item=Item.adapt(self.node)
633     item.selected()