2025-03-01 12:22:44 +01:00

124 lines
4.3 KiB
Python

import subprocess
import gi
from timer import Timer
gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
from gi.repository import GLib, Gio, Gtk, Adw
class Application(Adw.Application):
def __init__(self) -> None:
super().__init__(application_id='de.p1st.dndbuster')
self.window: AppWindow | None = None
def do_activate(self) -> None:
# Windows are associated with the application.
# When the last one is closed the application shuts down.
self.window = AppWindow(application=self)
self.window.present()
action = Gio.SimpleAction.new('restart-timer', None)
action.connect('activate', self.on_notification_button_restart)
self.add_action(action)
def send_notification_timeout(self) -> None:
notification = Gio.Notification()
notification.set_title('Timeout')
notification.set_body('The time is over and your do-not-disturb mode just got busted!')
notification.set_priority(Gio.NotificationPriority.URGENT)
notification.add_button(label='Restart', detailed_action='app.restart-timer')
self.send_notification(id=f'{self.get_application_id()}.{Timer.current_time()}', notification=notification)
# https://0pointer.de/public/sound-naming-spec.html
sound_name = 'alarm-clock-elapsed'
subprocess.run(['canberra-gtk-play', '-i', sound_name])
def on_notification_button_restart(self, _action: Gio.SimpleAction, _other: None):
self.window.restart()
class AppWindow(Gtk.ApplicationWindow):
def __init__(self, application: Application) -> None:
super().__init__(application=application, title='DnDBuster')
self.app = application
self.set_default_size(400, 200)
self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.box.set_spacing(10)
self.box.set_margin_top(10)
self.box.set_margin_bottom(10)
self.box.set_margin_start(10)
self.box.set_margin_end(10)
self.set_child(self.box)
self.button_start_restart = Gtk.Button(label='Start')
self.button_start_restart.connect('clicked', self.on_button_start_restart_clicked)
self.box.append(self.button_start_restart)
self.button_pause_resume = Gtk.Button(label='Pause', visible=False)
self.button_pause_resume.connect('clicked', self.on_button_pause_resume_clicked)
self.box.append(self.button_pause_resume)
self.progress_bar = Gtk.ProgressBar(visible=False)
self.box.append(self.progress_bar)
self.timer = Timer()
def on_button_start_restart_clicked(self, _widget) -> None:
if not self.timer.is_started():
self.start()
else:
self.restart()
def on_button_pause_resume_clicked(self, _widget) -> None:
if self.timer.is_paused():
self.timer.resume()
self.regularly_update_progress_bar()
else:
self.timer.pause()
self.update_pause_resume_label()
def start(self):
self.reset_start_timer()
self.button_start_restart.set_label('Restart')
self.button_pause_resume.set_visible(True)
def restart(self):
self.reset_start_timer()
self.update_pause_resume_label()
def update_pause_resume_label(self) -> None:
if self.timer.is_paused():
self.button_pause_resume.set_label('Resume')
else:
self.button_pause_resume.set_label('Pause')
def reset_start_timer(self) -> None:
self.timer.reset()
self.timer.start()
self.progress_bar.set_visible(True)
self.regularly_update_progress_bar()
def regularly_update_progress_bar(self) -> None:
# Start regularly calling update_progress()
GLib.timeout_add_seconds(1, self.update_progress_bar)
def update_progress_bar(self) -> bool:
total_min = 25
total_sec = total_min * 60
delta_sec = self.timer.read()
progress = delta_sec / total_sec
self.progress_bar.set_fraction(progress)
if progress >= 1:
self.app.send_notification_timeout()
# Stop regularly calling update_progress()
return False
# Weather to continue regularly calling update_progress()
return not self.timer.is_paused()