Last active
September 23, 2017 07:13
-
-
Save entrity/685894af0642fc31a906 to your computer and use it in GitHub Desktop.
Python timer app with a GUI for time input and display of time remaining. When timer expires, it jiggles the icon in the unity launcher until the GUI window receives a focus-in event.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Desktop Entry] | |
Name=My Timer | |
Exec=/home/markham/scripts/timer.py | |
Icon=/usr/share/icons/cute.jpg | |
Type=Application | |
Terminal=false | |
StartupNotify=true | |
Categories=GTK;GNOME;Utility; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
DESKTOP_FILE_NAME = 'my-timer.desktop' # you need to create this file | |
INITIAL_TEXT = '0:0:1' | |
from gi.repository import Unity, GObject, Gtk | |
import re, StringIO | |
class TimerWindow(Gtk.Window): | |
def __init__(self): | |
Gtk.Window.__init__(self, title="My Timer") | |
self.connect("delete-event", Gtk.main_quit) | |
box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6) | |
self.add(box) | |
self.entry = Gtk.Entry() | |
self.entry.set_text(INITIAL_TEXT) | |
self.entry.connect("activate", self.activate_entry) | |
# self.focus_btn = Gtk.Button() | |
# self.focus_btn.set_label(u"\u2766") | |
box.add(self.entry) | |
# box.add(self.focus_btn) | |
self.show_all() | |
self.finished = False | |
def reset(self, a, b): | |
self.disconnect(self.focus_in_handler) | |
self.finished = False | |
print 'reset' | |
def activate_entry(self, entry): | |
self.start_time = GObject.get_current_time() | |
text = entry.get_text() | |
print text | |
arr = re.split('\D+', text) | |
n = len(arr) | |
hr = int(arr[-3]) if n >= 3 else 0 | |
mn = int(arr[-2] or 0) if n >= 2 else int(arr[0]) | |
sc = int(arr[-1]) if n >= 2 else 0 | |
self.total_seconds = sc + 60*mn + 360*hr | |
print 'Timer for', self.total_seconds, 'seconds' | |
launcher.set_property('progress_visible', True) | |
self.set_focus(None) | |
self.update_progress() | |
GObject.timeout_add_seconds(1, self.update_progress) | |
def update_progress(self): | |
delta = GObject.get_current_time() - self.start_time | |
progress = delta / self.total_seconds | |
if progress >= 1: | |
if not self.finished: | |
self.finished = True | |
launcher.set_property('progress_visible', False) | |
self.entry.set_text("TIME'S UP!") | |
GObject.timeout_add(200, self.jiggle_unity) | |
message = Gtk.MessageDialog(None, Gtk.DialogFlags.MODAL, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, "TIME'S UP!") | |
message.set_keep_above(True) | |
btn = message.get_child().get_children()[1].get_children()[0] | |
btn.connect('activate', lambda x: message.close()) | |
btn.connect('clicked', lambda x: message.close()) | |
message.run() # Blocks. Should return -4; Before calling this, I could add self.set_focus(message), but I don't want to accidentally hit Enter at the wrong moment and miss seeing the modal dialog | |
self.focus_in_handler = self.connect("focus-in-event", self.reset) | |
message.close() | |
self.set_focus(self.entry) | |
return False | |
else: | |
launcher.set_property('progress', progress) | |
if not self.entry.has_focus(): | |
remaining = self.total_seconds - delta | |
mn = remaining / 60 | |
hr = mn / 60 | |
stamp = StringIO.StringIO() | |
stamp.write('%d:%02d:%02d' % (hr, mn%60, remaining%60)) | |
self.entry.set_text(stamp.getvalue()) | |
return True | |
def jiggle_unity(self): | |
if self.finished: | |
urgent = launcher.get_property('urgent') | |
launcher.set_property('urgent', not urgent) | |
return True | |
else: | |
return False | |
launcher = Unity.LauncherEntry.get_for_desktop_id(DESKTOP_FILE_NAME) | |
win = TimerWindow() | |
Gtk.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It would be nice if you can integrate with messaging menu integration as well.