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

Revision 1606, 25.8 kB (checked in by asterix, 4 years ago)

when we add a new group, we send that to the server

Line 
1##      dialogs.py
2##
3## Gajim Team:
4##      - Yann Le Boulanger <asterix@lagaule.org>
5##      - Vincent Hanquez <tab@snarc.org>
6##      - Nikos Kouremenos <kourem@gmail.com>
7##
8##      Copyright (C) 2003-2005 Gajim Team
9##
10## This program is free software; you can redistribute it and/or modify
11## it under the terms of the GNU General Public License as published
12## by the Free Software Foundation; version 2 only.
13##
14## This program is distributed in the hope that it will be useful,
15## but WITHOUT ANY WARRANTY; without even the implied warranty of
16## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17## GNU General Public License for more details.
18##
19
20import gtk
21import gtk.glade
22import gobject
23import os
24
25from vcard import Vcard_window
26from advanced import Advanced_configuration_window
27from gajim import User
28from common import gajim
29from common import helpers
30from common import i18n
31
32_ = i18n._
33APP = i18n.APP
34gtk.glade.bindtextdomain (APP, i18n.DIR)
35gtk.glade.textdomain (APP)
36
37GTKGUI_GLADE = 'gtkgui.glade'
38
39class Edit_groups_dialog:
40        '''Class for the edit group dialog window'''
41        def __init__(self, user, account, plugin):
42                self.xml = gtk.glade.XML(GTKGUI_GLADE, 'edit_groups_dialog', APP)
43                self.dialog = self.xml.get_widget('edit_groups_dialog')
44                self.plugin = plugin
45                self.account = account
46                self.user = user
47                self.changes_made = False
48                self.list = self.xml.get_widget('groups_treeview')
49                self.xml.get_widget('nickname_label').set_markup(
50                        _("Contact's name: <i>%s</i>") % user.name)
51                self.xml.get_widget('jid_label').set_markup(
52                        _('JID: <i>%s</i>') % user.jid)
53                self.xml.signal_autoconnect(self)
54                self.dialog.show_all()
55                self.init_list()
56
57        def run(self):
58                self.dialog.run()
59                self.dialog.destroy()
60                if self.changes_made:
61                        gajim.connections[self.account].update_user(self.user.jid,
62                                self.user.name, self.user.groups)
63
64        def update_user(self):
65                self.plugin.roster.remove_user(self.user, self.account)
66                self.plugin.roster.add_user_to_roster(self.user.jid, self.account)
67
68        def on_add_button_clicked(self, widget):
69                group = self.xml.get_widget('group_entry').get_text()
70                if not group:
71                        return
72                # check if it already exists
73                model = self.list.get_model()
74                iter = model.get_iter_root()
75                while iter:
76                        if model.get_value(iter, 0) == group:
77                                return
78                        iter = model.iter_next(iter)
79                self.changes_made = True
80                model.append((group, True))
81                self.user.groups.append(group)
82                self.update_user()
83
84        def group_toggled_cb(self, cell, path):
85                self.changes_made = True
86                model = self.list.get_model()
87                if model[path][1] and len(self.user.groups) == 1: # we try to remove
88                                                                                                                                                  # the last group
89                        Error_dialog(_('A contact must belong at least to one group'))
90                        return
91                model[path][1] = not model[path][1]
92                if model[path][1]:
93                        self.user.groups.append(model[path][0])
94                else:
95                        self.user.groups.remove(model[path][0])
96                self.update_user()
97
98        def init_list(self):
99                store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_BOOLEAN)
100                self.list.set_model(store)
101                for g in self.plugin.roster.groups[self.account].keys():
102                        iter = store.append()
103                        store.set(iter, 0, g)
104                        if g in self.user.groups:
105                                store.set(iter, 1, True)
106                        else:
107                                store.set(iter, 1, False)
108                column = gtk.TreeViewColumn(_('Group'))
109                self.list.append_column(column)
110                renderer = gtk.CellRendererText()
111                column.pack_start(renderer)
112                column.set_attributes(renderer, text = 0)
113               
114                column = gtk.TreeViewColumn(_('In the group'))
115                self.list.append_column(column)
116                renderer = gtk.CellRendererToggle()
117                column.pack_start(renderer)
118                renderer.set_property('activatable', True)
119                renderer.connect('toggled', self.group_toggled_cb)
120                column.set_attributes(renderer, active = 1)
121
122class Passphrase_dialog:
123        '''Class for Passphrase dialog'''
124        def run(self):
125                '''Wait for OK button to be pressed and return passphrase/password'''
126                rep = self.window.run()
127                if rep == gtk.RESPONSE_OK:
128                        passphrase = self.passphrase_entry.get_text()
129                else:
130                        passphrase = -1
131                save_passphrase_checkbutton = self.xml.\
132                        get_widget('save_passphrase_checkbutton')
133                self.window.destroy()
134                return passphrase, save_passphrase_checkbutton.get_active()
135
136        def __init__(self, labeltext, checkbuttontext):
137                self.xml = gtk.glade.XML(GTKGUI_GLADE, 'passphrase_dialog', APP)
138                self.window = self.xml.get_widget('passphrase_dialog')
139                self.passphrase_entry = self.xml.get_widget('passphrase_entry')
140                self.passphrase = -1
141                self.xml.get_widget('message_label').set_text(labeltext)
142                self.xml.get_widget('save_passphrase_checkbutton').set_label(checkbuttontext)
143                self.xml.signal_autoconnect(self)
144                self.window.show_all()
145
146class choose_gpg_key_dialog:
147        '''Class for GPG key dialog'''
148        def run(self):
149                '''Wait for Ok button to be pressed and return the selected key'''
150                rep = self.window.run()
151                if rep == gtk.RESPONSE_OK:
152                        selection = self.keys_treeview.get_selection()
153                        (model, iter) = selection.get_selected()
154                        keyID = [model.get_value(iter, 0), model.get_value(iter, 1)]
155                else:
156                        keyID = -1
157                self.window.destroy()
158                return keyID
159
160        def fill_tree(self, list):
161                model = self.keys_treeview.get_model()
162                for keyID in list.keys():
163                        model.append((keyID, list[keyID]))
164       
165        def __init__(self, secret_keys):
166                #list : {keyID: userName, ...}
167                xml = gtk.glade.XML(GTKGUI_GLADE, 'choose_gpg_key_dialog', APP)
168                self.window = xml.get_widget('choose_gpg_key_dialog')
169                self.keys_treeview = xml.get_widget('keys_treeview')
170                model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
171                self.keys_treeview.set_model(model)
172                #columns
173                renderer = gtk.CellRendererText()
174                self.keys_treeview.insert_column_with_attributes(-1, _('KeyID'),
175                        renderer, text = 0)
176                renderer = gtk.CellRendererText()
177                self.keys_treeview.insert_column_with_attributes(-1, _('User name'),
178                        renderer, text = 1)
179                self.fill_tree(secret_keys)
180
181                self.window.show_all()
182
183class Change_status_message_dialog:
184        def __init__(self, plugin, show):
185                self.xml = gtk.glade.XML(GTKGUI_GLADE, 'change_status_message_dialog', APP)
186                self.window = self.xml.get_widget('change_status_message_dialog')
187                uf_show = helpers.get_uf_show(show)
188                self.window.set_title(_('%s Status Message') %uf_show)
189               
190                message_textview = self.xml.get_widget('message_textview')
191                self.message_buffer = message_textview.get_buffer()
192                self.message_buffer.set_text(gajim.config.get('last_status_msg'))
193                self.values = {'':''}
194                for msg in gajim.config.get_per('statusmsg'):
195                        self.values[msg] = gajim.config.get_per('statusmsg', msg, 'message')
196                liststore = gtk.ListStore(str, str)
197                message_comboboxentry = self.xml.get_widget('message_comboboxentry')
198                message_comboboxentry.set_model(liststore)
199                message_comboboxentry.set_text_column(0)
200                for val in self.values.keys():
201                        message_comboboxentry.append_text(val)
202                self.xml.signal_autoconnect(self)
203                self.window.show_all()
204
205        def run(self):
206                '''Wait for OK button to be pressed and return status messsage'''
207                rep = self.window.run()
208                if rep == gtk.RESPONSE_OK:
209                        beg, end = self.message_buffer.get_bounds()
210                        message = self.message_buffer.get_text(beg, end, 0)
211                        #FIXME: support more than one line
212                        gajim.config.set('last_status_msg', message)
213                else:
214                        message = -1
215                self.window.destroy()
216                return message
217
218        def on_message_comboboxentry_changed(self, widget, data = None):
219                model = widget.get_model()
220                active = widget.get_active()
221                if active < 0:
222                        return None
223                name = model[active][0]
224                self.message_buffer.set_text(self.values[name])
225       
226        def on_change_status_message_dialog_key_press_event(self, widget, event):
227                if event.keyval == gtk.keysyms.Return or \
228                event.keyval == gtk.keysyms.KP_Enter:  # catch CTRL+ENTER
229                        if (event.state & gtk.gdk.CONTROL_MASK):
230                                self.window.response(gtk.RESPONSE_OK)
231
232class Add_new_contact_window:
233        '''Class for Add_new_contact_window'''
234        def __init__(self, plugin, account, jid = None):
235                if gajim.connections[account].connected < 2:
236                        Error_dialog(_('You must be connected to add a contact'))
237                        return
238                self.plugin = plugin
239                self.account = account
240                self.xml = gtk.glade.XML(GTKGUI_GLADE, 'add_new_contact_window', APP)
241                self.window = self.xml.get_widget('add_new_contact_window')
242                self.uid_entry = self.xml.get_widget('uid_entry')
243                self.protocol_combobox = self.xml.get_widget('protocol_combobox')
244                self.jid_entry = self.xml.get_widget('jid_entry')
245                self.nickname_entry = self.xml.get_widget('nickname_entry')
246                self.old_uid_value = ''
247                liststore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
248                liststore.append(['Jabber', ''])
249                self.agents = ['Jabber']
250                jid_agents = []
251                for j in self.plugin.roster.contacts[account]:
252                        user = self.plugin.roster.contacts[account][j][0]
253                        if 'Transports' in user.groups:
254                                jid_agents.append(j)
255                for a in jid_agents:
256                        if a.find('aim') > -1:
257                                name = 'AIM'
258                        elif a.find('icq') > -1:
259                                name = 'ICQ'
260                        elif a.find('msn') > -1:
261                                name = 'MSN'
262                        elif a.find('yahoo') > -1:
263                                name = 'Yahoo!'
264                        else:
265                                name = a
266                        iter = liststore.append([name, a])
267                        self.agents.append(name)
268               
269                self.protocol_combobox.set_model(liststore)
270                self.protocol_combobox.set_active(0)
271                self.fill_jid()
272                if jid:
273                        self.jid_entry.set_text(jid)
274                        jid_splited = jid.split('@')
275                        if jid_splited[1] in jid_agents:
276                                uid = jid_splited[0].replace('%', '@')
277                                self.uid_entry.set_text(uid)
278                                self.protocol_combobox.set_active(jid_agents.index(jid_splited[1]) + 1)
279                        else:
280                                self.uid_entry.set_text(jid)
281                                self.protocol_combobox.set_active(0)
282                        self.set_nickname()
283
284                self.group_comboboxentry = self.xml.get_widget('group_comboboxentry')
285                liststore = gtk.ListStore(str)
286                self.group_comboboxentry.set_model(liststore)
287                for g in self.plugin.roster.groups[account].keys():
288                        if g != 'not in the roster' and g != 'Transports':
289                                self.group_comboboxentry.append_text(g)
290
291                self.xml.signal_autoconnect(self)
292                self.window.show_all()
293
294        def on_add_new_contact_window_key_press_event(self, widget, event):
295                if event.keyval == gtk.keysyms.Escape: # ESCAPE
296                        self.window.destroy()
297
298        def on_cancel_button_clicked(self, widget):
299                '''When Cancel button is clicked'''
300                self.window.destroy()
301
302        def on_subscribe_button_clicked(self, widget):
303                '''When Subscribe button is clicked'''
304                jid = self.jid_entry.get_text()
305                nickname = self.nickname_entry.get_text()
306                if not jid:
307                        return
308                if jid.find('@') < 0:
309                        Error_dialog(_("The contact's name must be something like login@hostname"))
310                        return
311                message_buffer = self.xml.get_widget('message_textview').get_buffer()
312                start_iter = message_buffer.get_start_iter()
313                end_iter = message_buffer.get_end_iter()
314                message = message_buffer.get_text(start_iter, end_iter, 0)
315                group = self.group_comboboxentry.child.get_text()
316                self.plugin.roster.req_sub(self, jid, message, self.account, group,
317                        nickname)
318                if self.xml.get_widget('auto_authorize_checkbutton').get_active():
319                        gajim.connections[self.account].send_authorization(jid)
320                self.window.destroy()
321               
322        def fill_jid(self):
323                model = self.protocol_combobox.get_model()
324                index = self.protocol_combobox.get_active()
325                jid = self.uid_entry.get_text()
326                if index > 0: # it's not jabber but a transport
327                        jid = jid.replace('@', '%')
328                agent = model[index][1]
329                if agent:
330                        jid += '@' + agent
331                self.jid_entry.set_text(jid)
332
333        def on_protocol_combobox_changed(self, widget):
334                self.fill_jid()
335
336        def guess_agent(self):
337                uid = self.uid_entry.get_text()
338                model = self.protocol_combobox.get_model()
339               
340                #If login contains only numbers, it's probably an ICQ number
341                if uid.isdigit():
342                        if 'ICQ' in self.agents:
343                                self.protocol_combobox.set_active(self.agents.index('ICQ'))
344                                return
345
346        def set_nickname(self):
347                uid = self.uid_entry.get_text()
348                nickname = self.nickname_entry.get_text()
349                if nickname == self.old_uid_value:
350                        self.nickname_entry.set_text(uid.split('@')[0])
351                       
352        def on_uid_entry_changed(self, widget):
353                uid = self.uid_entry.get_text()
354                if len(uid) == 0:
355                        self.protocol_combobox.set_sensitive(False)
356                else:
357                        self.protocol_combobox.set_sensitive(True)
358                self.guess_agent()
359                self.set_nickname()
360                self.fill_jid()
361                self.old_uid_value = uid.split('@')[0]
362
363class About_dialog:
364        '''Class for about dialog'''
365        def __init__(self):
366                if gtk.pygtk_version < (2, 6, 0):
367                        Information_dialog(_('Gajim - a GTK+ Jabber client'))
368                        return
369
370                dlg = gtk.AboutDialog()
371                dlg.set_name('Gajim')
372                dlg.set_version(gajim.version)
373                s = u'Copyright \xa9 2003-2005 Gajim Team'
374                dlg.set_copyright(s)
375                text = open('../COPYING').read()
376                dlg.set_license(text)
377
378                dlg.set_comments(_('A GTK jabber client'))
379                dlg.set_website('http://www.gajim.org')
380
381                authors = ['Yann Le Boulanger <asterix@lagaule.org>', 'Vincent Hanquez <tab@snarc.org>', 'Nikos Kouremenos <kourem@gmail.com>', 'Alex Podaras <bigpod@gmail.com>']
382                dlg.set_authors(authors)
383                dlg.set_logo(gtk.gdk.pixbuf_new_from_file(os.path.join(gajim.DATA_DIR,
384                        'pixmaps/logo.png')))
385                dlg.set_translator_credits(_('translator_credits'))
386
387                rep = dlg.run()
388                dlg.destroy()
389
390class Confirmation_dialog:
391        '''Class for confirmation dialog'''
392        def get_response(self):
393                response = self.dialog.run()
394                self.dialog.destroy()
395                return response
396
397        def __init__(self, label):
398                self.dialog = gtk.MessageDialog(None,
399                        gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
400                        gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, label)
401
402class Warning_dialog:
403        '''Class for warning dialog'''
404        def on_response(self, dialog, response_id):
405                dialog.destroy()
406
407        def __init__(self, label):
408                dialog = gtk.MessageDialog(None,
409                        gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
410                        gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, label)
411                dialog.connect('response', self.on_response)
412                dialog.show()
413
414class Information_dialog:
415        '''Class for information dialog'''
416        def on_response(self, dialog, response_id):
417                dialog.destroy()
418
419        def __init__(self, label):
420                dialog = gtk.MessageDialog(None,
421                        gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
422                        gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, label)
423                dialog.connect('response', self.on_response)
424                dialog.show()
425
426class Input_dialog:
427        '''Class for Input dialog'''
428        def __init__(self, title, label_str, input_str = None):
429                xml = gtk.glade.XML(GTKGUI_GLADE, 'input_dialog', APP)
430                self.dialog = xml.get_widget('input_dialog')
431                label = xml.get_widget('label')
432                self.input_entry = xml.get_widget('input_entry')
433                self.dialog.set_title(title)
434                label.set_text(label_str)
435                if input_str:
436                        self.input_entry.set_text(input_str)
437                        self.input_entry.select_region(0, -1) # select all     
438       
439class Error_dialog:
440        '''Class for error dialog'''
441        def on_response(self, dialog, response_id):
442                dialog.destroy()
443
444        def __init__(self, label):
445                dialog = gtk.MessageDialog(None,
446                        gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
447                        gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, label)
448                dialog.connect('response', self.on_response)
449                dialog.show()
450
451class Subscription_request_window:
452        def __init__(self, plugin, jid, text, account):
453                xml = gtk.glade.XML(GTKGUI_GLADE, 'subscription_request_window', APP)
454                self.window = xml.get_widget('subscription_request_window')
455                self.plugin = plugin
456                self.jid = jid
457                self.account = account
458                xml.get_widget('from_label').set_text(
459                        _('Subscription request from %s') % self.jid)
460                xml.get_widget('message_textview').get_buffer().set_text(text)
461                xml.signal_autoconnect(self)
462                self.window.show_all()
463
464        def on_close_button_clicked(self, widget):
465                self.window.destroy()
466               
467        def on_authorize_button_clicked(self, widget):
468                '''accept the request'''
469                gajim.connections[self.account].send_authorization(self.jid)
470                self.window.destroy()
471                if not self.plugin.roster.contacts[self.account].has_key(self.jid):
472                        Add_new_contact_window(self.plugin, self.account, self.jid)
473
474        def on_contact_info_button_clicked(self, widget):
475                '''ask vcard'''
476                if self.plugin.windows[self.account]['infos'].has_key(self.jid):
477                        self.plugin.windows[self.account]['infos'][self.jid].window.present()
478                else:
479                        self.plugin.windows[self.account]['infos'][self.jid] = \
480                                Vcard_window(self.jid, self.plugin, self.account, True)
481                        #remove the publish / retrieve buttons
482                        vcard_xml = self.plugin.windows[self.account]['infos'][self.jid].xml
483                        hbuttonbox = vcard_xml.get_widget('information_hbuttonbox')
484                        children = hbuttonbox.get_children()
485                        hbuttonbox.remove(children[0])
486                        hbuttonbox.remove(children[1])
487                        vcard_xml.get_widget('nickname_label').set_text(self.jid)
488                        gajim.connections[self.account].request_vcard(self.jid)
489       
490        def on_deny_button_clicked(self, widget):
491                '''refuse the request'''
492                gajim.connections[self.account].refuse_authorization(self.jid)
493                self.window.destroy()
494
495class Join_groupchat_window:
496        def __init__(self, plugin, account, server = '', room = ''):
497                self.plugin = plugin
498                self.account = account
499                if gajim.connections[account].connected < 2:
500                        Error_dialog(_('You must be connected to join a groupchat'))
501                        raise RuntimeError, 'You must be connected to join a groupchat'
502
503                self.xml = gtk.glade.XML(GTKGUI_GLADE, 'join_groupchat_window', APP)
504                self.window = self.xml.get_widget('join_groupchat_window')
505                self.xml.get_widget('server_entry').set_text(server)
506                self.xml.get_widget('room_entry').set_text(room)
507                self.xml.get_widget('nickname_entry').set_text(
508                                                self.plugin.nicks[self.account])
509                self.xml.signal_autoconnect(self)
510                self.plugin.windows[account]['join_gc'] = self #now add us to open windows
511                our_jid = gajim.config.get_per('accounts', self.account, 'name') + '@' + \
512                        gajim.config.get_per('accounts', self.account, 'hostname')
513                if len(gajim.connections) > 1:
514                        title = _('Join Groupchat as ') + our_jid
515                else:
516                        title = _('Join Groupchat')
517                self.window.set_title(title)
518
519                self.recently_combobox = self.xml.get_widget('recently_combobox')
520                liststore = gtk.ListStore(str)
521                self.recently_combobox.set_model(liststore)
522                cell = gtk.CellRendererText()
523                self.recently_combobox.pack_start(cell, True)
524                self.recently_combobox.add_attribute(cell, 'text', 0)
525                self.recently_groupchat = gajim.config.get('recently_groupchat').split()
526                for g in self.recently_groupchat:
527                        self.recently_combobox.append_text(g)
528
529                self.window.show_all()
530
531        def on_join_groupchat_window_destroy(self, widget):
532                '''close window'''
533                del self.plugin.windows[self.account]['join_gc'] # remove us from open windows
534
535        def on_join_groupchat_window_key_press_event(self, widget, event):
536                if event.keyval == gtk.keysyms.Escape: # ESCAPE
537                        widget.destroy()
538
539        def on_recently_combobox_changed(self, widget):
540                model = widget.get_model()
541                iter = widget.get_active_iter()
542                gid = model.get_value(iter, 0)
543                self.xml.get_widget('room_entry').set_text(gid.split('@')[0])
544                self.xml.get_widget('server_entry').set_text(gid.split('@')[1])
545
546        def on_cancel_button_clicked(self, widget):
547                '''When Cancel button is clicked'''
548                self.window.destroy()
549
550        def on_join_button_clicked(self, widget):
551                '''When Join button is clicked'''
552                nickname = self.xml.get_widget('nickname_entry').get_text()
553                room = self.xml.get_widget('room_entry').get_text()
554                server = self.xml.get_widget('server_entry').get_text()