root/branches/gajim_0.9.1/src/notify.py

Revision 4870, 7.4 kB (checked in by asterix, 3 years ago)

print more dbus errors in verbose mode only

Line 
1##      notify.py
2##
3## Contributors for this file:
4## - Yann Le Boulanger <asterix@lagaule.org>
5## - Nikos Kouremenos <kourem@gmail.com>
6## - Dimitur Kirov <dkirov@gmail.com>
7## - Andrew Sayman <lorien420@myrealbox.com>
8##
9## Copyright (C) 2003-2004 Yann Le Boulanger <asterix@lagaule.org>
10##                         Vincent Hanquez <tab@snarc.org>
11## Copyright (C) 2005 Yann Le Boulanger <asterix@lagaule.org>
12##                    Vincent Hanquez <tab@snarc.org>
13##                    Nikos Kouremenos <nkour@jabber.org>
14##                    Dimitur Kirov <dkirov@gmail.com>
15##                    Travis Shirk <travis@pobox.com>
16##                    Norman Rasmussen <norman@rasmussen.co.za>
17##
18## DBUS/libnotify connection code:
19## Copyright (C) 2005 by Sebastian Estienne
20##
21## This program is free software; you can redistribute it and/or modify
22## it under the terms of the GNU General Public License as published
23## by the Free Software Foundation; version 2 only.
24##
25## This program is distributed in the hope that it will be useful,
26## but WITHOUT ANY WARRANTY; without even the implied warranty of
27## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28## GNU General Public License for more details.
29##
30
31import os
32import sys
33import gajim
34import dialogs
35import gobject
36
37from common import gajim
38from common import exceptions
39from common import i18n
40i18n.init()
41_ = i18n._
42
43import dbus_support
44if dbus_support.supported:
45        import dbus
46        if dbus_support.version >= (0, 41, 0):
47                import dbus.glib
48                import dbus.service
49
50def notify(event_type, jid, account, msg_type = '', file_props = None):
51        '''Notifies a user of an event. It first tries to a valid implementation of
52        the Desktop Notification Specification. If that fails, then we fall back to
53        the older style PopupNotificationWindow method.'''
54        if gajim.config.get('use_notif_daemon') and dbus_support.supported:
55                try:
56                        DesktopNotification(event_type, jid, account, msg_type, file_props)
57                        return
58                except dbus.dbus_bindings.DBusException, e:
59                        # Connection to DBus failed, try popup
60                        gajim.log.debug(str(e))
61                except TypeError, e:
62                        # This means that we sent the message incorrectly
63                        gajim.log.debug(str(e))
64        instance = dialogs.PopupNotificationWindow(event_type, jid, account,
65                msg_type, file_props)
66        gajim.interface.roster.popup_notification_windows.append(instance)
67
68class NotificationResponseManager:
69        '''Collects references to pending DesktopNotifications and manages there
70        signalling. This is necessary due to a bug in DBus where you can't remove
71        a signal from an interface once it's connected.'''
72        def __init__(self):
73                self.pending = {}
74                self.interface = None
75
76        def attach_to_interface(self):
77                if self.interface is not None:
78                        return
79                self.interface = dbus_support.get_notifications_interface()
80                self.interface.connect_to_signal('ActionInvoked', self.on_action_invoked)
81                self.interface.connect_to_signal('NotificationClosed', self.on_closed)
82
83        def on_action_invoked(self, id, reason):
84                if self.pending.has_key(id):
85                        notification = self.pending[id]
86                        notification.on_action_invoked(id, reason)
87                        del self.pending[id]
88                else:
89                        # This happens in the case of a race condition where the user clicks
90                        # on a popup before the program finishes registering this callback
91                        gobject.timeout_add(1000, self.on_action_invoked, id, reason)
92
93        def on_closed(self, id, reason):
94                if self.pending.has_key(id):
95                        del self.pending[id]
96
97notification_response_manager = NotificationResponseManager()
98
99class DesktopNotification:
100        '''A DesktopNotification that interfaces with DBus via the Desktop
101        Notification specification'''
102        def __init__(self, event_type, jid, account, msg_type = '', file_props = None):
103                self.account = account
104                self.jid = jid
105                self.msg_type = msg_type
106                self.file_props = file_props
107
108                if jid in gajim.contacts[account]:
109                        actor = gajim.get_first_contact_instance_from_jid(account, jid).name
110                else:
111                        actor = jid
112
113                txt = actor # default value of txt
114
115                if event_type == _('Contact Signed In'):
116                        img = 'contact_online.png'
117                        ntype = 'presence.online'
118                elif event_type == _('Contact Signed Out'):
119                        img = 'contact_offline.png'
120                        ntype = 'presence.offline'
121                elif event_type in (_('New Message'), _('New Single Message'),
122                        _('New Private Message')):
123                        ntype = 'im.received'
124                        if event_type == _('New Private Message'):
125                                room_jid, nick = gajim.get_room_and_nick_from_fjid(jid)
126                                room_name,t = gajim.get_room_name_and_server_from_room_jid(room_jid)
127                                txt = _('%(nickname)s in room %(room_name)s has sent you a new message.')\
128                                        % {'nickname': nick, 'room_name': room_name}
129                                img = 'priv_msg_recv.png'
130                        else:
131                                #we talk about a name here
132                                txt = _('%s has sent you a new message.') % actor
133                                if event_type == _('New Message'):
134                                        img = 'chat_msg_recv.png'
135                                else: # New Single Message
136                                        img = 'single_msg_recv.png'
137                elif event_type == _('File Transfer Request'):
138                        img = 'ft_request.png'
139                        ntype = 'transfer'
140                        #we talk about a name here
141                        txt = _('%s wants to send you a file.') % actor
142                elif event_type == _('File Transfer Error'):
143                        img = 'ft_stopped.png'
144                        ntype = 'transfer.error'
145                elif event_type in (_('File Transfer Completed'), _('File Transfer Stopped')):
146                        ntype = 'transfer.complete'
147                        if file_props is not None:
148                                if file_props['type'] == 'r':
149                                        # get the name of the sender, as it is in the roster
150                                        sender = unicode(file_props['sender']).split('/')[0]
151                                        name = gajim.get_first_contact_instance_from_jid(
152                                                account, sender).name
153                                        filename = os.path.basename(file_props['file-name'])
154                                        if event_type == _('File Transfer Completed'):
155                                                txt = _('You successfully received %(filename)s from %(name)s.')\
156                                                        % {'filename': filename, 'name': name}
157                                                img = 'ft_done.png'
158                                        else: # ft stopped
159                                                txt = _('File transfer of %(filename)s from %(name)s stopped.')\
160                                                        % {'filename': filename, 'name': name}
161                                                img = 'ft_stopped.png'
162                                else:
163                                        receiver = file_props['receiver']
164                                        if hasattr(receiver, 'jid'):
165                                                receiver = receiver.jid
166                                        receiver = receiver.split('/')[0]
167                                        # get the name of the contact, as it is in the roster
168                                        name = gajim.get_first_contact_instance_from_jid(
169                                                account, receiver).name
170                                        filename = os.path.basename(file_props['file-name'])
171                                        if event_type == _('File Transfer Completed'):
172                                                txt = _('You successfully sent %(filename)s to %(name)s.')\
173                                                        % {'filename': filename, 'name': name}
174                                                img = 'ft_done.png'
175                                        else: # ft stopped
176                                                txt = _('File transfer of %(filename)s to %(name)s stopped.')\
177                                                        % {'filename': filename, 'name': name}
178                                                img = 'ft_stopped.png'
179                        else:
180                                txt = ''
181                else:
182                        # defaul failsafe values
183                        img = 'chat_msg_recv.png' # img to display
184                        ntype = 'im'     # Notification Type
185
186                path = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', img)
187                path = os.path.abspath(path)
188
189                self.notif = dbus_support.get_notifications_interface()
190                if self.notif is None:
191                        raise dbus.dbus_bindings.DBusException()
192                self.id = self.notif.Notify(dbus.String(_('Gajim')),
193                        dbus.String(path), dbus.UInt32(0), ntype, dbus.Byte(0),
194                        dbus.String(event_type), dbus.String(txt),
195                        [dbus.String(path)], {'default':0}, [''], True, dbus.UInt32(5))
196                notification_response_manager.attach_to_interface()
197                notification_response_manager.pending[self.id] = self
198
199        def on_action_invoked(self, id, reason):
200                if self.notif is None:
201                        return
202                self.notif.CloseNotification(dbus.UInt32(id))
203                self.notif = None
204                if not self.msg_type:
205                        self.msg_type = 'chat'
206                gajim.interface.handle_event(self.account, self.jid, self.msg_type)
Note: See TracBrowser for help on using the browser.