2005-04-18 16:05:30 +02:00
|
|
|
## dialogs.py
|
2004-05-15 18:50:38 +02:00
|
|
|
##
|
|
|
|
## Gajim Team:
|
2005-03-29 18:37:59 +02:00
|
|
|
## - Yann Le Boulanger <asterix@lagaule.org>
|
|
|
|
## - Vincent Hanquez <tab@snarc.org>
|
|
|
|
## - Nikos Kouremenos <kourem@gmail.com>
|
2005-07-30 16:14:10 +02:00
|
|
|
## - Dimitur Kirov <dkirov@gmail.com>
|
2004-05-15 18:50:38 +02:00
|
|
|
##
|
2005-01-07 22:52:38 +01:00
|
|
|
## Copyright (C) 2003-2005 Gajim Team
|
2004-05-15 18:50:38 +02:00
|
|
|
##
|
|
|
|
## This program is free software; you can redistribute it and/or modify
|
|
|
|
## it under the terms of the GNU General Public License as published
|
|
|
|
## by the Free Software Foundation; version 2 only.
|
|
|
|
##
|
|
|
|
## This program is distributed in the hope that it will be useful,
|
|
|
|
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
## GNU General Public License for more details.
|
|
|
|
##
|
|
|
|
|
|
|
|
import gtk
|
2005-03-01 14:46:22 +01:00
|
|
|
import gtk.glade
|
|
|
|
import gobject
|
2005-05-17 19:37:50 +02:00
|
|
|
import os
|
2005-05-20 17:58:23 +02:00
|
|
|
|
2005-07-21 23:42:53 +02:00
|
|
|
import gtkgui_helpers
|
2005-07-21 23:39:47 +02:00
|
|
|
|
2005-06-11 00:45:50 +02:00
|
|
|
from vcard import VcardWindow
|
2005-06-10 00:29:06 +02:00
|
|
|
from gajim_themes_window import GajimThemesWindow
|
2005-06-11 00:45:50 +02:00
|
|
|
from advanced import AdvancedConfigurationWindow
|
2005-06-24 16:28:00 +02:00
|
|
|
from gajim import Contact
|
2005-04-14 09:05:10 +02:00
|
|
|
from common import gajim
|
2004-05-17 01:47:14 +02:00
|
|
|
from common import i18n
|
2005-06-06 13:53:07 +02:00
|
|
|
from common import helpers
|
2005-05-20 17:58:23 +02:00
|
|
|
|
2004-05-17 01:47:14 +02:00
|
|
|
_ = i18n._
|
|
|
|
APP = i18n.APP
|
|
|
|
gtk.glade.bindtextdomain (APP, i18n.DIR)
|
|
|
|
gtk.glade.textdomain (APP)
|
2004-05-15 18:50:38 +02:00
|
|
|
|
2005-04-22 01:20:18 +02:00
|
|
|
GTKGUI_GLADE = 'gtkgui.glade'
|
2004-05-15 18:50:38 +02:00
|
|
|
|
2005-06-10 23:14:16 +02:00
|
|
|
class EditGroupsDialog:
|
2005-04-18 14:17:43 +02:00
|
|
|
'''Class for the edit group dialog window'''
|
2005-03-17 18:41:09 +01:00
|
|
|
def __init__(self, user, account, plugin):
|
|
|
|
self.xml = gtk.glade.XML(GTKGUI_GLADE, 'edit_groups_dialog', APP)
|
|
|
|
self.dialog = self.xml.get_widget('edit_groups_dialog')
|
|
|
|
self.plugin = plugin
|
|
|
|
self.account = account
|
|
|
|
self.user = user
|
2005-04-17 23:31:18 +02:00
|
|
|
self.changes_made = False
|
2005-03-17 18:41:09 +01:00
|
|
|
self.list = self.xml.get_widget('groups_treeview')
|
2005-05-19 19:47:40 +02:00
|
|
|
self.xml.get_widget('nickname_label').set_markup(
|
|
|
|
_("Contact's name: <i>%s</i>") % user.name)
|
|
|
|
self.xml.get_widget('jid_label').set_markup(
|
2005-03-18 01:47:50 +01:00
|
|
|
_('JID: <i>%s</i>') % user.jid)
|
2005-07-23 00:32:45 +02:00
|
|
|
|
2005-03-17 18:41:09 +01:00
|
|
|
self.xml.signal_autoconnect(self)
|
|
|
|
self.init_list()
|
|
|
|
|
|
|
|
def run(self):
|
2005-07-23 00:32:45 +02:00
|
|
|
self.dialog.show_all()
|
2005-04-17 23:31:18 +02:00
|
|
|
if self.changes_made:
|
2005-07-18 16:52:28 +02:00
|
|
|
gajim.connections[self.account].update_contact(self.user.jid,
|
2005-04-17 23:31:18 +02:00
|
|
|
self.user.name, self.user.groups)
|
2005-03-17 18:41:09 +01:00
|
|
|
|
2005-07-23 00:32:45 +02:00
|
|
|
def on_edit_groups_dialog_response(self, widget, response_id):
|
|
|
|
if response_id == gtk.RESPONSE_CLOSE:
|
|
|
|
self.dialog.destroy()
|
|
|
|
|
2005-07-18 16:52:28 +02:00
|
|
|
def update_contact(self):
|
2005-07-21 19:54:58 +02:00
|
|
|
self.plugin.roster.remove_contact(self.user, self.account)
|
2005-07-07 18:38:36 +02:00
|
|
|
self.plugin.roster.add_contact_to_roster(self.user.jid, self.account)
|
2005-08-01 21:33:22 +02:00
|
|
|
gajim.connections[self.account].update_contact(self.user.jid,
|
|
|
|
self.user.name, self.user.groups)
|
2005-03-17 18:41:09 +01:00
|
|
|
|
|
|
|
def on_add_button_clicked(self, widget):
|
|
|
|
group = self.xml.get_widget('group_entry').get_text()
|
|
|
|
if not group:
|
|
|
|
return
|
|
|
|
# check if it already exists
|
|
|
|
model = self.list.get_model()
|
|
|
|
iter = model.get_iter_root()
|
|
|
|
while iter:
|
|
|
|
if model.get_value(iter, 0) == group:
|
|
|
|
return
|
|
|
|
iter = model.iter_next(iter)
|
2005-05-23 19:21:05 +02:00
|
|
|
self.changes_made = True
|
2005-03-17 18:41:09 +01:00
|
|
|
model.append((group, True))
|
|
|
|
self.user.groups.append(group)
|
2005-07-18 16:52:28 +02:00
|
|
|
self.update_contact()
|
2005-03-17 18:41:09 +01:00
|
|
|
|
|
|
|
def group_toggled_cb(self, cell, path):
|
2005-04-17 23:31:18 +02:00
|
|
|
self.changes_made = True
|
2005-03-17 18:41:09 +01:00
|
|
|
model = self.list.get_model()
|
|
|
|
if model[path][1] and len(self.user.groups) == 1: # we try to remove
|
2005-05-18 14:34:20 +02:00
|
|
|
# the last group
|
2005-08-02 00:48:58 +02:00
|
|
|
ErrorDialog(_('Cannot remove last group'),
|
2005-06-07 03:10:24 +02:00
|
|
|
_('At least one contact group must be present.')).get_response()
|
2005-03-17 18:41:09 +01:00
|
|
|
return
|
|
|
|
model[path][1] = not model[path][1]
|
|
|
|
if model[path][1]:
|
|
|
|
self.user.groups.append(model[path][0])
|
|
|
|
else:
|
|
|
|
self.user.groups.remove(model[path][0])
|
2005-07-18 16:52:28 +02:00
|
|
|
self.update_contact()
|
2005-03-17 18:41:09 +01:00
|
|
|
|
|
|
|
def init_list(self):
|
2005-06-18 15:48:43 +02:00
|
|
|
store = gtk.ListStore(str, bool)
|
2005-03-17 18:41:09 +01:00
|
|
|
self.list.set_model(store)
|
2005-07-18 23:08:31 +02:00
|
|
|
for g in gajim.groups[self.account].keys():
|
2005-07-07 19:33:15 +02:00
|
|
|
if g in [_('Transports'), _('not in the roster')]:
|
2005-06-01 22:47:01 +02:00
|
|
|
continue
|
2005-03-17 18:41:09 +01:00
|
|
|
iter = store.append()
|
|
|
|
store.set(iter, 0, g)
|
|
|
|
if g in self.user.groups:
|
|
|
|
store.set(iter, 1, True)
|
|
|
|
else:
|
|
|
|
store.set(iter, 1, False)
|
|
|
|
column = gtk.TreeViewColumn(_('Group'))
|
|
|
|
self.list.append_column(column)
|
|
|
|
renderer = gtk.CellRendererText()
|
|
|
|
column.pack_start(renderer)
|
2005-04-22 01:20:18 +02:00
|
|
|
column.set_attributes(renderer, text = 0)
|
2005-03-17 18:41:09 +01:00
|
|
|
|
|
|
|
column = gtk.TreeViewColumn(_('In the group'))
|
|
|
|
self.list.append_column(column)
|
|
|
|
renderer = gtk.CellRendererToggle()
|
|
|
|
column.pack_start(renderer)
|
|
|
|
renderer.set_property('activatable', True)
|
|
|
|
renderer.connect('toggled', self.group_toggled_cb)
|
2005-04-22 01:20:18 +02:00
|
|
|
column.set_attributes(renderer, active = 1)
|
2005-03-17 18:41:09 +01:00
|
|
|
|
2005-06-10 23:14:16 +02:00
|
|
|
class PassphraseDialog:
|
2005-04-18 14:17:43 +02:00
|
|
|
'''Class for Passphrase dialog'''
|
2004-10-07 16:43:59 +02:00
|
|
|
def run(self):
|
2005-04-18 14:17:43 +02:00
|
|
|
'''Wait for OK button to be pressed and return passphrase/password'''
|
2005-03-02 11:46:12 +01:00
|
|
|
rep = self.window.run()
|
2004-10-07 16:43:59 +02:00
|
|
|
if rep == gtk.RESPONSE_OK:
|
2005-03-02 11:46:12 +01:00
|
|
|
passphrase = self.passphrase_entry.get_text()
|
2004-10-07 16:43:59 +02:00
|
|
|
else:
|
2005-03-02 11:46:12 +01:00
|
|
|
passphrase = -1
|
|
|
|
save_passphrase_checkbutton = self.xml.\
|
|
|
|
get_widget('save_passphrase_checkbutton')
|
|
|
|
self.window.destroy()
|
2005-03-15 11:20:10 +01:00
|
|
|
return passphrase, save_passphrase_checkbutton.get_active()
|
2004-12-02 01:00:57 +01:00
|
|
|
|
2005-06-03 12:28:53 +02:00
|
|
|
def __init__(self, titletext, labeltext, checkbuttontext):
|
2005-03-02 11:46:12 +01:00
|
|
|
self.xml = gtk.glade.XML(GTKGUI_GLADE, 'passphrase_dialog', APP)
|
|
|
|
self.window = self.xml.get_widget('passphrase_dialog')
|
|
|
|
self.passphrase_entry = self.xml.get_widget('passphrase_entry')
|
|
|
|
self.passphrase = -1
|
2005-06-03 12:28:53 +02:00
|
|
|
self.window.set_title(titletext)
|
2005-03-02 13:38:33 +01:00
|
|
|
self.xml.get_widget('message_label').set_text(labeltext)
|
2005-07-23 00:49:03 +02:00
|
|
|
self.xml.get_widget('save_passphrase_checkbutton').set_label(
|
|
|
|
checkbuttontext)
|
2005-03-02 11:46:12 +01:00
|
|
|
self.xml.signal_autoconnect(self)
|
2005-04-04 17:51:29 +02:00
|
|
|
self.window.show_all()
|
2004-05-15 18:50:38 +02:00
|
|
|
|
2005-06-08 15:45:30 +02:00
|
|
|
class ChooseGPGKeyDialog:
|
2005-04-18 14:17:43 +02:00
|
|
|
'''Class for GPG key dialog'''
|
2005-06-08 15:45:30 +02:00
|
|
|
def __init__(self, title_text, prompt_text, secret_keys, selected = None):
|
2004-10-10 20:44:38 +02:00
|
|
|
#list : {keyID: userName, ...}
|
2005-03-02 12:46:51 +01:00
|
|
|
xml = gtk.glade.XML(GTKGUI_GLADE, 'choose_gpg_key_dialog', APP)
|
|
|
|
self.window = xml.get_widget('choose_gpg_key_dialog')
|
2005-06-08 15:45:30 +02:00
|
|
|
self.window.set_title(title_text)
|
2005-03-02 12:46:51 +01:00
|
|
|
self.keys_treeview = xml.get_widget('keys_treeview')
|
2005-06-08 15:45:30 +02:00
|
|
|
prompt_label = xml.get_widget('prompt_label')
|
|
|
|
prompt_label.set_text(prompt_text)
|
2005-06-18 15:48:43 +02:00
|
|
|
model = gtk.ListStore(str, str)
|
2005-03-02 12:46:51 +01:00
|
|
|
self.keys_treeview.set_model(model)
|
2004-10-10 20:44:38 +02:00
|
|
|
#columns
|
|
|
|
renderer = gtk.CellRendererText()
|
2005-05-19 19:47:40 +02:00
|
|
|
self.keys_treeview.insert_column_with_attributes(-1, _('KeyID'),
|
2005-04-22 01:20:18 +02:00
|
|
|
renderer, text = 0)
|
2004-10-10 20:44:38 +02:00
|
|
|
renderer = gtk.CellRendererText()
|
2005-06-24 16:28:00 +02:00
|
|
|
self.keys_treeview.insert_column_with_attributes(-1, _('Contact name'),
|
2005-04-22 01:20:18 +02:00
|
|
|
renderer, text = 1)
|
2005-05-29 23:34:01 +02:00
|
|
|
self.fill_tree(secret_keys, selected)
|
2005-04-04 17:51:29 +02:00
|
|
|
self.window.show_all()
|
|
|
|
|
2005-08-02 18:27:25 +02:00
|
|
|
def run(self):
|
|
|
|
rep = self.window.run()
|
|
|
|
if rep == gtk.RESPONSE_OK:
|
2005-07-23 00:49:03 +02:00
|
|
|
selection = self.keys_treeview.get_selection()
|
|
|
|
(model, iter) = selection.get_selected()
|
2005-08-02 18:27:25 +02:00
|
|
|
keyID = [ model[iter][0], model[iter][1] ]
|
|
|
|
else:
|
|
|
|
keyID = None
|
2005-07-23 00:49:03 +02:00
|
|
|
self.window.destroy()
|
2005-08-02 18:27:25 +02:00
|
|
|
return keyID
|
|
|
|
|
2005-07-23 00:49:03 +02:00
|
|
|
def fill_tree(self, list, selected):
|
|
|
|
model = self.keys_treeview.get_model()
|
|
|
|
for keyID in list.keys():
|
|
|
|
iter = model.append((keyID, list[keyID]))
|
|
|
|
if keyID == selected:
|
|
|
|
path = model.get_path(iter)
|
|
|
|
self.keys_treeview.set_cursor(path)
|
|
|
|
|
|
|
|
|
2005-06-10 23:14:16 +02:00
|
|
|
class ChangeStatusMessageDialog:
|
2005-05-20 18:31:52 +02:00
|
|
|
def __init__(self, plugin, show):
|
2005-06-30 21:23:41 +02:00
|
|
|
self.show = show
|
2005-04-04 18:46:35 +02:00
|
|
|
self.xml = gtk.glade.XML(GTKGUI_GLADE, 'change_status_message_dialog', APP)
|
|
|
|
self.window = self.xml.get_widget('change_status_message_dialog')
|
2005-05-20 18:31:52 +02:00
|
|
|
uf_show = helpers.get_uf_show(show)
|
2005-06-03 17:38:06 +02:00
|
|
|
self.window.set_title(_('%s Status Message') % uf_show)
|
2005-05-12 11:14:31 +02:00
|
|
|
|
2005-04-04 18:46:35 +02:00
|
|
|
message_textview = self.xml.get_widget('message_textview')
|
|
|
|
self.message_buffer = message_textview.get_buffer()
|
2005-06-30 21:23:41 +02:00
|
|
|
msg = gajim.config.get('last_status_msg_' + show)
|
|
|
|
if not msg:
|
|
|
|
msg = ''
|
2005-07-02 14:43:36 +02:00
|
|
|
msg = helpers.from_one_line(msg)
|
2005-06-30 21:23:41 +02:00
|
|
|
self.message_buffer.set_text(msg)
|
2005-06-06 13:53:07 +02:00
|
|
|
self.values = {'':''} # have an empty string selectable, so user can clear msg
|
2005-04-16 19:36:27 +02:00
|
|
|
for msg in gajim.config.get_per('statusmsg'):
|
|
|
|
self.values[msg] = gajim.config.get_per('statusmsg', msg, 'message')
|
2005-06-06 13:53:07 +02:00
|
|
|
sorted_keys_list = helpers.get_sorted_keys(self.values)
|
2005-04-04 18:46:35 +02:00
|
|
|
liststore = gtk.ListStore(str, str)
|
|
|
|
message_comboboxentry = self.xml.get_widget('message_comboboxentry')
|
|
|
|
message_comboboxentry.set_model(liststore)
|
|
|
|
message_comboboxentry.set_text_column(0)
|
2005-07-21 22:55:00 +02:00
|
|
|
message_comboboxentry.child.set_property('editable', False)
|
2005-06-06 13:53:07 +02:00
|
|
|
for val in sorted_keys_list:
|
2005-04-04 18:46:35 +02:00
|
|
|
message_comboboxentry.append_text(val)
|
|
|
|
self.xml.signal_autoconnect(self)
|
|
|
|
self.window.show_all()
|
|
|
|
|
2004-05-15 18:50:38 +02:00
|
|
|
def run(self):
|
2005-05-19 19:47:40 +02:00
|
|
|
'''Wait for OK button to be pressed and return status messsage'''
|
2005-03-02 13:46:37 +01:00
|
|
|
rep = self.window.run()
|
2004-05-15 18:50:38 +02:00
|
|
|
if rep == gtk.RESPONSE_OK:
|
2005-03-02 13:46:37 +01:00
|
|
|
beg, end = self.message_buffer.get_bounds()
|
2005-06-04 20:06:03 +02:00
|
|
|
message = self.message_buffer.get_text(beg, end, 0).strip()
|
2005-07-02 14:43:36 +02:00
|
|
|
msg = helpers.to_one_line(message)
|
|
|
|
gajim.config.set('last_status_msg_' + self.show, msg)
|
2004-05-15 18:50:38 +02:00
|
|
|
else:
|
2005-03-02 13:46:37 +01:00
|
|
|
message = -1
|
|
|
|
self.window.destroy()
|
|
|
|
return message
|
2004-10-26 00:02:16 +02:00
|
|
|
|
2005-04-22 01:20:18 +02:00
|
|
|
def on_message_comboboxentry_changed(self, widget, data = None):
|
2004-10-26 00:02:16 +02:00
|
|
|
model = widget.get_model()
|
|
|
|
active = widget.get_active()
|
|
|
|
if active < 0:
|
|
|
|
return None
|
|
|
|
name = model[active][0]
|
2005-03-02 13:46:37 +01:00
|
|
|
self.message_buffer.set_text(self.values[name])
|
2004-05-15 18:50:38 +02:00
|
|
|
|
2005-03-16 02:27:37 +01:00
|
|
|
def on_change_status_message_dialog_key_press_event(self, widget, event):
|
2005-03-18 02:28:59 +01:00
|
|
|
if event.keyval == gtk.keysyms.Return or \
|
2005-03-18 02:25:11 +01:00
|
|
|
event.keyval == gtk.keysyms.KP_Enter: # catch CTRL+ENTER
|
2005-01-08 15:40:08 +01:00
|
|
|
if (event.state & gtk.gdk.CONTROL_MASK):
|
2005-03-02 13:46:37 +01:00
|
|
|
self.window.response(gtk.RESPONSE_OK)
|
2005-04-04 18:46:35 +02:00
|
|
|
|
2005-06-10 23:14:16 +02:00
|
|
|
class AddNewContactWindow:
|
|
|
|
'''Class for AddNewContactWindow'''
|
2005-04-22 01:20:18 +02:00
|
|
|
def __init__(self, plugin, account, jid = None):
|
2004-10-26 00:02:16 +02:00
|
|
|
self.plugin = plugin
|
2005-04-04 18:46:35 +02:00
|
|
|
self.account = account
|
|
|
|
self.xml = gtk.glade.XML(GTKGUI_GLADE, 'add_new_contact_window', APP)
|
|
|
|
self.window = self.xml.get_widget('add_new_contact_window')
|
2005-05-04 19:44:49 +02:00
|
|
|
self.uid_entry = self.xml.get_widget('uid_entry')
|
|
|
|
self.protocol_combobox = self.xml.get_widget('protocol_combobox')
|
|
|
|
self.jid_entry = self.xml.get_widget('jid_entry')
|
|
|
|
self.nickname_entry = self.xml.get_widget('nickname_entry')
|
2005-06-13 15:19:54 +02:00
|
|
|
if len(gajim.connections) >= 2:
|
|
|
|
prompt_text =\
|
|
|
|
_('Please fill in the data of the contact you want to add in account %s') %account
|
|
|
|
else:
|
|
|
|
prompt_text = _('Please fill in the data of the contact you want to add')
|
|
|
|
self.xml.get_widget('prompt_label').set_text(prompt_text)
|
2005-04-04 18:46:35 +02:00
|
|
|
self.old_uid_value = ''
|
2005-06-13 15:19:54 +02:00
|
|
|
liststore = gtk.ListStore(str, str)
|
2005-04-04 18:46:35 +02:00
|
|
|
liststore.append(['Jabber', ''])
|
|
|
|
self.agents = ['Jabber']
|
|
|
|
jid_agents = []
|
2005-07-18 23:08:31 +02:00
|
|
|
for j in gajim.contacts[account]:
|
|
|
|
user = gajim.contacts[account][j][0]
|
2005-07-07 19:25:04 +02:00
|
|
|
if _('Transports') in user.groups and user.show != 'offline' and \
|
2005-05-25 13:00:41 +02:00
|
|
|
user.show != 'error':
|
2005-04-04 18:46:35 +02:00
|
|
|
jid_agents.append(j)
|
|
|
|
for a in jid_agents:
|
|
|
|
if a.find('aim') > -1:
|
|
|
|
name = 'AIM'
|
|
|
|
elif a.find('icq') > -1:
|
|
|
|
name = 'ICQ'
|
|
|
|
elif a.find('msn') > -1:
|
|
|
|
name = 'MSN'
|
|
|
|
elif a.find('yahoo') > -1:
|
|
|
|
name = 'Yahoo!'
|
|
|
|
else:
|
|
|
|
name = a
|
|
|
|
iter = liststore.append([name, a])
|
|
|
|
self.agents.append(name)
|
2005-05-04 19:44:49 +02:00
|
|
|
|
|
|
|
self.protocol_combobox.set_model(liststore)
|
|
|
|
self.protocol_combobox.set_active(0)
|
2005-04-04 18:46:35 +02:00
|
|
|
self.fill_jid()
|
|
|
|
if jid:
|
2005-05-04 19:44:49 +02:00
|
|
|
self.jid_entry.set_text(jid)
|
2005-04-04 18:46:35 +02:00
|
|
|
jid_splited = jid.split('@')
|
|
|
|
if jid_splited[1] in jid_agents:
|
2005-04-25 22:41:29 +02:00
|
|
|
uid = jid_splited[0].replace('%', '@')
|
2005-05-04 19:44:49 +02:00
|
|
|
self.uid_entry.set_text(uid)
|
|
|
|
self.protocol_combobox.set_active(jid_agents.index(jid_splited[1]) + 1)
|
2005-04-25 22:41:29 +02:00
|
|
|
else:
|
2005-05-04 19:44:49 +02:00
|
|
|
self.uid_entry.set_text(jid)
|
|
|
|
self.protocol_combobox.set_active(0)
|
2005-04-25 22:41:29 +02:00
|
|
|
self.set_nickname()
|
2005-04-04 18:46:35 +02:00
|
|
|
|
|
|
|
self.group_comboboxentry = self.xml.get_widget('group_comboboxentry')
|
|
|
|
liststore = gtk.ListStore(str)
|
|
|
|
self.group_comboboxentry.set_model(liststore)
|
2005-07-18 23:08:31 +02:00
|
|
|
for g in gajim.groups[account].keys():
|
2005-07-07 19:33:15 +02:00
|
|
|
if g != _('not in the roster') and g != _('Transports'):
|
2005-04-04 18:46:35 +02:00
|
|
|
self.group_comboboxentry.append_text(g)
|
|
|
|
|
2005-03-02 13:46:37 +01:00
|
|
|
self.xml.signal_autoconnect(self)
|
2005-04-04 17:51:29 +02:00
|
|
|
self.window.show_all()
|
2004-05-15 18:50:38 +02:00
|
|
|
|
2005-04-28 15:01:47 +02:00
|
|
|
def on_add_new_contact_window_key_press_event(self, widget, event):
|
|
|
|
if event.keyval == gtk.keysyms.Escape: # ESCAPE
|
|
|
|
self.window.destroy()
|
|
|
|
|
2005-03-01 00:44:52 +01:00
|
|
|
def on_cancel_button_clicked(self, widget):
|
2005-04-18 14:17:43 +02:00
|
|
|
'''When Cancel button is clicked'''
|
2005-04-12 17:30:09 +02:00
|
|
|
self.window.destroy()
|
2004-05-15 18:50:38 +02:00
|
|
|
|
2005-03-01 00:44:52 +01:00
|
|
|
def on_subscribe_button_clicked(self, widget):
|
2005-04-18 14:17:43 +02:00
|
|
|
'''When Subscribe button is clicked'''
|
2005-05-04 19:44:49 +02:00
|
|
|
jid = self.jid_entry.get_text()
|
|
|
|
nickname = self.nickname_entry.get_text()
|
2005-03-01 00:44:52 +01:00
|
|
|
if not jid:
|
2004-11-18 20:22:33 +01:00
|
|
|
return
|
2005-03-01 00:44:52 +01:00
|
|
|
if jid.find('@') < 0:
|
2005-06-10 23:14:16 +02:00
|
|
|
ErrorDialog(_("Invalid user name"),
|
2005-06-24 16:28:00 +02:00
|
|
|
_('Contact names must be of the form "user@servername".')).get_response()
|
2004-11-18 20:22:33 +01:00
|
|
|
return
|
2005-03-01 00:44:52 +01:00
|
|
|
message_buffer = self.xml.get_widget('message_textview').get_buffer()
|
|
|
|
start_iter = message_buffer.get_start_iter()
|
|
|
|
end_iter = message_buffer.get_end_iter()
|
|
|
|
message = message_buffer.get_text(start_iter, end_iter, 0)
|
2005-03-27 23:35:55 +02:00
|
|
|
group = self.group_comboboxentry.child.get_text()
|
2005-06-15 09:38:58 +02:00
|
|
|
self.plugin.roster.req_sub(self, jid, message, self.account,
|
|
|
|
group = group, pseudo = nickname)
|
2005-03-01 00:44:52 +01:00
|
|
|
if self.xml.get_widget('auto_authorize_checkbutton').get_active():
|
2005-04-14 11:38:08 +02:00
|
|
|
gajim.connections[self.account].send_authorization(jid)
|
2005-04-12 17:30:09 +02:00
|
|
|
self.window.destroy()
|
2004-05-15 18:50:38 +02:00
|
|
|
|
2005-03-01 00:44:52 +01:00
|
|
|
def fill_jid(self):
|
2005-05-04 19:44:49 +02:00
|
|
|
model = self.protocol_combobox.get_model()
|
|
|
|
index = self.protocol_combobox.get_active()
|
2005-06-04 15:33:38 +02:00
|
|
|
jid = self.uid_entry.get_text().strip()
|
2005-05-04 19:44:49 +02:00
|
|
|
if index > 0: # it's not jabber but a transport
|
2005-03-01 00:44:52 +01:00
|
|
|
jid = jid.replace('@', '%')
|
2005-02-03 23:21:55 +01:00
|
|
|
agent = model[index][1]
|
|
|
|
if agent:
|
2005-03-01 00:44:52 +01:00
|
|
|
jid += '@' + agent
|
2005-05-04 19:44:49 +02:00
|
|
|
self.jid_entry.set_text(jid)
|
2005-02-03 23:21:55 +01:00
|
|
|
|
2005-03-23 14:25:48 +01:00
|
|
|
def on_protocol_combobox_changed(self, widget):
|
2005-03-01 00:44:52 +01:00
|
|
|
self.fill_jid()
|
2005-02-03 23:21:55 +01:00
|
|
|
|
|
|
|
def guess_agent(self):
|
2005-05-04 19:44:49 +02:00
|
|
|
uid = self.uid_entry.get_text()
|
|
|
|
model = self.protocol_combobox.get_model()
|
2005-02-03 23:21:55 +01:00
|
|
|
|
|
|
|
#If login contains only numbers, it's probably an ICQ number
|
2005-05-04 19:44:49 +02:00
|
|
|
if uid.isdigit():
|
2005-02-03 23:21:55 +01:00
|
|
|
if 'ICQ' in self.agents:
|
2005-05-04 19:44:49 +02:00
|
|
|
self.protocol_combobox.set_active(self.agents.index('ICQ'))
|
2005-02-03 23:21:55 +01:00
|
|
|
return
|
2005-02-04 08:58:40 +01:00
|
|
|
|
2005-03-01 00:44:52 +01:00
|
|
|
def set_nickname(self):
|
2005-05-04 19:44:49 +02:00
|
|
|
uid = self.uid_entry.get_text()
|
|
|
|
nickname = self.nickname_entry.get_text()
|
2005-03-01 00:44:52 +01:00
|
|
|
if nickname == self.old_uid_value:
|
2005-05-04 19:44:49 +02:00
|
|
|
self.nickname_entry.set_text(uid.split('@')[0])
|
2005-02-03 23:21:55 +01:00
|
|
|
|
2005-03-01 00:44:52 +01:00
|
|
|
def on_uid_entry_changed(self, widget):
|
2005-05-04 19:44:49 +02:00
|
|
|
uid = self.uid_entry.get_text()
|
2005-02-04 08:58:40 +01:00
|
|
|
self.guess_agent()
|
2005-03-01 00:44:52 +01:00
|
|
|
self.set_nickname()
|
|
|
|
self.fill_jid()
|
|
|
|
self.old_uid_value = uid.split('@')[0]
|
2004-05-15 18:50:38 +02:00
|
|
|
|
2005-06-10 01:28:07 +02:00
|
|
|
class AboutDialog:
|
2005-04-18 14:17:43 +02:00
|
|
|
'''Class for about dialog'''
|
2005-04-04 18:46:35 +02:00
|
|
|
def __init__(self):
|
2005-06-04 00:22:29 +02:00
|
|
|
if gtk.pygtk_version < (2, 6, 0) or gtk.gtk_version < (2, 6, 0):
|
2005-06-10 23:14:16 +02:00
|
|
|
InformationDialog(_('Gajim - a GTK+ Jabber client'),
|
2005-06-10 01:28:07 +02:00
|
|
|
_('Version %s') % gajim.version).get_response()
|
2005-03-14 21:21:49 +01:00
|
|
|
return
|
2005-04-04 18:46:35 +02:00
|
|
|
|
2005-03-09 22:29:20 +01:00
|
|
|
dlg = gtk.AboutDialog()
|
|
|
|
dlg.set_name('Gajim')
|
2005-04-16 19:03:21 +02:00
|
|
|
dlg.set_version(gajim.version)
|
2005-03-16 03:16:29 +01:00
|
|
|
s = u'Copyright \xa9 2003-2005 Gajim Team'
|
|
|
|
dlg.set_copyright(s)
|
2005-04-16 19:03:21 +02:00
|
|
|
text = open('../COPYING').read()
|
2005-03-16 03:16:29 +01:00
|
|
|
dlg.set_license(text)
|
2005-03-09 22:29:20 +01:00
|
|
|
|
2005-03-22 20:02:27 +01:00
|
|
|
dlg.set_comments(_('A GTK jabber client'))
|
2005-03-09 22:29:20 +01:00
|
|
|
dlg.set_website('http://www.gajim.org')
|
2005-03-18 01:47:50 +01:00
|
|
|
|
2005-07-07 20:23:43 +02:00
|
|
|
authors = ['Yann Le Boulanger <asterix@lagaule.org>', 'Vincent Hanquez <tab@snarc.org>', 'Nikos Kouremenos <kourem@gmail.com>', 'Alex Podaras <bigpod@gmail.com>', 'Gajim patchers']
|
2005-03-16 03:16:29 +01:00
|
|
|
dlg.set_authors(authors)
|
2005-06-03 13:41:02 +02:00
|
|
|
|
2005-06-10 01:28:07 +02:00
|
|
|
pixbuf = gtk.gdk.pixbuf_new_from_file(os.path.join(gajim.DATA_DIR, 'pixmaps/gajim_about.png'))
|
2005-06-03 13:41:02 +02:00
|
|
|
|
|
|
|
dlg.set_logo(pixbuf)
|
2005-03-16 03:16:29 +01:00
|
|
|
dlg.set_translator_credits(_('translator_credits'))
|
2005-03-09 22:29:20 +01:00
|
|
|
|
2005-05-12 02:00:40 +02:00
|
|
|
rep = dlg.run()
|
2005-03-13 00:48:08 +01:00
|
|
|
dlg.destroy()
|
2004-05-15 18:50:38 +02:00
|
|
|
|
2005-06-07 03:10:24 +02:00
|
|
|
class Dialog(gtk.Dialog):
|
2005-06-12 19:36:27 +02:00
|
|
|
def __init__(self, parent, title, buttons, default = None):
|
|
|
|
gtk.Dialog.__init__(self, title, parent, gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_MODAL | gtk.DIALOG_NO_SEPARATOR)
|
2005-06-07 03:10:24 +02:00
|
|
|
|
2005-06-12 19:36:27 +02:00
|
|
|
self.set_border_width(6)
|
|
|
|
self.vbox.set_spacing(12)
|
|
|
|
self.set_resizable(False)
|
2005-06-07 03:10:24 +02:00
|
|
|
|
2005-06-12 19:36:27 +02:00
|
|
|
for stock, response in buttons:
|
|
|
|
self.add_button(stock, response)
|
2005-06-07 03:10:24 +02:00
|
|
|
|
2005-06-12 19:36:27 +02:00
|
|
|
if default is not None:
|
|
|
|
self.set_default_response(default)
|
|
|
|
else:
|
|
|
|
self.set_default_response(buttons[-1][1])
|
2005-06-07 03:10:24 +02:00
|
|
|
|
2005-06-12 19:36:27 +02:00
|
|
|
def get_button(self, index):
|
|
|
|
buttons = self.action_area.get_children()
|
|
|
|
return index < len(buttons) and buttons[index] or None
|
2005-06-07 03:10:24 +02:00
|
|
|
|
2005-06-10 00:29:06 +02:00
|
|
|
|
2005-06-07 03:10:24 +02:00
|
|
|
class HigDialog(Dialog):
|
2005-06-12 19:36:27 +02:00
|
|
|
def __init__(self, parent, pritext, sectext, stockimage, buttons, default = None):
|
|
|
|
"""GNOME higified version of the Dialog object. Inherit
|
|
|
|
from here if possible when you need a new dialog."""
|
|
|
|
Dialog.__init__(self, parent, "", buttons, default)
|
|
|
|
|
|
|
|
# hbox separating dialog image and contents
|
|
|
|
hbox = gtk.HBox()
|
|
|
|
hbox.set_spacing(12)
|
|
|
|
hbox.set_border_width(6)
|
|
|
|
self.vbox.pack_start(hbox)
|
|
|
|
|
|
|
|
# set up image
|
|
|
|
if stockimage is not None:
|
|
|
|
image = gtk.Image()
|
|
|
|
image.set_from_stock(stockimage, gtk.ICON_SIZE_DIALOG)
|
|
|
|
image.set_alignment(0.5, 0)
|
|
|
|
hbox.pack_start(image, False, False)
|
|
|
|
|
|
|
|
# set up main content area
|
|
|
|
self.contents = gtk.VBox()
|
|
|
|
self.contents.set_spacing(10)
|
|
|
|
hbox.pack_start(self.contents)
|
|
|
|
|
|
|
|
label = gtk.Label()
|
|
|
|
label.set_markup("<span size=\"larger\" weight=\"bold\">" + pritext + "</span>\n\n" + sectext)
|
|
|
|
label.set_line_wrap(True)
|
|
|
|
label.set_alignment(0, 0)
|
|
|
|
label.set_selectable(True)
|
|
|
|
self.contents.pack_start(label)
|
|
|
|
|
|
|
|
def get_response(self):
|
|
|
|
self.show_all()
|
|
|
|
response = gtk.Dialog.run(self)
|
|
|
|
self.destroy()
|
|
|
|
return response
|
2005-06-07 03:10:24 +02:00
|
|
|
|
2005-06-10 23:14:16 +02:00
|
|
|
class ConfirmationDialog(HigDialog):
|
2005-06-12 18:56:26 +02:00
|
|
|
"""HIG compliant confirmation dialog."""
|
|
|
|
def __init__(self, pritext, sectext=''):
|
|
|
|
HigDialog.__init__(self, None, pritext, sectext,
|
|
|
|
gtk.STOCK_DIALOG_WARNING, [ [gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL],
|
|
|
|
[ gtk.STOCK_OK, gtk.RESPONSE_OK ] ])
|
2005-07-29 19:18:51 +02:00
|
|
|
|
|
|
|
class ConfirmationDialogCheck(ConfirmationDialog):
|
|
|
|
'''HIG compliant confirmation dialog with checkbutton.'''
|
|
|
|
def __init__(self, pritext, sectext='', checktext = ''):
|
|
|
|
HigDialog.__init__(self, None, pritext, sectext,
|
2005-07-30 02:27:58 +02:00
|
|
|
gtk.STOCK_DIALOG_WARNING, [ [gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL] ])
|
2005-08-03 01:03:21 +02:00
|
|
|
|
2005-07-30 02:27:58 +02:00
|
|
|
# add ok button manually, because we need to focus on it
|
2005-08-03 01:03:21 +02:00
|
|
|
ok_button = self.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
|
2005-07-29 19:18:51 +02:00
|
|
|
self.checkbutton = gtk.CheckButton(checktext)
|
|
|
|
self.vbox.pack_start(self.checkbutton, expand=False, fill=True)
|
2005-07-30 02:27:58 +02:00
|
|
|
ok_button.grab_focus()
|
2005-07-29 19:18:51 +02:00
|
|
|
|
|
|
|
def is_checked(self):
|
|
|
|
''' Get active state of the checkbutton '''
|
|
|
|
return self.checkbutton.get_active()
|
|
|
|
|
2005-06-10 23:14:16 +02:00
|
|
|
class WarningDialog(HigDialog):
|
2005-06-12 19:36:27 +02:00
|
|
|
def __init__(self, pritext, sectext=''):
|
|
|
|
"""HIG compliant warning dialog."""
|
|
|
|
HigDialog.__init__(
|
|
|
|
self, None, pritext, sectext, gtk.STOCK_DIALOG_WARNING,
|
|
|
|
[ [ gtk.STOCK_OK, gtk.RESPONSE_OK ] ]
|
|
|
|
)
|
2005-06-07 03:10:24 +02:00
|
|
|
|
2005-06-10 23:14:16 +02:00
|
|
|
class InformationDialog(HigDialog):
|
2005-06-12 19:36:27 +02:00
|
|
|
def __init__(self, pritext, sectext=''):
|
|
|
|
"""HIG compliant info dialog."""
|
|
|
|
HigDialog.__init__(
|
|
|
|
self, None, pritext, sectext, gtk.STOCK_DIALOG_INFO,
|
|
|
|
[ [ gtk.STOCK_OK, gtk.RESPONSE_OK ] ]
|
|
|
|
)
|
2005-07-31 21:21:11 +02:00
|
|
|
class BaseTooltip:
|
|
|
|
''' Base Tooltip . Usage:
|
|
|
|
tooltip = BaseTooltip()
|
|
|
|
....
|
|
|
|
tooltip.show_tooltip('', window_postions, widget_postions)
|
|
|
|
....
|
|
|
|
if tooltip.timeout != 0:
|
|
|
|
tooltip.hide_tooltip()
|
|
|
|
'''
|
|
|
|
def __init__(self):
|
2005-07-08 01:37:04 +02:00
|
|
|
self.timeout = 0
|
|
|
|
self.prefered_position = [0, 0]
|
2005-07-31 21:21:11 +02:00
|
|
|
self.win = None
|
|
|
|
self.id = None
|
|
|
|
|
|
|
|
def populate(self, data):
|
2005-08-02 01:17:53 +02:00
|
|
|
''' this method must be overriden by all extenders '''
|
2005-07-30 21:19:48 +02:00
|
|
|
self.create_window()
|
2005-07-31 21:21:11 +02:00
|
|
|
self.win.add(gtk.Label(data))
|
2005-07-18 13:03:53 +02:00
|
|
|
|
2005-07-30 21:19:48 +02:00
|
|
|
def create_window(self):
|
|
|
|
''' create a popup window each time tooltip is requested '''
|
|
|
|
self.win = gtk.Window(gtk.WINDOW_POPUP)
|
2005-07-31 21:21:11 +02:00
|
|
|
self.win.set_border_width(3)
|
2005-07-30 21:19:48 +02:00
|
|
|
self.win.set_resizable(False)
|
|
|
|
self.win.set_name('gtk-tooltips')
|
2005-07-31 21:21:11 +02:00
|
|
|
|
2005-07-07 23:27:53 +02:00
|
|
|
|
2005-07-30 21:19:48 +02:00
|
|
|
self.win.set_events(gtk.gdk.POINTER_MOTION_MASK)
|
|
|
|
self.win.connect_after('expose_event', self.expose)
|
|
|
|
self.win.connect('size-request', self.size_request)
|
|
|
|
self.win.connect('motion-notify-event', self.motion_notify_event)
|
2005-07-20 19:50:50 +02:00
|
|
|
|
2005-07-07 23:27:53 +02:00
|
|
|
def motion_notify_event(self, widget, event):
|
|
|
|
self.hide_tooltip()
|
|
|
|
|
|
|
|
def size_request(self, widget, requisition):
|
2005-07-30 21:19:48 +02:00
|
|
|
screen = self.win.get_screen()
|
2005-07-07 23:27:53 +02:00
|
|
|
half_width = requisition.width / 2 + 1
|
|
|
|
if self.prefered_position[0] < half_width:
|
|
|
|
self.prefered_position[0] = 0
|
|
|
|
elif self.prefered_position[0] + requisition.width > screen.get_width() \
|
|
|
|
+ half_width:
|
|
|
|
self.prefered_position[0] = screen.get_width() - requisition.width
|
|
|
|
else:
|
|
|
|
self.prefered_position[0] -= half_width
|
2005-07-31 21:21:11 +02:00
|
|
|
screen.get_height()
|
2005-07-07 23:27:53 +02:00
|
|
|
if self.prefered_position[1] + requisition.height > screen.get_height():
|
2005-07-31 21:21:11 +02:00
|
|
|
# flip tooltip up
|
|
|
|
self.prefered_position[1] -= requisition.height + self.widget_height + 8
|
2005-07-07 23:27:53 +02:00
|
|
|
if self.prefered_position[1] < 0:
|
|
|
|
self.prefered_position[1] = 0
|
2005-07-30 21:19:48 +02:00
|
|
|
self.win.move(self.prefered_position[0], self.prefered_position[1])
|
2005-07-07 23:27:53 +02:00
|
|
|
|
|
|
|
def expose(self, widget, event):
|
2005-07-30 21:19:48 +02:00
|
|
|
style = self.win.get_style()
|
|
|
|
size = self.win.get_size()
|
|
|
|
style.paint_flat_box(self.win.window, gtk.STATE_NORMAL, gtk.SHADOW_OUT, None,
|
|
|
|
self.win, 'tooltip', 0, 0, -1, 1)
|
|
|
|
style.paint_flat_box(self.win.window, gtk.STATE_NORMAL, gtk.SHADOW_OUT, None,
|
|
|
|
self.win, 'tooltip', 0, size[1] - 1, -1, 1)
|
|
|
|
style.paint_flat_box(self.win.window, gtk.STATE_NORMAL, gtk.SHADOW_OUT, None,
|
|
|
|
self.win, 'tooltip', 0, 0, 1, -1)
|
|
|
|
style.paint_flat_box(self.win.window, gtk.STATE_NORMAL, gtk.SHADOW_OUT, None,
|
|
|
|
self.win, 'tooltip', size[0] - 1, 0, 1, -1)
|
2005-07-07 23:27:53 +02:00
|
|
|
return True
|
|
|
|
|
2005-07-31 21:21:11 +02:00
|
|
|
def show_tooltip(self, data, widget_pos, win_size):
|
|
|
|
self.populate(data)
|
|
|
|
new_x = win_size[0] + widget_pos[0]
|
|
|
|
new_y = win_size[1] + widget_pos[1] + 4
|
2005-07-07 23:27:53 +02:00
|
|
|
self.prefered_position = [new_x, new_y]
|
2005-07-31 21:21:11 +02:00
|
|
|
self.widget_height = widget_pos[1]
|
2005-07-30 21:19:48 +02:00
|
|
|
self.win.ensure_style()
|
|
|
|
self.win.show_all()
|
2005-07-07 23:27:53 +02:00
|
|
|
|
|
|
|
def hide_tooltip(self):
|
|
|
|
if(self.timeout > 0):
|
|
|
|
gobject.source_remove(self.timeout)
|
2005-07-18 11:06:54 +02:00
|
|
|
self.timeout = 0
|
2005-07-31 21:21:11 +02:00
|
|
|
if self.win:
|
|
|
|
self.win.destroy()
|
|
|
|
self.win = None
|
|
|
|
self.id = None
|
|
|
|
|
|
|
|
class StatusTable:
|
|
|
|
''' Contains methods for creating status table. This
|
|
|
|
is used in Roster and NotificationArea tooltips '''
|
|
|
|
def __init__(self):
|
|
|
|
self.current_row = 1
|
|
|
|
self.table = None
|
|
|
|
self.text_lable = None
|
|
|
|
|
|
|
|
def create_table(self):
|
|
|
|
self.table = gtk.Table(3, 1)
|
|
|
|
self.table.set_property('column-spacing', 6)
|
|
|
|
self.text_lable = gtk.Label()
|
|
|
|
self.text_lable.set_line_wrap(True)
|
|
|
|
self.text_lable.set_alignment(0, 0)
|
|
|
|
self.text_lable.set_selectable(False)
|
|
|
|
self.table.attach(self.text_lable, 1, 4, 1, 2)
|
|
|
|
|
|
|
|
def get_status_info(self, resource, priority, show, status):
|
2005-08-02 01:17:53 +02:00
|
|
|
str_status = resource + ' (' + str(priority) + ')'
|
2005-07-31 21:21:11 +02:00
|
|
|
if status:
|
|
|
|
status = status.strip()
|
|
|
|
if status != '':
|
2005-08-01 18:14:35 +02:00
|
|
|
if gtk.gtk_version < (2, 6, 0) or gtk.pygtk_version < (2, 6, 0):
|
|
|
|
# FIXME: check and do the same if we have more than one \n
|
2005-08-08 17:44:22 +02:00
|
|
|
status = gtkgui_helpers.reduce_chars_newlines(status, 50, 1)
|
|
|
|
else:
|
|
|
|
status = gtkgui_helpers.reduce_chars_newlines(status, 0, 1)
|
2005-07-31 21:21:11 +02:00
|
|
|
str_status += ' - ' + status
|
|
|
|
return gtkgui_helpers.escape_for_pango_markup(str_status)
|
2005-07-31 23:16:20 +02:00
|
|
|
|
2005-07-31 21:21:11 +02:00
|
|
|
def add_status_row(self, file_path, show, str_status):
|
2005-07-20 19:50:50 +02:00
|
|
|
''' appends a new row with status icon to the table '''
|
|
|
|
self.current_row += 1
|
|
|
|
state_file = show.replace(' ', '_')
|
|
|
|
files = []
|
|
|
|
files.append(os.path.join(file_path, state_file + '.png'))
|
|
|
|
files.append(os.path.join(file_path, state_file + '.gif'))
|
|
|
|
image = gtk.Image()
|
|
|
|
image.set_from_pixbuf(None)
|
2005-07-31 21:21:11 +02:00
|
|
|
spacer = gtk.Label(' ')
|
2005-07-20 19:50:50 +02:00
|
|
|
for file in files:
|
|
|
|
if os.path.exists(file):
|
|
|
|
image.set_from_file(file)
|
|
|
|
break
|
2005-07-21 16:09:17 +02:00
|
|
|
image.set_alignment(0.01, 1)
|
2005-07-20 19:50:50 +02:00
|
|
|
self.table.attach(spacer, 1, 2, self.current_row,
|
|
|
|
self.current_row + 1, 0, 0, 0, 0)
|
|
|
|
self.table.attach(image,2,3,self.current_row,
|
|
|
|
self.current_row + 1, 0, 0, 3, 0)
|
2005-07-21 16:09:17 +02:00
|
|
|
image.set_alignment(0.01, 1)
|
2005-07-31 21:21:11 +02:00
|
|
|
status_label = gtk.Label()
|
|
|
|
status_label.set_markup(str_status)
|
2005-07-20 19:50:50 +02:00
|
|
|
status_label.set_alignment(00, 0)
|
2005-07-21 23:39:47 +02:00
|
|
|
self.table.attach(status_label, 3, 4, self.current_row,
|
|
|
|
self.current_row + 1, gtk.EXPAND | gtk.FILL, 0, 0, 0)
|
2005-07-31 21:21:11 +02:00
|
|
|
|
|
|
|
class NotificationAreaTooltip(BaseTooltip, StatusTable):
|
|
|
|
''' Tooltip that is shown in the notification area '''
|
|
|
|
def __init__(self, plugin):
|
|
|
|
self.plugin = plugin
|
|
|
|
BaseTooltip.__init__(self)
|
|
|
|
StatusTable.__init__(self)
|
2005-08-02 01:17:53 +02:00
|
|
|
|
2005-07-31 21:21:11 +02:00
|
|
|
def populate(self, data):
|
|
|
|
self.create_window()
|
|
|
|
self.create_table()
|
|
|
|
self.hbox = gtk.HBox()
|
|
|
|
self.table.set_property('column-spacing', 1)
|
|
|
|
text, single_line, accounts = '', '', []
|
|
|
|
if gajim.contacts:
|
|
|
|
for account in gajim.contacts.keys():
|
|
|
|
status_idx = gajim.connections[account].connected
|
|
|
|
# uncomment the following to hide offline accounts
|
|
|
|
# if status_idx == 0: continue
|
|
|
|
from common.connection import STATUS_LIST
|
|
|
|
status = STATUS_LIST[status_idx]
|
|
|
|
message = gajim.connections[account].status
|
|
|
|
single_line = helpers.get_uf_show(status)
|
|
|
|
if message is None:
|
|
|
|
message = ''
|
|
|
|
else:
|
|
|
|
message = message.strip()
|
|
|
|
if message != '':
|
|
|
|
single_line += ': ' + message
|
2005-08-01 17:54:26 +02:00
|
|
|
# the other solution is to hide offline accounts
|
|
|
|
elif status == 'offline':
|
|
|
|
message = helpers.get_uf_show(status)
|
2005-08-02 01:17:53 +02:00
|
|
|
accounts.append({'name': account, 'status_line': single_line,
|
|
|
|
'show': status, 'message': message})
|
2005-07-31 21:21:11 +02:00
|
|
|
unread_messages_no = self.plugin.roster.nb_unread
|
|
|
|
if unread_messages_no > 1:
|
|
|
|
text = _('Gajim - %s unread messages') % unread_messages_no
|
|
|
|
elif unread_messages_no == 1:
|
|
|
|
text = _('Gajim - 1 unread message')
|
|
|
|
elif len(accounts) > 1:
|
|
|
|
text = _('Gajim')
|
|
|
|
self.current_row = 1
|
|
|
|
self.table.resize(2,1)
|
|
|
|
iconset = gajim.config.get('iconset')
|
|
|
|
if not iconset:
|
|
|
|
iconset = 'sun'
|
|
|
|
file_path = os.path.join(gajim.DATA_DIR, 'iconsets', iconset, '16x16')
|
|
|
|
for acct in accounts:
|
2005-08-08 17:44:22 +02:00
|
|
|
message = gtkgui_helpers.reduce_chars_newlines(acct['message'], 50, 1)
|
|
|
|
message = gtkgui_helpers.escape_for_pango_markup(message)
|
2005-07-31 21:21:11 +02:00
|
|
|
self.add_status_row(file_path, acct['show'], '<span weight="bold">' +
|
|
|
|
gtkgui_helpers.escape_for_pango_markup(acct['name']) + '</span>'
|
2005-08-08 17:44:22 +02:00
|
|
|
+ ' - ' + message)
|
2005-07-31 21:21:11 +02:00
|
|
|
|
|
|
|
elif len(accounts) == 1:
|
2005-08-08 17:44:22 +02:00
|
|
|
message = gtkgui_helpers.reduce_chars_newlines(accounts[0]['status_line'],
|
|
|
|
50, 1)
|
|
|
|
message = gtkgui_helpers.escape_for_pango_markup(message)
|
|
|
|
text = _('Gajim - %s') % message
|
2005-07-31 21:21:11 +02:00
|
|
|
else:
|
|
|
|
text = _('Gajim - %s') % helpers.get_uf_show('offline')
|
|
|
|
self.text_lable.set_markup(text)
|
|
|
|
self.hbox.add(self.table)
|
|
|
|
self.win.add(self.hbox)
|
2005-08-07 14:06:24 +02:00
|
|
|
|
|
|
|
class FileTransfersTooltip(BaseTooltip):
|
|
|
|
''' Tooltip that is shown in the notification area '''
|
|
|
|
def __init__(self):
|
|
|
|
self.text_lable = gtk.Label()
|
|
|
|
self.text_lable.set_line_wrap(True)
|
|
|
|
self.text_lable.set_alignment(0, 0)
|
|
|
|
self.text_lable.set_selectable(False)
|
|
|
|
BaseTooltip.__init__(self)
|
|
|
|
|
|
|
|
def populate(self, file_props):
|
|
|
|
self.create_window()
|
|
|
|
self.hbox = gtk.HBox()
|
|
|
|
text = '<b>' + _('Name: ') + '</b>'
|
|
|
|
name = file_props['name']
|
|
|
|
if not name and file_props['file-name']:
|
|
|
|
if os.path.exists(file_props['file-name']):
|
|
|
|
(path, name) = os.path.split(file_props['file-name'])
|
|
|
|
text += gtkgui_helpers.escape_for_pango_markup(name)
|
|
|
|
text += '\n<b>' + _('Type: ') + '</b>'
|
|
|
|
if file_props['type'] == 'r':
|
|
|
|
text += _('Download')
|
|
|
|
else:
|
|
|
|
text += _('Upload')
|
|
|
|
if file_props['type'] == 'r':
|
|
|
|
text += '\n<b>' + _('Sender: ') + '</b>'
|
2005-08-09 19:15:45 +02:00
|
|
|
sender = str(file_props['sender']).split('/')[0]
|
|
|
|
name = gajim.get_first_contact_instance_from_jid(
|
|
|
|
file_props['tt_account'], sender).name
|
2005-08-07 14:06:24 +02:00
|
|
|
else:
|
|
|
|
text += '\n<b>' + _('Recipient: ') + '</b>'
|
|
|
|
receiver = file_props['receiver']
|
|
|
|
if hasattr(receiver, 'name'):
|
|
|
|
receiver = receiver.name
|
2005-08-09 19:15:45 +02:00
|
|
|
receiver = receiver.split('/')[0]
|
2005-08-09 21:00:19 +02:00
|
|
|
if receiver.find('@') == -1:
|
|
|
|
name = receiver
|
|
|
|
else:
|
|
|
|
name = gajim.get_first_contact_instance_from_jid(
|
2005-08-09 19:15:45 +02:00
|
|
|
file_props['tt_account'], receiver).name
|
|
|
|
text += gtkgui_helpers.escape_for_pango_markup(name)
|
2005-08-07 14:06:24 +02:00
|
|
|
text += '\n<b>' + _('Size: ') + '</b>'
|
2005-08-09 19:27:27 +02:00
|
|
|
text += helpers.convert_bytes(file_props['size'])
|
2005-08-07 14:06:24 +02:00
|
|
|
text += '\n<b>' + _('Transfered: ') + '</b>'
|
|
|
|
transfered_len = 0
|
|
|
|
if file_props.has_key('received-len'):
|
|
|
|
transfered_len = file_props['received-len']
|
2005-08-09 19:27:27 +02:00
|
|
|
text += helpers.convert_bytes(transfered_len)
|
2005-08-07 14:06:24 +02:00
|
|
|
text += '\n<b>' + _('Status: ') + '</b>'
|
2005-08-07 23:01:21 +02:00
|
|
|
status = ''
|
2005-08-07 14:06:24 +02:00
|
|
|
if not file_props.has_key('started') or not file_props['started']:
|
2005-08-07 23:01:21 +02:00
|
|
|
status = _('not started')
|
2005-08-07 14:06:24 +02:00
|
|
|
elif file_props.has_key('connected'):
|
|
|
|
if file_props['connected'] == False:
|
|
|
|
if file_props['completed']:
|
2005-08-07 23:01:21 +02:00
|
|
|
status = _('completed')
|
2005-08-07 14:06:24 +02:00
|
|
|
else:
|
|
|
|
if file_props.has_key('stopped') and \
|
|
|
|
file_props['stopped'] == True:
|
2005-08-07 23:01:21 +02:00
|
|
|
status = _('stopped')
|
2005-08-07 14:06:24 +02:00
|
|
|
elif file_props.has_key('paused') and \
|
|
|
|
file_props['paused'] == True:
|
2005-08-07 23:01:21 +02:00
|
|
|
status = _('paused')
|
2005-08-07 14:06:24 +02:00
|
|
|
elif file_props.has_key('stalled') and \
|
|
|
|
file_props['stalled'] == True:
|
2005-08-07 23:01:21 +02:00
|
|
|
status = _('stalled')
|
2005-08-09 19:15:45 +02:00
|
|
|
elif file_props['completed']:
|
|
|
|
status = _('completed')
|
2005-08-07 14:06:24 +02:00
|
|
|
else:
|
2005-08-07 23:01:21 +02:00
|
|
|
status = _('transfering')
|
2005-08-07 15:23:17 +02:00
|
|
|
else:
|
2005-08-07 23:01:21 +02:00
|
|
|
status = _('stopped')
|
2005-08-07 15:23:17 +02:00
|
|
|
|
2005-08-07 14:06:24 +02:00
|
|
|
text += status
|
|
|
|
self.text_lable.set_markup(text)
|
|
|
|
self.hbox.add(self.text_lable)
|
|
|
|
self.win.add(self.hbox)
|
2005-07-31 21:21:11 +02:00
|
|
|
|
|
|
|
class RosterTooltip(BaseTooltip, StatusTable):
|
|
|
|
''' Tooltip that is shown in the roster treeview '''
|
|
|
|
def __init__(self, plugin):
|
|
|
|
self.account = None
|
|
|
|
self.plugin = plugin
|
|
|
|
|
|
|
|
self.image = gtk.Image()
|
|
|
|
self.image.set_alignment(0.5, 0.025)
|
|
|
|
BaseTooltip.__init__(self)
|
|
|
|
StatusTable.__init__(self)
|
2005-07-21 16:09:17 +02:00
|
|
|
|
2005-07-15 20:13:54 +02:00
|
|
|
def populate(self, contacts):
|
2005-07-08 02:04:59 +02:00
|
|
|
if not contacts or len(contacts) == 0:
|
|
|
|
return
|
2005-07-30 21:19:48 +02:00
|
|
|
self.create_window()
|
2005-07-31 21:21:11 +02:00
|
|
|
self.hbox = gtk.HBox()
|
|
|
|
self.hbox.set_homogeneous(False)
|
|
|
|
self.create_table()
|
2005-08-09 19:58:50 +02:00
|
|
|
# primary contact
|
2005-08-09 21:15:59 +02:00
|
|
|
prim_contact = gajim.get_highest_prio_contact_from_contacts(contacts)
|
2005-08-09 19:58:50 +02:00
|
|
|
|
2005-07-09 01:43:11 +02:00
|
|
|
# try to find the image for the contact status
|
|
|
|
state_file = prim_contact.show.replace(' ', '_')
|
2005-07-15 20:13:54 +02:00
|
|
|
transport = self.plugin.roster.get_transport_name_by_jid(prim_contact.jid)
|
|
|
|
if transport:
|
2005-07-19 17:05:01 +02:00
|
|
|
file_path = os.path.join(gajim.DATA_DIR, 'iconsets', 'transports',
|
|
|
|
transport , '16x16')
|
2005-07-15 20:13:54 +02:00
|
|
|
else:
|
|
|
|
iconset = gajim.config.get('iconset')
|
|
|
|
if not iconset:
|
|
|
|
iconset = 'sun'
|
|
|
|
file_path = os.path.join(gajim.DATA_DIR, 'iconsets', iconset, '16x16')
|
|
|
|
|
2005-07-09 01:43:11 +02:00
|
|
|
files = []
|
2005-07-20 19:50:50 +02:00
|
|
|
file_full_path = os.path.join(file_path, state_file)
|
|
|
|
files.append(file_full_path + '.png')
|
|
|
|
files.append(file_full_path + '.gif')
|
2005-07-15 20:13:54 +02:00
|
|
|
self.image.set_from_pixbuf(None)
|
2005-07-09 01:43:11 +02:00
|
|
|
for file in files:
|
|
|
|
if os.path.exists(file):
|
|
|
|
self.image.set_from_file(file)
|
|
|
|
break
|
2005-07-31 21:21:11 +02:00
|
|
|
|
2005-07-08 02:04:59 +02:00
|
|
|
info = '<span size="large" weight="bold">' + prim_contact.jid + '</span>'
|
2005-07-07 23:27:53 +02:00
|
|
|
info += '\n<span weight="bold">' + _('Name: ') + '</span>' + \
|
2005-07-21 23:39:47 +02:00
|
|
|
gtkgui_helpers.escape_for_pango_markup(prim_contact.name)
|
2005-07-08 01:37:04 +02:00
|
|
|
info += '\n<span weight="bold">' + _('Subscription: ') + '</span>' + \
|
2005-07-21 23:39:47 +02:00
|
|
|
gtkgui_helpers.escape_for_pango_markup(prim_contact.sub)
|
2005-07-08 02:04:59 +02:00
|
|
|
|
|
|
|
if prim_contact.keyID:
|
2005-07-07 23:27:53 +02:00
|
|
|
keyID = None
|
2005-07-08 02:04:59 +02:00
|
|
|
if len(prim_contact.keyID) == 8:
|
|
|
|
keyID = prim_contact.keyID
|
|
|
|
elif len(prim_contact.keyID) == 16:
|
|
|
|
keyID = prim_contact.keyID[8:]
|
2005-07-07 23:27:53 +02:00
|
|
|
if keyID:
|
2005-07-08 02:04:59 +02:00
|
|
|
info += '\n<span weight="bold">' + _('OpenPGP: ') + \
|
2005-07-21 23:39:47 +02:00
|
|
|
'</span>' + gtkgui_helpers.escape_for_pango_markup(keyID)
|
2005-07-08 02:04:59 +02:00
|
|
|
|
2005-07-19 17:05:01 +02:00
|
|
|
single_line, resource_str, multiple_resource= '', '', False
|
2005-07-20 19:50:50 +02:00
|
|
|
num_resources = 0
|
2005-07-08 02:04:59 +02:00
|
|
|
for contact in contacts:
|
|
|
|
if contact.resource:
|
2005-07-20 19:50:50 +02:00
|
|
|
num_resources += 1
|
|
|
|
if num_resources > 1:
|
|
|
|
self.current_row = 1
|
|
|
|
self.table.resize(2,1)
|
2005-07-19 17:05:01 +02:00
|
|
|
info += '\n<span weight="bold">' + _('Status: ') + '</span>'
|
2005-07-20 19:50:50 +02:00
|
|
|
for contact in contacts:
|
|
|
|
if contact.resource:
|
2005-07-31 21:21:11 +02:00
|
|
|
status_line = self.get_status_info(contact.resource, contact.priority,
|
2005-07-20 19:50:50 +02:00
|
|
|
contact.show, contact.status)
|
2005-07-31 21:21:11 +02:00
|
|
|
self.add_status_row(file_path, contact.show, status_line)
|
2005-07-20 19:50:50 +02:00
|
|
|
|
|
|
|
else: # only one resource
|
|
|
|
if contact.resource:
|
|
|
|
info += '\n<span weight="bold">' + _('Resource: ') + \
|
2005-07-22 02:01:05 +02:00
|
|
|
'</span>' + gtkgui_helpers.escape_for_pango_markup(
|
|
|
|
contact.resource) + ' (' + str(contact.priority) + ')'
|
2005-07-20 19:50:50 +02:00
|
|
|
if contact.show:
|
|
|
|
info += '\n<span weight="bold">' + _('Status: ') + \
|
|
|
|
'</span>' + helpers.get_uf_show(contact.show)
|
2005-07-21 15:11:35 +02:00
|
|
|
if contact.status:
|
|
|
|
status = contact.status.strip()
|
|
|
|
if status != '':
|
2005-07-21 16:09:17 +02:00
|
|
|
# escape markup entities. Is it posible to have markup in status?
|
2005-07-21 23:39:47 +02:00
|
|
|
info += ' - ' + gtkgui_helpers.escape_for_pango_markup(status)
|
2005-07-21 16:09:17 +02:00
|
|
|
|
2005-07-31 21:21:11 +02:00
|
|
|
self.text_lable.set_markup(info)
|
|
|
|
self.hbox.pack_start(self.image, False, False)
|
|
|
|
self.hbox.pack_start(self.table, True, True)
|
|
|
|
self.win.add(self.hbox)
|
2005-07-07 23:27:53 +02:00
|
|
|
|
2005-06-10 23:14:16 +02:00
|
|
|
class InputDialog:
|
2005-05-14 03:29:53 +02:00
|
|
|
'''Class for Input dialog'''
|
2005-07-25 09:47:05 +02:00
|
|
|
def __init__(self, title, label_str, input_str = None, is_modal = True, ok_handler = None):
|
2005-05-14 03:29:53 +02:00
|
|
|
xml = gtk.glade.XML(GTKGUI_GLADE, 'input_dialog', APP)
|
|
|
|
self.dialog = xml.get_widget('input_dialog')
|
|
|
|
label = xml.get_widget('label')
|
|
|
|
self.input_entry = xml.get_widget('input_entry')
|
|
|
|
self.dialog.set_title(title)
|
|
|
|
label.set_text(label_str)
|
2005-05-14 18:34:07 +02:00
|
|
|
if input_str:
|
|
|
|
self.input_entry.set_text(input_str)
|
2005-06-19 01:44:33 +02:00
|
|
|
self.input_entry.select_region(0, -1) # select all
|
2005-07-25 09:47:05 +02:00
|
|
|
|
|
|
|
self.is_modal = is_modal
|
|
|
|
if not is_modal and ok_handler is not None:
|
|
|
|
self.ok_handler = ok_handler
|
|
|
|
okbutton = xml.get_widget('okbutton')
|
|
|
|
okbutton.connect('clicked', self.on_okbutton_clicked)
|
2005-07-25 16:21:01 +02:00
|
|
|
cancelbutton = xml.get_widget('cancelbutton')
|
|
|
|
cancelbutton.connect('clicked', self.on_cancelbutton_clicked)
|
2005-07-25 09:47:05 +02:00
|
|
|
self.dialog.show_all()
|
|
|
|
|
|
|
|
def on_okbutton_clicked(self, widget):
|
|
|
|
response = self.input_entry.get_text()
|
2005-06-19 01:44:33 +02:00
|
|
|
self.dialog.destroy()
|
2005-07-25 09:47:05 +02:00
|
|
|
self.ok_handler(response)
|
2005-07-25 16:21:01 +02:00
|
|
|
|
|
|
|
def on_cancelbutton_clicked(self, widget):
|
|
|
|
self.dialog.destroy()
|
2005-07-25 09:47:05 +02:00
|
|
|
|
|
|
|
def get_response(self):
|
|
|
|
if self.is_modal:
|
|
|
|
response = self.dialog.run()
|
|
|
|
self.dialog.destroy()
|
2005-06-19 01:44:33 +02:00
|
|
|
return response
|
2005-05-14 03:29:53 +02:00
|
|
|
|
2005-06-10 23:14:16 +02:00
|
|
|
class ErrorDialog(HigDialog):
|
2005-06-12 19:36:27 +02:00
|
|
|
def __init__(self, pritext, sectext=''):
|
|
|
|
"""HIG compliant error dialog."""
|
|
|
|
HigDialog.__init__(
|
|
|
|
self, None, pritext, sectext, gtk.STOCK_DIALOG_ERROR,
|
|
|
|
[ [ gtk.STOCK_OK, gtk.RESPONSE_OK ] ]
|
|
|
|
)
|
2005-03-01 20:02:51 +01:00
|
|
|
|
2005-06-10 00:29:06 +02:00
|
|
|
|
2005-06-13 12:48:07 +02:00
|
|
|
class SubscriptionRequestWindow:
|
2005-04-04 18:46:35 +02:00
|
|
|
def __init__(self, plugin, jid, text, account):
|
|
|
|
xml = gtk.glade.XML(GTKGUI_GLADE, 'subscription_request_window', APP)
|
2005-04-12 17:30:09 +02:00
|
|
|
self.window = xml.get_widget('subscription_request_window')
|
2005-04-04 18:46:35 +02:00
|
|
|
self.plugin = plugin
|
|
|
|
self.jid = jid
|
|
|
|
self.account = account
|
2005-06-13 15:26:04 +02:00
|
|
|
if len(gajim.connections) >= 2:
|
|
|
|
prompt_text = _('Subscription request for account %s from %s')\
|
|
|
|
% (account, self.jid)
|
|
|
|
else:
|
|
|
|
prompt_text = _('Subscription request from %s') % self.jid
|
|
|
|
xml.get_widget('from_label').set_text(prompt_text)
|
2005-04-04 18:46:35 +02:00
|
|
|
xml.get_widget('message_textview').get_buffer().set_text(text)
|
|
|
|
xml.signal_autoconnect(self)
|
|
|
|
self.window.show_all()
|
|
|
|
|
2005-03-01 15:02:32 +01:00
|
|
|
def on_close_button_clicked(self, widget):
|
2005-04-12 17:30:09 +02:00
|
|
|
self.window.destroy()
|
2004-05-15 18:50:38 +02:00
|
|
|
|
2005-03-01 15:02:32 +01:00
|
|
|
def on_authorize_button_clicked(self, widget):
|
2005-05-16 15:56:46 +02:00
|
|
|
'''accept the request'''
|
2005-04-14 11:38:08 +02:00
|
|
|
gajim.connections[self.account].send_authorization(self.jid)
|
2005-04-12 17:30:09 +02:00
|
|
|
self.window.destroy()
|
2005-07-18 23:08:31 +02:00
|
|
|
if not gajim.contacts[self.account].has_key(self.jid):
|
2005-06-10 23:14:16 +02:00
|
|
|
AddNewContactWindow(self.plugin, self.account, self.jid)
|
2005-05-18 10:47:38 +02:00
|
|
|
|
|
|
|
def on_contact_info_button_clicked(self, widget):
|
|
|
|
'''ask vcard'''
|
|
|
|
if self.plugin.windows[self.account]['infos'].has_key(self.jid):
|
|
|
|
self.plugin.windows[self.account]['infos'][self.jid].window.present()
|
|
|
|
else:
|
|
|
|
self.plugin.windows[self.account]['infos'][self.jid] = \
|
2005-06-11 00:45:50 +02:00
|
|
|
VcardWindow(self.jid, self.plugin, self.account, True)
|
2005-05-18 10:47:38 +02:00
|
|
|
#remove the publish / retrieve buttons
|
|
|
|
vcard_xml = self.plugin.windows[self.account]['infos'][self.jid].xml
|
|
|
|
hbuttonbox = vcard_xml.get_widget('information_hbuttonbox')
|
|
|
|
children = hbuttonbox.get_children()
|
|
|
|
hbuttonbox.remove(children[0])
|
|
|
|
hbuttonbox.remove(children[1])
|
|
|
|
vcard_xml.get_widget('nickname_label').set_text(self.jid)
|
|
|
|
gajim.connections[self.account].request_vcard(self.jid)
|
2004-05-15 18:50:38 +02:00
|
|
|
|
2005-03-01 15:02:32 +01:00
|
|
|
def on_deny_button_clicked(self, widget):
|
2005-04-18 14:17:43 +02:00
|
|
|
'''refuse the request'''
|
2005-04-14 11:38:08 +02:00
|
|
|
gajim.connections[self.account].refuse_authorization(self.jid)
|
2005-04-12 17:30:09 +02:00
|
|
|
self.window.destroy()
|
2005-04-04 18:46:35 +02:00
|
|
|
|
2005-06-10 23:14:16 +02:00
|
|
|
class JoinGroupchatWindow:
|
2005-04-22 01:20:18 +02:00
|
|
|
def __init__(self, plugin, account, server = '', room = ''):
|
2005-04-21 20:53:16 +02:00
|
|
|
self.plugin = plugin
|
|
|
|
self.account = account
|
2005-04-14 09:20:14 +02:00
|
|
|
if gajim.connections[account].connected < 2:
|
2005-06-10 23:14:16 +02:00
|
|
|
ErrorDialog(_('You are not connected to the server'),
|
2005-06-07 03:10:24 +02:00
|
|
|
_('You can not join a group chat unless you are connected.')).get_response()
|
2005-05-12 02:00:40 +02:00
|
|
|
raise RuntimeError, 'You must be connected to join a groupchat'
|
|
|
|
|
2005-04-04 18:46:35 +02:00
|
|
|
self.xml = gtk.glade.XML(GTKGUI_GLADE, 'join_groupchat_window', APP)
|
|
|
|
self.window = self.xml.get_widget('join_groupchat_window')
|
|
|
|
self.xml.get_widget('server_entry').set_text(server)
|
|
|
|
self.xml.get_widget('room_entry').set_text(room)
|
2005-07-18 23:08:31 +02:00
|
|
|
self.xml.get_widget('nickname_entry').set_text(gajim.nicks[self.account])
|
2005-04-04 18:46:35 +02:00
|
|
|
self.xml.signal_autoconnect(self)
|
2005-04-07 13:25:59 +02:00
|
|
|
self.plugin.windows[account]['join_gc'] = self #now add us to open windows
|
2005-04-21 20:53:16 +02:00
|
|
|
our_jid = gajim.config.get_per('accounts', self.account, 'name') + '@' + \
|
|
|
|
gajim.config.get_per('accounts', self.account, 'hostname')
|
|
|
|
if len(gajim.connections) > 1:
|
2005-08-02 00:48:58 +02:00
|
|
|
title = _('Join Group Chat as %s') % our_jid
|
2005-04-21 20:53:16 +02:00
|
|
|
else:
|
2005-08-02 00:48:58 +02:00
|
|
|
title = _('Join Group Chat')
|
2005-04-21 20:53:16 +02:00
|
|
|
self.window.set_title(title)
|
2005-04-07 00:52:48 +02:00
|
|
|
|
|
|
|
self.recently_combobox = self.xml.get_widget('recently_combobox')
|
|
|
|
liststore = gtk.ListStore(str)
|
|
|
|
self.recently_combobox.set_model(liststore)
|
|
|
|
cell = gtk.CellRendererText()
|
|
|
|
self.recently_combobox.pack_start(cell, True)
|
|
|
|
self.recently_combobox.add_attribute(cell, 'text', 0)
|
2005-04-12 23:09:06 +02:00
|
|
|
self.recently_groupchat = gajim.config.get('recently_groupchat').split()
|
2005-04-07 00:52:48 +02:00
|
|
|
for g in self.recently_groupchat:
|
|
|
|
self.recently_combobox.append_text(g)
|
2005-06-30 18:45:14 +02:00
|
|
|
if len(self.recently_groupchat) and server == '' and room == '':
|
2005-06-10 14:31:06 +02:00
|
|
|
self.recently_combobox.set_active(0)
|
|
|
|
self.xml.get_widget('room_entry').select_region(0, -1)
|
2005-04-07 00:52:48 +02:00
|
|
|
|
2005-04-04 17:51:29 +02:00
|
|
|
self.window.show_all()
|
2005-03-02 00:48:05 +01:00
|
|
|
|
2005-03-02 13:32:44 +01:00
|
|
|
def on_join_groupchat_window_destroy(self, widget):
|
2005-04-18 14:17:43 +02:00
|
|
|
'''close window'''
|
2005-04-07 13:25:59 +02:00
|
|
|
del self.plugin.windows[self.account]['join_gc'] # remove us from open windows
|
2005-03-02 00:48:05 +01:00
|
|
|
|
2005-04-07 11:53:54 +02:00
|
|
|
def on_join_groupchat_window_key_press_event(self, widget, event):
|
|
|
|
if event.keyval == gtk.keysyms.Escape: # ESCAPE
|
|
|
|
widget.destroy()
|
|
|
|
|
2005-04-07 00:52:48 +02:00
|
|
|
def on_recently_combobox_changed(self, widget):
|
|
|
|
model = widget.get_model()
|
|
|
|
iter = widget.get_active_iter()
|
2005-07-25 16:38:41 +02:00
|
|
|
gid = model[iter][0]
|
2005-04-07 00:52:48 +02:00
|
|
|
self.xml.get_widget('room_entry').set_text(gid.split('@')[0])
|
|
|
|
self.xml.get_widget('server_entry').set_text(gid.split('@')[1])
|
|
|
|
|
2005-03-04 14:41:48 +01:00
|
|
|
def on_cancel_button_clicked(self, widget):
|
2005-04-18 14:17:43 +02:00
|
|
|
'''When Cancel button is clicked'''
|
2005-04-12 17:30:09 +02:00
|
|
|
self.window.destroy()
|
2005-03-02 00:48:05 +01:00
|
|
|
|
2005-03-02 13:32:44 +01:00
|
|
|
def on_join_button_clicked(self, widget):
|
2005-04-18 14:17:43 +02:00
|
|
|
'''When Join button is clicked'''
|
2005-03-02 13:32:44 +01:00
|
|
|
nickname = self.xml.get_widget('nickname_entry').get_text()
|
|
|
|
room = self.xml.get_widget('room_entry').get_text()
|
|
|
|
server = self.xml.get_widget('server_entry').get_text()
|
2005-03-04 14:41:48 +01:00
|
|
|
password = self.xml.get_widget('password_entry').get_text()
|
2005-03-02 00:48:05 +01:00
|
|
|
jid = '%s@%s' % (room, server)
|
2005-04-07 00:52:48 +02:00
|
|
|
if jid in self.recently_groupchat:
|
|
|
|
self.recently_groupchat.remove(jid)
|
|
|
|
self.recently_groupchat.insert(0, jid)
|
|
|
|
if len(self.recently_groupchat) > 10:
|
|
|
|
self.recently_groupchat = self.recently_groupchat[0:10]
|
2005-04-12 23:09:06 +02:00
|
|
|
gajim.config.set('recently_groupchat', ' '.join(self.recently_groupchat))
|
2005-06-13 12:49:48 +02:00
|
|
|
|
|
|
|
self.plugin.roster.join_gc_room(self.account, jid, nickname, password)
|
|
|
|
|
2005-04-12 17:30:09 +02:00
|
|
|
self.window.destroy()
|
2005-03-02 00:48:05 +01:00
|
|
|
|
2005-06-10 23:14:16 +02:00
|
|
|
class NewMessageDialog:
|
2005-04-04 18:46:35 +02:00
|
|
|
def __init__(self, plugin, account):
|
2005-03-02 00:48:05 +01:00
|
|
|
self.plugin = plugin
|
|
|
|
self.account = account
|
2005-06-20 01:09:15 +02:00
|
|
|
|
2005-04-14 09:05:10 +02:00
|
|
|
our_jid = gajim.config.get_per('accounts', self.account, 'name') + '@' + \
|
|
|
|
gajim.config.get_per('accounts', self.account, 'hostname')
|
2005-04-17 21:53:39 +02:00
|
|
|
if len(gajim.connections) > 1:
|
2005-07-01 17:15:35 +02:00
|
|
|
title = _('New Message as %s') % our_jid
|
2005-04-04 18:46:35 +02:00
|
|
|
else:
|
2005-05-21 16:12:35 +02:00
|
|
|
title = _('New Message')
|
2005-07-01 17:15:35 +02:00
|
|
|
prompt_text = _('Fill in the contact ID of the contact you would like\nto send a chat message to:')
|
2005-03-02 00:48:05 +01:00
|
|
|
|
2005-07-25 09:47:05 +02:00
|
|
|
instance = InputDialog(title, prompt_text, is_modal = False, ok_handler = self.new_message_response)
|
|
|
|
|
|
|
|
def new_message_response(self, jid):
|
|
|
|
''' called when ok button is clicked '''
|
2005-08-06 21:14:21 +02:00
|
|
|
if gajim.connections[self.account].connected <= 1:
|
|
|
|
#if offline or connecting
|
|
|
|
ErrorDialog(_('Connection not available'),
|
|
|
|
_('Please make sure you are connected with "%s".' % self.account)
|
|
|
|
).get_response()
|
|
|
|
return
|
|
|
|
|
2005-07-25 09:47:05 +02:00
|
|
|
if jid.find('@') == -1: # if no @ was given
|
|
|
|
ErrorDialog(_('Invalid contact ID'),
|
|
|
|
_('Contact ID must be of the form "username@servername".')).get_response()
|
|
|
|
return
|
2005-06-20 01:09:15 +02:00
|
|
|
|
2005-07-25 09:47:05 +02:00
|
|
|
self.plugin.roster.new_chat_from_jid(self.account, jid)
|
2005-03-02 00:48:05 +01:00
|
|
|
|
2005-06-10 23:14:16 +02:00
|
|
|
class ChangePasswordDialog:
|
2005-03-02 19:38:27 +01:00
|
|
|
def __init__(self, plugin, account):
|
2005-07-18 13:03:53 +02:00
|
|
|
# 'account' can be None if we are about to create our first one
|
|
|
|
if not account or gajim.connections[account].connected < 2:
|
2005-06-10 23:14:16 +02:00
|
|
|
ErrorDialog(_('You are not connected to the server'),
|
2005-06-07 03:10:24 +02:00
|
|
|
_('Without a connection, you can not change your password.')).get_response()
|
2005-07-18 13:03:53 +02:00
|
|
|
raise RuntimeError, 'You are not connected to the server'
|
2005-03-02 00:48:05 +01:00
|
|
|
self.plugin = plugin
|
|
|
|
self.account = account
|
2005-04-04 18:46:35 +02:00
|
|
|
self.xml = gtk.glade.XML(GTKGUI_GLADE, 'change_password_dialog', APP)
|
|
|
|
self.dialog = self.xml.get_widget('change_password_dialog')
|
|
|
|
self.password1_entry = self.xml.get_widget('password1_entry')
|
|
|
|
self.password2_entry = self.xml.get_widget('password2_entry')
|
2005-03-28 03:39:12 +02:00
|
|
|
|
2005-06-05 12:48:34 +02:00
|
|
|
self.dialog.show_all()
|
2005-03-04 14:10:00 +01:00
|
|
|
|
|
|
|
def run(self):
|
2005-04-18 14:17:43 +02:00
|
|
|
'''Wait for OK button to be pressed and return new password'''
|
2005-03-04 14:10:00 +01:00
|
|
|
end = False
|
|
|
|
while not end:
|
|
|
|
rep = self.dialog.run()
|
|
|
|
if rep == gtk.RESPONSE_OK:
|
|
|
|
password1 = self.password1_entry.get_text()
|
|
|
|
if not password1:
|
2005-08-02 01:17:53 +02:00
|
|
|
ErrorDialog(_('Invalid password'),
|
2005-06-07 03:10:24 +02:00
|
|
|
_('You must enter a password.')).get_response()
|
2005-03-04 14:10:00 +01:00
|
|
|
continue
|
|
|
|
password2 = self.password2_entry.get_text()
|
|
|
|
if password1 != password2:
|
2005-08-02 00:48:58 +02:00
|
|
|
ErrorDialog(_('Passwords do not match'),
|
2005-06-07 03:10:24 +02:00
|
|
|
_('The passwords typed in both fields must be identical.')).get_response()
|
2005-03-04 14:10:00 +01:00
|
|
|
continue
|
|
|
|
message = password1
|
|
|
|
else:
|
|
|
|
message = -1
|
|
|
|
end = True
|
|
|
|
self.dialog.destroy()
|
|
|
|
return message
|
|
|
|
|
2005-06-10 00:29:06 +02:00
|
|
|
|
2005-06-10 20:40:19 +02:00
|
|
|
class PopupNotificationWindow:
|
2005-07-30 12:20:46 +02:00
|
|
|
def __init__(self, plugin, event_type, jid, account, msg_type = '', file_props = None):
|
2005-03-04 14:10:00 +01:00
|
|
|
self.plugin = plugin
|
2005-04-12 17:30:09 +02:00
|
|
|
self.account = account
|
|
|
|
self.jid = jid
|
2005-07-07 17:41:03 +02:00
|
|
|
self.msg_type = msg_type
|
2005-07-30 12:20:46 +02:00
|
|
|
self.file_props = file_props
|
2005-04-04 21:27:06 +02:00
|
|
|
|
2005-04-21 23:23:41 +02:00
|
|
|
xml = gtk.glade.XML(GTKGUI_GLADE, 'popup_notification_window', APP)
|
|
|
|
self.window = xml.get_widget('popup_notification_window')
|
2005-04-04 21:27:06 +02:00
|
|
|
close_button = xml.get_widget('close_button')
|
2005-04-06 20:51:54 +02:00
|
|
|
event_type_label = xml.get_widget('event_type_label')
|
|
|
|
event_description_label = xml.get_widget('event_description_label')
|
|
|
|
eventbox = xml.get_widget('eventbox')
|
2005-04-05 17:06:11 +02:00
|
|
|
|
2005-04-22 01:20:18 +02:00
|
|
|
event_type_label.set_markup('<b>' + event_type + '</b>')
|
2005-04-12 17:30:09 +02:00
|
|
|
|
2005-07-18 23:08:31 +02:00
|
|
|
if self.jid in gajim.contacts[account]:
|
|
|
|
txt = gajim.contacts[account][self.jid][0].name
|
2005-04-12 17:30:09 +02:00
|
|
|
else:
|
|
|
|
txt = self.jid
|
|
|
|
event_description_label.set_text(txt)
|
2005-04-04 18:46:35 +02:00
|
|
|
|
2005-04-06 20:51:54 +02:00
|
|
|
# set colors [ http://www.w3schools.com/html/html_colornames.asp ]
|
|
|
|
self.window.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse('black'))
|
2005-08-04 13:17:16 +02:00
|
|
|
|
2005-06-03 20:40:43 +02:00
|
|
|
if event_type == _('Contact Signed In'):
|
2005-07-16 11:33:43 +02:00
|
|
|
limegreen = gtk.gdk.color_parse('limegreen')
|
|
|
|
close_button.modify_bg(gtk.STATE_NORMAL, limegreen)
|
|
|
|
eventbox.modify_bg(gtk.STATE_NORMAL, limegreen)
|
2005-06-03 20:40:43 +02:00
|
|
|
elif event_type == _('Contact Signed Out'):
|
2005-07-16 11:33:43 +02:00
|
|
|
red = gtk.gdk.color_parse('red')
|
|
|
|
close_button.modify_bg(gtk.STATE_NORMAL, red)
|
|
|
|
eventbox.modify_bg(gtk.STATE_NORMAL, red)
|
|
|
|
elif event_type == _('New Message') or\
|
|
|
|
event_type == _('New Single Message'):
|
|
|
|
dodgerblue = gtk.gdk.color_parse('dodgerblue')
|
|
|
|
close_button.modify_bg(gtk.STATE_NORMAL, dodgerblue)
|
|
|
|
eventbox.modify_bg(gtk.STATE_NORMAL, dodgerblue)
|
2005-06-03 20:40:43 +02:00
|
|
|
txt = _('From %s') % txt
|
2005-08-03 18:53:04 +02:00
|
|
|
elif event_type == _('File Transfer Request'):
|
2005-07-30 12:20:46 +02:00
|
|
|
bg_color = gtk.gdk.color_parse('coral')
|
|
|
|
close_button.modify_bg(gtk.STATE_NORMAL, bg_color)
|
|
|
|
eventbox.modify_bg(gtk.STATE_NORMAL, bg_color)
|
|
|
|
txt = _('From %s') % txt
|
2005-08-09 17:29:45 +02:00
|
|
|
event_description_label.set_text(txt)
|
2005-08-07 23:01:21 +02:00
|
|
|
elif event_type == _('File Transfer Error'):
|
2005-08-08 12:42:25 +02:00
|
|
|
bg_color = gtk.gdk.color_parse('coral')
|
2005-08-07 23:01:21 +02:00
|
|
|
close_button.modify_bg(gtk.STATE_NORMAL, bg_color)
|
|
|
|
eventbox.modify_bg(gtk.STATE_NORMAL, bg_color)
|
2005-08-02 00:48:58 +02:00
|
|
|
elif event_type in [_('File Transfer Completed'), _('File Transfer Stopped')]:
|
2005-07-30 16:14:10 +02:00
|
|
|
bg_color = gtk.gdk.color_parse('coral')
|
|
|
|
close_button.modify_bg(gtk.STATE_NORMAL, bg_color)
|
|
|
|
eventbox.modify_bg(gtk.STATE_NORMAL, bg_color)
|
2005-08-09 17:29:45 +02:00
|
|
|
if file_props is not None:
|
|
|
|
if file_props['type'] == 'r':
|
2005-08-09 19:15:45 +02:00
|
|
|
# get the name of the sender, as it is in the roster
|
|
|
|
sender = str(file_props['sender']).split('/')[0]
|
|
|
|
name = gajim.get_first_contact_instance_from_jid(
|
|
|
|
account, sender).name
|
|
|
|
txt = _('From %s') % name
|
2005-08-09 17:29:45 +02:00
|
|
|
else:
|
|
|
|
receiver = file_props['receiver']
|
2005-08-09 19:15:45 +02:00
|
|
|
if hasattr(receiver, 'jid'):
|
|
|
|
receiver = receiver.jid
|
|
|
|
receiver = receiver.split('/')[0]
|
|
|
|
# get the name of the contact, as it is in the roster
|
|
|
|
name = gajim.get_first_contact_instance_from_jid(
|
|
|
|
account, receiver).name
|
|
|
|
txt = _('To %s') % name
|
2005-08-09 17:29:45 +02:00
|
|
|
else:
|
|
|
|
txt=''
|
|
|
|
event_description_label.set_text(txt)
|
2005-04-04 18:46:35 +02:00
|
|
|
# position the window to bottom-right of screen
|
2005-04-12 17:30:09 +02:00
|
|
|
window_width, self.window_height = self.window.get_size()
|
2005-04-21 23:30:56 +02:00
|
|
|
self.plugin.roster.popups_notification_height += self.window_height
|
2005-05-19 19:47:40 +02:00
|
|
|
self.window.move(gtk.gdk.screen_width() - window_width,
|
2005-06-10 20:40:19 +02:00
|
|
|
gtk.gdk.screen_height() - self.plugin.roster.popups_notification_height)
|
2005-04-04 18:46:35 +02:00
|
|
|
|
2005-04-04 21:27:06 +02:00
|
|
|
xml.signal_autoconnect(self)
|
2005-04-04 17:51:29 +02:00
|
|
|
self.window.show_all()
|
2005-04-12 17:30:09 +02:00
|
|
|
gobject.timeout_add(5000, self.on_timeout)
|
2005-04-04 18:46:35 +02:00
|
|
|
|
2005-04-12 17:30:09 +02:00
|
|
|
def on_close_button_clicked(self, widget):
|
2005-04-21 23:23:41 +02:00
|
|
|
self.adjust_height_and_move_popup_notification_windows()
|
2005-04-04 21:27:06 +02:00
|
|
|
|
2005-04-12 17:30:09 +02:00
|
|
|
def on_timeout(self):
|
2005-04-21 23:23:41 +02:00
|
|
|
self.adjust_height_and_move_popup_notification_windows()
|
2005-04-05 17:06:11 +02:00
|
|
|
|
2005-04-21 23:23:41 +02:00
|
|
|
def adjust_height_and_move_popup_notification_windows(self):
|
2005-04-05 17:06:11 +02:00
|
|
|
#remove
|
2005-04-21 23:30:56 +02:00
|
|
|
self.plugin.roster.popups_notification_height -= self.window_height
|
2005-04-04 21:27:06 +02:00
|
|
|
self.window.destroy()
|
2005-04-05 17:06:11 +02:00
|
|
|
|
2005-04-21 23:23:41 +02:00
|
|
|
if len(self.plugin.roster.popup_notification_windows) > 0:
|
2005-04-05 17:06:11 +02:00
|
|
|
# we want to remove the first window added in the list
|
2005-04-21 23:23:41 +02:00
|
|
|
self.plugin.roster.popup_notification_windows.pop(0) # remove 1st item
|
2005-04-05 17:06:11 +02:00
|
|
|
|
|
|
|
# move the rest of popup windows
|
2005-04-21 23:30:56 +02:00
|
|
|
self.plugin.roster.popups_notification_height = 0
|
2005-04-21 23:23:41 +02:00
|
|
|
for window_instance in self.plugin.roster.popup_notification_windows:
|
2005-04-05 17:06:11 +02:00
|
|
|
window_width, window_height = window_instance.window.get_size()
|
2005-04-21 23:30:56 +02:00
|
|
|
self.plugin.roster.popups_notification_height += window_height
|
2005-05-19 19:47:40 +02:00
|
|
|
window_instance.window.move(gtk.gdk.screen_width() - window_width,
|
2005-07-07 17:41:03 +02:00
|
|
|
gtk.gdk.screen_height() - self.plugin.roster.popups_notification_height)
|
2005-04-06 20:51:54 +02:00
|
|
|
|
2005-04-21 23:23:41 +02:00
|
|
|
def on_popup_notification_window_button_press_event(self, widget, event):
|
2005-06-24 16:28:00 +02:00
|
|
|
# use Contact class, new_chat expects it that way
|
2005-04-12 17:30:09 +02:00
|
|
|
# is it in the roster?
|
2005-07-18 23:08:31 +02:00
|
|
|
if gajim.contacts[self.account].has_key(self.jid):
|
2005-08-06 12:20:04 +02:00
|
|
|
contact = gajim.get_contact_instance_with_highest_priority(
|
|
|
|
self.account, self.jid)
|
2005-04-12 17:30:09 +02:00
|
|
|
else:
|
2005-05-29 23:34:01 +02:00
|
|
|
keyID = ''
|
|
|
|
attached_keys = gajim.config.get_per('accounts', self.account,
|
|
|
|
'attached_gpg_keys').split()
|
2005-08-03 23:11:46 +02:00
|
|
|
if self.jid in attached_keys:
|
2005-05-29 23:34:01 +02:00
|
|
|
keyID = attached_keys[attached_keys.index(jid) + 1]
|
2005-08-04 09:23:31 +02:00
|
|
|
if self.msg_type.find('file') != 0:
|
|
|
|
contact = Contact(jid = self.jid, name = self.jid.split('@')[0],
|
|
|
|
groups = [_('not in the roster')], show = 'not in the roster',
|
|
|
|
status = _('not in the roster'), sub = 'none', keyID = keyID)
|
|
|
|
gajim.contacts[self.account][self.jid] = [contact]
|
|
|
|
self.plugin.roster.add_contact_to_roster(contact.jid,
|
|
|
|
self.account)
|
2005-04-12 17:30:09 +02:00
|
|
|
|
2005-07-08 01:37:04 +02:00
|
|
|
if self.msg_type == 'normal': # it's single message
|
2005-07-16 11:33:43 +02:00
|
|
|
return # FIXME: I think I should not print here but in new_chat?
|
2005-08-06 21:14:21 +02:00
|
|
|
contact = get_contact_instance_with_highest_priority(account, jid)
|
2005-08-06 14:33:20 +02:00
|
|
|
SingleMessageWindow(self.plugin, self.account, contact.jid,
|
2005-07-16 11:33:43 +02:00
|
|
|
action = 'receive', from_whom = jid, subject = subject, message = msg)
|
2005-07-30 12:20:46 +02:00
|
|
|
|
|
|
|
elif self.msg_type == 'file': # it's file request
|
2005-08-01 17:02:17 +02:00
|
|
|
self.plugin.windows['file_transfers'].show_file_request(
|
|
|
|
self.account, contact, self.file_props)
|
2005-07-30 12:20:46 +02:00
|
|
|
|
2005-08-06 22:20:31 +02:00
|
|
|
elif self.msg_type == 'file-completed': # file transfer is complete
|
|
|
|
self.plugin.windows['file_transfers'].show_completed(self.jid,
|
2005-08-06 18:16:40 +02:00
|
|
|
self.file_props)
|
2005-08-04 13:17:16 +02:00
|
|
|
|
2005-08-06 22:20:31 +02:00
|
|
|
elif self.msg_type == 'file-stopped': # file transfer ended unexpectedly
|
|
|
|
self.plugin.windows['file_transfers'].show_stopped(self.jid,
|
2005-08-06 18:16:40 +02:00
|
|
|
self.file_props)
|
2005-08-07 23:01:21 +02:00
|
|
|
elif self.msg_type == 'file-error': # file transfer ended unexpectedly
|
|
|
|
self.plugin.windows['file_transfers'].show_stopped(self.jid,
|
|
|
|
self.file_props)
|
2005-07-07 17:41:03 +02:00
|
|
|
else: # 'chat'
|
2005-07-16 11:33:43 +02:00
|
|
|
self.plugin.roster.new_chat(contact, self.account)
|
2005-07-07 17:41:03 +02:00
|
|
|
chats_window = self.plugin.windows[self.account]['chats'][self.jid]
|
|
|
|
chats_window.set_active_tab(self.jid)
|
|
|
|
chats_window.window.present()
|
|
|
|
|
2005-04-21 23:23:41 +02:00
|
|
|
self.adjust_height_and_move_popup_notification_windows()
|
2005-07-01 17:15:35 +02:00
|
|
|
|
|
|
|
|
2005-07-05 23:35:37 +02:00
|
|
|
class SingleMessageWindow:
|
|
|
|
'''SingleMessageWindow can send or show a received
|
|
|
|
singled message depending on action argument'''
|
2005-08-06 21:14:21 +02:00
|
|
|
def __init__(self, plugin, account, to = '', action = '', from_whom = '',
|
|
|
|
subject = '', message = ''):
|
2005-07-01 17:15:35 +02:00
|
|
|
self.plugin = plugin
|
|
|
|
self.account = account
|
2005-07-05 23:35:37 +02:00
|
|
|
self.action = action
|
|
|
|
|
|
|
|
self.subject = subject
|
|
|
|
self.message = message
|
2005-07-01 17:15:35 +02:00
|
|
|
|
2005-07-05 23:35:37 +02:00
|
|
|
self.xml = gtk.glade.XML(GTKGUI_GLADE, 'single_message_window', APP)
|
|
|
|
self.window = self.xml.get_widget('single_message_window')
|
2005-07-02 17:49:25 +02:00
|
|
|
self.count_chars_label = self.xml.get_widget('count_chars_label')
|
2005-07-05 23:35:37 +02:00
|
|
|
self.from_label = self.xml.get_widget('from_label')
|
|
|
|
self.from_entry = self.xml.get_widget('from_entry')
|
|
|
|
self.to_label = self.xml.get_widget('to_label')
|
2005-07-02 17:49:25 +02:00
|
|
|
self.to_entry = self.xml.get_widget('to_entry')
|
|
|
|
self.subject_entry = self.xml.get_widget('subject_entry')
|
2005-07-05 23:35:37 +02:00
|
|
|
self.message_textview = self.xml.get_widget('message_textview')
|
|
|
|
self.message_tv_buffer = self.message_textview.get_buffer()
|
|
|
|
self.send_button = self.xml.get_widget('send_button')
|
|
|
|
self.reply_button = self.xml.get_widget('reply_button')
|
2005-07-06 01:55:33 +02:00
|
|
|
self.send_and_close_button = self.xml.get_widget('send_and_close_button')
|
2005-07-02 17:49:25 +02:00
|
|
|
self.message_tv_buffer.connect('changed', self.update_char_counter)
|
|
|
|
|
2005-08-06 14:33:20 +02:00
|
|
|
self.to_entry.set_text(to)
|
2005-07-01 17:15:35 +02:00
|
|
|
|
2005-07-05 23:35:37 +02:00
|
|
|
self.send_button.set_no_show_all(True)
|
|
|
|
self.reply_button.set_no_show_all(True)
|
2005-07-06 01:55:33 +02:00
|
|
|
self.send_and_close_button.set_no_show_all(True)
|
2005-07-05 23:35:37 +02:00
|
|
|
self.to_label.set_no_show_all(True)
|
|
|
|
self.to_entry.set_no_show_all(True)
|
|
|
|
self.from_label.set_no_show_all(True)
|
|
|
|
self.from_entry.set_no_show_all(True)
|
|
|
|
|
|
|
|
self.prepare_widgets_for(self.action)
|
|
|
|
|
|
|
|
if self.action == 'send':
|
|
|
|
if self.message: # we come from a reply?
|
|
|
|
self.message_textview.grab_focus()
|
|
|
|
else: # we write a new message
|
|
|
|
self.subject_entry.grab_focus()
|
|
|
|
elif self.action == 'receive':
|
|
|
|
self.from_whom = from_whom
|
|
|
|
self.from_entry.set_text(self.from_whom)
|
|
|
|
self.from_entry.set_property('editable', False)
|
|
|
|
self.subject_entry.set_property('editable', False)
|
|
|
|
self.message_textview.set_editable(False)
|
|
|
|
self.reply_button.grab_focus()
|
2005-07-26 17:23:11 +02:00
|
|
|
|
|
|
|
# set_text(None) raises TypeError exception
|
|
|
|
if self.subject is None:
|
|
|
|
self.subject = ''
|
2005-07-05 23:35:37 +02:00
|
|
|
self.subject_entry.set_text(self.subject)
|
|
|
|
self.message_tv_buffer.set_text(self.message)
|
|
|
|
begin_iter = self.message_tv_buffer.get_start_iter()
|
|
|
|
self.message_tv_buffer.place_cursor(begin_iter)
|
|
|
|
|
|
|
|
self.xml.signal_autoconnect(self)
|
|
|
|
self.window.show_all()
|
|
|
|
|
|
|
|
def prepare_widgets_for(self, action):
|
2005-07-01 17:15:35 +02:00
|
|
|
our_jid = gajim.config.get_per('accounts', self.account, 'name') + '@' + \
|
|
|
|
gajim.config.get_per('accounts', self.account, 'hostname')
|
|
|
|
if len(gajim.connections) > 1:
|
2005-07-05 23:35:37 +02:00
|
|
|
title = _('Single Message as %s') % our_jid
|
2005-07-01 17:15:35 +02:00
|
|
|
else:
|
2005-07-05 23:35:37 +02:00
|
|
|
title = _('Single Message')
|
|
|
|
|
|
|
|
if action == 'send':
|
|
|
|
title = _('Send %s') % title
|
|
|
|
self.send_button.show()
|
2005-07-06 01:55:33 +02:00
|
|
|
self.send_and_close_button.show()
|
2005-07-05 23:35:37 +02:00
|
|
|
self.to_label.show()
|
|
|
|
self.to_entry.show()
|
|
|
|
self.reply_button.hide()
|
|
|
|
self.from_label.hide()
|
|
|
|
self.from_entry.hide()
|
|
|
|
elif action == 'receive':
|
2005-07-06 01:55:33 +02:00
|
|
|
title = _('Received %s') % title
|
2005-07-05 23:35:37 +02:00
|
|
|
self.reply_button.show()
|
|
|
|
self.from_label.show()
|
|
|
|
self.from_entry.show()
|
|
|
|
self.send_button.hide()
|
2005-07-06 01:55:33 +02:00
|
|
|
self.send_and_close_button.hide()
|
2005-07-05 23:35:37 +02:00
|
|
|
self.to_label.hide()
|
|
|
|
self.to_entry.hide()
|
2005-07-02 17:49:25 +02:00
|
|
|
|
2005-07-05 23:35:37 +02:00
|
|
|
self.window.set_title(title)
|
2005-07-01 17:15:35 +02:00
|
|
|
|
2005-07-02 17:49:25 +02:00
|
|
|
def on_cancel_button_clicked(self, widget):
|
|
|
|
self.window.destroy()
|
2005-07-01 17:15:35 +02:00
|
|
|
|
2005-07-02 17:49:25 +02:00
|
|
|
def update_char_counter(self, widget):
|
|
|
|
characters_no = self.message_tv_buffer.get_char_count()
|
|
|
|
self.count_chars_label.set_text(str(characters_no))
|
2005-07-01 17:15:35 +02:00
|
|
|
|
2005-07-06 01:55:33 +02:00
|
|
|
def send_single_message(self):
|
2005-08-06 21:14:21 +02:00
|
|
|
if gajim.connections[self.account].connected <= 1:
|
|
|
|
#if offline or connecting
|
|
|
|
ErrorDialog(_('Connection not available'),
|
|
|
|
_('Please make sure you are connected with "%s".' % self.account)
|
|
|
|
).get_response()
|
|
|
|
return
|
2005-07-02 17:49:25 +02:00
|
|
|
to_whom_jid = self.to_entry.get_text()
|
2005-08-06 14:33:20 +02:00
|
|
|
subject = self.subject_entry.get_text()
|
|
|
|
begin, end = self.message_tv_buffer.get_bounds()
|
|
|
|
message = self.message_tv_buffer.get_text(begin, end)
|
|
|
|
|
2005-08-07 13:40:48 +02:00
|
|
|
if to_whom_jid.find('/announce/') != -1:
|
2005-08-06 14:33:20 +02:00
|
|
|
gajim.connections[self.account].send_motd(to_whom_jid, subject,
|
|
|
|
message)
|
|
|
|
return
|
2005-08-06 21:14:21 +02:00
|
|
|
|
2005-07-02 17:49:25 +02:00
|
|
|
if to_whom_jid.find('@') == -1: # if no @ was given
|
|
|
|
ErrorDialog(_('Invalid contact ID'),
|
|
|
|
_('Contact ID must be of the form "username@servername".')).get_response()
|
|
|
|
return
|
|
|
|
|
|
|
|
# FIXME: allow GPG message some day
|
|
|
|
gajim.connections[self.account].send_message(to_whom_jid, message,
|
|
|
|
keyID = None, type = 'normal', subject=subject)
|
|
|
|
|
2005-07-05 23:57:19 +02:00
|
|
|
self.subject_entry.set_text('') # we sent ok, clear the subject
|
2005-07-02 17:49:25 +02:00
|
|
|
self.message_tv_buffer.set_text('') # we sent ok, clear the textview
|
2005-07-04 23:29:22 +02:00
|
|
|
|
2005-07-06 01:55:33 +02:00
|
|
|
def on_send_button_clicked(self, widget):
|
|
|
|
self.send_single_message()
|
|
|
|
|
2005-07-05 23:35:37 +02:00
|
|
|
def on_reply_button_clicked(self, widget):
|
|
|
|
# we create a new blank window to send and we preset RE: and to jid
|
|
|
|
self.subject = _('RE: %s') % self.subject
|
2005-07-06 01:55:33 +02:00
|
|
|
self.message = _('\n\n\n== Original Message ==\n%s') % self.message
|
2005-07-05 23:57:19 +02:00
|
|
|
self.window.destroy()
|
2005-08-06 14:33:20 +02:00
|
|
|
SingleMessageWindow(self.plugin, self.account, to = to,
|
2005-07-05 23:35:37 +02:00
|
|
|
action = 'send', from_whom = self.from_whom, subject = self.subject,
|
|
|
|
message = self.message)
|
|
|
|
|
2005-07-06 01:55:33 +02:00
|
|
|
def on_send_and_close_button_clicked(self, widget):
|
|
|
|
self.send_single_message()
|
|
|
|
self.window.destroy()
|
|
|
|
|
|
|
|
def on_single_message_window_key_press_event(self, widget, event):
|
|
|
|
if event.keyval == gtk.keysyms.Escape: # ESCAPE
|
|
|
|
self.window.destroy()
|
|
|
|
|
2005-07-04 23:29:22 +02:00
|
|
|
class XMLConsoleWindow:
|
|
|
|
def __init__(self, plugin, account):
|
|
|
|
self.plugin = plugin
|
|
|
|
self.account = account
|
|
|
|
|
|
|
|
self.xml = gtk.glade.XML(GTKGUI_GLADE, 'xml_console_window', APP)
|
|
|
|
self.window = self.xml.get_widget('xml_console_window')
|
|
|
|
self.input_textview = self.xml.get_widget('input_textview')
|
|
|
|
self.stanzas_log_textview = self.xml.get_widget('stanzas_log_textview')
|
2005-08-06 02:38:24 +02:00
|
|
|
self.input_tv_buffer = self.input_textview.get_buffer()
|
2005-08-06 01:43:28 +02:00
|
|
|
buffer = self.stanzas_log_textview.get_buffer()
|
2005-08-06 02:38:24 +02:00
|
|
|
end_iter = buffer.get_end_iter()
|
|
|
|
buffer.create_mark('end', end_iter, False)
|
|
|
|
|
2005-08-06 01:43:28 +02:00
|
|
|
self.tagIn = buffer.create_tag('incoming')
|
|
|
|
color = gajim.config.get('inmsgcolor')
|
|
|
|
self.tagIn.set_property('foreground', color)
|
|
|
|
self.tagOut = buffer.create_tag('outgoing')
|
|
|
|
color = gajim.config.get('outmsgcolor')
|
|
|
|
self.tagOut.set_property('foreground', color)
|
|
|
|
|
2005-08-06 21:14:21 +02:00
|
|
|
self.enabled = False
|
2005-08-06 01:43:28 +02:00
|
|
|
|
2005-08-06 02:38:24 +02:00
|
|
|
self.input_textview.modify_text(
|
2005-08-06 01:43:28 +02:00
|
|
|
gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
|
2005-07-04 23:29:22 +02:00
|
|
|
|
|
|
|
if len(gajim.connections) > 1:
|
2005-07-05 01:18:05 +02:00
|
|
|
title = _('XML Console for %s') % self.account
|
2005-07-04 23:29:22 +02:00
|
|
|
else:
|
|
|
|
title = _('XML Console')
|
|
|
|
|
|
|
|
self.window.set_title(title)
|
|
|
|
|
|
|
|
self.xml.signal_autoconnect(self)
|
|
|
|
|
2005-08-06 02:38:24 +02:00
|
|
|
def on_xml_console_window_delete_event(self, widget, event):
|
|
|
|
self.window.hide()
|
|
|
|
return True # do NOT destroy the window
|
|
|
|
|
|
|
|
def on_clear_button_clicked(self, widget):
|
2005-08-04 22:32:38 +02:00
|
|
|
buffer = self.stanzas_log_textview.get_buffer()
|
2005-08-06 02:38:24 +02:00
|
|
|
buffer.set_text('')
|
|
|
|
|
|
|
|
def on_enable_checkbutton_toggled(self, widget):
|
2005-08-06 21:14:21 +02:00
|
|
|
self.enabled = widget.get_active()
|
2005-08-06 02:38:24 +02:00
|
|
|
|
|
|
|
def scroll_to_end(self, ):
|
|
|
|
parent = self.stanzas_log_textview.get_parent()
|
|
|
|
buffer = self.stanzas_log_textview.get_buffer()
|
|
|
|
self.stanzas_log_textview.scroll_to_mark(buffer.get_mark('end'), 0, True,
|
|
|
|
0, 1)
|
|
|
|
adjustment = parent.get_hadjustment()
|
|
|
|
adjustment.set_value(0)
|
|
|
|
return False
|
|
|
|
|
|
|
|
def print_stanza(self, stanza, kind):
|
|
|
|
# kind must be 'incoming' or 'outgoing'
|
2005-08-06 21:14:21 +02:00
|
|
|
if not self.enabled:
|
2005-08-06 02:38:24 +02:00
|
|
|
return
|
|
|
|
|
|
|
|
buffer = self.stanzas_log_textview.get_buffer()
|
|
|
|
at_the_end = False
|
|
|
|
end_iter = buffer.get_end_iter()
|
|
|
|
end_rect = self.stanzas_log_textview.get_iter_location(end_iter)
|
|
|
|
visible_rect = self.stanzas_log_textview.get_visible_rect()
|
|
|
|
if end_rect.y <= (visible_rect.y + visible_rect.height):
|
|
|
|
at_the_end = True
|
2005-08-04 22:32:38 +02:00
|
|
|
end_iter = buffer.get_end_iter()
|
2005-08-06 02:38:24 +02:00
|
|
|
buffer.insert_with_tags_by_name(end_iter, stanza + '\n\n', kind)
|
|
|
|
if at_the_end:
|
|
|
|
gobject.idle_add(self.scroll_to_end)
|
2005-08-04 22:32:38 +02:00
|
|
|
|
2005-07-04 23:29:22 +02:00
|
|
|
def on_send_button_clicked(self, widget):
|
2005-08-06 21:14:21 +02:00
|
|
|
if gajim.connections[self.account].connected <= 1:
|
|
|
|
#if offline or connecting
|
|
|
|
ErrorDialog(_('Connection not available'),
|
|
|
|
_('Please make sure you are connected with "%s".' % self.account)
|
|
|
|
).get_response()
|
|
|
|
return
|
2005-07-04 23:29:22 +02:00
|
|
|
begin_iter, end_iter = self.input_tv_buffer.get_bounds()
|
|
|
|
stanza = self.input_tv_buffer.get_text(begin_iter, end_iter)
|
|
|
|
if stanza:
|
|
|
|
gajim.connections[self.account].send_stanza(stanza)
|
|
|
|
self.input_tv_buffer.set_text('') # we sent ok, clear the textview
|
|
|
|
|
|
|
|
def on_presence_button_clicked(self, widget):
|
|
|
|
self.input_tv_buffer.set_text(
|
|
|
|
'<presence><show></show><status></status><priority></priority></presence>'
|
|
|
|
)
|
|
|
|
|
|
|
|
def on_iq_button_clicked(self, widget):
|
|
|
|
self.input_tv_buffer.set_text(
|
|
|
|
'<iq to="" type=""><query xmlns=""></query></iq>'
|
|
|
|
)
|
|
|
|
|
|
|
|
def on_message_button_clicked(self, widget):
|
|
|
|
self.input_tv_buffer.set_text(
|
|
|
|
'<message to="" type=""><body></body></message>'
|
|
|
|
)
|
2005-07-05 01:18:05 +02:00
|
|
|
|
|
|
|
def on_expander_activate(self, widget):
|
|
|
|
if not widget.get_expanded(): # it's the opposite!
|
|
|
|
# it's expanded!!
|
|
|
|
self.input_textview.grab_focus()
|
2005-07-04 23:29:22 +02:00
|
|
|
|
|
|
|
def on_xml_console_window_destroy(self, widget):
|
|
|
|
# remove us from open windows
|
|
|
|
del self.plugin.windows[self.account]['xml_console']
|
|
|
|
widget.destroy()
|
2005-08-01 17:02:17 +02:00
|
|
|
|
|
|
|
class FileTransfersWindow:
|
|
|
|
def __init__(self, plugin):
|
2005-08-03 16:11:51 +02:00
|
|
|
self.files_props = {'r' : {}, 's': {}}
|
2005-08-01 17:02:17 +02:00
|
|
|
self.plugin = plugin
|
2005-08-07 14:06:24 +02:00
|
|
|
self.height_diff = 0
|
2005-08-01 17:02:17 +02:00
|
|
|
self.last_save_dir = None
|
|
|
|
self.xml = gtk.glade.XML(GTKGUI_GLADE, 'file_transfers_window', APP)
|
|
|
|
self.window = self.xml.get_widget('file_transfers_window')
|
|
|
|
self.tree = self.xml.get_widget('transfers_list')
|
2005-08-09 19:58:50 +02:00
|
|
|
self.cancel_button = self.xml.get_widget('cancel_button')
|
2005-08-01 17:02:17 +02:00
|
|
|
self.pause_button = self.xml.get_widget('pause_restore_button')
|
2005-08-03 23:11:46 +02:00
|
|
|
self.remove_button = self.xml.get_widget('remove_button')
|
2005-08-06 22:31:15 +02:00
|
|
|
self.notify_ft_checkbox = self.xml.get_widget(
|
|
|
|
'notify_ft_complete_checkbox')
|
2005-08-01 17:02:17 +02:00
|
|
|
notify = gajim.config.get('notify_on_file_complete')
|
|
|
|
if notify:
|
2005-08-06 22:31:15 +02:00
|
|
|
self.notify_ft_checkbox.set_active(True)
|
2005-08-01 17:02:17 +02:00
|
|
|
else:
|
2005-08-06 22:31:15 +02:00
|
|
|
self.notify_ft_checkbox.set_active(False)
|
2005-08-01 17:02:17 +02:00
|
|
|
self.model = gtk.ListStore(gtk.gdk.Pixbuf, str, str, str, str, str)
|
|
|
|
self.tree.set_model(self.model)
|
|
|
|
col = gtk.TreeViewColumn()
|
|
|
|
|
|
|
|
render_pixbuf = gtk.CellRendererPixbuf()
|
|
|
|
|
|
|
|
col.pack_start(render_pixbuf, expand = True)
|
|
|
|
render_pixbuf.set_property('xpad', 3)
|
|
|
|
render_pixbuf.set_property('ypad', 3)
|
|
|
|
render_pixbuf.set_property('yalign', .0)
|
2005-08-06 22:31:15 +02:00
|
|
|
col.add_attribute(render_pixbuf, 'pixbuf', 0)
|
2005-08-01 17:02:17 +02:00
|
|
|
self.tree.append_column(col)
|
|
|
|
|
|
|
|
col = gtk.TreeViewColumn(_('File'))
|
|
|
|
renderer = gtk.CellRendererText()
|
|
|
|
col.pack_start(renderer, expand=False)
|
|
|
|
col.add_attribute(renderer, 'markup' , 1)
|
|
|
|
renderer.set_property('yalign', 0.)
|
|
|
|
renderer = gtk.CellRendererText()
|
|
|
|
col.pack_start(renderer, expand=True)
|
|
|
|
col.add_attribute(renderer, 'markup' , 2)
|
|
|
|
renderer.set_property('xalign', 0.)
|
|
|
|
renderer.set_property('yalign', 0.)
|
2005-08-06 22:49:24 +02:00
|
|
|
col.set_resizable(True)
|
2005-08-01 17:02:17 +02:00
|
|
|
self.tree.append_column(col)
|
|
|
|
|
|
|
|
col = gtk.TreeViewColumn(_('Progress'))
|
|
|
|
renderer = gtk.CellRendererText()
|
|
|
|
renderer.set_property('yalign', 0.)
|
|
|
|
renderer.set_property('xalign', 0.)
|
|
|
|
col.pack_start(renderer, expand = True)
|
|
|
|
col.set_expand(False)
|
|
|
|
col.add_attribute(renderer, 'text' , 3)
|
|
|
|
self.tree.append_column(col)
|
|
|
|
self.set_images()
|
|
|
|
self.tree.get_selection().set_select_function(self.select_func)
|
2005-08-07 14:06:24 +02:00
|
|
|
self.tooltip = FileTransfersTooltip()
|
2005-08-01 17:02:17 +02:00
|
|
|
self.xml.signal_autoconnect(self)
|
2005-08-04 13:17:16 +02:00
|
|
|
|
|
|
|
def show_completed(self, jid, file_props):
|
|
|
|
self.window.present()
|
|
|
|
self.window.window.focus()
|
|
|
|
sectext = '\t' + _('Filename: %s') % \
|
|
|
|
gtkgui_helpers.escape_for_pango_markup(file_props['name'])
|
|
|
|
sectext += '\n\t' + _('Size: %s') % \
|
2005-08-09 19:27:27 +02:00
|
|
|
helpers.convert_bytes(file_props['size'])
|
2005-08-04 13:17:16 +02:00
|
|
|
sectext += '\n\t' +_('Sender: %s') % \
|
|
|
|
gtkgui_helpers.escape_for_pango_markup(jid)
|
|
|
|
InformationDialog(_('File transfer completed'), sectext).get_response()
|
|
|
|
self.tree.get_selection().unselect_all()
|
|
|
|
|
2005-08-06 18:16:40 +02:00
|
|
|
def show_request_error(self, file_props):
|
|
|
|
self.window.present()
|
|
|
|
self.window.window.focus()
|
2005-08-07 23:01:21 +02:00
|
|
|
InformationDialog(_('File transfer canceled'), _('Connection with peer cannot be established.')).get_response()
|
2005-08-06 18:16:40 +02:00
|
|
|
self.tree.get_selection().unselect_all()
|
|
|
|
|
|
|
|
def show_send_error(self, jid, file_props):
|
|
|
|
self.window.present()
|
|
|
|
self.window.window.focus()
|
2005-08-06 22:31:15 +02:00
|
|
|
InformationDialog(_('File transfer canceled'),
|
2005-08-09 17:29:45 +02:00
|
|
|
_('Connection with peer cannot be established.')).get_response()
|
2005-08-06 18:16:40 +02:00
|
|
|
self.tree.get_selection().unselect_all()
|
2005-08-07 14:06:24 +02:00
|
|
|
|
2005-08-06 22:20:31 +02:00
|
|
|
def show_stopped(self, jid, file_props):
|
2005-08-04 13:17:16 +02:00
|
|
|
self.window.present()
|
|
|
|
self.window.window.focus()
|
|
|
|
sectext = '\t' + _('Filename: %s') % \
|
|
|
|
gtkgui_helpers.escape_for_pango_markup(file_props['name'])
|
|
|
|
sectext += '\n\t' + _('Sender: %s') % \
|
|
|
|
gtkgui_helpers.escape_for_pango_markup(jid)
|
|
|
|
ErrorDialog(_('File transfer stopped by the contact of the other side'), \
|
|
|
|
sectext).get_response()
|
|
|
|
self.tree.get_selection().unselect_all()
|
|
|
|
|
2005-08-03 16:11:51 +02:00
|
|
|
def show_file_send_request(self, account, contact):
|
2005-08-06 22:31:15 +02:00
|
|
|
dialog = gtk.FileChooserDialog(title=_('Choose File to Send...'),
|
2005-08-03 16:11:51 +02:00
|
|
|
action=gtk.FILE_CHOOSER_ACTION_OPEN,
|
2005-08-07 14:06:24 +02:00
|
|
|
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
|
|
|
|
butt = dialog.add_button(_('Send'), gtk.RESPONSE_OK)
|
|
|
|
butt.set_use_stock(True)
|
2005-08-03 16:11:51 +02:00
|
|
|
dialog.set_default_response(gtk.RESPONSE_OK)
|
|
|
|
if self.last_save_dir and os.path.exists(self.last_save_dir) \
|
|
|
|
and os.path.isdir(self.last_save_dir):
|
|
|
|
dialog.set_current_folder(self.last_save_dir)
|
|
|
|
file_props = {}
|
|
|
|
response = dialog.run()
|
|
|
|
if response == gtk.RESPONSE_OK:
|
2005-08-07 14:31:05 +02:00
|
|
|
file_path = unicode(dialog.get_filename(), 'utf-8')
|
2005-08-03 16:11:51 +02:00
|
|
|
(file_dir, file_name) = os.path.split(file_path)
|
|
|
|
if file_dir:
|
|
|
|
self.last_save_dir = file_dir
|
2005-08-07 14:31:05 +02:00
|
|
|
file_props = self.get_send_file_props(account, contact,
|
|
|
|
file_path, file_name)
|
2005-08-03 16:11:51 +02:00
|
|
|
dialog.destroy()
|
|
|
|
self.add_transfer(account, contact, file_props)
|
|
|
|
gajim.connections[account].send_file_request(file_props)
|
|
|
|
else:
|
|
|
|
dialog.destroy()
|
2005-08-09 21:00:19 +02:00
|
|
|
|
2005-08-01 17:02:17 +02:00
|
|
|
def show_file_request(self, account, contact, file_props):
|
|
|
|
if file_props is None or not file_props.has_key('name'):
|
|
|
|
return
|
2005-08-04 13:17:16 +02:00
|
|
|
sec_text = '\t' + _('File: %s') % \
|
|
|
|
gtkgui_helpers.escape_for_pango_markup(file_props['name'])
|
2005-08-01 17:02:17 +02:00
|
|
|
if file_props.has_key('size'):
|
|
|
|
sec_text += '\n\t' + _('Size: %s') % \
|
2005-08-09 19:27:27 +02:00
|
|
|
helpers.convert_bytes(file_props['size'])
|
2005-08-01 17:02:17 +02:00
|
|
|
if file_props.has_key('mime-type'):
|
2005-08-04 13:17:16 +02:00
|
|
|
sec_text += '\n\t' + _('Type: %s') % \
|
|
|
|
gtkgui_helpers.escape_for_pango_markup(file_props['mime-type'])
|
2005-08-01 17:02:17 +02:00
|
|
|
if file_props.has_key('desc'):
|
2005-08-04 13:17:16 +02:00
|
|
|
sec_text += '\n\t' + _('Description: %s') % \
|
|
|
|
gtkgui_helpers.escape_for_pango_markup(file_props['desc'])
|
2005-08-02 00:48:58 +02:00
|
|
|
prim_text = _('%s wants to send you a file:') % contact.jid
|
2005-08-01 17:02:17 +02:00
|
|
|
dialog = ConfirmationDialog(prim_text, sec_text)
|
|
|
|
if dialog.get_response() == gtk.RESPONSE_OK:
|
2005-08-02 00:48:58 +02:00
|
|
|
dialog = gtk.FileChooserDialog(title=_('Save File as...'),
|
2005-08-01 17:02:17 +02:00
|
|
|
action=gtk.FILE_CHOOSER_ACTION_SAVE,
|
|
|
|
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
|
|
|
|
gtk.STOCK_SAVE, gtk.RESPONSE_OK))
|
|
|
|
dialog.set_current_name(file_props['name'])
|
|
|
|
dialog.set_default_response(gtk.RESPONSE_OK)
|
|
|
|
if self.last_save_dir and os.path.exists(self.last_save_dir) \
|
|
|
|
and os.path.isdir(self.last_save_dir):
|
|
|
|
dialog.set_current_folder(self.last_save_dir)
|
2005-08-04 13:17:16 +02:00
|
|
|
while True:
|
|
|
|
response = dialog.run()
|
|
|
|
if response == gtk.RESPONSE_OK:
|
|
|
|
file_path = dialog.get_filename()
|
|
|
|
if os.path.exists(file_path):
|
|
|
|
primtext = _('This file already exists')
|
|
|
|
sectext = _('Would you like to overwrite it?')
|
|
|
|
dialog2 = ConfirmationDialog(primtext, sectext)
|
|
|
|
if dialog2.get_response() != gtk.RESPONSE_OK:
|
|
|
|
continue
|
|
|
|
(file_dir, file_name) = os.path.split(file_path)
|
|
|
|
if file_dir:
|
|
|
|
self.last_save_dir = file_dir
|
2005-08-07 14:06:24 +02:00
|
|
|
file_props['file-name'] = file_path.decode('utf-8')
|
2005-08-04 13:17:16 +02:00
|
|
|
self.add_transfer(account, contact, file_props)
|
|
|
|
gajim.connections[account].send_file_approval(file_props)
|
|
|
|
else:
|
|
|
|
gajim.connections[account].send_file_rejection(file_props)
|
|
|
|
dialog.destroy()
|
|
|
|
break
|
2005-08-01 17:02:17 +02:00
|
|
|
else:
|
|
|
|
gajim.connections[account].send_file_rejection(file_props)
|
|
|
|
|
|
|
|
def set_images(self):
|
|
|
|
self.images = {}
|
|
|
|
self.images['upload'] = self.window.render_icon(gtk.STOCK_GO_UP,
|
|
|
|
gtk.ICON_SIZE_MENU)
|
|
|
|
self.images['download'] = self.window.render_icon(gtk.STOCK_GO_DOWN,
|
|
|
|
gtk.ICON_SIZE_MENU)
|
|
|
|
self.images['stop'] = self.window.render_icon(gtk.STOCK_STOP,
|
|
|
|
gtk.ICON_SIZE_MENU)
|
2005-08-04 09:23:31 +02:00
|
|
|
self.images['waiting'] = self.window.render_icon(gtk.STOCK_REFRESH,
|
2005-08-01 17:02:17 +02:00
|
|
|
gtk.ICON_SIZE_MENU)
|
|
|
|
self.images['pause'] = self.window.render_icon(gtk.STOCK_MEDIA_PAUSE,
|
|
|
|
gtk.ICON_SIZE_MENU)
|
|
|
|
self.images['ok'] = self.window.render_icon(gtk.STOCK_APPLY,
|
|
|
|
gtk.ICON_SIZE_MENU)
|
|
|
|
|
|
|
|
def set_status(self, typ, sid, status):
|
|
|
|
iter = self.get_iter_by_sid(typ, sid)
|
2005-08-09 13:38:11 +02:00
|
|
|
if iter is None:
|
2005-08-09 15:35:05 +02:00
|
|
|
return
|
2005-08-09 19:15:45 +02:00
|
|
|
sid = self.model[iter][4]
|
|
|
|
file_props = self.files_props[sid[0]][sid[1:]]
|
2005-08-07 14:06:24 +02:00
|
|
|
if status == 'stop':
|
|
|
|
file_props['stopped'] = True
|
2005-08-09 19:15:45 +02:00
|
|
|
elif status == 'ok':
|
|
|
|
file_props['completed'] = True
|
2005-08-09 13:38:11 +02:00
|
|
|
self.model.set(iter, 0, self.images[status])
|
2005-08-09 21:00:19 +02:00
|
|
|
|
2005-08-01 17:02:17 +02:00
|
|
|
def set_progress(self, typ, sid, transfered_size, iter = None):
|
|
|
|
if not self.files_props[typ].has_key(sid):
|
|
|
|
return
|
|
|
|
file_props = self.files_props[typ][sid]
|
|
|
|
full_size = int(file_props['size'])
|
|
|
|
if full_size == 0:
|
|
|
|
percent = 0
|
|
|
|
else:
|
|
|
|
percent = round(float(transfered_size) / full_size * 100)
|
|
|
|
if iter is None:
|
|
|
|
iter = self.get_iter_by_sid(typ, sid)
|
|
|
|
if iter is not None:
|
|
|
|
text = str(percent) + '%\n'
|
|
|
|
if transfered_size == 0:
|
|
|
|
text += '0'
|
|
|
|
else:
|
2005-08-09 19:27:27 +02:00
|
|
|
text += helpers.convert_bytes(transfered_size)
|
|
|
|
text += '/' + helpers.convert_bytes(full_size)
|
2005-08-01 17:02:17 +02:00
|
|
|
self.model.set(iter, 3, text)
|
2005-08-03 16:11:51 +02:00
|
|
|
if file_props['type'] == 'r':
|
|
|
|
status = 'download'
|
|
|
|
else:
|
|
|
|
status = 'upload'
|
|
|
|
if file_props.has_key('paused') and file_props['paused'] == True:
|
|
|
|
status = 'pause'
|
2005-08-04 09:23:31 +02:00
|
|
|
elif file_props.has_key('stalled') and file_props['stalled'] == True:
|
|
|
|
status = 'waiting'
|
2005-08-03 16:11:51 +02:00
|
|
|
if file_props.has_key('connected') and file_props['connected'] == False:
|
|
|
|
status = 'stop'
|
|
|
|
self.model.set(iter, 0, self.images[status])
|
2005-08-01 17:02:17 +02:00
|
|
|
if percent == 100:
|
|
|
|
self.set_status(typ, sid, 'ok')
|
2005-08-09 21:00:19 +02:00
|
|
|
|
2005-08-01 17:02:17 +02:00
|
|
|
def get_iter_by_sid(self, typ, sid):
|
2005-08-03 02:39:00 +02:00
|
|
|
'''returns iter to the row, which holds file transfer, identified by the
|
|
|
|
session id'''
|
2005-08-01 17:02:17 +02:00
|
|
|
iter = self.model.get_iter_root()
|
|
|
|
while iter:
|
2005-08-03 02:39:00 +02:00
|
|
|
if typ + sid == self.model[iter][4]:
|
2005-08-01 17:02:17 +02:00
|
|
|
return iter
|
|
|
|
iter = self.model.iter_next(iter)
|
2005-08-09 21:00:19 +02:00
|
|
|
|
2005-08-03 16:11:51 +02:00
|
|
|
def get_sid(self):
|
|
|
|
rng = range(65, 90)
|
|
|
|
rng.extend(range(48, 57))
|
|
|
|
char_sequence = map(lambda e:chr(e), rng)
|
|
|
|
from random import sample
|
|
|
|
return reduce(lambda e1, e2: e1 + e2,
|
|
|
|
sample(char_sequence, 16))
|
|
|
|
|
|
|
|
def get_send_file_props(self, account, contact, file_path, file_name):
|
|
|
|
file_props = {'file-name' : file_path, 'name' : file_name,
|
|
|
|
'type' : 's'}
|
|
|
|
if os.path.exists(file_path) and os.path.isfile(file_path):
|
|
|
|
stat = os.stat(file_path)
|
|
|
|
os.stat(file_path)
|
|
|
|
file_props['size'] = str(stat[6])
|
|
|
|
file_props['sid'] = self.get_sid()
|
|
|
|
file_props['completed'] = False
|
|
|
|
file_props['started'] = False
|
|
|
|
file_props['sender'] = account
|
|
|
|
file_props['receiver'] = contact
|
2005-08-09 21:00:19 +02:00
|
|
|
file_props['tt_account'] = account
|
2005-08-03 16:11:51 +02:00
|
|
|
return file_props
|
2005-08-01 17:02:17 +02:00
|
|
|
|
|
|
|
def add_transfer(self, account, contact, file_props):
|
2005-08-07 14:06:24 +02:00
|
|
|
self.on_transfers_list_leave_notify_event(None)
|
2005-08-01 17:02:17 +02:00
|
|
|
if file_props is None:
|
|
|
|
return
|
|
|
|
self.files_props[file_props['type']][file_props['sid']] = file_props
|
|
|
|
iter = self.model.append()
|
|
|
|
text_labels = '<b>' + _('Name: ') + '</b>\n'
|
2005-08-03 17:51:37 +02:00
|
|
|
if file_props['type'] == 'r':
|
|
|
|
text_labels += '<b>' + _('Sender: ') + '</b>'
|
|
|
|
else:
|
|
|
|
text_labels += '<b>' + _('Recipient: ') + '</b>'
|
2005-08-04 13:17:16 +02:00
|
|
|
text_props = gtkgui_helpers.escape_for_pango_markup(file_props['name']) + '\n'
|
|
|
|
text_props += gtkgui_helpers.escape_for_pango_markup(contact.name)
|
2005-08-01 17:02:17 +02:00
|
|
|
self.model.set(iter, 1, text_labels, 2, text_props, 4, \
|
|
|
|
file_props['type'] + file_props['sid'])
|
|
|
|
self.set_progress(file_props['type'], file_props['sid'], 0, iter)
|
2005-08-03 16:11:51 +02:00
|
|
|
if file_props.has_key('started') and file_props['started'] is False:
|
|
|
|
status = 'waiting'
|
|
|
|
elif file_props['type'] == 'r':
|
|
|
|
status = 'download'
|
|
|
|
else:
|
|
|
|
status = 'upload'
|
2005-08-09 19:15:45 +02:00
|
|
|
file_props['tt_account'] = account
|
2005-08-03 16:11:51 +02:00
|
|
|
self.set_status(file_props['type'], file_props['sid'], status)
|
2005-08-01 17:02:17 +02:00
|
|
|
self.window.show_all()
|
|
|
|
|
2005-08-07 14:06:24 +02:00
|
|
|
def on_transfers_list_motion_notify_event(self, widget, event):
|
|
|
|
pointer = self.tree.get_pointer()
|
|
|
|
orig = widget.window.get_origin()
|
|
|
|
props = widget.get_path_at_pos(int(event.x), int(event.y))
|
|
|
|
self.height_diff = pointer[1] - int(event.y)
|
|
|
|
if self.tooltip.timeout > 0:
|
|
|
|
if not props or self.tooltip.id != props[0]:
|
|
|
|
self.tooltip.hide_tooltip()
|
|
|
|
if props:
|
|
|
|
[row, col, x, y] = props
|
|
|
|
iter = None
|
|
|
|
try:
|
|
|
|
iter = self.model.get_iter(row)
|
|
|
|
except:
|
|
|
|
self.tooltip.hide_tooltip()
|
|
|
|
return
|
|
|
|
sid = self.model[iter][4]
|
|
|
|
file_props = self.files_props[sid[0]][sid[1:]]
|
|
|
|
if file_props is not None:
|
|
|
|
if self.tooltip.timeout == 0 or self.tooltip.id != props[0]:
|
|
|
|
self.tooltip.id = row
|
|
|
|
self.tooltip.timeout = gobject.timeout_add(500,
|
|
|
|
self.show_tooltip, widget)
|
2005-08-01 17:02:17 +02:00
|
|
|
|
2005-08-07 14:06:24 +02:00
|
|
|
def on_transfers_list_leave_notify_event(self, widget = None, event = None):
|
|
|
|
if event is not None:
|
|
|
|
self.height_diff = int(event.y)
|
|
|
|
elif self.height_diff is 0:
|
|
|
|
return
|
|
|
|
pointer = self.tree.get_pointer()
|
|
|
|
props = self.tree.get_path_at_pos(pointer[0],
|
|
|
|
pointer[1] - self.height_diff)
|
|
|
|
if self.tooltip.timeout > 0:
|
|
|
|
if not props or self.tooltip.id == props[0]:
|
|
|
|
self.tooltip.hide_tooltip()
|
2005-08-01 17:02:17 +02:00
|
|
|
|
|
|
|
def on_transfers_list_row_activated(self, widget, path, col):
|
|
|
|
# try to open the file
|
2005-08-06 22:31:15 +02:00
|
|
|
#FIXME: plz remove this :)
|
2005-08-01 17:02:17 +02:00
|
|
|
pass
|
|
|
|
|
|
|
|
def is_transfer_paused(self, file_props):
|
|
|
|
if file_props.has_key('error') and file_props['error'] != 0:
|
|
|
|
return False
|
|
|
|
if file_props['completed'] or file_props['disconnect_cb'] is None:
|
|
|
|
return False
|
|
|
|
return file_props['paused']
|
|
|
|
|
|
|
|
def is_transfer_active(self, file_props):
|
|
|
|
if file_props.has_key('error') and file_props['error'] != 0:
|
|
|
|
return False
|
|
|
|
if file_props['completed'] or file_props['disconnect_cb'] is None:
|
|
|
|
return False
|
|
|
|
return not file_props['paused']
|
|
|
|
|
|
|
|
def is_transfer_stoped(self, file_props):
|
|
|
|
if file_props.has_key('error') and file_props['error'] != 0:
|
|
|
|
return True
|
2005-08-03 16:11:51 +02:00
|
|
|
if file_props.has_key('completed') and file_props['completed']:
|
2005-08-01 17:02:17 +02:00
|
|
|
return True
|
|
|
|
if file_props.has_key('disconnect_cb') and \
|
|
|
|
file_props['disconnect_cb'] is not None:
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
|
|
def select_func(self, path):
|
|
|
|
is_selected = False
|
|
|
|
current_iter = self.model.get_iter(path)
|
|
|
|
selected = self.tree.get_selection().get_selected()
|
|
|
|
if selected[1] != None:
|
|
|
|
selected_path = self.model.get_path(selected[1])
|
|
|
|
if selected_path == path:
|
|
|
|
is_selected = True
|
|
|
|
sid = self.model[current_iter][4]
|
|
|
|
file_props = self.files_props[sid[0]][sid[1:]]
|
2005-08-06 22:31:15 +02:00
|
|
|
self.remove_button.set_sensitive(not is_selected)
|
2005-08-01 17:02:17 +02:00
|
|
|
if self.is_transfer_stoped(file_props):
|
|
|
|
is_selected = True
|
2005-08-09 19:58:50 +02:00
|
|
|
self.cancel_button.set_sensitive(not is_selected)
|
2005-08-01 17:02:17 +02:00
|
|
|
if is_selected:
|
2005-08-06 22:31:15 +02:00
|
|
|
self.pause_button.set_sensitive(False)
|
2005-08-01 17:02:17 +02:00
|
|
|
else:
|
|
|
|
if self.is_transfer_active(file_props):
|
2005-08-06 22:31:15 +02:00
|
|
|
self.pause_button.set_sensitive(True)
|
2005-08-01 17:02:17 +02:00
|
|
|
self.pause_button.set_label(_('_Pause'))
|
|
|
|
elif self.is_transfer_paused(file_props):
|
2005-08-06 22:31:15 +02:00
|
|
|
self.pause_button.set_sensitive(True)
|
2005-08-01 17:02:17 +02:00
|
|
|
self.pause_button.set_label(_('_Continue'))
|
|
|
|
else:
|
2005-08-06 22:31:15 +02:00
|
|
|
self.pause_button.set_sensitive(False)
|
2005-08-01 17:02:17 +02:00
|
|
|
return True
|
2005-08-03 02:39:00 +02:00
|
|
|
|
|
|
|
def on_remove_button_clicked(self, widget):
|
2005-08-01 17:02:17 +02:00
|
|
|
selected = self.tree.get_selection().get_selected()
|
|
|
|
if selected is None or selected[1] is None:
|
|
|
|
return
|
|
|
|
s_iter = selected[1]
|
|
|
|
sid = self.model[s_iter][4]
|
|
|
|
file_props = self.files_props[sid[0]][sid[1:]]
|
|
|
|
if not self.is_transfer_stoped(file_props):
|
|
|
|
file_props['disconnect_cb']()
|
|
|
|
self.model.remove(s_iter)
|
2005-08-06 22:31:15 +02:00
|
|
|
self.remove_button.set_sensitive(False)
|
2005-08-01 17:02:17 +02:00
|
|
|
|
|
|
|
def on_pause_restore_button_clicked(self, widget):
|
|
|
|
selected = self.tree.get_selection().get_selected()
|
|
|
|
if selected is None or selected[1] is None:
|
|
|
|
return
|
|
|
|
s_iter = selected[1]
|
|
|
|
sid = self.model[s_iter][4]
|
|
|
|
file_props = self.files_props[sid[0]][sid[1:]]
|
|
|
|
if self.is_transfer_paused(file_props):
|
|
|
|
file_props['paused'] = False
|
2005-08-01 18:14:35 +02:00
|
|
|
types = {'r' : 'download', 's' : 'upload'}
|
2005-08-01 17:02:17 +02:00
|
|
|
self.set_status(file_props['type'], file_props['sid'], types[sid[0]])
|
|
|
|
widget.set_label(_('Pause'))
|
|
|
|
elif self.is_transfer_active(file_props):
|
|
|
|
file_props['paused'] = True
|
|
|
|
self.set_status(file_props['type'], file_props['sid'], 'pause')
|
|
|
|
widget.set_label(_('_Continue'))
|
|
|
|
|
2005-08-09 19:21:40 +02:00
|
|
|
def on_cancel_button_clicked(self, widget):
|
2005-08-01 17:02:17 +02:00
|
|
|
selected = self.tree.get_selection().get_selected()
|
|
|
|
if selected is None or selected[1] is None:
|
|
|
|
return
|
|
|
|
s_iter = selected[1]
|
|
|
|
sid = self.model[s_iter][4]
|
2005-08-03 17:51:37 +02:00
|
|
|
|
2005-08-01 17:02:17 +02:00
|
|
|
file_props = self.files_props[sid[0]][sid[1:]]
|
|
|
|
if not self.is_transfer_stoped(file_props):
|
|
|
|
file_props['disconnect_cb']()
|
|
|
|
self.set_status(file_props['type'], file_props['sid'], 'stop')
|
2005-08-07 14:06:24 +02:00
|
|
|
|
|
|
|
def show_tooltip(self, widget):
|
|
|
|
pointer = self.tree.get_pointer()
|
|
|
|
props = self.tree.get_path_at_pos(pointer[0],
|
|
|
|
pointer[1] - self.height_diff)
|
|
|
|
if props and self.tooltip.id == props[0]:
|
|
|
|
# check if the current pointer is at the same path
|
|
|
|
# as it was before setting the timeout
|
|
|
|
iter = self.model.get_iter(props[0])
|
|
|
|
sid = self.model[iter][4]
|
|
|
|
file_props = self.files_props[sid[0]][sid[1:]]
|
|
|
|
rect = self.tree.get_cell_area(props[0],props[1])
|
|
|
|
position = widget.window.get_origin()
|
|
|
|
self.tooltip.show_tooltip(file_props , (pointer[0], rect.height ),
|
|
|
|
(position[0], position[1] + rect.y + self.height_diff))
|
|
|
|
else:
|
|
|
|
self.tooltip.hide_tooltip()
|
|
|
|
|
2005-08-01 17:02:17 +02:00
|
|
|
def on_notify_ft_complete_checkbox_toggled(self, widget):
|
|
|
|
gajim.config.set('notify_on_file_complete',
|
|
|
|
widget.get_active())
|
|
|
|
|
|
|
|
def on_file_transfers_dialog_delete_event(self, widget, event):
|
2005-08-07 14:06:24 +02:00
|
|
|
self.on_transfers_list_leave_notify_event(widget, None)
|
2005-08-01 17:02:17 +02:00
|
|
|
self.window.hide()
|
2005-08-03 02:39:00 +02:00
|
|
|
return True # do NOT destory window
|
2005-08-01 17:02:17 +02:00
|
|
|
|
2005-08-03 17:59:44 +02:00
|
|
|
def on_close_button_clicked(self, widget):
|
|
|
|
self.window.hide()
|