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