92 lines
2.1 KiB
Python
92 lines
2.1 KiB
Python
|
#!/usr/bin/env python3
|
||
|
|
||
|
import gi, threading
|
||
|
gi.require_version('Gtk', '3.0')
|
||
|
from gi.repository import Gtk, GObject
|
||
|
|
||
|
def time_to_str(stamp = 0):
|
||
|
m = stamp // 60
|
||
|
s = stamp % 60
|
||
|
if m < 10:
|
||
|
m = f"0{m}"
|
||
|
if s < 10:
|
||
|
s = f"0{s}"
|
||
|
return f"{m}:{s}"
|
||
|
|
||
|
|
||
|
class Slider(Gtk.Scale):
|
||
|
def __init__(self, width = 256, height = 5):
|
||
|
Gtk.Scale.__init__(self)
|
||
|
|
||
|
self.set_name('Slider')
|
||
|
self.set_range(0, 100)
|
||
|
self.set_size_request(width, height)
|
||
|
self.set_draw_value(False)
|
||
|
|
||
|
|
||
|
class Timebar(Gtk.Fixed):
|
||
|
|
||
|
__gsignals__ = {
|
||
|
'seeked': (GObject.SignalFlags.RUN_FIRST, None, (float,))
|
||
|
}
|
||
|
|
||
|
def __init__(self):
|
||
|
Gtk.Fixed.__init__(self)
|
||
|
|
||
|
self.timer = None
|
||
|
self.pending = False
|
||
|
|
||
|
self._duration = 0
|
||
|
self._time = 0
|
||
|
|
||
|
self.slider = Slider(272)
|
||
|
self.curr = Gtk.Label()
|
||
|
self.duration = Gtk.Label()
|
||
|
|
||
|
self.curr.set_name('text')
|
||
|
self.curr.set_selectable(False)
|
||
|
self.duration.set_name('text')
|
||
|
self.duration.set_selectable(False)
|
||
|
self.duration.set_justify(Gtk.Justification.RIGHT)
|
||
|
self.duration.set_xalign(1)
|
||
|
|
||
|
self.slider.connect('change-value', self.debounce)
|
||
|
self.slider.set_sensitive(False)
|
||
|
|
||
|
self.put(self.curr, 3, 0)
|
||
|
self.put(self.duration, 233, 0)
|
||
|
self.put(self.slider, 0, 12)
|
||
|
|
||
|
|
||
|
def update_time(self, curr = 0, duration = 0):
|
||
|
self._duration = duration
|
||
|
self._time = curr
|
||
|
self.slider.set_sensitive(duration > 0)
|
||
|
if duration == 0:
|
||
|
self.curr.set_text('')
|
||
|
self.duration.set_text('')
|
||
|
self.slider.set_value(0)
|
||
|
else:
|
||
|
progress = curr * 100 / duration
|
||
|
self.curr.set_text(time_to_str(curr))
|
||
|
self.duration.set_text(time_to_str(duration))
|
||
|
# 优化拖拽进度时的更新
|
||
|
if not self.pending:
|
||
|
self.slider.set_value(progress)
|
||
|
|
||
|
|
||
|
|
||
|
def on_timeupdate(self):
|
||
|
self.pending = False
|
||
|
p = self.slider.get_value()
|
||
|
time = p * self._duration / 100
|
||
|
self.emit('seeked', time)
|
||
|
|
||
|
|
||
|
def debounce(self, slider, a, b):
|
||
|
if self.timer is not None:
|
||
|
self.timer.cancel()
|
||
|
|
||
|
self.pending = True
|
||
|
self.timer = threading.Timer(0.2, self.on_timeupdate)
|
||
|
self.timer.start()
|