1 # Copyright (C) 2006, Thomas Leonard
6 from rox
import options
9 memo_soundfile
= options
.Option('memo_sound', "")
10 timer_soundfile
= options
.Option('timer_sound', "")
12 # See http://www.galago-project.org/specs/notification/
14 _avail
= None # Unknown
15 notification_service
= None
23 def _NotificationClosed(nid
, *unused
):
24 if nid
in _nid_to_memo
:
28 def _ActionInvoked(nid
, action
):
30 memo
= _nid_to_memo
.get(nid
, None)
33 from EditBox
import EditBox
35 elif action
== 'delete':
36 from main
import memo_list
37 memo_list
.delete(memo
)
38 elif action
== 'hide':
39 from main
import memo_list
40 memo_list
.set_hidden(memo
, 1)
41 elif action
in ('ok', 'default'):
44 raise Exception('Unknown action "%s"' % action
)
46 rox
.report_exception()
49 global _avail
, notification_service
50 if _avail
is not None: return _avail
56 session_bus
= dbus
.SessionBus()
58 remote_object
= session_bus
.get_object('org.freedesktop.Notifications',
59 '/org/freedesktop/Notifications')
61 notification_service
= dbus
.Interface(remote_object
,
62 'org.freedesktop.Notifications')
64 # The Python bindings insist on printing a pointless introspection
65 # warning to stderr if the service is missing. Force it to be done
66 # now so we can skip it
67 old_stderr
= sys
.stderr
70 notification_service
.GetCapabilities()
72 sys
.stderr
= old_stderr
74 notification_service
.connect_to_signal('NotificationClosed', _NotificationClosed
)
75 notification_service
.connect_to_signal('ActionInvoked', _ActionInvoked
)
83 # Used when the memo has been deleted (or changed)
84 for nid
in _nid_to_memo
:
85 if _nid_to_memo
[nid
] is memo
:
86 notification_service
.CloseNotification(nid
)
89 for nid
in _nid_to_memo
:
90 notification_service
.CloseNotification(nid
)
93 return s
.replace('&', '&').replace('<', '<')
103 delay
= memo
.time
- now
104 earlyAlert
= delay
> 0
106 parts
= memo
.message
.split('\n', 1)
107 summary
= escape(parts
[0])
108 body
= '<i>' + (_('Alarm set for %s') % time
.ctime(memo
.time
)) + '</i>'
110 body
+= '\n' + escape(parts
[1])
115 hints
['urgency'] = dbus
.types
.Byte(NORMAL
)
118 hints
['urgency'] = dbus
.types
.Byte(CRITICAL
)
121 hints
['suppress-sound'] = dbus
.types
.Boolean(True)
122 elif memo
.soundfile
is not None and memo
.soundfile
!= "":
123 hints
['suppress-sound'] = dbus
.types
.Boolean(False)
124 hints
['sound-file'] = dbus
.types
.String(memo
.soundfile
)
125 elif memo_soundfile
.value
!= "":
126 hints
['suppress-sound'] = dbus
.types
.Boolean(False)
127 hints
['sound-file'] = dbus
.types
.String(memo_soundfile
.value
)
128 id = notification_service
.Notify('Memo',
130 path
.join(rox
.app_dir
, ".DirIcon"), # icon
142 _nid_to_memo
[id] = memo
145 memo
.state
= Memo
.EARLY
147 memo
.state
= Memo
.DONE
148 from main
import memo_list
149 memo_list
.notify_changed()
157 hints
['urgency'] = dbus
.types
.Byte(CRITICAL
)
158 if timer_soundfile
.value
!= "":
159 hints
['sound-file'] = timer_soundfile
.value
161 notification_service
.Notify('Memo',
163 path
.join(rox
.app_dir
, ".DirIcon"), # icon
165 'The Memo timer you set has expired.',
170 if __name__
== '__main__':
171 __builtins__
._ = lambda x
: x
172 from Memo
import Memo
173 assert is_available()
174 notify(Memo(0, 'This is a <message>.\nMore <details> go <here>.', True))