Version: 9.16.0
GraphViewer.py
Go to the documentation of this file.
1# Copyright (C) 2006-2026 CEA, EDF
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
20import sys
21from qt import *
22from qtcanvas import *
23import 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
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
407if __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
def popup(self, canvasView)
Definition: GraphViewer.py:388
def moveBy(self, dx, dy)
Definition: GraphViewer.py:371
def __init__(self, canvas)
Definition: GraphViewer.py:357
def tooltip(self, view, pos)
Definition: GraphViewer.py:396
def maybeTip(self, pos)
Definition: GraphViewer.py:29
def __init__(self, parent)
Definition: GraphViewer.py:26
def __init__(self, c, parent, name, f)
Definition: GraphViewer.py:42
def contentsMouseMoveEvent(self, e)
Definition: GraphViewer.py:190
def selectItem(self, item)
Definition: GraphViewer.py:117
def deselectObj(self, obj)
Definition: GraphViewer.py:141
def contentsMouseDoubleClickEvent(self, e)
Definition: GraphViewer.py:54
def contentsMousePressEvent(self, e)
Definition: GraphViewer.py:68
def __init__(self, img, canvas)
Definition: GraphViewer.py:201
def myMove(self, dx, dy)
Definition: GraphViewer.py:323
def __init__(self, node, canvas)
Definition: GraphViewer.py:319
def addInLink(self, link)
Definition: GraphViewer.py:334
def setToPoint(self, x, y)
Definition: GraphViewer.py:243
def popup(self, canvasView)
Definition: GraphViewer.py:264
def moveBy(self, dx, dy)
Definition: GraphViewer.py:247
def setFromPoint(self, x, y)
Definition: GraphViewer.py:239
def tooltip(self, view, pos)
Definition: GraphViewer.py:275
def __init__(self, fromPort, toPort, canvas)
Definition: GraphViewer.py:225
def __init__(self, node, canvas)
Definition: GraphViewer.py:338
def myMove(self, dx, dy)
Definition: GraphViewer.py:342
def addOutLink(self, link)
Definition: GraphViewer.py:353
def moveBy(self, dx, dy)
Definition: GraphViewer.py:288
def __init__(self, node, canvas)
Definition: GraphViewer.py:281
def popup(self, canvasView)
Definition: GraphViewer.py:297
def tooltip(self, view, pos)
Definition: GraphViewer.py:313
def myMove(self, dx, dy)
Definition: GraphViewer.py:291