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)