SafeEyes/safeeyes/safeeyes/safeeyes

225 lines
6.8 KiB
Plaintext
Raw Normal View History

2016-10-23 18:40:41 +02:00
#!/usr/bin/env python2
2016-10-15 06:11:27 +02:00
# Safe Eyes is a utility to remind you to take break frequently
# to protect your eyes from eye strain.
# Copyright (C) 2016 Gobinath
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import gi
import json
import shutil
import errno
2016-10-30 10:44:15 +01:00
import dbus
2016-11-08 14:17:48 +01:00
import logging
from threading import Timer
2016-10-30 10:44:15 +01:00
from dbus.mainloop.glib import DBusGMainLoop
2016-10-15 06:11:27 +02:00
from BreakScreen import BreakScreen
from TrayIcon import TrayIcon
from SettingsDialog import SettingsDialog
from SafeEyesCore import SafeEyesCore
from Notification import Notification
2016-10-30 10:44:15 +01:00
2016-10-15 06:11:27 +02:00
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
# Define necessary paths
bin_directory = os.path.dirname(os.path.realpath(__file__))
config_file_path = os.path.join(os.path.expanduser('~'), '.config/safeeyes/safeeyes.json')
style_sheet_path = os.path.join(os.path.expanduser('~'), '.config/safeeyes/style/safeeyes_style.css')
2016-11-08 14:17:48 +01:00
log_file_path = os.path.join(os.path.expanduser('~'), '.config/safeeyes/safeeyes.log')
2016-10-15 06:11:27 +02:00
break_screen_glade = os.path.join(bin_directory, "glade/break_screen.glade")
settings_dialog_glade = os.path.join(bin_directory, "glade/settings_dialog.glade")
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")
2016-11-04 09:47:21 +01:00
system_language_directory = os.path.join(bin_directory, "config/lang")
2016-10-15 06:11:27 +02:00
2016-10-30 10:44:15 +01:00
is_active = True
2016-11-15 05:26:48 +01:00
CONFIGURATION_VERSION = 1
2016-10-30 10:44:15 +01:00
2016-10-15 06:11:27 +02:00
def show_settings():
2016-11-08 14:17:48 +01:00
logging.info("Show Settings dialog")
2016-11-04 09:53:14 +01:00
settings_dialog = SettingsDialog(config, language, save_settings, settings_dialog_glade)
2016-10-15 06:11:27 +02:00
settings_dialog.show()
def show_notification():
notification.show(config['pre_break_warning_time'])
def show_alert(message):
2016-11-08 14:17:48 +01:00
logging.info("Show the break screen")
2016-10-15 06:11:27 +02:00
notification.close()
break_screen.show_message(message)
def close_alert():
2016-11-08 14:17:48 +01:00
logging.info("Close the break screen")
2016-10-15 06:11:27 +02:00
break_screen.close()
def on_countdown(count):
break_screen.show_count_down(count)
2016-11-08 14:17:48 +01:00
def on_quit():
logging.info("Quit Safe Eyes")
2016-10-15 06:11:27 +02:00
core.stop()
notification.quite();
Gtk.main_quit()
2016-10-30 10:44:15 +01:00
def handle_suspend_callback(sleeping):
if sleeping:
# Sleeping / suspending
if is_active:
core.stop()
2016-11-08 14:17:48 +01:00
logging.info("Stopped Safe Eyes due to system suspend")
2016-10-30 10:44:15 +01:00
else:
# Resume from sleep
if is_active:
core.start()
2016-11-08 14:17:48 +01:00
logging.info("Resumed Safe Eyes after system wakeup")
2016-10-30 10:44:15 +01:00
def handle_system_suspend():
DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
bus.add_signal_receiver(handle_suspend_callback, 'PrepareForSleep', 'org.freedesktop.login1.Manager', 'org.freedesktop.login1')
2016-10-15 06:11:27 +02:00
def on_skipped():
2016-11-08 14:17:48 +01:00
logging.info("User skipped the break")
core.skip_break()
2016-10-15 06:11:27 +02:00
def save_settings(config):
2016-11-08 14:17:48 +01:00
logging.info("Saving settings to safeeyes.json")
if is_active:
core.stop()
2016-10-15 06:11:27 +02:00
# Write the configuration to file
with open(config_file_path, 'w') as config_file:
json.dump(config, config_file, indent=4, sort_keys=True)
# Restart the core and intialize the components
logging.info("Initialize SafeEyesCore with modified settings")
core.initialize(config, language)
break_screen.initialize(config, language)
if is_active:
# 1 sec delay is required to give enough time for core to be stopped
Timer(1.0, core.start).start()
2016-10-15 06:11:27 +02:00
def enable_safeeyes():
2016-10-30 10:44:15 +01:00
is_active = True
core.toggle_active_state()
2016-10-15 06:11:27 +02:00
def disable_safeeyes():
2016-10-30 10:44:15 +01:00
is_active = False
core.toggle_active_state()
2016-10-15 06:11:27 +02:00
2016-11-15 05:26:48 +01:00
def initialize_config():
global config
2016-10-15 06:11:27 +02:00
config_dir_path = os.path.join(os.path.expanduser('~'), '.config/safeeyes/style')
2016-10-15 19:10:08 +02:00
startup_dir_path = os.path.join(os.path.expanduser('~'), '.config/autostart')
2016-10-15 06:11:27 +02:00
try:
os.makedirs(config_dir_path)
except OSError as exc:
if exc.errno == errno.EEXIST and os.path.isdir(config_dir_path):
pass
else:
raise
if not os.path.isfile(config_file_path):
shutil.copy2(system_config_file_path, config_file_path)
2016-10-15 19:10:08 +02:00
try:
os.makedirs(startup_dir_path)
except OSError as exc:
if exc.errno == errno.EEXIST and os.path.isdir(startup_dir_path):
pass
else:
raise
2016-10-15 06:11:27 +02:00
# Add to startup for the first time only
2016-10-25 16:14:50 +02:00
try:
os.symlink("/usr/share/applications/safeeyes.desktop", os.path.join(startup_dir_path, "safeeyes.desktop"))
except OSError as exc:
pass
2016-10-15 06:11:27 +02:00
if not os.path.isfile(style_sheet_path):
shutil.copy2(system_style_sheet_path, style_sheet_path)
2016-11-15 05:26:48 +01:00
# Read the configuration
with open(config_file_path) as config_file:
config = json.load(config_file)
"""
Configuration file has a version config_version.
It is used to overwrite the exsiting config file if there is an update.
Earlier versions did not have this attribute so the following method
checks the version and if it mismatches, it will overwrite the exsiting
config files. If the version property is not available, the file is
considered as an older one and replaced by the new configuration file.
"""
def validate_config():
version_mismatch = False
try:
# Check the config version
config_version = config['meta']['config_version']
version_mismatch = config_version is not CONFIGURATION_VERSION
except:
version_mismatch = True
if version_mismatch:
# Remove ~/.config/safeeyes directory
try:
shutil.rmtree(os.path.join(os.path.expanduser('~'), '.config/safeeyes'), ignore_errors=False)
except:
pass
# Remove startup script
try:
os.remove("/usr/share/applications/safeeyes.desktop")
except:
pass
# Create config files again
initialize_config()
2016-10-15 06:11:27 +02:00
def main():
2016-11-15 05:26:48 +01:00
initialize_config()
2016-10-15 06:11:27 +02:00
2016-11-08 14:17:48 +01:00
# Configure logging. Reset with every restart
logging.basicConfig(format='%(asctime)s [%(levelname)s] %(message)s', filename=log_file_path, filemode='w', level=logging.INFO)
logging.info("Starting Safe Eyes")
2016-11-15 05:26:48 +01:00
validate_config()
2016-10-15 06:11:27 +02:00
global break_screen
global core
global notification
global tray_icon
2016-11-04 09:47:21 +01:00
global language
2016-10-15 06:11:27 +02:00
2016-11-04 09:47:21 +01:00
language_file_path = os.path.join(system_language_directory, str(config['language']) + '.json')
with open(language_file_path) as language_file:
language = json.load(language_file)
2016-11-08 14:17:48 +01:00
tray_icon = TrayIcon(language, show_settings, enable_safeeyes, disable_safeeyes, on_quit)
2016-10-15 06:11:27 +02:00
break_screen = BreakScreen(on_skipped, break_screen_glade, style_sheet_path)
2016-11-04 09:47:21 +01:00
break_screen.initialize(config, language)
core = SafeEyesCore(show_notification, show_alert, close_alert, on_countdown, tray_icon.next_break_time)
2016-11-04 09:47:21 +01:00
core.initialize(config, language)
2016-10-15 06:11:27 +02:00
core.start()
2016-11-04 09:47:21 +01:00
notification = Notification(language)
2016-10-15 06:11:27 +02:00
2016-11-04 09:53:14 +01:00
handle_system_suspend()
2016-10-30 10:44:15 +01:00
2016-10-15 06:11:27 +02:00
Gtk.main()
main()