Source code for midi.time_ruler
"""
TimeRulerWidget
"""
import mido
from PySide6.QtCore import Qt
from PySide6.QtGui import QColor, QPainter, QPaintEvent, QPen
from PySide6.QtWidgets import QWidget
from jdxi_editor.jdxi.style import JDXiStyle
[docs]
class TimeRulerWidget(QWidget):
"""
TimeRulerWidget
"""
def __init__(self, midi_file: mido.MidiFile = None, parent: QWidget = None):
super().__init__(parent)
self.setMinimumHeight(20)
self.setMaximumHeight(JDXiStyle.MAX_RULER_HEIGHT)
# List of (seconds: float, color: QColor | None, label: str | None)
[docs]
def set_midi_file(self, midi_file: mido.MidiFile) -> None:
self.midi_file = midi_file
self.midi_file_cached_total_length = self.midi_file.length
self.update()
[docs]
def paintEvent(self, event: QPaintEvent) -> None:
if not self.midi_file:
return
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
duration = self.midi_file_cached_total_length
width = self.width()
height = self.height()
num_marks = int(duration) + 1
spacing = width / duration if duration else width
font = painter.font()
font.setPointSize(8)
painter.setFont(font)
painter.setPen(QPen(Qt.white))
for second in range(num_marks):
if second % 10 == 0:
# Draw major ticks every 10 seconds
x = int(second * spacing)
painter.drawLine(x, 0, x, height)
painter.drawText(x + 2, height - 4, f"{second}s")
# Draw markers
for seconds, color, label in self._markers:
if duration <= 0:
continue
x = int((seconds / duration) * width)
pen = QPen(color if isinstance(color, QColor) else QColor(JDXiStyle.ACCENT))
pen.setWidth(2)
painter.setPen(pen)
# Marker line
painter.drawLine(x, 0, x, height // 2)
# Optional label just above midline
if label:
painter.drawText(x + 3, (height // 2) - 2, label)
[docs]
def add_marker(
self, seconds: float, color: QColor | None = None, label: str | None = None
) -> None:
"""Add a time marker in seconds and repaint."""
try:
if seconds < 0:
seconds = 0.0
except Exception:
seconds = 0.0
self._markers.append((float(seconds), color, label))
self.update()
[docs]
def clear_markers(self) -> None:
"""Clear all time markers and repaint."""
self._markers.clear()
self.update()