Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""B-ASIC Scheduler-gui Graphics Graph Event Module.
Contains the scheduler-gui GraphicsGraphEvent class containing event filters and handlers for GraphicsGraphItem objects.
"""
from typing import Optional, overload, List
# QGraphics and QPainter imports
from qtpy.QtCore import Qt, QObject, Signal, QEvent, QPointF
from qtpy.QtGui import QCursor, QFocusEvent
from qtpy.QtWidgets import (
QGraphicsItem, QGraphicsSceneMouseEvent, QGraphicsSceneHoverEvent,
QGraphicsSceneContextMenuEvent, QGraphicsSceneDragDropEvent, QGraphicsSceneWheelEvent)
from b_asic.scheduler_gui.graphics_component_item import GraphicsComponentItem
from b_asic.scheduler_gui.graphics_axes_item import GraphicsAxesItem
from b_asic.scheduler_gui.graphics_timeline_item import GraphicsTimelineItem
# sys.settrace
# class GraphicsGraphEvent(QGraphicsItemGroup, QObject): # PySide2
class GraphicsGraphEvent: # PyQt5
"""Event filter and handlers for GraphicsGraphItem"""
class Signals(QObject): # PyQt5
"""A class respresenting signals."""
component_selected = Signal(str)
schedule_time_changed = Signal()
_axes: GraphicsAxesItem
_current_pos: QPointF
_delta_time: int
_signals: Signals # PyQt5
# component_selected = Signal(str) # PySide2
# schedule_time_changed = Signal() # PySide2
#@overload
def is_component_valid_pos(self, item: GraphicsComponentItem, pos: float) -> bool: ...
#@overload
def is_valid_delta_time(self, delta_time: int) -> bool: ...
#@overload
def set_schedule_time(self, delta_time: int) -> None: ...
# def __init__(self, parent: Optional[QGraphicsItem] = None): # PySide2
# QObject.__init__(self)
# QGraphicsItemGroup.__init__(self, parent)
def __init__(self, parent: Optional[QGraphicsItem] = None): # PyQt5
# QGraphicsItemGroup.__init__(self, parent)
# QObject.__init__(self)
super().__init__(parent=parent)
self._signals = self.Signals()
#################
#### Filters ####
#################
@overload
def installSceneEventFilters(self, filterItems: QGraphicsItem) -> None: ...
@overload
def installSceneEventFilters(self, filterItems: List[QGraphicsItem]) -> None: ...
def installSceneEventFilters(self, filterItems) -> None:
"""Installs an event filter for 'filterItems' on 'self', causing all events
for 'filterItems' to first pass through 'self's sceneEventFilter()
function. 'filterItems' can be one object or a list of objects."""
item: GraphicsComponentItem
for item in filterItems:
item.installSceneEventFilter(self)
@overload
def removeSceneEventFilters(self, filterItems: QGraphicsItem) -> None: ...
@overload
def removeSceneEventFilters(self, filterItems: List[QGraphicsItem]) -> None: ...
def removeSceneEventFilters(self, filterItems) -> None:
"""Removes an event filter on 'filterItems' from 'self'. 'filterItems' can
be one object or a list of objects."""
item: GraphicsComponentItem
for item in filterItems:
item.removeSceneEventFilter(self)
def sceneEventFilter(self, item: QGraphicsItem, event: QEvent) -> bool:
"""Returns true if the event was filtered (i.e. stopped), otherwise false.
If false is returned, the event is forwarded to the appropriate child in
the event chain."""
handler = None
if isinstance(item, GraphicsComponentItem): # one component
switch = {
# QEvent.FocusIn: self.comp_focusInEvent,
# QEvent.GraphicsSceneContextMenu: self.comp_contextMenuEvent,
# QEvent.GraphicsSceneDragEnter: self.comp_dragEnterEvent,
# QEvent.GraphicsSceneDragMove: self.comp_dragMoveEvent,
# QEvent.GraphicsSceneDragLeave: self.comp_dragLeaveEvent,
# QEvent.GraphicsSceneDrop: self.comp_dropEvent,
# QEvent.GraphicsSceneHoverEnter: self.comp_hoverEnterEvent,
# QEvent.GraphicsSceneHoverMove: self.comp_hoverMoveEvent,
# QEvent.GraphicsSceneHoverLeave: self.comp_hoverLeaveEvent,
QEvent.GraphicsSceneMouseMove: self.comp_mouseMoveEvent,
QEvent.GraphicsSceneMousePress: self.comp_mousePressEvent,
QEvent.GraphicsSceneMouseRelease: self.comp_mouseReleaseEvent,
# QEvent.GraphicsSceneMouseDoubleClick: self.comp_mouseDoubleClickEvent,
# QEvent.GraphicsSceneWheel: self.comp_wheelEvent
}
handler = switch.get(event.type())
elif isinstance(item, GraphicsTimelineItem): # the timeline
switch = {
# QEvent.GraphicsSceneHoverEnter: self.timeline_hoverEnterEvent,
# QEvent.GraphicsSceneHoverLeave: self.timeline_hoverLeaveEvent,
QEvent.GraphicsSceneMouseMove: self.timeline_mouseMoveEvent,
QEvent.GraphicsSceneMousePress: self.timeline_mousePressEvent,
QEvent.GraphicsSceneMouseRelease: self.timeline_mouseReleaseEvent,
}
handler = switch.get(event.type())
else:
raise TypeError(f"Received an unexpected event '{event.type()}' "
f"from an '{type(item).__name__}' object.")
if handler is not None:
handler(event)
return True
return False # returns False if event is ignored and pass through event to its child
# def sceneEvent(self, event: QEvent) -> bool:
# print(f'sceneEvent() --> {event.type()}')
# # event.accept()
# # QApplication.sendEvent(self.scene(), event)
# return False
###############################################
#### Event Handlers: GraphicsComponentItem ####
###############################################
def comp_focusInEvent(self, event: QFocusEvent) -> None: ...
def comp_contextMenuEvent(self, event: QGraphicsSceneContextMenuEvent) -> None: ...
def comp_dragEnterEvent(self, event: QGraphicsSceneDragDropEvent) -> None: ...
def comp_dragMoveEvent(self, event: QGraphicsSceneDragDropEvent) -> None: ...
def comp_dragLeaveEvent(self, event: QGraphicsSceneDragDropEvent) -> None: ...
def comp_dropEvent(self, event: QGraphicsSceneDragDropEvent) -> None: ...
def comp_hoverEnterEvent(self, event: QGraphicsSceneHoverEvent) -> None: ...
def comp_hoverMoveEvent(self, event: QGraphicsSceneHoverEvent) -> None: ...
def comp_hoverLeaveEvent(self, event: QGraphicsSceneHoverEvent) -> None: ...
def comp_mouseMoveEvent(self, event: QGraphicsSceneMouseEvent) -> None:
"""Set the position of the graphical element in the graphic scene,
translate coordinates of the cursor within the graphic element in the
coordinate system of the parent object. The object can only move
horizontally in x-axis scale steps."""
# Qt.DragMoveCursor
# button = event.button()
item: GraphicsComponentItem = self.scene().mouseGrabberItem()
dx = (item.mapToParent(event.pos()) - self._current_pos).x()
if dx > 0.505:
pos = item.x() + 1.0
if self.is_component_valid_pos(item, pos):
# self.prepareGeometryChange()
item.setX(pos)
self._current_pos.setX(self._current_pos.x() + 1.0)
self._redraw_lines(item)
elif dx < -0.505:
pos = item.x() - 1.0
if self.is_component_valid_pos(item, pos):
# self.prepareGeometryChange()
item.setX(pos)
self._current_pos.setX(self._current_pos.x() - 1.0)
self._redraw_lines(item)
def comp_mousePressEvent(self, event: QGraphicsSceneMouseEvent) -> None:
"""Changes the cursor to ClosedHandCursor when grabbing an object and
stores the current position in item's parent coordinates. 'event' will
by default be accepted, and this item is then the mouse grabber. This
allows the item to receive future move, release and double-click events."""
item: GraphicsComponentItem = self.scene().mouseGrabberItem()
self._signals.component_selected.emit(item.op_id)
# self.component_selected.emit(item.op_id)
self._current_pos = item.mapToParent(event.pos())
item.setCursor(QCursor(Qt.ClosedHandCursor))
event.accept()
def comp_mouseReleaseEvent(self, event: QGraphicsSceneMouseEvent) -> None:
"""Changes the cursor to OpenHandCursor when releasing an object."""
item: GraphicsComponentItem = self.scene().mouseGrabberItem()
item.setCursor(QCursor(Qt.OpenHandCursor))
self.set_new_starttime(item)
def comp_mouseDoubleClickEvent(self, event: QGraphicsSceneMouseEvent) -> None: ...
def comp_wheelEvent(self, event: QGraphicsSceneWheelEvent) -> None: ...
###############################################
#### Event Handlers: GraphicsLineTem ####
###############################################
def timeline_mouseMoveEvent(self, event: QGraphicsSceneMouseEvent) -> None:
"""Set the position of the graphical element in the graphic scene,
translate coordinates of the cursor within the graphic element in the
coordinate system of the parent object. The object can only move
horizontally in x-axis scale steps."""
# Qt.DragMoveCursor
# button = event.button()
def update_pos(item, delta_x):
pos = item.x() + delta_x
if self.is_valid_delta_time(self._delta_time + delta_x):
# self.prepareGeometryChange()
item.setX(pos)
self._current_pos.setX(self._current_pos.x() + delta_x)
self._delta_time += delta_x
item.set_text(self._delta_time)
item: GraphicsTimelineItem = self.scene().mouseGrabberItem()
delta_x = (item.mapToParent(event.pos()) - self._current_pos).x()
if delta_x > 0.505:
update_pos(item, 1)
elif delta_x < -0.505:
update_pos(item, -1)
def timeline_mousePressEvent(self, event: QGraphicsSceneMouseEvent) -> None:
"""Stores the current position in item's parent coordinates. 'event' will
by default be accepted, and this item is then the mouse grabber. This
allows the item to receive future move, release and double-click events."""
item: GraphicsTimelineItem = self.scene().mouseGrabberItem()
self._delta_time = 0
item.set_text(self._delta_time)
item.show_label()
self._current_pos = item.mapToParent(event.pos())
event.accept()
def timeline_mouseReleaseEvent(self, event: QGraphicsSceneMouseEvent) -> None:
"""Updates the schedule time."""
item: GraphicsTimelineItem = self.scene().mouseGrabberItem()
item.hide_label()
if self._delta_time != 0:
self.set_schedule_time(self._delta_time)
self._signals.schedule_time_changed.emit()