""" B-ASIC port button module. """ from typing import TYPE_CHECKING from qtpy.QtCore import QMimeData, Qt, Signal from qtpy.QtGui import QDrag from qtpy.QtWidgets import QMenu, QPushButton if TYPE_CHECKING: from b_asic.GUI.drag_button import DragButton from b_asic.operation import Operation from b_asic.port import Port class PortButton(QPushButton): """ A button corresponding to a port. Parameters ---------- name : str The name of the button. operation_button : :class:`~b_asic.GUI.drag_button.DragButton` The parent DragButton. port : :class:`~b_asic.port.Port` The SFG Port. """ connectionRequested = Signal(QPushButton) moved = Signal() def __init__(self, name: str, operation_button: "DragButton", port: "Port"): super().__init__(name, parent=operation_button) self.pressed = False self._window = operation_button._window self.port = port self._operation_button = operation_button self._m_drag = False self._m_press = False self.setAcceptDrops(True) self.setCursor(Qt.ArrowCursor) self.setStyleSheet("background-color: white") self.connectionRequested.connect(self._window._connect_callback) @property def operation(self) -> "Operation": """Operation associated with PortButton.""" return self._operation_button.operation def contextMenuEvent(self, event): menu = QMenu() menu.addAction("Connect", lambda: self.connectionRequested.emit(self)) menu.exec_(self.cursor().pos()) def mousePressEvent(self, event): if event.button() == Qt.MouseButton.LeftButton: self._window._mouse_pressed = True self.select_port(event.modifiers()) super().mousePressEvent(event) def mouseReleaseEvent(self, event): if event.button() == Qt.MouseButton.LeftButton and self._window._mouse_pressed: self._window._mouse_pressed = False if self._window._mouse_dragging: self._window._mouse_dragging = False super().mouseReleaseEvent(event) def mouseMoveEvent(self, event): if self._window._mouse_pressed: self._window._mouse_dragging = True self._window._starting_port = self data = QMimeData() drag = QDrag(self) drag.setMimeData(data) drag.exec() super().mouseMoveEvent(event) def dragEnterEvent(self, event): event.acceptProposedAction() self.update() super().dragEnterEvent(event) def dragLeaveEvent(self, event): self.update() super().dragLeaveEvent(event) def dragMoveEvent(self, event): event.acceptProposedAction() super().dragMoveEvent(event) def dropEvent(self, event): event.acceptProposedAction() if self != self._window._starting_port: self.select_port(Qt.KeyboardModifier.ControlModifier) self._window._connect_callback() self.update() super().dropEvent(event) def _toggle_port(self, pressed: bool = False): self.pressed = not pressed self.setStyleSheet( f"background-color: {'white' if not self.pressed else 'grey'}" ) def select_port(self, modifiers=None): """ Select the port taking *modifiers* into account. Parameters ---------- modifiers : optional Qt keyboard modifier. """ if modifiers != Qt.KeyboardModifier.ControlModifier: for port in self._window._pressed_ports: port._toggle_port(port.pressed) self._toggle_port(self.pressed) self._window._pressed_ports = [self] else: self._toggle_port(self.pressed) if self in self._window._pressed_ports: self._window._pressed_ports.remove(self) else: self._window._pressed_ports.append(self) for arrow in self._window._arrow_ports: arrow.update()