Add log support
This commit is contained in:
parent
e3341e26c1
commit
95b4a53e87
|
@ -18,9 +18,11 @@
|
|||
|
||||
import gi
|
||||
import signal
|
||||
import sys
|
||||
import threading
|
||||
import logging
|
||||
from Xlib import Xatom, Xutil
|
||||
from Xlib.display import Display, X
|
||||
import sys, threading
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk, Gdk, GLib, GdkX11
|
||||
|
@ -51,16 +53,19 @@ class BreakScreen:
|
|||
Initialize the internal properties from configuration
|
||||
"""
|
||||
def initialize(self, config, language):
|
||||
logging.info("Initialize the break screen")
|
||||
self.skip_button_text = language['ui_controls']['skip']
|
||||
self.strict_break = config['strict_break']
|
||||
self.btn_skip.set_label(self.skip_button_text)
|
||||
self.btn_skip.set_visible(not self.strict_break)
|
||||
|
||||
def on_window_delete(self, *args):
|
||||
logging.info("Closing the break screen")
|
||||
self.lock_keyboard = False
|
||||
self.close()
|
||||
|
||||
def on_skip_clicked(self, button):
|
||||
logging.info("User skipped the break")
|
||||
self.on_skip()
|
||||
self.close()
|
||||
|
||||
|
@ -74,6 +79,7 @@ class BreakScreen:
|
|||
Lock the keyboard to prevent the user from using keyboard shortcuts
|
||||
"""
|
||||
def block_keyboard(self):
|
||||
logging.info("Lock the keyboard")
|
||||
self.lock_keyboard = True
|
||||
display = Display()
|
||||
root = display.screen().root
|
||||
|
@ -84,7 +90,9 @@ class BreakScreen:
|
|||
while self.lock_keyboard:
|
||||
self.key_lock_condition.wait()
|
||||
self.key_lock_condition.release()
|
||||
|
||||
# Ungrap the keyboard
|
||||
logging.info("Unlock the keyboard")
|
||||
display.ungrab_keyboard(X.CurrentTime)
|
||||
display.flush()
|
||||
|
||||
|
@ -98,6 +106,7 @@ class BreakScreen:
|
|||
no_of_monitors = screen.get_n_monitors()
|
||||
|
||||
if no_of_monitors > 1:
|
||||
logging.info("Multiple displays are identified")
|
||||
for monitor in range(no_of_monitors):
|
||||
if monitor != current_monitor:
|
||||
monitor_gemoetry = screen.get_monitor_geometry(monitor)
|
||||
|
@ -116,6 +125,7 @@ class BreakScreen:
|
|||
|
||||
self.secondary_windows.append(window)
|
||||
|
||||
logging.info("Show an empty break screen on display {}, {}".format(x, y))
|
||||
window.move(x, y)
|
||||
window.stick()
|
||||
window.set_keep_above(True)
|
||||
|
@ -137,6 +147,7 @@ class BreakScreen:
|
|||
thread = threading.Thread(target=self.block_keyboard)
|
||||
thread.start()
|
||||
|
||||
logging.info("Show break screen(s)")
|
||||
# Show blank break screen on other non-active screens
|
||||
self.block_external_screens()
|
||||
|
||||
|
@ -149,6 +160,7 @@ class BreakScreen:
|
|||
# Set the style only for the first time
|
||||
if not self.is_pretified:
|
||||
# Set style
|
||||
logging.info("Apply style to the break screen")
|
||||
css_provider = Gtk.CssProvider()
|
||||
css_provider.load_from_path(self.style_sheet)
|
||||
Gtk.StyleContext().add_provider_for_screen(Gdk.Screen.get_default(), css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
|
||||
|
@ -160,6 +172,7 @@ class BreakScreen:
|
|||
Hide the break screen from active window and destroy all other windows
|
||||
"""
|
||||
def close(self):
|
||||
logging.info("Close the break screen(s)")
|
||||
self.release_keyboard()
|
||||
GLib.idle_add(lambda: self.window.hide())
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import gi
|
||||
import logging
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('AppIndicator3', '0.1')
|
||||
gi.require_version('Notify', '0.7')
|
||||
|
@ -27,28 +28,23 @@ APPINDICATOR_ID = 'safeeyes'
|
|||
|
||||
class Notification:
|
||||
def __init__(self, language):
|
||||
logging.info("Initialize the notification")
|
||||
Notify.init(APPINDICATOR_ID)
|
||||
self.language = language
|
||||
# self.notification.set_timeout(500)
|
||||
|
||||
def show(self, warning_time):
|
||||
# self.notification.show()
|
||||
# self.notification.close()
|
||||
logging.info("Show pre-break notification")
|
||||
self.notification = Notify.Notification.new("Safe Eyes", "\n" + self.language['messages']['ready_for_a_break'].format(warning_time), icon="safeeyes_enabled")
|
||||
# GLib.idle_add(lambda: self.notification.show())
|
||||
self.notification.show()
|
||||
|
||||
def close(self):
|
||||
logging.info("Close pre-break notification")
|
||||
try:
|
||||
self.notification.close()
|
||||
except:
|
||||
logging.warning("Notification is already closed")
|
||||
pass
|
||||
# GLib.idle_add(lambda: self.notification.close())
|
||||
|
||||
def quite(self):
|
||||
# Notify.uninit()
|
||||
GLib.idle_add(lambda: Notify.uninit())
|
||||
|
||||
# notification = Notification()
|
||||
# notification.show(10)
|
||||
# Gtk.main()
|
||||
logging.info("Uninitialize Safe Eyes notification")
|
||||
GLib.idle_add(lambda: Notify.uninit())
|
|
@ -19,7 +19,7 @@
|
|||
import gi
|
||||
gi.require_version('Gdk', '3.0')
|
||||
from gi.repository import Gdk, Gio, GLib, GdkX11
|
||||
import time, datetime,threading, sys, subprocess
|
||||
import time, datetime,threading, sys, subprocess, logging
|
||||
|
||||
class SafeEyesCore:
|
||||
|
||||
|
@ -41,6 +41,7 @@ class SafeEyesCore:
|
|||
Initialize the internal properties from configuration
|
||||
"""
|
||||
def initialize(self, config, language):
|
||||
logging.info("Initialize the core")
|
||||
self.short_break_exercises = language['exercises']['short_break_exercises']
|
||||
self.long_break_exercises = language['exercises']['long_break_exercises']
|
||||
self.no_of_short_breaks_per_long_break = config['no_of_short_breaks_per_long_break']
|
||||
|
@ -59,14 +60,20 @@ class SafeEyesCore:
|
|||
next_break_time = datetime.datetime.now() + datetime.timedelta(minutes=self.break_interval)
|
||||
self.update_next_break_info(next_break_time)
|
||||
|
||||
|
||||
# Wait for the pre break warning period
|
||||
logging.info("Pre-break waiting for {} minutes".format(self.break_interval))
|
||||
self.notification_condition.acquire()
|
||||
self.notification_condition.wait(self.break_interval * 60) # In minutes
|
||||
self.notification_condition.release()
|
||||
|
||||
logging.info("Pre-break waiting is over")
|
||||
|
||||
if not self.active:
|
||||
return
|
||||
|
||||
logging.info("Ready to show the break")
|
||||
|
||||
GLib.idle_add(lambda: self.process_job())
|
||||
|
||||
"""
|
||||
|
@ -75,6 +82,7 @@ class SafeEyesCore:
|
|||
def process_job(self):
|
||||
if self.is_full_screen_app_found():
|
||||
# If full screen app found, do not show break screen
|
||||
logging.info("Found a full-screen application. Skip the break")
|
||||
if self.active:
|
||||
self.start()
|
||||
return
|
||||
|
@ -91,6 +99,7 @@ class SafeEyesCore:
|
|||
# Show a notification
|
||||
self.show_notification()
|
||||
|
||||
logging.info("Wait for {} seconds which is the time to prepare".format(self.pre_break_warning_time))
|
||||
# Wait for the pre break warning period
|
||||
self.notification_condition.acquire()
|
||||
self.notification_condition.wait(self.pre_break_warning_time)
|
||||
|
@ -100,9 +109,11 @@ class SafeEyesCore:
|
|||
if self.active:
|
||||
message = ""
|
||||
if self.is_long_break():
|
||||
logging.info("Count is {}; get a long beak message".format(self.break_count))
|
||||
self.long_break_message_index = (self.long_break_message_index + 1) % len(self.long_break_exercises)
|
||||
message = self.long_break_exercises[self.long_break_message_index]
|
||||
else:
|
||||
logging.info("Count is {}; get a short beak message".format(self.break_count))
|
||||
self.short_break_message_index = (self.short_break_message_index + 1) % len(self.short_break_exercises)
|
||||
message = self.short_break_exercises[self.short_break_message_index]
|
||||
|
||||
|
@ -125,6 +136,7 @@ class SafeEyesCore:
|
|||
|
||||
# Loop terminated because of timeout (not skipped) -> Close the break alert
|
||||
if not self.skipped:
|
||||
logging.info("Break wasn't skipped. Automatically terminating the break")
|
||||
self.end_break()
|
||||
|
||||
# Resume
|
||||
|
@ -157,6 +169,7 @@ class SafeEyesCore:
|
|||
Stop Safe Eyes
|
||||
"""
|
||||
def stop(self):
|
||||
logging.info("Stop the core")
|
||||
# Reset the state properties in case of restart
|
||||
self.break_count = 0
|
||||
self.long_break_message_index = -1
|
||||
|
@ -176,6 +189,7 @@ class SafeEyesCore:
|
|||
Start Safe Eyes
|
||||
"""
|
||||
def start(self):
|
||||
logging.info("Scheduling next break")
|
||||
self.active = True
|
||||
thread = threading.Thread(target=self.scheduler_job)
|
||||
thread.start()
|
||||
|
@ -184,6 +198,7 @@ class SafeEyesCore:
|
|||
Check for full-screen applications
|
||||
"""
|
||||
def is_full_screen_app_found(self):
|
||||
logging.info("Searching for full-screen application")
|
||||
screen = Gdk.Screen.get_default()
|
||||
active_xid = str(screen.get_active_window().get_xid())
|
||||
cmdlist = ['xprop', '-root', '-notype','-id',active_xid, '_NET_WM_STATE']
|
||||
|
@ -191,6 +206,7 @@ class SafeEyesCore:
|
|||
try:
|
||||
stdout = subprocess.check_output(cmdlist)
|
||||
except subprocess.CalledProcessError:
|
||||
logging.warning("Error in finding full-screen application")
|
||||
pass
|
||||
else:
|
||||
if stdout:
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import gi
|
||||
import logging
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('AppIndicator3', '0.1')
|
||||
from gi.repository import Gtk, Gdk, GLib, GdkX11
|
||||
|
@ -28,6 +29,7 @@ APPINDICATOR_ID = 'safeeyes'
|
|||
|
||||
class TrayIcon:
|
||||
def __init__(self, language, on_show_settings, on_enable, on_disable, on_quite):
|
||||
logging.info("Initialize the tray icon")
|
||||
self.on_show_settings = on_show_settings;
|
||||
self.on_quite = on_quite
|
||||
self.on_enable = on_enable
|
||||
|
@ -81,6 +83,7 @@ class TrayIcon:
|
|||
self.on_show_settings()
|
||||
|
||||
def next_break_time(self, dateTime):
|
||||
logging.info("Update next break information")
|
||||
timeStr = dateTime.strftime("%l:%M")
|
||||
if dateTime.hour == 12:
|
||||
message = self.language['messages']['next_break_at_noon'].format(timeStr)
|
||||
|
@ -94,10 +97,12 @@ class TrayIcon:
|
|||
def on_toogle_enable(self, *args):
|
||||
active = self.item_enable.get_active()
|
||||
if active:
|
||||
logging.info("Enable Safe Eyes")
|
||||
self.indicator.set_icon("safeeyes_enabled")
|
||||
self.item_info.set_sensitive(True)
|
||||
self.on_enable()
|
||||
else:
|
||||
logging.info("Disable Safe Eyes")
|
||||
self.indicator.set_icon("safeeyes_disabled")
|
||||
self.item_info.set_label(self.language['messages']['safe_eyes_is_disabled'])
|
||||
self.item_info.set_sensitive(False)
|
||||
|
|
|
@ -24,6 +24,7 @@ import json
|
|||
import shutil
|
||||
import errno
|
||||
import dbus
|
||||
import logging
|
||||
from dbus.mainloop.glib import DBusGMainLoop
|
||||
|
||||
from BreakScreen import BreakScreen
|
||||
|
@ -39,6 +40,7 @@ from gi.repository import Gtk
|
|||
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')
|
||||
log_file_path = os.path.join(os.path.expanduser('~'), '.config/safeeyes/safeeyes.log')
|
||||
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")
|
||||
|
@ -48,6 +50,7 @@ system_language_directory = os.path.join(bin_directory, "config/lang")
|
|||
is_active = True
|
||||
|
||||
def show_settings():
|
||||
logging.info("Show Settings dialog")
|
||||
settings_dialog = SettingsDialog(config, language, save_settings, settings_dialog_glade)
|
||||
settings_dialog.show()
|
||||
|
||||
|
@ -55,26 +58,19 @@ def show_notification():
|
|||
notification.show(config['pre_break_warning_time'])
|
||||
|
||||
def show_alert(message):
|
||||
logging.info("Show the break screen")
|
||||
notification.close()
|
||||
# Hide and show tray icon if strict break is on
|
||||
# This feature is required because, by disabling Safe Eyes,
|
||||
# user can skip the break.
|
||||
# if config['strict_break']:
|
||||
# tray_icon.hide_icon()
|
||||
break_screen.show_message(message)
|
||||
|
||||
def close_alert():
|
||||
# Hide and show tray icon if strict break is on
|
||||
# This feature is required because, by disabling Safe Eyes,
|
||||
# user can skip the break.
|
||||
# if config['strict_break']:
|
||||
# tray_icon.show_icon()
|
||||
logging.info("Close the break screen")
|
||||
break_screen.close()
|
||||
|
||||
def on_countdown(count):
|
||||
break_screen.show_count_down(count)
|
||||
|
||||
def on_quite():
|
||||
def on_quit():
|
||||
logging.info("Quit Safe Eyes")
|
||||
core.stop()
|
||||
notification.quite();
|
||||
Gtk.main_quit()
|
||||
|
@ -84,10 +80,12 @@ def handle_suspend_callback(sleeping):
|
|||
# Sleeping / suspending
|
||||
if is_active:
|
||||
core.stop()
|
||||
logging.info("Stopped Safe Eyes due to system suspend")
|
||||
else:
|
||||
# Resume from sleep
|
||||
if is_active:
|
||||
core.start()
|
||||
logging.info("Resumed Safe Eyes after system wakeup")
|
||||
|
||||
def handle_system_suspend():
|
||||
DBusGMainLoop(set_as_default=True)
|
||||
|
@ -95,19 +93,17 @@ def handle_system_suspend():
|
|||
bus.add_signal_receiver(handle_suspend_callback, 'PrepareForSleep', 'org.freedesktop.login1.Manager', 'org.freedesktop.login1')
|
||||
|
||||
def on_skipped():
|
||||
# Hide and show tray icon if strict break is on
|
||||
# This feature is required because, by disabling Safe Eyes,
|
||||
# user can skip the break.
|
||||
if config['strict_break']:
|
||||
tray_icon.show_icon()
|
||||
logging.info("User skipped the break")
|
||||
core.skip_break()
|
||||
|
||||
def save_settings(config):
|
||||
logging.info("Saving settings to safeeyes.json")
|
||||
# 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. This will take affect from next break")
|
||||
core.initialize(config, language)
|
||||
break_screen.initialize(config, language)
|
||||
|
||||
|
@ -153,6 +149,10 @@ def prepare_local_config_dir():
|
|||
def main():
|
||||
prepare_local_config_dir()
|
||||
|
||||
# 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")
|
||||
|
||||
global break_screen
|
||||
global core
|
||||
global notification
|
||||
|
@ -168,7 +168,7 @@ def main():
|
|||
with open(language_file_path) as language_file:
|
||||
language = json.load(language_file)
|
||||
|
||||
tray_icon = TrayIcon(language, show_settings, enable_safeeyes, disable_safeeyes, on_quite)
|
||||
tray_icon = TrayIcon(language, show_settings, enable_safeeyes, disable_safeeyes, on_quit)
|
||||
break_screen = BreakScreen(on_skipped, break_screen_glade, style_sheet_path)
|
||||
break_screen.initialize(config, language)
|
||||
core = SafeEyesCore(show_notification, show_alert, close_alert, on_countdown, tray_icon.next_break_time)
|
||||
|
|
Loading…
Reference in New Issue