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