1# This file is part of Gajim. 2# 3# Gajim is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published 5# by the Free Software Foundation; version 3 only. 6# 7# Gajim is distributed in the hope that it will be useful, 8# but WITHOUT ANY WARRANTY; without even the implied warranty of 9# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10# GNU General Public License for more details. 11# 12# You should have received a copy of the GNU General Public License 13# along with Gajim. If not, see <http://www.gnu.org/licenses/>. 14 15from gi.repository import Gtk 16 17from gajim.common import app 18from gajim.common import i18n 19from gajim.common.i18n import _ 20 21from .dialogs import InformationDialog 22from .util import get_builder 23 24 25class RosterItemExchangeWindow(Gtk.ApplicationWindow): 26 """ 27 Used when someone sends a Roster Item Exchange suggestion (XEP-0144) 28 """ 29 def __init__(self, account, action, exchange_list, jid_from, 30 message_body=None): 31 Gtk.ApplicationWindow.__init__(self) 32 self.set_application(app.app) 33 self.set_position(Gtk.WindowPosition.CENTER) 34 self.set_show_menubar(False) 35 self.set_title(_('Contact List Exchange')) 36 self.set_name('RosterItemExchangeWindow') 37 38 self.account = account 39 self.action = action 40 self.exchange_list = exchange_list 41 self.message_body = message_body 42 self.jid_from = jid_from 43 44 self._ui = get_builder('roster_item_exchange_window.ui') 45 self.add(self._ui.roster_item_exchange) 46 47 # Set label depending on action 48 if action == 'add': 49 type_label = _('<b>%s</b> would like to add some ' 50 'contacts to your contact list.') % self.jid_from 51 elif action == 'modify': 52 type_label = _('<b>%s</b> would like to modify some ' 53 'contacts in your contact list.') % self.jid_from 54 elif action == 'delete': 55 type_label = _('<b>%s</b> would like to delete some ' 56 'contacts from your contact list.') % self.jid_from 57 self._ui.type_label.set_markup(type_label) 58 if message_body: 59 buffer_ = self._ui.body_textview.get_buffer() 60 buffer_.set_text(self.message_body) 61 else: 62 self._ui.body_scrolledwindow.hide() 63 # Treeview 64 model = Gtk.ListStore(bool, str, str, str, str) 65 self._ui.items_list_treeview.set_model(model) 66 # Columns 67 renderer1 = Gtk.CellRendererToggle() 68 renderer1.set_property('activatable', True) 69 renderer1.connect('toggled', self._toggled) 70 if self.action == 'add': 71 title = _('Add') 72 elif self.action == 'modify': 73 title = _('Modify') 74 elif self.action == 'delete': 75 title = _('Delete') 76 self._ui.items_list_treeview.insert_column_with_attributes( 77 -1, title, renderer1, active=0) 78 renderer2 = Gtk.CellRendererText() 79 self._ui.items_list_treeview.insert_column_with_attributes( 80 -1, _('JID'), renderer2, text=1) 81 renderer3 = Gtk.CellRendererText() 82 self._ui.items_list_treeview.insert_column_with_attributes( 83 -1, _('Name'), renderer3, text=2) 84 renderer4 = Gtk.CellRendererText() 85 self._ui.items_list_treeview.insert_column_with_attributes( 86 -1, _('Groups'), renderer4, text=3) 87 88 # Init contacts 89 self.model = self._ui.items_list_treeview.get_model() 90 self.model.clear() 91 92 if action == 'add': 93 self._add() 94 elif action == 'modify': 95 self._modify() 96 elif action == 'delete': 97 self._delete() 98 99 self._ui.connect_signals(self) 100 101 def _toggled(self, cell, path): 102 model = self._ui.items_list_treeview.get_model() 103 iter_ = model.get_iter(path) 104 model[iter_][0] = not cell.get_active() 105 106 def _add(self): 107 for jid in self.exchange_list: 108 groups = '' 109 is_in_roster = True 110 contact = app.contacts.get_contact_with_highest_priority( 111 self.account, jid) 112 if not contact or _('Not in contact list') in contact.groups: 113 is_in_roster = False 114 name = self.exchange_list[jid][0] 115 num_list = len(self.exchange_list[jid][1]) 116 current = 0 117 for group in self.exchange_list[jid][1]: 118 current += 1 119 if contact and group not in contact.groups: 120 is_in_roster = False 121 if current == num_list: 122 groups = groups + group 123 else: 124 groups = groups + group + ', ' 125 if not is_in_roster: 126 self.show_all() 127 iter_ = self.model.append() 128 self.model.set(iter_, 0, True, 1, jid, 2, name, 3, groups) 129 130 self._ui.accept_button.set_label(_('Add')) 131 132 def _modify(self): 133 for jid in self.exchange_list: 134 groups = '' 135 is_in_roster = True 136 is_right = True 137 contact = app.contacts.get_contact_with_highest_priority( 138 self.account, jid) 139 name = self.exchange_list[jid][0] 140 if not contact: 141 is_in_roster = False 142 is_right = False 143 else: 144 if name != contact.name: 145 is_right = False 146 num_list = len(self.exchange_list[jid][1]) 147 current = 0 148 for group in self.exchange_list[jid][1]: 149 current += 1 150 if contact and group not in contact.groups: 151 is_right = False 152 if current == num_list: 153 groups = groups + group 154 else: 155 groups = groups + group + ', ' 156 if not is_right and is_in_roster: 157 self.show_all() 158 iter_ = self.model.append() 159 self.model.set(iter_, 0, True, 1, jid, 2, name, 3, groups) 160 161 self._ui.accept_button.set_label(_('Modify')) 162 163 def _delete(self): 164 for jid in self.exchange_list: 165 groups = '' 166 is_in_roster = True 167 contact = app.contacts.get_contact_with_highest_priority( 168 self.account, jid) 169 name = self.exchange_list[jid][0] 170 if not contact: 171 is_in_roster = False 172 num_list = len(self.exchange_list[jid][1]) 173 current = 0 174 for group in self.exchange_list[jid][1]: 175 current += 1 176 if current == num_list: 177 groups = groups + group 178 else: 179 groups = groups + group + ', ' 180 if is_in_roster: 181 self.show_all() 182 iter_ = self.model.append() 183 self.model.set(iter_, 0, True, 1, jid, 2, name, 3, groups) 184 185 self._ui.accept_button.set_label(_('Delete')) 186 187 def _on_accept_button_clicked(self, _widget): 188 model = self._ui.items_list_treeview.get_model() 189 iter_ = model.get_iter_first() 190 if self.action == 'add': 191 count = 0 192 while iter_: 193 if model[iter_][0]: 194 count += 1 195 # It is selected 196 message = _('%s suggested me to add you to my ' 197 'contact list.') % self.jid_from 198 # Keep same groups and same nickname 199 groups = model[iter_][3].split(', ') 200 if groups == ['']: 201 groups = [] 202 jid = model[iter_][1] 203 if app.jid_is_transport(self.jid_from): 204 con = app.connections[self.account] 205 con.get_module('Presence').automatically_added.append( 206 jid) 207 app.interface.roster.req_sub( 208 self, jid, message, self.account, groups=groups, 209 nickname=model[iter_][2], auto_auth=True) 210 iter_ = model.iter_next(iter_) 211 InformationDialog(i18n.ngettext('Added %d contact', 212 'Added %d contacts', 213 count, count, count)) 214 elif self.action == 'modify': 215 count = 0 216 while iter_: 217 if model[iter_][0]: 218 count += 1 219 # It is selected 220 jid = model[iter_][1] 221 # Keep same groups and same nickname 222 groups = model[iter_][3].split(', ') 223 if groups == ['']: 224 groups = [] 225 for contact in app.contacts.get_contact(self.account, jid): 226 contact.name = model[iter_][2] 227 con = app.connections[self.account] 228 con.get_module('Roster').update_contact( 229 jid, model[iter_][2], groups) 230 con.get_module('Roster').draw_contact(jid, self.account) 231 # Update opened chats 232 ctrl = app.interface.msg_win_mgr.get_control(jid, 233 self.account) 234 if ctrl: 235 ctrl.update_ui() 236 win = app.interface.msg_win_mgr.get_window(jid, 237 self.account) 238 win.redraw_tab(ctrl) 239 win.show_title() 240 iter_ = model.iter_next(iter_) 241 elif self.action == 'delete': 242 count = 0 243 while iter_: 244 if model[iter_][0]: 245 count += 1 246 # It is selected 247 jid = model[iter_][1] 248 app.connections[self.account].get_module( 249 'Presence').unsubscribe(jid) 250 app.interface.roster.remove_contact(jid, self.account) 251 app.contacts.remove_jid(self.account, jid) 252 iter_ = model.iter_next(iter_) 253 InformationDialog(i18n.ngettext('Removed %d contact', 254 'Removed %d contacts', 255 count, count, count)) 256 self.destroy() 257 258 def _on_cancel_button_clicked(self, _widget): 259 self.destroy() 260