Add sub-menu to take any, short or long breaks

This commit is contained in:
Gobinath 2021-05-10 19:03:12 -04:00 committed by AdamPS
parent b90349ab10
commit 9e64e65fce
6 changed files with 71 additions and 55 deletions

View File

@ -456,6 +456,18 @@ msgstr ""
msgid "Take a break now"
msgstr ""
#: plugins/trayicon
msgid "Any break"
msgstr ""
#: plugins/trayicon
msgid "Short break"
msgstr ""
#: plugins/trayicon
msgid "Long break"
msgstr ""
#: plugins/trayicon
msgid "Until restart"
msgstr ""

View File

@ -131,7 +131,7 @@ class SafeEyesCore:
logging.debug("Postpone the break for %d seconds", self.postpone_duration)
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
"""
@ -139,15 +139,15 @@ class SafeEyesCore:
return
if not self.context['state'] == State.WAITING:
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
"""
@ -167,7 +167,7 @@ class SafeEyesCore:
time.sleep(1) # Wait for 1 sec to ensure the sceduler is dead
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):
"""
@ -243,9 +243,10 @@ class SafeEyesCore:
self.__wait_for(self.postpone_duration)
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
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
self.__start_next_break()
return
@ -258,15 +259,14 @@ class SafeEyesCore:
# Wait in user thread
utility.start_thread(self.__postpone_break)
else:
self.start_break.fire(self.break_queue.get_break())
utility.start_thread(self.__start_break)
self.start_break.fire(break_obj)
utility.start_thread(self.__start_break, break_obj = break_obj)
def __start_break(self):
def __start_break(self, break_obj):
"""
Start the break screen.
"""
self.context['state'] = State.BREAK
break_obj = self.break_queue.get_break()
countdown = break_obj.duration
total_break_time = countdown

View File

@ -84,7 +84,6 @@ class BreakQueue:
self.__current_break = None
self.__current_long = 0
self.__current_short = 0
self.__shorts_taken = 0
self.__short_break_time = config.get('short_break_interval')
self.__long_break_time = config.get('long_break_interval')
self.__is_random_order = config.get('random_order')
@ -113,15 +112,18 @@ class BreakQueue:
while brk != current_break and brk.name != last_break:
brk = self.next()
def get_break(self):
def get_break(self, break_type = 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
def is_long_break(self):
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
shorts = self.__short_queue
longs = self.__long_queue
@ -133,22 +135,11 @@ class BreakQueue:
break_obj = self.__next_long()
elif longs is None:
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()
else:
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:
# Reset the time of long breaks
if self.__current_break.type == BreakType.LONG_BREAK:
@ -166,8 +157,16 @@ class BreakQueue:
for break_object in self.__long_queue:
break_object.time = self.__long_break_time
def is_empty(self):
return self.__short_queue is None and self.__long_queue is None
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
def __next_short(self):
longs = self.__long_queue
@ -185,7 +184,6 @@ class BreakQueue:
if self.__current_short == 0 and self.__is_random_order:
self.__build_shorts()
self.__shorts_taken += 1
return break_obj
def __next_long(self):

View File

@ -27,7 +27,6 @@ import logging
context = None
no_of_skipped_breaks = 0
no_of_breaks = 0
no_of_cycles = -1
session = None
safe_eyes_start_time = datetime.datetime.now()
total_idle_time = 0
@ -46,7 +45,6 @@ def init(ctx, safeeyes_config, plugin_config):
global session
global no_of_skipped_breaks
global no_of_breaks
global no_of_cycles
global statistics_reset_cron
global safe_eyes_start_time
global total_idle_time
@ -71,7 +69,6 @@ def init(ctx, safeeyes_config, plugin_config):
if session is None:
session = {'no_of_skipped_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"),
'total_idle_time': 0,
'last_screen_time': -1,
@ -79,7 +76,6 @@ def init(ctx, safeeyes_config, plugin_config):
context['session']['plugin']['healthstats'] = session
no_of_skipped_breaks = session.get('no_of_skipped_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)
last_screen_time = session.get('last_screen_time', -1)
str_time = session.get('safe_eyes_start_time', None)
@ -115,12 +111,8 @@ def get_widget_title(break_obj):
return ""
global no_of_breaks
global no_of_cycles
no_of_breaks += 1
if context['new_cycle']:
no_of_cycles += 1
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['total_idle_time'] = total_idle_time
session['last_screen_time'] = last_screen_time
@ -129,7 +121,6 @@ def get_widget_title(break_obj):
def _reset_stats():
global no_of_breaks
global no_of_cycles
global safe_eyes_start_time
global total_idle_time
global no_of_skipped_breaks
@ -154,10 +145,8 @@ def _reset_stats():
last_screen_time = round((total_duration_sec - total_idle_time) / 60)
total_idle_time = 0
no_of_breaks = 0
no_of_cycles = 0
no_of_skipped_breaks = 0
session['no_of_breaks'] = 0
session['no_of_cycles'] = 0
session['no_of_skipped_breaks'] = 0
session['safe_eyes_start_time'] = safe_eyes_start_time.strftime("%Y-%m-%d %H:%M:%S")
session['total_idle_time'] = total_idle_time
@ -195,7 +184,7 @@ def get_widget_content(break_obj):
elif screen_time < last_screen_time:
symbol = '-'
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():

View File

@ -17,6 +17,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import datetime
from safeeyes.model import BreakType
import gi
gi.require_version('Gtk', '3.0')
try:
@ -85,10 +86,8 @@ class TrayIcon:
self.item_enable.connect('activate', self.on_enable_clicked)
self.item_disable = Gtk.MenuItem()
self.item_disable.connect('activate', self.on_disable_clicked)
self.sub_menu_disable = Gtk.Menu()
self.sub_menu_items = []
self.sub_menu_disable_items = []
# Read disable options and build the sub menu
for disable_option in plugin_config['disable_options']:
@ -116,7 +115,7 @@ class TrayIcon:
# Create submenu
sub_menu_item = Gtk.MenuItem()
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)
# Disable until restart submenu
@ -129,7 +128,19 @@ class TrayIcon:
# Settings menu item
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
self.item_settings = Gtk.MenuItem()
@ -182,7 +193,7 @@ class TrayIcon:
"""
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)
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_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_about.set_label(_('About'))
self.item_quit.set_label(_('Quit'))
@ -282,7 +296,11 @@ class TrayIcon:
"""
Trigger a break manually.
"""
self.take_break()
if len(args) > 1:
break_type = args[1]
self.take_break(break_type)
else:
self.take_break()
def on_enable_clicked(self, *args):
"""

View File

@ -93,8 +93,7 @@ class SafeEyes:
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.initialize(self.config)
self.context['api']['take_break'] = lambda: utility.execute_main_thread(
self.safe_eyes_core.take_break)
self.context['api']['take_break'] = self.take_break
self.context['api']['has_breaks'] = self.safe_eyes_core.has_breaks
self.context['api']['postpone'] = self.safe_eyes_core.postpone
self.plugins_manager.init(self.context, self.config)
@ -295,11 +294,11 @@ class SafeEyes:
self.plugins_manager.stop_break()
return True
def take_break(self):
def take_break(self, break_type = None):
"""
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):
"""