SafeEyes
This commit is contained in:
parent
886053b589
commit
427ff11ac4
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
|
@ -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()
|
|
@ -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
|
||||
|
Loading…
Reference in New Issue