Get the hierarchy of objects in QGraphicsScene right
For now, the Occurrence
class (derived from the QGraphicsRectItem
class) has the correct hierarchical dependence on the timeline to which it is associated. Indeed, in its __init__
method, there is this: super().__init__(timeline)
. Furthermore, the initial positioning of an Occurrence
item, in the timeline, is also done in the __init__
method.
The Occurrence
class provides a method for changing the rectangle coordinates: update_rect
. This method accepts an argument new_rect
that is never used (it should be removed from the method signature). Actually, this new_rect
variable is always set to self.time_pane.scene.sceneRect()
, in order to adjust the beginning and the end X positions of the occurrence. (N.B.: self.time_pane.scene.sceneRect()
is the actual GraphicsScene rectangle, which is zoomable.). It should instead use the Timeline
in which it is included, in order to compute its width.
The Timeline
graphics item is defined as the rectangle that comprises the TimelineLabel
object and the Occurrence
objects appearing on it. This means that the Occurrence object must have access to the TimeLabel
's height (via self.timeline.label.FIXED_HEIGHT
), in order to determine its own height. This breaks the hierarchical organization and could be fixed by making the Timeline
object have two independent children, say TimelineTitle
(containing the timeline title) and TimelineTrack
(containing the Occurrence
objects).
Contrary to the Occurrence
object, the TimeLine
object is added directly to the scene via the command self.time_pane.scene.addItem(self)
in its method add_to_scene
. This method is only called in the method TimePane.add_timeline
. The method Timeline.add_to_scene
heavily references the TimePane
object. For this reason, its code should be moved into the TimePane
class.
The order of the calls to Timeline.add_to_scene
matters for the positioning of the timelines. Indeed, they are added sequentially, from top to bottom, and their positioning is rigid. There are no provisions for changing the positions inside the time pane. However, this seems easy to implement.
Things become less clear at the level of the TimePane
object. Indeed, it is derived from QWidget
and included as a component of the QSplitter
object of MainWindow
. It looks like a level up in the hierarchy, as regards the timelines. However, this is the actual relationship:
TimePane(QWidget) ⇒ QVBoxLayout ⇒ ZoomableGraphicsView(QGraphicsView) ⇒ QGraphicsScene ⇒ Timeline [, Timeline, …]
The later object, a QGraphicsScene
is created in TimePane.__init__
and passed as the first argument of ZoomableGraphicsView.__init__
. This is a little bit intricate. In particular, the information of the “height” of the time pane is kept in the TimePane
class, which is many layers above the timelines.
A possible improvement of the code would include the following transformations (following the hierarchy, from top to bottom):
-
ZoomableGraphicsView
⇒TimePaneView
(derived fromQGraphicsView
, to be included in the layout ofMainWindow
) -
TimePane.scene
⇒TimePaneScene
(derived fromQGraphicsScene
) - (new)
TimePane
(derived fromQGraphicsRectItem
, will be the parent of the timeline objects)
One of the reasons for having the new TimePane
object as defined above is to better managed the height of the scene. For now, it is managed by manually changing the height of the QGraphicsScene
object in TimePane.add_timeline
.