Skip to content
Snippets Groups Projects
Commit 31cd1ec6 authored by Johannes Kung's avatar Johannes Kung
Browse files

Fixed SignalGraphicsItem drawing

parent a87365b1
No related branches found
No related tags found
No related merge requests found
Pipeline #134634 failed
import itertools
import math
import typing
from qtpy import QtCore
from qtpy.QtCore import QPoint, QPointF, QRectF, Qt
from qtpy.QtGui import QCursor, QPainter, QPen
from qtpy.QtGui import QCursor, QPainter, QPainterPath, QPen
from qtpy.QtWidgets import (
QGraphicsItem,
QGraphicsLineItem,
QGraphicsSceneMouseEvent,
QGraphicsWidget,
QWidget,
)
from simudator.gui.color_scheme import ColorScheme
......@@ -63,30 +65,28 @@ class SignalGraphicsItem(QGraphicsWidget):
# |
# port -----|
start_point = self.start_port.getPoint()
end_point = self.end_port.getPoint()
self._init_line_points(start_point, end_point)
# local_start = self.mapFromItem(start_port, start_point)
# local_end = self.mapFromItem(end_port, end_point)
# local_start = self.mapFromScene(start_point)
# local_end = self.mapFromScene(end_point)
local_start = start_point - self.start_port.scenePos()
local_end = end_point - self.end_port.scenePos()
start_point = self.mapFromScene(self.start_port.getPoint())
end_point = self.mapFromScene(self.end_port.getPoint())
self._init_line_points(start_point, end_point)
self.setPos(0, 0)
# Used to lock layout
self.is_locked = False
def _init_line_points(self, start_point: QPointF, end_point: QPointF) -> None:
""" """
# |---- port
# |
# port -----|
"""Initialise the visual representation of the signal as a zig-zag
between the ports of the signal.
|---- port
|
port -----|
Parameters
----------
start_point : QPointF
Point of the end of one port.
end_point : QPointF
Point of the end of the other port.
"""
half_x = (start_point.x() + end_point.x()) / 2
......@@ -109,27 +109,17 @@ class SignalGraphicsItem(QGraphicsWidget):
self.last_line_start_i = None
self.last_line_end_i = None
# Initialise the visual representation of the signal as a zig-zag
# between the ports of the signal
# |---- port
# |
# port -----|
start_point = self.start_port.getPoint()
end_point = self.end_port.getPoint()
self.points.append(start_point)
half_x = (start_point.x() + end_point.x()) / 2
self.points.append(QPointF(half_x, start_point.y()))
self.points.append(QPointF(half_x, end_point.y()))
self.points.append(end_point)
self._init_line_points(start_point, end_point)
self.setVisible(True)
self.drawSignal()
self.update()
def splitLine(self, start_point_index: int, end_point_index: int) -> None:
"""
Splits an existing line of two segments into a new line of four line
segments by adding three new points and removing the old corer.
segments by adding three new points and removing the old corner.
| -> __|
____| -> __|
......@@ -153,7 +143,7 @@ class SignalGraphicsItem(QGraphicsWidget):
else:
bot_corner = QPointF(half_point.x(), next_half_point.y())
# Remove the old corner and insteart new points in the correct288.5 order
# Remove the old corner and insert new points in the correct order
self.points.pop(end_point_index)
self.points.insert(end_point_index, next_half_point)
self.points.insert(end_point_index, bot_corner)
......@@ -167,10 +157,9 @@ class SignalGraphicsItem(QGraphicsWidget):
no line segment will be chosen as pressed and the mouse press event
is ignored.
"""
print(892734)
# Calculate and save which line segment was pressed (choose the one
# closest to the point pressed)
press_point = event.scenePos()
press_point = self.mapFromScene(event.scenePos())
line_start_i, line_end_i = self.getClosestPoints(press_point)
line_start = self.points[line_start_i]
line_end = self.points[line_end_i]
......@@ -186,34 +175,36 @@ class SignalGraphicsItem(QGraphicsWidget):
dist_to_line = self.getLineDistance(line_start, line_end, press_point)
if dist_to_line > LONGEST_CLICK_DIST:
event.ignore()
# event.accept()
# Save whether the pressed line segment is vertical or horisontal
# Save whether the pressed line segment is vertical or horizontal
# for convenience
if line_start.x() == line_end.x():
self.last_line_vertical = True
elif line_start.y() == line_end.y():
self.last_line_vertical = False
event.accept()
def mouseReleaseEvent(self, event: QGraphicsSceneMouseEvent) -> None:
"""
Calls the functions 'handleLeftClick' or 'handleRightClick' if
the user left or right clicked.
"""
print(1111111111111)
if event.button() == Qt.MouseButton.LeftButton:
self.handleLeftClick()
elif event.button() == Qt.MouseButton.RightButton:
self.handleRightClick()
event.accept()
def mouseMoveEvent(self, event: QGraphicsSceneMouseEvent) -> None:
"""
Handles moving a pressed line segment with left click. The segment is
moved horisontally of the segment itself is vertical and vice versa.
moved horizontally of the segment itself is vertical and vice versa.
The two line sgments that make up the ends of the signal are not moved
if pressed.
"""
print(22222222222222222222)
if not self.left_click or self.is_locked:
return
......@@ -224,7 +215,7 @@ class SignalGraphicsItem(QGraphicsWidget):
self.setCursor(QCursor(QtCore.Qt.SizeVerCursor))
# Retrieve which line segment to move and where to move it
current_mouse_point = event.scenePos()
current_mouse_point = self.mapFromScene(event.scenePos())
line_start = self.points[self.last_line_start_i]
line_end = self.points[self.last_line_end_i]
......@@ -235,30 +226,30 @@ class SignalGraphicsItem(QGraphicsWidget):
if line_end == self.points[0] or line_end == self.points[-1]:
return
# If the line segment is vertical, move it horisontally288.5
# If the line segment is vertical, move it horizontally
if self.last_line_vertical:
line_start.setX(current_mouse_point.x())
line_end.setX(current_mouse_point.x())
# If the line segment is horisontal, move it vertically
# If the line segment is horizontal, move it vertically
if not self.last_line_vertical:
line_start.setY(current_mouse_point.y())
line_end.setY(current_mouse_point.y())
self.drawSignal()
self.update()
def handleLeftClick(self) -> None:
self.align(
self.last_line_start_i, self.last_line_end_i, self.last_line_vertical
)
self.drawSignal()
# Reset cursor
self.setCursor(QCursor(QtCore.Qt.ArrowCursor))
self.update()
def align_search(self, start_index, ascending=False) -> int:
"""
Recursivly searches deeper into the line structure to get the smallest
Recursively searches deeper into the line structure to get the smallest
and largest index of which all points in between should be removed to
merge small line segments.
"""
......@@ -316,22 +307,27 @@ class SignalGraphicsItem(QGraphicsWidget):
return
self.splitLine(self.last_line_start_i, self.last_line_end_i)
self.drawSignal()
self.update()
def shape(self) -> QPainterPath:
# Construct the shape as the union of the shapes of the line segments
path = QPainterPath()
for line_segment in self._line_segments:
local_shape = self.mapFromItem(line_segment, line_segment.shape())
path.addPath(local_shape)
return path
def boundingRect(self):
return self.childrenBoundingRect()
def paint(self, painter, *args):
# This avoids errors, it is a pure virtual function that
# needs an implementation
def paint(
self,
painter: typing.Optional[QPainter],
option: typing.Optional['QStyleOptionGraphicsItem'],
widget: typing.Optional[QWidget] = None,
) -> None:
# Remove old lines from the GUI
painter.setPen(QPen(QtCore.Qt.red))
painter.drawLine(0, 0, 5, 0)
while self.lines:
item = self.lines.pop()
item.setParentItem(None)
painter.save()
# Remove old lines form the GUI
while self._line_segments:
......@@ -342,19 +338,12 @@ class SignalGraphicsItem(QGraphicsWidget):
# to the third point and so on
prev_point = self.points[0]
for point in self.points[1:]:
# Coordinates
# Bounded box for clicking
x1 = prev_point.x()
y1 = prev_point.y()
x2 = point.x()
y2 = point.y()
# line = QGraphicsLineItem(x1, y1, x2, y2, self)
# line.setPen(ColorScheme.Signal)
segment = LineSegment(prev_point, point, self)
self._line_segments.append(segment)
# self.lines.append(line)
prev_point = point
painter.restore()
def distance_sq(self, point1, point2):
dx = point1.x() - point2.x()
dy = point1.y() - point2.y()
......@@ -420,8 +409,8 @@ class SignalGraphicsItem(QGraphicsWidget):
# Find out whether the start or the end of the signal moved
old_start = self.points[0]
old_end = self.points[-1]
new_start = self.start_port.getPoint()
new_end = self.end_port.getPoint()
new_start = self.mapFromScene(self.start_port.getPoint())
new_end = self.mapFromScene(self.end_port.getPoint())
# Index the points that should be moved
if old_start != new_start:
......@@ -475,42 +464,19 @@ class LineSegment(QGraphicsWidget):
super().__init__(parent)
self.setFlag(QGraphicsItem.ItemIsMovable)
self._parent = parent
self._margin = 5
self._calc_area(start_pos, end_pos)
self.setPos(self._start_pos)
def _calc_area(self, start_pos: QPointF, end_pos: QPointF):
start_pos = self.mapFromItem(self._parent, start_pos)
end_pos = self.mapFromItem(self._parent, end_pos)
self._start_pos = start_pos
self._end_pos = end_pos
top_left = QPointF(
min(self._start_pos.x(), self._end_pos.x()),
min(self._start_pos.y(), self._end_pos.y()),
)
width = max(self._start_pos.x(), self._end_pos.x()) - top_left.x()
height = max(self._start_pos.y(), self._end_pos.y()) - top_left.y()
self.setGeometry(
top_left.x() - self._margin,
top_left.y() - self._margin,
width + 2 * self._margin,
height + 2 * self._margin,
)
def update_position(self, start_pos: QPointF, end_pos: QPointF):
self._calc_area(start_pos, end_pos)
self.setPos(start_pos)
self._start_pos = QPointF(0, 0)
self._end_pos = self.mapFromParent(end_pos)
def paint(self, painter: QPainter, *args):
painter.drawLine(self._start_pos, self._end_pos)
painter.setPen(QPen(QtCore.Qt.red))
painter.drawRect(self.boundingRect())
def shape(self) -> QPainterPath:
path = QPainterPath()
path.addRect(self.boundingRect())
return path
def boundingRect(self):
top_left = QPointF(
......@@ -526,21 +492,18 @@ class LineSegment(QGraphicsWidget):
height + 2 * self._margin,
)
def mouseReleaseEvent(self, event: QGraphicsSceneMouseEvent) -> None:
"""
Calls the functions 'handleLeftClick' or 'handleRightClick' if
the user left or right clicked.
"""
print(123)
return
if event.button() == Qt.MouseButton.LeftButton:
self.handleLeftClick()
elif event.button() == Qt.MouseButton.RightButton:
self.handleRightClick()
def mousePressEvent(self, event: QGraphicsSceneMouseEvent) -> None:
print(321)
def mouseMoveEvent(self, event: QGraphicsSceneMouseEvent) -> None:
print(654)
def mousePressEvent(
self, event: typing.Optional['QGraphicsSceneMouseEvent']
) -> None:
# Let the parent SignalGraphicsItem handle mouse events
event.ignore()
def mouseReleaseEvent(
self, event: typing.Optional['QGraphicsSceneMouseEvent']
) -> None:
# Let the parent SignalGraphicsItem handle mouse events
event.ignore()
def mouseMoveEvent(self, event: 'QGraphicsSceneMouseEvent | None') -> None:
# Let the parent SignalGraphicsItem handle mouse events
event.ignore()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment