diff options
Diffstat (limited to 'scudcloud-1.0/lib/notify2.py')
-rw-r--r-- | scudcloud-1.0/lib/notify2.py | 342 |
1 files changed, 0 insertions, 342 deletions
diff --git a/scudcloud-1.0/lib/notify2.py b/scudcloud-1.0/lib/notify2.py deleted file mode 100644 index 1b40269..0000000 --- a/scudcloud-1.0/lib/notify2.py +++ /dev/null @@ -1,342 +0,0 @@ -"""This is a pure-python replacement for notify-python, using python-dbus -to communicate with the notifications server directly. It's compatible with -Python 2 and 3, and its callbacks can work with Gtk 3 or Qt 4 applications. - -To use it, first call ``notify2.init('app name')``, then create and show notifications:: - - n = notify2.Notification("Summary", - "Some body text", - "notification-message-im" # Icon name - ) - n.show() - -To see more of what's possible, refer to docstrings of methods and objects. - -Based on the notifications spec at: -http://developer.gnome.org/notification-spec/ - -Porting applications from pynotify ----------------------------------- - -There are a few differences from pynotify you should be aware of: - -- If you need callbacks from notifications, notify2 must know about your event - loop. The simplest way is to pass 'glib' or 'qt' as the ``mainloop`` parameter - to ``init``. -- The methods ``attach_to_widget`` and ``attach_to_status_icon`` are not - implemented. You can calculate the location you want the notification to - appear and call ``Notification``. -- ``set_property`` and ``get_property`` are not implemented. The summary, body - and icon are accessible as attributes of a ``Notification`` instance. -- Various methods that pynotify Notification instances got from gobject do not - exist, or only implement part of the functionality. - -Several pynotify functions, especially getters and setters, are only supported -for compatibility. You are encouraged to use more direct, Pythonic alternatives. -""" - -import dbus - -# Constants -EXPIRES_DEFAULT = -1 -EXPIRES_NEVER = 0 - -URGENCY_LOW = 0 -URGENCY_NORMAL = 1 -URGENCY_CRITICAL = 2 -urgency_levels = [URGENCY_LOW, URGENCY_NORMAL, URGENCY_CRITICAL] - -# Initialise the module (following pynotify's API) ----------------------------- - -initted = False -appname = "" -_have_mainloop = False - -class UninittedError(RuntimeError): - pass - -class UninittedDbusObj(object): - def __getattr__(self, name): - raise UninittedError("You must call notify2.init() before using the " - "notification features.") - -dbus_iface = UninittedDbusObj() - -def init(app_name, mainloop=None): - """Initialise the Dbus connection. - - To get callbacks from notifications, DBus must be integrated with a mainloop. - There are three ways to achieve this: - - - Set a default mainloop (dbus.set_default_main_loop) before calling init() - - Pass the mainloop parameter as a string 'glib' or 'qt' to integrate with - those mainloops. (N.B. passing 'qt' currently makes that the default dbus - mainloop, because that's the only way it seems to work.) - - Pass the mainloop parameter a DBus compatible mainloop instance, such as - dbus.mainloop.glib.DBusGMainLoop(). - - If you only want to display notifications, without receiving information - back from them, you can safely omit mainloop. - """ - global appname, initted, dbus_iface, _have_mainloop - - if mainloop == 'glib': - from dbus.mainloop.glib import DBusGMainLoop - mainloop = DBusGMainLoop() - elif mainloop == 'qt': - from dbus.mainloop.qt import DBusQtMainLoop - # For some reason, this only works if we make it the default mainloop - # for dbus. That might make life tricky for anyone trying to juggle two - # event loops, but I can't see any way round it. - mainloop = DBusQtMainLoop(set_as_default=True) - - bus = dbus.SessionBus(mainloop=mainloop) - - dbus_obj = bus.get_object('org.freedesktop.Notifications', - '/org/freedesktop/Notifications') - dbus_iface = dbus.Interface(dbus_obj, - dbus_interface='org.freedesktop.Notifications') - appname = app_name - initted = True - - if mainloop or dbus.get_default_main_loop(): - _have_mainloop = True - dbus_iface.connect_to_signal('ActionInvoked', _action_callback) - dbus_iface.connect_to_signal('NotificationClosed', _closed_callback) - - return True - -def is_initted(): - """Has init() been called? Only exists for compatibility with pynotify. - """ - return initted - -def get_app_name(): - """Return appname. Only exists for compatibility with pynotify. - """ - return appname - -def uninit(): - """Undo what init() does.""" - global initted, dbus_iface, _have_mainloop - initted = False - _have_mainloop = False - dbus_iface = UninittedDbusObj() - -# Retrieve basic server information -------------------------------------------- - -def get_server_caps(): - """Get a list of server capabilities. - """ - return [str(x) for x in dbus_iface.GetCapabilities()] - -def get_server_info(): - """Get basic information about the server. - """ - res = dbus_iface.GetServerInformation() - return {'name': str(res[0]), - 'vendor': str(res[1]), - 'version': str(res[2]), - 'spec-version': str(res[3]), - } - -# Action callbacks ------------------------------------------------------------- - -notifications_registry = {} - -def _action_callback(nid, action): - nid, action = int(nid), str(action) - n = notifications_registry[nid] - n._action_callback(action) - -def _closed_callback(nid, reason): - nid, reason = int(nid), int(reason) - n = notifications_registry[nid] - n._closed_callback(n) - del notifications_registry[nid] - -def no_op(*args): - """No-op function for callbacks. - """ - pass - -# Controlling notifications ---------------------------------------------------- - -class Notification(object): - id = 0 - timeout = -1 # -1 = server default settings - _closed_callback = no_op - - def __init__(self, summary, message='', icon=''): - self.summary = summary - self.message = message - self.icon = icon - self.hints = {} - self.actions = {} - self.data = {} # Any data the user wants to attach - - def show(self): - """Ask the server to show the notification. - """ - nid = dbus_iface.Notify(appname, # app_name (spec names) - self.id, # replaces_id - self.icon, # app_icon - self.summary, # summary - self.message, # body - self._make_actions_array(), # actions - self.hints, # hints - self.timeout, # expire_timeout - ) - - self.id = int(nid) - - if _have_mainloop: - notifications_registry[self.id] = self - return True - - def update(self, summary, message="", icon=None): - """Replace the summary and body of the notification, and optionally its - icon. You should call show() again after this to display the updated - notification. - """ - self.summary = summary - self.message = message - if icon is not None: - self.icon = icon - - def close(self): - """Ask the server to close this notification. - """ - if self.id != 0: - dbus_iface.CloseNotification(self.id) - - def set_hint(self, key, value): - """n.set_hint(key, value) <--> n.hints[key] = value - - Only exists for compatibility with pynotify. - """ - self.hints[key] = value - - set_hint_string = set_hint_int32 = set_hint_double = set_hint - - def set_hint_byte(self, key, value): - """Set a hint with a dbus byte value. The input value can be an - integer or a bytes string of length 1. - """ - self.hints[key] = dbus.Byte(value) - - def set_urgency(self, level): - """Set the urgency level to one of URGENCY_LOW, URGENCY_NORMAL or - URGENCY_CRITICAL. - """ - if level not in urgency_levels: - raise ValueError("Unknown urgency level specified", level) - self.set_hint_byte("urgency", level) - - def set_category(self, category): - """Set the 'category' hint for this notification. - """ - self.hints['category'] = category - - def set_timeout(self, timeout): - """Set the display duration in milliseconds, or one of the special - values EXPIRES_DEFAULT or EXPIRES_NEVER. - - Only exists for compatibility with pynotify; you can simply set:: - - n.timeout = 5000 - """ - if not isinstance(timeout, int): - raise TypeError("timeout value was not int", timeout) - self.timeout = timeout - - def get_timeout(self): - """Return the timeout value for this notification. - - Only exists for compatibility with pynotify; you can inspect the - timeout attribute directly. - """ - return self.timeout - - def add_action(self, action, label, callback, user_data=None): - """Add an action to the notification (if the server supports it). - - action : str - A brief key. - label : str - The text displayed on the action button - callback : callable - A function taking at 2-3 parameters: the Notification object, the - action key and (if specified) the user_data. - user_data : - An extra argument to pass to the callback. - """ - self.actions[action] = (label, callback, user_data) - - def _make_actions_array(self): - """Make the actions array to send over DBus. - """ - arr = [] - for action, (label, callback, user_data) in self.actions.items(): - arr.append(action) - arr.append(label) - return arr - - def _action_callback(self, action): - """Called when the user selects an action on the notification, to - dispatch it to the relevant user-specified callback. - """ - try: - label, callback, user_data = self.actions[action] - except KeyError: - return - - if user_data is None: - callback(self, action) - else: - callback(self, action, user_data) - - def connect(self, event, callback): - """Set the callback for the notification closing; the only valid value - for event is 'closed'. The API is compatible with pynotify. - """ - if event != 'closed': - raise ValueError("'closed' is the only valid value for event", event) - self._closed_callback = callback - - def set_data(self, key, value): - """n.set_data(key, value) <--> n.data[key] = value - - Only exists for compatibility with pynotify. - """ - self.data[key] = value - - def get_data(self, key): - """n.get_data(key) <--> n.data[key] - - Only exists for compatibility with pynotify. - """ - return self.data[key] - - def set_icon_from_pixbuf(self, icon): - """Set a custom icon from a GdkPixbuf. - """ - struct = ( - icon.get_width(), - icon.get_height(), - icon.get_rowstride(), - icon.get_has_alpha(), - icon.get_bits_per_sample(), - icon.get_n_channels(), - dbus.ByteArray(icon.get_pixels()) - ) - self.hints['icon_data'] = struct - - def set_location(self, x, y): - """Set the notification location as (x, y), if the server supports it. - """ - if (not isinstance(x, int)) or (not isinstance(y, int)): - raise TypeError("x and y must both be ints", (x,y)) - self.hints['x'] = x - self.hints['y'] = y - |