root/branches/gajim_0.11/src/dialogs.py

Revision 7940, 101.6 kB (checked in by asterix, 19 months ago)

merge diff from trunk

  • Property svn:eol-style set to LF
Line 
1# -*- coding: utf-8 -*-
2##      dialogs.py
3##
4## Copyright (C) 2003-2006 Yann Le Boulanger <asterix@lagaule.org>
5## Copyright (C) 2003-2004 Vincent Hanquez <tab@snarc.org>
6## Copyright (C) 2005-2006 Nikos Kouremenos <kourem@gmail.com>
7## Copyright (C) 2005 Dimitur Kirov <dkirov@gmail.com>
8## Copyright (C) 2005-2006 Travis Shirk <travis@pobox.com>
9## Copyright (C) 2005 Norman Rasmussen <norman@rasmussen.co.za>
10##
11## This program is free software; you can redistribute it and/or modify
12## it under the terms of the GNU General Public License as published
13## by the Free Software Foundation; version 2 only.
14##
15## This program is distributed in the hope that it will be useful,
16## but WITHOUT ANY WARRANTY; without even the implied warranty of
17## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18## GNU General Public License for more details.
19##
20
21import gtk
22import gobject
23import os
24
25import gtkgui_helpers
26import vcard
27import conversation_textview
28import message_control
29
30try:
31        import gtkspell
32        HAS_GTK_SPELL = True
33except:
34        HAS_GTK_SPELL = False
35
36# those imports are not used in this file, but in files that 'import dialogs'
37# so they can do dialog.GajimThemesWindow() for example
38from filetransfers_window import FileTransfersWindow
39from gajim_themes_window import GajimThemesWindow
40from advanced import AdvancedConfigurationWindow
41
42from common import gajim
43from common import helpers
44from common.exceptions import GajimGeneralException
45
46class EditGroupsDialog:
47        '''Class for the edit group dialog window'''
48        def __init__(self, list_):
49                '''list_ is a list of (contact, account) tuples'''
50                self.xml = gtkgui_helpers.get_glade('edit_groups_dialog.glade')
51                self.dialog = self.xml.get_widget('edit_groups_dialog')
52                self.dialog.set_transient_for(gajim.interface.roster.window)
53                self.list_ = list_
54                self.changes_made = False
55                self.list = self.xml.get_widget('groups_treeview')
56                if len(list_) == 1:
57                        contact = list_[0][0]
58                        self.xml.get_widget('nickname_label').set_markup(
59                                _("Contact name: <i>%s</i>") % contact.get_shown_name())
60                        self.xml.get_widget('jid_label').set_markup(
61                                _('Jabber ID: <i>%s</i>') % contact.jid)
62                else:
63                        self.xml.get_widget('nickname_label').set_no_show_all(True)
64                        self.xml.get_widget('nickname_label').hide()
65                        self.xml.get_widget('jid_label').set_no_show_all(True)
66                        self.xml.get_widget('jid_label').hide()
67
68                self.xml.signal_autoconnect(self)
69                self.init_list()
70
71        def run(self):
72                self.dialog.show_all()
73                if self.changes_made:
74                        for (contact, account) in self.list_:
75                                gajim.connections[account].update_contact(contact.jid, contact.name,
76                                        contact.groups)
77
78        def on_edit_groups_dialog_response(self, widget, response_id):
79                if response_id == gtk.RESPONSE_CLOSE:
80                        self.dialog.destroy()
81
82        def update_contact(self):
83                for (contact, account) in self.list_:
84                        tag = gajim.contacts.get_metacontacts_tag(account, contact.jid)
85                        if not tag:
86                                gajim.interface.roster.remove_contact(contact, account)
87                                gajim.interface.roster.add_contact_to_roster(contact.jid, account)
88                                gajim.connections[account].update_contact(contact.jid, contact.name,
89                                        contact.groups)
90                                continue
91                        all_jid = gajim.contacts.get_metacontacts_jids(tag)
92                        for _account in all_jid:
93                                if not gajim.interface.roster.regroup and _account != account:
94                                        continue
95                                for _jid in all_jid[_account]:
96                                        c = gajim.contacts.get_first_contact_from_jid(_account, _jid)
97                                        if not c:
98                                                continue
99                                        gajim.interface.roster.remove_contact(c, _account)
100                                        gajim.interface.roster.add_contact_to_roster(_jid, _account)
101                                        gajim.connections[_account].update_contact(_jid, c.name,
102                                                c.groups)
103
104        def remove_group(self, group):
105                '''remove group group from all contacts and all their brothers'''
106                for (contact, account) in self.list_:
107                        tag = gajim.contacts.get_metacontacts_tag(account, contact.jid)
108                        if not tag:
109                                if group in contact.groups:
110                                        contact.groups.remove(group)
111                                continue
112                        all_jid = gajim.contacts.get_metacontacts_jids(tag)
113                        for _account in all_jid:
114                                if not gajim.interface.roster.regroup and _account != account:
115                                        continue
116                                for _jid in all_jid[_account]:
117                                        contacts = gajim.contacts.get_contact(_account, _jid)
118                                        for c in contacts:
119                                                if group in c.groups:
120                                                        c.groups.remove(group)
121
122        def add_group(self, group):
123                '''add group group to all contacts and all their brothers'''
124                for (contact, account) in self.list_:
125                        tag = gajim.contacts.get_metacontacts_tag(account, contact.jid)
126                        if not tag:
127                                if group not in contact.groups:
128                                        contact.groups.append(group)
129                                continue
130                        all_jid = gajim.contacts.get_metacontacts_jids(tag)
131                        for _account in all_jid:
132                                if not gajim.interface.roster.regroup and _account != account:
133                                        continue
134                                for _jid in all_jid[_account]:
135                                        contacts = gajim.contacts.get_contact(_account, _jid)
136                                        for c in contacts:
137                                                if not group in c.groups:
138                                                        c.groups.append(group)
139
140        def on_add_button_clicked(self, widget):
141                group = self.xml.get_widget('group_entry').get_text().decode('utf-8')
142                if not group:
143                        return
144                # Do not allow special groups
145                if group in helpers.special_groups:
146                        return
147                # check if it already exists
148                model = self.list.get_model()
149                iter = model.get_iter_root()
150                while iter:
151                        if model.get_value(iter, 0).decode('utf-8') == group:
152                                return
153                        iter = model.iter_next(iter)
154                self.changes_made = True
155                model.append((group, True, False))
156                self.add_group(group)
157                self.update_contact()
158                self.init_list() # Re-draw list to sort new item
159
160        def group_toggled_cb(self, cell, path):
161                self.changes_made = True
162                model = self.list.get_model()
163                if model[path][2]:
164                        model[path][2] = False
165                        model[path][1] = True
166                else:
167                        model[path][1] = not model[path][1]
168                group = model[path][0].decode('utf-8')
169                if model[path][1]:
170                        self.add_group(group)
171                else:
172                        self.remove_group(group)
173                self.update_contact()
174
175        def init_list(self):
176                store = gtk.ListStore(str, bool, bool)
177                self.list.set_model(store)
178                for column in self.list.get_columns(): # Clear treeview when re-drawing
179                        self.list.remove_column(column)
180                accounts = []
181                # Store groups in a list so we can sort them and the number of contacts in
182                # it
183                groups = {}
184                for (contact, account) in self.list_:
185                        if account not in accounts:
186                                accounts.append(account)
187                                for g in gajim.groups[account].keys():
188                                        if g in groups:
189                                                continue
190                                        groups[g] = 0
191                        for g in contact.groups:
192                                groups[g] += 1
193                group_list = []
194                # Remove special groups if they are empty
195                for group in groups:
196                        if group not in helpers.special_groups or groups[group] > 0:
197                                group_list.append(group)
198                group_list.sort()                       
199                for group in group_list:
200                        iter = store.append()
201                        store.set(iter, 0, group) # Group name
202                        if groups[group] == 0:
203                                store.set(iter, 1, False)
204                        else:
205                                store.set(iter, 1, True)
206                                if groups[group] == len(self.list_):
207                                        # all contacts are in this group
208                                        store.set(iter, 2, False)
209                                else:
210                                        store.set(iter, 2, True)
211                column = gtk.TreeViewColumn(_('Group'))
212                column.set_expand(True)
213                self.list.append_column(column)
214                renderer = gtk.CellRendererText()
215                column.pack_start(renderer)
216                column.set_attributes(renderer, text = 0)
217
218                column = gtk.TreeViewColumn(_('In the group'))
219                column.set_expand(False)
220                self.list.append_column(column)
221                renderer = gtk.CellRendererToggle()
222                column.pack_start(renderer)
223                renderer.set_property('activatable', True)
224                renderer.connect('toggled', self.group_toggled_cb)
225                column.set_attributes(renderer, active = 1, inconsistent = 2)
226
227class PassphraseDialog:
228        '''Class for Passphrase dialog'''
229        def run(self):
230                '''Wait for OK button to be pressed and return passphrase/password'''
231                rep = self.window.run()
232                if rep == gtk.RESPONSE_OK:
233                        passphrase = self.passphrase_entry.get_text().decode('utf-8')
234                else:
235                        passphrase = -1
236                save_passphrase_checkbutton = self.xml.\
237                        get_widget('save_passphrase_checkbutton')
238                self.window.destroy()
239                return passphrase, save_passphrase_checkbutton.get_active()
240
241        def __init__(self, titletext, labeltext, checkbuttontext):
242                self.xml = gtkgui_helpers.get_glade('passphrase_dialog.glade')
243                self.window = self.xml.get_widget('passphrase_dialog')
244                self.passphrase_entry = self.xml.get_widget('passphrase_entry')
245                self.passphrase = -1
246                self.window.set_title(titletext)
247                self.xml.get_widget('message_label').set_text(labeltext)
248                self.xml.get_widget('save_passphrase_checkbutton').set_label(
249                        checkbuttontext)
250                self.xml.signal_autoconnect(self)
251                self.window.show_all()
252
253class ChooseGPGKeyDialog:
254        '''Class for GPG key dialog'''
255        def __init__(self, title_text, prompt_text, secret_keys, selected = None):
256                #list : {keyID: userName, ...}
257                xml = gtkgui_helpers.get_glade('choose_gpg_key_dialog.glade')
258                self.window = xml.get_widget('choose_gpg_key_dialog')
259                self.window.set_title(title_text)
260                self.keys_treeview = xml.get_widget('keys_treeview')
261                prompt_label = xml.get_widget('prompt_label')
262                prompt_label.set_text(prompt_text)
263                model = gtk.ListStore(str, str)
264                model.set_sort_func(1, self.sort_keys)
265                model.set_sort_column_id(1, gtk.SORT_ASCENDING)
266                self.keys_treeview.set_model(model)
267                #columns
268                renderer = gtk.CellRendererText()
269                self.keys_treeview.insert_column_with_attributes(-1, _('KeyID'),
270                        renderer, text = 0)
271                renderer = gtk.CellRendererText()
272                self.keys_treeview.insert_column_with_attributes(-1, _('Contact name'),
273                        renderer, text = 1)
274                self.keys_treeview.set_search_column(1)
275                self.fill_tree(secret_keys, selected)
276                self.window.show_all()
277
278        def sort_keys(self, model, iter1, iter2):
279                value1 = model[iter1][1]
280                value2 = model[iter2][1]
281                if value1 == _('None'):
282                        return -1
283                elif value2 == _('None'):
284                        return 1
285                elif value1 < value2:
286                        return -1
287                return 1
288
289        def run(self):
290                rep = self.window.run()
291                if rep == gtk.RESPONSE_OK:
292                        selection = self.keys_treeview.get_selection()
293                        (model, iter) = selection.get_selected()
294                        keyID = [ model[iter][0].decode('utf-8'),
295                                model[iter][1].decode('utf-8') ]
296                else:
297                        keyID = None
298                self.window.destroy()
299                return keyID
300
301        def fill_tree(self, list, selected):
302                model = self.keys_treeview.get_model()
303                for keyID in list.keys():
304                        iter = model.append((keyID, list[keyID]))
305                        if keyID == selected:
306                                path = model.get_path(iter)
307                                self.keys_treeview.set_cursor(path)
308
309
310class ChangeStatusMessageDialog:
311        def __init__(self, show = None):
312                self.show = show
313                self.xml = gtkgui_helpers.get_glade('change_status_message_dialog.glade')
314                self.window = self.xml.get_widget('change_status_message_dialog')
315                self.window.set_transient_for(gajim.interface.roster.window)
316                if show:
317                        uf_show = helpers.get_uf_show(show)
318                        title_text = _('%s Status Message') % uf_show
319                else:
320                        title_text = _('Status Message')
321                self.window.set_title(title_text)
322
323                message_textview = self.xml.get_widget('message_textview')
324                self.message_buffer = message_textview.get_buffer()
325                self.message_buffer.connect('changed',
326                        self.toggle_sensitiviy_of_save_as_preset)
327                msg = None
328                if show:
329                        msg = gajim.config.get('last_status_msg_' + show)
330                if not msg:
331                        msg = ''
332                msg = helpers.from_one_line(msg)
333                self.message_buffer.set_text(msg)
334
335                # have an empty string selectable, so user can clear msg
336                self.preset_messages_dict = {'': ''}
337                for msg_name in gajim.config.get_per('statusmsg'):
338                        msg_text = gajim.config.get_per('statusmsg', msg_name, 'message')
339                        msg_text = helpers.from_one_line(msg_text)
340                        self.preset_messages_dict[msg_name] = msg_text
341                sorted_keys_list = helpers.get_sorted_keys(self.preset_messages_dict)
342
343                self.message_liststore = gtk.ListStore(str) # msg_name
344                self.message_combobox = self.xml.get_widget('message_combobox')
345                self.message_combobox.set_model(self.message_liststore)
346                cellrenderertext = gtk.CellRendererText()
347                self.message_combobox.pack_start(cellrenderertext, True)
348                self.message_combobox.add_attribute(cellrenderertext, 'text', 0)
349                for msg_name in sorted_keys_list:
350                        self.message_liststore.append((msg_name,))
351                self.xml.signal_autoconnect(self)
352                self.window.show_all()
353
354        def run(self):
355                '''Wait for OK or Cancel button to be pressed and return status messsage
356                (None if users pressed Cancel or x button of WM'''
357                rep = self.window.run()
358                if rep == gtk.RESPONSE_OK:
359                        beg, end = self.message_buffer.get_bounds()
360                        message = self.message_buffer.get_text(beg, end).decode('utf-8')\
361                                .strip()
362                        msg = helpers.to_one_line(message)
363                        if self.show:
364                                gajim.config.set('last_status_msg_' + self.show, msg)
365                else:
366                        message = None # user pressed Cancel button or X wm button
367                self.window.destroy()
368                return message
369
370        def on_message_combobox_changed(self, widget):
371                model = widget.get_model()
372                active = widget.get_active()
373                if active < 0:
374                        return None
375                name = model[active][0].decode('utf-8')
376                self.message_buffer.set_text(self.preset_messages_dict[name])
377
378        def on_change_status_message_dialog_key_press_event(self, widget, event):
379                if event.keyval == gtk.keysyms.Return or \
380                event.keyval == gtk.keysyms.KP_Enter:  # catch CTRL+ENTER
381                        if (event.state & gtk.gdk.CONTROL_MASK):
382                                self.window.response(gtk.RESPONSE_OK)
383
384        def toggle_sensitiviy_of_save_as_preset(self, widget):
385                btn = self.xml.get_widget('save_as_preset_button')
386                if self.message_buffer.get_char_count() == 0:
387                        btn.set_sensitive(False)
388                else:
389                        btn.set_sensitive(True)
390
391        def on_save_as_preset_button_clicked(self, widget):
392                start_iter, finish_iter = self.message_buffer.get_bounds()
393                status_message_to_save_as_preset = self.message_buffer.get_text(
394                        start_iter, finish_iter)
395                dlg = InputDialog(_('Save as Preset Status Message'),
396                        _('Please type a name for this status message'), is_modal = True)
397                response = dlg.get_response()
398                if response == gtk.RESPONSE_OK:
399                        msg_name = dlg.input_entry.get_text()
400                        msg_text = status_message_to_save_as_preset.decode('utf-8')
401                        msg_text_1l = helpers.to_one_line(msg_text)
402                        if not msg_name: # msg_name was ''
403                                msg_name = msg_text_1l
404                        msg_name = msg_name.decode('utf-8')
405                        iter_ = self.message_liststore.append((msg_name,))
406
407                        gajim.config.add_per('statusmsg', msg_name)
408                        gajim.config.set_per('statusmsg', msg_name, 'message', msg_text_1l)
409                        self.preset_messages_dict[msg_name] = msg_text
410                        # select in combobox the one we just saved
411                        self.message_combobox.set_active_iter(iter_)
412
413
414class AddNewContactWindow:
415        '''Class for AddNewContactWindow'''
416        uid_labels = {'jabber': _('Jabber ID:'),
417                'aim': _('AIM Address:'),
418                'gadu-gadu': _('GG Number:'),
419                'icq': _('ICQ Number:'),
420                'msn': _('MSN Address:'),
421                'yahoo': _('Yahoo! Address:')}
422        def __init__(self, account = None, jid = None, user_nick = None,
423        group = None):
424                self.account = account
425                if account == None:
426                        # fill accounts with active accounts
427                        accounts = []
428                        for account in gajim.connections.keys():
429                                if gajim.connections[account].connected > 1:
430                                        accounts.append(account)
431                        if not accounts:
432                                return
433                        if len(accounts) == 1:
434                                self.account = account
435                else:
436                        accounts = [self.account]
437                if self.account:
438                        location = gajim.interface.instances[self.account]
439                else:
440                        location = gajim.interface.instances
441                if location.has_key('add_contact'):
442                        location['add_contact'].window.present()
443                        # An instance is already opened
444                        return
445                location['add_contact'] = self
446                self.xml = gtkgui_helpers.get_glade('add_new_contact_window.glade')
447                self.window = self.xml.get_widget('add_new_contact_window')
448                for w in ('account_combobox', 'account_hbox', 'account_label',
449                'uid_label', 'uid_entry', 'protocol_combobox', 'protocol_jid_combobox',
450                'protocol_hbox', 'nickname_entry', 'message_scrolledwindow',
451                'register_hbox', 'subscription_table', 'add_button',
452                'message_textview', 'connected_label', 'group_comboboxentry',
453                'auto_authorize_checkbutton'):
454                        self.__dict__[w] = self.xml.get_widget(w)
455                if account and len(gajim.connections) >= 2:
456                        prompt_text =\
457_('Please fill in the data of the contact you want to add in account %s') %account
458                else:
459                        prompt_text = _('Please fill in the data of the contact you want to add')
460                self.xml.get_widget('prompt_label').set_text(prompt_text)
461                self.agents = {'jabber': []}
462                # types to which we are not subscribed but account has an agent for it
463                self.available_types = []
464                for acct in accounts:
465                        for j in gajim.contacts.get_jid_list(acct):
466                                contact = gajim.contacts.get_first_contact_from_jid(acct, j)
467                                if gajim.jid_is_transport(j):
468                                        type_ = gajim.get_transport_name_from_jid(j)
469                                        if self.agents.has_key(type_):
470                                                self.agents[type_].append(j)
471                                        else:
472                                                self.agents[type_] = [j]
473                # Now add the one to which we can register
474                for acct in accounts:
475                        for type_ in gajim.connections[account].available_transports:
476                                if type_ in self.agents:
477                                        continue
478                                self.agents[type_] = []
479                                for jid_ in gajim.connections[account].available_transports[type_]:
480                                        self.agents[type_].append(jid_)
481                                self.available_types.append(type_)
482                liststore = gtk.ListStore(str)
483                self.group_comboboxentry.set_model(liststore)
484                liststore = gtk.ListStore(str, str)
485                uf_type = {'jabber': 'Jabber', 'aim': 'AIM', 'gadu-gadu': 'Gadu Gadu',
486                        'icq': 'ICQ', 'msn': 'MSN', 'yahoo': 'Yahoo'}
487                # Jabber as first
488                liststore.append(['Jabber', 'jabber'])
489                for type_ in self.agents:
490                        if type_ == 'jabber':
491                                continue
492                        if type_ in uf_type:
493                                liststore.append([uf_type[type_], type_])
494                        else:
495                                liststore.append([type_, type_])
496                self.protocol_combobox.set_model(liststore)
497                self.protocol_combobox.set_active(0)
498                self.protocol_jid_combobox.set_no_show_all(True)
499                self.protocol_jid_combobox.hide()
500                self.subscription_table.set_no_show_all(True)
501                self.auto_authorize_checkbutton.show()
502                self.message_scrolledwindow.set_no_show_all(True)
503                self.register_hbox.set_no_show_all(True)
504                self.register_hbox.hide()
505                self.connected_label.set_no_show_all(True)
506                self.connected_label.hide()
507                liststore = gtk.ListStore(str)
508                self.protocol_jid_combobox.set_model(liststore)
509                self.xml.signal_autoconnect(self)
510                if jid:
511                        type_ = gajim.get_transport_name_from_jid(jid)
512                        if not type_:
513                                type_ = 'jabber'
514                        if type_ == 'jabber':
515                                self.uid_entry.set_text(jid)
516                        else:
517                                uid, transport = gajim.get_name_and_server_from_jid(jid)
518                                self.uid_entry.set_text(uid.replace('%', '@', 1))
519                        #set protocol_combobox
520                        model = self.protocol_combobox.get_model()
521                        iter = model.get_iter_first()
522                        i = 0
523                        while iter:
524                                if model[iter][1] == type_:
525                                        self.protocol_combobox.set_active(i)
526                                        break
527                                iter = model.iter_next(iter)
528                                i += 1
529
530                        # set protocol_jid_combobox
531                        self.protocol_jid_combobox.set_active(0)
532                        model = self.protocol_jid_combobox.get_model()
533                        iter = model.get_iter_first()
534                        i = 0
535                        while iter:
536                                if model[iter][0] == transport:
537                                        self.protocol_jid_combobox.set_active(i)
538                                        break
539                                iter = model.iter_next(iter)
540                                i += 1
541                        if user_nick:
542                                self.nickname_entry.set_text(user_nick)
543                        self.nickname_entry.grab_focus()
544                else:
545                        self.uid_entry.grab_focus()
546                group_names = []
547                for acct in accounts:
548                        for g in gajim.groups[acct].keys():
549                                if g not in helpers.special_groups and g not in group_names:
550                                        group_names.append(g)
551                group_names.sort()
552                i = 0
553                for g in group_names:
554                        self.group_comboboxentry.append_text(g)
555                        if group == g:
556                                self.group_comboboxentry.set_active(i)
557                        i += 1
558
559                if self.account:
560                        self.account_label.hide()
561                        self.account_hbox.hide()
562                        self.account_label.set_no_show_all(True)
563                        self.account_hbox.set_no_show_all(True)
564                else:
565                        liststore = gtk.ListStore(str, str)
566                        for acct in accounts:
567                                liststore.append([acct, acct])
568                        self.account_combobox.set_model(liststore)
569                        self.account_combobox.set_active(0)
570                self.window.show_all()
571
572        def on_add_new_contact_window_destroy(self, widget):
573                if self.account:
574                        location = gajim.interface.instances[self.account]
575                else:
576                        location = gajim.interface.instances
577                del location['add_contact']
578
579        def on_register_button_clicked(self, widget):
580                jid = self.protocol_jid_combobox.get_active_text().decode('utf-8')
581                gajim.connections[self.account].request_register_agent_info(jid)
582
583        def on_add_new_contact_window_key_press_event(self, widget, event):
584                if event.keyval == gtk.keysyms.Escape: # ESCAPE
585                        self.window.destroy()
586
587        def on_cancel_button_clicked(self, widget):
588                '''When Cancel button is clicked'''
589                self.window.destroy()
590
591        def on_add_button_clicked(self, widget):
592                '''When Subscribe button is clicked'''
593                jid = self.uid_entry.get_text().decode('utf-8')
594                if not jid:
595                        return
596
597                model = self.protocol_combobox.get_model()
598                iter = self.protocol_combobox.get_active_iter()
599                type_ = model[iter][1]
600                if type_ != 'jabber':
601                        transport = self.protocol_jid_combobox.get_active_text().decode(
602                                'utf-8')
603                        jid = jid.replace('@', '%') + '@' + transport
604
605                # check if jid is conform to RFC and stringprep it
606                try:
607                        jid = helpers.parse_jid(jid)
608                except helpers.InvalidFormat, s:
609                        pritext = _('Invalid User ID')
610                        ErrorDialog(pritext, str(s))
611                        return
612
613                # No resource in jid
614                if jid.find('/') >= 0:
615                        pritext = _('Invalid User ID')
616                        ErrorDialog(pritext, _('The user ID must not contain a resource.'))
617                        return
618
619                nickname = self.nickname_entry.get_text().decode('utf-8') or ''
620                # get value of account combobox, if account was not specified
621                if not self.account:
622                        model = self.account_combobox.get_model()
623                        index = self.account_combobox.get_active()
624                        self.account = model[index][1]
625
626                # Check if jid is already in roster
627                if jid in gajim.contacts.get_jid_list(self.account):
628                        c = gajim.contacts.get_first_contact_from_jid(self.account, jid)
629                        if _('Not in Roster') not in c.groups and c.sub in ('both', 'to'):
630                                ErrorDialog(_('Contact already in roster'),
631                                _('This contact is already listed in your roster.'))
632                                return
633
634                if type_ == 'jabber':
635                        message_buffer = self.message_textview.get_buffer()
636                        start_iter = message_buffer.get_start_iter()
637                        end_iter = message_buffer.get_end_iter()
638                        message = message_buffer.get_text(start_iter, end_iter).decode('utf-8')
639                else:
640                        message= ''
641                group = self.group_comboboxentry.child.get_text().decode('utf-8')
642                groups = []
643                if group:
644                        groups = [group]
645                auto_auth = self.auto_authorize_checkbutton.get_active()
646                gajim.interface.roster.req_sub(self, jid, message, self.account,
647                        groups = groups, nickname = nickname, auto_auth = auto_auth)
648                self.window.destroy()
649
650        def on_protocol_combobox_changed(self, widget):
651                model = widget.get_model()
652                iter = widget.get_active_iter()
653                type_ = model[iter][1]
654                model = self.protocol_jid_combobox.get_model()
655                model.clear()
656                if len(self.agents[type_]):
657                        for jid_ in self.agents[type_]:
658                                model.append([jid_])
659                        self.protocol_jid_combobox.set_active(0)
660                if len(self.agents[type_]) > 1:
661                        self.protocol_jid_combobox.set_no_show_all(False)
662                        self.protocol_jid_combobox.show_all()
663                else:
664                        self.protocol_jid_combobox.hide()
665                if type_ in self.uid_labels:
666                        self.uid_label.set_text(self.uid_labels[type_])
667                else:
668                        self.uid_label.set_text(_('User ID:'))
669                if type_ == 'jabber':
670                        self.message_scrolledwindow.show()
671                else:
672                        self.message_scrolledwindow.hide()
673                if type_ in self.available_types:
674                        self.register_hbox.set_no_show_all(False)
675                        self.register_hbox.show_all()
676                        self.auto_authorize_checkbutton.hide()
677                        self.connected_label.hide()
678                        self.subscription_table.hide()
679                        self.add_button.set_sensitive(False)
680                else:
681                        self.register_hbox.hide()
682                        if type_ != 'jabber':
683                                jid = self.protocol_jid_combobox.get_active_text()
684                                contact = gajim.contacts.get_first_contact_from_jid(self.account,
685                                        jid)
686                                if contact.show in ('offline', 'error'):
687                                        self.subscription_table.hide()
688                                        self.connected_label.show()
689                                        self.add_button.set_sensitive(False)
690                                        self.auto_authorize_checkbutton.hide()
691                                        return
692                        self.subscription_table.set_no_show_all(False)
693                        self.subscription_table.show_all()
694                        self.auto_authorize_checkbutton.show()
695                        self.connected_label.hide()
696                        self.add_button.set_sensitive(True)
697
698        def transport_signed_in(self, jid):
699                if self.protocol_jid_combobox.get_active_text() == jid:
700                        self.register_hbox.hide()
701                        self.connected_label.hide()
702                        self.subscription_table.set_no_show_all(False)
703                        self.subscription_table.show_all()
704                        self.add_button.set_sensitive(True)
705
706        def transport_signed_out(self, jid):
707                if self.protocol_jid_combobox.get_active_text() == jid:
708                        self.subscription_table.hide()
709                        self.connected_label.show()
710                        self.add_button.set_sensitive(False)
711
712class AboutDialog:
713        '''Class for about dialog'''
714        def __init__(self):
715                dlg = gtk.AboutDialog()
716                dlg.set_transient_for(gajim.interface.roster.window)
717                dlg.set_name('Gajim')
718                dlg.set_version(gajim.version)
719                s = u'Copyright © 2003-2006 Gajim Team'
720                dlg.set_copyright(s)
721                copying_file_path = None
722                if os.path.isfile(os.path.join(gajim.defs.docdir, 'COPYING')):
723                        copying_file_path = os.path.join(gajim.defs.docdir, 'COPYING')
724                elif os.path.isfile('../COPYING'):
725                        copying_file_path = '../COPYING'
726                if copying_file_path:
727                        text = open(copying_file_path).read()
728                        dlg.set_license(text)
729
730                dlg.set_comments('%s\n%s %s\n%s %s' 
731                        % (_('A GTK+ jabber client'), \
732                        _('GTK+ Version:'), self.tuple2str(gtk.gtk_version), \
733                        _('PyGTK Version:'), self.tuple2str(gtk.pygtk_version)))
734                dlg.set_website('http://www.gajim.org/')
735
736                authors_file_path = None
737                if os.path.isfile(os.path.join(gajim.defs.docdir, 'AUTHORS')):
738                        authors_file_path = os.path.join(gajim.defs.docdir, 'AUTHORS')
739                elif os.path.isfile('../AUTHORS'):
740                        authors_file_path = '../AUTHORS'
741                if authors_file_path:
742                        authors = []
743                        authors_file = open(authors_file_path).read()
744                        authors_file = authors_file.split('\n')
745                        for author in authors_file:
746                                if author == 'CURRENT DEVELOPERS:':
747                                        authors.append(_('Current Developers:'))
748                                elif author == 'PAST DEVELOPERS:':
749                                        authors.append('\n' + _('Past Developers:'))
750                                elif author != '': # Real author line
751                                        authors.append(author)
752
753                        thanks_file_path = None
754                        if os.path.isfile(os.path.join(gajim.defs.docdir, 'THANKS')):
755                                thanks_file_path = os.path.join(gajim.defs.docdir, 'THANKS')
756                        elif os.path.isfile('../THANKS'):
757                                thanks_file_path = '../THANKS'
758                        if thanks_file_path:
759                                authors.append('\n' + _('THANKS:'))
760
761                                text = open(thanks_file_path).read()
762                                text_splitted = text.split('\n')
763                                text = '\n'.join(text_splitted[:-2]) # remove one english sentence
764                                # and add it manually as translatable
765                                text += '\n%s\n' % _('Last but not least, we would like to thank all '
766                                        'the package maintainers.')
767                                authors.append(text)
768
769                        dlg.set_authors(authors)
770
771                if gtk.pygtk_version >= (2, 8, 0) and gtk.gtk_version >= (2, 8, 0):
772                        dlg.props.wrap_license = True
773
774                pixbuf = gtk.gdk.pixbuf_new_from_file(os.path.join(
775                        gajim.DATA_DIR, 'pixmaps', 'gajim_about.png'))                 
776
777                dlg.set_logo(pixbuf)
778                #here you write your name in the form Name FamilyName <someone@somewhere>
779                dlg.set_translator_credits(_('translator-credits'))
780
781                artists = ['Anders Ström', 'Christophe Got', 'Dennis Craven',
782                        'Guillaume Morin', 'Josef Vybíral', 'Membris Khan']
783                dlg.set_artists(artists)
784
785                rep = dlg.run()
786                dlg.destroy()
787
788        def tuple2str(self, tuple_):
789                str_ = ''
790                for num in tuple_:
791                        str_ += str(num) + '.'
792                return str_[0:-1] # remove latest .
793
794class Dialog(gtk.Dialog):
795        def __init__(self, parent, title, buttons, default = None):
796                gtk.Dialog.__init__(self, title, parent, gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_MODAL | gtk.DIALOG_NO_SEPARATOR)
797
798                self.set_border_width(6)
799        Â