This commit is contained in:
Gobinath 2016-01-08 12:51:50 +05:30
parent 886053b589
commit 427ff11ac4
5 changed files with 264 additions and 0 deletions

BIN
icon-64.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

2
run Executable file
View File

@ -0,0 +1,2 @@
#!/bin/bash
python safeeyes

252
safeeyes Executable file
View File

@ -0,0 +1,252 @@
#!/usr/bin/python3
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses.
'''
import os
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.schedulers.base import BaseScheduler
from gi.repository import Gtk as gtk
from gi.repository import AppIndicator3 as appindicator
from gi.repository import Notify as notify
from gi.repository import Gtk, Gdk, GLib, Pango
import threading
import cairo
import time
import ConfigParser
config = ConfigParser.RawConfigParser()
config_file = "/home/gobinath/applications/safeeye/safeeyes.cfg"
active = True
initialized = False
scheduler = BackgroundScheduler()
APPINDICATOR_ID = 'safeeyes'
PATH = "/home/gobinath/applications/safeeye/"
job_break = None
screen = None
short_break_messages = ["Tightly close your eyes", "Roll your eyes", "Blink your eyes", "Have some water"]
long_break_messages = ["Walk for a while", "Lean back at your seat and relax"]
class FullScreenBreak(Gtk.Window):
def __init__(self):
super(FullScreenBreak, self).__init__()
self.short_break_message_index = 0
self.long_break_message_index = 0
self.break_count = 0;
self.tran_setup()
self.init_ui()
def close(self, button, name):
if(self.is_break):
self.is_break = False
if self.is_long_break():
self.long_break_message_index = (self.long_break_message_index + 1) % len(long_break_messages)
else:
self.short_break_message_index = (self.short_break_message_index + 1) % len(short_break_messages)
self.break_count = ((self.break_count + 1) % config.getint('SafeEyes', 'no_of_short_breaks_per_long_break'))
resume_eyesafe()
self.hide()
def init_ui(self):
self.connect("draw", self.on_draw)
self.set_title("Safe Eyes")
self.resize(300, 250)
self.set_keep_above(True)
self.set_position(Gtk.WindowPosition.CENTER)
vbox = Gtk.VBox(False, 0)
vbox_center = Gtk.VBox(False, 10)
hbox = Gtk.HBox(False)
valign = Gtk.Alignment()
valign.set(0.5, 0.5, 0, 0)
hbox.pack_start(valign, False, True, 0)
halign = Gtk.Alignment()
halign.set(0.5, 0.5, 0, 0)
# vbox.pack_start(halign, False, True, 0)
self.lbl_message = Gtk.Label("Take rest")
self.lbl_message.modify_font(Pango.FontDescription(config.get('SafeEyes', 'message_font')))
self.lbl_time = Gtk.Label("MM:SS")
self.btn_skip = Gtk.Button(config.get('SafeEyes', 'skip_button_text'))
self.btn_skip.connect("clicked", self.close, None)
self.btn_skip.set_size_request(20, 20)
halign.add(self.btn_skip)
vbox_center.add(self.lbl_message)
vbox_center.add(self.lbl_time)
hbox.add(halign)
vbox_center.add(hbox)
halign = Gtk.Alignment()
halign.set(0.5, 0.5, 0, 0)
halign.add(vbox_center)
vbox.pack_start(halign, True, False, 0)
self.add(vbox)
def tran_setup(self):
self.set_app_paintable(True)
screen = self.get_screen()
visual = screen.get_rgba_visual()
if visual is not None and screen.is_composited():
self.set_visual(visual)
def on_draw(self, wid, cr):
cr.set_source_rgba(.2, .2, .2, 0.9)
cr.set_operator(cairo.OPERATOR_SOURCE)
cr.paint()
cr.set_operator(cairo.OPERATOR_OVER)
def is_long_break(self):
return self.break_count == config.getint('SafeEyes', 'no_of_short_breaks_per_long_break') - 1
def countdown(self):
seconds = config.getint('SafeEyes', 'short_break_duration')
if self.is_long_break():
seconds = config.getint('SafeEyes', 'long_break_duration')
while seconds and self.is_break:
mins, secs = divmod(seconds, 60)
timeformat = '{:02d}:{:02d}'.format(mins, secs)
GLib.idle_add(lambda: self.show_time(timeformat))
time.sleep(1)
seconds -= 1
self.close(None, None)
def show_time(self, t):
self.lbl_time.set_markup("<span size='x-large' font_weight='bold' color='white'>" + t + "</span>");
def break_message(self):
message = ''
if self.is_long_break():
message = long_break_messages[self.long_break_message_index]
else:
message = short_break_messages[self.short_break_message_index]
return "<span size='xx-large' font_weight='bold' color='white'>" + message + "</span>"
def show_screen(self):
self.is_break = True
self.lbl_message.set_markup(self.break_message());
self.show_all()
self.fullscreen()
self.stick() # Show on all workplaces
if config.getboolean('SafeEyes', 'strict_break'):
self.btn_skip.hide()
else:
self.btn_skip.show()
# Start countdown timer
thread = threading.Thread(target=self.countdown)
thread.start()
def resume_eyesafe():
global job_break
if job_break:
print("Resume")
scheduler.resume_job("take_rest")
def pause_eyesafe():
global job_break
if job_break:
print("Pause")
scheduler.pause_job("take_rest")
# @scheduler.scheduled_job('interval', minutes=10)
def take_rest():
global active
# Pause the job
pause_eyesafe()
# Show a notification
notification = notify.Notification.new("<b>Safe Eyes</b>", "Ready for a break after 15 seconds.", icon=os.path.abspath(PATH + 'icon.png'))
notification.set_timeout(1000)
notification.show()
notification.close()
time.sleep(config.getint('SafeEyes', 'pre_break_warning_time'))
if active:
# Show the screen
GLib.idle_add(lambda: screen.show_screen())
def main():
indicator = appindicator.Indicator.new(APPINDICATOR_ID, os.path.abspath(PATH + 'icon-64.png'), appindicator.IndicatorCategory.SYSTEM_SERVICES)
indicator.set_status(appindicator.IndicatorStatus.ACTIVE)
indicator.set_menu(build_menu())
notify.init(APPINDICATOR_ID)
gtk.main()
def build_menu():
menu = gtk.Menu()
item_enable = gtk.CheckMenuItem('Enable SafeEyes')
item_enable.connect('activate', enable)
item_enable.set_active(True)
item_quit = gtk.MenuItem('Quit')
item_quit.connect('activate', quit)
menu.append(item_enable)
menu.append(item_quit)
menu.show_all()
return menu
def quit(_):
notify.uninit()
gtk.main_quit()
scheduler.shutdown(False)
def enable(menu):
global active
active = menu.get_active()
if active:
resume_eyesafe()
else:
pause_eyesafe()
def start_eyesafe():
screen.post_close = resume_eyesafe
scheduler.start()
global job_break
job_break = scheduler.add_job(take_rest, 'interval', minutes=config.getint('SafeEyes', 'break_interval'), id='take_rest')
if __name__ == "__main__":
# Initialize the properties
config.read(config_file)
screen = FullScreenBreak()
start_eyesafe()
main()

10
safeeyes.cfg Normal file
View File

@ -0,0 +1,10 @@
[SafeEyes]
pre_break_warning_time = 15
no_of_short_breaks_per_long_break = 5
break_interval = 15
short_break_duration = 15
long_break_duration = 60
strict_break = False
skip_button_text = Skip
message_font = Adele