summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUltrabug <ultrabug@gentoo.org>2013-04-16 10:02:26 +0200
committerUltrabug <ultrabug@gentoo.org>2013-04-16 10:02:26 +0200
commiteb2b4e9006629413df9eb5c64d40a923e44131f6 (patch)
tree851e87e426f893c25d36bc3a0ecfac0921b90540
parente45935a24953837498db7a68c4851d81825e4e7b (diff)
enhanced self key binding pomodoro example as discussed with Fandekasp
-rw-r--r--examples/pomodoro.py220
1 files changed, 122 insertions, 98 deletions
diff --git a/examples/pomodoro.py b/examples/pomodoro.py
index 2094448..df15be4 100644
--- a/examples/pomodoro.py
+++ b/examples/pomodoro.py
@@ -1,130 +1,154 @@
"""
-REQUIREMENTS
-------------
-* libnotify
-* python-gobject
-
-
-INSTALLATION
-------------
-Please add the following lines in your ~/.i3/config file::
-
- bindsym $mod+minus exec echo "stop" > ~/.i3/pomodoro.log
- bindsym $mod+equal exec echo "pause" > ~/.i3/pomodoro.log
- bindsym $mod+plus exec echo "start" > ~/.i3/pomodoro.log
+Pomodoro countdown on i3bar originally written by @Fandekasp (Adrien Lemaire)
+Requires:
+ - libnotify
+ - python-gobject
+ - python-keybinder
"""
-from datetime import timedelta
from gi.repository import Notify
-import os.path
-from time import time
+from gi.repository import GObject as gobject
+#FIXME: keybinder gobject collides with Notify but its not blocking
+import keybinder
+import gtk
-LOG_FILE = os.path.join(os.path.expanduser('~'), '.i3', 'pomodoro.log')
-LONG_REST = 1800 # 60 * 30
-NB_REST = 4
-POMO = 1500 # 60 * 25
-POSITION = 0
-SHORT_REST = 300 # 60 * 5
+from threading import Thread
+from time import time
+from time import sleep
+KEY_PAUSE = '<Mod1>B' #Alt + B(reak)
+KEY_START = '<Mod1>P' #Alt + P(omodoro)
+KEY_STOP = '<Mod1>R' #Alt + R(eset)
+MAX_BREAKS = 4
+POSITION = 0
+TIMER_POMODORO = 25 * 60
+TIMER_BREAK = 5 * 60
+TIMER_LONG_BREAK = 15 * 60
-class Py3status:
+pomo_thread = None
+gobject.threads_init()
+
+class Pomodoro(Thread):
"""
- Pomodoro method
+ Handles Pomodoro and Break countdowns
"""
- pomo = POMO
- rest = SHORT_REST
- nb_rest = NB_REST
+ def __init__(self):
+ """
+ Well, default values
+ """
+ Thread.__init__(self)
+ self.kill = False
+ self.callback('stop')
@property
def response(self):
- return {
- 'cached_until' : time(),
- 'full_text': '',
- 'name': 'pomodoro',
- }
-
- def pomodoro(self, json, i3status_config):
"""
- This function will update a timer in the i3status bar for 25 minutes,
- then print a red "Break time" message for 5 minutes.
+ Return the response full_text string
"""
- status = self.get_status()
+ return '%s (%d)' % (self.prefix, self.timer)
+ def callback(self, status):
+ """
+ Called on a keybinder event
+ """
+ self.status = status
if status == 'stop':
- self.pomo = POMO
- self.rest = SHORT_REST
- self.nb_rest = NB_REST
- return (POSITION, self.response)
+ self.prefix = 'Pomodoro'
+ self.status = 'stop'
+ self.timer = TIMER_POMODORO
+ self.breaks = 1
- # Else run normally
- if not self.pomo:
- if status != 'pause':
- self.rest -= 1
- timer = self.rest
- self.full_text = 'Break time'
- color = 'color_bad'
- else:
- if status != 'pause':
- self.pomo -= 1
- timer = self.pomo
- self.full_text = 'Pomodoro'
- color = 'color_degraded'
-
- if status == 'pause':
- color = 'color_good'
+ elif status == 'start':
+ self.prefix = 'Pomodoro'
+ self.timer = TIMER_POMODORO
- if not timer:
- # Pomodoro or Rest is finished, send notification
- self.send_notification()
+ elif status == 'pause':
+ self.prefix = 'Break #%d' % self.breaks
+ if self.breaks > MAX_BREAKS:
+ self.timer = TIMER_LONG_BREAK
+ self.breaks = 1
+ else:
+ self.breaks += 1
+ self.timer = TIMER_BREAK
- response = self.response
- response.update({
- 'color': i3status_config[color],
- 'full_text': '{}: {}'.format(
- self.full_text, str(timedelta(seconds=timer))[2:]),
- })
-
- return (POSITION, response)
+ def stop(self):
+ """
+ Exit nicely
+ """
+ self.kill = True
- def get_status(self):
+ def notify(self):
"""
- Read the log file and get the status value. Value is modifying via
- i3 key mapping.
+ Print a visual message
+ """
+ try:
+ Notify.init('')
+ notification = Notify.Notification.new (
+ '<b>Attention:</b>',
+ '{} is finished'.format(self.response),
+ 'dialog-information',
+ )
+ notification.show()
+ except Exception as err:
+ pass
- Value can be:
- * start
- * pause
- * stop (default)
+ def run(self):
+ """
+ Infinite loop setting the keybinder and waiting for key events
"""
- if not os.path.isfile(LOG_FILE):
- return 'stop'
+ bindings = {
+ 'pause': KEY_PAUSE,
+ 'start': KEY_START,
+ 'stop' : KEY_STOP,
+ }
+ for status, keystr in bindings.items():
+ keybinder.bind(keystr, self.callback, status)
- with open(LOG_FILE, 'r') as f:
- status = f.read()
+ while not self.kill:
+ gtk.main_iteration(block=False)
+ if self.status != 'stop' and self.timer > 0:
+ self.timer -= 1
+ if self.timer == 0:
+ self.notify()
+ sleep(1)
- return status.rstrip('\n')
+ for status, keystr in bindings.items():
+ try:
+ keybinder.unbind(keystr)
+ except Exception as e:
+ pass
- def send_notification(self):
+class Py3status:
+ """
+ Main py3status class which spawns a thread for Pomodoro keybinder
+ """
+ def kill(self):
"""
- Print a visual message
+ Exit nicely
"""
+ pomo_thread.stop()
- Notify.init('Pomodoro')
- notification = Notify.Notification.new (
- '<b>Attention:</b>',
- '{} is finished'.format(self.full_text),
- 'dialog-information',
- )
- notification.show()
+ def pomodoro(self, json, i3status_config):
+ """
+ Pomodoro response handling
+ """
+ response = {'full_text' : '', 'name' : 'pomodoro'}
+
+ global pomo_thread
- if not self.rest:
- # Rest is finished, reinitialize data
- self.nb_rest -= 1
- self.pomo = POMO
- self.rest = SHORT_REST
+ if not pomo_thread:
+ pomo_thread = Pomodoro()
+ pomo_thread.start()
+ else:
+ response['full_text'] = pomo_thread.response
+
+ if pomo_thread.status == 'start':
+ response['color'] = i3status_config['color_good']
+ elif pomo_thread.status == 'pause':
+ response['color'] = i3status_config['color_degraded']
+ else:
+ response['color'] = i3status_config['color_bad']
- if not self.nb_rest:
- # Number of small rest reached, go for long rest
- self.rest = LONG_REST
- self.nb_rest = NB_REST
+ response['cached_until'] = time()
+ return (POSITION, response)