Add log support

This commit is contained in:
Gobinath 2016-11-08 18:47:48 +05:30
parent e3341e26c1
commit 95b4a53e87
5 changed files with 60 additions and 30 deletions

View File

@ -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())

View File

@ -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())

View File

@ -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:

View File

@ -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)

View File

@ -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)