functionality: right click = drag the node, left click = connect radio buttons)
Code: Select all
from __future__ import division
import sys
from PySide import QtGui, QtCore
import math
import FreeCAD as App
class QAnchorNode(QtGui.QRadioButton):
"""a RadioButton which has some connection info and connections to other AnchorNodes
make new connection with left click"""
def __init__(self, parent=None, scene=None):
super(QAnchorNode, self).__init__(parent)
self.scene = scene
self.line = []
self.connection = False
self.connection_node = None
scene.node_list.append(self)
@property
def global_pos(self):
return self.parent().mapToGlobal(self.pos())
def mousePressEvent(self, event):
pos = self.global_pos
line = QtCore.QLineF(pos.x(), pos.y(), pos.x(), pos.y())
line_item = QtGui.QGraphicsLineItem(line, scene=self.scene)
line_item.setZValue(0)
self.line.append(line_item)
def mouseMoveEvent(self, event):
if event.buttons() == QtCore.Qt.LeftButton:
if len(self.line) > 0:
self.connection = True
pos = self.mapToGlobal(event.pos())
for node in self.scene.node_list:
node_pos = node.global_pos
if PointNorm(node_pos, pos) < 30 and node is not self:
self.connection_node = node
pos = node_pos
break
else:
self.connection_node = None
line = self.line[-1]
l = line.line()
x1 = l.x1()
y1 = l.y1()
line.setLine(x1, y1, pos.x(), pos.y())
def mouseReleaseEvent(self, event):
if self.connection:
if self.connection_node is not None:
line = QNodeLine(self, self.connection_node, scene=self.scene)
self.connection_node.line.append(line)
self.line[-1] = line
self.setChecked(1)
self.connection_node.setChecked(1)
self.connection_node = None
else: #(mouserelease not distinguish between right or left click)
self.line.pop(-1)
self.connection = False
class QNodeWidget(QtGui.QGraphicsProxyWidget):
"""The QGraphicsProxyWidget allows to get the Widget on the scene"""
def __init__(self, widget):
super(QNodeWidget, self).__init__()
self.setWidget(widget)
self.current_pos = None
def mousePressEvent(self, event):
if event.buttons() == QtCore.Qt.RightButton:
self.current_pos = event.pos()
else:
super(QNodeWidget, self).mousePressEvent(event)
def mouseMoveEvent(self, event):
if event.buttons() == QtCore.Qt.RightButton:
self.setPos(self.mapToParent(event.pos()) - self.current_pos)
for anchor_node in self.widget().children():
if isinstance(anchor_node, QAnchorNode):
for line in anchor_node.line:
line.update_line()
else:
super(QNodeWidget, self).mouseMoveEvent(event)
class QNodeScene(QtGui.QGraphicsScene):
"""A GraphicsScene which has a list of all the nodes"""
def __init__(self):
super(QNodeScene, self).__init__()
self.setSceneRect(0, 0, 1000, 1000)
self.node_list=[]
class QNodeView(QtGui.QGraphicsView):
def wheelEvent(self, event):
scale_value = 1 + (event.delta() / 5000)
self.scale(scale_value, scale_value)
class QNodeLine(QtGui.QGraphicsLineItem):
""" a Line Element to connect Nodes"""
def __init__(self, node1, node2, scene=None):
super(QNodeLine, self).__init__(scene=scene)
self.node1 = node1
self.node2 = node2
self.linef = QtCore.QLineF(node1.global_pos, node2.global_pos)
self.setZValue(-1)
self.setLine(self.linef)
def update_line(self):
self.linef.setP1(self.node1.global_pos)
self.linef.setP2(self.node2.global_pos)
self.setLine(self.linef)
def PointNorm(p1, p2):
return(math.sqrt((p1.x() - p2.x()) ** 2 + (p1.y() - p2.y()) ** 2))
def getMainWindow():
""" Return the FreeCAD main window. """
toplevel = QtGui.qApp.topLevelWidgets()
for i in toplevel:
if i.metaObject().className() == "Gui::MainWindow":
return i
return None
def getMdiArea():
""" Return FreeCAD MdiArea. """
mw = getMainWindow()
if not mw:
return None
childs = mw.children()
for c in childs:
if isinstance(c, QtGui.QMdiArea):
return c
return None
def test():
App.newDocument()
def createNodeView(winTitle="NodeView"):
mdi = getMdiArea()
if not mdi:
return None
scene = QNodeScene()
view = QNodeView()
view.setScene(scene)
view.setWindowTitle(winTitle)
sub = mdi.addSubWindow(view)
wid = QtGui.QWidget()
layout = QtGui.QVBoxLayout(wid)
layout.addWidget(QtGui.QLabel("text"))
qp = QtGui.QPushButton("Create new Document")
wid.connect(qp, QtCore.SIGNAL("clicked()"), test)
layout.addWidget(qp)
node1 = QAnchorNode(wid, scene)
layout.addWidget(node1)
wid2 = QtGui.QWidget()
layout2 = QtGui.QVBoxLayout(wid2)
layout2.addWidget(QtGui.QLabel("text"))
node2 = QAnchorNode(wid2, scene)
layout2.addWidget(node2)
node_wid = QNodeWidget(wid)
node_wid2 = QNodeWidget(wid2)
scene.addItem(node_wid)
scene.addItem(node_wid2)
sub.show()
createNodeView()