Merge pull request #504 from slgobinath/feature-long-break-friendly-tray-icon
#347 Take short or long breaks from tray
This commit is contained in:
commit
d20894a7c4
|
@ -456,6 +456,18 @@ msgstr ""
|
||||||
msgid "Take a break now"
|
msgid "Take a break now"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/trayicon
|
||||||
|
msgid "Any break"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/trayicon
|
||||||
|
msgid "Short break"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/trayicon
|
||||||
|
msgid "Long break"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: plugins/trayicon
|
#: plugins/trayicon
|
||||||
msgid "Until restart"
|
msgid "Until restart"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
@ -131,7 +131,7 @@ class SafeEyesCore:
|
||||||
logging.debug("Postpone the break for %d seconds", self.postpone_duration)
|
logging.debug("Postpone the break for %d seconds", self.postpone_duration)
|
||||||
self.context['postponed'] = True
|
self.context['postponed'] = True
|
||||||
|
|
||||||
def take_break(self):
|
def take_break(self, break_type = None):
|
||||||
"""
|
"""
|
||||||
Calling this method stops the scheduler and show the next break screen
|
Calling this method stops the scheduler and show the next break screen
|
||||||
"""
|
"""
|
||||||
|
@ -139,15 +139,15 @@ class SafeEyesCore:
|
||||||
return
|
return
|
||||||
if not self.context['state'] == State.WAITING:
|
if not self.context['state'] == State.WAITING:
|
||||||
return
|
return
|
||||||
utility.start_thread(self.__take_break)
|
utility.start_thread(self.__take_break, break_type=break_type)
|
||||||
|
|
||||||
def has_breaks(self):
|
def has_breaks(self, break_type = None):
|
||||||
"""
|
"""
|
||||||
Check whether Safe Eyes has breaks or not.
|
Check whether Safe Eyes has breaks or not. Use the break_type to check for either short or long break.
|
||||||
"""
|
"""
|
||||||
return not self.break_queue.is_empty()
|
return not self.break_queue.is_empty(break_type)
|
||||||
|
|
||||||
def __take_break(self):
|
def __take_break(self, break_type = None):
|
||||||
"""
|
"""
|
||||||
Show the next break screen
|
Show the next break screen
|
||||||
"""
|
"""
|
||||||
|
@ -167,7 +167,7 @@ class SafeEyesCore:
|
||||||
time.sleep(1) # Wait for 1 sec to ensure the sceduler is dead
|
time.sleep(1) # Wait for 1 sec to ensure the sceduler is dead
|
||||||
self.running = True
|
self.running = True
|
||||||
|
|
||||||
utility.execute_main_thread(self.__fire_start_break)
|
utility.execute_main_thread(self.__fire_start_break, break_type)
|
||||||
|
|
||||||
def __scheduler_job(self):
|
def __scheduler_job(self):
|
||||||
"""
|
"""
|
||||||
|
@ -243,9 +243,10 @@ class SafeEyesCore:
|
||||||
self.__wait_for(self.postpone_duration)
|
self.__wait_for(self.postpone_duration)
|
||||||
utility.execute_main_thread(self.__fire_start_break)
|
utility.execute_main_thread(self.__fire_start_break)
|
||||||
|
|
||||||
def __fire_start_break(self):
|
def __fire_start_break(self, break_type = None):
|
||||||
|
break_obj = self.break_queue.get_break(break_type)
|
||||||
# Show the break screen
|
# Show the break screen
|
||||||
if not self.on_start_break.fire(self.break_queue.get_break()):
|
if not self.on_start_break.fire(break_obj):
|
||||||
# Plugins want to ignore this break
|
# Plugins want to ignore this break
|
||||||
self.__start_next_break()
|
self.__start_next_break()
|
||||||
return
|
return
|
||||||
|
@ -258,15 +259,14 @@ class SafeEyesCore:
|
||||||
# Wait in user thread
|
# Wait in user thread
|
||||||
utility.start_thread(self.__postpone_break)
|
utility.start_thread(self.__postpone_break)
|
||||||
else:
|
else:
|
||||||
self.start_break.fire(self.break_queue.get_break())
|
self.start_break.fire(break_obj)
|
||||||
utility.start_thread(self.__start_break)
|
utility.start_thread(self.__start_break, break_obj = break_obj)
|
||||||
|
|
||||||
def __start_break(self):
|
def __start_break(self, break_obj):
|
||||||
"""
|
"""
|
||||||
Start the break screen.
|
Start the break screen.
|
||||||
"""
|
"""
|
||||||
self.context['state'] = State.BREAK
|
self.context['state'] = State.BREAK
|
||||||
break_obj = self.break_queue.get_break()
|
|
||||||
countdown = break_obj.duration
|
countdown = break_obj.duration
|
||||||
total_break_time = countdown
|
total_break_time = countdown
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,6 @@ class BreakQueue:
|
||||||
self.__current_break = None
|
self.__current_break = None
|
||||||
self.__current_long = 0
|
self.__current_long = 0
|
||||||
self.__current_short = 0
|
self.__current_short = 0
|
||||||
self.__shorts_taken = 0
|
|
||||||
self.__short_break_time = config.get('short_break_interval')
|
self.__short_break_time = config.get('short_break_interval')
|
||||||
self.__long_break_time = config.get('long_break_interval')
|
self.__long_break_time = config.get('long_break_interval')
|
||||||
self.__is_random_order = config.get('random_order')
|
self.__is_random_order = config.get('random_order')
|
||||||
|
@ -113,15 +112,18 @@ class BreakQueue:
|
||||||
while brk != current_break and brk.name != last_break:
|
while brk != current_break and brk.name != last_break:
|
||||||
brk = self.next()
|
brk = self.next()
|
||||||
|
|
||||||
def get_break(self):
|
def get_break(self, break_type = None):
|
||||||
if self.__current_break is None:
|
if self.__current_break is None:
|
||||||
self.__current_break = self.next()
|
self.__current_break = self.next(break_type)
|
||||||
|
elif break_type is not None and self.__current_break.type != break_type:
|
||||||
|
self.__current_break = self.next(break_type)
|
||||||
|
|
||||||
return self.__current_break
|
return self.__current_break
|
||||||
|
|
||||||
def is_long_break(self):
|
def is_long_break(self):
|
||||||
return self.__current_break is not None and self.__current_break.type == BreakType.LONG_BREAK
|
return self.__current_break is not None and self.__current_break.type == BreakType.LONG_BREAK
|
||||||
|
|
||||||
def next(self):
|
def next(self, break_type = None):
|
||||||
break_obj = None
|
break_obj = None
|
||||||
shorts = self.__short_queue
|
shorts = self.__short_queue
|
||||||
longs = self.__long_queue
|
longs = self.__long_queue
|
||||||
|
@ -133,22 +135,11 @@ class BreakQueue:
|
||||||
break_obj = self.__next_long()
|
break_obj = self.__next_long()
|
||||||
elif longs is None:
|
elif longs is None:
|
||||||
break_obj = self.__next_short()
|
break_obj = self.__next_short()
|
||||||
elif longs[self.__current_long].time <= shorts[self.__current_short].time:
|
elif break_type == BreakType.LONG_BREAK or longs[self.__current_long].time <= shorts[self.__current_short].time:
|
||||||
break_obj = self.__next_long()
|
break_obj = self.__next_long()
|
||||||
else:
|
else:
|
||||||
break_obj = self.__next_short()
|
break_obj = self.__next_short()
|
||||||
|
|
||||||
# Shorts and longs exist -> set cycle on every long
|
|
||||||
if break_obj.type == BreakType.LONG_BREAK:
|
|
||||||
self.context['new_cycle'] = True
|
|
||||||
self.__shorts_taken = 0
|
|
||||||
# Only shorts exist -> set cycle when enough short breaks pass
|
|
||||||
elif self.__shorts_taken == self.__cycle_len:
|
|
||||||
self.context['new_cycle'] = True
|
|
||||||
self.__shorts_taken = 0
|
|
||||||
else:
|
|
||||||
self.context['new_cycle'] = False
|
|
||||||
|
|
||||||
if self.__current_break is not None:
|
if self.__current_break is not None:
|
||||||
# Reset the time of long breaks
|
# Reset the time of long breaks
|
||||||
if self.__current_break.type == BreakType.LONG_BREAK:
|
if self.__current_break.type == BreakType.LONG_BREAK:
|
||||||
|
@ -166,7 +157,15 @@ class BreakQueue:
|
||||||
for break_object in self.__long_queue:
|
for break_object in self.__long_queue:
|
||||||
break_object.time = self.__long_break_time
|
break_object.time = self.__long_break_time
|
||||||
|
|
||||||
def is_empty(self):
|
def is_empty(self, break_type = None):
|
||||||
|
"""
|
||||||
|
Check if the given break type is empty or not. If the break_type is None, check for both short and long breaks.
|
||||||
|
"""
|
||||||
|
if break_type == BreakType.SHORT_BREAK:
|
||||||
|
return self.__short_queue is None
|
||||||
|
elif break_type == BreakType.LONG_BREAK:
|
||||||
|
return self.__long_queue is None
|
||||||
|
else:
|
||||||
return self.__short_queue is None and self.__long_queue is None
|
return self.__short_queue is None and self.__long_queue is None
|
||||||
|
|
||||||
def __next_short(self):
|
def __next_short(self):
|
||||||
|
@ -185,7 +184,6 @@ class BreakQueue:
|
||||||
if self.__current_short == 0 and self.__is_random_order:
|
if self.__current_short == 0 and self.__is_random_order:
|
||||||
self.__build_shorts()
|
self.__build_shorts()
|
||||||
|
|
||||||
self.__shorts_taken += 1
|
|
||||||
return break_obj
|
return break_obj
|
||||||
|
|
||||||
def __next_long(self):
|
def __next_long(self):
|
||||||
|
|
|
@ -27,7 +27,6 @@ import logging
|
||||||
context = None
|
context = None
|
||||||
no_of_skipped_breaks = 0
|
no_of_skipped_breaks = 0
|
||||||
no_of_breaks = 0
|
no_of_breaks = 0
|
||||||
no_of_cycles = -1
|
|
||||||
session = None
|
session = None
|
||||||
safe_eyes_start_time = datetime.datetime.now()
|
safe_eyes_start_time = datetime.datetime.now()
|
||||||
total_idle_time = 0
|
total_idle_time = 0
|
||||||
|
@ -46,7 +45,6 @@ def init(ctx, safeeyes_config, plugin_config):
|
||||||
global session
|
global session
|
||||||
global no_of_skipped_breaks
|
global no_of_skipped_breaks
|
||||||
global no_of_breaks
|
global no_of_breaks
|
||||||
global no_of_cycles
|
|
||||||
global statistics_reset_cron
|
global statistics_reset_cron
|
||||||
global safe_eyes_start_time
|
global safe_eyes_start_time
|
||||||
global total_idle_time
|
global total_idle_time
|
||||||
|
@ -71,7 +69,6 @@ def init(ctx, safeeyes_config, plugin_config):
|
||||||
if session is None:
|
if session is None:
|
||||||
session = {'no_of_skipped_breaks': 0,
|
session = {'no_of_skipped_breaks': 0,
|
||||||
'no_of_breaks': 0,
|
'no_of_breaks': 0,
|
||||||
'no_of_cycles': -1,
|
|
||||||
'safe_eyes_start_time': safe_eyes_start_time.strftime("%Y-%m-%d %H:%M:%S"),
|
'safe_eyes_start_time': safe_eyes_start_time.strftime("%Y-%m-%d %H:%M:%S"),
|
||||||
'total_idle_time': 0,
|
'total_idle_time': 0,
|
||||||
'last_screen_time': -1,
|
'last_screen_time': -1,
|
||||||
|
@ -79,7 +76,6 @@ def init(ctx, safeeyes_config, plugin_config):
|
||||||
context['session']['plugin']['healthstats'] = session
|
context['session']['plugin']['healthstats'] = session
|
||||||
no_of_skipped_breaks = session.get('no_of_skipped_breaks', 0)
|
no_of_skipped_breaks = session.get('no_of_skipped_breaks', 0)
|
||||||
no_of_breaks = session.get('no_of_breaks', 0)
|
no_of_breaks = session.get('no_of_breaks', 0)
|
||||||
no_of_cycles = session.get('no_of_cycles', -1)
|
|
||||||
total_idle_time = session.get('total_idle_time', 0)
|
total_idle_time = session.get('total_idle_time', 0)
|
||||||
last_screen_time = session.get('last_screen_time', -1)
|
last_screen_time = session.get('last_screen_time', -1)
|
||||||
str_time = session.get('safe_eyes_start_time', None)
|
str_time = session.get('safe_eyes_start_time', None)
|
||||||
|
@ -115,12 +111,8 @@ def get_widget_title(break_obj):
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
global no_of_breaks
|
global no_of_breaks
|
||||||
global no_of_cycles
|
|
||||||
no_of_breaks += 1
|
no_of_breaks += 1
|
||||||
if context['new_cycle']:
|
|
||||||
no_of_cycles += 1
|
|
||||||
session['no_of_breaks'] = no_of_breaks
|
session['no_of_breaks'] = no_of_breaks
|
||||||
session['no_of_cycles'] = no_of_cycles
|
|
||||||
session['safe_eyes_start_time'] = safe_eyes_start_time.strftime("%Y-%m-%d %H:%M:%S")
|
session['safe_eyes_start_time'] = safe_eyes_start_time.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
session['total_idle_time'] = total_idle_time
|
session['total_idle_time'] = total_idle_time
|
||||||
session['last_screen_time'] = last_screen_time
|
session['last_screen_time'] = last_screen_time
|
||||||
|
@ -129,7 +121,6 @@ def get_widget_title(break_obj):
|
||||||
|
|
||||||
def _reset_stats():
|
def _reset_stats():
|
||||||
global no_of_breaks
|
global no_of_breaks
|
||||||
global no_of_cycles
|
|
||||||
global safe_eyes_start_time
|
global safe_eyes_start_time
|
||||||
global total_idle_time
|
global total_idle_time
|
||||||
global no_of_skipped_breaks
|
global no_of_skipped_breaks
|
||||||
|
@ -154,10 +145,8 @@ def _reset_stats():
|
||||||
last_screen_time = round((total_duration_sec - total_idle_time) / 60)
|
last_screen_time = round((total_duration_sec - total_idle_time) / 60)
|
||||||
total_idle_time = 0
|
total_idle_time = 0
|
||||||
no_of_breaks = 0
|
no_of_breaks = 0
|
||||||
no_of_cycles = 0
|
|
||||||
no_of_skipped_breaks = 0
|
no_of_skipped_breaks = 0
|
||||||
session['no_of_breaks'] = 0
|
session['no_of_breaks'] = 0
|
||||||
session['no_of_cycles'] = 0
|
|
||||||
session['no_of_skipped_breaks'] = 0
|
session['no_of_skipped_breaks'] = 0
|
||||||
session['safe_eyes_start_time'] = safe_eyes_start_time.strftime("%Y-%m-%d %H:%M:%S")
|
session['safe_eyes_start_time'] = safe_eyes_start_time.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
session['total_idle_time'] = total_idle_time
|
session['total_idle_time'] = total_idle_time
|
||||||
|
@ -195,7 +184,7 @@ def get_widget_content(break_obj):
|
||||||
elif screen_time < last_screen_time:
|
elif screen_time < last_screen_time:
|
||||||
symbol = '-'
|
symbol = '-'
|
||||||
screen_time_diff = ' ( {}{:02d}:{:02d} )'.format(symbol, hrs_diff, mins_diff)
|
screen_time_diff = ' ( {}{:02d}:{:02d} )'.format(symbol, hrs_diff, mins_diff)
|
||||||
return "{}\tBREAKS: {}\tSKIPPED: {}\tCYCLES: {}\tSCREEN TIME: {}{}".format(heart, no_of_breaks, no_of_skipped_breaks, no_of_cycles, time_format, screen_time_diff)
|
return "{}\tBREAKS: {}\tSKIPPED: {}\tSCREEN TIME: {}{}".format(heart, no_of_breaks, no_of_skipped_breaks, time_format, screen_time_diff)
|
||||||
|
|
||||||
|
|
||||||
def on_start():
|
def on_start():
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
from safeeyes.model import BreakType
|
||||||
import gi
|
import gi
|
||||||
gi.require_version('Gtk', '3.0')
|
gi.require_version('Gtk', '3.0')
|
||||||
try:
|
try:
|
||||||
|
@ -85,10 +86,8 @@ class TrayIcon:
|
||||||
self.item_enable.connect('activate', self.on_enable_clicked)
|
self.item_enable.connect('activate', self.on_enable_clicked)
|
||||||
|
|
||||||
self.item_disable = Gtk.MenuItem()
|
self.item_disable = Gtk.MenuItem()
|
||||||
self.item_disable.connect('activate', self.on_disable_clicked)
|
|
||||||
|
|
||||||
self.sub_menu_disable = Gtk.Menu()
|
self.sub_menu_disable = Gtk.Menu()
|
||||||
self.sub_menu_items = []
|
self.sub_menu_disable_items = []
|
||||||
|
|
||||||
# Read disable options and build the sub menu
|
# Read disable options and build the sub menu
|
||||||
for disable_option in plugin_config['disable_options']:
|
for disable_option in plugin_config['disable_options']:
|
||||||
|
@ -116,7 +115,7 @@ class TrayIcon:
|
||||||
# Create submenu
|
# Create submenu
|
||||||
sub_menu_item = Gtk.MenuItem()
|
sub_menu_item = Gtk.MenuItem()
|
||||||
sub_menu_item.connect('activate', self.on_disable_clicked, time_in_minutes)
|
sub_menu_item.connect('activate', self.on_disable_clicked, time_in_minutes)
|
||||||
self.sub_menu_items.append([sub_menu_item, label, disable_option['time']])
|
self.sub_menu_disable_items.append([sub_menu_item, label, disable_option['time']])
|
||||||
self.sub_menu_disable.append(sub_menu_item)
|
self.sub_menu_disable.append(sub_menu_item)
|
||||||
|
|
||||||
# Disable until restart submenu
|
# Disable until restart submenu
|
||||||
|
@ -129,7 +128,19 @@ class TrayIcon:
|
||||||
|
|
||||||
# Settings menu item
|
# Settings menu item
|
||||||
self.item_manual_break = Gtk.MenuItem()
|
self.item_manual_break = Gtk.MenuItem()
|
||||||
self.item_manual_break.connect('activate', self.on_manual_break_clicked)
|
|
||||||
|
self.sub_menu_manual_next_break = Gtk.MenuItem()
|
||||||
|
self.sub_menu_manual_next_break.connect('activate', self.on_manual_break_clicked, None)
|
||||||
|
self.sub_menu_manual_next_short_break = Gtk.MenuItem()
|
||||||
|
self.sub_menu_manual_next_short_break.connect('activate', self.on_manual_break_clicked, BreakType.SHORT_BREAK)
|
||||||
|
self.sub_menu_manual_next_long_break = Gtk.MenuItem()
|
||||||
|
self.sub_menu_manual_next_long_break.connect('activate', self.on_manual_break_clicked, BreakType.LONG_BREAK)
|
||||||
|
|
||||||
|
self.sub_menu_manual_break = Gtk.Menu()
|
||||||
|
self.sub_menu_manual_break.append(self.sub_menu_manual_next_break)
|
||||||
|
self.sub_menu_manual_break.append(self.sub_menu_manual_next_short_break)
|
||||||
|
self.sub_menu_manual_break.append(self.sub_menu_manual_next_long_break)
|
||||||
|
self.item_manual_break.set_submenu(self.sub_menu_manual_break)
|
||||||
|
|
||||||
# Settings menu item
|
# Settings menu item
|
||||||
self.item_settings = Gtk.MenuItem()
|
self.item_settings = Gtk.MenuItem()
|
||||||
|
@ -182,7 +193,7 @@ class TrayIcon:
|
||||||
"""
|
"""
|
||||||
Update the text of menu items based on the selected language.
|
Update the text of menu items based on the selected language.
|
||||||
"""
|
"""
|
||||||
for entry in self.sub_menu_items:
|
for entry in self.sub_menu_disable_items:
|
||||||
# print(self.context['locale'].ngettext('For %d Hour', 'For %d Hours', 1) % 1)
|
# print(self.context['locale'].ngettext('For %d Hour', 'For %d Hours', 1) % 1)
|
||||||
entry[0].set_label(self.context['locale'].ngettext(entry[1][0], entry[1][1], entry[2]) % entry[2])
|
entry[0].set_label(self.context['locale'].ngettext(entry[1][0], entry[1][1], entry[2]) % entry[2])
|
||||||
|
|
||||||
|
@ -213,6 +224,9 @@ class TrayIcon:
|
||||||
self.item_manual_break.set_sensitive(breaks_found and self.active)
|
self.item_manual_break.set_sensitive(breaks_found and self.active)
|
||||||
|
|
||||||
self.item_manual_break.set_label(_('Take a break now'))
|
self.item_manual_break.set_label(_('Take a break now'))
|
||||||
|
self.sub_menu_manual_next_break.set_label(_('Any break'))
|
||||||
|
self.sub_menu_manual_next_short_break.set_label(_('Short break'))
|
||||||
|
self.sub_menu_manual_next_long_break.set_label(_('Long break'))
|
||||||
self.item_settings.set_label(_('Settings'))
|
self.item_settings.set_label(_('Settings'))
|
||||||
self.item_about.set_label(_('About'))
|
self.item_about.set_label(_('About'))
|
||||||
self.item_quit.set_label(_('Quit'))
|
self.item_quit.set_label(_('Quit'))
|
||||||
|
@ -282,6 +296,10 @@ class TrayIcon:
|
||||||
"""
|
"""
|
||||||
Trigger a break manually.
|
Trigger a break manually.
|
||||||
"""
|
"""
|
||||||
|
if len(args) > 1:
|
||||||
|
break_type = args[1]
|
||||||
|
self.take_break(break_type)
|
||||||
|
else:
|
||||||
self.take_break()
|
self.take_break()
|
||||||
|
|
||||||
def on_enable_clicked(self, *args):
|
def on_enable_clicked(self, *args):
|
||||||
|
|
|
@ -93,8 +93,7 @@ class SafeEyes:
|
||||||
self.safe_eyes_core.on_stop_break += self.stop_break
|
self.safe_eyes_core.on_stop_break += self.stop_break
|
||||||
self.safe_eyes_core.on_update_next_break += self.update_next_break
|
self.safe_eyes_core.on_update_next_break += self.update_next_break
|
||||||
self.safe_eyes_core.initialize(self.config)
|
self.safe_eyes_core.initialize(self.config)
|
||||||
self.context['api']['take_break'] = lambda: utility.execute_main_thread(
|
self.context['api']['take_break'] = self.take_break
|
||||||
self.safe_eyes_core.take_break)
|
|
||||||
self.context['api']['has_breaks'] = self.safe_eyes_core.has_breaks
|
self.context['api']['has_breaks'] = self.safe_eyes_core.has_breaks
|
||||||
self.context['api']['postpone'] = self.safe_eyes_core.postpone
|
self.context['api']['postpone'] = self.safe_eyes_core.postpone
|
||||||
self.plugins_manager.init(self.context, self.config)
|
self.plugins_manager.init(self.context, self.config)
|
||||||
|
@ -295,11 +294,11 @@ class SafeEyes:
|
||||||
self.plugins_manager.stop_break()
|
self.plugins_manager.stop_break()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def take_break(self):
|
def take_break(self, break_type = None):
|
||||||
"""
|
"""
|
||||||
Take a break now.
|
Take a break now.
|
||||||
"""
|
"""
|
||||||
self.safe_eyes_core.take_break()
|
utility.execute_main_thread(self.safe_eyes_core.take_break, break_type)
|
||||||
|
|
||||||
def status(self):
|
def status(self):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue