#!/usr/bin/env python2.6 # -*- coding: utf-8 -*- # Copyright (C) 2010 by RoboLab # # This file is part of RoboComp # # RoboComp 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. # # RoboComp 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 RoboComp. If not, see <http://www.gnu.org/licenses/>. # from PyQt4 import QtGui from PyQt4 import QtCore import PyQt4 import random import sys import math import managerCompConfig2 import managerNode from logger import logger class visualNode(QtGui.QGraphicsEllipseItem): def __init__(self, _parent, _contextMenu=None): QtGui.QGraphicsEllipseItem.__init__(self) #.parent() es una built function de QGraphicsEllipseItem self.nParent=_parent self.tl = QtCore.QTimeLine(50) self.tl.setFrameRange(0, 100) self.a = QtGui.QGraphicsItemAnimation() self.a.setItem(self) self.a.setTimeLine(self.tl) self.animated=False self.menu = None self.setFlag(QtGui.QGraphicsItem.ItemIsMovable); self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable); #~ self.setFlag(QtGui.QGraphicsItem.ItemSendsScenePositionChanges) self.setFlag(QtGui.QGraphicsItem.ItemSendsGeometryChanges) self.setCacheMode(QtGui.QGraphicsItem.DeviceCoordinateCache) self.setZValue(1); self.id='' self.text = QtGui.QGraphicsTextItem(self) self.setPos(random.randint(0, 400), random.randint(0, 400)) #~ self.setRect(self.pos().x(), self.pos().y() , 20, 20) self.vel_x = 0. self.vel_y = 0. self.scale=200 self.weight=30 self.repulsion=300 self.radius=30 self.newPos=self.pos() self.contextMenu= _contextMenu self.stopAnimation() def boundingRect(self): adjust = 2 return QtCore.QRectF((-1*self.radius/2) -adjust, (-1*self.radius/2) -adjust, self.radius+ 3 + adjust, self.radius+ 3 +adjust) def shape(self): path= QtGui.QPainterPath() path.addEllipse((-1*self.radius/2) , (-1*self.radius/2) , self.radius, self.radius) return path def paint(self, painter, option, widget = None): if self.radius < 30: self.radius = 30 gradient=QtGui.QRadialGradient(-3, -3, 10) if self.isSelected(): gradient.setColorAt(1, QtCore.Qt.white) gradient.setColorAt(0, QtCore.Qt.black) else: if self.nParent and self.nParent.active: gradient.setColorAt(0, QtCore.Qt.green) gradient.setColorAt(1, QtCore.Qt.darkGreen) else: if self.nParent.data.failed == False: gradient.setColorAt(0, QtCore.Qt.red) gradient.setColorAt(1, QtCore.Qt.darkRed) else: gradient.setColorAt(0, QtCore.Qt.darkGray) gradient.setColorAt(1, QtCore.Qt.darkMagenta) painter.setBrush(gradient) painter.setPen(QtGui.QPen(QtCore.Qt.black, 0)); painter.drawEllipse((-1*self.radius/2), (-1*self.radius/2), self.radius, self.radius); if self.nParent and self.nParent.active: painter.setBrush(QtGui.QColor(0, 255, 0, 0)) painter.setPen(QtGui.QColor(0, 255, 0)) else: painter.setBrush(QtGui.QColor(255, 0, 0, 0)) painter.setPen(QtGui.QColor(255, 0, 0)) painter.drawEllipse(-1*self.radius/2, -1*self.radius/2, self.radius, self.radius) font = painter.font() font.setBold(True); font.setPointSize(14); painter.setFont(font); if self.nParent: name = self.nParent.data.alias #~ name = self.nParent.data.endpoint self.text.setPlainText(name) self.text.setPos(-1*self.text.boundingRect().width()/2, -1*self.radius-3) #~ if self.parent.data.alias is not None: #~ painter.drawRect(self.boundingRect()) #~ def advance(self, step): #~ print "visualNode.advance(): step="+str(step) #~ if self.newPos == self.pos(): #~ return False #~ return True def itemChange(self, change, value): self.a.setPosAt(0, self.scenePos()) if change == QtGui.QGraphicsItem.ItemPositionHasChanged and self.nParent is not None: for edge in self.nParent.edges: edge.view.adjust() self.itemMoved() if self.menu: self.menu.setGeometry(self.pos().x(), self.pos().y(), 100, 75) return QtGui.QGraphicsItem.itemChange(self,change, value) def mousePressEvent(self, event): print "visualNode.mousePressEvent" oldpos=self.scenePos() #~ self.update() if event.button() == 2: self.showNodeMenu(event) QtGui.QGraphicsItem.mousePressEvent(self, event) #~ def randomAnimation(self): #~ self.a.setPosAt(0, self.scenePos()) #~ self.a.setPosAt(0.25, QtCore.QPointF(random.randint(0,500),random.randint(0,300))) #~ self.a.setPosAt(0.50, QtCore.QPointF(random.randint(0,500),random.randint(0,300))) #~ self.a.setPosAt(0.75, QtCore.QPointF(random.randint(0,500),random.randint(0,300))) #~ self.a.setPosAt(1, oldpos) #~ self.tl.start() def mouseReleaseEvent(self, event): #~ self.update() QtGui.QGraphicsItem.mouseReleaseEvent(self, event) def itemMoved(self): ##~ print str(self)+" "+str(self.animated) if self.animated == True: if self.nParent.parent: for node in self.nParent.parent.nodes: node.view.pruebaAnim() def stopAnimation(self): self.tl.setPaused(True) self.animated=False def startAnimation(self): self.tl.setPaused(False) self.animated=True self.itemMoved() def pruebaAnim(self): self.a.setPosAt(0, self.scenePos()) if not self.scene() or self.scene().mouseGrabberItem() == self or self.tl.state() != QtCore.QTimeLine.NotRunning: return ##Sum up all forces pushing this item away xvel = 0 yvel = 0 for node in self.nParent.parent.nodes: line = QtCore.QLineF(self.mapFromItem(node.view, 0, 0), QtCore.QPointF(0, 0)) dx = line.dx() dy = line.dy() l = 2.0 * (dx * dx + dy * dy) if l > 0 : xvel += (dx * self.repulsion) / l yvel += (dy * self.repulsion) / l ##Now subtract all forces pulling items together weight = (len(self.nParent.edges) + 1) * self.weight for edge in self.nParent.edges: if edge.fromNode == self.nParent: pos = self.mapFromItem(edge.toNode.view, 0, 0) else: pos = self.mapFromItem(edge.fromNode.view, 0, 0) xvel += pos.x() / weight yvel += pos.y() / weight if math.fabs(xvel) < 0.3 and math.fabs(yvel) < 0.3: xvel = yvel = 0 sceneRect = self.scene().sceneRect(); self.newPos = self.pos() + QtCore.QPointF(xvel, yvel) #~ self.newPos.setX(min(max(self.newPos.x(), sceneRect.left() + 10), sceneRect.right() - 10)) #~ self.newPos.setY(min(max(self.newPos.y(), sceneRect.top() + 10), sceneRect.bottom() - 10)) #~ self.newPos.setX(self.pos().x()+random.randint(-10,10)) #~ self.newPos.setY(self.pos().y()+random.randint(-10,10)) if self.scene(): rect = self.scene().views()[-1].sceneRect() nodeWidth = max(self.boundingRect().width(),self.text.boundingRect().width()) nodeHeight = self.boundingRect().height()+self.text.boundingRect().height() self.newPos.setX(min(rect.right()-(nodeWidth/2), max(self.newPos.x(), rect.left()+(nodeWidth/2)))) self.newPos.setY(min(rect.bottom()-(nodeHeight/2), max(self.newPos.y(), rect.top()+(nodeHeight/2)+5))) self.a.setPosAt(1, self.newPos) self.tl.start() #def animate(self): #print "Main.animate()" #def animate_to(t,item,x,y,angle): #animation=QtGui.QGraphicsItemAnimation() #timeline=QtCore.QTimeLine(1000) #timeline.setFrameRange(0,100) #animation.setItem(item) #animation.setPosAt(t,QtCore.QPointF(x,y)) #animation.setRotationAt(t,angle) #animation.setTimeLine(timeline) #return animation ## Random animations #animation=animate_to(1,self,random.randint(0,500),random.randint(0,300),random.randint(0,0)) #animation.setPosAt(0,self.pos()) #print animation.posList() #animation.timeLine().start() #~ self.animator.start(1000) #~ def mouseReleaseEvent(self, event): #~ self.update() #~ QtGui.QGraphicsItem.mouseReleaseEvent(self, event) #~ def animate_to(self,t,item,x,y): #~ animation=QtGui.QGraphicsItemAnimation() #~ timeline=QtCore.QTimeLine(1000) #~ timeline.setFrameRange(0,100) #~ animation.setPosAt(t,QtCore.QPointF(x,y)) #~ animation.setItem(item) #~ animation.setTimeLine(timeline) #~ return animation #def calculateForces(self): #print "visualNode.calculateForces() en "+str(self.nParent.data.alias) #self.animator.start(1000) #if not self.scene() or self.scene().mouseGrabberItem() == self: ##~ self.animator.stop() #return #print "oldpos "+str(self.pos()) ##~ if self.newPos == self.pos(): ##~ return ##Sum up all forces pushing this item away #xvel = 0 #yvel = 0 #for node in self.nParent.parent.nodes: #line = QtCore.QLineF(self.mapFromItem(node.view, 0, 0), QtCore.QPointF(0, 0)) #dx = line.dx() #dy = line.dy() #l = 2.0 * (dx * dx + dy * dy) ##~ print "Distancia "+str(l) #if l > 0 : #xvel += (dx * self.repulsion) / l #yvel += (dy * self.repulsion) / l ##~ print "velx "+str(xvel)+" yvel "+str(yvel) ##Now subtract all forces pulling items together #weight = (len(self.nParent.edges) + 1) * self.weight #for edge in self.nParent.edges: #if edge.fromNode == self.nParent: #pos = self.mapFromItem(edge.toNode.view, 0, 0) #else: #pos = self.mapFromItem(edge.fromNode.view, 0, 0) #xvel += pos.x() / weight #yvel += pos.y() / weight #if math.fabs(xvel) < 0.1 and math.fabs(yvel) < 0.1: #xvel = yvel = 0 ##~ print "velx "+str(xvel)+" yvel "+str(yvel) #sceneRect = self.scene().sceneRect(); #self.newPos = self.pos() + QtCore.QPointF(xvel, yvel) #self.newPos.setX(min(max(self.newPos.x(), sceneRect.left() + 10), sceneRect.right() - 10)) #self.newPos.setY(min(max(self.newPos.y(), sceneRect.top() + 10), sceneRect.bottom() - 10)) #self.newPos.setX(self.pos().x()+random.randint(-10,10)) #self.newPos.setY(self.pos().y()+random.randint(-10,10)) #animation = self.animate_to(1,self, self.newPos.x(),self.newPos.y()) #print "\t "+str(animation.posList()) #print str(animation)+"-----------" #animation.timeLine().start() ##~ self.setPos(self.newPos) def showNodeMenu(self, event): self.scene().clearSelection() self.setSelected(True) self.contextMenu.exec_(event.screenPos()) #~ def __repr__(self): #~ string = '' #~ string = string + 'vel_x: \t' + str(self.vel_x) + '\n' #~ string = string + 'vel_x: \t' + str(self.vel_y) + '\n' #~ return string def getVisualNodesFromData(dataNodes): nodeList=[] for dNode in dataNodes: newNode = managerNode.managerNode() newNode.visual = visualNode(newNode) newNode.id = dNode.alias nodeList.append(newNode) return nodeList if __name__ == "__main__": app = QtGui.QApplication(sys.argv) a = visualNode(None) b = visualNode(None) c = visualNode(None) d = visualNode(None) e = visualNode(None) f = visualNode(None) g = visualNode(None) h = visualNode(None) grview = QtGui.QGraphicsView() grview.setRenderHints(QtGui.QPainter.Antialiasing) scene = QtGui.QGraphicsScene() #~ for node in datanodeList.nodes: #~ for edge in node.edges: #~ scene.addItem(edge.view) #~ scene.addItem(node.view) #~ node.view.timeLine.start() scene.addItem(a) scene.addItem(b) scene.addItem(c) scene.addItem(d) scene.addItem(e) scene.addItem(f) scene.addItem(g) scene.addItem(h) grview.setScene(scene) grview.show() sys.exit(app.exec_())