From 773d44d409ff377a4f7fbf4c0391cd2222f0c5a4 Mon Sep 17 00:00:00 2001 From: deltragon Date: Fri, 26 Jul 2024 10:27:26 +0200 Subject: [PATCH] black: format the world --- safeeyes/__main__.py | 81 ++- safeeyes/core.py | 102 ++-- safeeyes/model.py | 85 +-- safeeyes/plugin_manager.py | 180 +++--- safeeyes/plugins/audiblealert/plugin.py | 18 +- safeeyes/plugins/donotdisturb/plugin.py | 80 ++- safeeyes/plugins/healthstats/plugin.py | 81 +-- .../limitconsecutiveskipping/plugin.py | 33 +- safeeyes/plugins/mediacontrol/plugin.py | 29 +- safeeyes/plugins/notification/plugin.py | 26 +- safeeyes/plugins/screensaver/plugin.py | 88 +-- safeeyes/plugins/smartpause/plugin.py | 90 +-- .../plugins/trayicon/dependency_checker.py | 17 +- safeeyes/plugins/trayicon/plugin.py | 372 +++++++------ safeeyes/rpc.py | 34 +- safeeyes/safeeyes.py | 126 +++-- safeeyes/ui/about_dialog.py | 12 +- safeeyes/ui/break_screen.py | 58 +- safeeyes/ui/required_plugin_dialog.py | 32 +- safeeyes/ui/settings_dialog.py | 515 +++++++++++------- safeeyes/utility.py | 298 +++++----- setup.py | 138 +++-- validate_po.py | 6 +- 23 files changed, 1464 insertions(+), 1037 deletions(-) diff --git a/safeeyes/__main__.py b/safeeyes/__main__.py index c6685c43..4e1a98b8 100755 --- a/safeeyes/__main__.py +++ b/safeeyes/__main__.py @@ -33,7 +33,7 @@ from safeeyes.safeeyes import SAFE_EYES_VERSION from safeeyes.rpc import RPCClient -gettext.install('safeeyes', utility.LOCALE_PATH) +gettext.install("safeeyes", utility.LOCALE_PATH) def __running(): @@ -52,9 +52,8 @@ def __running(): else: # In older versions cmdline was a list object cmd_line = proc.cmdline - if ( - ('python3' in cmd_line[0] or 'python' in cmd_line[0]) - and ('safeeyes' in cmd_line[1] or 'safeeyes' in cmd_line) + if ("python3" in cmd_line[0] or "python" in cmd_line[0]) and ( + "safeeyes" in cmd_line[1] or "safeeyes" in cmd_line ): process_count += 1 if process_count > 1: @@ -71,40 +70,60 @@ def main(): Start the Safe Eyes. """ system_locale = gettext.translation( - 'safeeyes', + "safeeyes", localedir=utility.LOCALE_PATH, - languages=[utility.system_locale(), 'en_US'], - fallback=True + languages=[utility.system_locale(), "en_US"], + fallback=True, ) system_locale.install() try: # locale.bindtextdomain is required for Glade files - locale.bindtextdomain('safeeyes', utility.LOCALE_PATH) + locale.bindtextdomain("safeeyes", utility.LOCALE_PATH) except AttributeError: logging.warning( - 'installed python\'s gettext module does not support locale.bindtextdomain. locale.bindtextdomain is required for Glade files' # noqa: E501 + "installed python's gettext module does not support locale.bindtextdomain. locale.bindtextdomain is required for Glade files" # noqa: E501 ) - parser = argparse.ArgumentParser(prog='safeeyes', description=_('description')) + parser = argparse.ArgumentParser(prog="safeeyes", description=_("description")) group = parser.add_mutually_exclusive_group() - group.add_argument('-a', '--about', help=_('show the about dialog'), action='store_true') group.add_argument( - '-d', - '--disable', - help=_('disable the currently running safeeyes instance'), - action='store_true' + "-a", "--about", help=_("show the about dialog"), action="store_true" + ) + group.add_argument( + "-d", + "--disable", + help=_("disable the currently running safeeyes instance"), + action="store_true", + ) + group.add_argument( + "-e", + "--enable", + help=_("enable the currently running safeeyes instance"), + action="store_true", + ) + group.add_argument( + "-q", + "--quit", + help=_("quit the running safeeyes instance and exit"), + action="store_true", + ) + group.add_argument( + "-s", "--settings", help=_("show the settings dialog"), action="store_true" + ) + group.add_argument( + "-t", "--take-break", help=_("Take a break now").lower(), action="store_true" + ) + parser.add_argument( + "--debug", help=_("start safeeyes in debug mode"), action="store_true" + ) + parser.add_argument( + "--status", + help=_("print the status of running safeeyes instance and exit"), + action="store_true", ) - group.add_argument('-e', '--enable', help=_('enable the currently running safeeyes instance'), action='store_true') - group.add_argument('-q', '--quit', help=_('quit the running safeeyes instance and exit'), action='store_true') - group.add_argument('-s', '--settings', help=_('show the settings dialog'), action='store_true') - group.add_argument('-t', '--take-break', help=_('Take a break now').lower(), action='store_true') - parser.add_argument('--debug', help=_('start safeeyes in debug mode'), action='store_true') parser.add_argument( - '--status', - help=_('print the status of running safeeyes instance and exit'), - action='store_true' + "--version", action="version", version="%(prog)s " + SAFE_EYES_VERSION ) - parser.add_argument('--version', action='version', version='%(prog)s ' + SAFE_EYES_VERSION) args = parser.parse_args() # Initialize the logging @@ -116,10 +135,14 @@ def main(): logging.info("Safe Eyes is already running") if not config.get("use_rpc_server", True): # RPC sever is disabled - print(_('Safe Eyes is running without an RPC server. Turn it on to use command-line arguments.')) + print( + _( + "Safe Eyes is running without an RPC server. Turn it on to use command-line arguments." + ) + ) sys.exit(0) return - rpc_client = RPCClient(config.get('rpc_port')) + rpc_client = RPCClient(config.get("rpc_port")) if args.about: rpc_client.show_about() elif args.disable: @@ -140,7 +163,7 @@ def main(): sys.exit(0) else: if args.status: - print(_('Safe Eyes is not running')) + print(_("Safe Eyes is not running")) sys.exit(0) elif not args.quit: logging.info("Starting Safe Eyes") @@ -148,6 +171,6 @@ def main(): safe_eyes.start() -if __name__ == '__main__': - signal.signal(signal.SIGINT, signal.SIG_DFL) # Handle Ctrl + C +if __name__ == "__main__": + signal.signal(signal.SIGINT, signal.SIG_DFL) # Handle Ctrl + C main() diff --git a/safeeyes/core.py b/safeeyes/core.py index 2adb1eb8..f0b79ba7 100644 --- a/safeeyes/core.py +++ b/safeeyes/core.py @@ -64,20 +64,22 @@ def __init__(self, context): self.waiting_condition = threading.Condition() self.lock = threading.Lock() self.context = context - self.context['skipped'] = False - self.context['postponed'] = False - self.context['skip_button_disabled'] = False - self.context['postpone_button_disabled'] = False - self.context['state'] = State.WAITING + self.context["skipped"] = False + self.context["postponed"] = False + self.context["skip_button_disabled"] = False + self.context["postpone_button_disabled"] = False + self.context["state"] = State.WAITING def initialize(self, config): """ Initialize the internal properties from configuration """ logging.info("Initialize the core") - self.pre_break_warning_time = config.get('pre_break_warning_time') + self.pre_break_warning_time = config.get("pre_break_warning_time") self.break_queue = BreakQueue(config, self.context) - self.default_postpone_duration = config.get('postpone_duration') * 60 # Convert to seconds + self.default_postpone_duration = ( + config.get("postpone_duration") * 60 + ) # Convert to seconds self.postpone_duration = self.default_postpone_duration def start(self, next_break_time=-1, reset_breaks=False): @@ -110,8 +112,8 @@ def stop(self, is_resting=False): # Stop the break thread self.waiting_condition.acquire() self.running = False - if self.context['state'] != State.QUIT: - self.context['state'] = State.RESTING if (is_resting) else State.STOPPED + if self.context["state"] != State.QUIT: + self.context["state"] = State.RESTING if (is_resting) else State.STOPPED self.waiting_condition.notify_all() self.waiting_condition.release() @@ -119,7 +121,7 @@ def skip(self): """ User skipped the break using Skip button """ - self.context['skipped'] = True + self.context["skipped"] = True def postpone(self, duration=-1): """ @@ -130,7 +132,7 @@ def postpone(self, duration=-1): else: self.postpone_duration = self.default_postpone_duration logging.debug("Postpone the break for %d seconds", self.postpone_duration) - self.context['postponed'] = True + self.context["postponed"] = True def get_break_time(self, break_type=None): """ @@ -139,8 +141,9 @@ def get_break_time(self, break_type=None): break_obj = self.break_queue.get_break(break_type) if not break_obj: return False - time = self.scheduled_next_break_time + \ - datetime.timedelta(minutes=break_obj.time - self.break_queue.get_break().time) + time = self.scheduled_next_break_time + datetime.timedelta( + minutes=break_obj.time - self.break_queue.get_break().time + ) return time def take_break(self, break_type=None): @@ -149,7 +152,7 @@ def take_break(self, break_type=None): """ if self.break_queue.is_empty(): return - if not self.context['state'] == State.WAITING: + if not self.context["state"] == State.WAITING: return utility.start_thread(self.__take_break, break_type=break_type) @@ -163,7 +166,7 @@ def __take_break(self, break_type=None): """ Show the next break screen """ - logging.info('Take a break due to external request') + logging.info("Take a break due to external request") with self.lock: if not self.running: @@ -193,31 +196,43 @@ def __scheduler_job(self): current_time = datetime.datetime.now() current_timestamp = current_time.timestamp() - if self.context['state'] == State.RESTING and self.paused_time > -1: + if self.context["state"] == State.RESTING and self.paused_time > -1: # Safe Eyes was resting paused_duration = int(current_timestamp - self.paused_time) self.paused_time = -1 - if paused_duration > self.break_queue.get_break(BreakType.LONG_BREAK).duration: - logging.info('Skip next long break due to the pause %ds longer than break duration', paused_duration) + if ( + paused_duration + > self.break_queue.get_break(BreakType.LONG_BREAK).duration + ): + logging.info( + "Skip next long break due to the pause %ds longer than break duration", + paused_duration, + ) # Skip the next long break self.break_queue.reset() - if self.context['postponed']: + if self.context["postponed"]: # Previous break was postponed - logging.info('Prepare for postponed break') + logging.info("Prepare for postponed break") time_to_wait = self.postpone_duration - self.context['postponed'] = False + self.context["postponed"] = False elif current_timestamp < self.scheduled_next_break_timestamp: # Non-standard break was set. - time_to_wait = round(self.scheduled_next_break_timestamp - current_timestamp) + time_to_wait = round( + self.scheduled_next_break_timestamp - current_timestamp + ) self.scheduled_next_break_timestamp = -1 else: # Use next break, convert to seconds time_to_wait = self.break_queue.get_break().time * 60 - self.scheduled_next_break_time = current_time + datetime.timedelta(seconds=time_to_wait) - self.context['state'] = State.WAITING - utility.execute_main_thread(self.__fire_on_update_next_break, self.scheduled_next_break_time) + self.scheduled_next_break_time = current_time + datetime.timedelta( + seconds=time_to_wait + ) + self.context["state"] = State.WAITING + utility.execute_main_thread( + self.__fire_on_update_next_break, self.scheduled_next_break_time + ) # Wait for the pre break warning period logging.info("Waiting for %d minutes until next break", (time_to_wait / 60)) @@ -239,7 +254,7 @@ def __fire_pre_break(self): """ Show the notification and start the break after the notification. """ - self.context['state'] = State.PRE_BREAK + self.context["state"] = State.PRE_BREAK if not self.on_pre_break.fire(self.break_queue.get_break()): # Plugins wanted to ignore this break self.__start_next_break() @@ -247,7 +262,9 @@ def __fire_pre_break(self): utility.start_thread(self.__wait_until_prepare) def __wait_until_prepare(self): - logging.info("Wait for %d seconds before the break", self.pre_break_warning_time) + logging.info( + "Wait for %d seconds before the break", self.pre_break_warning_time + ) # Wait for the pre break warning period self.__wait_for(self.pre_break_warning_time) if not self.running: @@ -265,12 +282,14 @@ def __fire_start_break(self): # Plugins want to ignore this break self.__start_next_break() return - if self.context['postponed']: + if self.context["postponed"]: # Plugins want to postpone this break - self.context['postponed'] = False + self.context["postponed"] = False # Update the next break time - self.scheduled_next_break_time = self.scheduled_next_break_time + \ - datetime.timedelta(seconds=self.postpone_duration) + self.scheduled_next_break_time = ( + self.scheduled_next_break_time + + datetime.timedelta(seconds=self.postpone_duration) + ) self.__fire_on_update_next_break(self.scheduled_next_break_time) # Wait in user thread utility.start_thread(self.__postpone_break) @@ -282,28 +301,33 @@ def __start_break(self): """ 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 total_break_time = countdown - while countdown and self.running and not self.context['skipped'] and not self.context['postponed']: + while ( + countdown + and self.running + and not self.context["skipped"] + and not self.context["postponed"] + ): seconds = total_break_time - countdown self.on_count_down.fire(countdown, seconds) - time.sleep(1) # Sleep for 1 second + time.sleep(1) # Sleep for 1 second countdown -= 1 utility.execute_main_thread(self.__fire_stop_break) def __fire_stop_break(self): # Loop terminated because of timeout (not skipped) -> Close the break alert - if not self.context['skipped'] and not self.context['postponed']: + if not self.context["skipped"] and not self.context["postponed"]: logging.info("Break is terminated automatically") self.on_stop_break.fire() # Reset the skipped flag - self.context['skipped'] = False - self.context['skip_button_disabled'] = False - self.context['postpone_button_disabled'] = False + self.context["skipped"] = False + self.context["skip_button_disabled"] = False + self.context["postpone_button_disabled"] = False self.__start_next_break() def __wait_for(self, duration): @@ -315,7 +339,7 @@ def __wait_for(self, duration): self.waiting_condition.release() def __start_next_break(self): - if not self.context['postponed']: + if not self.context["postponed"]: self.break_queue.next() if self.running: diff --git a/safeeyes/model.py b/safeeyes/model.py index 01b49910..1b621654 100644 --- a/safeeyes/model.py +++ b/safeeyes/model.py @@ -45,7 +45,9 @@ def __init__(self, break_type, name, time, duration, image, plugins): self.next = None def __str__(self): - return 'Break: {{name: "{}", type: {}, duration: {}}}\n'.format(self.name, self.type, self.duration) + return 'Break: {{name: "{}", type: {}, duration: {}}}\n'.format( + self.name, self.type, self.duration + ) def __repr__(self): return str(self) @@ -76,6 +78,7 @@ class BreakType(Enum): """ Type of Safe Eyes breaks. """ + SHORT_BREAK = 1 LONG_BREAK = 2 @@ -86,9 +89,9 @@ def __init__(self, config, context): self.__current_break = None self.__current_long = 0 self.__current_short = 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') + 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") self.__config = config self.__build_longs() @@ -96,8 +99,8 @@ def __init__(self, config, context): # Interface guarantees that short_interval >= 1 # And that long_interval is a multiple of short_interval - short_interval = config.get('short_break_interval') - long_interval = config.get('long_break_interval') + short_interval = config.get("short_break_interval") + long_interval = config.get("long_break_interval") self.__cycle_len = int(long_interval / short_interval) # To count every long break as a cycle in .next() if there are no short breaks if self.__short_queue is None: @@ -105,7 +108,7 @@ def __init__(self, config, context): # Restore the last break from session if not self.is_empty(): - last_break = context['session'].get('break') + last_break = context["session"].get("break") if last_break is not None: current_break = self.get_break() if last_break != current_break.name: @@ -130,7 +133,10 @@ def get_break(self, break_type=None): return self.__short_queue[self.__current_short] 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, break_type=None): break_obj = None @@ -157,13 +163,16 @@ def next(self, break_type=None): break_obj = self.__next_long() elif longs is None: break_obj = self.__next_short() - elif break_type == BreakType.LONG_BREAK or 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() self.__current_break = break_obj - self.context['session']['break'] = self.__current_break.name + self.context["session"]["break"] = self.__current_break.name return break_obj @@ -188,7 +197,7 @@ def is_empty(self, break_type=None): def __next_short(self): shorts = self.__short_queue break_obj = shorts[self.__current_short] - self.context['break_type'] = 'short' + self.context["break_type"] = "short" # Update the index to next self.__current_short = (self.__current_short + 1) % len(shorts) @@ -198,7 +207,7 @@ def __next_short(self): def __next_long(self): longs = self.__long_queue break_obj = longs[self.__current_long] - self.context['break_type'] = 'long' + self.context["break_type"] = "long" # Update the index to next self.__current_long = (self.__current_long + 1) % len(longs) @@ -222,20 +231,18 @@ def __build_queue(self, break_type, break_configs, break_time, break_duration): queue = [None] * size for i, break_config in enumerate(breaks_order): - name = _(break_config['name']) - duration = break_config.get('duration', break_duration) - image = break_config.get('image') - plugins = break_config.get('plugins', None) - interval = break_config.get('interval', break_time) + name = _(break_config["name"]) + duration = break_config.get("duration", break_duration) + image = break_config.get("image") + plugins = break_config.get("plugins", None) + interval = break_config.get("interval", break_time) # Validate time value if not isinstance(duration, int) or duration <= 0: - logging.error('Invalid break duration in: ' + - str(break_config)) + logging.error("Invalid break duration in: " + str(break_config)) continue - break_obj = Break(break_type, name, interval, - duration, image, plugins) + break_obj = Break(break_type, name, interval, duration, image, plugins) queue[i] = break_obj return queue @@ -243,17 +250,17 @@ def __build_queue(self, break_type, break_configs, break_time, break_duration): def __build_shorts(self): self.__short_queue = self.__build_queue( BreakType.SHORT_BREAK, - self.__config.get('short_breaks'), + self.__config.get("short_breaks"), self.__short_break_time, - self.__config.get('short_break_duration') + self.__config.get("short_break_duration"), ) def __build_longs(self): self.__long_queue = self.__build_queue( BreakType.LONG_BREAK, - self.__config.get('long_breaks'), + self.__config.get("long_breaks"), self.__long_break_time, - self.__config.get('long_break_duration') + self.__config.get("long_break_duration"), ) @@ -261,13 +268,14 @@ class State(Enum): """ Possible states of Safe Eyes. """ - START = 0, # Starting scheduler - WAITING = 1, # User is working (waiting for next break) - PRE_BREAK = 2, # Preparing for break - BREAK = 3, # Break - STOPPED = 4, # Disabled - QUIT = 5, # Quitting - RESTING = 6 # Resting (natural break) + + START = (0,) # Starting scheduler + WAITING = (1,) # User is working (waiting for next break) + PRE_BREAK = (2,) # Preparing for break + BREAK = (3,) # Break + STOPPED = (4,) # Disabled + QUIT = (5,) # Quitting + RESTING = 6 # Resting (natural break) class EventHook: @@ -304,8 +312,7 @@ class Config: def __init__(self, init=True): # Read the config files self.__user_config = utility.load_json(utility.CONFIG_FILE_PATH) - self.__system_config = utility.load_json( - utility.SYSTEM_CONFIG_FILE_PATH) + self.__system_config = utility.load_json(utility.SYSTEM_CONFIG_FILE_PATH) # If there any breaking changes in long_breaks, short_breaks or any other keys, use the __force_upgrade list self.__force_upgrade = [] # self.__force_upgrade = ['long_breaks', 'short_breaks'] @@ -318,18 +325,18 @@ def __init__(self, init=True): self.__user_config = self.__system_config self.save() else: - system_config_version = self.__system_config['meta']['config_version'] - meta_obj = self.__user_config.get('meta', None) + system_config_version = self.__system_config["meta"]["config_version"] + meta_obj = self.__user_config.get("meta", None) if meta_obj is None: # Corrupted user config self.__user_config = self.__system_config else: - user_config_version = str( - meta_obj.get('config_version', '0.0.0')) + user_config_version = str(meta_obj.get("config_version", "0.0.0")) if parse(user_config_version) != parse(system_config_version): # Update the user config self.__merge_dictionary( - self.__user_config, self.__system_config) + self.__user_config, self.__system_config + ) self.__user_config = self.__system_config # Update the style sheet utility.replace_style_sheet() diff --git a/safeeyes/plugin_manager.py b/safeeyes/plugin_manager.py index a801451b..fe42ce11 100644 --- a/safeeyes/plugin_manager.py +++ b/safeeyes/plugin_manager.py @@ -71,7 +71,7 @@ class PluginManager: """ def __init__(self): - logging.info('Load all the plugins') + logging.info("Load all the plugins") self.__plugins = {} self.__plugins_on_init = [] self.__plugins_on_start = [] @@ -85,28 +85,31 @@ def __init__(self): self.__widget_plugins = [] self.__tray_actions_plugins = [] self.last_break = None - self.horizontal_line = '─' * HORIZONTAL_LINE_LENGTH + self.horizontal_line = "─" * HORIZONTAL_LINE_LENGTH def init(self, context, config): """ Initialize all the plugins with init(context, safe_eyes_config, plugin_config) function. """ # Load the plugins - for plugin in config.get('plugins'): + for plugin in config.get("plugins"): try: self.__load_plugin(plugin) except RequiredPluginException as e: raise e except BaseException as e: - traceback_wanted = logging.getLogger().getEffectiveLevel() == logging.DEBUG + traceback_wanted = ( + logging.getLogger().getEffectiveLevel() == logging.DEBUG + ) if traceback_wanted: import traceback + traceback.print_exc() - logging.error('Error in loading the plugin %s: %s', plugin['id'], e) + logging.error("Error in loading the plugin %s: %s", plugin["id"], e) continue # Initialize the plugins for plugin in self.__plugins_on_init: - plugin['module'].init(context, config, plugin['config']) + plugin["module"].init(context, config, plugin["config"]) return True def start(self): @@ -114,7 +117,7 @@ def start(self): Execute the on_start() function of plugins. """ for plugin in self.__plugins_on_start: - plugin['module'].on_start() + plugin["module"].on_start() return True def stop(self): @@ -122,7 +125,7 @@ def stop(self): Execute the on_stop() function of plugins. """ for plugin in self.__plugins_on_stop: - plugin['module'].on_stop() + plugin["module"].on_stop() return True def exit(self): @@ -130,7 +133,7 @@ def exit(self): Execute the on_exit() function of plugins. """ for plugin in self.__plugins_on_exit: - plugin['module'].on_exit() + plugin["module"].on_exit() return True def pre_break(self, break_obj): @@ -138,8 +141,8 @@ def pre_break(self, break_obj): Execute the on_pre_break(break_obj) function of plugins. """ for plugin in self.__plugins_on_pre_break: - if break_obj.plugin_enabled(plugin['id'], plugin['enabled']): - if plugin['module'].on_pre_break(break_obj): + if break_obj.plugin_enabled(plugin["id"], plugin["enabled"]): + if plugin["module"].on_pre_break(break_obj): return False return True @@ -149,8 +152,8 @@ def start_break(self, break_obj): """ self.last_break = break_obj for plugin in self.__plugins_on_start_break: - if break_obj.plugin_enabled(plugin['id'], plugin['enabled']): - if plugin['module'].on_start_break(break_obj): + if break_obj.plugin_enabled(plugin["id"], plugin["enabled"]): + if plugin["module"].on_start_break(break_obj): return False return True @@ -160,23 +163,23 @@ def stop_break(self): Execute the stop_break() function of plugins. """ for plugin in self.__plugins_on_stop_break: - if self.last_break.plugin_enabled(plugin['id'], plugin['enabled']): - plugin['module'].on_stop_break() + if self.last_break.plugin_enabled(plugin["id"], plugin["enabled"]): + plugin["module"].on_stop_break() def countdown(self, countdown, seconds): """ Execute the on_countdown(countdown, seconds) function of plugins. """ for plugin in self.__plugins_on_countdown: - if self.last_break.plugin_enabled(plugin['id'], plugin['enabled']): - plugin['module'].on_countdown(countdown, seconds) + if self.last_break.plugin_enabled(plugin["id"], plugin["enabled"]): + plugin["module"].on_countdown(countdown, seconds) def update_next_break(self, break_obj, break_time): """ Execute the update_next_break(break_time) function of plugins. """ for plugin in self.__plugins_update_next_break: - plugin['module'].update_next_break(break_obj, break_time) + plugin["module"].update_next_break(break_obj, break_time) return True def get_break_screen_widgets(self, break_obj): @@ -184,17 +187,19 @@ def get_break_screen_widgets(self, break_obj): Return the HTML widget generated by the plugins. The widget is generated by calling the get_widget_title and get_widget_content functions of plugins. """ - widget = '' + widget = "" for plugin in self.__widget_plugins: - if break_obj.plugin_enabled(plugin['id'], plugin['enabled']): + if break_obj.plugin_enabled(plugin["id"], plugin["enabled"]): try: - title = plugin['module'].get_widget_title(break_obj).upper().strip() - if title == '': + title = plugin["module"].get_widget_title(break_obj).upper().strip() + if title == "": continue - content = plugin['module'].get_widget_content(break_obj) - if content == '': + content = plugin["module"].get_widget_content(break_obj) + if content == "": continue - widget += '{}\n{}\n{}\n\n\n'.format(title, self.horizontal_line, content) + widget += "{}\n{}\n{}\n\n\n".format( + title, self.horizontal_line, content + ) except BaseException: continue return widget.strip() @@ -205,8 +210,8 @@ def get_break_screen_tray_actions(self, break_obj): """ actions = [] for plugin in self.__tray_actions_plugins: - if break_obj.plugin_enabled(plugin['id'], plugin['enabled']): - action = plugin['module'].get_tray_action(break_obj) + if break_obj.plugin_enabled(plugin["id"], plugin["enabled"]): + action = plugin["module"].get_tray_action(break_obj) if action: actions.append(action) @@ -216,23 +221,23 @@ def __load_plugin(self, plugin): """ Load the given plugin. """ - plugin_enabled = plugin['enabled'] - if plugin['id'] in self.__plugins and not plugin_enabled: + plugin_enabled = plugin["enabled"] + if plugin["id"] in self.__plugins and not plugin_enabled: # A disabled plugin but that was loaded earlier - plugin_obj = self.__plugins[plugin['id']] - if plugin_obj['enabled']: + plugin_obj = self.__plugins[plugin["id"]] + if plugin_obj["enabled"]: # Previously enabled but now disabled - plugin_obj['enabled'] = False + plugin_obj["enabled"] = False utility.remove_if_exists(self.__plugins_on_start, plugin_obj) utility.remove_if_exists(self.__plugins_on_stop, plugin_obj) utility.remove_if_exists(self.__plugins_on_exit, plugin_obj) utility.remove_if_exists(self.__plugins_update_next_break, plugin_obj) # Call the plugin.disable method if available - if utility.has_method(plugin_obj['module'], 'disable'): - plugin_obj['module'].disable() - logging.info("Successfully unloaded the plugin '%s'", plugin['id']) + if utility.has_method(plugin_obj["module"], "disable"): + plugin_obj["module"].disable() + logging.info("Successfully unloaded the plugin '%s'", plugin["id"]) - if not plugin_obj['break_override_allowed']: + if not plugin_obj["break_override_allowed"]: # Remaining methods also should be removed utility.remove_if_exists(self.__plugins_on_init, plugin_obj) utility.remove_if_exists(self.__plugins_on_pre_break, plugin_obj) @@ -241,43 +246,46 @@ def __load_plugin(self, plugin): utility.remove_if_exists(self.__plugins_on_countdown, plugin_obj) utility.remove_if_exists(self.__widget_plugins, plugin_obj) utility.remove_if_exists(self.__tray_actions_plugins, plugin_obj) - del self.__plugins[plugin['id']] + del self.__plugins[plugin["id"]] return # Look for plugin.py - if os.path.isfile(os.path.join(utility.SYSTEM_PLUGINS_DIR, plugin['id'], 'plugin.py')): + if os.path.isfile( + os.path.join(utility.SYSTEM_PLUGINS_DIR, plugin["id"], "plugin.py") + ): plugin_dir = utility.SYSTEM_PLUGINS_DIR - elif os.path.isfile(os.path.join(utility.USER_PLUGINS_DIR, plugin['id'], 'plugin.py')): + elif os.path.isfile( + os.path.join(utility.USER_PLUGINS_DIR, plugin["id"], "plugin.py") + ): plugin_dir = utility.USER_PLUGINS_DIR else: - logging.error('plugin.py not found for the plugin: %s', plugin['id']) + logging.error("plugin.py not found for the plugin: %s", plugin["id"]) return # Look for config.json - plugin_path = os.path.join(plugin_dir, plugin['id']) - plugin_config_path = os.path.join(plugin_path, 'config.json') + plugin_path = os.path.join(plugin_dir, plugin["id"]) + plugin_config_path = os.path.join(plugin_path, "config.json") if not os.path.isfile(plugin_config_path): - logging.error('config.json not found for the plugin: %s', plugin['id']) + logging.error("config.json not found for the plugin: %s", plugin["id"]) return plugin_config = utility.load_json(plugin_config_path) if plugin_config is None: return - if plugin_enabled or plugin_config.get('break_override_allowed', False): - if plugin['id'] in self.__plugins: + if plugin_enabled or plugin_config.get("break_override_allowed", False): + if plugin["id"] in self.__plugins: # The plugin is already enabled or partially loaded due to break_override_allowed # Validate the dependencies again if utility.check_plugin_dependencies( - plugin['id'], - plugin_config, - plugin.get('settings', {}), - plugin_path + plugin["id"], plugin_config, plugin.get("settings", {}), plugin_path ): - plugin_obj['enabled'] = False + plugin_obj["enabled"] = False utility.remove_if_exists(self.__plugins_on_start, plugin_obj) utility.remove_if_exists(self.__plugins_on_stop, plugin_obj) utility.remove_if_exists(self.__plugins_on_exit, plugin_obj) - utility.remove_if_exists(self.__plugins_update_next_break, plugin_obj) + utility.remove_if_exists( + self.__plugins_update_next_break, plugin_obj + ) utility.remove_if_exists(self.__plugins_on_init, plugin_obj) utility.remove_if_exists(self.__plugins_on_pre_break, plugin_obj) utility.remove_if_exists(self.__plugins_on_start_break, plugin_obj) @@ -285,80 +293,82 @@ def __load_plugin(self, plugin): utility.remove_if_exists(self.__plugins_on_countdown, plugin_obj) utility.remove_if_exists(self.__widget_plugins, plugin_obj) utility.remove_if_exists(self.__tray_actions_plugins, plugin_obj) - del self.__plugins[plugin['id']] + del self.__plugins[plugin["id"]] # Use the existing plugin object - plugin_obj = self.__plugins[plugin['id']] + plugin_obj = self.__plugins[plugin["id"]] # Update the config - plugin_obj['config'] = dict(plugin.get('settings', {})) - plugin_obj['config']['path'] = os.path.join(plugin_dir, plugin['id']) + plugin_obj["config"] = dict(plugin.get("settings", {})) + plugin_obj["config"]["path"] = os.path.join(plugin_dir, plugin["id"]) - if plugin_obj['enabled']: + if plugin_obj["enabled"]: # Already loaded completely return # Plugin was partially loaded due to break_override_allowed if plugin_enabled: # Load the rest of the methods - plugin_obj['enabled'] = True - module = plugin_obj['module'] + plugin_obj["enabled"] = True + module = plugin_obj["module"] self.__init_plugin(module, plugin_obj) else: # This is the first time to load the plugin # Check for dependencies message = utility.check_plugin_dependencies( - plugin['id'], - plugin_config, - plugin.get('settings', {}), - plugin_path + plugin["id"], plugin_config, plugin.get("settings", {}), plugin_path ) if message: - if plugin_config.get('required_plugin', False): + if plugin_config.get("required_plugin", False): raise RequiredPluginException( - plugin['id'], - plugin_config['meta']['name'], - message + plugin["id"], plugin_config["meta"]["name"], message ) return # Load the plugin module - module = importlib.import_module((plugin['id'] + '.plugin')) + module = importlib.import_module((plugin["id"] + ".plugin")) logging.info("Successfully loaded %s", str(module)) - plugin_obj = {'id': plugin['id'], 'module': module, 'config': dict(plugin.get( - 'settings', {})), 'enabled': plugin_enabled, - 'break_override_allowed': plugin_config.get('break_override_allowed', False)} + plugin_obj = { + "id": plugin["id"], + "module": module, + "config": dict(plugin.get("settings", {})), + "enabled": plugin_enabled, + "break_override_allowed": plugin_config.get( + "break_override_allowed", False + ), + } # Inject the plugin directory into the config - plugin_obj['config']['path'] = os.path.join(plugin_dir, plugin['id']) - self.__plugins[plugin['id']] = plugin_obj - if utility.has_method(module, 'enable'): + plugin_obj["config"]["path"] = os.path.join(plugin_dir, plugin["id"]) + self.__plugins[plugin["id"]] = plugin_obj + if utility.has_method(module, "enable"): module.enable() if plugin_enabled: self.__init_plugin(module, plugin_obj) - if utility.has_method(module, 'init', 3): + if utility.has_method(module, "init", 3): self.__plugins_on_init.append(plugin_obj) - if utility.has_method(module, 'on_pre_break', 1): + if utility.has_method(module, "on_pre_break", 1): self.__plugins_on_pre_break.append(plugin_obj) - if utility.has_method(module, 'on_start_break', 1): + if utility.has_method(module, "on_start_break", 1): self.__plugins_on_start_break.append(plugin_obj) - if utility.has_method(module, 'on_stop_break', 0): + if utility.has_method(module, "on_stop_break", 0): self.__plugins_on_stop_break.append(plugin_obj) - if utility.has_method(module, 'on_countdown', 2): + if utility.has_method(module, "on_countdown", 2): self.__plugins_on_countdown.append(plugin_obj) - if utility.has_method(module, 'get_widget_title', 1) and utility.has_method(module, - 'get_widget_content', 1): + if utility.has_method( + module, "get_widget_title", 1 + ) and utility.has_method(module, "get_widget_content", 1): self.__widget_plugins.append(plugin_obj) - if utility.has_method(module, 'get_tray_action', 1): + if utility.has_method(module, "get_tray_action", 1): self.__tray_actions_plugins.append(plugin_obj) def __init_plugin(self, module, plugin_obj): """ Collect mandatory methods from the plugin and add them to the life cycle methods list. """ - if utility.has_method(module, 'on_start'): + if utility.has_method(module, "on_start"): self.__plugins_on_start.append(plugin_obj) - if utility.has_method(module, 'on_stop'): + if utility.has_method(module, "on_stop"): self.__plugins_on_stop.append(plugin_obj) - if utility.has_method(module, 'on_exit'): + if utility.has_method(module, "on_exit"): self.__plugins_on_exit.append(plugin_obj) - if utility.has_method(module, 'update_next_break', 2): + if utility.has_method(module, "update_next_break", 2): self.__plugins_update_next_break.append(plugin_obj) diff --git a/safeeyes/plugins/audiblealert/plugin.py b/safeeyes/plugins/audiblealert/plugin.py index 0d9d4c1b..53b90f1b 100644 --- a/safeeyes/plugins/audiblealert/plugin.py +++ b/safeeyes/plugins/audiblealert/plugin.py @@ -34,16 +34,16 @@ def play_sound(resource_name): Arguments: resource_name {string} -- name of the wav file resource """ - logging.info('Playing audible alert %s', resource_name) + logging.info("Playing audible alert %s", resource_name) try: # Open the sound file path = utility.get_resource_path(resource_name) if path is None: return - utility.execute_command('aplay', ['-q', path]) + utility.execute_command("aplay", ["-q", path]) except BaseException: - logging.error('Failed to play audible alert %s', resource_name) + logging.error("Failed to play audible alert %s", resource_name) def init(ctx, safeeyes_config, plugin_config): @@ -53,10 +53,10 @@ def init(ctx, safeeyes_config, plugin_config): global context global pre_break_alert global post_break_alert - logging.debug('Initialize Audible Alert plugin') + logging.debug("Initialize Audible Alert plugin") context = ctx - pre_break_alert = plugin_config['pre_break_alert'] - post_break_alert = plugin_config['post_break_alert'] + pre_break_alert = plugin_config["pre_break_alert"] + post_break_alert = plugin_config["post_break_alert"] def on_pre_break(break_obj): @@ -66,7 +66,7 @@ def on_pre_break(break_obj): break_obj {safeeyes.model.Break} -- the break object """ if pre_break_alert: - play_sound('on_pre_break.wav') + play_sound("on_pre_break.wav") def on_stop_break(): @@ -74,6 +74,6 @@ def on_stop_break(): After the break, play the alert sound """ # Do not play if the break is skipped or postponed - if context['skipped'] or context['postponed'] or not post_break_alert: + if context["skipped"] or context["postponed"] or not post_break_alert: return - play_sound('on_stop_break.wav') + play_sound("on_stop_break.wav") diff --git a/safeeyes/plugins/donotdisturb/plugin.py b/safeeyes/plugins/donotdisturb/plugin.py index 0fdefa5c..19a5de5c 100644 --- a/safeeyes/plugins/donotdisturb/plugin.py +++ b/safeeyes/plugins/donotdisturb/plugin.py @@ -27,7 +27,8 @@ import subprocess import gi -gi.require_version('Gdk', '3.0') + +gi.require_version("Gdk", "3.0") from gi.repository import Gdk from gi.repository import GdkX11 # noqa F401 from gi.repository import Gio @@ -41,7 +42,7 @@ def is_active_window_skipped_wayland(pre_break): - cmdlist = ['wlrctl', 'toplevel', 'find', 'state:fullscreen'] + cmdlist = ["wlrctl", "toplevel", "find", "state:fullscreen"] try: process = subprocess.Popen(cmdlist, stdout=subprocess.PIPE) process.communicate()[0] @@ -50,10 +51,12 @@ def is_active_window_skipped_wayland(pre_break): elif process.returncode == 1: return False elif process.returncode == 127: - logging.warning('Could not find wlrctl needed to detect fullscreen under wayland') + logging.warning( + "Could not find wlrctl needed to detect fullscreen under wayland" + ) return False except subprocess.CalledProcessError: - logging.warning('Error in finding full-screen application') + logging.warning("Error in finding full-screen application") return False @@ -62,22 +65,29 @@ def is_active_window_skipped_xorg(pre_break): Check for full-screen applications. This method must be executed by the main thread. If not, it will cause random failure. """ - logging.info('Searching for full-screen application') + logging.info("Searching for full-screen application") screen = Gdk.Screen.get_default() active_window = screen.get_active_window() if active_window: active_xid = str(active_window.get_xid()) - cmdlist = ['xprop', '-root', '-notype', '-id', - active_xid, 'WM_CLASS', '_NET_WM_STATE'] + cmdlist = [ + "xprop", + "-root", + "-notype", + "-id", + active_xid, + "WM_CLASS", + "_NET_WM_STATE", + ] try: - stdout = subprocess.check_output(cmdlist).decode('utf-8') + stdout = subprocess.check_output(cmdlist).decode("utf-8") except subprocess.CalledProcessError: - logging.warning('Error in finding full-screen application') + logging.warning("Error in finding full-screen application") else: if stdout: - is_fullscreen = 'FULLSCREEN' in stdout + is_fullscreen = "FULLSCREEN" in stdout # Extract the process name process_names = re.findall('"(.+?)"', stdout) if process_names: @@ -89,7 +99,10 @@ def is_active_window_skipped_xorg(pre_break): try: active_window.unfullscreen() except BaseException as e: - logging.error('Error in unfullscreen the window ' + process_name, exc_info=e) + logging.error( + "Error in unfullscreen the window " + process_name, + exc_info=e, + ) return False return is_fullscreen @@ -109,12 +122,12 @@ def is_idle_inhibited_gnome(): bus_type=Gio.BusType.SESSION, flags=Gio.DBusProxyFlags.NONE, info=None, - name='org.gnome.SessionManager', - object_path='/org/gnome/SessionManager', - interface_name='org.gnome.SessionManager', + name="org.gnome.SessionManager", + object_path="/org/gnome/SessionManager", + interface_name="org.gnome.SessionManager", cancellable=None, ) - result = dbus_proxy.get_cached_property('InhibitedActions').unpack() + result = dbus_proxy.get_cached_property("InhibitedActions").unpack() # The result is a bitfield, documented here: # https://gitlab.gnome.org/GNOME/gnome-session/-/blob/9aa419397b7f6d42bee6e66cc5c5aad12902fba0/gnome-session/org.gnome.SessionManager.xml#L155 @@ -131,23 +144,26 @@ def is_on_battery(): Check if the computer is running on battery. """ on_battery = False - available_power_sources = os.listdir('/sys/class/power_supply') - logging.info('Looking for battery status in available power sources: %s' % str( - available_power_sources)) + available_power_sources = os.listdir("/sys/class/power_supply") + logging.info( + "Looking for battery status in available power sources: %s" + % str(available_power_sources) + ) for power_source in available_power_sources: - if 'BAT' in power_source: + if "BAT" in power_source: # Found battery battery_status = os.path.join( - '/sys/class/power_supply', power_source, 'status') + "/sys/class/power_supply", power_source, "status" + ) if os.path.isfile(battery_status): # Additional check to confirm that the status file exists try: - with open(battery_status, 'r') as status_file: + with open(battery_status, "r") as status_file: status = status_file.read() if status: - on_battery = 'discharging' in status.lower() + on_battery = "discharging" in status.lower() except BaseException: - logging.error('Failed to read %s' % battery_status) + logging.error("Failed to read %s" % battery_status) break return on_battery @@ -158,12 +174,16 @@ def init(ctx, safeeyes_config, plugin_config): global take_break_window_classes global unfullscreen_allowed global dnd_while_on_battery - logging.debug('Initialize Skip Fullscreen plugin') + logging.debug("Initialize Skip Fullscreen plugin") context = ctx - skip_break_window_classes = _normalize_window_classes(plugin_config['skip_break_windows']) - take_break_window_classes = _normalize_window_classes(plugin_config['take_break_windows']) - unfullscreen_allowed = plugin_config['unfullscreen'] - dnd_while_on_battery = plugin_config['while_on_battery'] + skip_break_window_classes = _normalize_window_classes( + plugin_config["skip_break_windows"] + ) + take_break_window_classes = _normalize_window_classes( + plugin_config["take_break_windows"] + ) + unfullscreen_allowed = plugin_config["unfullscreen"] + dnd_while_on_battery = plugin_config["while_on_battery"] def _normalize_window_classes(classes_as_str: str): @@ -175,7 +195,7 @@ def on_pre_break(break_obj): Lifecycle method executes before the pre-break period. """ if utility.IS_WAYLAND: - if utility.DESKTOP_ENVIRONMENT == 'gnome': + if utility.DESKTOP_ENVIRONMENT == "gnome": skip_break = is_idle_inhibited_gnome() else: skip_break = is_active_window_skipped_wayland(True) @@ -191,7 +211,7 @@ def on_start_break(break_obj): Lifecycle method executes just before the break. """ if utility.IS_WAYLAND: - if utility.DESKTOP_ENVIRONMENT == 'gnome': + if utility.DESKTOP_ENVIRONMENT == "gnome": skip_break = is_idle_inhibited_gnome() else: skip_break = is_active_window_skipped_wayland(True) diff --git a/safeeyes/plugins/healthstats/plugin.py b/safeeyes/plugins/healthstats/plugin.py index cf6c1d40..b878c0e4 100644 --- a/safeeyes/plugins/healthstats/plugin.py +++ b/safeeyes/plugins/healthstats/plugin.py @@ -27,7 +27,7 @@ context = None session = None statistics_reset_cron = None -default_statistics_reset_cron = '0 0 * * *' # Every midnight +default_statistics_reset_cron = "0 0 * * *" # Every midnight next_reset_time = None start_time = None @@ -40,27 +40,29 @@ def init(ctx, safeeyes_config, plugin_config): global session global statistics_reset_cron - logging.debug('Initialize Health Stats plugin') + logging.debug("Initialize Health Stats plugin") context = ctx - statistics_reset_cron = plugin_config.get('statistics_reset_cron', default_statistics_reset_cron) + statistics_reset_cron = plugin_config.get( + "statistics_reset_cron", default_statistics_reset_cron + ) if session is None: # Read the session defaults = { - 'breaks': 0, - 'skipped_breaks': 0, - 'screen_time': 0, - 'total_breaks': 0, - 'total_skipped_breaks': 0, - 'total_screen_time': 0, - 'total_resets': 0, + "breaks": 0, + "skipped_breaks": 0, + "screen_time": 0, + "total_breaks": 0, + "total_skipped_breaks": 0, + "total_screen_time": 0, + "total_resets": 0, } - session = context['session']['plugin'].get('healthstats', {}) | defaults - if 'no_of_breaks' in session: + session = context["session"]["plugin"].get("healthstats", {}) | defaults + if "no_of_breaks" in session: # Ignore old format session. session = defaults - context['session']['plugin']['healthstats'] = session + context["session"]["plugin"]["healthstats"] = session _get_next_reset_time() @@ -68,8 +70,8 @@ def init(ctx, safeeyes_config, plugin_config): def on_stop_break(): # Check if break was skipped. global session - if context['skipped']: - session['skipped_breaks'] += 1 + if context["skipped"]: + session["skipped_breaks"] += 1 # Screen time is starting again. on_start() @@ -77,7 +79,7 @@ def on_stop_break(): def on_start_break(break_obj): global session - session['breaks'] += 1 + session["breaks"] += 1 # Screen time has stopped. on_stop() @@ -88,7 +90,7 @@ def on_stop(): _reset_stats() if start_time: screen_time = datetime.datetime.now() - start_time - session['screen_time'] += round(screen_time.total_seconds()) + session["screen_time"] += round(screen_time.total_seconds()) start_time = None @@ -96,7 +98,7 @@ def get_widget_title(break_obj): """ Return the widget title. """ - return _('Health Statistics') + return _("Health Statistics") def _reset_stats(): @@ -110,13 +112,13 @@ def _reset_stats(): _get_next_reset_time() # Reset statistics - session['total_breaks'] += session['breaks'] - session['total_skipped_breaks'] += session['skipped_breaks'] - session['total_screen_time'] += session['screen_time'] - session['total_resets'] += 1 - session['breaks'] = 0 - session['skipped_breaks'] = 0 - session['screen_time'] = 0 + session["total_breaks"] += session["breaks"] + session["total_skipped_breaks"] += session["skipped_breaks"] + session["total_screen_time"] += session["screen_time"] + session["total_resets"] += 1 + session["breaks"] = 0 + session["skipped_breaks"] = 0 + session["screen_time"] = 0 def get_widget_content(break_obj): @@ -124,19 +126,22 @@ def get_widget_content(break_obj): Return the statistics. """ global next_reset_time - resets = session['total_resets'] - if session['screen_time'] > 21600 or (session['breaks'] and session['skipped_breaks'] / session['breaks']) >= 0.2: + resets = session["total_resets"] + if ( + session["screen_time"] > 21600 + or (session["breaks"] and session["skipped_breaks"] / session["breaks"]) >= 0.2 + ): # Unhealthy behavior -> Red broken heart - heart = '💔️' + heart = "💔️" else: # Healthy behavior -> Green heart - heart = '💚' + heart = "💚" content = [ - heart, - f"BREAKS: {session['breaks']}", - f"SKIPPED: {session['skipped_breaks']}", - f"SCREEN TIME: {_format_interval(session['screen_time'])}", + heart, + f"BREAKS: {session['breaks']}", + f"SKIPPED: {session['skipped_breaks']}", + f"SCREEN TIME: {_format_interval(session['screen_time'])}", ] if resets: @@ -148,7 +153,9 @@ def get_widget_content(break_obj): if resets: content += f"\n\t[] = average of {resets} reset(s)" if next_reset_time is None: - content += f"\n\tSettings error in statistics reset interval: {statistics_reset_cron}" + content += ( + f"\n\tSettings error in statistics reset interval: {statistics_reset_cron}" + ) return content @@ -168,8 +175,8 @@ def _get_next_reset_time(): try: cron = croniter.croniter(statistics_reset_cron, datetime.datetime.now()) next_reset_time = cron.get_next(datetime.datetime) - session['next_reset_time'] = next_reset_time.strftime("%Y-%m-%d %H:%M:%S") - logging.debug("Health stats will be reset at " + session['next_reset_time']) + session["next_reset_time"] = next_reset_time.strftime("%Y-%m-%d %H:%M:%S") + logging.debug("Health stats will be reset at " + session["next_reset_time"]) except: # noqa E722 # TODO: consider catching Exception here instead of bare except logging.error("Error in statistics reset expression: " + statistics_reset_cron) @@ -179,4 +186,4 @@ def _get_next_reset_time(): def _format_interval(seconds): screen_time = round(seconds / 60) hours, minutes = divmod(screen_time, 60) - return '{:02d}:{:02d}'.format(hours, minutes) + return "{:02d}:{:02d}".format(hours, minutes) diff --git a/safeeyes/plugins/limitconsecutiveskipping/plugin.py b/safeeyes/plugins/limitconsecutiveskipping/plugin.py index 469d9ffc..a5dbff0c 100644 --- a/safeeyes/plugins/limitconsecutiveskipping/plugin.py +++ b/safeeyes/plugins/limitconsecutiveskipping/plugin.py @@ -38,18 +38,18 @@ def init(ctx, safeeyes_config, plugin_config): global no_of_skipped_breaks global no_allowed_skips - logging.debug('Initialize Limit consecutive skipping plugin') + logging.debug("Initialize Limit consecutive skipping plugin") context = ctx - no_allowed_skips = plugin_config.get('number_of_allowed_skips_in_a_row', 2) + no_allowed_skips = plugin_config.get("number_of_allowed_skips_in_a_row", 2) if session is None: # Read the session - session = context['session']['plugin'].get('limitconsecutiveskipping', None) + session = context["session"]["plugin"].get("limitconsecutiveskipping", None) if session is None: - session = {'no_of_skipped_breaks': 0} - context['session']['plugin']['limitconsecutiveskipping'] = session - no_of_skipped_breaks = session.get('no_of_skipped_breaks', 0) + session = {"no_of_skipped_breaks": 0} + context["session"]["plugin"]["limitconsecutiveskipping"] = session + no_of_skipped_breaks = session.get("no_of_skipped_breaks", 0) def on_stop_break(): @@ -61,20 +61,22 @@ def on_stop_break(): return global no_of_skipped_breaks - if context['skipped'] or context['postponed']: + if context["skipped"] or context["postponed"]: no_of_skipped_breaks += 1 - session['no_of_skipped_breaks'] = no_of_skipped_breaks + session["no_of_skipped_breaks"] = no_of_skipped_breaks else: no_of_skipped_breaks = 0 - session['no_of_skipped_breaks'] = no_of_skipped_breaks + session["no_of_skipped_breaks"] = no_of_skipped_breaks def on_start_break(break_obj): - logging.debug('Skipped / allowed = {} / {}'.format(no_of_skipped_breaks, no_allowed_skips)) + logging.debug( + "Skipped / allowed = {} / {}".format(no_of_skipped_breaks, no_allowed_skips) + ) if no_of_skipped_breaks >= no_allowed_skips: - context['postpone_button_disabled'] = True - context['skip_button_disabled'] = True + context["postpone_button_disabled"] = True + context["skip_button_disabled"] = True def get_widget_title(break_obj): @@ -85,7 +87,7 @@ def get_widget_title(break_obj): if not enabled: return "" - return _('Limit Consecutive Skipping') + return _("Limit Consecutive Skipping") def get_widget_content(break_obj): @@ -96,4 +98,7 @@ def get_widget_content(break_obj): if not enabled: return "" - return _('Skipped or postponed %d/%d breaks in a row') % (no_of_skipped_breaks, no_allowed_skips) + return _("Skipped or postponed %d/%d breaks in a row") % ( + no_of_skipped_breaks, + no_allowed_skips, + ) diff --git a/safeeyes/plugins/mediacontrol/plugin.py b/safeeyes/plugins/mediacontrol/plugin.py index 2bbd02f9..405c343b 100644 --- a/safeeyes/plugins/mediacontrol/plugin.py +++ b/safeeyes/plugins/mediacontrol/plugin.py @@ -24,7 +24,8 @@ import re import gi from safeeyes.model import TrayAction -gi.require_version('Gtk', '3.0') + +gi.require_version("Gtk", "3.0") from gi.repository import Gtk, Gio tray_icon_path = None @@ -40,25 +41,25 @@ def __active_players(): bus_type=Gio.BusType.SESSION, flags=Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES, info=None, - name='org.freedesktop.DBus', - object_path='/org/freedesktop/DBus', - interface_name='org.freedesktop.DBus', + name="org.freedesktop.DBus", + object_path="/org/freedesktop/DBus", + interface_name="org.freedesktop.DBus", cancellable=None, ) for service in dbus_proxy.ListNames(): - if re.match('org.mpris.MediaPlayer2.', service): + if re.match("org.mpris.MediaPlayer2.", service): player = Gio.DBusProxy.new_for_bus_sync( bus_type=Gio.BusType.SESSION, flags=Gio.DBusProxyFlags.NONE, info=None, name=service, - object_path='/org/mpris/MediaPlayer2', - interface_name='org.mpris.MediaPlayer2.Player', + object_path="/org/mpris/MediaPlayer2", + interface_name="org.mpris.MediaPlayer2.Player", cancellable=None, ) - status = player.get_cached_property('PlaybackStatus').unpack().lower() + status = player.get_cached_property("PlaybackStatus").unpack().lower() if status == "playing": players.append(player) @@ -78,7 +79,7 @@ def init(ctx, safeeyes_config, plugin_config): Initialize the screensaver plugin. """ global tray_icon_path - tray_icon_path = os.path.join(plugin_config['path'], "resource/pause.png") + tray_icon_path = os.path.join(plugin_config["path"], "resource/pause.png") def get_tray_action(break_obj): @@ -87,7 +88,9 @@ def get_tray_action(break_obj): """ players = __active_players() if players: - return TrayAction.build("Pause media", - tray_icon_path, - Gtk.STOCK_MEDIA_PAUSE, - lambda: __pause_players(players)) + return TrayAction.build( + "Pause media", + tray_icon_path, + Gtk.STOCK_MEDIA_PAUSE, + lambda: __pause_players(players), + ) diff --git a/safeeyes/plugins/notification/plugin.py b/safeeyes/plugins/notification/plugin.py index b7920fbb..d4da41ee 100644 --- a/safeeyes/plugins/notification/plugin.py +++ b/safeeyes/plugins/notification/plugin.py @@ -21,14 +21,14 @@ import gi from safeeyes.model import BreakType -gi.require_version('Notify', '0.7') +gi.require_version("Notify", "0.7") from gi.repository import Notify """ Safe Eyes Notification plugin """ -APPINDICATOR_ID = 'safeeyes' +APPINDICATOR_ID = "safeeyes" notification = None context = None warning_time = 10 @@ -42,9 +42,9 @@ def init(ctx, safeeyes_config, plugin_config): """ global context global warning_time - logging.debug('Initialize Notification plugin') + logging.debug("Initialize Notification plugin") context = ctx - warning_time = safeeyes_config.get('pre_break_warning_time') + warning_time = safeeyes_config.get("pre_break_warning_time") def on_pre_break(break_obj): @@ -53,18 +53,20 @@ def on_pre_break(break_obj): """ # Construct the message based on the type of the next break global notification - logging.info('Show the notification') - message = '\n' + logging.info("Show the notification") + message = "\n" if break_obj.type == BreakType.SHORT_BREAK: - message += (_('Ready for a short break in %s seconds') % warning_time) + message += _("Ready for a short break in %s seconds") % warning_time else: - message += (_('Ready for a long break in %s seconds') % warning_time) + message += _("Ready for a long break in %s seconds") % warning_time - notification = Notify.Notification.new('Safe Eyes', message, icon='io.github.slgobinath.SafeEyes-enabled') + notification = Notify.Notification.new( + "Safe Eyes", message, icon="io.github.slgobinath.SafeEyes-enabled" + ) try: notification.show() except BaseException: - logging.error('Failed to show the notification') + logging.error("Failed to show the notification") def on_start_break(break_obj): @@ -72,7 +74,7 @@ def on_start_break(break_obj): Close the notification. """ global notification - logging.info('Close pre-break notification') + logging.info("Close pre-break notification") if notification: try: notification.close() @@ -86,5 +88,5 @@ def on_exit(): """ Uninitialize the registered notification. """ - logging.debug('Stop Notification plugin') + logging.debug("Stop Notification plugin") Notify.uninit() diff --git a/safeeyes/plugins/screensaver/plugin.py b/safeeyes/plugins/screensaver/plugin.py index b0f50cb6..afaa369f 100644 --- a/safeeyes/plugins/screensaver/plugin.py +++ b/safeeyes/plugins/screensaver/plugin.py @@ -26,7 +26,8 @@ from safeeyes import utility from safeeyes.model import TrayAction -gi.require_version('Gtk', '3.0') + +gi.require_version("Gtk", "3.0") from gi.repository import Gtk context = None @@ -50,52 +51,56 @@ def __lock_screen_command(): XFCE: ['xflock4'] Otherwise: None """ - desktop_session = os.environ.get('DESKTOP_SESSION') - current_desktop = os.environ.get('XDG_CURRENT_DESKTOP') + desktop_session = os.environ.get("DESKTOP_SESSION") + current_desktop = os.environ.get("XDG_CURRENT_DESKTOP") if desktop_session is not None: desktop_session = desktop_session.lower() if ( - ( - 'xfce' in desktop_session or desktop_session.startswith('xubuntu') - or (current_desktop is not None and 'xfce' in current_desktop) - ) and utility.command_exist('xflock4') + "xfce" in desktop_session + or desktop_session.startswith("xubuntu") + or (current_desktop is not None and "xfce" in current_desktop) + ) and utility.command_exist("xflock4"): + return ["xflock4"] + elif desktop_session == "cinnamon" and utility.command_exist( + "cinnamon-screensaver-command" ): - return ['xflock4'] - elif desktop_session == 'cinnamon' and utility.command_exist('cinnamon-screensaver-command'): - return ['cinnamon-screensaver-command', '--lock'] + return ["cinnamon-screensaver-command", "--lock"] elif ( - (desktop_session == 'pantheon' or desktop_session.startswith('lubuntu')) - and utility.command_exist('light-locker-command') + desktop_session == "pantheon" or desktop_session.startswith("lubuntu") + ) and utility.command_exist("light-locker-command"): + return ["light-locker-command", "--lock"] + elif desktop_session == "mate" and utility.command_exist( + "mate-screensaver-command" ): - return ['light-locker-command', '--lock'] - elif desktop_session == 'mate' and utility.command_exist('mate-screensaver-command'): - return ['mate-screensaver-command', '--lock'] + return ["mate-screensaver-command", "--lock"] elif ( - desktop_session == 'kde' or 'plasma' in desktop_session - or desktop_session.startswith('kubuntu') or os.environ.get('KDE_FULL_SESSION') == 'true' + desktop_session == "kde" + or "plasma" in desktop_session + or desktop_session.startswith("kubuntu") + or os.environ.get("KDE_FULL_SESSION") == "true" ): - return ['qdbus', 'org.freedesktop.ScreenSaver', '/ScreenSaver', 'Lock'] + return ["qdbus", "org.freedesktop.ScreenSaver", "/ScreenSaver", "Lock"] elif ( - desktop_session in ['gnome', 'unity', 'budgie-desktop'] or desktop_session.startswith('ubuntu') - or desktop_session.startswith('gnome') + desktop_session in ["gnome", "unity", "budgie-desktop"] + or desktop_session.startswith("ubuntu") + or desktop_session.startswith("gnome") ): - if utility.command_exist('gnome-screensaver-command'): - return ['gnome-screensaver-command', '--lock'] + if utility.command_exist("gnome-screensaver-command"): + return ["gnome-screensaver-command", "--lock"] # From Gnome 3.8 no gnome-screensaver-command return [ - 'dbus-send', - '--type=method_call', - '--dest=org.gnome.ScreenSaver', - '/org/gnome/ScreenSaver', - 'org.gnome.ScreenSaver.Lock' + "dbus-send", + "--type=method_call", + "--dest=org.gnome.ScreenSaver", + "/org/gnome/ScreenSaver", + "org.gnome.ScreenSaver.Lock", ] - elif os.environ.get('GNOME_DESKTOP_SESSION_ID'): - if ( - 'deprecated' not in os.environ.get('GNOME_DESKTOP_SESSION_ID') - and utility.command_exist('gnome-screensaver-command') - ): + elif os.environ.get("GNOME_DESKTOP_SESSION_ID"): + if "deprecated" not in os.environ.get( + "GNOME_DESKTOP_SESSION_ID" + ) and utility.command_exist("gnome-screensaver-command"): # Gnome 2 - return ['gnome-screensaver-command', '--lock'] + return ["gnome-screensaver-command", "--lock"] return None @@ -112,12 +117,12 @@ def init(ctx, safeeyes_config, plugin_config): global lock_screen_command global min_seconds global tray_icon_path - logging.debug('Initialize Screensaver plugin') + logging.debug("Initialize Screensaver plugin") context = ctx - min_seconds = plugin_config['min_seconds'] - tray_icon_path = os.path.join(plugin_config['path'], "resource/lock.png") - if plugin_config['command']: - lock_screen_command = plugin_config['command'].split() + min_seconds = plugin_config["min_seconds"] + tray_icon_path = os.path.join(plugin_config["path"], "resource/lock.png") + if plugin_config["command"]: + lock_screen_command = plugin_config["command"].split() else: lock_screen_command = __lock_screen_command() @@ -152,7 +157,6 @@ def on_stop_break(): def get_tray_action(break_obj): - return TrayAction.build("Lock screen", - tray_icon_path, - Gtk.STOCK_DIALOG_AUTHENTICATION, - __lock_screen) + return TrayAction.build( + "Lock screen", tray_icon_path, Gtk.STOCK_DIALOG_AUTHENTICATION, __lock_screen + ) diff --git a/safeeyes/plugins/smartpause/plugin.py b/safeeyes/plugins/smartpause/plugin.py index 22920370..bb8e47fe 100644 --- a/safeeyes/plugins/smartpause/plugin.py +++ b/safeeyes/plugins/smartpause/plugin.py @@ -52,8 +52,7 @@ def __swayidle_running(): - return (swayidle_process is not None and - swayidle_process.poll() is None) + return swayidle_process is not None and swayidle_process.poll() is None def __start_swayidle_monitor(): @@ -61,23 +60,27 @@ def __start_swayidle_monitor(): global swayidle_start global swayidle_idle global swayidle_active - logging.debug('Starting swayidle subprocess') - swayidle_process = subprocess.Popen([ - "swayidle", "timeout", "1", "date +S%s", "resume", "date +R%s" - ], stdout=subprocess.PIPE, bufsize=1, universal_newlines=True, encoding='utf-8') + logging.debug("Starting swayidle subprocess") + swayidle_process = subprocess.Popen( + ["swayidle", "timeout", "1", "date +S%s", "resume", "date +R%s"], + stdout=subprocess.PIPE, + bufsize=1, + universal_newlines=True, + encoding="utf-8", + ) for line in swayidle_process.stdout: with swayidle_lock: typ = line[0] timestamp = int(line[1:]) - if typ == 'S': + if typ == "S": swayidle_idle = timestamp - elif typ == 'R': + elif typ == "R": swayidle_active = timestamp def __stop_swayidle_monitor(): if __swayidle_running(): - logging.debug('Stopping swayidle subprocess') + logging.debug("Stopping swayidle subprocess") swayidle_process.terminate() @@ -99,14 +102,16 @@ def __gnome_wayland_idle_time(): https://unix.stackexchange.com/a/492328/222290 """ try: - output = subprocess.check_output([ - 'dbus-send', - '--print-reply', - '--dest=org.gnome.Mutter.IdleMonitor', - '/org/gnome/Mutter/IdleMonitor/Core', - 'org.gnome.Mutter.IdleMonitor.GetIdletime' - ]) - return int(re.search(rb'\d+$', output).group(0)) / 1000 + output = subprocess.check_output( + [ + "dbus-send", + "--print-reply", + "--dest=org.gnome.Mutter.IdleMonitor", + "/org/gnome/Mutter/IdleMonitor/Core", + "org.gnome.Mutter.IdleMonitor.GetIdletime", + ] + ) + return int(re.search(rb"\d+$", output).group(0)) / 1000 except BaseException as e: logging.warning("Failed to get system idle time for gnome/wayland.") logging.warning(str(e)) @@ -124,7 +129,7 @@ def __system_idle_time(): elif use_swayidle: return __swayidle_idle_time() # Convert to seconds - return int(subprocess.check_output(['xprintidle']).decode('utf-8')) / 1000 + return int(subprocess.check_output(["xprintidle"]).decode("utf-8")) / 1000 except BaseException: return 0 @@ -163,19 +168,20 @@ def init(ctx, safeeyes_config, plugin_config): global postpone_if_active global is_wayland_and_gnome global use_swayidle - logging.debug('Initialize Smart Pause plugin') + logging.debug("Initialize Smart Pause plugin") context = ctx - enable_safeeyes = context['api']['enable_safeeyes'] - disable_safeeyes = context['api']['disable_safeeyes'] - postpone = context['api']['postpone'] - idle_time = plugin_config['idle_time'] - postpone_if_active = plugin_config['postpone_if_active'] - short_break_interval = safeeyes_config.get( - 'short_break_interval') * 60 # Convert to seconds - long_break_duration = safeeyes_config.get('long_break_duration') + enable_safeeyes = context["api"]["enable_safeeyes"] + disable_safeeyes = context["api"]["disable_safeeyes"] + postpone = context["api"]["postpone"] + idle_time = plugin_config["idle_time"] + postpone_if_active = plugin_config["postpone_if_active"] + short_break_interval = ( + safeeyes_config.get("short_break_interval") * 60 + ) # Convert to seconds + long_break_duration = safeeyes_config.get("long_break_duration") waiting_time = min(2, idle_time) # If idle time is 1 sec, wait only 1 sec - is_wayland_and_gnome = context['desktop'] == 'gnome' and context['is_wayland'] - use_swayidle = context['desktop'] == 'sway' + is_wayland_and_gnome = context["desktop"] == "gnome" and context["is_wayland"] + use_swayidle = context["desktop"] == "sway" def __start_idle_monitor(): @@ -194,17 +200,23 @@ def __start_idle_monitor(): if __is_active(): # Get the system idle time system_idle_time = __system_idle_time() - if system_idle_time >= idle_time and context['state'] == State.WAITING: + if system_idle_time >= idle_time and context["state"] == State.WAITING: smart_pause_activated = True - idle_start_time = datetime.datetime.now() - datetime.timedelta(seconds=system_idle_time) - logging.info('Pause Safe Eyes due to system idle') + idle_start_time = datetime.datetime.now() - datetime.timedelta( + seconds=system_idle_time + ) + logging.info("Pause Safe Eyes due to system idle") disable_safeeyes(None, True) - elif system_idle_time < idle_time and context['state'] == State.RESTING and idle_start_time is not None: - logging.info('Resume Safe Eyes due to user activity') + elif ( + system_idle_time < idle_time + and context["state"] == State.RESTING + and idle_start_time is not None + ): + logging.info("Resume Safe Eyes due to user activity") smart_pause_activated = False - idle_period = (datetime.datetime.now() - idle_start_time) + idle_period = datetime.datetime.now() - idle_start_time idle_seconds = idle_period.total_seconds() - context['idle_period'] = idle_seconds + context["idle_period"] = idle_seconds if idle_seconds < short_break_interval: # Credit back the idle time if next_break_time is not None: @@ -226,7 +238,7 @@ def on_start(): global active if not __is_active(): # If SmartPause is already started, do not start it again - logging.debug('Start Smart Pause plugin') + logging.debug("Start Smart Pause plugin") __set_active(True) utility.start_thread(__start_idle_monitor) @@ -241,7 +253,7 @@ def on_stop(): # Safe Eyes is stopped due to system idle smart_pause_activated = False return - logging.debug('Stop Smart Pause plugin') + logging.debug("Stop Smart Pause plugin") if use_swayidle: __stop_swayidle_monitor() __set_active(False) @@ -276,4 +288,4 @@ def disable(): SmartPause plugin was active earlier but now user has disabled it. """ # Remove the idle_period - context.pop('idle_period', None) + context.pop("idle_period", None) diff --git a/safeeyes/plugins/trayicon/dependency_checker.py b/safeeyes/plugins/trayicon/dependency_checker.py index 3a3791c4..77a73c37 100644 --- a/safeeyes/plugins/trayicon/dependency_checker.py +++ b/safeeyes/plugins/trayicon/dependency_checker.py @@ -20,7 +20,8 @@ from safeeyes.model import PluginDependency import gi -gi.require_version('Gio', '2.0') + +gi.require_version("Gio", "2.0") from gi.repository import Gio @@ -29,18 +30,20 @@ def validate(plugin_config, plugin_settings): bus_type=Gio.BusType.SESSION, flags=Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES, info=None, - name='org.freedesktop.DBus', - object_path='/org/freedesktop/DBus', - interface_name='org.freedesktop.DBus', + name="org.freedesktop.DBus", + object_path="/org/freedesktop/DBus", + interface_name="org.freedesktop.DBus", cancellable=None, ) - if dbus_proxy.NameHasOwner('(s)', 'org.kde.StatusNotifierWatcher'): + if dbus_proxy.NameHasOwner("(s)", "org.kde.StatusNotifierWatcher"): return None else: return PluginDependency( - message=_("Please install service providing tray icons for your desktop environment."), - link="https://github.com/slgobinath/SafeEyes/wiki/How-to-install-backend-for-Safe-Eyes-tray-icon" + message=_( + "Please install service providing tray icons for your desktop environment." + ), + link="https://github.com/slgobinath/SafeEyes/wiki/How-to-install-backend-for-Safe-Eyes-tray-icon", ) command = None diff --git a/safeeyes/plugins/trayicon/plugin.py b/safeeyes/plugins/trayicon/plugin.py index 5be701f6..49587548 100644 --- a/safeeyes/plugins/trayicon/plugin.py +++ b/safeeyes/plugins/trayicon/plugin.py @@ -19,7 +19,8 @@ import datetime from safeeyes.model import BreakType import gi -gi.require_version('Gtk', '3.0') + +gi.require_version("Gtk", "3.0") from gi.repository import Gio, GLib import logging from safeeyes import utility @@ -34,7 +35,8 @@ tray_icon = None safeeyes_config = None -SNI_NODE_INFO = Gio.DBusNodeInfo.new_for_xml(""" +SNI_NODE_INFO = Gio.DBusNodeInfo.new_for_xml( + """ @@ -50,9 +52,11 @@ -""").interfaces[0] +""" +).interfaces[0] -MENU_NODE_INFO = Gio.DBusNodeInfo.new_for_xml(""" +MENU_NODE_INFO = Gio.DBusNodeInfo.new_for_xml( + """ @@ -97,7 +101,8 @@ -""").interfaces[0] +""" +).interfaces[0] class DBusService: @@ -112,7 +117,7 @@ def register(self): object_path=self.object_path, interface_info=self.interface_info, method_call_closure=self.on_method_call, - get_property_closure=self.on_get_property + get_property_closure=self.on_get_property, ) if not self.registration_id: @@ -127,7 +132,16 @@ def unregister(self): self.bus.unregister_object(self.registration_id) self.registration_id = None - def on_method_call(self, _connection, _sender, _path, _interface_name, method_name, parameters, invocation): + def on_method_call( + self, + _connection, + _sender, + _path, + _interface_name, + method_name, + parameters, + invocation, + ): method_info = self.interface_info.lookup_method(method_name) method = getattr(self, method_name) result = method(*parameters.unpack()) @@ -139,7 +153,9 @@ def on_method_call(self, _connection, _sender, _path, _interface_name, method_na invocation.return_value(return_value) - def on_get_property(self, _connection, _sender, _path, _interface_name, property_name): + def on_get_property( + self, _connection, _sender, _path, _interface_name, property_name + ): property_info = self.interface_info.lookup_property(property_name) return GLib.Variant(property_info.signature, getattr(self, property_name)) @@ -155,12 +171,12 @@ def emit_signal(self, signal_name, args=None): object_path=self.object_path, interface_name=self.interface_info.name, signal_name=signal_name, - parameters=parameters + parameters=parameters, ) class DBusMenuService(DBusService): - DBUS_SERVICE_PATH = '/io/github/slgobinath/SafeEyes/Menu' + DBUS_SERVICE_PATH = "/io/github/slgobinath/SafeEyes/Menu" revision = 0 @@ -171,7 +187,7 @@ def __init__(self, session_bus, context, items): super().__init__( interface_info=MENU_NODE_INFO, object_path=self.DBUS_SERVICE_PATH, - bus=session_bus + bus=session_bus, ) self.set_items(items) @@ -188,13 +204,13 @@ def set_items(self, items): @staticmethod def getItemsFlat(items, idToItems): for item in items: - if item.get('hidden', False): + if item.get("hidden", False): continue - idToItems[item['id']] = item + idToItems[item["id"]] = item - if 'children' in item: - idToItems = DBusMenuService.getItemsFlat(item['children'], idToItems) + if "children" in item: + idToItems = DBusMenuService.getItemsFlat(item["children"], idToItems) return idToItems @@ -202,27 +218,27 @@ def getItemsFlat(items, idToItems): def singleItemToDbus(item): props = DBusMenuService.itemPropsToDbus(item) - return (item['id'], props) + return (item["id"], props) @staticmethod def itemPropsToDbus(item): result = {} - string_props = ['label', 'icon-name', 'type', 'children-display'] + string_props = ["label", "icon-name", "type", "children-display"] for key in string_props: if key in item: - result[key] = GLib.Variant('s', item[key]) + result[key] = GLib.Variant("s", item[key]) - bool_props = ['enabled'] + bool_props = ["enabled"] for key in bool_props: if key in item: - result[key] = GLib.Variant('b', item[key]) + result[key] = GLib.Variant("b", item[key]) return result @staticmethod def itemToDbus(item, recursion_depth): - if item.get('hidden', False): + if item.get("hidden", False): return None props = DBusMenuService.itemPropsToDbus(item) @@ -230,20 +246,23 @@ def itemToDbus(item, recursion_depth): children = [] if recursion_depth > 1 or recursion_depth == -1: if "children" in item: - children = [DBusMenuService.itemToDbus(item, recursion_depth - 1) for item in item['children']] + children = [ + DBusMenuService.itemToDbus(item, recursion_depth - 1) + for item in item["children"] + ] children = [i for i in children if i is not None] - return GLib.Variant("(ia{sv}av)", (item['id'], props, children)) + return GLib.Variant("(ia{sv}av)", (item["id"], props, children)) def findItemsWithParent(self, parent_id, items): for item in items: - if item.get('hidden', False): + if item.get("hidden", False): continue - if 'children' in item: - if item['id'] == parent_id: - return item['children'] + if "children" in item: + if item["id"] == parent_id: + return item["children"] else: - ret = self.findItemsWithParent(parent_id, item['children']) + ret = self.findItemsWithParent(parent_id, item["children"]) if ret is not None: return ret return None @@ -263,11 +282,7 @@ def GetLayout(self, parent_id, recursion_depth, property_names): ret = ( self.revision, - ( - 0, - {'children-display': GLib.Variant('s', 'submenu')}, - children - ) + (0, {"children-display": GLib.Variant("s", "submenu")}, children), ) return ret @@ -299,13 +314,13 @@ def Event(self, idx, event_id, data, timestamp): if idx in self.idToItems: item = self.idToItems[idx] - if 'callback' in item: - item['callback']() + if "callback" in item: + item["callback"]() def EventGroup(self, events): not_found = [] - for (idx, event_id, data, timestamp) in events: + for idx, event_id, data, timestamp in events: if idx not in self.idToItems: not_found.append(idx) continue @@ -314,8 +329,8 @@ def EventGroup(self, events): continue item = self.idToItems[idx] - if 'callback' in item: - item['callback']() + if "callback" in item: + item["callback"]() return not_found @@ -333,22 +348,19 @@ def AboutToShowGroup(self, ids): return ([], not_found) def LayoutUpdated(self, revision, parent): - self.emit_signal( - 'LayoutUpdated', - (revision, parent) - ) + self.emit_signal("LayoutUpdated", (revision, parent)) class StatusNotifierItemService(DBusService): - DBUS_SERVICE_PATH = '/org/ayatana/NotificationItem/io_github_slgobinath_SafeEyes' - - Category = 'ApplicationStatus' - Id = 'io.github.slgobinath.SafeEyes' - Title = 'Safe Eyes' - Status = 'Active' - IconName = 'io.github.slgobinath.SafeEyes-enabled' - IconThemePath = '' - ToolTip = ('', [], 'Safe Eyes', '') + DBUS_SERVICE_PATH = "/org/ayatana/NotificationItem/io_github_slgobinath_SafeEyes" + + Category = "ApplicationStatus" + Id = "io.github.slgobinath.SafeEyes" + Title = "Safe Eyes" + Status = "Active" + IconName = "io.github.slgobinath.SafeEyes-enabled" + IconThemePath = "" + ToolTip = ("", [], "Safe Eyes", "") ItemIsMenu = True Menu = None @@ -356,7 +368,7 @@ def __init__(self, session_bus, context, menu_items): super().__init__( interface_info=SNI_NODE_INFO, object_path=self.DBUS_SERVICE_PATH, - bus=session_bus + bus=session_bus, ) self.bus = session_bus @@ -372,13 +384,13 @@ def register(self): connection=self.bus, flags=Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES, info=None, - name='org.kde.StatusNotifierWatcher', - object_path='/StatusNotifierWatcher', - interface_name='org.kde.StatusNotifierWatcher', + name="org.kde.StatusNotifierWatcher", + object_path="/StatusNotifierWatcher", + interface_name="org.kde.StatusNotifierWatcher", cancellable=None, ) - watcher.RegisterStatusNotifierItem('(s)', self.DBUS_SERVICE_PATH) + watcher.RegisterStatusNotifierItem("(s)", self.DBUS_SERVICE_PATH) def unregister(self): super().unregister() @@ -390,16 +402,12 @@ def set_items(self, items): def set_icon(self, icon): self.IconName = icon - self.emit_signal( - 'NewIcon' - ) + self.emit_signal("NewIcon") def set_tooltip(self, title, description): - self.ToolTip = ('', [], title, description) + self.ToolTip = ("", [], title, description) - self.emit_signal( - 'NewTooltip' - ) + self.emit_signal("NewTooltip") class TrayIcon: @@ -409,30 +417,28 @@ class TrayIcon: def __init__(self, context, plugin_config): self.context = context - self.on_show_settings = context['api']['show_settings'] - self.on_show_about = context['api']['show_about'] - self.quit = context['api']['quit'] - self.enable_safeeyes = context['api']['enable_safeeyes'] - self.disable_safeeyes = context['api']['disable_safeeyes'] - self.take_break = context['api']['take_break'] - self.has_breaks = context['api']['has_breaks'] - self.get_break_time = context['api']['get_break_time'] + self.on_show_settings = context["api"]["show_settings"] + self.on_show_about = context["api"]["show_about"] + self.quit = context["api"]["quit"] + self.enable_safeeyes = context["api"]["enable_safeeyes"] + self.disable_safeeyes = context["api"]["disable_safeeyes"] + self.take_break = context["api"]["take_break"] + self.has_breaks = context["api"]["has_breaks"] + self.get_break_time = context["api"]["get_break_time"] self.plugin_config = plugin_config self.date_time = None self.active = True self.wakeup_time = None self.idle_condition = threading.Condition() self.lock = threading.Lock() - self.allow_disabling = plugin_config['allow_disabling'] + self.allow_disabling = plugin_config["allow_disabling"] self.animate = False self.menu_locked = False session_bus = Gio.bus_get_sync(Gio.BusType.SESSION) self.sni_service = StatusNotifierItemService( - session_bus, - context, - menu_items=self.get_items() + session_bus, context, menu_items=self.get_items() ) self.sni_service.register() @@ -443,7 +449,7 @@ def initialize(self, plugin_config): Initialize the tray icon by setting the config. """ self.plugin_config = plugin_config - self.allow_disabling = plugin_config['allow_disabling'] + self.allow_disabling = plugin_config["allow_disabling"] self.update_menu() self.update_tooltip() @@ -451,7 +457,7 @@ def initialize(self, plugin_config): def get_items(self): breaks_found = self.has_breaks() - info_message = _('No Breaks Available') + info_message = _("No Breaks Available") if breaks_found: if self.active: @@ -462,126 +468,146 @@ def get_items(self): if next_long_time: if next_is_long: - info_message = _('Next long break at %s') % (next_long_time) + info_message = _("Next long break at %s") % (next_long_time) else: - info_message = _('Next breaks at %s/%s') % (next_time, next_long_time) + info_message = _("Next breaks at %s/%s") % ( + next_time, + next_long_time, + ) else: - info_message = _('Next break at %s') % (next_time) + info_message = _("Next break at %s") % (next_time) else: if self.wakeup_time: - info_message = _('Disabled until %s') % utility.format_time(self.wakeup_time) + info_message = _("Disabled until %s") % utility.format_time( + self.wakeup_time + ) else: - info_message = _('Disabled until restart') + info_message = _("Disabled until restart") disable_items = [] if self.allow_disabling: disable_option_dynamic_id = 13 - for disable_option in self.plugin_config['disable_options']: - time_in_minutes = time_in_x = disable_option['time'] + for disable_option in self.plugin_config["disable_options"]: + time_in_minutes = time_in_x = disable_option["time"] label = [] # Validate time value if not isinstance(time_in_minutes, int) or time_in_minutes <= 0: - logging.error('Invalid time in disable option: ' + str(time_in_minutes)) + logging.error( + "Invalid time in disable option: " + str(time_in_minutes) + ) continue - time_unit = disable_option['unit'].lower() - if time_unit == 'seconds' or time_unit == 'second': + time_unit = disable_option["unit"].lower() + if time_unit == "seconds" or time_unit == "second": time_in_minutes = int(time_in_minutes / 60) - label = ['For %d Second', 'For %d Seconds'] - elif time_unit == 'minutes' or time_unit == 'minute': + label = ["For %d Second", "For %d Seconds"] + elif time_unit == "minutes" or time_unit == "minute": time_in_minutes = int(time_in_minutes * 1) - label = ['For %d Minute', 'For %d Minutes'] - elif time_unit == 'hours' or time_unit == 'hour': + label = ["For %d Minute", "For %d Minutes"] + elif time_unit == "hours" or time_unit == "hour": time_in_minutes = int(time_in_minutes * 60) - label = ['For %d Hour', 'For %d Hours'] + label = ["For %d Hour", "For %d Hours"] else: # Invalid unit - logging.error('Invalid unit in disable option: ' + str(disable_option)) + logging.error( + "Invalid unit in disable option: " + str(disable_option) + ) continue - label = self.context['locale'].ngettext(label[0], label[1], time_in_x) % time_in_x + label = ( + self.context["locale"].ngettext(label[0], label[1], time_in_x) + % time_in_x + ) - disable_items.append({ - 'id': disable_option_dynamic_id, - 'label': label, - 'callback': lambda: self.on_disable_clicked(time_in_minutes), - }) + disable_items.append( + { + "id": disable_option_dynamic_id, + "label": label, + "callback": lambda: self.on_disable_clicked(time_in_minutes), + } + ) disable_option_dynamic_id += 1 - disable_items.append({ - 'id': 12, - 'label': _('Until restart'), - 'callback': lambda: self.on_disable_clicked(-1), - }) + disable_items.append( + { + "id": 12, + "label": _("Until restart"), + "callback": lambda: self.on_disable_clicked(-1), + } + ) return [ { - 'id': 1, - 'label': info_message, - 'icon-name': "io.github.slgobinath.SafeEyes-timer", - 'enabled': breaks_found and self.active, + "id": 1, + "label": info_message, + "icon-name": "io.github.slgobinath.SafeEyes-timer", + "enabled": breaks_found and self.active, }, { - 'id': 2, - 'type': "separator", + "id": 2, + "type": "separator", }, { - 'id': 3, - 'label': _("Enable Safe Eyes"), - 'enabled': breaks_found and not self.active, - 'callback': self.on_enable_clicked, - 'hidden': not self.allow_disabling, + "id": 3, + "label": _("Enable Safe Eyes"), + "enabled": breaks_found and not self.active, + "callback": self.on_enable_clicked, + "hidden": not self.allow_disabling, }, { - 'id': 4, - 'label': _("Disable Safe Eyes"), - 'enabled': breaks_found and self.active and not self.menu_locked, - 'children-display': 'submenu', - 'children': disable_items, - 'hidden': not self.allow_disabling, + "id": 4, + "label": _("Disable Safe Eyes"), + "enabled": breaks_found and self.active and not self.menu_locked, + "children-display": "submenu", + "children": disable_items, + "hidden": not self.allow_disabling, }, { - 'id': 5, - 'label': _('Take a break now'), - 'enabled': breaks_found and self.active and not self.menu_locked, - 'children-display': 'submenu', - 'children': [ + "id": 5, + "label": _("Take a break now"), + "enabled": breaks_found and self.active and not self.menu_locked, + "children-display": "submenu", + "children": [ { - 'id': 9, - 'label': _('Any break'), - 'callback': lambda: self.on_manual_break_clicked(None), + "id": 9, + "label": _("Any break"), + "callback": lambda: self.on_manual_break_clicked(None), }, { - 'id': 10, - 'label': _('Short break'), - 'callback': lambda: self.on_manual_break_clicked(BreakType.SHORT_BREAK), + "id": 10, + "label": _("Short break"), + "callback": lambda: self.on_manual_break_clicked( + BreakType.SHORT_BREAK + ), }, { - 'id': 11, - 'label': _('Long break'), - 'callback': lambda: self.on_manual_break_clicked(BreakType.LONG_BREAK), + "id": 11, + "label": _("Long break"), + "callback": lambda: self.on_manual_break_clicked( + BreakType.LONG_BREAK + ), }, - ] + ], }, { - 'id': 6, - 'label': _('Settings'), - 'enabled': not self.menu_locked, - 'callback': self.show_settings, + "id": 6, + "label": _("Settings"), + "enabled": not self.menu_locked, + "callback": self.show_settings, }, { - 'id': 7, - 'label': _('About'), - 'callback': self.show_about, + "id": 7, + "label": _("About"), + "callback": self.show_about, }, { - 'id': 8, - 'label': _('Quit'), - 'enabled': not self.menu_locked, - 'callback': self.quit_safe_eyes, - 'hidden': not self.allow_disabling, + "id": 8, + "label": _("Quit"), + "enabled": not self.menu_locked, + "callback": self.quit_safe_eyes, + "hidden": not self.allow_disabling, }, ] @@ -591,17 +617,21 @@ def update_menu(self): def update_tooltip(self): next_break = self.get_next_break_time() - if next_break is not None and self.plugin_config.get('show_time_in_tray', False): + if next_break is not None and self.plugin_config.get( + "show_time_in_tray", False + ): (next_time, next_long_time, _next_is_long) = next_break - if next_long_time and self.plugin_config.get('show_long_time_in_tray', False): + if next_long_time and self.plugin_config.get( + "show_long_time_in_tray", False + ): description = next_long_time else: description = next_time else: - description = '' + description = "" - self.sni_service.set_tooltip('Safe Eyes', description) + self.sni_service.set_tooltip("Safe Eyes", description) def quit_safe_eyes(self): """ @@ -684,12 +714,14 @@ def on_disable_clicked(self, time_to_wait): self.disable_ui() if time_to_wait <= 0: - info = _('Disabled until restart') + info = _("Disabled until restart") self.disable_safeeyes(info) self.wakeup_time = None else: - self.wakeup_time = datetime.datetime.now() + datetime.timedelta(minutes=time_to_wait) - info = _('Disabled until %s') % utility.format_time(self.wakeup_time) + self.wakeup_time = datetime.datetime.now() + datetime.timedelta( + minutes=time_to_wait + ) + info = _("Disabled until %s") % utility.format_time(self.wakeup_time) self.disable_safeeyes(info) utility.start_thread(self.__schedule_resume, time_minutes=time_to_wait) self.update_menu() @@ -715,7 +747,7 @@ def disable_ui(self): Change the UI to disabled state. """ if self.active: - logging.info('Disable Safe Eyes') + logging.info("Disable Safe Eyes") self.active = False self.sni_service.set_icon("io.github.slgobinath.SafeEyes-disabled") @@ -726,7 +758,7 @@ def enable_ui(self): Change the UI to enabled state. """ if not self.active: - logging.info('Enable Safe Eyes') + logging.info("Enable Safe Eyes") self.active = True self.sni_service.set_icon("io.github.slgobinath.SafeEyes-enabled") @@ -737,7 +769,7 @@ def __schedule_resume(self, time_minutes): Schedule a local timer to enable Safe Eyes after the given timeout. """ self.idle_condition.acquire() - self.idle_condition.wait(time_minutes * 60) # Convert to seconds + self.idle_condition.wait(time_minutes * 60) # Convert to seconds self.idle_condition.release() with self.lock: @@ -747,9 +779,13 @@ def __schedule_resume(self, time_minutes): def start_animation(self): if not self.active or not self.animate: return - utility.execute_main_thread(lambda: self.sni_service.set_icon("io.github.slgobinath.SafeEyes-disabled")) + utility.execute_main_thread( + lambda: self.sni_service.set_icon("io.github.slgobinath.SafeEyes-disabled") + ) time.sleep(0.5) - utility.execute_main_thread(lambda: self.sni_service.set_icon("io.github.slgobinath.SafeEyes-enabled")) + utility.execute_main_thread( + lambda: self.sni_service.set_icon("io.github.slgobinath.SafeEyes-enabled") + ) if self.animate and self.active: time.sleep(0.5) if self.animate and self.active: @@ -758,9 +794,17 @@ def start_animation(self): def stop_animation(self): self.animate = False if self.active: - utility.execute_main_thread(lambda: self.sni_service.set_icon("io.github.slgobinath.SafeEyes-enabled")) + utility.execute_main_thread( + lambda: self.sni_service.set_icon( + "io.github.slgobinath.SafeEyes-enabled" + ) + ) else: - utility.execute_main_thread(lambda: self.sni_service.set_icon("io.github.slgobinath.SafeEyes-disabled")) + utility.execute_main_thread( + lambda: self.sni_service.set_icon( + "io.github.slgobinath.SafeEyes-disabled" + ) + ) def init(ctx, safeeyes_cfg, plugin_config): @@ -770,7 +814,7 @@ def init(ctx, safeeyes_cfg, plugin_config): global context global tray_icon global safeeyes_config - logging.debug('Initialize Tray Icon plugin') + logging.debug("Initialize Tray Icon plugin") context = ctx safeeyes_config = safeeyes_cfg if not tray_icon: @@ -790,7 +834,7 @@ def on_pre_break(break_obj): """ Disable the menu if strict_break is enabled """ - if safeeyes_config.get('strict_break'): + if safeeyes_config.get("strict_break"): tray_icon.lock_menu() tray_icon.animate = True tray_icon.start_animation() diff --git a/safeeyes/rpc.py b/safeeyes/rpc.py index abe36295..d3a18e0c 100644 --- a/safeeyes/rpc.py +++ b/safeeyes/rpc.py @@ -30,17 +30,26 @@ class RPCServer: """ An asynchronous RPC server. """ + def __init__(self, port, context): self.__running = False - logging.info('Setting up an RPC server on port %d', port) - self.__server = SimpleXMLRPCServer(("localhost", port), logRequests=False, allow_none=True) - self.__server.register_function(context['api']['show_settings'], 'show_settings') - self.__server.register_function(context['api']['show_about'], 'show_about') - self.__server.register_function(context['api']['enable_safeeyes'], 'enable_safeeyes') - self.__server.register_function(context['api']['disable_safeeyes'], 'disable_safeeyes') - self.__server.register_function(context['api']['take_break'], 'take_break') - self.__server.register_function(context['api']['status'], 'status') - self.__server.register_function(context['api']['quit'], 'quit') + logging.info("Setting up an RPC server on port %d", port) + self.__server = SimpleXMLRPCServer( + ("localhost", port), logRequests=False, allow_none=True + ) + self.__server.register_function( + context["api"]["show_settings"], "show_settings" + ) + self.__server.register_function(context["api"]["show_about"], "show_about") + self.__server.register_function( + context["api"]["enable_safeeyes"], "enable_safeeyes" + ) + self.__server.register_function( + context["api"]["disable_safeeyes"], "disable_safeeyes" + ) + self.__server.register_function(context["api"]["take_break"], "take_break") + self.__server.register_function(context["api"]["status"], "status") + self.__server.register_function(context["api"]["quit"], "quit") def start(self): """ @@ -48,7 +57,7 @@ def start(self): """ if not self.__running: self.__running = True - logging.info('Start the RPC server') + logging.info("Start the RPC server") server_thread = Thread(target=self.__server.serve_forever) server_thread.start() @@ -57,7 +66,7 @@ def stop(self): Stop the server. """ if self.__running: - logging.info('Stop the RPC server') + logging.info("Stop the RPC server") self.__running = False self.__server.shutdown() @@ -66,9 +75,10 @@ class RPCClient: """ An RPC client to communicate with the RPC server. """ + def __init__(self, port): self.port = port - self.proxy = ServerProxy('http://localhost:%d/' % self.port, allow_none=True) + self.proxy = ServerProxy("http://localhost:%d/" % self.port, allow_none=True) def show_settings(self): """ diff --git a/safeeyes/safeeyes.py b/safeeyes/safeeyes.py index 4bb3fde9..008b6692 100644 --- a/safeeyes/safeeyes.py +++ b/safeeyes/safeeyes.py @@ -35,7 +35,7 @@ from safeeyes.core import SafeEyesCore from safeeyes.ui.settings_dialog import SettingsDialog -gi.require_version('Gtk', '3.0') +gi.require_version("Gtk", "3.0") from gi.repository import Gtk, Gio SAFE_EYES_VERSION = "2.2.1" @@ -51,7 +51,7 @@ class SafeEyes(Gtk.Application): def __init__(self, system_locale, config, cli_args): super().__init__( application_id="io.github.slgobinath.SafeEyes", - flags=Gio.ApplicationFlags.IS_SERVICE + flags=Gio.ApplicationFlags.IS_SERVICE, ) self.active = False self.break_screen = None @@ -61,33 +61,41 @@ def __init__(self, system_locale, config, cli_args): self.plugins_manager = None self.settings_dialog_active = False self.rpc_server = None - self._status = '' + self._status = "" self.cli_args = cli_args # Initialize the Safe Eyes Context - self.context['version'] = SAFE_EYES_VERSION - self.context['desktop'] = utility.desktop_environment() - self.context['is_wayland'] = utility.is_wayland() - self.context['locale'] = system_locale - self.context['api'] = {} - self.context['api']['show_settings'] = lambda: utility.execute_main_thread( - self.show_settings) - self.context['api']['show_about'] = lambda: utility.execute_main_thread( - self.show_about) - self.context['api']['enable_safeeyes'] = lambda next_break_time=-1, reset_breaks=False: \ - utility.execute_main_thread(self.enable_safeeyes, next_break_time, reset_breaks) - self.context['api']['disable_safeeyes'] = lambda status=None, is_resting=False: utility.execute_main_thread( - self.disable_safeeyes, status, is_resting) - self.context['api']['status'] = self.status - self.context['api']['quit'] = lambda: utility.execute_main_thread( - self.quit) - if self.config.get('persist_state'): - self.context['session'] = utility.open_session() + self.context["version"] = SAFE_EYES_VERSION + self.context["desktop"] = utility.desktop_environment() + self.context["is_wayland"] = utility.is_wayland() + self.context["locale"] = system_locale + self.context["api"] = {} + self.context["api"]["show_settings"] = lambda: utility.execute_main_thread( + self.show_settings + ) + self.context["api"]["show_about"] = lambda: utility.execute_main_thread( + self.show_about + ) + self.context["api"]["enable_safeeyes"] = ( + lambda next_break_time=-1, reset_breaks=False: utility.execute_main_thread( + self.enable_safeeyes, next_break_time, reset_breaks + ) + ) + self.context["api"]["disable_safeeyes"] = ( + lambda status=None, is_resting=False: utility.execute_main_thread( + self.disable_safeeyes, status, is_resting + ) + ) + self.context["api"]["status"] = self.status + self.context["api"]["quit"] = lambda: utility.execute_main_thread(self.quit) + if self.config.get("persist_state"): + self.context["session"] = utility.open_session() else: - self.context['session'] = {'plugin': {}} + self.context["session"] = {"plugin": {}} self.break_screen = BreakScreen( - self.context, self.on_skipped, self.on_postponed, utility.STYLE_SHEET_PATH) + self.context, self.on_skipped, self.on_postponed, utility.STYLE_SHEET_PATH + ) self.break_screen.initialize(self.config) self.plugins_manager = PluginManager() self.safe_eyes_core = SafeEyesCore(self.context) @@ -98,15 +106,17 @@ def __init__(self, system_locale, config, cli_args): 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'] = self.take_break - self.context['api']['has_breaks'] = self.safe_eyes_core.has_breaks - self.context['api']['postpone'] = self.safe_eyes_core.postpone - self.context['api']['get_break_time'] = self.safe_eyes_core.get_break_time + 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.context["api"]["get_break_time"] = self.safe_eyes_core.get_break_time try: self.plugins_manager.init(self.context, self.config) except RequiredPluginException as e: - self.show_required_plugin_dialog(e.get_plugin_id(), e.get_plugin_name(), e.get_message()) + self.show_required_plugin_dialog( + e.get_plugin_id(), e.get_plugin_name(), e.get_message() + ) self.required_plugin_dialog_active = True self.hold() @@ -117,13 +127,13 @@ def start(self): """ Start Safe Eyes """ - if self.config.get('use_rpc_server', True): + if self.config.get("use_rpc_server", True): self.__start_rpc_server() if not self.required_plugin_dialog_active and self.safe_eyes_core.has_breaks(): self.active = True - self.context['state'] = State.START - self.plugins_manager.start() # Call the start method of all plugins + self.context["state"] = State.START + self.plugins_manager.start() # Call the start method of all plugins self.safe_eyes_core.start() self.handle_system_suspend() @@ -150,8 +160,7 @@ def show_settings(self): if not self.settings_dialog_active: logging.info("Show Settings dialog") self.settings_dialog_active = True - settings_dialog = SettingsDialog( - self.config.clone(), self.save_settings) + settings_dialog = SettingsDialog(self.config.clone(), self.save_settings) settings_dialog.show() def show_required_plugin_dialog(self, plugin_id, plugin_name, message): @@ -161,7 +170,7 @@ def show_required_plugin_dialog(self, plugin_id, plugin_name, message): plugin_name, message, self.quit, - lambda: self.disable_plugin(plugin_id) + lambda: self.disable_plugin(plugin_id), ) dialog.show() @@ -171,9 +180,9 @@ def disable_plugin(self, plugin_id): """ config = self.config.clone() - for plugin in config.get('plugins'): - if plugin['id'] == plugin_id: - plugin['enabled'] = False + for plugin in config.get("plugins"): + if plugin["id"] == plugin_id: + plugin["enabled"] = False self.required_plugin_dialog_active = False @@ -192,7 +201,7 @@ def quit(self): Listen to the tray menu quit action and stop the core, notification and the app itself. """ logging.info("Quit Safe Eyes") - self.context['state'] = State.QUIT + self.context["state"] = State.QUIT self.plugins_manager.stop() self.safe_eyes_core.stop() self.plugins_manager.exit() @@ -223,7 +232,7 @@ def handle_suspend_signal(self, proxy, sender, signal, parameters): if signal != "PrepareForSleep": return - (sleeping, ) = parameters + (sleeping,) = parameters self.handle_suspend_callback(sleeping) @@ -235,12 +244,12 @@ def handle_system_suspend(self): bus_type=Gio.BusType.SYSTEM, flags=Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES, info=None, - name='org.freedesktop.login1', - object_path='/org/freedesktop/login1', - interface_name='org.freedesktop.login1.Manager', + name="org.freedesktop.login1", + object_path="/org/freedesktop/login1", + interface_name="org.freedesktop.login1.Manager", cancellable=None, ) - self.suspend_proxy.connect('g-signal', self.handle_suspend_signal) + self.suspend_proxy.connect("g-signal", self.handle_suspend_signal) def on_skipped(self): """ @@ -283,10 +292,10 @@ def save_settings(self, config): def restart(self, config, set_active=False): logging.info("Initialize SafeEyesCore with modified settings") - if self.rpc_server is None and config.get('use_rpc_server'): + if self.rpc_server is None and config.get("use_rpc_server"): # RPC server wasn't running but now enabled self.__start_rpc_server() - elif self.rpc_server is not None and not config.get('use_rpc_server'): + elif self.rpc_server is not None and not config.get("use_rpc_server"): # RPC server was running but now disabled self.__stop_rpc_server() @@ -298,7 +307,9 @@ def restart(self, config, set_active=False): try: self.plugins_manager.init(self.context, self.config) except RequiredPluginException as e: - self.show_required_plugin_dialog(e.get_plugin_id(), e.get_plugin_name(), e.get_message()) + self.show_required_plugin_dialog( + e.get_plugin_id(), e.get_plugin_name(), e.get_message() + ) self.required_plugin_dialog_active = True return @@ -314,7 +325,11 @@ def enable_safeeyes(self, scheduled_next_break_time=-1, reset_breaks=False): """ Listen to tray icon enable action and send the signal to core. """ - if not self.required_plugin_dialog_active and not self.active and self.safe_eyes_core.has_breaks(): + if ( + not self.required_plugin_dialog_active + and not self.active + and self.safe_eyes_core.has_breaks() + ): self.active = True self.safe_eyes_core.start(scheduled_next_break_time, reset_breaks) self.plugins_manager.start() @@ -328,7 +343,7 @@ def disable_safeeyes(self, status=None, is_resting=False): self.plugins_manager.stop() self.safe_eyes_core.stop(is_resting) if status is None: - status = _('Disabled until restart') + status = _("Disabled until restart") self._status = status def on_start_break(self, break_obj): @@ -361,11 +376,9 @@ def update_next_break(self, break_obj, break_time): Update the next break to plugins and save the session. """ self.plugins_manager.update_next_break(break_obj, break_time) - self._status = _('Next break at %s') % ( - utility.format_time(break_time)) - if self.config.get('persist_state'): - utility.write_json(utility.SESSION_FILE_PATH, - self.context['session']) + self._status = _("Next break at %s") % (utility.format_time(break_time)) + if self.config.get("persist_state"): + utility.write_json(utility.SESSION_FILE_PATH, self.context["session"]) def stop_break(self): """ @@ -391,15 +404,14 @@ def persist_session(self): """ Save the session object to the session file. """ - if self.config.get('persist_state'): - utility.write_json(utility.SESSION_FILE_PATH, - self.context['session']) + if self.config.get("persist_state"): + utility.write_json(utility.SESSION_FILE_PATH, self.context["session"]) else: utility.delete(utility.SESSION_FILE_PATH) def __start_rpc_server(self): if self.rpc_server is None: - self.rpc_server = RPCServer(self.config.get('rpc_port'), self.context) + self.rpc_server = RPCServer(self.config.get("rpc_port"), self.context) self.rpc_server.start() def __stop_rpc_server(self): diff --git a/safeeyes/ui/about_dialog.py b/safeeyes/ui/about_dialog.py index 1fd1b593..d607dc32 100644 --- a/safeeyes/ui/about_dialog.py +++ b/safeeyes/ui/about_dialog.py @@ -36,14 +36,16 @@ class AboutDialog: def __init__(self, version): builder = utility.create_gtk_builder(ABOUT_DIALOG_GLADE) builder.connect_signals(self) - self.window = builder.get_object('window_about') - builder.get_object('lbl_decription').set_label( - _("Safe Eyes protects your eyes from eye strain (asthenopia) by reminding you to take breaks while you're working long hours at the computer") # noqa: E501 + self.window = builder.get_object("window_about") + builder.get_object("lbl_decription").set_label( + _( + "Safe Eyes protects your eyes from eye strain (asthenopia) by reminding you to take breaks while you're working long hours at the computer" # noqa: E501 + ) ) - builder.get_object('lbl_license').set_label(_('License') + ':') + builder.get_object("lbl_license").set_label(_("License") + ":") # Set the version at the runtime - builder.get_object('lbl_app_name').set_label('Safe Eyes ' + version) + builder.get_object("lbl_app_name").set_label("Safe Eyes " + version) def show(self): """ diff --git a/safeeyes/ui/break_screen.py b/safeeyes/ui/break_screen.py index 38b67006..8219c155 100644 --- a/safeeyes/ui/break_screen.py +++ b/safeeyes/ui/break_screen.py @@ -26,7 +26,7 @@ from Xlib.display import Display from Xlib.display import X -gi.require_version('Gtk', '3.0') +gi.require_version("Gtk", "3.0") from gi.repository import Gdk from gi.repository import GLib from gi.repository import Gtk @@ -61,7 +61,7 @@ def __init__(self, context, on_skipped, on_postponed, style_sheet_path): Gtk.StyleContext.add_provider_for_screen( Gdk.Screen.get_default(), css_provider, - Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION, ) def initialize(self, config): @@ -69,11 +69,11 @@ def initialize(self, config): Initialize the internal properties from configuration """ logging.info("Initialize the break screen") - self.enable_postpone = config.get('allow_postpone', False) - self.keycode_shortcut_postpone = config.get('shortcut_postpone', 65) - self.keycode_shortcut_skip = config.get('shortcut_skip', 9) - self.shortcut_disable_time = config.get('shortcut_disable_time', 2) - self.strict_break = config.get('strict_break', False) + self.enable_postpone = config.get("allow_postpone", False) + self.keycode_shortcut_postpone = config.get("shortcut_postpone", 65) + self.keycode_shortcut_skip = config.get("shortcut_skip", 9) + self.shortcut_disable_time = config.get("shortcut_disable_time", 2) + self.strict_break = config.get("strict_break", False) def skip_break(self): """ @@ -117,7 +117,7 @@ def show_count_down(self, countdown, seconds): """ self.enable_shortcut = self.shortcut_disable_time <= seconds mins, secs = divmod(countdown, 60) - timeformat = '{:02d}:{:02d}'.format(mins, secs) + timeformat = "{:02d}:{:02d}".format(mins, secs) GLib.idle_add(lambda: self.__update_count_down(timeformat)) def show_message(self, break_obj, widget, tray_actions=[]): @@ -127,7 +127,9 @@ def show_message(self, break_obj, widget, tray_actions=[]): message = break_obj.name image_path = break_obj.image self.enable_shortcut = self.shortcut_disable_time <= 0 - GLib.idle_add(lambda: self.__show_break_screen(message, image_path, widget, tray_actions)) + GLib.idle_add( + lambda: self.__show_break_screen(message, image_path, widget, tray_actions) + ) def close(self): """ @@ -159,8 +161,8 @@ def __show_break_screen(self, message, image_path, widget, tray_actions): no_of_monitors = display.get_n_monitors() logging.info("Show break screens in %d display(s)", no_of_monitors) - skip_button_disabled = self.context.get('skip_button_disabled', False) - postpone_button_disabled = self.context.get('postpone_button_disabled', False) + skip_button_disabled = self.context.get("skip_button_disabled", False) + postpone_button_disabled = self.context.get("postpone_button_disabled", False) for monitor_num in range(no_of_monitors): monitor = display.get_monitor(monitor_num) @@ -184,14 +186,18 @@ def __show_break_screen(self, message, image_path, widget, tray_actions): for tray_action in tray_actions: toolbar_button = None if tray_action.system_icon: - toolbar_button = Gtk.ToolButton.new_from_stock(tray_action.get_icon()) + toolbar_button = Gtk.ToolButton.new_from_stock( + tray_action.get_icon() + ) else: - toolbar_button = Gtk.ToolButton.new(tray_action.get_icon(), tray_action.name) + toolbar_button = Gtk.ToolButton.new( + tray_action.get_icon(), tray_action.name + ) tray_action.add_toolbar_button(toolbar_button) toolbar_button.connect( "clicked", lambda button, action: self.__tray_action(button, action), - tray_action + tray_action, ) toolbar_button.set_tooltip_text(_(tray_action.name)) toolbar.add(toolbar_button) @@ -200,17 +206,17 @@ def __show_break_screen(self, message, image_path, widget, tray_actions): # Add the buttons if self.enable_postpone and not postpone_button_disabled: # Add postpone button - btn_postpone = Gtk.Button.new_with_label(_('Postpone')) - btn_postpone.get_style_context().add_class('btn_postpone') - btn_postpone.connect('clicked', self.on_postpone_clicked) + btn_postpone = Gtk.Button.new_with_label(_("Postpone")) + btn_postpone.get_style_context().add_class("btn_postpone") + btn_postpone.connect("clicked", self.on_postpone_clicked) btn_postpone.set_visible(True) box_buttons.pack_start(btn_postpone, True, True, 0) if not self.strict_break and not skip_button_disabled: # Add the skip button - btn_skip = Gtk.Button.new_with_label(_('Skip')) - btn_skip.get_style_context().add_class('btn_skip') - btn_skip.connect('clicked', self.on_skip_clicked) + btn_skip = Gtk.Button.new_with_label(_("Skip")) + btn_skip.get_style_context().add_class("btn_skip") + btn_skip.connect("clicked", self.on_skip_clicked) btn_skip.set_visible(True) box_buttons.pack_start(btn_skip, True, True, 0) @@ -225,7 +231,7 @@ def __show_break_screen(self, message, image_path, widget, tray_actions): # Set visual to apply css theme. It should be called before show method. window.set_visual(window.get_screen().get_rgba_visual()) - if self.context['desktop'] == 'kde': + if self.context["desktop"] == "kde": # Fix flickering screen in KDE by setting opacity to 1 window.set_opacity(0.9) @@ -266,10 +272,16 @@ def __lock_keyboard(self): # Avoid waiting for next event by checking pending events event = self.display.next_event() if self.enable_shortcut and event.type == X.KeyPress: - if event.detail == self.keycode_shortcut_skip and not self.strict_break: + if ( + event.detail == self.keycode_shortcut_skip + and not self.strict_break + ): self.skip_break() break - elif self.enable_postpone and event.detail == self.keycode_shortcut_postpone: + elif ( + self.enable_postpone + and event.detail == self.keycode_shortcut_postpone + ): self.postpone_break() break else: diff --git a/safeeyes/ui/required_plugin_dialog.py b/safeeyes/ui/required_plugin_dialog.py index 779f57e4..66b3b7fe 100644 --- a/safeeyes/ui/required_plugin_dialog.py +++ b/safeeyes/ui/required_plugin_dialog.py @@ -25,7 +25,9 @@ from safeeyes import utility from safeeyes.model import PluginDependency -REQUIRED_PLUGIN_DIALOG_GLADE = os.path.join(utility.BIN_DIRECTORY, "glade/required_plugin_dialog.glade") +REQUIRED_PLUGIN_DIALOG_GLADE = os.path.join( + utility.BIN_DIRECTORY, "glade/required_plugin_dialog.glade" +) class RequiredPluginDialog: @@ -38,31 +40,37 @@ def __init__(self, plugin_id, plugin_name, message, on_quit, on_disable_plugin): self.on_disable_plugin = on_disable_plugin builder = utility.create_gtk_builder(REQUIRED_PLUGIN_DIALOG_GLADE) - self.window = builder.get_object('window_required_plugin') + self.window = builder.get_object("window_required_plugin") self.window.connect("delete-event", self.on_window_delete) - builder.get_object('btn_close').connect('clicked', self.on_close_clicked) - builder.get_object('btn_disable_plugin').connect('clicked', self.on_disable_plugin_clicked) + builder.get_object("btn_close").connect("clicked", self.on_close_clicked) + builder.get_object("btn_disable_plugin").connect( + "clicked", self.on_disable_plugin_clicked + ) - builder.get_object('lbl_header').set_label( + builder.get_object("lbl_header").set_label( _("The required plugin '%s' is missing dependencies!") % _(plugin_name) ) - builder.get_object('lbl_main').set_label( - _("Please install the dependencies or disable the plugin. To hide this message, you can also deactivate the plugin in the settings.") # noqa: E501 + builder.get_object("lbl_main").set_label( + _( + "Please install the dependencies or disable the plugin. To hide this message, you can also deactivate the plugin in the settings." # noqa: E501 + ) ) - builder.get_object('btn_close').set_label(_("Quit")) - builder.get_object('btn_disable_plugin').set_label(_("Disable plugin temporarily")) + builder.get_object("btn_close").set_label(_("Quit")) + builder.get_object("btn_disable_plugin").set_label( + _("Disable plugin temporarily") + ) if isinstance(message, PluginDependency): - builder.get_object('lbl_message').set_label(_(message.message)) - btn_extra_link = builder.get_object('btn_extra_link') + builder.get_object("lbl_message").set_label(_(message.message)) + btn_extra_link = builder.get_object("btn_extra_link") btn_extra_link.set_label(_("Click here for more information")) btn_extra_link.set_uri(message.link) btn_extra_link.set_visible(True) else: - builder.get_object('lbl_message').set_label(_(message)) + builder.get_object("lbl_message").set_label(_(message)) def show(self): """ diff --git a/safeeyes/ui/settings_dialog.py b/safeeyes/ui/settings_dialog.py index b3956346..48064c92 100644 --- a/safeeyes/ui/settings_dialog.py +++ b/safeeyes/ui/settings_dialog.py @@ -23,17 +23,29 @@ from safeeyes import utility from safeeyes.model import Config, PluginDependency -gi.require_version('Gtk', '3.0') +gi.require_version("Gtk", "3.0") from gi.repository import Gtk from gi.repository import GdkPixbuf -SETTINGS_DIALOG_GLADE = os.path.join(utility.BIN_DIRECTORY, "glade/settings_dialog.glade") -SETTINGS_DIALOG_PLUGIN_GLADE = os.path.join(utility.BIN_DIRECTORY, "glade/settings_plugin.glade") -SETTINGS_DIALOG_BREAK_GLADE = os.path.join(utility.BIN_DIRECTORY, "glade/settings_break.glade") -SETTINGS_DIALOG_NEW_BREAK_GLADE = os.path.join(utility.BIN_DIRECTORY, "glade/new_break.glade") -SETTINGS_BREAK_ITEM_GLADE = os.path.join(utility.BIN_DIRECTORY, "glade/item_break.glade") -SETTINGS_PLUGIN_ITEM_GLADE = os.path.join(utility.BIN_DIRECTORY, "glade/item_plugin.glade") +SETTINGS_DIALOG_GLADE = os.path.join( + utility.BIN_DIRECTORY, "glade/settings_dialog.glade" +) +SETTINGS_DIALOG_PLUGIN_GLADE = os.path.join( + utility.BIN_DIRECTORY, "glade/settings_plugin.glade" +) +SETTINGS_DIALOG_BREAK_GLADE = os.path.join( + utility.BIN_DIRECTORY, "glade/settings_break.glade" +) +SETTINGS_DIALOG_NEW_BREAK_GLADE = os.path.join( + utility.BIN_DIRECTORY, "glade/new_break.glade" +) +SETTINGS_BREAK_ITEM_GLADE = os.path.join( + utility.BIN_DIRECTORY, "glade/item_break.glade" +) +SETTINGS_PLUGIN_ITEM_GLADE = os.path.join( + utility.BIN_DIRECTORY, "glade/item_plugin.glade" +) SETTINGS_ITEM_INT_GLADE = os.path.join(utility.BIN_DIRECTORY, "glade/item_int.glade") SETTINGS_ITEM_TEXT_GLADE = os.path.join(utility.BIN_DIRECTORY, "glade/item_text.glade") SETTINGS_ITEM_BOOL_GLADE = os.path.join(utility.BIN_DIRECTORY, "glade/item_bool.glade") @@ -41,7 +53,7 @@ class SettingsDialog: """ - Create and initialize SettingsDialog instance. + Create and initialize SettingsDialog instance. """ def __init__(self, config, on_save_settings): @@ -49,7 +61,7 @@ def __init__(self, config, on_save_settings): self.on_save_settings = on_save_settings self.plugin_switches = {} self.plugin_map = {} - self.last_short_break_interval = config.get('short_break_interval') + self.last_short_break_interval = config.get("short_break_interval") self.initializing = True self.infobar_long_break_shown = False self.warn_bar_rpc_server_shown = False @@ -57,24 +69,26 @@ def __init__(self, config, on_save_settings): builder = utility.create_gtk_builder(SETTINGS_DIALOG_GLADE) builder.connect_signals(self) - self.window = builder.get_object('window_settings') - self.box_short_breaks = builder.get_object('box_short_breaks') - self.box_long_breaks = builder.get_object('box_long_breaks') - self.box_plugins = builder.get_object('box_plugins') - self.popover = builder.get_object('popover') - - self.spin_short_break_duration = builder.get_object('spin_short_break_duration') - self.spin_long_break_duration = builder.get_object('spin_long_break_duration') - self.spin_short_break_interval = builder.get_object('spin_short_break_interval') - self.spin_long_break_interval = builder.get_object('spin_long_break_interval') - self.spin_time_to_prepare = builder.get_object('spin_time_to_prepare') - self.spin_postpone_duration = builder.get_object('spin_postpone_duration') - self.spin_disable_keyboard_shortcut = builder.get_object('spin_disable_keyboard_shortcut') - self.switch_strict_break = builder.get_object('switch_strict_break') - self.switch_random_order = builder.get_object('switch_random_order') - self.switch_postpone = builder.get_object('switch_postpone') - self.switch_persist = builder.get_object('switch_persist') - self.switch_rpc_server = builder.get_object('switch_rpc_server') + self.window = builder.get_object("window_settings") + self.box_short_breaks = builder.get_object("box_short_breaks") + self.box_long_breaks = builder.get_object("box_long_breaks") + self.box_plugins = builder.get_object("box_plugins") + self.popover = builder.get_object("popover") + + self.spin_short_break_duration = builder.get_object("spin_short_break_duration") + self.spin_long_break_duration = builder.get_object("spin_long_break_duration") + self.spin_short_break_interval = builder.get_object("spin_short_break_interval") + self.spin_long_break_interval = builder.get_object("spin_long_break_interval") + self.spin_time_to_prepare = builder.get_object("spin_time_to_prepare") + self.spin_postpone_duration = builder.get_object("spin_postpone_duration") + self.spin_disable_keyboard_shortcut = builder.get_object( + "spin_disable_keyboard_shortcut" + ) + self.switch_strict_break = builder.get_object("switch_strict_break") + self.switch_random_order = builder.get_object("switch_random_order") + self.switch_postpone = builder.get_object("switch_postpone") + self.switch_persist = builder.get_object("switch_persist") + self.switch_rpc_server = builder.get_object("switch_rpc_server") self.info_bar_long_break = builder.get_object("info_bar_long_break") self.warn_bar_rpc_server = builder.get_object("warn_bar_rpc_server") self.info_bar_long_break.hide() @@ -87,36 +101,46 @@ def __init__(self, config, on_save_settings): # GtkSwitch state-set signal is available only from 3.14 if Gtk.get_minor_version() >= 14: # Add event listener to postpone switch - self.switch_postpone.connect('state-set', self.on_switch_postpone_activate) - self.on_switch_postpone_activate(self.switch_postpone, self.switch_postpone.get_active()) + self.switch_postpone.connect("state-set", self.on_switch_postpone_activate) + self.on_switch_postpone_activate( + self.switch_postpone, self.switch_postpone.get_active() + ) # Add event listener to RPC server switch - self.switch_rpc_server.connect('state-set', self.on_switch_rpc_server_activate) - self.on_switch_rpc_server_activate(self.switch_rpc_server, self.switch_rpc_server.get_active()) + self.switch_rpc_server.connect( + "state-set", self.on_switch_rpc_server_activate + ) + self.on_switch_rpc_server_activate( + self.switch_rpc_server, self.switch_rpc_server.get_active() + ) self.initializing = False def __initialize(self, config): # Don't show infobar for changes made internally self.infobar_long_break_shown = True - for short_break in config.get('short_breaks'): + for short_break in config.get("short_breaks"): self.__create_break_item(short_break, True) - for long_break in config.get('long_breaks'): + for long_break in config.get("long_breaks"): self.__create_break_item(long_break, False) for plugin_config in utility.load_plugins_config(config): - self.box_plugins.pack_start(self.__create_plugin_item(plugin_config), False, False, 0) - - self.spin_short_break_duration.set_value(config.get('short_break_duration')) - self.spin_long_break_duration.set_value(config.get('long_break_duration')) - self.spin_short_break_interval.set_value(config.get('short_break_interval')) - self.spin_long_break_interval.set_value(config.get('long_break_interval')) - self.spin_time_to_prepare.set_value(config.get('pre_break_warning_time')) - self.spin_postpone_duration.set_value(config.get('postpone_duration')) - self.spin_disable_keyboard_shortcut.set_value(config.get('shortcut_disable_time')) - self.switch_strict_break.set_active(config.get('strict_break')) - self.switch_random_order.set_active(config.get('random_order')) - self.switch_postpone.set_active(config.get('allow_postpone')) - self.switch_persist.set_active(config.get('persist_state')) - self.switch_rpc_server.set_active(config.get('use_rpc_server')) + self.box_plugins.pack_start( + self.__create_plugin_item(plugin_config), False, False, 0 + ) + + self.spin_short_break_duration.set_value(config.get("short_break_duration")) + self.spin_long_break_duration.set_value(config.get("long_break_duration")) + self.spin_short_break_interval.set_value(config.get("short_break_interval")) + self.spin_long_break_interval.set_value(config.get("long_break_interval")) + self.spin_time_to_prepare.set_value(config.get("pre_break_warning_time")) + self.spin_postpone_duration.set_value(config.get("postpone_duration")) + self.spin_disable_keyboard_shortcut.set_value( + config.get("shortcut_disable_time") + ) + self.switch_strict_break.set_active(config.get("strict_break")) + self.switch_random_order.set_active(config.get("random_order")) + self.switch_postpone.set_active(config.get("allow_postpone")) + self.switch_persist.set_active(config.get("persist_state")) + self.switch_rpc_server.set_active(config.get("use_rpc_server")) self.infobar_long_break_shown = False def __create_break_item(self, break_config, is_short): @@ -127,29 +151,31 @@ def __create_break_item(self, break_config, is_short): if is_short: parent_box = self.box_short_breaks builder = utility.create_gtk_builder(SETTINGS_BREAK_ITEM_GLADE) - box = builder.get_object('box') - lbl_name = builder.get_object('lbl_name') - lbl_name.set_label(_(break_config['name'])) - btn_properties = builder.get_object('btn_properties') + box = builder.get_object("box") + lbl_name = builder.get_object("lbl_name") + lbl_name.set_label(_(break_config["name"])) + btn_properties = builder.get_object("btn_properties") btn_properties.connect( - 'clicked', + "clicked", lambda button: self.__show_break_properties_dialog( break_config, is_short, self.config, - lambda cfg: lbl_name.set_label(_(cfg['name'])), - lambda is_short, break_config: self.__create_break_item(break_config, is_short), - lambda: parent_box.remove(box) - ) + lambda cfg: lbl_name.set_label(_(cfg["name"])), + lambda is_short, break_config: self.__create_break_item( + break_config, is_short + ), + lambda: parent_box.remove(box), + ), ) - btn_delete = builder.get_object('btn_delete') + btn_delete = builder.get_object("btn_delete") btn_delete.connect( - 'clicked', + "clicked", lambda button: self.__delete_break( break_config, is_short, lambda: parent_box.remove(box), - ) + ), ) box.set_visible(True) parent_box.pack_start(box, False, False, 0) @@ -163,10 +189,16 @@ def __confirmation_dialog_response(widget, response_id): utility.reset_config() self.config = Config() # Remove breaks from the container - self.box_short_breaks.foreach(lambda element: self.box_short_breaks.remove(element)) - self.box_long_breaks.foreach(lambda element: self.box_long_breaks.remove(element)) + self.box_short_breaks.foreach( + lambda element: self.box_short_breaks.remove(element) + ) + self.box_long_breaks.foreach( + lambda element: self.box_long_breaks.remove(element) + ) # Remove plugins from the container - self.box_plugins.foreach(lambda element: self.box_plugins.remove(element)) + self.box_plugins.foreach( + lambda element: self.box_plugins.remove(element) + ) # Initialize again self.__initialize(self.config) widget.destroy() @@ -174,10 +206,12 @@ def __confirmation_dialog_response(widget, response_id): messagedialog = Gtk.MessageDialog() messagedialog.set_modal(True) messagedialog.set_transient_for(self.window) - messagedialog.set_property('message_type', Gtk.MessageType.WARNING) - messagedialog.set_property('text', _("Are you sure you want to reset all settings to default?")) - messagedialog.set_property('secondary-text', _("You can't undo this action.")) - messagedialog.add_button('_Cancel', Gtk.ResponseType.CANCEL) + messagedialog.set_property("message_type", Gtk.MessageType.WARNING) + messagedialog.set_property( + "text", _("Are you sure you want to reset all settings to default?") + ) + messagedialog.set_property("secondary-text", _("You can't undo this action.")) + messagedialog.add_button("_Cancel", Gtk.ResponseType.CANCEL) messagedialog.add_button(_("Reset"), Gtk.ResponseType.OK) messagedialog.connect("response", __confirmation_dialog_response) @@ -191,19 +225,21 @@ def __delete_break(self, break_config, is_short, on_remove): def __confirmation_dialog_response(widget, response_id): if response_id == Gtk.ResponseType.OK: if is_short: - self.config.get('short_breaks').remove(break_config) + self.config.get("short_breaks").remove(break_config) else: - self.config.get('long_breaks').remove(break_config) + self.config.get("long_breaks").remove(break_config) on_remove() widget.destroy() messagedialog = Gtk.MessageDialog() messagedialog.set_modal(True) messagedialog.set_transient_for(self.window) - messagedialog.set_property('message_type', Gtk.MessageType.WARNING) - messagedialog.set_property('text', _("Are you sure you want to delete this break?")) - messagedialog.set_property('secondary-text', _("You can't undo this action.")) - messagedialog.add_button('_Cancel', Gtk.ResponseType.CANCEL) + messagedialog.set_property("message_type", Gtk.MessageType.WARNING) + messagedialog.set_property( + "text", _("Are you sure you want to delete this break?") + ) + messagedialog.set_property("secondary-text", _("You can't undo this action.")) + messagedialog.add_button("_Cancel", Gtk.ResponseType.CANCEL) messagedialog.add_button(_("Delete"), Gtk.ResponseType.OK) messagedialog.connect("response", __confirmation_dialog_response) @@ -214,17 +250,17 @@ def __create_plugin_item(self, plugin_config): Create an entry for plugin to be listed in the plugin tab. """ builder = utility.create_gtk_builder(SETTINGS_PLUGIN_ITEM_GLADE) - lbl_plugin_name = builder.get_object('lbl_plugin_name') - lbl_plugin_description = builder.get_object('lbl_plugin_description') - switch_enable = builder.get_object('switch_enable') - btn_properties = builder.get_object('btn_properties') - lbl_plugin_name.set_label(_(plugin_config['meta']['name'])) - switch_enable.set_active(plugin_config['enabled']) - if plugin_config['error']: - message = plugin_config['meta']['dependency_description'] + lbl_plugin_name = builder.get_object("lbl_plugin_name") + lbl_plugin_description = builder.get_object("lbl_plugin_description") + switch_enable = builder.get_object("switch_enable") + btn_properties = builder.get_object("btn_properties") + lbl_plugin_name.set_label(_(plugin_config["meta"]["name"])) + switch_enable.set_active(plugin_config["enabled"]) + if plugin_config["error"]: + message = plugin_config["meta"]["dependency_description"] if isinstance(message, PluginDependency): lbl_plugin_description.set_label(_(message.message)) - btn_plugin_extra_link = builder.get_object('btn_plugin_extra_link') + btn_plugin_extra_link = builder.get_object("btn_plugin_extra_link") btn_plugin_extra_link.set_label(_("Click here for more information")) btn_plugin_extra_link.set_uri(message.link) btn_plugin_extra_link.set_visible(True) @@ -234,25 +270,30 @@ def __create_plugin_item(self, plugin_config): lbl_plugin_description.set_sensitive(False) switch_enable.set_sensitive(False) btn_properties.set_sensitive(False) - if plugin_config['enabled']: - btn_disable_errored = builder.get_object('btn_disable_errored') + if plugin_config["enabled"]: + btn_disable_errored = builder.get_object("btn_disable_errored") btn_disable_errored.set_visible(True) btn_disable_errored.connect( - 'clicked', lambda button: self.__disable_errored_plugin(button, plugin_config)) + "clicked", + lambda button: self.__disable_errored_plugin(button, plugin_config), + ) else: - lbl_plugin_description.set_label(_(plugin_config['meta']['description'])) - if plugin_config['settings']: + lbl_plugin_description.set_label(_(plugin_config["meta"]["description"])) + if plugin_config["settings"]: btn_properties.set_sensitive(True) - btn_properties.connect('clicked', lambda button: self.__show_plugins_properties_dialog(plugin_config)) + btn_properties.connect( + "clicked", + lambda button: self.__show_plugins_properties_dialog(plugin_config), + ) else: btn_properties.set_sensitive(False) - self.plugin_switches[plugin_config['id']] = switch_enable - if plugin_config.get('break_override_allowed', False): - self.plugin_map[plugin_config['id']] = plugin_config['meta']['name'] - if plugin_config['icon']: - builder.get_object('img_plugin_icon').set_from_file(plugin_config['icon']) - box = builder.get_object('box') + self.plugin_switches[plugin_config["id"]] = switch_enable + if plugin_config.get("break_override_allowed", False): + self.plugin_map[plugin_config["id"]] = plugin_config["meta"]["name"] + if plugin_config["icon"]: + builder.get_object("img_plugin_icon").set_from_file(plugin_config["icon"]) + box = builder.get_object("box") box.set_visible(True) return box @@ -268,13 +309,17 @@ def __disable_errored_plugin(self, button, plugin_config): Permanently disable errored plugin """ button.set_sensitive(False) - self.plugin_switches[plugin_config['id']].set_active(False) + self.plugin_switches[plugin_config["id"]].set_active(False) - def __show_break_properties_dialog(self, break_config, is_short, parent, on_close, on_add, on_remove): + def __show_break_properties_dialog( + self, break_config, is_short, parent, on_close, on_add, on_remove + ): """ Show the BreakProperties dialog """ - dialog = BreakSettingsDialog(break_config, is_short, parent, self.plugin_map, on_close, on_add, on_remove) + dialog = BreakSettingsDialog( + break_config, is_short, parent, self.plugin_map, on_close, on_add, on_remove + ) dialog.show() def show(self): @@ -297,9 +342,13 @@ def on_spin_short_break_interval_change(self, spin_button, *value): short_break_interval = self.spin_short_break_interval.get_value_as_int() long_break_interval = self.spin_long_break_interval.get_value_as_int() self.spin_long_break_interval.set_range(short_break_interval * 2, 120) - self.spin_long_break_interval.set_increments(short_break_interval, short_break_interval * 2) + self.spin_long_break_interval.set_increments( + short_break_interval, short_break_interval * 2 + ) self.spin_long_break_interval.set_value( - short_break_interval * math.ceil(long_break_interval / self.last_short_break_interval)) + short_break_interval + * math.ceil(long_break_interval / self.last_short_break_interval) + ) self.last_short_break_interval = short_break_interval if not self.initializing and not self.infobar_long_break_shown: self.infobar_long_break_shown = True @@ -340,31 +389,50 @@ def add_break(self, button): """ Event handler for add break button. """ - dialog = NewBreakDialog(self.config, lambda is_short, - break_config: self.__create_break_item(break_config, is_short)) + dialog = NewBreakDialog( + self.config, + lambda is_short, break_config: self.__create_break_item( + break_config, is_short + ), + ) dialog.show() def on_window_delete(self, *args): """ Event handler for Settings dialog close action. """ - self.config.set('short_break_duration', self.spin_short_break_duration.get_value_as_int()) - self.config.set('long_break_duration', self.spin_long_break_duration.get_value_as_int()) - self.config.set('short_break_interval', self.spin_short_break_interval.get_value_as_int()) - self.config.set('long_break_interval', self.spin_long_break_interval.get_value_as_int()) - self.config.set('pre_break_warning_time', self.spin_time_to_prepare.get_value_as_int()) - self.config.set('postpone_duration', self.spin_postpone_duration.get_value_as_int()) - self.config.set('shortcut_disable_time', self.spin_disable_keyboard_shortcut.get_value_as_int()) - self.config.set('strict_break', self.switch_strict_break.get_active()) - self.config.set('random_order', self.switch_random_order.get_active()) - self.config.set('allow_postpone', self.switch_postpone.get_active()) - self.config.set('persist_state', self.switch_persist.get_active()) - self.config.set('use_rpc_server', self.switch_rpc_server.get_active()) - for plugin in self.config.get('plugins'): - if plugin['id'] in self.plugin_switches: - plugin['enabled'] = self.plugin_switches[plugin['id']].get_active() - - self.on_save_settings(self.config) # Call the provided save method + self.config.set( + "short_break_duration", self.spin_short_break_duration.get_value_as_int() + ) + self.config.set( + "long_break_duration", self.spin_long_break_duration.get_value_as_int() + ) + self.config.set( + "short_break_interval", self.spin_short_break_interval.get_value_as_int() + ) + self.config.set( + "long_break_interval", self.spin_long_break_interval.get_value_as_int() + ) + self.config.set( + "pre_break_warning_time", self.spin_time_to_prepare.get_value_as_int() + ) + self.config.set( + "postpone_duration", self.spin_postpone_duration.get_value_as_int() + ) + self.config.set( + "shortcut_disable_time", + self.spin_disable_keyboard_shortcut.get_value_as_int(), + ) + self.config.set("strict_break", self.switch_strict_break.get_active()) + self.config.set("random_order", self.switch_random_order.get_active()) + self.config.set("allow_postpone", self.switch_postpone.get_active()) + self.config.set("persist_state", self.switch_persist.get_active()) + self.config.set("use_rpc_server", self.switch_rpc_server.get_active()) + for plugin in self.config.get("plugins"): + if plugin["id"] in self.plugin_switches: + plugin["enabled"] = self.plugin_switches[plugin["id"]].get_active() + + self.on_save_settings(self.config) # Call the provided save method self.window.destroy() @@ -379,36 +447,40 @@ def __init__(self, config): builder = utility.create_gtk_builder(SETTINGS_DIALOG_PLUGIN_GLADE) builder.connect_signals(self) - self.window = builder.get_object('dialog_settings_plugin') - box_settings = builder.get_object('box_settings') - self.window.set_title(_('Plugin Settings')) - for setting in config.get('settings'): - if setting['type'].upper() == 'INT': + self.window = builder.get_object("dialog_settings_plugin") + box_settings = builder.get_object("box_settings") + self.window.set_title(_("Plugin Settings")) + for setting in config.get("settings"): + if setting["type"].upper() == "INT": box_settings.pack_start( self.__load_int_item( - setting['label'], - setting['id'], - setting['safeeyes_config'], - setting.get('min', 0), - setting.get('max', 120) + setting["label"], + setting["id"], + setting["safeeyes_config"], + setting.get("min", 0), + setting.get("max", 120), ), False, False, - 0 + 0, ) - elif setting['type'].upper() == 'TEXT': + elif setting["type"].upper() == "TEXT": box_settings.pack_start( - self.__load_text_item(setting['label'], setting['id'], setting['safeeyes_config']), + self.__load_text_item( + setting["label"], setting["id"], setting["safeeyes_config"] + ), False, False, - 0 + 0, ) - elif setting['type'].upper() == 'BOOL': + elif setting["type"].upper() == "BOOL": box_settings.pack_start( - self.__load_bool_item(setting['label'], setting['id'], setting['safeeyes_config']), + self.__load_bool_item( + setting["label"], setting["id"], setting["safeeyes_config"] + ), False, False, - 0 + 0, ) def __load_int_item(self, name, key, settings, min_value, max_value): @@ -416,13 +488,15 @@ def __load_int_item(self, name, key, settings, min_value, max_value): Load the UI control for int property. """ builder = utility.create_gtk_builder(SETTINGS_ITEM_INT_GLADE) - builder.get_object('lbl_name').set_label(_(name)) - spin_value = builder.get_object('spin_value') + builder.get_object("lbl_name").set_label(_(name)) + spin_value = builder.get_object("spin_value") spin_value.set_range(min_value, max_value) spin_value.set_value(settings[key]) - box = builder.get_object('box') + box = builder.get_object("box") box.set_visible(True) - self.property_controls.append({'key': key, 'settings': settings, 'value': spin_value.get_value}) + self.property_controls.append( + {"key": key, "settings": settings, "value": spin_value.get_value} + ) return box def __load_text_item(self, name, key, settings): @@ -430,12 +504,14 @@ def __load_text_item(self, name, key, settings): Load the UI control for text property. """ builder = utility.create_gtk_builder(SETTINGS_ITEM_TEXT_GLADE) - builder.get_object('lbl_name').set_label(_(name)) - txt_value = builder.get_object('txt_value') + builder.get_object("lbl_name").set_label(_(name)) + txt_value = builder.get_object("txt_value") txt_value.set_text(settings[key]) - box = builder.get_object('box') + box = builder.get_object("box") box.set_visible(True) - self.property_controls.append({'key': key, 'settings': settings, 'value': txt_value.get_text}) + self.property_controls.append( + {"key": key, "settings": settings, "value": txt_value.get_text} + ) return box def __load_bool_item(self, name, key, settings): @@ -443,12 +519,14 @@ def __load_bool_item(self, name, key, settings): Load the UI control for boolean property. """ builder = utility.create_gtk_builder(SETTINGS_ITEM_BOOL_GLADE) - builder.get_object('lbl_name').set_label(_(name)) - switch_value = builder.get_object('switch_value') + builder.get_object("lbl_name").set_label(_(name)) + switch_value = builder.get_object("switch_value") switch_value.set_active(settings[key]) - box = builder.get_object('box') + box = builder.get_object("box") box.set_visible(True) - self.property_controls.append({'key': key, 'settings': settings, 'value': switch_value.get_active}) + self.property_controls.append( + {"key": key, "settings": settings, "value": switch_value.get_active} + ) return box def on_window_delete(self, *args): @@ -456,7 +534,9 @@ def on_window_delete(self, *args): Event handler for Properties dialog close action. """ for property_control in self.property_controls: - property_control['settings'][property_control['key']] = property_control['value']() + property_control["settings"][property_control["key"]] = property_control[ + "value" + ]() self.window.destroy() def show(self): @@ -471,7 +551,16 @@ class BreakSettingsDialog: Builds a settings dialog based on the configuration of a plugin. """ - def __init__(self, break_config, is_short, parent_config, plugin_map, on_close, on_add, on_remove): + def __init__( + self, + break_config, + is_short, + parent_config, + plugin_map, + on_close, + on_add, + on_remove, + ): self.break_config = break_config self.parent_config = parent_config self.plugin_check_buttons = {} @@ -482,26 +571,26 @@ def __init__(self, break_config, is_short, parent_config, plugin_map, on_close, builder = utility.create_gtk_builder(SETTINGS_DIALOG_BREAK_GLADE) builder.connect_signals(self) - self.window = builder.get_object('dialog_settings_break') - self.txt_break = builder.get_object('txt_break') - self.switch_override_interval = builder.get_object('switch_override_interval') - self.switch_override_duration = builder.get_object('switch_override_duration') - self.switch_override_plugins = builder.get_object('switch_override_plugins') - self.spin_interval = builder.get_object('spin_interval') - self.spin_duration = builder.get_object('spin_duration') - self.img_break = builder.get_object('img_break') - self.cmb_type = builder.get_object('cmb_type') - - grid_plugins = builder.get_object('grid_plugins') - list_types = builder.get_object('lst_break_types') - - interval_overriden = break_config.get('interval', None) is not None - duration_overriden = break_config.get('duration', None) is not None - plugins_overriden = break_config.get('plugins', None) is not None + self.window = builder.get_object("dialog_settings_break") + self.txt_break = builder.get_object("txt_break") + self.switch_override_interval = builder.get_object("switch_override_interval") + self.switch_override_duration = builder.get_object("switch_override_duration") + self.switch_override_plugins = builder.get_object("switch_override_plugins") + self.spin_interval = builder.get_object("spin_interval") + self.spin_duration = builder.get_object("spin_duration") + self.img_break = builder.get_object("img_break") + self.cmb_type = builder.get_object("cmb_type") + + grid_plugins = builder.get_object("grid_plugins") + list_types = builder.get_object("lst_break_types") + + interval_overriden = break_config.get("interval", None) is not None + duration_overriden = break_config.get("duration", None) is not None + plugins_overriden = break_config.get("plugins", None) is not None # Set the values - self.window.set_title(_('Break Settings')) - self.txt_break.set_text(_(break_config['name'])) + self.window.set_title(_("Break Settings")) + self.txt_break.set_text(_(break_config["name"])) self.switch_override_interval.set_active(interval_overriden) self.switch_override_duration.set_active(duration_overriden) self.switch_override_plugins.set_active(plugins_overriden) @@ -510,20 +599,20 @@ def __init__(self, break_config, is_short, parent_config, plugin_map, on_close, list_types[1][0] = _(list_types[1][0]) if interval_overriden: - self.spin_interval.set_value(break_config['interval']) + self.spin_interval.set_value(break_config["interval"]) else: if is_short: - self.spin_interval.set_value(parent_config.get('short_break_interval')) + self.spin_interval.set_value(parent_config.get("short_break_interval")) else: - self.spin_interval.set_value(parent_config.get('long_break_interval')) + self.spin_interval.set_value(parent_config.get("long_break_interval")) if duration_overriden: - self.spin_duration.set_value(break_config['duration']) + self.spin_duration.set_value(break_config["duration"]) else: if is_short: - self.spin_duration.set_value(parent_config.get('short_break_duration')) + self.spin_duration.set_value(parent_config.get("short_break_duration")) else: - self.spin_duration.set_value(parent_config.get('long_break_duration')) + self.spin_duration.set_value(parent_config.get("long_break_duration")) row = 0 col = 0 for plugin_id in plugin_map.keys(): @@ -531,7 +620,7 @@ def __init__(self, break_config, is_short, parent_config, plugin_map, on_close, self.plugin_check_buttons[plugin_id] = chk_button grid_plugins.attach(chk_button, row, col, 1, 1) if plugins_overriden: - chk_button.set_active(plugin_id in break_config['plugins']) + chk_button.set_active(plugin_id in break_config["plugins"]) else: chk_button.set_active(True) row += 1 @@ -540,15 +629,26 @@ def __init__(self, break_config, is_short, parent_config, plugin_map, on_close, row = 0 # GtkSwitch state-set signal is available only from 3.14 if Gtk.get_minor_version() >= 14: - self.switch_override_interval.connect('state-set', self.on_switch_override_interval_activate) - self.switch_override_duration.connect('state-set', self.on_switch_override_duration_activate) - self.switch_override_plugins.connect('state-set', self.on_switch_override_plugins_activate) + self.switch_override_interval.connect( + "state-set", self.on_switch_override_interval_activate + ) + self.switch_override_duration.connect( + "state-set", self.on_switch_override_duration_activate + ) + self.switch_override_plugins.connect( + "state-set", self.on_switch_override_plugins_activate + ) self.on_switch_override_interval_activate( - self.switch_override_interval, self.switch_override_interval.get_active()) + self.switch_override_interval, + self.switch_override_interval.get_active(), + ) self.on_switch_override_duration_activate( - self.switch_override_duration, self.switch_override_duration.get_active()) + self.switch_override_duration, + self.switch_override_duration.get_active(), + ) self.on_switch_override_plugins_activate( - self.switch_override_plugins, self.switch_override_plugins.get_active()) + self.switch_override_plugins, self.switch_override_plugins.get_active() + ) def on_switch_override_interval_activate(self, switch_button, state): """ @@ -574,10 +674,15 @@ def select_image(self, button): Show a file chooser dialog and let the user to select an image. """ dialog = Gtk.FileChooserDialog( - _('Please select an image'), + _("Please select an image"), self.window, Gtk.FileChooserAction.OPEN, - (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK) + ( + Gtk.STOCK_CANCEL, + Gtk.ResponseType.CANCEL, + Gtk.STOCK_OPEN, + Gtk.ResponseType.OK, + ), ) png_filter = Gtk.FileFilter() @@ -588,12 +693,14 @@ def select_image(self, button): response = dialog.run() if response == Gtk.ResponseType.OK: - self.break_config['image'] = dialog.get_filename() - pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(self.break_config['image'], 16, 16, True) + self.break_config["image"] = dialog.get_filename() + pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale( + self.break_config["image"], 16, 16, True + ) self.img_break.set_from_pixbuf(pixbuf) elif response == Gtk.ResponseType.CANCEL: - self.break_config.pop('image', None) - self.img_break.set_from_stock('gtk-missing-image', Gtk.IconSize.BUTTON) + self.break_config.pop("image", None) + self.img_break.set_from_stock("gtk-missing-image", Gtk.IconSize.BUTTON) dialog.destroy() @@ -603,34 +710,34 @@ def on_window_delete(self, *args): """ break_name = self.txt_break.get_text().strip() if break_name: - self.break_config['name'] = break_name + self.break_config["name"] = break_name if self.switch_override_interval.get_active(): - self.break_config['interval'] = int(self.spin_interval.get_value()) + self.break_config["interval"] = int(self.spin_interval.get_value()) else: - self.break_config.pop('interval', None) + self.break_config.pop("interval", None) if self.switch_override_duration.get_active(): - self.break_config['duration'] = int(self.spin_duration.get_value()) + self.break_config["duration"] = int(self.spin_duration.get_value()) else: - self.break_config.pop('duration', None) + self.break_config.pop("duration", None) if self.switch_override_plugins.get_active(): selected_plugins = [] for plugin_id in self.plugin_check_buttons: if self.plugin_check_buttons[plugin_id].get_active(): selected_plugins.append(plugin_id) - self.break_config['plugins'] = selected_plugins + self.break_config["plugins"] = selected_plugins else: - self.break_config.pop('plugins', None) + self.break_config.pop("plugins", None) if self.is_short and self.cmb_type.get_active() == 1: # Changed from short to long - self.parent_config.get('short_breaks').remove(self.break_config) - self.parent_config.get('long_breaks').append(self.break_config) + self.parent_config.get("short_breaks").remove(self.break_config) + self.parent_config.get("long_breaks").append(self.break_config) self.on_remove() self.on_add(not self.is_short, self.break_config) elif not self.is_short and self.cmb_type.get_active() == 0: # Changed from long to short - self.parent_config.get('long_breaks').remove(self.break_config) - self.parent_config.get('short_breaks').append(self.break_config) + self.parent_config.get("long_breaks").remove(self.break_config) + self.parent_config.get("short_breaks").append(self.break_config) self.on_remove() self.on_add(not self.is_short, self.break_config) else: @@ -655,16 +762,16 @@ def __init__(self, parent_config, on_add): builder = utility.create_gtk_builder(SETTINGS_DIALOG_NEW_BREAK_GLADE) builder.connect_signals(self) - self.window = builder.get_object('dialog_new_break') - self.txt_break = builder.get_object('txt_break') - self.cmb_type = builder.get_object('cmb_type') - list_types = builder.get_object('lst_break_types') + self.window = builder.get_object("dialog_new_break") + self.txt_break = builder.get_object("txt_break") + self.cmb_type = builder.get_object("cmb_type") + list_types = builder.get_object("lst_break_types") list_types[0][0] = _(list_types[0][0]) list_types[1][0] = _(list_types[1][0]) # Set the values - self.window.set_title(_('New Break')) + self.window.set_title(_("New Break")) def discard(self, button): """ @@ -676,13 +783,13 @@ def save(self, button): """ Event handler for Properties dialog close action. """ - break_config = {'name': self.txt_break.get_text().strip()} + break_config = {"name": self.txt_break.get_text().strip()} if self.cmb_type.get_active() == 0: - self.parent_config.get('short_breaks').append(break_config) + self.parent_config.get("short_breaks").append(break_config) self.on_add(True, break_config) else: - self.parent_config.get('long_breaks').append(break_config) + self.parent_config.get("long_breaks").append(break_config) self.on_add(False, break_config) self.window.destroy() diff --git a/safeeyes/utility.py b/safeeyes/utility.py index e090a3ca..1b376df1 100644 --- a/safeeyes/utility.py +++ b/safeeyes/utility.py @@ -38,31 +38,35 @@ import babel.core import babel.dates import gi -gi.require_version('Gtk', '3.0') + +gi.require_version("Gtk", "3.0") from gi.repository import Gtk from gi.repository import GLib from gi.repository import GdkPixbuf from packaging.version import parse -gi.require_version('Gdk', '3.0') +gi.require_version("Gdk", "3.0") BIN_DIRECTORY = os.path.dirname(os.path.realpath(__file__)) -HOME_DIRECTORY = os.environ.get('HOME') or os.path.expanduser('~') -CONFIG_DIRECTORY = os.path.join(os.environ.get( - 'XDG_CONFIG_HOME') or os.path.join(HOME_DIRECTORY, '.config'), 'safeeyes') -STYLE_SHEET_DIRECTORY = os.path.join(CONFIG_DIRECTORY, 'style') -CONFIG_FILE_PATH = os.path.join(CONFIG_DIRECTORY, 'safeeyes.json') -CONFIG_RESOURCE = os.path.join(CONFIG_DIRECTORY, 'resource') -SESSION_FILE_PATH = os.path.join(CONFIG_DIRECTORY, 'session.json') -STYLE_SHEET_PATH = os.path.join(STYLE_SHEET_DIRECTORY, 'safeeyes_style.css') +HOME_DIRECTORY = os.environ.get("HOME") or os.path.expanduser("~") +CONFIG_DIRECTORY = os.path.join( + os.environ.get("XDG_CONFIG_HOME") or os.path.join(HOME_DIRECTORY, ".config"), + "safeeyes", +) +STYLE_SHEET_DIRECTORY = os.path.join(CONFIG_DIRECTORY, "style") +CONFIG_FILE_PATH = os.path.join(CONFIG_DIRECTORY, "safeeyes.json") +CONFIG_RESOURCE = os.path.join(CONFIG_DIRECTORY, "resource") +SESSION_FILE_PATH = os.path.join(CONFIG_DIRECTORY, "session.json") +STYLE_SHEET_PATH = os.path.join(STYLE_SHEET_DIRECTORY, "safeeyes_style.css") SYSTEM_CONFIG_FILE_PATH = os.path.join(BIN_DIRECTORY, "config/safeeyes.json") -SYSTEM_STYLE_SHEET_PATH = os.path.join( - BIN_DIRECTORY, "config/style/safeeyes_style.css") -LOG_FILE_PATH = os.path.join(HOME_DIRECTORY, 'safeeyes.log') -SYSTEM_PLUGINS_DIR = os.path.join(BIN_DIRECTORY, 'plugins') -USER_PLUGINS_DIR = os.path.join(CONFIG_DIRECTORY, 'plugins') -LOCALE_PATH = os.path.join(BIN_DIRECTORY, 'config/locale') -SYSTEM_DESKTOP_FILE = os.path.join(BIN_DIRECTORY, "platform/io.github.slgobinath.SafeEyes.desktop") +SYSTEM_STYLE_SHEET_PATH = os.path.join(BIN_DIRECTORY, "config/style/safeeyes_style.css") +LOG_FILE_PATH = os.path.join(HOME_DIRECTORY, "safeeyes.log") +SYSTEM_PLUGINS_DIR = os.path.join(BIN_DIRECTORY, "plugins") +USER_PLUGINS_DIR = os.path.join(CONFIG_DIRECTORY, "plugins") +LOCALE_PATH = os.path.join(BIN_DIRECTORY, "config/locale") +SYSTEM_DESKTOP_FILE = os.path.join( + BIN_DIRECTORY, "platform/io.github.slgobinath.SafeEyes.desktop" +) SYSTEM_ICONS = os.path.join(BIN_DIRECTORY, "platform/icons") DESKTOP_ENVIRONMENT = None IS_WAYLAND = False @@ -77,8 +81,7 @@ def get_resource_path(resource_name): return None resource_location = os.path.join(CONFIG_RESOURCE, resource_name) if not os.path.isfile(resource_location): - resource_location = os.path.join( - BIN_DIRECTORY, 'resource', resource_name) + resource_location = os.path.join(BIN_DIRECTORY, "resource", resource_name) if not os.path.isfile(resource_location): # Resource not found resource_location = None @@ -90,7 +93,9 @@ def start_thread(target_function, **args): """ Execute the function in a separate thread. """ - thread = threading.Thread(target=target_function, name="WorkThread", daemon=False, kwargs=args) + thread = threading.Thread( + target=target_function, name="WorkThread", daemon=False, kwargs=args + ) thread.start() @@ -99,6 +104,7 @@ def start_thread(target_function, **args): # Execute the given function in main thread, forwarding positional and keyword arguments. # """ + def execute_main_thread(target_function, *args, **kwargs): """ Execute the given function in main thread. @@ -111,14 +117,14 @@ def system_locale(category=locale.LC_MESSAGES): Return the system locale. If not available, return en_US.UTF-8. """ try: - locale.setlocale(locale.LC_ALL, '') + locale.setlocale(locale.LC_ALL, "") sys_locale = locale.getlocale(category)[0] if not sys_locale: - sys_locale = 'en_US.UTF-8' + sys_locale = "en_US.UTF-8" return sys_locale except BaseException: # Some systems does not return proper locale - return 'en_US.UTF-8' + return "en_US.UTF-8" def format_time(time): @@ -127,11 +133,11 @@ def format_time(time): """ sys_locale = system_locale(locale.LC_TIME) try: - return babel.dates.format_time(time, format='short', locale=sys_locale) + return babel.dates.format_time(time, format="short", locale=sys_locale) except babel.core.UnknownLocaleError: # Some locale types are not supported by the babel library. # Use 'en' locale format if the system locale is not supported. - return babel.dates.format_time(time, format='short', locale='en') + return babel.dates.format_time(time, format="short", locale="en") def mkdir(path): @@ -144,7 +150,7 @@ def mkdir(path): if exc.errno == errno.EEXIST and os.path.isdir(path): pass else: - logging.error('Error while creating ' + str(path)) + logging.error("Error while creating " + str(path)) raise @@ -167,7 +173,7 @@ def write_json(json_path, json_obj): Write the JSON object at the given path """ try: - with open(json_path, 'w') as json_file: + with open(json_path, "w") as json_file: json.dump(json_obj, json_file, indent=4, sort_keys=True) except BaseException: pass @@ -188,29 +194,42 @@ def check_plugin_dependencies(plugin_id, plugin_config, plugin_settings, plugin_ Check the plugin dependencies. """ # Check the desktop environment - if plugin_config['dependencies']['desktop_environments']: + if plugin_config["dependencies"]["desktop_environments"]: # Plugin has restrictions on desktop environments - if DESKTOP_ENVIRONMENT not in plugin_config['dependencies']['desktop_environments']: - return _('Plugin does not support %s desktop environment') % DESKTOP_ENVIRONMENT + if ( + DESKTOP_ENVIRONMENT + not in plugin_config["dependencies"]["desktop_environments"] + ): + return ( + _("Plugin does not support %s desktop environment") + % DESKTOP_ENVIRONMENT + ) # Check the Python modules - for module in plugin_config['dependencies']['python_modules']: + for module in plugin_config["dependencies"]["python_modules"]: if not module_exist(module): return _("Please install the Python module '%s'") % module # Check the shell commands - for command in plugin_config['dependencies']['shell_commands']: + for command in plugin_config["dependencies"]["shell_commands"]: if not command_exist(command): return _("Please install the command-line tool '%s'") % command # Check the resources - for resource in plugin_config['dependencies']['resources']: + for resource in plugin_config["dependencies"]["resources"]: if get_resource_path(resource) is None: - return _('Please add the resource %(resource)s to %(config_resource)s directory') % {'resource': resource, 'config_resource': CONFIG_RESOURCE} # noqa: E501 - - plugin_dependency_checker = os.path.join(plugin_path, 'dependency_checker.py') + return _( + "Please add the resource %(resource)s to %(config_resource)s directory" + ) % { + "resource": resource, + "config_resource": CONFIG_RESOURCE, + } # noqa: E501 + + plugin_dependency_checker = os.path.join(plugin_path, "dependency_checker.py") if os.path.isfile(plugin_dependency_checker): - dependency_checker = importlib.import_module((plugin_id + '.dependency_checker')) + dependency_checker = importlib.import_module( + (plugin_id + ".dependency_checker") + ) if dependency_checker and hasattr(dependency_checker, "validate"): return dependency_checker.validate(plugin_config, plugin_settings) @@ -222,37 +241,38 @@ def load_plugins_config(safeeyes_config): Load all the plugins from the given directory. """ configs = [] - for plugin in safeeyes_config.get('plugins'): - plugin_path = os.path.join(SYSTEM_PLUGINS_DIR, plugin['id']) + for plugin in safeeyes_config.get("plugins"): + plugin_path = os.path.join(SYSTEM_PLUGINS_DIR, plugin["id"]) if not os.path.isdir(plugin_path): # User plugin - plugin_path = os.path.join(USER_PLUGINS_DIR, plugin['id']) - plugin_config_path = os.path.join(plugin_path, 'config.json') - plugin_icon_path = os.path.join(plugin_path, 'icon.png') - plugin_module_path = os.path.join(plugin_path, 'plugin.py') + plugin_path = os.path.join(USER_PLUGINS_DIR, plugin["id"]) + plugin_config_path = os.path.join(plugin_path, "config.json") + plugin_icon_path = os.path.join(plugin_path, "icon.png") + plugin_module_path = os.path.join(plugin_path, "plugin.py") if not os.path.isfile(plugin_module_path): return icon = None if os.path.isfile(plugin_icon_path): icon = plugin_icon_path else: - icon = get_resource_path('ic_plugin.png') + icon = get_resource_path("ic_plugin.png") config = load_json(plugin_config_path) if config is None: continue dependency_description = check_plugin_dependencies( - plugin['id'], config, plugin.get('settings', {}), plugin_path) + plugin["id"], config, plugin.get("settings", {}), plugin_path + ) if dependency_description: - config['error'] = True - config['meta']['dependency_description'] = dependency_description - icon = get_resource_path('ic_warning.png') + config["error"] = True + config["meta"]["dependency_description"] = dependency_description + icon = get_resource_path("ic_warning.png") else: - config['error'] = False - config['id'] = plugin['id'] - config['icon'] = icon - config['enabled'] = plugin['enabled'] - for setting in config['settings']: - setting['safeeyes_config'] = plugin['settings'] + config["error"] = False + config["id"] = plugin["id"] + config["icon"] = icon + config["enabled"] = plugin["enabled"] + for setting in config["settings"]: + setting["safeeyes_config"] = plugin["settings"] configs.append(config) return configs @@ -262,32 +282,51 @@ def desktop_environment(): Detect the desktop environment. """ global DESKTOP_ENVIRONMENT - desktop_session = os.environ.get('DESKTOP_SESSION') - current_desktop = os.environ.get('XDG_CURRENT_DESKTOP') - env = 'unknown' + desktop_session = os.environ.get("DESKTOP_SESSION") + current_desktop = os.environ.get("XDG_CURRENT_DESKTOP") + env = "unknown" if desktop_session is not None: desktop_session = desktop_session.lower() if desktop_session in [ - 'gnome', 'unity', 'budgie-desktop', 'cinnamon', 'mate', 'xfce4', 'lxde', 'pantheon', 'fluxbox', 'blackbox', - 'openbox', 'icewm', 'jwm', 'afterstep', 'trinity', 'kde' + "gnome", + "unity", + "budgie-desktop", + "cinnamon", + "mate", + "xfce4", + "lxde", + "pantheon", + "fluxbox", + "blackbox", + "openbox", + "icewm", + "jwm", + "afterstep", + "trinity", + "kde", ]: env = desktop_session - elif desktop_session.startswith('xubuntu') or (current_desktop is not None and 'xfce' in current_desktop): - env = 'xfce' - elif desktop_session.startswith('lubuntu'): - env = 'lxde' + elif desktop_session.startswith("xubuntu") or ( + current_desktop is not None and "xfce" in current_desktop + ): + env = "xfce" + elif desktop_session.startswith("lubuntu"): + env = "lxde" elif ( - 'plasma' in desktop_session or desktop_session.startswith('kubuntu') - or os.environ.get('KDE_FULL_SESSION') == 'true' + "plasma" in desktop_session + or desktop_session.startswith("kubuntu") + or os.environ.get("KDE_FULL_SESSION") == "true" ): - env = 'kde' - elif os.environ.get('GNOME_DESKTOP_SESSION_ID') or desktop_session.startswith('gnome'): - env = 'gnome' - elif desktop_session.startswith('ubuntu'): - env = 'unity' + env = "kde" + elif os.environ.get("GNOME_DESKTOP_SESSION_ID") or desktop_session.startswith( + "gnome" + ): + env = "gnome" + elif desktop_session.startswith("ubuntu"): + env = "unity" elif current_desktop is not None: - if current_desktop.startswith('sway'): - env = 'sway' + if current_desktop.startswith("sway"): + env = "sway" DESKTOP_ENVIRONMENT = env return env @@ -306,15 +345,15 @@ def is_wayland(): return IS_WAYLAND try: - session_id = subprocess.check_output(['loginctl']).split(b'\n')[1].split()[0] + session_id = subprocess.check_output(["loginctl"]).split(b"\n")[1].split()[0] output = subprocess.check_output( - ['loginctl', 'show-session', session_id, '-p', 'Type'] + ["loginctl", "show-session", session_id, "-p", "Type"] ) except BaseException: - logging.warning('Unable to determine if wayland is running. Assuming no.') + logging.warning("Unable to determine if wayland is running. Assuming no.") IS_WAYLAND = False else: - IS_WAYLAND = bool(re.search(b'wayland', output, re.IGNORECASE)) + IS_WAYLAND = bool(re.search(b"wayland", output, re.IGNORECASE)) return IS_WAYLAND @@ -333,7 +372,7 @@ def execute_command(command, args=[]): try: subprocess.Popen(command_to_execute) except BaseException: - logging.error('Error in executing the command ' + str(command)) + logging.error("Error in executing the command " + str(command)) def command_exist(command): @@ -369,7 +408,7 @@ def initialize_safeeyes(): """ Create the config file and style sheet in XDG_CONFIG_HOME(or ~/.config)/safeeyes directory. """ - logging.info('Copy the config files to XDG_CONFIG_HOME(or ~/.config)/safeeyes') + logging.info("Copy the config files to XDG_CONFIG_HOME(or ~/.config)/safeeyes") # Remove the ~/.config/safeeyes/safeeyes.json file delete(CONFIG_FILE_PATH) @@ -396,11 +435,13 @@ def create_startup_entry(force=False): """ Create start up entry. """ - startup_dir_path = os.path.join(HOME_DIRECTORY, '.config/autostart') - startup_entry = os.path.join(startup_dir_path, 'io.github.slgobinath.SafeEyes.desktop') + startup_dir_path = os.path.join(HOME_DIRECTORY, ".config/autostart") + startup_entry = os.path.join( + startup_dir_path, "io.github.slgobinath.SafeEyes.desktop" + ) # until SafeEyes 2.1.5 the startup entry had another name # https://github.com/slgobinath/SafeEyes/commit/684d16265a48794bb3fd670da67283fe4e2f591b#diff-0863348c2143a4928518a4d3661f150ba86d042bf5320b462ea2e960c36ed275L398 - obsolete_entry = os.path.join(startup_dir_path, 'safeeyes.desktop') + obsolete_entry = os.path.join(startup_dir_path, "safeeyes.desktop") create_link = False @@ -443,15 +484,21 @@ def initialize_platform(): """ logging.debug("Initialize the platform") - applications_dir_path = os.path.join(HOME_DIRECTORY, '.local/share/applications') - icons_dir_path = os.path.join(HOME_DIRECTORY, '.local/share/icons') - desktop_entry = os.path.join(applications_dir_path, 'io.github.slgobinath.SafeEyes.desktop') + applications_dir_path = os.path.join(HOME_DIRECTORY, ".local/share/applications") + icons_dir_path = os.path.join(HOME_DIRECTORY, ".local/share/icons") + desktop_entry = os.path.join( + applications_dir_path, "io.github.slgobinath.SafeEyes.desktop" + ) # Create the folder if not exist mkdir(icons_dir_path) # Create a desktop entry - if not os.path.exists(os.path.join(sys.prefix, "share/applications/io.github.slgobinath.SafeEyes.desktop")): + if not os.path.exists( + os.path.join( + sys.prefix, "share/applications/io.github.slgobinath.SafeEyes.desktop" + ) + ): # Create the folder if not exist mkdir(applications_dir_path) @@ -465,11 +512,15 @@ def initialize_platform(): logging.error("Failed to create desktop entry at %s" % desktop_entry) # Add links for all icons - for (path, _, filenames) in os.walk(SYSTEM_ICONS): + for path, _, filenames in os.walk(SYSTEM_ICONS): for filename in filenames: system_icon = os.path.join(path, filename) - local_icon = os.path.join(icons_dir_path, os.path.relpath(system_icon, SYSTEM_ICONS)) - global_icon = os.path.join(sys.prefix, "share/icons", os.path.relpath(system_icon, SYSTEM_ICONS)) + local_icon = os.path.join( + icons_dir_path, os.path.relpath(system_icon, SYSTEM_ICONS) + ) + global_icon = os.path.join( + sys.prefix, "share/icons", os.path.relpath(system_icon, SYSTEM_ICONS) + ) parent_dir = str(Path(local_icon).parent) if os.path.exists(global_icon): @@ -521,13 +572,15 @@ def initialize_logging(debug): # Configure logging. root_logger = logging.getLogger() log_formatter = logging.Formatter( - '%(asctime)s [%(levelname)s]:[%(threadName)s] %(message)s') + "%(asctime)s [%(levelname)s]:[%(threadName)s] %(message)s" + ) # Append the logs and overwrite once reached 1MB if debug: # Log to file file_handler = RotatingFileHandler( - LOG_FILE_PATH, maxBytes=1024 * 1024, backupCount=5, encoding=None, delay=0) + LOG_FILE_PATH, maxBytes=1024 * 1024, backupCount=5, encoding=None, delay=0 + ) file_handler.setFormatter(log_formatter) # Log to console console_handler = logging.StreamHandler() @@ -544,8 +597,8 @@ def __open_plugin_config(plugins_dir, plugin_id): """ Open the given plugin's configuration. """ - plugin_config_path = os.path.join(plugins_dir, plugin_id, 'config.json') - plugin_module_path = os.path.join(plugins_dir, plugin_id, 'plugin.py') + plugin_config_path = os.path.join(plugins_dir, plugin_id, "config.json") + plugin_module_path = os.path.join(plugins_dir, plugin_id, "plugin.py") if not os.path.isfile(plugin_config_path) or not os.path.isfile(plugin_module_path): # Either the config.json or plugin.py is not available return None @@ -557,42 +610,43 @@ def __update_plugin_config(plugin, plugin_config, config): Update the plugin configuration. """ if plugin_config is None: - config['plugins'].remove(plugin) + config["plugins"].remove(plugin) else: - if parse(plugin.get('version', '0.0.0')) != parse(plugin_config['meta']['version']): + if parse(plugin.get("version", "0.0.0")) != parse( + plugin_config["meta"]["version"] + ): # Update the configuration - plugin['version'] = plugin_config['meta']['version'] + plugin["version"] = plugin_config["meta"]["version"] setting_ids = [] # Add the new settings - for setting in plugin_config['settings']: - setting_ids.append(setting['id']) - if 'settings' not in plugin: - plugin['settings'] = {} - if plugin['settings'].get(setting['id'], None) is None: - plugin['settings'][setting['id']] = setting['default'] + for setting in plugin_config["settings"]: + setting_ids.append(setting["id"]) + if "settings" not in plugin: + plugin["settings"] = {} + if plugin["settings"].get(setting["id"], None) is None: + plugin["settings"][setting["id"]] = setting["default"] # Remove the removed ids keys_to_remove = [] - for key in plugin.get('settings', []): + for key in plugin.get("settings", []): if key not in setting_ids: keys_to_remove.append(key) for key in keys_to_remove: - del plugin['settings'][key] + del plugin["settings"][key] def __add_plugin_config(plugin_id, plugin_config, safe_eyes_config): - """ - """ + """ """ if plugin_config is None: return config = {} - config['id'] = plugin_id - config['enabled'] = False # By default plugins are disabled - config['version'] = plugin_config['meta']['version'] - if plugin_config['settings']: - config['settings'] = {} - for setting in plugin_config['settings']: - config['settings'][setting['id']] = setting['default'] - safe_eyes_config['plugins'].append(config) + config["id"] = plugin_id + config["enabled"] = False # By default plugins are disabled + config["version"] = plugin_config["meta"]["version"] + if plugin_config["settings"]: + config["settings"] = {} + for setting in plugin_config["settings"]: + config["settings"][setting["id"]] = setting["default"] + safe_eyes_config["plugins"].append(config) def merge_plugins(config): @@ -615,8 +669,8 @@ def merge_plugins(config): user_plugins = [] # Create a list of existing plugins - for plugin in config['plugins']: - plugin_id = plugin['id'] + for plugin in config["plugins"]: + plugin_id = plugin["id"] if plugin_id in system_plugins: plugin_config = __open_plugin_config(SYSTEM_PLUGINS_DIR, plugin_id) __update_plugin_config(plugin, plugin_config, config) @@ -626,7 +680,7 @@ def merge_plugins(config): __update_plugin_config(plugin, plugin_config, config) user_plugins.remove(plugin_id) else: - config['plugins'].remove(plugin) + config["plugins"].remove(plugin) # Add all system plugins for plugin_id in system_plugins: @@ -643,11 +697,11 @@ def open_session(): """ Open the last session. """ - logging.info('Reading the session file') + logging.info("Reading the session file") session = load_json(SESSION_FILE_PATH) if session is None: - session = {'plugin': {}} + session = {"plugin": {}} return session @@ -656,7 +710,7 @@ def create_gtk_builder(glade_file): Create a Gtk builder and load the glade file. """ builder = Gtk.Builder() - builder.set_translation_domain('safeeyes') + builder.set_translation_domain("safeeyes") builder.add_from_file(glade_file) # Tranlslate all sub components for obj in builder.get_objects(): @@ -675,10 +729,8 @@ def load_and_scale_image(path, width, height): if not os.path.isfile(path): return None pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale( - filename=path, - width=width, - height=height, - preserve_aspect_ratio=True) + filename=path, width=width, height=height, preserve_aspect_ratio=True + ) image = Gtk.Image.new_from_pixbuf(pixbuf) return image diff --git a/setup.py b/setup.py index 3e3f069a..bd69d387 100644 --- a/setup.py +++ b/setup.py @@ -3,18 +3,11 @@ import setuptools -requires = [ - 'babel', - 'psutil', - 'croniter', - 'PyGObject', - 'packaging', - 'python-xlib' -] +requires = ["babel", "psutil", "croniter", "PyGObject", "packaging", "python-xlib"] _ROOT = os.path.abspath(os.path.dirname(__file__)) -with open(os.path.join(_ROOT, 'README.md')) as f: +with open(os.path.join(_ROOT, "README.md")) as f: long_description = f.read() @@ -22,18 +15,18 @@ def __compile_po_files(): """ Compile the *.po trainslation files. """ - localedir = 'safeeyes/config/locale' - po_dirs = [localedir + '/' + l + '/LC_MESSAGES/' - for l in next(os.walk(localedir))[1]] + localedir = "safeeyes/config/locale" + po_dirs = [ + localedir + "/" + l + "/LC_MESSAGES/" for l in next(os.walk(localedir))[1] + ] for po_dir in po_dirs: - po_files = [f - for f in next(os.walk(po_dir))[2] - if os.path.splitext(f)[1] == '.po'] + po_files = [ + f for f in next(os.walk(po_dir))[2] if os.path.splitext(f)[1] == ".po" + ] for po_file in po_files: filename, _ = os.path.splitext(po_file) - mo_file = filename + '.mo' - msgfmt_cmd = 'msgfmt {} -o {}'.format( - po_dir + po_file, po_dir + mo_file) + mo_file = filename + ".mo" + msgfmt_cmd = "msgfmt {} -o {}".format(po_dir + po_file, po_dir + mo_file) subprocess.call(msgfmt_cmd, shell=True) @@ -42,17 +35,78 @@ def __data_files(): Collect the data files. """ root_dir = sys.prefix - return [(os.path.join(root_dir, "share/applications"), ["safeeyes/platform/io.github.slgobinath.SafeEyes.desktop"]), - (os.path.join(root_dir, "share/icons/hicolor/24x24/status"), ["safeeyes/platform/icons/hicolor/24x24/status/io.github.slgobinath.SafeEyes-disabled.png", "safeeyes/platform/icons/hicolor/24x24/status/io.github.slgobinath.SafeEyes-enabled.png", "safeeyes/platform/icons/hicolor/24x24/status/io.github.slgobinath.SafeEyes-timer.png"]), - (os.path.join(root_dir, "share/icons/hicolor/24x24/apps"), ["safeeyes/platform/icons/hicolor/24x24/apps/io.github.slgobinath.SafeEyes.png"]), - (os.path.join(root_dir, "share/icons/hicolor/16x16/status"), ["safeeyes/platform/icons/hicolor/16x16/status/io.github.slgobinath.SafeEyes-disabled.png", "safeeyes/platform/icons/hicolor/16x16/status/io.github.slgobinath.SafeEyes-enabled.png", "safeeyes/platform/icons/hicolor/16x16/status/io.github.slgobinath.SafeEyes-timer.png"]), - (os.path.join(root_dir, "share/icons/hicolor/16x16/apps"), ["safeeyes/platform/icons/hicolor/16x16/apps/io.github.slgobinath.SafeEyes.png"]), - (os.path.join(root_dir, "share/icons/hicolor/32x32/status"), ["safeeyes/platform/icons/hicolor/32x32/status/io.github.slgobinath.SafeEyes-disabled.png", "safeeyes/platform/icons/hicolor/32x32/status/io.github.slgobinath.SafeEyes-enabled.png"]), - (os.path.join(root_dir, "share/icons/hicolor/32x32/apps"), ["safeeyes/platform/icons/hicolor/32x32/apps/io.github.slgobinath.SafeEyes.png"]), - (os.path.join(root_dir, "share/icons/hicolor/64x64/apps"), ["safeeyes/platform/icons/hicolor/64x64/apps/io.github.slgobinath.SafeEyes.png"]), - (os.path.join(root_dir, "share/icons/hicolor/128x128/apps"), ["safeeyes/platform/icons/hicolor/128x128/apps/io.github.slgobinath.SafeEyes.png"]), - (os.path.join(root_dir, "share/icons/hicolor/48x48/status"), ["safeeyes/platform/icons/hicolor/48x48/status/io.github.slgobinath.SafeEyes-disabled.png", "safeeyes/platform/icons/hicolor/48x48/status/io.github.slgobinath.SafeEyes-enabled.png"]), - (os.path.join(root_dir, "share/icons/hicolor/48x48/apps"), ["safeeyes/platform/icons/hicolor/48x48/apps/io.github.slgobinath.SafeEyes.png"]),] + return [ + ( + os.path.join(root_dir, "share/applications"), + ["safeeyes/platform/io.github.slgobinath.SafeEyes.desktop"], + ), + ( + os.path.join(root_dir, "share/icons/hicolor/24x24/status"), + [ + "safeeyes/platform/icons/hicolor/24x24/status/io.github.slgobinath.SafeEyes-disabled.png", + "safeeyes/platform/icons/hicolor/24x24/status/io.github.slgobinath.SafeEyes-enabled.png", + "safeeyes/platform/icons/hicolor/24x24/status/io.github.slgobinath.SafeEyes-timer.png", + ], + ), + ( + os.path.join(root_dir, "share/icons/hicolor/24x24/apps"), + [ + "safeeyes/platform/icons/hicolor/24x24/apps/io.github.slgobinath.SafeEyes.png" + ], + ), + ( + os.path.join(root_dir, "share/icons/hicolor/16x16/status"), + [ + "safeeyes/platform/icons/hicolor/16x16/status/io.github.slgobinath.SafeEyes-disabled.png", + "safeeyes/platform/icons/hicolor/16x16/status/io.github.slgobinath.SafeEyes-enabled.png", + "safeeyes/platform/icons/hicolor/16x16/status/io.github.slgobinath.SafeEyes-timer.png", + ], + ), + ( + os.path.join(root_dir, "share/icons/hicolor/16x16/apps"), + [ + "safeeyes/platform/icons/hicolor/16x16/apps/io.github.slgobinath.SafeEyes.png" + ], + ), + ( + os.path.join(root_dir, "share/icons/hicolor/32x32/status"), + [ + "safeeyes/platform/icons/hicolor/32x32/status/io.github.slgobinath.SafeEyes-disabled.png", + "safeeyes/platform/icons/hicolor/32x32/status/io.github.slgobinath.SafeEyes-enabled.png", + ], + ), + ( + os.path.join(root_dir, "share/icons/hicolor/32x32/apps"), + [ + "safeeyes/platform/icons/hicolor/32x32/apps/io.github.slgobinath.SafeEyes.png" + ], + ), + ( + os.path.join(root_dir, "share/icons/hicolor/64x64/apps"), + [ + "safeeyes/platform/icons/hicolor/64x64/apps/io.github.slgobinath.SafeEyes.png" + ], + ), + ( + os.path.join(root_dir, "share/icons/hicolor/128x128/apps"), + [ + "safeeyes/platform/icons/hicolor/128x128/apps/io.github.slgobinath.SafeEyes.png" + ], + ), + ( + os.path.join(root_dir, "share/icons/hicolor/48x48/status"), + [ + "safeeyes/platform/icons/hicolor/48x48/status/io.github.slgobinath.SafeEyes-disabled.png", + "safeeyes/platform/icons/hicolor/48x48/status/io.github.slgobinath.SafeEyes-enabled.png", + ], + ), + ( + os.path.join(root_dir, "share/icons/hicolor/48x48/apps"), + [ + "safeeyes/platform/icons/hicolor/48x48/apps/io.github.slgobinath.SafeEyes.png" + ], + ), + ] def __package_files(directory): @@ -60,9 +114,9 @@ def __package_files(directory): Collect the package files. """ paths = [] - for (path, _, filenames) in os.walk(directory): + for path, _, filenames in os.walk(directory): for filename in filenames: - paths.append(os.path.join('..', path, filename)) + paths.append(os.path.join("..", path, filename)) return paths @@ -71,12 +125,13 @@ def __package_data(): Return a list of package data. """ __compile_po_files() - data = ['glade/*.glade', 'resource/*'] - data.extend(__package_files('safeeyes/config')) - data.extend(__package_files('safeeyes/plugins')) - data.extend(__package_files('safeeyes/platform')) + data = ["glade/*.glade", "resource/*"] + data.extend(__package_files("safeeyes/config")) + data.extend(__package_files("safeeyes/plugins")) + data.extend(__package_files("safeeyes/platform")) return data + setuptools.setup( name="safeeyes", version="2.2.1", @@ -88,16 +143,21 @@ def __package_data(): url="https://github.com/slgobinath/SafeEyes", download_url="https://github.com/slgobinath/SafeEyes/archive/v2.2.1.tar.gz", packages=setuptools.find_packages(), - package_data={'safeeyes': __package_data()}, + package_data={"safeeyes": __package_data()}, data_files=__data_files(), install_requires=requires, - entry_points={'console_scripts': ['safeeyes = safeeyes.__main__:main']}, - keywords='linux utility health eye-strain safe-eyes', + entry_points={"console_scripts": ["safeeyes = safeeyes.__main__:main"]}, + keywords="linux utility health eye-strain safe-eyes", classifiers=[ "Operating System :: POSIX :: Linux", "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "Development Status :: 5 - Production/Stable", "Environment :: X11 Applications :: GTK", "Intended Audience :: End Users/Desktop", - "Topic :: Utilities"] + [('Programming Language :: Python :: %s' % x) for x in '3 3.5 3.6 3.7 3.8 3.9'.split()] + "Topic :: Utilities", + ] + + [ + ("Programming Language :: Python :: %s" % x) + for x in "3 3.5 3.6 3.7 3.8 3.9".split() + ], ) diff --git a/validate_po.py b/validate_po.py index f258d8b7..32e143d0 100644 --- a/validate_po.py +++ b/validate_po.py @@ -35,10 +35,10 @@ def validate_po(locale: str, path: str) -> bool: success = True -locales = os.listdir('safeeyes/config/locale') +locales = os.listdir("safeeyes/config/locale") for locale in sorted(locales): - path = os.path.join('safeeyes/config/locale', locale, "LC_MESSAGES/safeeyes.po") + path = os.path.join("safeeyes/config/locale", locale, "LC_MESSAGES/safeeyes.po") if os.path.isfile(path): - print('Validating translation %s...' % path) + print("Validating translation %s..." % path) success = validate_po(locale, path) and success sys.exit(0 if success else 1)