diff --git a/safeeyes/config/locale/safeeyes.pot b/safeeyes/config/locale/safeeyes.pot index 6352149..aea416e 100644 --- a/safeeyes/config/locale/safeeyes.pot +++ b/safeeyes/config/locale/safeeyes.pot @@ -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 "" diff --git a/safeeyes/core.py b/safeeyes/core.py index f51a8c0..178bb9f 100644 --- a/safeeyes/core.py +++ b/safeeyes/core.py @@ -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 diff --git a/safeeyes/model.py b/safeeyes/model.py index cbd5590..888b3f7 100644 --- a/safeeyes/model.py +++ b/safeeyes/model.py @@ -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): diff --git a/safeeyes/plugins/healthstats/plugin.py b/safeeyes/plugins/healthstats/plugin.py index d66c9ae..041bf98 100644 --- a/safeeyes/plugins/healthstats/plugin.py +++ b/safeeyes/plugins/healthstats/plugin.py @@ -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(): diff --git a/safeeyes/plugins/trayicon/plugin.py b/safeeyes/plugins/trayicon/plugin.py index 9fb3b48..de90326 100644 --- a/safeeyes/plugins/trayicon/plugin.py +++ b/safeeyes/plugins/trayicon/plugin.py @@ -17,6 +17,7 @@ # along with this program. If not, see . 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): """ diff --git a/safeeyes/safeeyes.py b/safeeyes/safeeyes.py index 9ce47eb..709ec0c 100644 --- a/safeeyes/safeeyes.py +++ b/safeeyes/safeeyes.py @@ -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): """