class FWidget(QtCore.QObject): def __init__(self, node, name, layout, ui, left): super(FWidget, self).__init__() self.node = node self.name = name self.plugRect = None self.labelRect = None self.links = WeakList() self.linked = WeakList() self._over = False self._base_color = QtCore.Qt.cyan self._color = self._base_color widget = UiFactory.widget(ui) self.widget = widget if left: widget.setLayoutDirection(QtCore.Qt.RightToLeft) widget.setStyleSheet("background: green") else: widget.setLayoutDirection(QtCore.Qt.LeftToRight) widget.setStyleSheet("background: red") widget.setMouseTracking(True) widget.setFocusPolicy(QtCore.Qt.NoFocus) widget.installEventFilter(self) layout.addWidget(widget) def scene(self): return self.node.scene() @WeakProperty def node(self): return @property def over(self): return self._over @over.setter def over(self, state): if self._over == state: return self._over = state self.updateColor() self.node.update() def updateColor(self): if self._over: color = COLORS.OVER elif self.node._selected: color = COLORS.SELECTED else: color = self._base_color self._color = color for link in self.links: link.updateColor(color) @WeakProperty def widget(self): return def paint(self, painter, options, widget): if not self.widget: return if not self.plugRect: return dbg3("PAINT {0}", self) painter.setBrush(self._color) painter.drawEllipse(self.plugRect) if self.over: painter.setBrush(self._color) painter.drawRect(self.labelRect) def repaintLinks(self): for link in self.links: link.setVisible(True) link.fetchPath() link.update() for link in self.linked: link.setVisible(True) link.fetchPath() link.update() def hideLinks(self): for link in self.links: link.setVisible(False) for link in self.linked: link.setVisible(False) def __str__(self): return self.name def __repr__(self): return self.__str__() def getPlugRect(self): icon = self.widget.plug pos = icon.pos() rect = icon.rect() rect.translate(pos) rect = self.mapToParent(rect) return rect def getLabelRect(self): icon = self.widget.label pos = icon.pos() rect = icon.rect() rect.translate(pos) rect = self.mapToParent(rect) return rect def updateLayout(self): if not self.widget: return rect = self.getPlugRect() if rect == self.plugRect: return self.plugRect = rect self.labelRect = self.getLabelRect() self.updateLinks() def updateLinks(self): rect = self.plugRect if not rect: return for link in self.links: link.updatePath(root=self.mapToScene(rect.center())) for link in self.linked: link.updatePath(tip=self.mapToScene(rect.center())) def eventFilter(self, widget, event): etype = event.type() dbg4("FILTER {0} {1}", self, etype) if etype == QtCore.QEvent.Paint: self.updateLayout() elif etype == QtCore.QEvent.Enter: self.over = True elif etype == QtCore.QEvent.Leave: self.over = False elif etype == QtCore.QEvent.MouseButtonPress: self.scene().dragged = self return False def mapToParent(self, rect): p1 = self.widget.mapToParent(rect.topLeft()) p2 = self.widget.mapToParent(rect.bottomRight()) return QtCore.QRect(p1, p2) def mapToScene(self, value): return self.node.mapToScene(value) def connectField(self, target): dbg3("CONNECT {0} to {1}".format(self, target)) lnk = Link(self, target) self.scene().addItem(lnk) self.links.append(lnk) target.linked.append(lnk) lnk.fetchPath() def dropped(self, source): source.connectField(self) def disconnectField(self, target, link=None): if link is None: for item in self.links: if item.target == target: link = item break if link in self.links: self.links.remove(link) if target and link in target.linked: target.linked.remove(link) self.scene().removeItem(link) def release(self): for link in self.links: link.breakLink() for link in self.linked: link.breakLink()