diff --git a/data/pixmaps/events/subscription_request.png b/data/pixmaps/events/subscription_request.png new file mode 100644 index 0000000000000000000000000000000000000000..f3eeb37da85ee181b07f746a84d85ddb3adb7d9f Binary files /dev/null and b/data/pixmaps/events/subscription_request.png differ diff --git a/data/pixmaps/events/unsubscribed.png b/data/pixmaps/events/unsubscribed.png new file mode 100644 index 0000000000000000000000000000000000000000..f9e93bf17b2135d7610cef660689a5e0f78fa95a Binary files /dev/null and b/data/pixmaps/events/unsubscribed.png differ diff --git a/src/common/events.py b/src/common/events.py index cb819d59491408ed47c223bda29f9aa096252377..82017112aa9047418b5494e89eaab4d2b1004653 100644 --- a/src/common/events.py +++ b/src/common/events.py @@ -28,11 +28,12 @@ import time class Event: '''Information concerning each event''' - def __init__(self, type_, time_, parameters, show_in_roster = False, - show_in_systray = True): + def __init__(self, type_, time_, parameters, show_in_roster=False, + show_in_systray=True): ''' type_ in chat, normal, file-request, file-error, file-completed, file-request-error, file-send-error, file-stopped, gc_msg, pm, - printed_chat, printed_gc_msg, printed_marked_gc_msg, printed_pm + printed_chat, printed_gc_msg, printed_marked_gc_msg, printed_pm, + gc-invitation, subscription_request, unsubscribed parameters is (per type_): chat, normal, pm: [message, subject, kind, time, encrypted, resource, msg_id] @@ -41,7 +42,11 @@ class Event: gc_msg: None printed_chat: control printed_*: None - messages that are already printed in chat, but not read''' + messages that are already printed in chat, but not read + gc-invitation: [room_jid, reason, password, is_continued] + subscription_request: [text, nick] + unsubscribed: contact + ''' self.type_ = type_ self.time_ = time_ self.parameters = parameters diff --git a/src/dialogs.py b/src/dialogs.py index fb531973da30a111977deabd6eb43fdbf7f11e5f..de8e7f5b6e3be66795c2986eaf690ea09deee20c 100644 --- a/src/dialogs.py +++ b/src/dialogs.py @@ -1644,6 +1644,9 @@ class SubscriptionRequestWindow: def on_deny_button_clicked(self, widget): '''refuse the request''' gajim.connections[self.account].refuse_authorization(self.jid) + contact = gajim.contacts.get_contact(self.account, self.jid) + if contact and _('Not in Roster') in contact.get_shown_groups(): + gajim.interface.roster.remove_contact(self.jid, self.account) self.window.destroy() def on_actions_button_clicked(self, widget): diff --git a/src/gajim.py b/src/gajim.py index 081d84a58ee0888f36db18776613b087f55644e5..d0ee392b11d589d1eb8359b4f517659c84ffc5ae 100644 --- a/src/gajim.py +++ b/src/gajim.py @@ -959,10 +959,26 @@ class Interface: def handle_event_subscribe(self, account, array): #('SUBSCRIBE', account, (jid, text, user_nick)) user_nick is JEP-0172 - dialogs.SubscriptionRequestWindow(array[0], array[1], account, array[2]) if self.remote_ctrl: self.remote_ctrl.raise_signal('Subscribe', (account, array)) + jid = array[0] + text = array[1] + nick = array[2] + if helpers.allow_popup_window(account) or not self.systray_enabled: + dialogs.SubscriptionRequestWindow(jid, text, account, nick) + return + + self.add_event(account, jid, 'subscription_request', (text, nick)) + + if helpers.allow_showing_notification(account): + path = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', + 'subscription_request.png') + path = gtkgui_helpers.get_path_to_generic_or_avatar(path) + event_type = _('Subscription request') + notify.popup(event_type, jid, account, 'subscription_request', path, + event_type, jid) + def handle_event_subscribed(self, account, array): #('SUBSCRIBED', account, (jid, resource)) jid = array[0] @@ -992,7 +1008,20 @@ class Interface: if self.remote_ctrl: self.remote_ctrl.raise_signal('Subscribed', (account, array)) + def show_unsubscribed_dialog(self, account, contact): + def on_yes(is_checked, list_): + self.roster.on_req_usub(None, list_) + list_ = [(contact, account)] + dialogs.YesNoDialog( + _('Contact "%s" removed subscription from you') % contact.jid, + _('You will always see him or her as offline.\nDo you want to ' + 'remove him or her from your contact list?'), + on_response_yes=(on_yes, list_)) + # FIXME: Per RFC 3921, we can "deny" ack as well, but the GUI does + # not show deny + def handle_event_unsubscribed(self, account, jid): + #('UNSUBSCRIBED', account, jid) gajim.connections[account].ack_unsubscribed(jid) if self.remote_ctrl: self.remote_ctrl.raise_signal('Unsubscribed', (account, jid)) @@ -1000,14 +1029,19 @@ class Interface: contact = gajim.contacts.get_first_contact_from_jid(account, jid) if not contact: return - def on_yes(is_checked, list_): - self.roster.on_req_usub(None, list_) - list_ = [(contact, account)] - dialogs.YesNoDialog( - _('Contact "%s" removed subscription from you') % jid, - _('You will always see him or her as offline.\nDo you want to remove him or her from your contact list?'), - on_response_yes=(on_yes, list_)) - # FIXME: Per RFC 3921, we can "deny" ack as well, but the GUI does not show deny + + if helpers.allow_popup_window(account) or not self.systray_enabled: + self.show_unsubscribed_dialog(account, contact) + + self.add_event(account, jid, 'unsubscribed', contact) + + if helpers.allow_showing_notification(account): + path = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events', + 'unsubscribed.png') + path = gtkgui_helpers.get_path_to_generic_or_avatar(path) + event_type = _('Unsubscribed') + notify.popup(event_type, jid, account, 'unsubscribed', path, + event_type, jid) def handle_event_agent_info_error(self, account, agent): #('AGENT_ERROR_INFO', account, (agent)) @@ -2256,8 +2290,8 @@ class Interface: show_in_roster = notify.get_show_in_roster(event_type, account, jid) show_in_systray = notify.get_show_in_systray(event_type, account, jid) event = gajim.events.create_event(type_, event_args, - show_in_roster = show_in_roster, - show_in_systray = show_in_systray) + show_in_roster=show_in_roster, + show_in_systray=show_in_systray) gajim.events.add_event(account, jid, event) self.roster.show_title() @@ -2389,6 +2423,18 @@ class Interface: data[1], data[3]) gajim.events.remove_events(account, jid, event) self.roster.draw_contact(jid, account) + elif type_ == 'subscription_request': + event = gajim.events.get_first_event(account, jid, type_) + data = event.parameters + dialogs.SubscriptionRequestWindow(jid, data[0], account, data[1]) + gajim.events.remove_events(account, jid, event) + self.roster.draw_contact(jid, account) + elif type_ == 'unsubscribed': + event = gajim.events.get_first_event(account, jid, type_) + contact = event.parameters + self.show_unsubscribed_dialog(account, contact) + gajim.events.remove_events(account, jid, event) + self.roster.draw_contact(jid, account) if w: w.set_active_tab(ctrl) w.window.window.focus() diff --git a/src/notify.py b/src/notify.py index 6b2b7da144491608ee151e9908ebf5c23ff5315e..97deface2a6829f828147c8632bedb477118be6e 100644 --- a/src/notify.py +++ b/src/notify.py @@ -492,6 +492,10 @@ class DesktopNotification: ntype = 'presence.status' elif event_type == _('Connection Failed'): ntype = 'connection.failed' + elif event_type == _('Subscription request'): + ntype = 'subscription.request' + elif event_type == _('Unsubscribed'): + ntype = 'unsubscribed' else: # default failsafe values self.path_to_image = os.path.abspath( diff --git a/src/roster_window.py b/src/roster_window.py index f7be989fbc1ee6f10a4cf42290d27ff55b2d665a..0e819e3ba68767c7b44b7c2abdae9da7423d7661 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -1832,6 +1832,14 @@ class RosterWindow: data[1]) gajim.events.remove_events(account, jid, event) return True + elif event.type_ == 'subscription_request': + dialogs.SubscriptionRequestWindow(jid, data[0], account, data[1]) + gajim.events.remove_events(account, jid, event) + return True + elif event.type_ == 'unsubscribed': + gajim.interface.show_unsubscribed_dialog(account, data) + gajim.events.remove_events(account, jid, event) + return True return False ################################################################################