Version: 8.3.0
GraphViewer.py
Go to the documentation of this file.
1 # Copyright (C) 2006-2016 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, or (at your option) any later version.
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
21 from qt import *
22 from qtcanvas import *
23 import math
24 
26  def __init__( self, parent ):
27  QToolTip.__init__( self, parent )
28 
29  def maybeTip( self, pos ):
30  pos2=self.parentWidget().viewportToContents(pos)
31  point = self.parentWidget().inverseWorldMatrix().map(pos2)
32  ilist = self.parentWidget().canvas().collisions(point) #QCanvasItemList ilist
33  for each_item in ilist:
34  if hasattr(each_item,"tooltip"):
35  each_item.tooltip(self,pos)
36  return
37  elif hasattr(each_item,"getObj"):
38  each_item.getObj().tooltip(self,pos)
39  return
40 
42  def __init__(self,c,parent,name,f):
43  QCanvasView.__init__(self,c,parent,name,f)
44  self.__moving=0
45  self.__connecting=0
47  # for highlighting selections
48  self.selectPen=QPen(QColor(255,255,0),2,Qt.DashLine)
49  self.selectBrush=QBrush(Qt.red)
50  self.selectStyle = Qt.Dense5Pattern
51  self.selected=None
52  self.tooltip = DynamicTip( self )
53 
54  def contentsMouseDoubleClickEvent(self,e): # QMouseEvent e
55  point = self.inverseWorldMatrix().map(e.pos())
56  ilist = self.canvas().collisions(point) #QCanvasItemList ilist
57  for each_item in ilist:
58  if each_item.rtti()==984376:
59  if not each_item.hit(point):
60  continue
61  if e.button()== Qt.LeftButton:
62  if hasattr(each_item,"handleDoubleClick"):
63  each_item.handleDoubleClick(point)
64  self.canvas().update()
65  return
66 
67 
68  def contentsMousePressEvent(self,e): # QMouseEvent e
69  p=e.globalPos()
70  point = self.inverseWorldMatrix().map(e.pos())
71  ilist = self.canvas().collisions(point) #QCanvasItemList ilist
72  for each_item in ilist:
73  if each_item.rtti()==984376:
74  if not each_item.hit(point):
75  continue
76  if e.button()== Qt.RightButton:
77  #Right button click
78  self.__moving=0
79  self.__connecting=0
80  if hasattr(each_item,"popup"):
81  menu=each_item.popup(self)
82  if menu:
83  menu.exec_loop( QCursor.pos() )
84  self.canvas().update()
85  elif hasattr(each_item,"getObj"):
86  menu=each_item.getObj().popup(self)
87  if menu:
88  menu.exec_loop( QCursor.pos() )
89  self.canvas().update()
90 
91  elif e.button()== Qt.LeftButton:
92  #Left button click
93  if self.__connecting:
94  #We are linking objects
95  if hasattr(each_item,"getObj"):
96  #a connection is ending
97  self.__connecting.link(each_item.getObj().item)
98  #self.__connecting.link(each_item.getObj())
99  self.canvas().update()
100  self.__connecting=0
101  else:
102  #We are moving or selecting a composite object
103  each_item.selected()
104  self.__moving=each_item
105  self.__moving_start=point
106  self.canvas().update()
107  return
108  if e.button()== Qt.RightButton:
109  menu=self.popup()
110  if menu:
111  menu.exec_loop( QCursor.pos() )
112  self.canvas().update()
113  self.__moving=0
114  self.__connecting=0
115  QCanvasView.contentsMousePressEvent(self,e)
116 
117  def selectItem(self,item):
118  #print "selectItem",item
119  if self.selected:
120  try:
121  self.deselectObj(self.selected)
122  except:
123  pass
124  self.selected=None
125  #need to find equivalent canvas item
126  for citem in self.canvas().allItems():
127  if hasattr(citem,"item") and citem.item is item:
128  self.selected=citem
129  self.selectObj(self.selected)
130  break
131  self.canvas().update()
132 
133  def selectObj(self,obj):
134  if obj:
135  obj._origPen = obj.pen()
136  obj._origBrush = obj.brush()
137  obj._origStyle = obj.brush().style()
138  obj.setPen(self.selectPen)
139  #obj.setBrush(self.selectBrush)
140 
141  def deselectObj(self,obj):
142  if obj:
143  obj.setPen(obj._origPen)
144  #obj.setBrush(obj._origBrush)
145 
146  def popup(self):
147  menu=QPopupMenu()
148  caption = QLabel( "<font color=darkblue><u><b>View Menu</b></u></font>", self )
149  caption.setAlignment( Qt.AlignCenter )
150  menu.insertItem( caption )
151  menu.insertItem("add Node", self.addNode)
152  return menu
153 
154  #def layout(self,rankdir):
155  # print rankdir
156 
157  def updateCanvas(self):
158  #Par defaut, Qt n'efface pas le background. Seul repaintContents
159  #semble le faire. Utile apres un popup ou un resize avec scrollbars
160  #Peut-on l'utiliser partout ? Pb de performance ?
161  self.repaintContents(True)
162  #self.canvas().update()
163 
164  def addNode(self):
165  print "addNode"
166 
167  def zoomIn(self):
168  m = self.worldMatrix()
169  m.scale( 2.0, 2.0 )
170  self.setWorldMatrix( m )
171 
172  def zoomOut(self):
173  m = self.worldMatrix()
174  m.scale( 0.5, 0.5 )
175  self.setWorldMatrix( m )
176 
177  def clear(self):
178  ilist = self.canvas().allItems()
179  for each_item in ilist:
180  if each_item:
181  each_item.setCanvas(None)
182  del each_item
183  self.canvas().update()
184 
185  def connecting(self,obj):
186  """Method called by an item to notify canvasView a connection has begun"""
187  print "connecting",obj
188  self.__connecting=obj
189 
191  if self.__moving :
192  point = self.inverseWorldMatrix().map(e.pos())
193  self.__moving.moveBy(point.x()-self.__moving_start.x(),point.y()-self.__moving_start.y())
194  self.__moving_start = point
195  self.canvas().update()
196  else:
197  #self.tooltip.maybeTip(point)
198  QCanvasView.contentsMouseMoveEvent(self,e)
199 
201  def __init__(self,img,canvas):
202  QCanvasRectangle.__init__(self,canvas)
203 
204  self.imageRTTI=984376
205  self.image=img
206  self.pixmap=QPixmap()
207  self.setSize(self.image.width(), self.image.height())
208  self.pixmap.convertFromImage(self.image, Qt.OrderedAlphaDither);
209 
210  def rtti(self):
211  return self.imageRTTI
212 
213  def hit(self,p):
214  ix = p.x()-self.x()
215  iy = p.y()-self.y()
216  if not self.image.valid( ix , iy ):
217  return False
218  self.pixel = self.image.pixel( ix, iy )
219  return (qAlpha( self.pixel ) != 0)
220 
221  def drawShape(self,p):
222  p.drawPixmap( self.x(), self.y(), self.pixmap )
223 
225  def __init__(self,fromPort, toPort,canvas):
226  QCanvasLine.__init__(self,canvas)
227  self.setPen(QPen(Qt.black))
228  self.setBrush(QBrush(Qt.red))
229  fromPort.addOutLink(self)
230  toPort.addInLink(self)
231  self.setPoints(int(fromPort.x()),int(fromPort.y()), int(toPort.x()), int(toPort.y()))
232  self.setZ(min(fromPort.z(),toPort.z())-1)
233  self.setVisible(True)
234  self.arrow = QCanvasPolygon(self.canvas())
235  self.arrow.setBrush(QBrush(Qt.black))
236  self.setArrow()
237  self.arrow.show()
238 
239  def setFromPoint(self,x,y):
240  self.setPoints(x,y,self.endPoint().x(),self.endPoint().y())
241  self.setArrow()
242 
243  def setToPoint(self,x,y):
244  self.setPoints(self.startPoint().x(), self.startPoint().y(),x,y)
245  self.setArrow()
246 
247  def moveBy(self,dx,dy):
248  pass
249 
250  def setArrow(self):
251  x1,y1=self.startPoint().x(),self.startPoint().y()
252  x2,y2=self.endPoint().x(),self.endPoint().y()
253  d=math.hypot(x2-x1,y2-y1)
254  sina=(y2-y1)/d
255  cosa=(x2-x1)/d
256  x=(x1+x2)/2.
257  y=(y1+y2)/2.
258  pa=QPointArray(3)
259  pa.setPoint(0, QPoint(x+10*cosa,y+10*sina))
260  pa.setPoint(1, QPoint(x-5*sina,y+5*cosa))
261  pa.setPoint(2, QPoint(x+5*sina,y-5*cosa))
262  self.arrow.setPoints(pa)
263 
264  def popup(self,canvasView):
265  menu=QPopupMenu()
266  caption = QLabel( "<font color=darkblue><u><b>Node Menu</b></u></font>",menu )
267  caption.setAlignment( Qt.AlignCenter )
268  menu.insertItem( caption )
269  menu.insertItem("Delete", self.delete)
270  return menu
271 
272  def delete(self):
273  print "delete link"
274 
275  def tooltip(self,view,pos):
276  r = QRect(pos.x(), pos.y(), pos.x()+10, pos.y()+10)
277  s = QString( "link: %d,%d" % (r.center().x(), r.center().y()) )
278  view.tip( r, s )
279 
281  def __init__(self,node,canvas):
282  QCanvasEllipse.__init__(self,6,6,canvas)
283  self.setPen(QPen(Qt.black))
284  self.setBrush(QBrush(Qt.red))
285  self.setZ(node.z()+1)
286  self.node=node
287 
288  def moveBy(self,dx,dy):
289  self.node.moveBy(dx,dy)
290 
291  def myMove(self,dx,dy):
292  QCanvasEllipse.moveBy(self,dx,dy)
293 
294  def getObj(self):
295  return self
296 
297  def popup(self,canvasView):
298  self.context=canvasView
299  menu=QPopupMenu()
300  caption = QLabel( "<font color=darkblue><u><b>Port Menu</b></u></font>",menu )
301  caption.setAlignment( Qt.AlignCenter )
302  menu.insertItem( caption )
303  menu.insertItem("Connect", self.connect)
304  return menu
305 
306  def connect(self):
307  print "connect",self.context
308  self.context.connecting(self)
309 
310  def link(self,obj):
311  print "link:",obj
312 
313  def tooltip(self,view,pos):
314  r = QRect(self.x(), self.y(), self.width(), self.height())
315  s = QString( "port: %d,%d" % (r.center().x(), r.center().y()) )
316  view.tip( r, s )
317 
319  def __init__(self,node,canvas):
320  PortItem.__init__(self,node,canvas)
321  self.__inList=[]
322 
323  def myMove(self,dx,dy):
324  PortItem.myMove(self,dx,dy)
325  for link in self.__inList:
326  link.setToPoint( int(self.x()), int(self.y()) )
327 
328  def link(self,obj):
329  print "link:",obj
330  if isinstance(obj,OutPortItem):
331  #Connection possible
332  l=LinkItem(obj,self,self.canvas())
333 
334  def addInLink(self,link):
335  self.__inList.append(link)
336 
338  def __init__(self,node,canvas):
339  PortItem.__init__(self,node,canvas)
340  self.__outList=[]
341 
342  def myMove(self,dx,dy):
343  PortItem.myMove(self,dx,dy)
344  for link in self.__outList:
345  link.setFromPoint( int(self.x()), int(self.y()) )
346 
347  def link(self,obj):
348  print "link:",obj
349  if isinstance(obj,InPortItem):
350  #Connection possible
351  l=LinkItem(self,obj,self.canvas())
352 
353  def addOutLink(self,link):
354  self.__outList.append(link)
355 
357  def __init__(self,canvas):
358  QCanvasRectangle.__init__(self,canvas)
359  self.setSize(50,50)
360 
361  self.inports=[]
362  self.outports=[]
363 
364  p=InPortItem(self,canvas)
365  p.myMove(0,25)
366  self.inports.append(p)
367  p=OutPortItem(self,canvas)
368  p.myMove(50,25)
369  self.outports.append(p)
370 
371  def moveBy(self,dx,dy):
372  QCanvasRectangle.moveBy(self,dx,dy)
373  for p in self.inports:
374  p.myMove(dx,dy)
375  for p in self.outports:
376  p.myMove(dx,dy)
377 
378  def show(self):
379  QCanvasRectangle.show(self)
380  for p in self.inports:
381  p.show()
382  for p in self.outports:
383  p.show()
384 
385  def getObj(self):
386  return self
387 
388  def popup(self,canvasView):
389  menu=QPopupMenu()
390  caption = QLabel( "<font color=darkblue><u><b>Node Menu</b></u></font>",menu )
391  caption.setAlignment( Qt.AlignCenter )
392  menu.insertItem( caption )
393  menu.insertItem("Browse", self.browse)
394  return menu
395 
396  def tooltip(self,view,pos):
397  r = QRect(self.x(), self.y(), self.width(), self.height())
398  s = QString( "node: %d,%d" % (r.center().x(), r.center().y()) )
399  view.tip( r, s )
400 
401  def browse(self):
402  print "browse"
403 
404  def selected(self):
405  print "selected"
406 
407 if __name__=='__main__':
408  app=QApplication(sys.argv)
410  QToolBar(box,"toolbar")
411  canvas=QCanvas(800,600)
412  canvas.setAdvancePeriod(30)
413  m=GraphViewer(canvas,box,"example",0)
414  box.setCentralWidget(m)
415  c1=Cell(canvas)
416  c1.moveBy(150,150)
417  c1.show()
418  c2=Cell(canvas)
419  c2.moveBy(250,150)
420  c2.show()
421  c1.outports[0].link(c2.inports[0])
422 
423  qApp.setMainWidget(box)
424  box.show()
425  app.exec_loop()
426 
427