From 75fe384da4ed10aff338bb781ca3b566d6f79743 Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Sat, 26 Aug 2006 22:51:33 +0000 Subject: [PATCH] handle advanced notification for new_message event only (without systray / roster / urgency hint that require a event refactorizatin) use subprocess module as we depend on python2.4 --- src/common/helpers.py | 64 +++++++++++++++------- src/gajim.py | 10 ++-- src/notify.py | 122 ++++++++++++++++++++++++++++++++++++------ src/roster_window.py | 6 +-- src/systray.py | 10 ++-- 5 files changed, 167 insertions(+), 45 deletions(-) diff --git a/src/common/helpers.py b/src/common/helpers.py index a462839a9..edccad675 100644 --- a/src/common/helpers.py +++ b/src/common/helpers.py @@ -18,6 +18,7 @@ import sre import os +import subprocess import urllib import errno import select @@ -360,6 +361,11 @@ def is_in_path(name_of_command, return_abs_path = False): else: return is_in_dir +def exec_command(command): + '''command is a string that contain arguments''' +# os.system(command) + subprocess.Popen(command.split()) + def launch_browser_mailer(kind, uri): #kind = 'url' or 'mail' if os.name == 'nt': @@ -383,11 +389,9 @@ def launch_browser_mailer(kind, uri): command = gajim.config.get('custommailapp') if command == '': # if no app is configured return - # we add the uri in "" so we have good parsing from shell - uri = uri.replace('"', '\\"') # escape " - command = command + ' "' + uri + '" &' - try: #FIXME: when we require python2.4+ use subprocess module - os.system(command) + command = command + ' ' + uri + try: + exec_command(command) except: pass @@ -406,11 +410,9 @@ def launch_file_manager(path_to_open): command = gajim.config.get('custom_file_manager') if command == '': # if no app is configured return - # we add the path in "" so we have good parsing from shell - path_to_open = path_to_open.replace('"', '\\"') # escape " - command = command + ' "' + path_to_open + '" &' - try: #FIXME: when we require python2.4+ use subprocess module - os.system(command) + command = command + ' ' + path_to_open + try: + exec_command(command) except: pass @@ -436,11 +438,8 @@ def play_sound_file(path_to_soundfile): if gajim.config.get('soundplayer') == '': return player = gajim.config.get('soundplayer') - # we add the path in "" so we have good parsing from shell - path_to_soundfile = path_to_soundfile.replace('"', '\\"') # escape " - command = player + ' "' + path_to_soundfile + '" &' - #FIXME: when we require 2.4+ use subprocess module - os.system(command) + command = player + ' ' + path_to_soundfile + exec_command(command) def get_file_path_from_dnd_dropped_uri(uri): path = urllib.url2pathname(uri) # escape special chars @@ -727,20 +726,49 @@ def sanitize_filename(filename): return filename -def allow_showing_notification(account): +def allow_showing_notification(account, type = None, advanced_notif_num = None): '''is it allowed to show nofication? - check OUR status and if we allow notifications for that status''' + check OUR status and if we allow notifications for that status + type is the option that need to be True ex: notify_on_signin''' + if advanced_notif_num != None: + popup = gajim.config.get_per('notifications', str(advanced_notif_num), + 'popup') + if popup == 'yes': + return True + if popup == 'no': + return False + if type and not gajim.config.get(type): + return False if gajim.config.get('autopopupaway'): # always show notification return True if gajim.connections[account].connected in (2, 3): # we're online or chat return True return False -def allow_popup_window(account): +def allow_popup_window(account, advanced_notif_num = None): '''is it allowed to popup windows?''' + if advanced_notif_num != None: + popup = gajim.config.get_per('notifications', str(advanced_notif_num), + 'auto_open') + if popup == 'yes': + return True + if popup == 'no': + return False autopopup = gajim.config.get('autopopup') autopopupaway = gajim.config.get('autopopupaway') if autopopup and (autopopupaway or \ gajim.connections[account].connected in (2, 3)): # we're online or chat return True return False + +def allow_sound_notification(sound_event, advanced_notif_num = None): + if advanced_notif_num != None: + sound = gajim.config.get_per('notifications', str(advanced_notif_num), + 'sound') + if sound == 'yes': + return True + if sound == 'no': + return False + if gajim.config.get_per('soundevents', sound_event, 'enabled'): + return True + return False diff --git a/src/gajim.py b/src/gajim.py index e96ad34c6..1e35f83ab 100755 --- a/src/gajim.py +++ b/src/gajim.py @@ -557,6 +557,9 @@ class Interface: not gajim.contacts.get_contact(account, jid) and not pm: return + advanced_notif_num = notify.get_advanced_notification('message_received', + account, contact) + # Is it a first or next message received ? first = False if not chat_control and not gajim.awaiting_events[account].has_key( @@ -571,14 +574,14 @@ class Interface: else: # array: (jid, msg, time, encrypted, msg_type, subject) self.roster.on_message(jid, message, array[2], account, array[3], - msg_type, subject, resource, msg_id, array[9]) + msg_type, subject, resource, msg_id, array[9], advanced_notif_num) nickname = gajim.get_name_from_jid(account, jid) # Check and do wanted notifications msg = message if subject: msg = _('Subject: %s') % subject + '\n' + msg notify.notify('new_message', jid, account, [msg_type, first, nickname, - msg]) + msg], advanced_notif_num) if self.remote_ctrl: self.remote_ctrl.raise_signal('NewMessage', (account, array)) @@ -930,8 +933,7 @@ class Interface: self.add_event(account, jid, 'gc-invitation', (room_jid, array[2], array[3])) - if gajim.config.get('notify_on_new_message') and \ - helpers.allow_showing_notification(account): + if helpers.allow_showing_notification(account, 'notify_on_new_message'): path = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', 'gc_invitation.png') path = gtkgui_helpers.get_path_to_generic_or_avatar(path) diff --git a/src/notify.py b/src/notify.py index e25c47d29..4f7818a02 100644 --- a/src/notify.py +++ b/src/notify.py @@ -32,12 +32,78 @@ if dbus_support.supported: import dbus.glib import dbus.service -def notify(event, jid, account, parameters): +def get_advanced_notification(event, account, contact): + num = 0 + notif = gajim.config.get_per('notifications', str(num)) + while notif: + recipient_ok = False + status_ok = False + tab_opened_ok = False + # test event + if gajim.config.get_per('notifications', str(num), 'event') == event: + # test recipient + recipient_type = gajim.config.get_per('notifications', str(num), + 'recipient_type') + recipients = gajim.config.get_per('notifications', str(num), + 'recipients').split() + if recipient_type == 'all': + recipient_ok = True + elif recipient_type == 'contact' and contact.jid in recipients: + recipient_ok = True + elif recipient_type == 'group': + for group in contact.groups: + if group in contact.groups: + recipient_ok = True + break + if recipient_ok: + # test status + our_status = gajim.SHOW_LIST[gajim.connections[account].connected] + status = gajim.config.get_per('notifications', str(num), 'status') + if status == 'all' or our_status in status.split(): + status_ok = True + if status_ok: + # test window_opened + tab_opened = gajim.config.get_per('notifications', str(num), + 'tab_opened') + if tab_opened == 'both': + tab_opened_ok = True + else: + chat_control = False + full_jid_with_resource = contact.jid + if contact.resource: + full_jid_with_resource += '/' + contact.resource + highest_contact = gajim.contacts.get_contact_with_highest_priority( + account, contact.jid) + # Look for a chat control that has the given resource, or default to + # one without resource + if gajim.interface.msg_win_mgr.get_control(full_jid_with_resource, + account): + chat_control = True + elif not highest_contact or not highest_contact.resource: + # unknow contact or offline message + if gajim.interface.msg_win_mgr.get_control(contact.jid, account): + chat_control = True + elif highest_contact and contact.resource != \ + highest_contact.resource: + chat_control = False + elif gajim.interface.msg_win_mgr.get_control(contact.jid, account): + chat_control = True + if (chat_control and tab_opened == 'yes') or (not chat_control and \ + tab_opened == 'no'): + tab_opened_ok = True + if tab_opened_ok: + return num + + num += 1 + notif = gajim.config.get_per('notifications', str(num)) + +def notify(event, jid, account, parameters, advanced_notif_num = None): '''Check what type of notifications we want, depending on basic configuration of notifications and advanced one and do these notifications''' # First, find what notifications we want do_popup = False do_sound = False + do_cmd = False if (event == 'status_change'): new_show = parameters[0] status_message = parameters[1] @@ -51,9 +117,8 @@ def notify(event, jid, account, parameters): if account_server in gajim.block_signed_in_notifications and \ gajim.block_signed_in_notifications[account_server]: block_transport = True - if gajim.config.get('notify_on_signin') and \ - not gajim.block_signed_in_notifications[account] and not block_transport \ - and helpers.allow_showing_notification(account): + if helpers.allow_showing_notification(account, 'notify_on_signin') and \ + not gajim.block_signed_in_notifications[account] and not block_transport: do_popup = True if gajim.config.get_per('soundevents', 'contact_connected', 'enabled') and not gajim.block_signed_in_notifications[account] and \ @@ -61,8 +126,7 @@ def notify(event, jid, account, parameters): do_sound = True elif (event == 'contact_disconnected'): status_message = parameters - if gajim.config.get('notify_on_signout') \ - and helpers.allow_showing_notification(account): + if helpers.allow_showing_notification(account, 'notify_on_signout'): do_popup = True if gajim.config.get_per('soundevents', 'contact_disconnected', 'enabled'): @@ -72,17 +136,21 @@ def notify(event, jid, account, parameters): first = parameters[1] nickname = parameters[2] message = parameters[3] - if gajim.config.get('notify_on_new_message') and \ - helpers.allow_showing_notification(account) and first: + if helpers.allow_showing_notification(account, 'notify_on_new_message', + advanced_notif_num) and first: do_popup = True - if first and gajim.config.get_per('soundevents', 'first_message_received', - 'enabled'): + if first and helpers.allow_sound_notification('first_message_received', + advanced_notif_num): do_sound = True - elif not first and gajim.config.get_per('soundevents', 'next_message_received', - 'enabled'): + elif not first and helpers.allow_sound_notification( + 'next_message_received', advanced_notif_num): do_sound = True else: print '*Event not implemeted yet*' + + if advanced_notif_num != None and gajim.config.get_per('notifications', + str(advanced_notif_num), 'run_command'): + do_cmd = True # Do the wanted notifications if (do_popup): @@ -161,14 +229,34 @@ def notify(event, jid, account, parameters): path_to_image = path, title = title, text = text) if (do_sound): + snd_file = None + snd_event = None # If not snd_file, play the event if (event == 'new_message'): - if first: - helpers.play_sound('first_message_received') + if advanced_notif_num != None and gajim.config.get_per('notifications', + str(advanced_notif_num), 'sound') == 'yes': + snd_file = gajim.config.get_per('notifications', + str(advanced_notif_num), 'sound_file') + elif advanced_notif_num != None and gajim.config.get_per( + 'notifications', str(advanced_notif_num), 'sound') == 'no': + pass # do not set snd_event + elif first: + snd_event = 'first_message_received' else: - helpers.play_sound('next_message_received') + snd_event = 'next_message_received' elif event in ('contact_connected', 'contact_disconnected'): - helpers.play_sound(event) - + snd_event = event + if snd_file: + helpers.play_sound_file(snd_file) + if snd_event: + helpers.play_sound(snd_event) + + if do_cmd: + command = gajim.config.get_per('notifications', str(advanced_notif_num), + 'command') + try: + helpers.exec_command(command) + except: + pass def popup(event_type, jid, account, msg_type = '', path_to_image = None, title = None, text = None): diff --git a/src/roster_window.py b/src/roster_window.py index e967a4b23..0ebea5941 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -2439,7 +2439,7 @@ _('If "%s" accepts this request you will know his or her status.') % jid) def on_message(self, jid, msg, tim, account, encrypted = False, msg_type = '', subject = None, resource = '', msg_id = None, - user_nick = ''): + user_nick = '', advanced_notif_num = None): '''when we receive a message''' contact = None # if chat window will be for specific resource @@ -2496,7 +2496,7 @@ _('If "%s" accepts this request you will know his or her status.') % jid) if qs.has_key(fjid): no_queue = False - popup = helpers.allow_popup_window(account) + popup = helpers.allow_popup_window(account, advanced_notif_num) if msg_type == 'normal' and popup: # it's single message to be autopopuped dialogs.SingleMessageWindow(account, contact.jid, @@ -2554,7 +2554,7 @@ _('If "%s" accepts this request you will know his or her status.') % jid) self.tree.scroll_to_cell(path) self.tree.set_cursor(path) if gajim.interface.systray_capabilities: - gajim.interface.systray.add_jid(fjid, account, kind) + gajim.interface.systray.add_jid(fjid, account, kind, advanced_notif_num) def on_preferences_menuitem_activate(self, widget): if gajim.interface.instances.has_key('preferences'): diff --git a/src/systray.py b/src/systray.py index 8d07f9597..b7e780919 100644 --- a/src/systray.py +++ b/src/systray.py @@ -58,9 +58,13 @@ class Systray: self.xml.signal_autoconnect(self) self.popup_menus = [] - def set_img(self): + def set_img(self, advanced_notif_num = None): if not gajim.interface.systray_enabled: return + if advanced_notif_num: + if gajim.config.get_per('notifications', str(advanced_notif_num), + 'systray') == 'no': + return if len(self.jids) > 0: state = 'message' else: @@ -71,12 +75,12 @@ class Systray: elif image.get_storage_type() == gtk.IMAGE_PIXBUF: self.img_tray.set_from_pixbuf(image.get_pixbuf()) - def add_jid(self, jid, account, typ): + def add_jid(self, jid, account, typ, advanced_notif_num = None): l = [account, jid, typ] # We can keep several single message 'cause we open them one by one if not l in self.jids or typ == 'normal': self.jids.append(l) - self.set_img() + self.set_img(advanced_notif_num) def remove_jid(self, jid, account, typ): l = [account, jid, typ]