[nanny: 7/13] Implement systray as a notify service, fix some information services.
- From: Roberto Majadas <telemaco src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nanny: 7/13] Implement systray as a notify service, fix some information services.
- Date: Fri, 6 Jul 2012 13:29:59 +0000 (UTC)
commit 1a295699e53c5a97717461f729d598c9e24c64c3
Author: Guido Tabbernuk <boamaod gmail com>
Date: Mon Feb 27 03:01:56 2012 +0200
Implement systray as a notify service, fix some information services.
client/common/src/DBusClient.py | 6 +-
client/gnome/systray/src/SystrayNanny.py | 145 +++++++++++++-------
daemon/data/applists/Makefile.am | 6 +-
daemon/data/applists/browser | 7 +
daemon/data/applists/{browsers.w32 => browser.w32} | 0
daemon/data/applists/browsers | 3 -
daemon/src/Chrono.py | 3 +-
daemon/src/NannyDBus.py | 8 +-
daemon/src/QuarterBack.py | 143 ++++++++++----------
9 files changed, 189 insertions(+), 132 deletions(-)
---
diff --git a/client/common/src/DBusClient.py b/client/common/src/DBusClient.py
index 11ff332..0a305f2 100755
--- a/client/common/src/DBusClient.py
+++ b/client/common/src/DBusClient.py
@@ -44,7 +44,7 @@ class DBusClient(gobject.GObject):
__metaclass__ = Singleton
__gsignals__ = {'user-notification': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
- (gobject.TYPE_BOOLEAN, gobject.TYPE_STRING, gobject.TYPE_INT, gobject.TYPE_INT, gobject.TYPE_INT))
+ (gobject.TYPE_BOOLEAN, gobject.TYPE_STRING, gobject.TYPE_INT, gobject.TYPE_INT, gobject.TYPE_INT, gobject.TYPE_BOOLEAN))
}
def __init__(self):
@@ -261,5 +261,5 @@ class DBusClient(gobject.GObject):
def check_web_access (self, uid, url):
return self.nanny_wcf.CheckWebAccess (uid, url)
- def __on_user_notification_cb (self, block_status, user_id, app_id, next_change, available_time):
- self.emit ('user-notification', block_status, user_id, app_id, next_change, available_time)
+ def __on_user_notification_cb (self, block_status, user_id, app_id, next_change, available_time, active):
+ self.emit ('user-notification', block_status, user_id, app_id, next_change, available_time, active)
diff --git a/client/gnome/systray/src/SystrayNanny.py b/client/gnome/systray/src/SystrayNanny.py
old mode 100644
new mode 100755
index 7e9c327..28b973d
--- a/client/gnome/systray/src/SystrayNanny.py
+++ b/client/gnome/systray/src/SystrayNanny.py
@@ -37,6 +37,8 @@ elif os.name == "nt":
import gobject
from gettext import ngettext
+from datetime import datetime, timedelta
+
import nanny.client.common
import nanny.client.gnome.systray
import gettext
@@ -46,15 +48,16 @@ ngettext = gettext.ngettext
class SystrayNanny(gtk.StatusIcon):
def __init__(self):
- #atributes
- self.times_left = { 0:[-1, False], 1:[-1, False], 2:[-1, False] , 3:[-1, False] }
- self.times_show = { 0:-1, 1:-1, 2:-1, 3:-1 }
- self.app_names = { 0: _("Session"),
- 1: _("Web browser"),
- 2: _("e-Mail"),
- 3: _("Instant messanger")
+ #attributes
+ self.times_left = { 0:[-1, False, False], 1:[-1, False, False], 2:[-1, False, False] , 3:[-1, False, False] }
+ self.app_names = { 0: _("your session"),
+ 1: _("web browser"),
+ 2: _("e-mail"),
+ 3: _("instant messanger")
}
- self.look_times = [ 60, 30, 15, 5, 4, 3, 2, 1 ]
+ self.notified = {0: -1, 1: -1, 2: -1, 3: -1 }
+ self.notify_moments_deny = [ 60, 30, 15, 5, 2, 1, 0 ]
+ self.notify_moments_grant = [ 60, 30, 15, 5, 0 ]
#systray
gtk.StatusIcon.__init__ (self)
@@ -93,58 +96,106 @@ class SystrayNanny(gtk.StatusIcon):
available_time = ret[k][2]
self.__handlerUserNotification(self.dbus, block_status,
user_id, app_id,
- next_change, available_time)
+ next_change, available_time, active)
return True
- def __handlerUserNotification(self, dbus, block_status, user_id, app_id, next_change, available_time):
+ def __handlerUserNotification(self, dbus, block_status, user_id, app_id, next_change, available_time, active):
if os.name == "posix" :
uid= str(os.getuid())
elif os.name == "nt":
uid = self.uid
if uid==user_id:
- self.times_left[app_id] = [next_change, block_status]
+ print user_id, app_id, next_change, block_status, available_time, active
+
+ # a bit messy right now
+ # this should probably be a special function in QuarterBack
+ # is_blocked now deals only with scheduled blocks
+ minutes_till_midnight = int((datetime.now().replace(day=datetime.now().day+1, minute=0, hour=0, second=0, microsecond=0) - datetime.now()).seconds/60)
+ if (datetime.now() + timedelta(minutes=available_time)).day != datetime.now().day:
+ available_time = minutes_till_midnight + self.dbus.get_max_use_time(userid, appid)
+ elif available_time == 0:
+ if (next_change == -1 or (next_change > minutes_till_midnight and block_status == True)):
+ next_change = minutes_till_midnight
+ block_status = True
+
+ if next_change != -1 or available_time != -1:
+ if next_change != -1 and available_time != -1:
+ if (available_time == 0 and next_change > 0) or next_change <= available_time:
+ next_ch_unified = next_change
+ else:
+ next_ch_unified = available_time
+ block_status = False
+ else:
+ if next_change == -1:
+ next_ch_unified = available_time
+ block_status = False
+ elif available_time == -1:
+ next_ch_unified = next_change
+ else:
+ next_ch_unified = -1
+
+ self.times_left[app_id] = [next_ch_unified, block_status, active]
def __handlerTimer(self):
- mssg=""
- mssg_ready=False
+ msg = ""
+ need_to_notify = False
+
for app_id in self.times_left:
- if self.times_left[app_id][0]!=-1:
- if self.times_show[app_id] == -1:
- self.times_show[app_id] = self.times_left[app_id][0] + 60
-
- for time in self.look_times:
- #first element
- if time == self.look_times[0]:
- if self.times_left[app_id][0] >= time and self.times_show[app_id]-self.times_left[app_id][0] >= time:
- self.times_show[app_id]=self.times_left[app_id][0]
- mssg_ready=True
- else:
- if self.times_left[app_id][0]<= time and self.times_show[app_id]-self.times_left[app_id][0] >= time:
- self.times_show[app_id]=self.times_left[app_id][0]
- mssg_ready=True
-
- time = self.__format_time (self.times_left[app_id][0])
- if len (mssg) > 0:
- mssg += "\n"
- if self.times_left[app_id][1]:
- # To translators: In x-minutes the access to <app> will be granted
- mssg += _("In %(time)s the access to %(app)s will be granted.") % {'time': time, 'app': self.app_names[app_id]}
+ next_change = self.times_left[app_id][0]
+ block_status = self.times_left[app_id][1]
+ active = self.times_left[app_id][2]
+ if self.times_left[app_id][0] != -1:
+
+ active_notify = -1
+ if block_status == True:
+ moments_list = self.notify_moments_grant
else:
- # To translators: In x-minutes the access to <app> will be denied
- mssg += _("In %(time)s the access to %(app)s will be denied.") % {'time': time, 'app': self.app_names[app_id]}
-
- if mssg_ready:
- self.__showNotification( mssg )
+ moments_list = self.notify_moments_deny
+
+ for moment in moments_list:
+ if next_change - 1 <= moment:
+ active_notify = moment
+ continue
+ else:
+ break
+
+ if ((active and not block_status) or block_status) and next_change > 1:
+ # running and will be blocked or will be released and ...
+ # (not running and will be blocked is of no interest)
+
+ time = self.__format_time (next_change - 1) # -1 is to overcome lags
+ if len(msg) > 0:
+ msg += "\n"
+ if block_status == True:
+ if next_change <= 1:
+ msg += _("The access to %(app)s granted.") % {'app': self.app_names[app_id]}
+ else:
+ # To translators: In x-minutes the access to <app> will be granted
+ msg += _("In %(time)s the access to %(app)s will be granted.") % {'time': time, 'app': self.app_names[app_id]}
+ else:
+ if next_change <= 1:
+ msg += _("The access to %(app)s denied.") % {'app': self.app_names[app_id]}
+ else:
+ # To translators: In x-minutes the access to <app> will be denied
+ msg += _("In %(time)s the access to %(app)s will be denied.") % {'time': time, 'app': self.app_names[app_id]}
+
+ if self.notified[app_id] != active_notify:
+ self.notified[app_id] = active_notify
+ need_to_notify = True
+
+ if need_to_notify:
+ print "NOTIFY:", msg
+ self.__showNotification(msg)
- if self.last_tooltip != mssg :
- self.set_tooltip( mssg )
- self.last_tooltip = mssg
- print mssg
+ if self.last_tooltip != msg :
+ self.set_tooltip(msg)
+ self.last_tooltip = msg
+ print "TOOLTIP:", msg
- if len(mssg) != 0 :
+ if len(msg) != 0 :
self.set_visible(True)
else:
self.set_visible(False)
@@ -167,12 +218,12 @@ class SystrayNanny(gtk.StatusIcon):
return time
- def __showNotification (self, mssg):
+ def __showNotification (self, msg):
icon_path = os.path.join (nanny.client.gnome.systray.icons_files_dir, "48x48/apps", "nanny.png")
if os.name == "posix":
pynotify.init ("aa")
- self.notificacion = pynotify.Notification ("Nanny", mssg, icon_path)
+ self.notificacion = pynotify.Notification ("Nanny", msg, icon_path)
self.notificacion.show()
elif os.name == "nt":
- self.win_notify.new_popup("Nanny", mssg, icon_path)
+ self.win_notify.new_popup("Nanny", msg, icon_path)
diff --git a/daemon/data/applists/Makefile.am b/daemon/data/applists/Makefile.am
index 8e958c3..18de80e 100644
--- a/daemon/data/applists/Makefile.am
+++ b/daemon/data/applists/Makefile.am
@@ -1,12 +1,12 @@
if NANNY_POSIX_SUPPORT
appsinfodir = $(sysconfdir)/nanny/applists/
-appsinfo_DATA = browsers email im
+appsinfo_DATA = browser email im
endif
if NANNY_WIN32_SUPPORT
appsinfodir = $(sysconfdir)/nanny/applists/
-appsinfo_DATA = browsers.w32 email.w32 im.w32
+appsinfo_DATA = browser.w32 email.w32 im.w32
endif
-EXTRA_DIST = browsers email im browsers.w32 email.w32 im.w32
+EXTRA_DIST = browser email im browser.w32 email.w32 im.w32
diff --git a/daemon/data/applists/browser b/daemon/data/applists/browser
new file mode 100644
index 0000000..17ee17c
--- /dev/null
+++ b/daemon/data/applists/browser
@@ -0,0 +1,7 @@
+firefox
+epiphany
+konqueror
+chromium
+chrome
+opera
+midori
diff --git a/daemon/data/applists/browsers.w32 b/daemon/data/applists/browser.w32
similarity index 100%
rename from daemon/data/applists/browsers.w32
rename to daemon/data/applists/browser.w32
diff --git a/daemon/src/Chrono.py b/daemon/src/Chrono.py
index df84841..330539f 100644
--- a/daemon/src/Chrono.py
+++ b/daemon/src/Chrono.py
@@ -62,7 +62,7 @@ class Chrono(gobject.GObject) :
self.quarterback.connect('block-status', self.__update_cb)
- def __update_cb(self, quarterback, block_status, user_id, app_id, next_change, available_time):
+ def __update_cb(self, quarterback, block_status, user_id, app_id, next_change, available_time, active):
'''Callback that updates the used times of the categories.'''
if block_status == False:
app_list = self.__get_application_list(self.categories)
@@ -86,7 +86,6 @@ class Chrono(gobject.GObject) :
print "Crash Chrono __update_cb"
else:
category = self.categories[app_id]
- found = False
for proc in proclist:
if len(gtop.proc_args(proc)) > 0:
process = gtop.proc_args(proc)[0]
diff --git a/daemon/src/NannyDBus.py b/daemon/src/NannyDBus.py
index 0fe0710..e415ce0 100755
--- a/daemon/src/NannyDBus.py
+++ b/daemon/src/NannyDBus.py
@@ -337,12 +337,12 @@ class NannyDBus(dbus.service.Object):
# --------------------------------------------------------------
@dbus.service.signal("org.gnome.Nanny.Notification",
- signature='bsiii')
- def UserNotification(self, block_status, user_id, app_id, next_change, available_time):
+ signature='bsiiib')
+ def UserNotification(self, block_status, user_id, app_id, next_change, available_time, active):
pass
- def __UserNotification_cb(self, quarterback, block_status, user_id, app_id, next_change, available_time):
- self.UserNotification(block_status, user_id, app_id, next_change, available_time)
+ def __UserNotification_cb(self, quarterback, block_status, user_id, app_id, next_change, available_time, active):
+ self.UserNotification(block_status, user_id, app_id, next_change, available_time, active)
# org.gnome.Nanny.WebDatabase
diff --git a/daemon/src/QuarterBack.py b/daemon/src/QuarterBack.py
index a5e2ace..bd12da2 100755
--- a/daemon/src/QuarterBack.py
+++ b/daemon/src/QuarterBack.py
@@ -83,7 +83,7 @@ WEEKDAYS = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"]
class QuarterBack(gobject.GObject) :
__gsignals__ = {
'block-status' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
- (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,)),
+ (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,)),
'update-blocks' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
(gobject.TYPE_PYOBJECT,)),
'add-wcf-to-uid' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
@@ -146,6 +146,7 @@ class QuarterBack(gobject.GObject) :
self.chrono_times[t][c]["extra_time"] = 0
self.chrono_times[t][c]["mercy_count"] = 0
self.chrono_times[t][c]["force_close"] = 0
+ self.chrono_times[t][c]["last_active"] = -1
self.__next_update_info = None
self.usersmanager = UsersManager()
@@ -161,30 +162,6 @@ class QuarterBack(gobject.GObject) :
gobject.timeout_add(1000, self.__polling_cb)
- def __add_to_archive(self):
- """Appends usage data of the (previous) day to archive"""
-
- output = open(ARCHIVE_DB, 'a')
- writer = csv.writer(output, quoting=csv.QUOTE_NONNUMERIC)
-
- v=[]
- for t in self.chrono_times:
- z=[self.chrono_day, t]
- for c in self.chrono_times[t]:
- for s in self.chrono_times[t][c]:
- z.append(self.chrono_times[t][c][s])
- v.append(z)
-
- writer.writerows(v)
- output.close()
-
- def __save(self):
- output = open(BLOCK_DB, 'wb')
- p = [self.blocks, self.chore_settings, self.wcf_uid_list,
- self.chrono_times, self.chrono_day]
- pickle.dump(p, output)
- output.close()
-
def __polling_cb(self):
self.__check_users_info()
@@ -200,25 +177,6 @@ class QuarterBack(gobject.GObject) :
self.__next_update_info = (time.localtime().tm_min + 1) % 60
return True
- def __refresh_info(self):
- for user_id in self.blocks.keys() :
- for app_id in self.blocks[user_id] :
- block_status, next_change = self.is_blocked(user_id, app_id)
- available_time = self.get_available_time(user_id, app_id)
- self.emit("block-status", block_status, user_id, app_id, next_change, available_time)
-
- def get_block_status_by_uid(self, user_id):
- if user_id not in self.blocks.keys():
- return {}
-
- ret = {}
- for app_id in self.blocks[user_id] :
- block_status, next_change = self.is_blocked(user_id, app_id)
- available_time = self.get_available_time(user_id, app_id)
- ret[app_id] = [block_status, next_change, available_time]
-
- return ret
-
def __check_users_info(self):
some_users_info_changed = False
if not self.usersmanager.has_changes() :
@@ -230,13 +188,10 @@ class QuarterBack(gobject.GObject) :
self.blocks[user_id] = {0: [], 1: [], 2: [], 3: []}
some_users_info_changed = True
if not self.chrono_times.has_key(user_id) :
- self.chrono_times[user_id] = {0: {"max_use": 0, "used_time": 0, "extra_time": 0, "mercy_count": 0, "force_close": 0},
- 1: {"max_use": 0, "used_time": 0, "extra_time": 0, "mercy_count": 0, "force_close": 0},
- 2: {"max_use": 0, "used_time": 0, "extra_time": 0, "mercy_count": 0, "force_close": 0},
- 3: {"max_use": 0, "used_time": 0, "extra_time": 0, "mercy_count": 0, "force_close": 0}}
+ self.chrono_times[user_id] = self.__new_user_chrono_times()
some_users_info_changed = True
if not self.chore_settings.has_key(user_id) :
- self.chore_settings[user_id] = [True, 5]
+ self.chore_settings[user_id] = [True, 5] # defaults to: can use chores, max 5 unfinished
some_users_info_changed = True
# remove deleted users from lists
@@ -282,6 +237,52 @@ class QuarterBack(gobject.GObject) :
self.emit("update-users-info")
self.__refresh_info()
+ def __refresh_info(self):
+ for user_id in self.blocks.keys() :
+ for app_id in self.blocks[user_id] :
+ block_status, next_change = self.is_blocked(user_id, app_id)
+ available_time = self.get_available_time(user_id, app_id)
+ self.emit("block-status", block_status, user_id, app_id, next_change, available_time, self.chrono_times[user_id][app_id]["last_active"] + 1 >= int(time.time()/60))
+
+ def __get_min_block_status(self, user_id, app_id, min) :
+ for block in self.blocks[user_id][app_id]:
+ l, r = block
+ if l <= min <= r :
+ return True
+ return False
+
+ def __add_to_archive(self):
+ """Appends usage data of the (previous) day to archive"""
+
+ output = open(ARCHIVE_DB, 'a')
+ writer = csv.writer(output, quoting=csv.QUOTE_NONNUMERIC)
+
+ v=[]
+ for t in self.chrono_times:
+ z=[self.chrono_day, t]
+ for c in self.chrono_times[t]:
+ for s in self.chrono_times[t][c]:
+ z.append(self.chrono_times[t][c][s])
+ v.append(z)
+
+ writer.writerows(v)
+ output.close()
+
+
+ def __save(self):
+ output = open(BLOCK_DB, 'wb')
+ p = [self.blocks, self.chore_settings, self.wcf_uid_list,
+ self.chrono_times, self.chrono_day]
+ pickle.dump(p, output)
+ output.close()
+
+ def __new_user_chrono_times(self):
+ user ={0: {"max_use": 0, "used_time": 0, "extra_time": 0, "mercy_count": 0, "force_close": 0, "last_active": -1},
+ 1: {"max_use": 0, "used_time": 0, "extra_time": 0, "mercy_count": 0, "force_close": 0, "last_active": -1},
+ 2: {"max_use": 0, "used_time": 0, "extra_time": 0, "mercy_count": 0, "force_close": 0, "last_active": -1},
+ 3: {"max_use": 0, "used_time": 0, "extra_time": 0, "mercy_count": 0, "force_close": 0, "last_active": -1}}
+ return user
+
def is_allowed_to_use(self, user_id, app_id):
available_time = self.get_available_time(user_id, app_id)
is_blocked = self.is_blocked(user_id, app_id)[0]
@@ -316,7 +317,6 @@ class QuarterBack(gobject.GObject) :
if not self.blocks[user_id].has_key(app_id) :
return block_status, next_block
-
if date_time == None:
t = time.localtime()
h = t.tm_hour
@@ -331,7 +331,7 @@ class QuarterBack(gobject.GObject) :
atime = int(w)*24*60 + int(h)*60 + int(m)
block_status = self.__get_min_block_status(user_id, app_id, atime)
-
+
week_m_list = range(atime+1, 24*60*7) + range(0, atime+1)
for m in week_m_list :
@@ -352,17 +352,23 @@ class QuarterBack(gobject.GObject) :
return block_status, next_block
return block_status, next_block
-
-
- def __get_min_block_status(self, user_id, app_id, min) :
- for block in self.blocks[user_id][app_id]:
- l, r = block
- if l <= min <= r :
- return True
- return False
+
+ def get_block_status_by_uid(self, user_id):
+ if user_id not in self.blocks.keys():
+ return {}
+
+ ret = {}
+ for app_id in self.blocks[user_id] :
+ block_status, next_change = self.is_blocked(user_id, app_id)
+ available_time = self.get_available_time(user_id, app_id)
+ ret[app_id] = [block_status, next_change, available_time]
+
+ return ret
+
def set_blocks(self, user_id, app_id, data):
+
if not self.blocks.has_key(user_id) :
self.blocks[user_id] = {}
@@ -479,7 +485,7 @@ class QuarterBack(gobject.GObject) :
self.chrono_times[userid] = new_user
if not self.chrono_times[userid].has_key(appid):
- new_app = {"max_use": 0, "used_time": 0, "extra_time": 0, "mercy_count": 0, "force_close": 0}
+ new_app = {"max_use": 0, "used_time": 0, "extra_time": 0, "mercy_count": 0, "force_close": 0, "last_active": -1}
self.chrono_times[userid][appid] = new_app
self.chrono_times[userid][appid]["max_use"] = mins
@@ -516,11 +522,12 @@ class QuarterBack(gobject.GObject) :
def subtract_time(self, userid, appid, mins=1):
if self.chrono_times.has_key(userid):
if self.chrono_times[userid].has_key(appid):
+ self.chrono_times[userid][appid]["last_active"] = int(time.time()/60)
if self.get_available_time(userid, appid) != 0:
- self.chrono_times[userid][appid]["used_time"] += mins
- print "Substract time (%s, %s) = %s" % (userid, appid,
- self.chrono_times[userid][appid]["used_time"])
- self.__save()
+ self.chrono_times[userid][appid]["used_time"] += mins
+ print "Substract time (%s, %s) = %s" % (userid, appid,
+ self.chrono_times[userid][appid]["used_time"])
+ self.__save()
def new_chrono_day(self):
self.chrono_day = (datetime.today() - datetime.utcfromtimestamp(0)).days
@@ -533,12 +540,8 @@ class QuarterBack(gobject.GObject) :
self.__save()
- def __new_user_chrono_times(self):
- user ={0: {"max_use": 0, "used_time": 0, "extra_time": 0, "mercy_count": 0, "force_close": 0},
- 1: {"max_use": 0, "used_time": 0, "extra_time": 0, "mercy_count": 0, "force_close": 0},
- 2: {"max_use": 0, "used_time": 0, "extra_time": 0, "mercy_count": 0, "force_close": 0},
- 3: {"max_use": 0, "used_time": 0, "extra_time": 0, "mercy_count": 0, "force_close": 0}}
- return user
+
+
gobject.type_register(QuarterBack)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]