gajim-plural/src/dialogs.py

4071 lines
140 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
## src/dialogs.py
2004-05-15 18:50:38 +02:00
##
## Copyright (C) 2003-2005 Vincent Hanquez <tab AT snarc.org>
## Copyright (C) 2003-2008 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005 Alex Mauer <hawke AT hawkesnest.net>
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
## Travis Shirk <travis AT pobox.com>
## Copyright (C) 2005-2008 Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org>
## Copyright (C) 2007 Lukas Petrovicky <lukas AT petrovicky.net>
## Copyright (C) 2007-2008 Brendan Taylor <whateley AT gmail.com>
## Julien Pivotto <roidelapluie AT gmail.com>
## Stephan Erb <steve-e AT h3c.de>
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
2004-05-15 18:50:38 +02:00
##
2007-12-12 09:44:46 +01:00
## This file is part of Gajim.
##
## Gajim is free software; you can redistribute it and/or modify
2004-05-15 18:50:38 +02:00
## it under the terms of the GNU General Public License as published
2007-12-12 09:44:46 +01:00
## by the Free Software Foundation; version 3 only.
2004-05-15 18:50:38 +02:00
##
2007-12-12 09:44:46 +01:00
## Gajim is distributed in the hope that it will be useful,
2004-05-15 18:50:38 +02:00
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2004-05-15 18:50:38 +02:00
## GNU General Public License for more details.
##
2007-12-12 09:44:46 +01:00
## You should have received a copy of the GNU General Public License
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
2007-12-12 09:44:46 +01:00
##
2004-05-15 18:50:38 +02:00
import gtk
import gobject
2005-05-17 19:37:50 +02:00
import os
2005-07-21 23:42:53 +02:00
import gtkgui_helpers
2005-11-13 21:25:04 +01:00
import vcard
import conversation_textview
2006-11-18 21:52:28 +01:00
import message_control
2007-12-12 09:44:46 +01:00
import dataforms_widget
from random import randrange
2008-07-23 00:20:51 +02:00
from common import pep
try:
import gtkspell
HAS_GTK_SPELL = True
except ImportError:
HAS_GTK_SPELL = False
2006-03-24 19:49:47 +01:00
# those imports are not used in this file, but in files that 'import dialogs'
# so they can do dialog.GajimThemesWindow() for example
from filetransfers_window import FileTransfersWindow
from gajim_themes_window import GajimThemesWindow
from advanced import AdvancedConfigurationWindow
from common import gajim
from common import helpers
2007-12-12 09:44:46 +01:00
from common import dataforms
2006-11-18 21:52:28 +01:00
from common.exceptions import GajimGeneralException
2004-05-15 18:50:38 +02:00
class EditGroupsDialog:
2005-04-18 14:17:43 +02:00
'''Class for the edit group dialog window'''
2006-09-13 18:47:58 +02:00
def __init__(self, list_):
'''list_ is a list of (contact, account) tuples'''
self.xml = gtkgui_helpers.get_glade('edit_groups_dialog.glade')
self.dialog = self.xml.get_widget('edit_groups_dialog')
2006-09-13 18:47:58 +02:00
self.dialog.set_transient_for(gajim.interface.roster.window)
self.list_ = list_
self.changes_made = False
2008-10-12 22:32:24 +02:00
self.treeview = self.xml.get_widget('groups_treeview')
2006-09-13 18:47:58 +02:00
if len(list_) == 1:
contact = list_[0][0]
self.xml.get_widget('nickname_label').set_markup(
2007-06-03 12:04:20 +02:00
_('Contact name: <i>%s</i>') % contact.get_shown_name())
2006-09-13 18:47:58 +02:00
self.xml.get_widget('jid_label').set_markup(
2006-11-21 01:26:51 +01:00
_('Jabber ID: <i>%s</i>') % contact.jid)
2006-09-13 18:47:58 +02:00
else:
self.xml.get_widget('nickname_label').set_no_show_all(True)
self.xml.get_widget('nickname_label').hide()
self.xml.get_widget('jid_label').set_no_show_all(True)
self.xml.get_widget('jid_label').hide()
self.xml.signal_autoconnect(self)
self.init_list()
self.dialog.show_all()
if self.changes_made:
2006-09-13 18:47:58 +02:00
for (contact, account) in self.list_:
gajim.connections[account].update_contact(contact.jid, contact.name,
contact.groups)
def on_edit_groups_dialog_response(self, widget, response_id):
if response_id == gtk.RESPONSE_CLOSE:
self.dialog.destroy()
def remove_group(self, group):
2006-09-13 18:47:58 +02:00
'''remove group group from all contacts and all their brothers'''
for (contact, account) in self.list_:
gajim.interface.roster.remove_contact_from_groups(contact.jid, account, [group])
# FIXME: Ugly workaround.
gajim.interface.roster.draw_group(_('General'), account)
def add_group(self, group):
2006-09-13 18:47:58 +02:00
'''add group group to all contacts and all their brothers'''
for (contact, account) in self.list_:
gajim.interface.roster.add_contact_to_groups(contact.jid, account, [group])
2008-12-03 22:56:12 +01:00
# FIXME: Ugly workaround. Maybe we haven't been in any group (defaults to General)
gajim.interface.roster.draw_group(_('General'), account)
def on_add_button_clicked(self, widget):
group = self.xml.get_widget('group_entry').get_text().decode('utf-8')
if not group:
return
2006-11-18 21:52:28 +01:00
# Do not allow special groups
if group in helpers.special_groups:
return
# check if it already exists
2008-10-12 22:32:24 +02:00
model = self.treeview.get_model()
2008-12-03 18:16:04 +01:00
iter_ = model.get_iter_root()
while iter_:
if model.get_value(iter_, 0).decode('utf-8') == group:
return
2008-12-03 18:16:04 +01:00
iter_ = model.iter_next(iter_)
self.changes_made = True
2006-09-13 18:47:58 +02:00
model.append((group, True, False))
self.add_group(group)
self.init_list() # Re-draw list to sort new item
def group_toggled_cb(self, cell, path):
self.changes_made = True
2008-10-12 22:32:24 +02:00
model = self.treeview.get_model()
2006-09-13 18:47:58 +02:00
if model[path][2]:
model[path][2] = False
model[path][1] = True
else:
model[path][1] = not model[path][1]
group = model[path][0].decode('utf-8')
if model[path][1]:
self.add_group(group)
else:
self.remove_group(group)
def init_list(self):
2006-09-13 18:47:58 +02:00
store = gtk.ListStore(str, bool, bool)
2008-10-12 22:32:24 +02:00
self.treeview.set_model(store)
for column in self.treeview.get_columns():
# Clear treeview when re-drawing
self.treeview.remove_column(column)
2006-09-13 18:47:58 +02:00
accounts = []
# Store groups in a list so we can sort them and the number of contacts in
# it
groups = {}
for (contact, account) in self.list_:
if account not in accounts:
accounts.append(account)
for g in gajim.groups[account].keys():
if g in groups:
continue
groups[g] = 0
c_groups = contact.groups
for g in c_groups:
2006-09-13 18:47:58 +02:00
groups[g] += 1
2006-11-18 21:52:28 +01:00
group_list = []
# Remove special groups if they are empty
for group in groups:
if group not in helpers.special_groups or groups[group] > 0:
group_list.append(group)
group_list.sort()
2006-09-13 18:47:58 +02:00
for group in group_list:
2008-12-03 18:16:04 +01:00
iter_ = store.append()
store.set(iter_, 0, group) # Group name
2006-09-13 18:47:58 +02:00
if groups[group] == 0:
2008-12-03 18:16:04 +01:00
store.set(iter_, 1, False)
2006-09-13 18:47:58 +02:00
else:
2008-12-03 18:16:04 +01:00
store.set(iter_, 1, True)
2006-09-13 18:47:58 +02:00
if groups[group] == len(self.list_):
# all contacts are in this group
2008-12-03 18:16:04 +01:00
store.set(iter_, 2, False)
2006-09-13 18:47:58 +02:00
else:
2008-12-03 18:16:04 +01:00
store.set(iter_, 2, True)
column = gtk.TreeViewColumn(_('Group'))
2005-08-29 02:01:43 +02:00
column.set_expand(True)
2008-10-12 22:32:24 +02:00
self.treeview.append_column(column)
renderer = gtk.CellRendererText()
column.pack_start(renderer)
2008-09-03 13:25:27 +02:00
column.set_attributes(renderer, text=0)
column = gtk.TreeViewColumn(_('In the group'))
2005-08-29 02:01:43 +02:00
column.set_expand(False)
2008-10-12 22:32:24 +02:00
self.treeview.append_column(column)
renderer = gtk.CellRendererToggle()
column.pack_start(renderer)
renderer.set_property('activatable', True)
renderer.connect('toggled', self.group_toggled_cb)
2008-09-03 13:25:27 +02:00
column.set_attributes(renderer, active=1, inconsistent=2)
class PassphraseDialog:
2005-04-18 14:17:43 +02:00
'''Class for Passphrase dialog'''
def __init__(self, titletext, labeltext, checkbuttontext=None,
ok_handler=None, cancel_handler=None):
self.xml = gtkgui_helpers.get_glade('passphrase_dialog.glade')
self.window = self.xml.get_widget('passphrase_dialog')
self.passphrase_entry = self.xml.get_widget('passphrase_entry')
self.passphrase = -1
self.window.set_title(titletext)
self.xml.get_widget('message_label').set_text(labeltext)
2007-12-12 09:44:46 +01:00
self.ok = False
self.cancel_handler = cancel_handler
self.ok_handler = ok_handler
okbutton = self.xml.get_widget('ok_button')
okbutton.connect('clicked', self.on_okbutton_clicked)
cancelbutton = self.xml.get_widget('cancel_button')
cancelbutton.connect('clicked', self.on_cancelbutton_clicked)
2007-12-12 09:44:46 +01:00
self.xml.signal_autoconnect(self)
2009-04-05 20:35:59 +02:00
self.window.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
self.window.show_all()
2007-12-12 09:44:46 +01:00
self.check = bool(checkbuttontext)
checkbutton = self.xml.get_widget('save_passphrase_checkbutton')
if self.check:
checkbutton.set_label(checkbuttontext)
else:
checkbutton.hide()
2007-12-12 09:44:46 +01:00
def on_okbutton_clicked(self, widget):
if not self.ok_handler:
return
2007-12-12 09:44:46 +01:00
passph = self.passphrase_entry.get_text().decode('utf-8')
if self.check:
checked = self.xml.get_widget('save_passphrase_checkbutton').\
get_active()
else:
checked = False
self.ok = True
self.window.destroy()
if isinstance(self.ok_handler, tuple):
self.ok_handler[0](passph, checked, *self.ok_handler[1:])
else:
self.ok_handler(passph, checked)
def on_cancelbutton_clicked(self, widget):
self.window.destroy()
def on_passphrase_dialog_destroy(self, widget):
if self.cancel_handler and not self.ok:
self.cancel_handler()
2004-05-15 18:50:38 +02:00
class ChooseGPGKeyDialog:
2005-04-18 14:17:43 +02:00
'''Class for GPG key dialog'''
2008-08-08 12:26:11 +02:00
def __init__(self, title_text, prompt_text, secret_keys, on_response,
selected=None):
'''secret_keys : {keyID: userName, ...}'''
self.on_response = on_response
xml = gtkgui_helpers.get_glade('choose_gpg_key_dialog.glade')
self.window = xml.get_widget('choose_gpg_key_dialog')
self.window.set_title(title_text)
self.keys_treeview = xml.get_widget('keys_treeview')
prompt_label = xml.get_widget('prompt_label')
prompt_label.set_text(prompt_text)
model = gtk.ListStore(str, str)
2006-09-13 18:47:58 +02:00
model.set_sort_func(1, self.sort_keys)
2005-10-22 10:52:13 +02:00
model.set_sort_column_id(1, gtk.SORT_ASCENDING)
self.keys_treeview.set_model(model)
#columns
renderer = gtk.CellRendererText()
2007-12-12 09:44:46 +01:00
col = self.keys_treeview.insert_column_with_attributes(-1, _('KeyID'),
renderer, text = 0)
2007-12-12 09:44:46 +01:00
col.set_sort_column_id(0)
renderer = gtk.CellRendererText()
2007-12-12 09:44:46 +01:00
col = self.keys_treeview.insert_column_with_attributes(-1,
2008-09-03 13:25:27 +02:00
_('Contact name'), renderer, text=1)
2007-12-12 09:44:46 +01:00
col.set_sort_column_id(1)
2006-11-18 21:52:28 +01:00
self.keys_treeview.set_search_column(1)
self.fill_tree(secret_keys, selected)
2008-08-08 12:26:11 +02:00
self.window.connect('response', self.on_dialog_response)
2009-04-05 20:35:59 +02:00
self.window.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
self.window.show_all()
2006-09-13 18:47:58 +02:00
def sort_keys(self, model, iter1, iter2):
value1 = model[iter1][1]
value2 = model[iter2][1]
if value1 == _('None'):
return -1
elif value2 == _('None'):
return 1
elif value1 < value2:
return -1
return 1
2008-08-08 12:26:11 +02:00
def on_dialog_response(self, dialog, response):
selection = self.keys_treeview.get_selection()
2008-12-03 18:16:04 +01:00
(model, iter_) = selection.get_selected()
if iter_ and response == gtk.RESPONSE_OK:
keyID = [ model[iter_][0].decode('utf-8'),
model[iter_][1].decode('utf-8') ]
else:
keyID = None
2008-08-08 12:26:11 +02:00
self.on_response(keyID)
self.window.destroy()
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)
class ChangeActivityDialog:
PAGELIST = ['doing_chores', 'drinking', 'eating', 'exercising', 'grooming',
'having_appointment', 'inactive', 'relaxing', 'talking', 'traveling',
'working']
2008-07-28 22:57:56 +02:00
def __init__(self, on_response, activity=None, subactivity=None, text=''):
self.on_response = on_response
self.activity = activity
self.subactivity = subactivity
self.text = text
2008-07-28 22:57:56 +02:00
self.xml = gtkgui_helpers.get_glade(
'change_activity_dialog.glade')
self.window = self.xml.get_widget('change_activity_dialog')
self.window.set_transient_for(gajim.interface.roster.window)
2008-07-28 22:57:56 +02:00
self.checkbutton = self.xml.get_widget('enable_checkbutton')
self.notebook = self.xml.get_widget('notebook')
self.entry = self.xml.get_widget('description_entry')
2008-07-28 22:57:56 +02:00
rbtns = {}
group = None
2008-08-14 16:49:03 +02:00
2008-07-28 22:57:56 +02:00
for category in pep.ACTIVITIES:
item = self.xml.get_widget(category + '_image')
item.set_from_pixbuf(
gtkgui_helpers.load_activity_icon(category).get_pixbuf())
gtk.Tooltips().set_tip(item, pep.ACTIVITIES[category]['category'])
2008-07-28 22:57:56 +02:00
vbox = self.xml.get_widget(category + '_vbox')
vbox.set_border_width(5)
# Other
act = category + '_other'
if group:
rbtns[act] = gtk.RadioButton(group)
else:
rbtns[act] = group = gtk.RadioButton()
hbox = gtk.HBox(False, 5)
hbox.pack_start(gtkgui_helpers.load_activity_icon(category),
False, False, 0)
lbl = gtk.Label('<b>' + pep.ACTIVITIES[category]['category'] + '</b>')
lbl.set_use_markup(True)
hbox.pack_start(lbl, False, False, 0)
rbtns[act].add(hbox)
rbtns[act].connect('toggled', self.on_rbtn_toggled,
[category, 'other'])
vbox.pack_start(rbtns[act], False, False, 0)
2008-08-14 16:49:03 +02:00
activities = []
2008-07-28 22:57:56 +02:00
for activity in pep.ACTIVITIES[category]:
2008-08-14 16:49:03 +02:00
activities.append(activity)
activities.sort()
for activity in activities:
2008-07-29 00:33:20 +02:00
if activity == 'category':
continue
2008-07-28 22:57:56 +02:00
act = category + '_' + activity
2008-07-28 22:57:56 +02:00
if group:
rbtns[act] = gtk.RadioButton(group)
else:
rbtns[act] = group = gtk.RadioButton()
hbox = gtk.HBox(False, 5)
hbox.pack_start(gtkgui_helpers.load_activity_icon(category,
activity), False, False, 0)
hbox.pack_start(gtk.Label(pep.ACTIVITIES[category][activity]),
False, False, 0)
rbtns[act].connect('toggled', self.on_rbtn_toggled,
2008-07-28 22:57:56 +02:00
[category, activity])
rbtns[act].add(hbox)
2008-07-28 22:57:56 +02:00
vbox.pack_start(rbtns[act], False, False, 0)
2008-07-28 22:57:56 +02:00
if self.activity in pep.ACTIVITIES:
if not self.subactivity in pep.ACTIVITIES[self.activity]:
self.subactivity = 'other'
2008-07-28 22:57:56 +02:00
rbtns[self.activity + '_' + self.subactivity].set_active(True)
2008-07-28 22:57:56 +02:00
self.checkbutton.set_active(True)
self.notebook.set_sensitive(True)
self.entry.set_sensitive(True)
self.notebook.set_current_page(
self.PAGELIST.index(self.activity))
self.entry.set_text(text)
else:
self.checkbutton.set_active(False)
self.xml.signal_autoconnect(self)
2009-04-05 20:35:59 +02:00
self.window.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
self.window.show_all()
2008-07-28 22:57:56 +02:00
def on_enable_checkbutton_toggled(self, widget):
self.notebook.set_sensitive(widget.get_active())
self.entry.set_sensitive(widget.get_active())
2008-07-28 22:57:56 +02:00
def on_rbtn_toggled(self, widget, data):
if widget.get_active():
self.activity = data[0]
self.subactivity = data[1]
def on_ok_button_clicked(self, widget):
2008-07-28 22:57:56 +02:00
'''
Return activity and messsage (None if no activity selected)
'''
if self.checkbutton.get_active():
self.on_response(self.activity, self.subactivity,
2008-07-28 22:57:56 +02:00
self.entry.get_text().decode('utf-8'))
else:
self.on_response(None, None, '')
2008-07-28 22:57:56 +02:00
self.window.destroy()
def on_cancel_button_clicked(self, widget):
self.window.destroy()
2007-03-31 00:52:11 +02:00
class ChangeMoodDialog:
2008-07-23 00:20:51 +02:00
COLS = 11
def __init__(self, on_response, mood=None, text=''):
self.on_response = on_response
self.mood = mood
self.text = text
2007-03-31 00:52:11 +02:00
self.xml = gtkgui_helpers.get_glade('change_mood_dialog.glade')
2008-07-23 00:20:51 +02:00
2007-03-31 00:52:11 +02:00
self.window = self.xml.get_widget('change_mood_dialog')
self.window.set_transient_for(gajim.interface.roster.window)
self.window.set_title(_('Set Mood'))
2007-03-31 00:52:11 +02:00
2008-07-23 00:20:51 +02:00
table = self.xml.get_widget('mood_icons_table')
self.label = self.xml.get_widget('mood_label')
self.entry = self.xml.get_widget('description_entry')
2007-03-31 09:43:33 +02:00
2008-07-23 00:20:51 +02:00
no_mood_button = self.xml.get_widget('no_mood_button')
no_mood_button.set_mode(False)
no_mood_button.connect('clicked',
self.on_mood_button_clicked, None)
x = 1
y = 0
self.mood_buttons = {}
2008-07-29 21:02:57 +02:00
# Order them first
self.MOODS = []
2008-07-23 00:20:51 +02:00
for mood in pep.MOODS:
2008-07-29 21:02:57 +02:00
self.MOODS.append(mood)
self.MOODS.sort()
for mood in self.MOODS:
self.mood_buttons[mood] = gtk.RadioButton(no_mood_button)
2008-07-23 00:20:51 +02:00
self.mood_buttons[mood].set_mode(False)
2008-07-29 21:02:57 +02:00
self.mood_buttons[mood].add(gtkgui_helpers.load_mood_icon(mood))
2008-07-23 00:20:51 +02:00
self.mood_buttons[mood].set_relief(gtk.RELIEF_NONE)
2008-07-29 21:02:57 +02:00
gtk.Tooltips().set_tip(self.mood_buttons[mood], pep.MOODS[mood])
2008-07-23 00:20:51 +02:00
self.mood_buttons[mood].connect('clicked',
self.on_mood_button_clicked, mood)
2008-07-29 21:02:57 +02:00
table.attach(self.mood_buttons[mood], x, x + 1, y, y + 1)
2008-12-03 22:56:12 +01:00
2008-07-23 00:20:51 +02:00
# Calculate the next position
x += 1
if x >= self.COLS:
x = 0
y += 1
2007-03-31 09:43:33 +02:00
if self.mood in pep.MOODS:
self.mood_buttons[self.mood].set_active(True)
self.label.set_text(pep.MOODS[self.mood])
2008-07-29 08:59:14 +02:00
self.entry.set_sensitive(True)
if self.text:
self.entry.set_text(self.text)
2008-07-29 08:59:14 +02:00
else:
self.label.set_text(_('None'))
self.entry.set_text('')
2008-07-29 08:59:14 +02:00
self.entry.set_sensitive(False)
self.xml.signal_autoconnect(self)
2009-04-05 20:35:59 +02:00
self.window.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
self.window.show_all()
2007-03-31 09:43:33 +02:00
2008-07-23 00:20:51 +02:00
def on_mood_button_clicked(self, widget, data):
if data:
2008-07-29 21:02:57 +02:00
self.label.set_text(pep.MOODS[data])
2008-07-23 00:20:51 +02:00
self.entry.set_sensitive(True)
else:
self.label.set_text(_('None'))
2008-07-23 00:20:51 +02:00
self.entry.set_text('')
self.entry.set_sensitive(False)
self.mood = data
def on_ok_button_clicked(self, widget):
'''Return mood and messsage (None if no mood selected)'''
2008-07-23 00:20:51 +02:00
message = self.entry.get_text().decode('utf-8')
self.on_response(self.mood, message)
2008-07-23 00:20:51 +02:00
self.window.destroy()
2007-03-31 00:52:11 +02:00
def on_cancel_button_clicked(self, widget):
self.window.destroy()
2007-03-31 00:52:11 +02:00
class ChangeStatusMessageDialog:
def __init__(self, on_response, show=None, show_pep=True):
self.show = show
self.pep_dict = {}
self.show_pep = show_pep
self.on_response = on_response
self.xml = gtkgui_helpers.get_glade('change_status_message_dialog.glade')
2005-04-04 18:46:35 +02:00
self.window = self.xml.get_widget('change_status_message_dialog')
2006-09-13 18:47:58 +02:00
self.window.set_transient_for(gajim.interface.roster.window)
msg = None
if show:
uf_show = helpers.get_uf_show(show)
2007-06-03 12:04:20 +02:00
self.title_text = _('%s Status Message') % uf_show
msg = gajim.config.get_per('statusmsg', '_last_' + self.show,
'message')
self.pep_dict['activity'] = gajim.config.get_per('statusmsg',
'_last_' + self.show, 'activity')
self.pep_dict['subactivity'] = gajim.config.get_per('statusmsg',
'_last_' + self.show, 'subactivity')
self.pep_dict['activity_text'] = gajim.config.get_per('statusmsg',
'_last_' + self.show, 'activity_text')
self.pep_dict['mood'] = gajim.config.get_per('statusmsg',
'_last_' + self.show, 'mood')
self.pep_dict['mood_text'] = gajim.config.get_per('statusmsg',
'_last_' + self.show, 'mood_text')
else:
2007-06-03 12:04:20 +02:00
self.title_text = _('Status Message')
self.window.set_title(self.title_text)
2005-04-04 18:46:35 +02:00
message_textview = self.xml.get_widget('message_textview')
self.message_buffer = message_textview.get_buffer()
self.message_buffer.connect('changed',
self.toggle_sensitiviy_of_save_as_preset)
if not msg:
msg = ''
msg = helpers.from_one_line(msg)
self.message_buffer.set_text(msg)
# have an empty string selectable, so user can clear msg
self.preset_messages_dict = {'': ['', '', '', '', '', '']}
for msg_name in gajim.config.get_per('statusmsg'):
if msg_name.startswith('_last_'):
continue
opts = []
for opt in ['message', 'activity', 'subactivity', 'activity_text',
'mood', 'mood_text']:
opts.append(gajim.config.get_per('statusmsg', msg_name, opt))
opts[0] = helpers.from_one_line(opts[0])
self.preset_messages_dict[msg_name] = opts
sorted_keys_list = helpers.get_sorted_keys(self.preset_messages_dict)
countdown_time = gajim.config.get('change_status_window_timeout')
self.countdown_left = countdown_time
2007-06-03 12:04:20 +02:00
self.countdown_enabled = True
self.message_liststore = gtk.ListStore(str) # msg_name
self.message_combobox = self.xml.get_widget('message_combobox')
self.message_combobox.set_model(self.message_liststore)
cellrenderertext = gtk.CellRendererText()
self.message_combobox.pack_start(cellrenderertext, True)
self.message_combobox.add_attribute(cellrenderertext, 'text', 0)
for msg_name in sorted_keys_list:
self.message_liststore.append((msg_name,))
if show_pep:
self.draw_activity()
self.draw_mood()
else:
# remove acvtivity / mood lines
self.xml.get_widget('activity_label').set_no_show_all(True)
self.xml.get_widget('activity_button').set_no_show_all(True)
self.xml.get_widget('mood_label').set_no_show_all(True)
self.xml.get_widget('mood_button').set_no_show_all(True)
self.xml.get_widget('activity_label').hide()
self.xml.get_widget('activity_button').hide()
self.xml.get_widget('mood_label').hide()
self.xml.get_widget('mood_button').hide()
2005-04-04 18:46:35 +02:00
self.xml.signal_autoconnect(self)
if countdown_time > 0:
self.countdown()
gobject.timeout_add(1000, self.countdown)
self.window.connect('response', self.on_dialog_response)
2009-04-05 20:35:59 +02:00
self.window.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
2005-04-04 18:46:35 +02:00
self.window.show_all()
def draw_activity(self):
'''Set activity button'''
img = self.xml.get_widget('activity_image')
label = self.xml.get_widget('activity_button_label')
if 'activity' in self.pep_dict and self.pep_dict['activity'] in \
pep.ACTIVITIES:
if 'subactivity' in self.pep_dict and self.pep_dict['subactivity'] in \
pep.ACTIVITIES[self.pep_dict['activity']]:
img.set_from_pixbuf(gtkgui_helpers.load_activity_icon(
self.pep_dict['activity'], self.pep_dict['subactivity']).\
get_pixbuf())
else:
img.set_from_pixbuf(gtkgui_helpers.load_activity_icon(
self.pep_dict['activity']).get_pixbuf())
# gtk.Tooltips().set_tip(item, pep.ACTIVITIES[category]['category'])
if self.pep_dict['activity_text']:
label.set_text(self.pep_dict['activity_text'])
else:
label.set_text('')
else:
img.set_from_pixbuf(None)
label.set_text('')
def draw_mood(self):
'''Set mood button'''
img = self.xml.get_widget('mood_image')
label = self.xml.get_widget('mood_button_label')
if self.pep_dict['mood'] in pep.MOODS:
img.set_from_pixbuf(gtkgui_helpers.load_mood_icon(
self.pep_dict['mood']).get_pixbuf())
if self.pep_dict['mood_text']:
label.set_text(self.pep_dict['mood_text'])
else:
label.set_text('')
else:
img.set_from_pixbuf(None)
label.set_text('')
2007-06-03 12:04:20 +02:00
def countdown(self):
if self.countdown_enabled:
if self.countdown_left <= 0:
# Prevent GUI freeze when the combobox menu is opened on close
self.message_combobox.popdown()
2007-06-03 12:04:20 +02:00
self.window.response(gtk.RESPONSE_OK)
return False
self.window.set_title('%s [%s]' % (self.title_text,
str(self.countdown_left)))
self.countdown_left -= 1
return True
else:
self.window.set_title(self.title_text)
return False
def on_dialog_response(self, dialog, response):
if response == gtk.RESPONSE_OK:
beg, end = self.message_buffer.get_bounds()
message = self.message_buffer.get_text(beg, end).decode('utf-8')\
.strip()
message = helpers.remove_invalid_xml_chars(message)
msg = helpers.to_one_line(message)
if self.show:
gajim.config.set_per('statusmsg', '_last_' + self.show, 'message',
msg)
if self.show_pep:
gajim.config.set_per('statusmsg', '_last_' + self.show,
'activity', self.pep_dict['activity'])
gajim.config.set_per('statusmsg', '_last_' + self.show,
'subactivity', self.pep_dict['subactivity'])
gajim.config.set_per('statusmsg', '_last_' + self.show,
'activity_text', self.pep_dict['activity_text'])
gajim.config.set_per('statusmsg', '_last_' + self.show, 'mood',
self.pep_dict['mood'])
gajim.config.set_per('statusmsg', '_last_' + self.show,
'mood_text', self.pep_dict['mood_text'])
2004-05-15 18:50:38 +02:00
else:
message = None # user pressed Cancel button or X wm button
self.window.destroy()
self.on_response(message, self.pep_dict)
def on_message_combobox_changed(self, widget):
2007-06-03 12:04:20 +02:00
self.countdown_enabled = False
model = widget.get_model()
active = widget.get_active()
if active < 0:
return None
name = model[active][0].decode('utf-8')
self.message_buffer.set_text(self.preset_messages_dict[name][0])
self.pep_dict['activity'] = self.preset_messages_dict[name][1]
self.pep_dict['subactivity'] = self.preset_messages_dict[name][2]
self.pep_dict['activity_text'] = self.preset_messages_dict[name][3]
self.pep_dict['mood'] = self.preset_messages_dict[name][4]
self.pep_dict['mood_text'] = self.preset_messages_dict[name][5]
self.draw_activity()
self.draw_mood()
def on_change_status_message_dialog_key_press_event(self, widget, event):
2007-06-03 12:04:20 +02:00
self.countdown_enabled = False
2005-03-18 02:28:59 +01:00
if event.keyval == gtk.keysyms.Return or \
2007-12-12 09:44:46 +01:00
event.keyval == gtk.keysyms.KP_Enter: # catch CTRL+ENTER
if (event.state & gtk.gdk.CONTROL_MASK):
self.window.response(gtk.RESPONSE_OK)
2007-06-03 12:04:20 +02:00
# Stop the event
return True
2005-04-04 18:46:35 +02:00
def toggle_sensitiviy_of_save_as_preset(self, widget):
btn = self.xml.get_widget('save_as_preset_button')
if self.message_buffer.get_char_count() == 0:
btn.set_sensitive(False)
else:
btn.set_sensitive(True)
def on_save_as_preset_button_clicked(self, widget):
2007-06-03 12:04:20 +02:00
self.countdown_enabled = False
start_iter, finish_iter = self.message_buffer.get_bounds()
status_message_to_save_as_preset = self.message_buffer.get_text(
start_iter, finish_iter)
2008-08-07 15:25:25 +02:00
def on_ok(msg_name):
msg_text = status_message_to_save_as_preset.decode('utf-8')
msg_text_1l = helpers.to_one_line(msg_text)
if not msg_name: # msg_name was ''
2008-08-07 23:59:20 +02:00
msg_name = msg_text_1l.decode('utf-8')
def on_ok2():
self.preset_messages_dict[msg_name] = [msg_text, self.pep_dict.get(
'activity'), self.pep_dict.get('subactivity'), self.pep_dict.get(
'activity_text'), self.pep_dict.get('mood'), self.pep_dict.get(
'mood_text')]
gajim.config.set_per('statusmsg', msg_name, 'message', msg_text_1l)
gajim.config.set_per('statusmsg', msg_name, 'activity',
self.pep_dict.get('activity'))
gajim.config.set_per('statusmsg', msg_name, 'subactivity',
self.pep_dict.get('subactivity'))
gajim.config.set_per('statusmsg', msg_name, 'activity_text',
self.pep_dict.get('activity_text'))
gajim.config.set_per('statusmsg', msg_name, 'mood',
self.pep_dict.get('mood'))
gajim.config.set_per('statusmsg', msg_name, 'mood_text',
self.pep_dict.get('mood_text'))
2007-08-09 17:39:18 +02:00
if msg_name in self.preset_messages_dict:
2008-12-02 16:53:23 +01:00
ConfirmationDialog(_('Overwrite Status Message?'),
2008-08-06 22:55:40 +02:00
_('This name is already used. Do you want to overwrite this '
2008-08-07 15:25:25 +02:00
'status message?'), on_response_ok=on_ok2)
2008-08-06 22:55:40 +02:00
return
gajim.config.add_per('statusmsg', msg_name)
on_ok2()
iter_ = self.message_liststore.append((msg_name,))
2008-08-06 22:55:40 +02:00
# select in combobox the one we just saved
self.message_combobox.set_active_iter(iter_)
2008-08-07 15:25:25 +02:00
InputDialog(_('Save as Preset Status Message'),
_('Please type a name for this status message'), is_modal=False,
ok_handler=on_ok)
def on_activity_button_clicked(self, widget):
self.countdown_enabled = False
def on_response(activity, subactivity, text):
self.pep_dict['activity'] = activity
self.pep_dict['subactivity'] = subactivity
self.pep_dict['activity_text'] = text
self.draw_activity()
ChangeActivityDialog(on_response, self.pep_dict['activity'],
self.pep_dict['subactivity'], self.pep_dict['activity_text'])
def on_mood_button_clicked(self, widget):
self.countdown_enabled = False
def on_response(mood, text):
self.pep_dict['mood'] = mood
self.pep_dict['mood_text'] = text
self.draw_mood()
ChangeMoodDialog(on_response, self.pep_dict['mood'],
self.pep_dict['mood_text'])
class AddNewContactWindow:
'''Class for AddNewContactWindow'''
2006-11-18 21:52:28 +01:00
uid_labels = {'jabber': _('Jabber ID:'),
'aim': _('AIM Address:'),
'gadu-gadu': _('GG Number:'),
'icq': _('ICQ Number:'),
'msn': _('MSN Address:'),
'yahoo': _('Yahoo! Address:')}
2008-09-03 13:25:27 +02:00
def __init__(self, account=None, jid=None, user_nick=None, group=None):
2005-04-04 18:46:35 +02:00
self.account = account
if account is None:
# fill accounts with active accounts
accounts = []
for account in gajim.connections.keys():
if gajim.connections[account].connected > 1:
accounts.append(account)
if not accounts:
return
if len(accounts) == 1:
self.account = account
else:
accounts = [self.account]
2006-09-13 18:47:58 +02:00
if self.account:
location = gajim.interface.instances[self.account]
else:
location = gajim.interface.instances
if 'add_contact' in location:
2006-09-13 18:47:58 +02:00
location['add_contact'].window.present()
# An instance is already opened
return
location['add_contact'] = self
self.xml = gtkgui_helpers.get_glade('add_new_contact_window.glade')
2007-12-12 09:44:46 +01:00
self.xml.signal_autoconnect(self)
2005-04-04 18:46:35 +02:00
self.window = self.xml.get_widget('add_new_contact_window')
2006-09-13 18:47:58 +02:00
for w in ('account_combobox', 'account_hbox', 'account_label',
'uid_label', 'uid_entry', 'protocol_combobox', 'protocol_jid_combobox',
'protocol_hbox', 'nickname_entry', 'message_scrolledwindow',
'register_hbox', 'subscription_table', 'add_button',
2006-11-18 21:52:28 +01:00
'message_textview', 'connected_label', 'group_comboboxentry',
'auto_authorize_checkbutton'):
2006-09-13 18:47:58 +02:00
self.__dict__[w] = self.xml.get_widget(w)
if account and len(gajim.connections) >= 2:
2005-06-13 15:19:54 +02:00
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)
2006-09-13 18:47:58 +02:00
self.agents = {'jabber': []}
# types to which we are not subscribed but account has an agent for it
self.available_types = []
for acct in accounts:
for j in gajim.contacts.get_jid_list(acct):
if gajim.jid_is_transport(j):
2007-06-03 12:04:20 +02:00
type_ = gajim.get_transport_name_from_jid(j, False)
2007-08-09 17:39:18 +02:00
if not type_:
continue
if type_ in self.agents:
2006-09-13 18:47:58 +02:00
self.agents[type_].append(j)
else:
self.agents[type_] = [j]
# Now add the one to which we can register
for acct in accounts:
2007-06-03 12:04:20 +02:00
for type_ in gajim.connections[acct].available_transports:
2006-09-13 18:47:58 +02:00
if type_ in self.agents:
continue
self.agents[type_] = []
2007-06-03 12:04:20 +02:00
for jid_ in gajim.connections[acct].available_transports[type_]:
if not jid_ in self.agents[type_]:
self.agents[type_].append(jid_)
2006-09-13 18:47:58 +02:00
self.available_types.append(type_)
liststore = gtk.ListStore(str)
self.group_comboboxentry.set_model(liststore)
2007-08-09 17:39:18 +02:00
# Combobox with transport/jabber icons
liststore = gtk.ListStore(str, gtk.gdk.Pixbuf, str)
cell = gtk.CellRendererPixbuf()
self.protocol_combobox.pack_start(cell, False)
self.protocol_combobox.add_attribute(cell, 'pixbuf', 1)
cell = gtk.CellRendererText()
cell.set_property('xpad', 5)
self.protocol_combobox.pack_start(cell, True)
self.protocol_combobox.add_attribute(cell, 'text', 0)
self.protocol_combobox.set_model(liststore)
2006-09-13 18:47:58 +02:00
uf_type = {'jabber': 'Jabber', 'aim': 'AIM', 'gadu-gadu': 'Gadu Gadu',
'icq': 'ICQ', 'msn': 'MSN', 'yahoo': 'Yahoo'}
# Jabber as first
img = gajim.interface.jabber_state_images['16']['online']
2007-08-09 17:39:18 +02:00
liststore.append(['Jabber', img.get_pixbuf(), 'jabber'])
2006-09-13 18:47:58 +02:00
for type_ in self.agents:
if type_ == 'jabber':
continue
2007-08-09 17:39:18 +02:00
imgs = gajim.interface.roster.transports_state_images
img = None
if type_ in imgs['16'] and 'online' in imgs['16'][type_]:
2007-08-09 17:39:18 +02:00
img = imgs['16'][type_]['online']
if type_ in uf_type:
liststore.append([uf_type[type_], img.get_pixbuf(), type_])
else:
liststore.append([type_, img.get_pixbuf(), type_])
2005-04-04 18:46:35 +02:00
else:
2007-08-09 17:39:18 +02:00
liststore.append([type_, img, type_])
self.protocol_combobox.set_active(0)
2006-11-18 21:52:28 +01:00
self.auto_authorize_checkbutton.show()
2006-09-13 18:47:58 +02:00
liststore = gtk.ListStore(str)
self.protocol_jid_combobox.set_model(liststore)
2005-04-04 18:46:35 +02:00
if jid:
2006-11-18 21:52:28 +01:00
type_ = gajim.get_transport_name_from_jid(jid)
if not type_:
type_ = 'jabber'
2006-09-13 18:47:58 +02:00
if type_ == 'jabber':
self.uid_entry.set_text(jid)
2006-09-13 18:47:58 +02:00
else:
2006-11-18 21:52:28 +01:00
uid, transport = gajim.get_name_and_server_from_jid(jid)
2006-09-13 18:47:58 +02:00
self.uid_entry.set_text(uid.replace('%', '@', 1))
#set protocol_combobox
model = self.protocol_combobox.get_model()
2008-12-03 18:16:04 +01:00
iter_ = model.get_iter_first()
2006-09-13 18:47:58 +02:00
i = 0
2008-12-03 18:16:04 +01:00
while iter_:
if model[iter_][2] == type_:
2006-09-13 18:47:58 +02:00
self.protocol_combobox.set_active(i)
break
2008-12-03 18:16:04 +01:00
iter_ = model.iter_next(iter_)
2006-09-13 18:47:58 +02:00
i += 1
# set protocol_jid_combobox
2006-11-18 21:52:28 +01:00
self.protocol_jid_combobox.set_active(0)
2006-09-13 18:47:58 +02:00
model = self.protocol_jid_combobox.get_model()
2008-12-03 18:16:04 +01:00
iter_ = model.get_iter_first()
2006-09-13 18:47:58 +02:00
i = 0
2008-12-03 18:16:04 +01:00
while iter_:
if model[iter_][0] == transport:
2006-11-18 21:52:28 +01:00
self.protocol_jid_combobox.set_active(i)
2006-09-13 18:47:58 +02:00
break
2008-12-03 18:16:04 +01:00
iter_ = model.iter_next(iter_)
2006-09-13 18:47:58 +02:00
i += 1
if user_nick:
self.nickname_entry.set_text(user_nick)
self.nickname_entry.grab_focus()
2006-09-13 18:47:58 +02:00
else:
self.uid_entry.grab_focus()
group_names = []
for acct in accounts:
for g in gajim.groups[acct].keys():
if g not in helpers.special_groups and g not in group_names:
group_names.append(g)
2006-09-13 18:47:58 +02:00
group_names.sort()
i = 0
for g in group_names:
self.group_comboboxentry.append_text(g)
if group == g:
self.group_comboboxentry.set_active(i)
i += 1
2007-12-12 09:44:46 +01:00
self.window.show_all()
if self.account:
self.account_label.hide()
2006-05-20 00:30:23 +02:00
self.account_hbox.hide()
else:
liststore = gtk.ListStore(str, str)
for acct in accounts:
liststore.append([acct, acct])
self.account_combobox.set_model(liststore)
self.account_combobox.set_active(0)
2004-05-15 18:50:38 +02:00
2006-09-13 18:47:58 +02:00
def on_add_new_contact_window_destroy(self, widget):
if self.account:
location = gajim.interface.instances[self.account]
else:
location = gajim.interface.instances
del location['add_contact']
def on_register_button_clicked(self, widget):
jid = self.protocol_jid_combobox.get_active_text().decode('utf-8')
gajim.connections[self.account].request_register_agent_info(jid)
def on_add_new_contact_window_key_press_event(self, widget, event):
if event.keyval == gtk.keysyms.Escape: # ESCAPE
self.window.destroy()
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
2006-09-13 18:47:58 +02:00
def on_add_button_clicked(self, widget):
2005-04-18 14:17:43 +02:00
'''When Subscribe button is clicked'''
2006-09-13 18:47:58 +02:00
jid = self.uid_entry.get_text().decode('utf-8')
if not jid:
2004-11-18 20:22:33 +01:00
return
2006-09-13 18:47:58 +02:00
model = self.protocol_combobox.get_model()
2008-12-03 18:16:04 +01:00
iter_ = self.protocol_combobox.get_active_iter()
type_ = model[iter_][2]
2006-09-13 18:47:58 +02:00
if type_ != 'jabber':
transport = self.protocol_jid_combobox.get_active_text().decode(
'utf-8')
jid = jid.replace('@', '%') + '@' + transport
# check if jid is conform to RFC and stringprep it
try:
jid = helpers.parse_jid(jid)
except helpers.InvalidFormat, s:
2005-11-02 15:54:25 +01:00
pritext = _('Invalid User ID')
ErrorDialog(pritext, str(s))
2004-11-18 20:22:33 +01:00
return
# No resource in jid
if jid.find('/') >= 0:
pritext = _('Invalid User ID')
ErrorDialog(pritext, _('The user ID must not contain a resource.'))
return
if jid == gajim.get_jid_from_account(self.account):
pritext = _('Invalid User ID')
ErrorDialog(pritext, _('You cannot add yourself to your roster.'))
return
2006-09-13 18:47:58 +02:00
nickname = self.nickname_entry.get_text().decode('utf-8') or ''
# get value of account combobox, if account was not specified
if not self.account:
model = self.account_combobox.get_model()
index = self.account_combobox.get_active()
self.account = model[index][1]
# Check if jid is already in roster
if jid in gajim.contacts.get_jid_list(self.account):
c = gajim.contacts.get_first_contact_from_jid(self.account, jid)
if _('Not in Roster') not in c.groups and c.sub in ('both', 'to'):
ErrorDialog(_('Contact already in roster'),
_('This contact is already listed in your roster.'))
return
2006-09-13 18:47:58 +02:00
if type_ == 'jabber':
message_buffer = self.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).decode('utf-8')
else:
message= ''
group = self.group_comboboxentry.child.get_text().decode('utf-8')
groups = []
if group:
groups = [group]
2006-11-18 21:52:28 +01:00
auto_auth = self.auto_authorize_checkbutton.get_active()
gajim.interface.roster.req_sub(self, jid, message, self.account,
groups = groups, nickname = nickname, auto_auth = auto_auth)
2005-04-12 17:30:09 +02:00
self.window.destroy()
2005-02-03 23:21:55 +01:00
2005-03-23 14:25:48 +01:00
def on_protocol_combobox_changed(self, widget):
2006-09-13 18:47:58 +02:00
model = widget.get_model()
2008-12-03 18:16:04 +01:00
iter_ = widget.get_active_iter()
type_ = model[iter_][2]
2006-09-13 18:47:58 +02:00
model = self.protocol_jid_combobox.get_model()
model.clear()
if len(self.agents[type_]):
for jid_ in self.agents[type_]:
model.append([jid_])
self.protocol_jid_combobox.set_active(0)
2006-11-18 21:52:28 +01:00
if len(self.agents[type_]) > 1:
2007-12-12 09:44:46 +01:00
self.protocol_jid_combobox.show()
2006-09-13 18:47:58 +02:00
else:
2006-11-18 21:52:28 +01:00
self.protocol_jid_combobox.hide()
2006-09-13 18:47:58 +02:00
if type_ in self.uid_labels:
self.uid_label.set_text(self.uid_labels[type_])
else:
2006-11-18 21:52:28 +01:00
self.uid_label.set_text(_('User ID:'))
2006-09-13 18:47:58 +02:00
if type_ == 'jabber':
self.message_scrolledwindow.show()
else:
self.message_scrolledwindow.hide()
if type_ in self.available_types:
2007-12-12 09:44:46 +01:00
self.register_hbox.show()
2006-11-18 21:52:28 +01:00
self.auto_authorize_checkbutton.hide()
2006-09-13 18:47:58 +02:00
self.connected_label.hide()
self.subscription_table.hide()
self.add_button.set_sensitive(False)
else:
self.register_hbox.hide()
if type_ != 'jabber':
jid = self.protocol_jid_combobox.get_active_text()
contact = gajim.contacts.get_first_contact_from_jid(self.account,
jid)
if contact.show in ('offline', 'error'):
self.subscription_table.hide()
self.connected_label.show()
self.add_button.set_sensitive(False)
2006-11-18 21:52:28 +01:00
self.auto_authorize_checkbutton.hide()
2006-09-13 18:47:58 +02:00
return
2007-12-12 09:44:46 +01:00
self.subscription_table.show()
2006-11-18 21:52:28 +01:00
self.auto_authorize_checkbutton.show()
2006-09-13 18:47:58 +02:00
self.connected_label.hide()
self.add_button.set_sensitive(True)
def transport_signed_in(self, jid):
if self.protocol_jid_combobox.get_active_text() == jid:
self.register_hbox.hide()
self.connected_label.hide()
2007-12-12 09:44:46 +01:00
self.subscription_table.show()
self.auto_authorize_checkbutton.show()
2006-09-13 18:47:58 +02:00
self.add_button.set_sensitive(True)
def transport_signed_out(self, jid):
if self.protocol_jid_combobox.get_active_text() == jid:
self.subscription_table.hide()
2007-12-12 09:44:46 +01:00
self.auto_authorize_checkbutton.hide()
2006-09-13 18:47:58 +02:00
self.connected_label.show()
self.add_button.set_sensitive(False)
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-03-09 22:29:20 +01:00
dlg = gtk.AboutDialog()
2006-09-13 18:47:58 +02:00
dlg.set_transient_for(gajim.interface.roster.window)
2005-03-09 22:29:20 +01:00
dlg.set_name('Gajim')
dlg.set_version(gajim.version)
2009-03-14 13:36:02 +01:00
s = u'Copyright © 2003-2009 Gajim Team'
2005-03-16 03:16:29 +01:00
dlg.set_copyright(s)
copying_file_path = self.get_path('COPYING')
2006-11-18 21:52:28 +01:00
if copying_file_path:
text = open(copying_file_path).read()
dlg.set_license(text)
dlg.set_comments('%s\n%s %s\n%s %s'
% (_('A GTK+ jabber client'), \
_('GTK+ Version:'), self.tuple2str(gtk.gtk_version), \
_('PyGTK Version:'), self.tuple2str(gtk.pygtk_version)))
2006-09-13 18:47:58 +02:00
dlg.set_website('http://www.gajim.org/')
authors_file_path = self.get_path('AUTHORS')
2006-11-18 21:52:28 +01:00
if authors_file_path:
authors = []
authors_file = open(authors_file_path).read()
authors_file = authors_file.split('\n')
for author in authors_file:
if author == 'CURRENT DEVELOPERS:':
authors.append(_('Current Developers:'))
elif author == 'PAST DEVELOPERS:':
authors.append('\n' + _('Past Developers:'))
elif author != '': # Real author line
authors.append(author)
thanks_file_path = self.get_path('THANKS')
2006-11-18 21:52:28 +01:00
if thanks_file_path:
authors.append('\n' + _('THANKS:'))
2006-11-18 21:52:28 +01:00
text = open(thanks_file_path).read()
text_splitted = text.split('\n')
text = '\n'.join(text_splitted[:-2]) # remove one english sentence
# and add it manually as translatable
text += '\n%s\n' % _('Last but not least, we would like to thank all '
'the package maintainers.')
authors.append(text)
2006-11-18 21:52:28 +01:00
dlg.set_authors(authors)
dlg.props.wrap_license = True
2005-09-24 23:50:58 +02:00
pixbuf = gtk.gdk.pixbuf_new_from_file(os.path.join(
gajim.DATA_DIR, 'pixmaps', 'gajim_about.png'))
dlg.set_logo(pixbuf)
2005-09-24 23:49:28 +02:00
#here you write your name in the form Name FamilyName <someone@somewhere>
2005-08-13 13:17:49 +02:00
dlg.set_translator_credits(_('translator-credits'))
2008-12-03 22:56:12 +01:00
thanks_artists_file_path = self.get_path('THANKS.artists')
if thanks_artists_file_path:
artists_text = open(thanks_artists_file_path).read()
artists = artists_text.split('\n')
dlg.set_artists(artists)
# connect close button to destroy() function
for button in dlg.action_area.get_children():
if button.get_property('label') == gtk.STOCK_CLOSE:
button.connect('clicked', lambda x:dlg.destroy())
dlg.show_all()
2006-04-25 22:38:16 +02:00
def tuple2str(self, tuple_):
str_ = ''
2006-04-25 22:38:16 +02:00
for num in tuple_:
str_ += str(num) + '.'
return str_[0:-1] # remove latest .
2004-05-15 18:50:38 +02:00
def get_path(self, filename):
'''where can we find this Credits file ?'''
if os.path.isfile(os.path.join(gajim.defs.docdir, filename)):
return os.path.join(gajim.defs.docdir, filename)
elif os.path.isfile('../' + filename):
return ('../' + filename)
else:
return None
2005-06-07 03:10:24 +02:00
class Dialog(gtk.Dialog):
2008-09-03 13:25:27 +02:00
def __init__(self, parent, title, buttons, default=None,
on_response_ok=None, on_response_cancel=None):
gtk.Dialog.__init__(self, title, parent, gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_NO_SEPARATOR)
2005-06-07 03:10:24 +02:00
self.user_response_ok = on_response_ok
self.user_response_cancel = on_response_cancel
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
possible_responses = {gtk.STOCK_OK: self.on_response_ok,
gtk.STOCK_CANCEL: self.on_response_cancel}
2005-06-12 19:36:27 +02:00
for stock, response in buttons:
b = self.add_button(stock, response)
for response in possible_responses:
if stock == response:
b.connect('clicked', possible_responses[response])
break
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
def on_response_ok(self, widget):
if self.user_response_ok:
if isinstance(self.user_response_ok, tuple):
self.user_response_ok[0](*self.user_response_ok[1:])
else:
self.user_response_ok()
self.destroy()
def on_response_cancel(self, widget):
if self.user_response_cancel:
if isinstance(self.user_response_cancel, tuple):
self.user_response_cancel[0](*self.user_response_ok[1:])
else:
self.user_response_cancel()
self.destroy()
def just_destroy(self, widget):
self.destroy()
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
class HigDialog(gtk.MessageDialog):
def __init__(self, parent, type_, buttons, pritext, sectext,
on_response_ok = None, on_response_cancel = None, on_response_yes = None,
on_response_no = None):
gtk.MessageDialog.__init__(self, parent,
gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_MODAL,
type_, buttons, message_format = pritext)
self.format_secondary_markup(sectext)
buttons = self.action_area.get_children()
possible_responses = {gtk.STOCK_OK: on_response_ok,
gtk.STOCK_CANCEL: on_response_cancel, gtk.STOCK_YES: on_response_yes,
gtk.STOCK_NO: on_response_no}
for b in buttons:
for response in possible_responses:
if b.get_label() == response:
if not possible_responses[response]:
b.connect('clicked', self.just_destroy)
elif isinstance(possible_responses[response], tuple):
2006-04-08 12:34:47 +02:00
if len(possible_responses[response]) == 1:
b.connect('clicked', possible_responses[response][0])
else:
b.connect('clicked', *possible_responses[response])
else:
b.connect('clicked', possible_responses[response])
break
def just_destroy(self, widget):
self.destroy()
def popup(self):
'''show dialog'''
vb = self.get_children()[0].get_children()[0] # Give focus to top vbox
vb.set_flags(gtk.CAN_FOCUS)
vb.grab_focus()
self.show_all()
class FileChooserDialog(gtk.FileChooserDialog):
'''Non-blocking FileChooser Dialog around gtk.FileChooserDialog'''
def __init__(self, title_text, action, buttons, default_response,
select_multiple = False, current_folder = None, on_response_ok = None,
on_response_cancel = None):
2008-09-03 13:25:27 +02:00
gtk.FileChooserDialog.__init__(self, title=title_text, action=action,
buttons=buttons)
self.set_default_response(default_response)
self.set_select_multiple(select_multiple)
if current_folder and os.path.isdir(current_folder):
self.set_current_folder(current_folder)
else:
self.set_current_folder(helpers.get_documents_path())
2006-11-18 21:52:28 +01:00
self.response_ok, self.response_cancel = \
on_response_ok, on_response_cancel
# in gtk+-2.10 clicked signal on some of the buttons in a dialog
# is emitted twice, so we cannot rely on 'clicked' signal
self.connect('response', self.on_dialog_response)
self.show_all()
2006-11-18 21:52:28 +01:00
def on_dialog_response(self, dialog, response):
if response in (gtk.RESPONSE_CANCEL, gtk.RESPONSE_CLOSE):
if self.response_cancel:
if isinstance(self.response_cancel, tuple):
self.response_cancel[0](dialog, *self.response_cancel[1:])
else:
self.response_cancel(dialog)
else:
self.just_destroy(dialog)
elif response == gtk.RESPONSE_OK:
if self.response_ok:
if isinstance(self.response_ok, tuple):
self.response_ok[0](dialog, *self.response_ok[1:])
else:
self.response_ok(dialog)
else:
self.just_destroy(dialog)
def just_destroy(self, widget):
self.destroy()
2008-05-02 18:15:39 +02:00
class AspellDictError:
2007-06-03 12:04:20 +02:00
def __init__(self, lang):
ErrorDialog(
_('Dictionary for lang %s not available') % lang,
_('You have to install %s dictionary to use spellchecking, or '
'choose another language by setting the speller_language option.'
'\n\nHighlighting misspelled words feature will not be used') % lang)
gajim.config.set('use_speller', False)
class ConfirmationDialog(HigDialog):
2005-10-13 21:44:09 +02:00
'''HIG compliant confirmation dialog.'''
2008-08-06 22:55:40 +02:00
def __init__(self, pritext, sectext='', on_response_ok=None,
on_response_cancel=None):
2007-12-12 09:44:46 +01:00
self.user_response_ok = on_response_ok
self.user_response_cancel = on_response_cancel
HigDialog.__init__(self, None,
gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, pritext, sectext,
2007-12-12 09:44:46 +01:00
self.on_response_ok, self.on_response_cancel)
self.popup()
2007-12-12 09:44:46 +01:00
def on_response_ok(self, widget):
if self.user_response_ok:
if isinstance(self.user_response_ok, tuple):
self.user_response_ok[0](*self.user_response_ok[1:])
else:
self.user_response_ok()
self.destroy()
def on_response_cancel(self, widget):
if self.user_response_cancel:
if isinstance(self.user_response_cancel, tuple):
self.user_response_cancel[0](*self.user_response_ok[1:])
else:
self.user_response_cancel()
self.destroy()
2006-04-08 19:02:55 +02:00
class NonModalConfirmationDialog(HigDialog):
'''HIG compliant non modal confirmation dialog.'''
2008-09-03 13:25:27 +02:00
def __init__(self, pritext, sectext='', on_response_ok=None,
on_response_cancel=None):
2007-12-12 09:44:46 +01:00
self.user_response_ok = on_response_ok
self.user_response_cancel = on_response_cancel
HigDialog.__init__(self, None,
2006-04-08 19:02:55 +02:00
gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, pritext, sectext,
2007-12-12 09:44:46 +01:00
self.on_response_ok, self.on_response_cancel)
2006-04-08 19:02:55 +02:00
self.set_modal(False)
2007-12-12 09:44:46 +01:00
def on_response_ok(self, widget):
if self.user_response_ok:
if isinstance(self.user_response_ok, tuple):
self.user_response_ok[0](*self.user_response_ok[1:])
else:
self.user_response_ok()
self.destroy()
def on_response_cancel(self, widget):
if self.user_response_cancel:
if isinstance(self.user_response_cancel, tuple):
self.user_response_cancel[0](*self.user_response_cancel[1:])
else:
self.user_response_cancel()
self.destroy()
class WarningDialog(HigDialog):
def __init__(self, pritext, sectext=''):
2005-10-13 21:44:09 +02:00
'''HIG compliant warning dialog.'''
HigDialog.__init__( self, None,
gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, pritext, sectext)
self.set_modal(False)
self.set_transient_for(gajim.interface.roster.window)
self.popup()
class InformationDialog(HigDialog):
def __init__(self, pritext, sectext=''):
2005-10-13 21:44:09 +02:00
'''HIG compliant info dialog.'''
HigDialog.__init__(self, None,
gtk.MESSAGE_INFO, gtk.BUTTONS_OK, pritext, sectext)
self.set_modal(False)
self.set_transient_for(gajim.interface.roster.window)
self.popup()
class ErrorDialog(HigDialog):
def __init__(self, pritext, sectext=''):
2005-10-13 21:44:09 +02:00
'''HIG compliant error dialog.'''
HigDialog.__init__( self, None,
gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, pritext, sectext)
self.popup()
class YesNoDialog(HigDialog):
def __init__(self, pritext, sectext='', checktext='', on_response_yes=None,
on_response_no=None):
'''HIG compliant YesNo dialog.'''
self.user_response_yes = on_response_yes
self.user_response_no = on_response_no
HigDialog.__init__( self, None,
gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, pritext, sectext,
on_response_yes=self.on_response_yes,
on_response_no=self.on_response_no)
if checktext:
self.checkbutton = gtk.CheckButton(checktext)
self.vbox.pack_start(self.checkbutton, expand=False, fill=True)
else:
self.checkbutton = None
2007-12-12 09:44:46 +01:00
self.set_modal(False)
2006-04-06 13:04:41 +02:00
self.popup()
def on_response_yes(self, widget):
if self.user_response_yes:
if isinstance(self.user_response_yes, tuple):
self.user_response_yes[0](self.is_checked(),
*self.user_response_yes[1:])
else:
self.user_response_yes(self.is_checked())
self.destroy()
def on_response_no(self, widget):
if self.user_response_no:
if isinstance(self.user_response_no, tuple):
self.user_response_no[0](*self.user_response_no[1:])
else:
self.user_response_no()
self.destroy()
def is_checked(self):
''' Get active state of the checkbutton '''
if not self.checkbutton:
return False
return self.checkbutton.get_active()
2005-07-29 19:18:51 +02:00
class ConfirmationDialogCheck(ConfirmationDialog):
'''HIG compliant confirmation dialog with checkbutton.'''
2008-09-03 13:25:27 +02:00
def __init__(self, pritext, sectext='', checktext='',
on_response_ok=None, on_response_cancel=None, is_modal=True):
2007-12-12 09:44:46 +01:00
self.user_response_ok = on_response_ok
self.user_response_cancel = on_response_cancel
HigDialog.__init__(self, None, gtk.MESSAGE_QUESTION,
2007-12-12 09:44:46 +01:00
gtk.BUTTONS_OK_CANCEL, pritext, sectext, self.on_response_ok,
self.on_response_cancel)
self.set_default_response(gtk.RESPONSE_OK)
ok_button = self.action_area.get_children()[0] # right to left
ok_button.grab_focus()
2005-07-29 19:18:51 +02:00
self.checkbutton = gtk.CheckButton(checktext)
2008-09-03 13:25:27 +02:00
self.vbox.pack_start(self.checkbutton, expand=False, fill=True)
2007-12-12 09:44:46 +01:00
self.set_modal(is_modal)
2006-04-04 16:49:56 +02:00
self.popup()
2007-12-12 09:44:46 +01:00
# XXX should cancel if somebody closes the dialog
def on_response_ok(self, widget):
if self.user_response_ok:
if isinstance(self.user_response_ok, tuple):
self.user_response_ok[0](self.is_checked(),
*self.user_response_ok[1:])
else:
self.user_response_ok(self.is_checked())
self.destroy()
def on_response_cancel(self, widget):
if self.user_response_cancel:
if isinstance(self.user_response_cancel, tuple):
self.user_response_cancel[0](self.is_checked(),
*self.user_response_cancel[1:])
2007-12-12 09:44:46 +01:00
else:
self.user_response_cancel(self.is_checked())
2007-12-12 09:44:46 +01:00
self.destroy()
2005-07-29 19:18:51 +02:00
def is_checked(self):
''' Get active state of the checkbutton '''
return self.checkbutton.get_active()
Merged revisions 5017-5020,5022-5029 via svnmerge from svn://svn.gajim.org/gajim/trunk ........ r5017 | asterix | 2006-01-06 01:55:51 -0700 (Fri, 06 Jan 2006) | 2 lines use escape for pango markup ........ r5018 | asterix | 2006-01-06 02:21:39 -0700 (Fri, 06 Jan 2006) | 2 lines missing new contacts function ........ r5019 | asterix | 2006-01-06 11:03:07 -0700 (Fri, 06 Jan 2006) | 2 lines handle the click on toggle_gpg_encryption menuitem ........ r5020 | asterix | 2006-01-06 11:14:14 -0700 (Fri, 06 Jan 2006) | 2 lines use the saved size even if a chat window is already opened ........ r5022 | asterix | 2006-01-07 03:43:47 -0700 (Sat, 07 Jan 2006) | 2 lines we can now resume filetransfert ........ r5023 | asterix | 2006-01-07 03:56:31 -0700 (Sat, 07 Jan 2006) | 2 lines [Knuckles] Google E-Mail Notification ........ r5024 | asterix | 2006-01-07 04:02:16 -0700 (Sat, 07 Jan 2006) | 2 lines better string ........ r5025 | asterix | 2006-01-07 04:14:32 -0700 (Sat, 07 Jan 2006) | 2 lines fix a TB ........ r5026 | asterix | 2006-01-07 05:36:55 -0700 (Sat, 07 Jan 2006) | 2 lines we can now drag a file on a contact in the roster to send him a file ........ r5027 | asterix | 2006-01-07 06:26:28 -0700 (Sat, 07 Jan 2006) | 2 lines contact.groups is always a list, even if emtpy ........ r5028 | asterix | 2006-01-07 06:54:30 -0700 (Sat, 07 Jan 2006) | 2 lines make all buttons insensitive on a category row in disco ........ r5029 | asterix | 2006-01-07 07:19:25 -0700 (Sat, 07 Jan 2006) | 2 lines auto open groupchat configuration window when we create a new room ........
2006-01-07 18:25:35 +01:00
class ConfirmationDialogDubbleCheck(ConfirmationDialog):
'''HIG compliant confirmation dialog with 2 checkbuttons.'''
2008-09-03 13:25:27 +02:00
def __init__(self, pritext, sectext='', checktext1='', checktext2='',
on_response_ok=None, on_response_cancel=None, is_modal=True):
self.user_response_ok = on_response_ok
self.user_response_cancel = on_response_cancel
HigDialog.__init__(self, None, gtk.MESSAGE_QUESTION,
gtk.BUTTONS_OK_CANCEL, pritext, sectext, self.on_response_ok,
self.on_response_cancel)
self.set_default_response(gtk.RESPONSE_OK)
ok_button = self.action_area.get_children()[0] # right to left
ok_button.grab_focus()
if checktext1:
self.checkbutton1 = gtk.CheckButton(checktext1)
2008-09-03 13:25:27 +02:00
self.vbox.pack_start(self.checkbutton1, expand=False, fill=True)
else:
self.checkbutton1 = None
if checktext2:
self.checkbutton2 = gtk.CheckButton(checktext2)
2008-09-03 13:25:27 +02:00
self.vbox.pack_start(self.checkbutton2, expand=False, fill=True)
else:
self.checkbutton2 = None
self.set_modal(is_modal)
self.popup()
# XXX should cancel if somebody closes the dialog
def on_response_ok(self, widget):
if self.user_response_ok:
if isinstance(self.user_response_ok, tuple):
self.user_response_ok[0](self.is_checked(),
*self.user_response_ok[1:])
else:
self.user_response_ok(self.is_checked())
self.destroy()
def on_response_cancel(self, widget):
if self.user_response_cancel:
if isinstance(self.user_response_cancel, tuple):
self.user_response_cancel[0](*self.user_response_cancel[1:])
else:
self.user_response_cancel()
self.destroy()
def is_checked(self):
''' Get active state of the checkbutton '''
if self.checkbutton1:
is_checked_1 = self.checkbutton1.get_active()
else:
is_checked_1 = False
if self.checkbutton2:
is_checked_2 = self.checkbutton2.get_active()
else:
is_checked_2 = False
return [is_checked_1, is_checked_2]
Merged revisions 5017-5020,5022-5029 via svnmerge from svn://svn.gajim.org/gajim/trunk ........ r5017 | asterix | 2006-01-06 01:55:51 -0700 (Fri, 06 Jan 2006) | 2 lines use escape for pango markup ........ r5018 | asterix | 2006-01-06 02:21:39 -0700 (Fri, 06 Jan 2006) | 2 lines missing new contacts function ........ r5019 | asterix | 2006-01-06 11:03:07 -0700 (Fri, 06 Jan 2006) | 2 lines handle the click on toggle_gpg_encryption menuitem ........ r5020 | asterix | 2006-01-06 11:14:14 -0700 (Fri, 06 Jan 2006) | 2 lines use the saved size even if a chat window is already opened ........ r5022 | asterix | 2006-01-07 03:43:47 -0700 (Sat, 07 Jan 2006) | 2 lines we can now resume filetransfert ........ r5023 | asterix | 2006-01-07 03:56:31 -0700 (Sat, 07 Jan 2006) | 2 lines [Knuckles] Google E-Mail Notification ........ r5024 | asterix | 2006-01-07 04:02:16 -0700 (Sat, 07 Jan 2006) | 2 lines better string ........ r5025 | asterix | 2006-01-07 04:14:32 -0700 (Sat, 07 Jan 2006) | 2 lines fix a TB ........ r5026 | asterix | 2006-01-07 05:36:55 -0700 (Sat, 07 Jan 2006) | 2 lines we can now drag a file on a contact in the roster to send him a file ........ r5027 | asterix | 2006-01-07 06:26:28 -0700 (Sat, 07 Jan 2006) | 2 lines contact.groups is always a list, even if emtpy ........ r5028 | asterix | 2006-01-07 06:54:30 -0700 (Sat, 07 Jan 2006) | 2 lines make all buttons insensitive on a category row in disco ........ r5029 | asterix | 2006-01-07 07:19:25 -0700 (Sat, 07 Jan 2006) | 2 lines auto open groupchat configuration window when we create a new room ........
2006-01-07 18:25:35 +01:00
class FTOverwriteConfirmationDialog(ConfirmationDialog):
'''HIG compliant confirmation dialog to overwrite or resume a file transfert'''
2008-08-07 15:27:36 +02:00
def __init__(self, pritext, sectext='', propose_resume=True,
on_response=None):
Merged revisions 5017-5020,5022-5029 via svnmerge from svn://svn.gajim.org/gajim/trunk ........ r5017 | asterix | 2006-01-06 01:55:51 -0700 (Fri, 06 Jan 2006) | 2 lines use escape for pango markup ........ r5018 | asterix | 2006-01-06 02:21:39 -0700 (Fri, 06 Jan 2006) | 2 lines missing new contacts function ........ r5019 | asterix | 2006-01-06 11:03:07 -0700 (Fri, 06 Jan 2006) | 2 lines handle the click on toggle_gpg_encryption menuitem ........ r5020 | asterix | 2006-01-06 11:14:14 -0700 (Fri, 06 Jan 2006) | 2 lines use the saved size even if a chat window is already opened ........ r5022 | asterix | 2006-01-07 03:43:47 -0700 (Sat, 07 Jan 2006) | 2 lines we can now resume filetransfert ........ r5023 | asterix | 2006-01-07 03:56:31 -0700 (Sat, 07 Jan 2006) | 2 lines [Knuckles] Google E-Mail Notification ........ r5024 | asterix | 2006-01-07 04:02:16 -0700 (Sat, 07 Jan 2006) | 2 lines better string ........ r5025 | asterix | 2006-01-07 04:14:32 -0700 (Sat, 07 Jan 2006) | 2 lines fix a TB ........ r5026 | asterix | 2006-01-07 05:36:55 -0700 (Sat, 07 Jan 2006) | 2 lines we can now drag a file on a contact in the roster to send him a file ........ r5027 | asterix | 2006-01-07 06:26:28 -0700 (Sat, 07 Jan 2006) | 2 lines contact.groups is always a list, even if emtpy ........ r5028 | asterix | 2006-01-07 06:54:30 -0700 (Sat, 07 Jan 2006) | 2 lines make all buttons insensitive on a category row in disco ........ r5029 | asterix | 2006-01-07 07:19:25 -0700 (Sat, 07 Jan 2006) | 2 lines auto open groupchat configuration window when we create a new room ........
2006-01-07 18:25:35 +01:00
HigDialog.__init__(self, None, gtk.MESSAGE_QUESTION, gtk.BUTTONS_CANCEL,
pritext, sectext)
2008-08-07 15:27:36 +02:00
self.on_response = on_response
Merged revisions 5017-5020,5022-5029 via svnmerge from svn://svn.gajim.org/gajim/trunk ........ r5017 | asterix | 2006-01-06 01:55:51 -0700 (Fri, 06 Jan 2006) | 2 lines use escape for pango markup ........ r5018 | asterix | 2006-01-06 02:21:39 -0700 (Fri, 06 Jan 2006) | 2 lines missing new contacts function ........ r5019 | asterix | 2006-01-06 11:03:07 -0700 (Fri, 06 Jan 2006) | 2 lines handle the click on toggle_gpg_encryption menuitem ........ r5020 | asterix | 2006-01-06 11:14:14 -0700 (Fri, 06 Jan 2006) | 2 lines use the saved size even if a chat window is already opened ........ r5022 | asterix | 2006-01-07 03:43:47 -0700 (Sat, 07 Jan 2006) | 2 lines we can now resume filetransfert ........ r5023 | asterix | 2006-01-07 03:56:31 -0700 (Sat, 07 Jan 2006) | 2 lines [Knuckles] Google E-Mail Notification ........ r5024 | asterix | 2006-01-07 04:02:16 -0700 (Sat, 07 Jan 2006) | 2 lines better string ........ r5025 | asterix | 2006-01-07 04:14:32 -0700 (Sat, 07 Jan 2006) | 2 lines fix a TB ........ r5026 | asterix | 2006-01-07 05:36:55 -0700 (Sat, 07 Jan 2006) | 2 lines we can now drag a file on a contact in the roster to send him a file ........ r5027 | asterix | 2006-01-07 06:26:28 -0700 (Sat, 07 Jan 2006) | 2 lines contact.groups is always a list, even if emtpy ........ r5028 | asterix | 2006-01-07 06:54:30 -0700 (Sat, 07 Jan 2006) | 2 lines make all buttons insensitive on a category row in disco ........ r5029 | asterix | 2006-01-07 07:19:25 -0700 (Sat, 07 Jan 2006) | 2 lines auto open groupchat configuration window when we create a new room ........
2006-01-07 18:25:35 +01:00
if propose_resume:
b = gtk.Button('', gtk.STOCK_REFRESH)
align = b.get_children()[0]
hbox = align.get_children()[0]
label = hbox.get_children()[1]
label.set_text('_Resume')
label.set_use_underline(True)
self.add_action_widget(b, 100)
b = gtk.Button('', gtk.STOCK_SAVE_AS)
align = b.get_children()[0]
hbox = align.get_children()[0]
label = hbox.get_children()[1]
label.set_text('Re_place')
label.set_use_underline(True)
self.add_action_widget(b, 200)
2008-08-07 15:27:36 +02:00
self.connect('response', self.on_dialog_response)
self.show_all()
2008-08-07 15:25:25 +02:00
2008-08-07 15:27:36 +02:00
def on_dialog_response(self, dialog, response):
if self.on_response:
if isinstance(self.on_response, tuple):
self.on_response[0](response, *self.on_response[1:])
2008-08-07 15:25:25 +02:00
else:
2008-08-07 15:27:36 +02:00
self.on_response(response)
2008-08-07 15:25:25 +02:00
self.destroy()
class CommonInputDialog:
'''Common Class for Input dialogs'''
def __init__(self, title, label_str, is_modal, ok_handler, cancel_handler):
2006-05-08 23:16:38 +02:00
self.dialog = self.xml.get_widget('input_dialog')
label = self.xml.get_widget('label')
self.dialog.set_title(title)
label.set_markup(label_str)
self.cancel_handler = cancel_handler
2008-08-07 23:59:20 +02:00
self.ok_handler = ok_handler
okbutton = self.xml.get_widget('okbutton')
okbutton.connect('clicked', self.on_okbutton_clicked)
cancelbutton = self.xml.get_widget('cancelbutton')
cancelbutton.connect('clicked', self.on_cancelbutton_clicked)
self.xml.signal_autoconnect(self)
self.dialog.show_all()
def on_input_dialog_destroy(self, widget):
if self.cancel_handler:
self.cancel_handler()
def on_okbutton_clicked(self, widget):
user_input = self.get_text()
2008-08-07 23:57:19 +02:00
if user_input:
user_input = user_input.decode('utf-8')
2007-08-09 17:39:18 +02:00
self.cancel_handler = None
self.dialog.destroy()
if isinstance(self.ok_handler, tuple):
self.ok_handler[0](user_input, *self.ok_handler[1:])
else:
self.ok_handler(user_input)
def on_cancelbutton_clicked(self, widget):
self.dialog.destroy()
class InputDialog(CommonInputDialog):
'''Class for Input dialog'''
2008-08-08 00:08:08 +02:00
def __init__(self, title, label_str, input_str=None, is_modal=True,
ok_handler=None, cancel_handler=None):
self.xml = gtkgui_helpers.get_glade('input_dialog.glade')
CommonInputDialog.__init__(self, title, label_str, is_modal, ok_handler,
cancel_handler)
self.input_entry = self.xml.get_widget('input_entry')
if input_str:
self.input_entry.set_text(input_str)
self.input_entry.select_region(0, -1) # select all
def get_text(self):
return self.input_entry.get_text().decode('utf-8')
class InputTextDialog(CommonInputDialog):
'''Class for multilines Input dialog (more place than InputDialog)'''
2008-08-08 00:08:08 +02:00
def __init__(self, title, label_str, input_str=None, is_modal=True,
ok_handler=None, cancel_handler=None):
self.xml = gtkgui_helpers.get_glade('input_text_dialog.glade')
CommonInputDialog.__init__(self, title, label_str, is_modal, ok_handler,
cancel_handler)
self.input_buffer = self.xml.get_widget('input_textview').get_buffer()
if input_str:
self.input_buffer.set_text(input_str)
start_iter, end_iter = self.input_buffer.get_bounds()
self.input_buffer.select_range(start_iter, end_iter) # select all
def get_text(self):
start_iter, end_iter = self.input_buffer.get_bounds()
return self.input_buffer.get_text(start_iter, end_iter).decode('utf-8')
class DubbleInputDialog:
'''Class for Dubble Input dialog'''
2008-08-08 00:08:08 +02:00
def __init__(self, title, label_str1, label_str2, input_str1=None,
input_str2=None, is_modal=True, ok_handler=None, cancel_handler=None):
self.xml = gtkgui_helpers.get_glade('dubbleinput_dialog.glade')
self.dialog = self.xml.get_widget('dubbleinput_dialog')
label1 = self.xml.get_widget('label1')
self.input_entry1 = self.xml.get_widget('input_entry1')
label2 = self.xml.get_widget('label2')
self.input_entry2 = self.xml.get_widget('input_entry2')
self.dialog.set_title(title)
label1.set_markup(label_str1)
label2.set_markup(label_str2)
self.cancel_handler = cancel_handler
if input_str1:
self.input_entry1.set_text(input_str1)
self.input_entry1.select_region(0, -1) # select all
if input_str2:
self.input_entry2.set_text(input_str2)
self.input_entry2.select_region(0, -1) # select all
2008-08-11 10:47:06 +02:00
self.dialog.set_modal(is_modal)
self.ok_handler = ok_handler
okbutton = self.xml.get_widget('okbutton')
okbutton.connect('clicked', self.on_okbutton_clicked)
cancelbutton = self.xml.get_widget('cancelbutton')
cancelbutton.connect('clicked', self.on_cancelbutton_clicked)
self.xml.signal_autoconnect(self)
self.dialog.show_all()
def on_dubbleinput_dialog_destroy(self, widget):
2008-08-29 09:37:55 +02:00
if not self.cancel_handler:
2008-08-11 10:47:06 +02:00
return False
if isinstance(self.cancel_handler, tuple):
self.cancel_handler[0](*self.cancel_handler[1:])
else:
self.cancel_handler()
def on_okbutton_clicked(self, widget):
user_input1 = self.input_entry1.get_text().decode('utf-8')
user_input2 = self.input_entry2.get_text().decode('utf-8')
self.dialog.destroy()
2008-08-29 09:37:55 +02:00
if not self.ok_handler:
2008-08-11 10:47:06 +02:00
return
if isinstance(self.ok_handler, tuple):
self.ok_handler[0](user_input1, user_input2, *self.ok_handler[1:])
else:
self.ok_handler(user_input1, user_input2)
def on_cancelbutton_clicked(self, widget):
self.dialog.destroy()
2008-10-24 14:10:05 +02:00
if not self.cancel_handler:
2008-08-11 10:47:06 +02:00
return
if isinstance(self.cancel_handler, tuple):
self.cancel_handler[0](*self.cancel_handler[1:])
else:
self.cancel_handler()
2005-06-13 12:48:07 +02:00
class SubscriptionRequestWindow:
2008-08-08 00:08:08 +02:00
def __init__(self, jid, text, account, user_nick=None):
xml = gtkgui_helpers.get_glade('subscription_request_window.glade')
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.jid = jid
self.account = account
self.user_nick = user_nick
if len(gajim.connections) >= 2:
2008-08-01 11:30:36 +02:00
prompt_text = \
_('Subscription request for account %(account)s from %(jid)s')\
% {'account': account, 'jid': 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()
2006-11-18 21:52:28 +01:00
def prepare_popup_menu(self):
xml = gtkgui_helpers.get_glade('subscription_request_popup_menu.glade')
menu = xml.get_widget('subscription_request_popup_menu')
xml.signal_autoconnect(self)
return menu
def on_close_button_clicked(self, widget):
2005-04-12 17:30:09 +02:00
self.window.destroy()
def on_authorize_button_clicked(self, widget):
'''accept the request'''
gajim.connections[self.account].send_authorization(self.jid)
2005-04-12 17:30:09 +02:00
self.window.destroy()
contact = gajim.contacts.get_contact(self.account, self.jid)
if not contact or _('Not in Roster') in contact.groups:
AddNewContactWindow(self.account, self.jid, self.user_nick)
2006-11-18 21:52:28 +01:00
def on_contact_info_activate(self, widget):
'''ask vcard'''
if self.jid in gajim.interface.instances[self.account]['infos']:
gajim.interface.instances[self.account]['infos'][self.jid].window.present()
else:
contact = gajim.contacts.create_contact(jid=self.jid, name='',
groups=[], show='', status='', sub='', ask='', resource='',
priority=5, keyID='', our_chatstate=None, chatstate=None)
gajim.interface.instances[self.account]['infos'][self.jid] = \
vcard.VcardWindow(contact, self.account)
# Remove jabber page
gajim.interface.instances[self.account]['infos'][self.jid].xml.\
get_widget('information_notebook').remove_page(0)
2006-11-18 21:52:28 +01:00
def on_start_chat_activate(self, widget):
'''open chat'''
gajim.interface.new_chat_from_jid(self.account, self.jid)
2006-11-18 21:52:28 +01:00
def on_deny_button_clicked(self, widget):
2005-04-18 14:17:43 +02:00
'''refuse the request'''
gajim.connections[self.account].refuse_authorization(self.jid)
contact = gajim.contacts.get_contact(self.account, self.jid)
if contact and _('Not in Roster') in contact.get_shown_groups():
gajim.interface.roster.remove_contact(self.jid, self.account)
2005-04-12 17:30:09 +02:00
self.window.destroy()
2005-04-04 18:46:35 +02:00
2006-11-18 21:52:28 +01:00
def on_actions_button_clicked(self, widget):
'''popup action menu'''
menu = self.prepare_popup_menu()
menu.show_all()
gtkgui_helpers.popup_emoticons_under_button(menu, widget, self.window.window)
class JoinGroupchatWindow:
2008-08-08 00:08:08 +02:00
def __init__(self, account, room_jid='', nick='', password='',
automatic=False):
2006-09-13 18:47:58 +02:00
'''automatic is a dict like {'invities': []}
If automatic is not empty, this means room must be automaticaly configured
and when done, invities must be automatically invited'''
2006-11-18 21:52:28 +01:00
if room_jid != '':
if room_jid in gajim.gc_connected[account] and\
gajim.gc_connected[account][room_jid]:
ErrorDialog(_('You are already in group chat %s') % room_jid)
raise GajimGeneralException, 'You are already in this group chat'
self.account = account
2006-09-13 18:47:58 +02:00
self.automatic = automatic
if nick == '':
nick = gajim.nicks[self.account]
if gajim.connections[account].connected < 2:
ErrorDialog(_('You are not connected to the server'),
2006-11-18 21:52:28 +01:00
_('You can not join a group chat unless you are connected.'))
raise GajimGeneralException, 'You must be connected to join a groupchat'
self._empty_required_widgets = []
self.xml = gtkgui_helpers.get_glade('join_groupchat_window.glade')
2005-04-04 18:46:35 +02:00
self.window = self.xml.get_widget('join_groupchat_window')
2006-11-18 21:52:28 +01:00
self._room_jid_entry = self.xml.get_widget('room_jid_entry')
self._nickname_entry = self.xml.get_widget('nickname_entry')
2007-08-09 17:39:18 +02:00
self._password_entry = self.xml.get_widget('password_entry')
2006-11-18 21:52:28 +01:00
self._room_jid_entry.set_text(room_jid)
self._nickname_entry.set_text(nick)
2007-08-09 17:39:18 +02:00
if password:
self._password_entry.set_text(password)
2005-04-04 18:46:35 +02:00
self.xml.signal_autoconnect(self)
2008-04-20 22:06:16 +02:00
# now add us to open windows
2008-12-03 22:56:12 +01:00
gajim.interface.instances[account]['join_gc'] = self
if len(gajim.connections) > 1:
title = _('Join Group Chat with account %s') % account
else:
title = _('Join Group Chat')
self.window.set_title(title)
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)
self.recently_groupchat = gajim.config.get('recently_groupchat').split()
for g in self.recently_groupchat:
self.recently_combobox.append_text(g)
if len(self.recently_groupchat) == 0:
self.recently_combobox.set_sensitive(False)
2006-11-18 21:52:28 +01:00
elif room_jid == '':
self.recently_combobox.set_active(0)
2006-11-18 21:52:28 +01:00
self._room_jid_entry.select_region(0, -1)
elif room_jid != '':
self.xml.get_widget('join_button').grab_focus()
2006-11-18 21:52:28 +01:00
if not self._room_jid_entry.get_text():
self._empty_required_widgets.append(self._room_jid_entry)
if not self._nickname_entry.get_text():
self._empty_required_widgets.append(self._nickname_entry)
if len(self._empty_required_widgets):
self.xml.get_widget('join_button').set_sensitive(False)
2007-12-12 09:44:46 +01:00
if not gajim.connections[account].private_storage_supported:
self.xml.get_widget('auto_join_checkbutton').set_sensitive(False)
self.window.show_all()
def on_join_groupchat_window_destroy(self, widget):
2005-04-18 14:17:43 +02:00
'''close window'''
# remove us from open windows
del gajim.interface.instances[self.account]['join_gc']
def on_join_groupchat_window_key_press_event(self, widget, event):
if event.keyval == gtk.keysyms.Escape: # ESCAPE
widget.destroy()
def on_required_entry_changed(self, widget):
if not widget.get_text():
self._empty_required_widgets.append(widget)
self.xml.get_widget('join_button').set_sensitive(False)
else:
if widget in self._empty_required_widgets:
self._empty_required_widgets.remove(widget)
if len(self._empty_required_widgets) == 0:
self.xml.get_widget('join_button').set_sensitive(True)
def on_recently_combobox_changed(self, widget):
model = widget.get_model()
2006-11-18 21:52:28 +01:00
iter_ = widget.get_active_iter()
room_jid = model[iter_][0].decode('utf-8')
self._room_jid_entry.set_text(room_jid)
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()
def on_join_button_clicked(self, widget):
2005-04-18 14:17:43 +02:00
'''When Join button is clicked'''
2006-11-18 21:52:28 +01:00
nickname = self._nickname_entry.get_text().decode('utf-8')
room_jid = self._room_jid_entry.get_text().decode('utf-8')
2007-08-09 17:39:18 +02:00
password = self._password_entry.get_text().decode('utf-8')
try:
nickname = helpers.parse_resource(nickname)
except Exception:
ErrorDialog(_('Invalid Nickname'),
_('The nickname has not allowed characters.'))
return
user, server, resource = helpers.decompose_jid(room_jid)
if not user or not server or resource:
ErrorDialog(_('Invalid group chat Jabber ID'),
_('The group chat Jabber ID has not allowed characters.'))
return
try:
2006-11-18 21:52:28 +01:00
room_jid = helpers.parse_jid(room_jid)
except Exception:
2006-11-18 21:52:28 +01:00
ErrorDialog(_('Invalid group chat Jabber ID'),
_('The group chat Jabber ID has not allowed characters.'))
2006-01-19 20:59:58 +01:00
return
2006-11-18 21:52:28 +01:00
if gajim.interface.msg_win_mgr.has_window(room_jid, self.account):
ctrl = gajim.interface.msg_win_mgr.get_gc_control(room_jid, self.account)
2006-11-18 21:52:28 +01:00
if ctrl.type_id != message_control.TYPE_GC:
ErrorDialog(_('This is not a group chat'),
_('%s is not the name of a group chat.') % room_jid)
return
if room_jid in self.recently_groupchat:
self.recently_groupchat.remove(room_jid)
self.recently_groupchat.insert(0, room_jid)
if len(self.recently_groupchat) > 10:
self.recently_groupchat = self.recently_groupchat[0:10]
2006-11-18 21:52:28 +01:00
gajim.config.set('recently_groupchat',
' '.join(self.recently_groupchat))
2006-09-13 18:47:58 +02:00
if self.xml.get_widget('auto_join_checkbutton').get_active():
# Add as bookmark, with autojoin and not minimized
name = gajim.get_nick_from_jid(room_jid)
gajim.interface.add_gc_bookmark(self.account, name, room_jid, '1', \
'0', password, nickname)
2006-09-13 18:47:58 +02:00
if self.automatic:
2006-11-18 21:52:28 +01:00
gajim.automatic_rooms[self.account][room_jid] = self.automatic
gajim.interface.join_gc_room(self.account, room_jid, nickname, password)
2005-06-13 12:49:48 +02:00
2005-04-12 17:30:09 +02:00
self.window.destroy()
2007-06-03 12:04:20 +02:00
class SynchroniseSelectAccountDialog:
def __init__(self, account):
# 'account' can be None if we are about to create our first one
if not account or gajim.connections[account].connected < 2:
ErrorDialog(_('You are not connected to the server'),
_('Without a connection, you can not synchronise your contacts.'))
raise GajimGeneralException, 'You are not connected to the server'
self.account = account
self.xml = gtkgui_helpers.get_glade('synchronise_select_account_dialog.glade')
self.dialog = self.xml.get_widget('synchronise_select_account_dialog')
self.accounts_treeview = self.xml.get_widget('accounts_treeview')
model = gtk.ListStore(str, str, bool)
self.accounts_treeview.set_model(model)
# columns
renderer = gtk.CellRendererText()
self.accounts_treeview.insert_column_with_attributes(-1,
2008-09-03 13:25:27 +02:00
_('Name'), renderer, text=0)
2007-06-03 12:04:20 +02:00
renderer = gtk.CellRendererText()
self.accounts_treeview.insert_column_with_attributes(-1,
2008-09-03 13:25:27 +02:00
_('Server'), renderer, text=1)
2007-06-03 12:04:20 +02:00
self.xml.signal_autoconnect(self)
self.init_accounts()
self.dialog.show_all()
def on_accounts_window_key_press_event(self, widget, event):
if event.keyval == gtk.keysyms.Escape:
self.window.destroy()
def init_accounts(self):
'''initialize listStore with existing accounts'''
model = self.accounts_treeview.get_model()
model.clear()
for remote_account in gajim.connections:
if remote_account == self.account:
# Do not show the account we're sync'ing
continue
2008-12-03 18:16:04 +01:00
iter_ = model.append()
model.set(iter_, 0, remote_account, 1, gajim.get_hostname_from_account(
2007-06-03 12:04:20 +02:00
remote_account))
def on_cancel_button_clicked(self, widget):
self.dialog.destroy()
def on_ok_button_clicked(self, widget):
sel = self.accounts_treeview.get_selection()
2008-12-03 18:16:04 +01:00
(model, iter_) = sel.get_selected()
if not iter_:
2007-06-03 12:04:20 +02:00
return
2008-12-03 18:16:04 +01:00
remote_account = model.get_value(iter_, 0).decode('utf-8')
2007-12-12 09:44:46 +01:00
2007-06-03 12:04:20 +02:00
if gajim.connections[remote_account].connected < 2:
ErrorDialog(_('This account is not connected to the server'),
_('You cannot synchronize with an account unless it is connected.'))
return
else:
try:
2008-12-02 16:53:23 +01:00
SynchroniseSelectContactsDialog(self.account, remote_account)
2007-06-03 12:04:20 +02:00
except GajimGeneralException:
# if we showed ErrorDialog, there will not be dialog instance
return
self.dialog.destroy()
class SynchroniseSelectContactsDialog:
def __init__(self, account, remote_account):
self.local_account = account
self.remote_account = remote_account
self.xml = gtkgui_helpers.get_glade('synchronise_select_contacts_dialog.glade')
self.dialog = self.xml.get_widget('synchronise_select_contacts_dialog')
self.contacts_treeview = self.xml.get_widget('contacts_treeview')
model = gtk.ListStore(bool, str)
self.contacts_treeview.set_model(model)
# columns
renderer1 = gtk.CellRendererToggle()
renderer1.set_property('activatable', True)
renderer1.connect('toggled', self.toggled_callback)
self.contacts_treeview.insert_column_with_attributes(-1,
2008-09-03 13:25:27 +02:00
_('Synchronise'), renderer1, active=0)
2007-06-03 12:04:20 +02:00
renderer2 = gtk.CellRendererText()
self.contacts_treeview.insert_column_with_attributes(-1,
2008-09-03 13:25:27 +02:00
_('Name'), renderer2, text=1)
2007-06-03 12:04:20 +02:00
self.xml.signal_autoconnect(self)
self.init_contacts()
self.dialog.show_all()
def toggled_callback(self, cell, path):
model = self.contacts_treeview.get_model()
2008-12-03 18:16:04 +01:00
iter_ = model.get_iter(path)
model[iter_][0] = not cell.get_active()
2007-06-03 12:04:20 +02:00
def on_contacts_window_key_press_event(self, widget, event):
if event.keyval == gtk.keysyms.Escape:
self.window.destroy()
def init_contacts(self):
'''initialize listStore with existing accounts'''
model = self.contacts_treeview.get_model()
model.clear()
# recover local contacts
local_jid_list = gajim.contacts.get_jid_list(self.local_account)
remote_jid_list = gajim.contacts.get_jid_list(self.remote_account)
for remote_jid in remote_jid_list:
if remote_jid not in local_jid_list:
2008-12-03 18:16:04 +01:00
iter_ = model.append()
model.set(iter_, 0, True, 1, remote_jid)
2007-06-03 12:04:20 +02:00
def on_cancel_button_clicked(self, widget):
self.dialog.destroy()
def on_ok_button_clicked(self, widget):
model = self.contacts_treeview.get_model()
2008-12-03 18:16:04 +01:00
iter_ = model.get_iter_root()
while iter_:
if model[iter_][0]:
2007-06-03 12:04:20 +02:00
# it is selected
2008-12-03 18:16:04 +01:00
remote_jid = model[iter_][1].decode('utf-8')
2007-06-03 12:04:20 +02:00
message = 'I\'m synchronizing my contacts from my %s account, could you please add this address to your contact list?' % \
gajim.get_hostname_from_account(self.remote_account)
remote_contact = gajim.contacts.get_first_contact_from_jid(
self.remote_account, remote_jid)
# keep same groups and same nickname
gajim.interface.roster.req_sub(self, remote_jid, message,
self.local_account, groups = remote_contact.groups,
nickname = remote_contact.name, auto_auth = True)
2008-12-03 18:16:04 +01:00
iter_ = model.iter_next(iter_)
2007-06-03 12:04:20 +02:00
self.dialog.destroy()
2006-05-08 23:16:38 +02:00
class NewChatDialog(InputDialog):
def __init__(self, account):
self.account = account
2005-04-17 21:53:39 +02:00
if len(gajim.connections) > 1:
title = _('Start Chat with account %s') % account
2005-04-04 18:46:35 +02:00
else:
title = _('Start Chat')
2006-11-18 21:52:28 +01:00
prompt_text = _('Fill in the nickname or the Jabber ID of the contact you would like\nto send a chat message to:')
2008-09-03 13:25:27 +02:00
InputDialog.__init__(self, title, prompt_text, is_modal=False)
2006-05-08 23:16:38 +02:00
self.completion_dict = {}
liststore = gtkgui_helpers.get_completion_liststore(self.input_entry)
self.completion_dict = helpers.get_contact_dict_for_account(account)
# add all contacts to the model
keys = sorted(self.completion_dict.keys())
2006-05-09 15:07:33 +02:00
for jid in keys:
2006-05-08 23:16:38 +02:00
contact = self.completion_dict[jid]
img = gajim.interface.jabber_state_images['16'][contact.show]
2006-05-08 23:16:38 +02:00
liststore.append((img.get_pixbuf(), jid))
self.ok_handler = self.new_chat_response
okbutton = self.xml.get_widget('okbutton')
okbutton.connect('clicked', self.on_okbutton_clicked)
cancelbutton = self.xml.get_widget('cancelbutton')
cancelbutton.connect('clicked', self.on_cancelbutton_clicked)
self.dialog.show_all()
def new_chat_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'),
2006-09-13 18:47:58 +02:00
_('Please make sure you are connected with "%s".') % self.account)
2005-08-06 21:14:21 +02:00
return
2005-06-20 01:09:15 +02:00
if jid in self.completion_dict:
2006-05-08 23:16:38 +02:00
jid = self.completion_dict[jid].jid
2006-07-17 21:30:53 +02:00
else:
try:
jid = helpers.parse_jid(jid)
except helpers.InvalidFormat, e:
ErrorDialog(_('Invalid JID'), e[0])
return
except:
2006-09-13 18:47:58 +02:00
ErrorDialog(_('Invalid JID'), _('Unable to parse "%s".') % jid)
2006-07-17 21:30:53 +02:00
return
gajim.interface.new_chat_from_jid(self.account, jid)
class ChangePasswordDialog:
def __init__(self, account, on_response):
# 'account' can be None if we are about to create our first one
if not account or gajim.connections[account].connected < 2:
ErrorDialog(_('You are not connected to the server'),
_('Without a connection, you can not change your password.'))
2006-11-18 21:52:28 +01:00
raise GajimGeneralException, 'You are not connected to the server'
self.account = account
self.on_response = on_response
self.xml = gtkgui_helpers.get_glade('change_password_dialog.glade')
2005-04-04 18:46:35 +02:00
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')
self.dialog.connect('response', self.on_dialog_response)
2005-06-05 12:48:34 +02:00
self.dialog.show_all()
2005-03-04 14:10:00 +01:00
def on_dialog_response(self, dialog, response):
if response != gtk.RESPONSE_OK:
dialog.destroy()
self.on_response(None)
return
password1 = self.password1_entry.get_text().decode('utf-8')
if not password1:
ErrorDialog(_('Invalid password'), _('You must enter a password.'))
return
password2 = self.password2_entry.get_text().decode('utf-8')
if password1 != password2:
ErrorDialog(_('Passwords do not match'),
_('The passwords typed in both fields must be identical.'))
return
dialog.destroy()
self.on_response(password1)
2005-06-10 20:40:19 +02:00
class PopupNotificationWindow:
2008-08-08 00:08:08 +02:00
def __init__(self, event_type, jid, account, msg_type='',
path_to_image=None, title=None, text=None):
2005-04-12 17:30:09 +02:00
self.account = account
self.jid = jid
self.msg_type = msg_type
2006-04-04 19:46:19 +02:00
xml = gtkgui_helpers.get_glade('popup_notification_window.glade')
2005-04-21 23:23:41 +02:00
self.window = xml.get_widget('popup_notification_window')
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_TOOLTIP)
close_button = xml.get_widget('close_button')
event_type_label = xml.get_widget('event_type_label')
event_description_label = xml.get_widget('event_description_label')
eventbox = xml.get_widget('eventbox')
image = xml.get_widget('notification_image')
2006-04-04 19:46:19 +02:00
if not text:
text = gajim.get_name_from_jid(account, jid) # default value of text
if not title:
2008-11-29 14:37:06 +01:00
title = ''
event_type_label.set_markup(
2008-11-29 14:37:06 +01:00
'<span foreground="black" weight="bold">%s</span>' %
gobject.markup_escape_text(title))
2005-09-05 02:08:52 +02:00
# set colors [ http://www.pitt.edu/~nisg/cis/web/cgi/rgb.html ]
self.window.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse('black'))
2006-04-04 19:46:19 +02:00
# default image
if not path_to_image:
path_to_image = os.path.abspath(
2006-11-18 21:52:28 +01:00
os.path.join(gajim.DATA_DIR, 'pixmaps', 'events',
'chat_msg_recv.png')) # img to display
if event_type == _('Contact Signed In'):
bg_color = 'limegreen'
elif event_type == _('Contact Signed Out'):
bg_color = 'red'
elif event_type in (_('New Message'), _('New Single Message'),
_('New Private Message'), _('New E-mail')):
bg_color = 'dodgerblue'
2005-08-03 18:53:04 +02:00
elif event_type == _('File Transfer Request'):
bg_color = 'khaki'
2005-08-07 23:01:21 +02:00
elif event_type == _('File Transfer Error'):
bg_color = 'firebrick'
elif event_type in (_('File Transfer Completed'),
_('File Transfer Stopped')):
bg_color = 'yellowgreen'
elif event_type == _('Groupchat Invitation'):
bg_color = 'tan1'
elif event_type == _('Contact Changed Status'):
bg_color = 'thistle2'
2006-11-18 21:52:28 +01:00
else: # Unknown event! Shouldn't happen but deal with it
bg_color = 'white'
popup_bg_color = gtk.gdk.color_parse(bg_color)
close_button.modify_bg(gtk.STATE_NORMAL, popup_bg_color)
eventbox.modify_bg(gtk.STATE_NORMAL, popup_bg_color)
2008-11-29 14:37:06 +01:00
event_description_label.set_markup('<span foreground="black">%s</span>' %
gobject.markup_escape_text(text))
# set the image
image.set_from_file(path_to_image)
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()
gajim.interface.roster.popups_notification_height += self.window_height
pos_x = gajim.config.get('notification_position_x')
if pos_x < 0:
pos_x = gtk.gdk.screen_width() - window_width + pos_x + 1
pos_y = gajim.config.get('notification_position_y')
if pos_y < 0:
2008-08-08 00:08:08 +02:00
pos_y = gtk.gdk.screen_height() - \
gajim.interface.roster.popups_notification_height + pos_y + 1
self.window.move(pos_x, pos_y)
xml.signal_autoconnect(self)
self.window.show_all()
timeout = gajim.config.get('notification_timeout')
gobject.timeout_add_seconds(timeout, 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-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-21 23:23:41 +02:00
def adjust_height_and_move_popup_notification_windows(self):
2005-04-05 17:06:11 +02:00
#remove
gajim.interface.roster.popups_notification_height -= self.window_height
self.window.destroy()
if len(gajim.interface.roster.popup_notification_windows) > 0:
2005-04-05 17:06:11 +02:00
# we want to remove the first window added in the list
2008-08-08 00:08:08 +02:00
gajim.interface.roster.popup_notification_windows.pop(0)
2005-04-05 17:06:11 +02:00
# move the rest of popup windows
gajim.interface.roster.popups_notification_height = 0
for window_instance in gajim.interface.roster.popup_notification_windows:
2005-04-05 17:06:11 +02:00
window_width, window_height = window_instance.window.get_size()
gajim.interface.roster.popups_notification_height += window_height
window_instance.window.move(gtk.gdk.screen_width() - window_width,
2008-08-08 00:08:08 +02:00
gtk.gdk.screen_height() - \
gajim.interface.roster.popups_notification_height)
2005-04-21 23:23:41 +02:00
def on_popup_notification_window_button_press_event(self, widget, event):
if event.button != 1:
self.window.destroy()
return
gajim.interface.handle_event(self.account, self.jid, self.msg_type)
2005-04-21 23:23:41 +02:00
self.adjust_height_and_move_popup_notification_windows()
class SingleMessageWindow:
'''SingleMessageWindow can send or show a received
singled message depending on action argument which can be 'send'
or 'receive'.
'''
2007-12-12 09:44:46 +01:00
# Keep a reference on windows so garbage collector don't restroy them
instances = []
def __init__(self, account, to='', action='', from_whom='', subject='',
message='', resource='', session=None, form_node=None):
self.instances.append(self)
self.account = account
self.action = action
self.subject = subject
self.message = message
self.to = to
self.from_whom = from_whom
self.resource = resource
2007-12-12 09:44:46 +01:00
self.session = session
self.xml = gtkgui_helpers.get_glade('single_message_window.glade')
self.window = self.xml.get_widget('single_message_window')
self.count_chars_label = self.xml.get_widget('count_chars_label')
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')
self.to_entry = self.xml.get_widget('to_entry')
self.subject_entry = self.xml.get_widget('subject_entry')
self.message_scrolledwindow = self.xml.get_widget(
'message_scrolledwindow')
self.message_textview = self.xml.get_widget('message_textview')
self.message_tv_buffer = self.message_textview.get_buffer()
self.conversation_scrolledwindow = self.xml.get_widget(
'conversation_scrolledwindow')
self.conversation_textview = conversation_textview.ConversationTextview(
account)
self.conversation_textview.tv.show()
self.conversation_tv_buffer = self.conversation_textview.tv.get_buffer()
self.xml.get_widget('conversation_scrolledwindow').add(
self.conversation_textview.tv)
2007-12-12 09:44:46 +01:00
self.form_widget = None
2008-08-08 00:08:08 +02:00
parent_box = self.xml.get_widget('conversation_scrolledwindow').\
get_parent()
2007-12-12 09:44:46 +01:00
if form_node:
2008-09-03 13:25:27 +02:00
dataform = dataforms.ExtendForm(node=form_node)
2007-12-12 09:44:46 +01:00
self.form_widget = dataforms_widget.DataFormWidget(dataform)
self.form_widget.show_all()
parent_box.add(self.form_widget)
parent_box.child_set_property(self.form_widget, 'position',
2008-08-08 00:08:08 +02:00
parent_box.child_get_property(self.xml.get_widget(
'conversation_scrolledwindow'), 'position'))
2007-12-12 09:44:46 +01:00
self.action = 'form'
self.send_button = self.xml.get_widget('send_button')
self.reply_button = self.xml.get_widget('reply_button')
self.send_and_close_button = self.xml.get_widget('send_and_close_button')
self.cancel_button = self.xml.get_widget('cancel_button')
self.close_button = self.xml.get_widget('close_button')
self.message_tv_buffer.connect('changed', self.update_char_counter)
if isinstance(to, list):
2006-11-18 21:52:28 +01:00
jid = ', '.join( [i[0].jid + '/' + i[0].resource for i in to])
self.to_entry.set_text(jid)
self.to_entry.set_sensitive(False)
else:
self.to_entry.set_text(to)
if gajim.config.get('use_speller') and HAS_GTK_SPELL and action == 'send':
try:
2006-09-13 18:47:58 +02:00
lang = gajim.config.get('speller_language')
if not lang:
lang = gajim.LANG
gtkspell.Spell(self.conversation_textview.tv, lang)
gtkspell.Spell(self.message_textview, lang)
except (gobject.GError, TypeError, RuntimeError, OSError):
2007-12-12 09:44:46 +01:00
AspellDictError(lang)
self.prepare_widgets_for(self.action)
# set_text(None) raises TypeError exception
if self.subject is None:
self.subject = ''
self.subject_entry.set_text(self.subject)
if to == '':
liststore = gtkgui_helpers.get_completion_liststore(self.to_entry)
self.completion_dict = helpers.get_contact_dict_for_account(account)
keys = sorted(self.completion_dict.keys())
2006-05-09 15:07:33 +02:00
for jid in keys:
contact = self.completion_dict[jid]
img = gajim.interface.jabber_state_images['16'][contact.show]
liststore.append((img.get_pixbuf(), jid))
else:
self.completion_dict = {}
self.xml.signal_autoconnect(self)
2005-10-17 00:08:42 +02:00
# get window position and size from config
gtkgui_helpers.resize_window(self.window,
gajim.config.get('single-msg-width'),
gajim.config.get('single-msg-height'))
gtkgui_helpers.move_window(self.window,
gajim.config.get('single-msg-x-position'),
gajim.config.get('single-msg-y-position'))
self.window.show_all()
2007-12-12 09:44:46 +01:00
def on_single_message_window_destroy(self, widget):
self.instances.remove(self)
2005-11-18 00:04:56 +01:00
def set_cursor_to_end(self):
end_iter = self.message_tv_buffer.get_end_iter()
self.message_tv_buffer.place_cursor(end_iter)
2005-11-18 00:04:56 +01:00
def save_pos(self):
# save the window size and position
x, y = self.window.get_position()
gajim.config.set('single-msg-x-position', x)
gajim.config.set('single-msg-y-position', y)
width, height = self.window.get_size()
gajim.config.set('single-msg-width', width)
gajim.config.set('single-msg-height', height)
gajim.interface.save_config()
def on_single_message_window_delete_event(self, window, ev):
self.save_pos()
def prepare_widgets_for(self, action):
if len(gajim.connections) > 1:
2006-09-13 18:47:58 +02:00
if action == 'send':
title = _('Single Message using account %s') % self.account
else:
title = _('Single Message in account %s') % self.account
else:
title = _('Single Message')
if action == 'send': # prepare UI for Sending
title = _('Send %s') % title
self.send_button.show()
self.send_and_close_button.show()
self.to_label.show()
self.to_entry.show()
self.reply_button.hide()
self.from_label.hide()
self.from_entry.hide()
self.conversation_scrolledwindow.hide()
self.message_scrolledwindow.show()
if self.message: # we come from a reply?
self.message_textview.grab_focus()
self.cancel_button.hide()
self.close_button.show()
self.message_tv_buffer.set_text(self.message)
gobject.idle_add(self.set_cursor_to_end)
else: # we write a new message (not from reply)
self.close_button.hide()
if self.to: # do we already have jid?
self.subject_entry.grab_focus()
elif action == 'receive': # prepare UI for Receiving
title = _('Received %s') % title
self.reply_button.show()
self.from_label.show()
self.from_entry.show()
self.send_button.hide()
self.send_and_close_button.hide()
self.to_label.hide()
self.to_entry.hide()
self.conversation_scrolledwindow.show()
self.message_scrolledwindow.hide()
if self.message:
self.conversation_textview.print_real_text(self.message)
fjid = self.from_whom
if self.resource:
fjid += '/' + self.resource # Full jid of sender (with resource)
self.from_entry.set_text(fjid)
self.from_entry.set_property('editable', False)
self.subject_entry.set_property('editable', False)
self.reply_button.grab_focus()
self.cancel_button.hide()
self.close_button.show()
2007-12-12 09:44:46 +01:00
elif action == 'form': # prepare UI for Receiving
title = _('Form %s') % title
self.send_button.show()
self.send_and_close_button.show()
self.to_label.show()
self.to_entry.show()
self.reply_button.hide()
self.from_label.hide()
self.from_entry.hide()
self.conversation_scrolledwindow.hide()
self.message_scrolledwindow.hide()
self.window.set_title(title)
def on_cancel_button_clicked(self, widget):
self.save_pos()
self.window.destroy()
def on_close_button_clicked(self, widget):
self.save_pos()
self.window.destroy()
def update_char_counter(self, widget):
characters_no = self.message_tv_buffer.get_char_count()
self.count_chars_label.set_text(unicode(characters_no))
def send_single_message(self):
2005-08-06 21:14:21 +02:00
if gajim.connections[self.account].connected <= 1:
# if offline or connecting
2005-08-06 21:14:21 +02:00
ErrorDialog(_('Connection not available'),
_('Please make sure you are connected with "%s".') % self.account)
2005-08-06 21:14:21 +02:00
return
if isinstance(self.to, list):
2006-11-18 21:52:28 +01:00
sender_list = [i[0].jid + '/' + i[0].resource for i in self.to]
else:
sender_list = [self.to_entry.get_text().decode('utf-8')]
2006-11-18 21:52:28 +01:00
for to_whom_jid in sender_list:
if to_whom_jid in self.completion_dict:
2006-11-18 21:52:28 +01:00
to_whom_jid = self.completion_dict[to_whom_jid].jid
try:
to_whom_jid = helpers.parse_jid(to_whom_jid)
except helpers.InvalidFormat:
ErrorDialog(_('Invalid Jabber ID'),
_('It is not possible to send a message to %s, this JID is not '
'valid.') % to_whom_jid)
return
2006-11-18 21:52:28 +01:00
subject = self.subject_entry.get_text().decode('utf-8')
begin, end = self.message_tv_buffer.get_bounds()
message = self.message_tv_buffer.get_text(begin, end).decode('utf-8')
if '/announce/' in to_whom_jid:
2006-11-18 21:52:28 +01:00
gajim.connections[self.account].send_motd(to_whom_jid, subject,
message)
continue
2005-08-06 21:14:21 +02:00
2007-12-12 09:44:46 +01:00
if self.session:
session = self.session
else:
2008-08-08 00:08:08 +02:00
session = gajim.connections[self.account].make_new_session(
to_whom_jid)
2007-12-12 09:44:46 +01:00
if self.form_widget:
form_node = self.form_widget.data_form
else:
form_node = None
2006-11-18 21:52:28 +01:00
# FIXME: allow GPG message some day
gajim.connections[self.account].send_message(to_whom_jid, message,
keyID=None, type_='normal', subject=subject, session=session,
2007-12-12 09:44:46 +01:00
form_node=form_node)
2005-07-05 23:57:19 +02:00
self.subject_entry.set_text('') # we sent ok, clear the subject
self.message_tv_buffer.set_text('') # we sent ok, clear the textview
def on_send_button_clicked(self, widget):
self.send_single_message()
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
2006-09-13 18:47:58 +02:00
self.message = _('%s wrote:\n') % self.from_whom + self.message
2005-11-18 00:04:56 +01:00
# add > at the begining of each line
self.message = self.message.replace('\n', '\n> ') + '\n\n'
2005-07-05 23:57:19 +02:00
self.window.destroy()
2008-09-03 13:25:27 +02:00
SingleMessageWindow(self.account, to=self.from_whom, action='send',
from_whom=self.from_whom, subject=self.subject, message=self.message,
session=self.session)
def on_send_and_close_button_clicked(self, widget):
self.send_single_message()
self.save_pos()
self.window.destroy()
def on_single_message_window_key_press_event(self, widget, event):
if event.keyval == gtk.keysyms.Escape: # ESCAPE
self.save_pos()
self.window.destroy()
class XMLConsoleWindow:
def __init__(self, account):
self.account = account
self.xml = gtkgui_helpers.get_glade('xml_console_window.glade')
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')
self.input_tv_buffer = self.input_textview.get_buffer()
2008-12-03 18:16:04 +01:00
buffer_ = self.stanzas_log_textview.get_buffer()
end_iter = buffer_.get_end_iter()
buffer_.create_mark('end', end_iter, False)
2008-12-03 18:16:04 +01:00
self.tagIn = buffer_.create_tag('incoming')
color = gajim.config.get('inmsgcolor')
self.tagIn.set_property('foreground', color)
self.tagInComment = buffer_.create_tag('in_comment')
self.tagInComment.set_property('foreground', color)
2008-12-03 18:16:04 +01:00
self.tagOut = buffer_.create_tag('outgoing')
color = gajim.config.get('outmsgcolor')
self.tagOut.set_property('foreground', color)
self.tagOutComment = buffer_.create_tag('out_comment')
self.tagOutComment.set_property('foreground', color)
2005-08-06 21:14:21 +02:00
self.enabled = False
self.input_textview.modify_text(
gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
if len(gajim.connections) > 1:
title = _('XML Console for %s') % self.account
else:
title = _('XML Console')
self.window.set_title(title)
self.window.show_all()
self.xml.signal_autoconnect(self)
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):
2008-12-03 18:16:04 +01:00
buffer_ = self.stanzas_log_textview.get_buffer()
buffer_.set_text('')
def on_enable_checkbutton_toggled(self, widget):
2005-08-06 21:14:21 +02:00
self.enabled = widget.get_active()
def scroll_to_end(self, ):
parent = self.stanzas_log_textview.get_parent()
2008-12-03 18:16:04 +01:00
buffer_ = self.stanzas_log_textview.get_buffer()
end_mark = buffer_.get_mark('end')
2006-05-29 20:23:12 +02:00
if not end_mark:
return False
self.stanzas_log_textview.scroll_to_mark(end_mark, 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:
return
if not stanza:
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
end_iter = buffer.get_end_iter()
if kind == 'incoming':
2009-06-15 21:00:14 +02:00
buffer.insert_with_tags_by_name(end_iter, '<!-- In -->\n',
'in_comment')
elif kind == 'outgoing':
2009-06-15 21:00:14 +02:00
buffer.insert_with_tags_by_name(end_iter, '<!-- Out -->\n',
'out_comment')
end_iter = buffer.get_end_iter()
2005-11-14 11:14:55 +01:00
buffer.insert_with_tags_by_name(end_iter, stanza.replace('><', '>\n<') + \
'\n\n', kind)
if at_the_end:
gobject.idle_add(self.scroll_to_end)
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'),
2006-09-13 18:47:58 +02:00
_('Please make sure you are connected with "%s".') % self.account)
2005-08-06 21:14:21 +02:00
return
begin_iter, end_iter = self.input_tv_buffer.get_bounds()
2008-08-08 00:08:08 +02:00
stanza = self.input_tv_buffer.get_text(begin_iter, end_iter).decode(
'utf-8')
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>'
)
def on_expander_activate(self, widget):
if not widget.get_expanded(): # it's the opposite!
# it's expanded!!
self.input_textview.grab_focus()
2006-07-17 21:30:53 +02:00
class PrivacyListWindow:
2006-11-18 21:52:28 +01:00
'''Window that is used for creating NEW or EDITING already there privacy
lists'''
def __init__(self, account, privacy_list_name, action):
'''action is 'EDIT' or 'NEW' depending on if we create a new priv list
or edit an already existing one'''
2006-07-17 21:30:53 +02:00
self.account = account
2006-11-18 21:52:28 +01:00
self.privacy_list_name = privacy_list_name
2006-07-17 21:30:53 +02:00
# Dicts and Default Values
self.active_rule = ''
self.global_rules = {}
self.list_of_groups = {}
# Default Edit Values
self.edit_rule_type = 'jid'
self.allow_deny = 'allow'
# Connect to glade
2006-11-18 21:52:28 +01:00
self.xml = gtkgui_helpers.get_glade('privacy_list_window.glade')
2006-07-17 21:30:53 +02:00
self.window = self.xml.get_widget('privacy_list_edit_window')
# Add Widgets
for widget_to_add in ('title_hbox', 'privacy_lists_title_label',
2006-07-17 21:30:53 +02:00
'list_of_rules_label', 'add_edit_rule_label', 'delete_open_buttons_hbox',
'privacy_list_active_checkbutton', 'privacy_list_default_checkbutton',
'list_of_rules_combobox', 'delete_open_buttons_hbox',
'delete_rule_button', 'open_rule_button', 'edit_allow_radiobutton',
'edit_deny_radiobutton', 'edit_type_jabberid_radiobutton',
'edit_type_jabberid_entry', 'edit_type_group_radiobutton',
'edit_type_group_combobox', 'edit_type_subscription_radiobutton',
'edit_type_subscription_combobox', 'edit_type_select_all_radiobutton',
'edit_queries_send_checkbutton', 'edit_send_messages_checkbutton',
'edit_view_status_checkbutton', 'edit_order_spinbutton',
'new_rule_button', 'save_rule_button', 'privacy_list_refresh_button',
'privacy_list_close_button', 'edit_send_status_checkbutton',
'add_edit_vbox', 'privacy_list_active_checkbutton',
'privacy_list_default_checkbutton'):
2006-07-17 21:30:53 +02:00
self.__dict__[widget_to_add] = self.xml.get_widget(widget_to_add)
self.privacy_lists_title_label.set_label(
_('Privacy List <b><i>%s</i></b>') % \
gobject.markup_escape_text(self.privacy_list_name))
2006-07-17 21:30:53 +02:00
if len(gajim.connections) > 1:
title = _('Privacy List for %s') % self.account
else:
title = _('Privacy List')
self.delete_rule_button.set_sensitive(False)
self.open_rule_button.set_sensitive(False)
self.privacy_list_active_checkbutton.set_sensitive(False)
self.privacy_list_default_checkbutton.set_sensitive(False)
2006-11-18 21:52:28 +01:00
self.list_of_rules_combobox.set_sensitive(False)
2006-07-17 21:30:53 +02:00
2007-06-03 12:04:20 +02:00
# set jabber id completion
jids_list_store = gtk.ListStore(gobject.TYPE_STRING)
for jid in gajim.contacts.get_jid_list(self.account):
jids_list_store.append([jid])
2007-06-03 12:04:20 +02:00
jid_entry_completion = gtk.EntryCompletion()
jid_entry_completion.set_text_column(0)
jid_entry_completion.set_model(jids_list_store)
jid_entry_completion.set_popup_completion(True)
2007-08-09 17:39:18 +02:00
self.edit_type_jabberid_entry.set_completion(jid_entry_completion)
2006-11-18 21:52:28 +01:00
if action == 'EDIT':
2006-07-17 21:30:53 +02:00
self.refresh_rules()
count = 0
for group in gajim.groups[self.account]:
self.list_of_groups[group] = count
count += 1
self.edit_type_group_combobox.append_text(group)
self.edit_type_group_combobox.set_active(0)
2006-07-17 21:30:53 +02:00
self.window.set_title(title)
self.window.show_all()
self.add_edit_vbox.hide()
2006-11-18 21:52:28 +01:00
2006-07-17 21:30:53 +02:00
self.xml.signal_autoconnect(self)
def on_privacy_list_edit_window_destroy(self, widget):
2006-11-18 21:52:28 +01:00
key_name = 'privacy_list_%s' % self.privacy_list_name
if key_name in gajim.interface.instances[self.account]:
del gajim.interface.instances[self.account][key_name]
2006-07-17 21:30:53 +02:00
def check_active_default(self, a_d_dict):
2006-11-18 21:52:28 +01:00
if a_d_dict['active'] == self.privacy_list_name:
2006-07-17 21:30:53 +02:00
self.privacy_list_active_checkbutton.set_active(True)
else:
self.privacy_list_active_checkbutton.set_active(False)
2006-11-18 21:52:28 +01:00
if a_d_dict['default'] == self.privacy_list_name:
2006-07-17 21:30:53 +02:00
self.privacy_list_default_checkbutton.set_active(True)
else:
self.privacy_list_default_checkbutton.set_active(False)
2006-07-17 21:30:53 +02:00
def privacy_list_received(self, rules):
self.list_of_rules_combobox.get_model().clear()
self.global_rules = {}
for rule in rules:
if 'type' in rule:
2008-08-01 11:30:36 +02:00
text_item = _('Order: %(order)s, action: %(action)s, type: %(type)s'
', value: %(value)s') % {'order': rule['order'],
'action': rule['action'], 'type': rule['type'],
'value': rule['value']}
2006-07-17 21:30:53 +02:00
else:
2008-08-01 11:30:36 +02:00
text_item = _('Order: %(order)s, action: %(action)s') % \
{'order': rule['order'], 'action': rule['action']}
2006-07-17 21:30:53 +02:00
self.global_rules[text_item] = rule
self.list_of_rules_combobox.append_text(text_item)
if len(rules) == 0:
self.title_hbox.set_sensitive(False)
self.list_of_rules_combobox.set_sensitive(False)
self.delete_rule_button.set_sensitive(False)
self.open_rule_button.set_sensitive(False)
self.privacy_list_active_checkbutton.set_sensitive(False)
self.privacy_list_default_checkbutton.set_sensitive(False)
else:
self.list_of_rules_combobox.set_active(0)
self.title_hbox.set_sensitive(True)
self.list_of_rules_combobox.set_sensitive(True)
self.delete_rule_button.set_sensitive(True)
self.open_rule_button.set_sensitive(True)
self.privacy_list_active_checkbutton.set_sensitive(True)
self.privacy_list_default_checkbutton.set_sensitive(True)
self.reset_fields()
gajim.connections[self.account].get_active_default_lists()
def refresh_rules(self):
2006-11-18 21:52:28 +01:00
gajim.connections[self.account].get_privacy_list(self.privacy_list_name)
2006-07-17 21:30:53 +02:00
def on_delete_rule_button_clicked(self, widget):
tags = []
for rule in self.global_rules:
2006-11-18 21:52:28 +01:00
if rule != self.list_of_rules_combobox.get_active_text():
2006-07-17 21:30:53 +02:00
tags.append(self.global_rules[rule])
gajim.connections[self.account].set_privacy_list(
2006-11-18 21:52:28 +01:00
self.privacy_list_name, tags)
2006-07-17 21:30:53 +02:00
self.privacy_list_received(tags)
self.add_edit_vbox.hide()
2006-11-18 21:52:28 +01:00
if not tags: # we removed latest rule
if 'privacy_lists' in gajim.interface.instances[self.account]:
win = gajim.interface.instances[self.account]['privacy_lists']
win.remove_privacy_list_from_combobox(self.privacy_list_name)
win.draw_widgets()
2006-07-17 21:30:53 +02:00
def on_open_rule_button_clicked(self, widget):
self.add_edit_rule_label.set_label(
2006-11-18 21:52:28 +01:00
_('<b>Edit a rule</b>'))
2006-07-17 21:30:53 +02:00
active_num = self.list_of_rules_combobox.get_active()
if active_num == -1:
self.active_rule = ''
else:
self.active_rule = \
self.list_of_rules_combobox.get_active_text().decode('utf-8')
if self.active_rule != '':
rule_info = self.global_rules[self.active_rule]
self.edit_order_spinbutton.set_value(int(rule_info['order']))
if 'type' in rule_info:
2006-07-17 21:30:53 +02:00
if rule_info['type'] == 'jid':
self.edit_type_jabberid_radiobutton.set_active(True)
self.edit_type_jabberid_entry.set_text(rule_info['value'])
elif rule_info['type'] == 'group':
self.edit_type_group_radiobutton.set_active(True)
if rule_info['value'] in self.list_of_groups:
2006-07-17 21:30:53 +02:00
self.edit_type_group_combobox.set_active(
self.list_of_groups[rule_info['value']])
else:
self.edit_type_group_combobox.set_active(0)
elif rule_info['type'] == 'subscription':
self.edit_type_subscription_radiobutton.set_active(True)
sub_value = rule_info['value']
if sub_value == 'none':
self.edit_type_subscription_combobox.set_active(0)
elif sub_value == 'both':
self.edit_type_subscription_combobox.set_active(1)
elif sub_value == 'from':
self.edit_type_subscription_combobox.set_active(2)
elif sub_value == 'to':
self.edit_type_subscription_combobox.set_active(3)
else:
self.edit_type_select_all_radiobutton.set_active(True)
else:
self.edit_type_select_all_radiobutton.set_active(True)
self.edit_send_messages_checkbutton.set_active(False)
self.edit_queries_send_checkbutton.set_active(False)
self.edit_view_status_checkbutton.set_active(False)
self.edit_send_status_checkbutton.set_active(False)
for child in rule_info['child']:
if child == 'presence-out':
self.edit_send_status_checkbutton.set_active(True)
elif child == 'presence-in':
self.edit_view_status_checkbutton.set_active(True)
elif child == 'iq':
self.edit_queries_send_checkbutton.set_active(True)
elif child == 'message':
self.edit_send_messages_checkbutton.set_active(True)
2006-11-18 21:52:28 +01:00
2006-07-17 21:30:53 +02:00
if rule_info['action'] == 'allow':
2006-11-18 21:52:28 +01:00
self.edit_allow_radiobutton.set_active(True)
2006-07-17 21:30:53 +02:00
else:
2006-11-18 21:52:28 +01:00
self.edit_deny_radiobutton.set_active(True)
2006-07-17 21:30:53 +02:00
self.add_edit_vbox.show()
2006-11-18 21:52:28 +01:00
2006-07-17 21:30:53 +02:00
def on_privacy_list_active_checkbutton_toggled(self, widget):
if widget.get_active():
2006-11-18 21:52:28 +01:00
gajim.connections[self.account].set_active_list(
self.privacy_list_name)
2006-07-17 21:30:53 +02:00
else:
gajim.connections[self.account].set_active_list(None)
def on_privacy_list_default_checkbutton_toggled(self, widget):
if widget.get_active():
2006-11-18 21:52:28 +01:00
gajim.connections[self.account].set_default_list(
self.privacy_list_name)
2006-07-17 21:30:53 +02:00
else:
gajim.connections[self.account].set_default_list(None)
def on_new_rule_button_clicked(self, widget):
self.reset_fields()
self.add_edit_vbox.show()
2006-11-18 21:52:28 +01:00
2006-07-17 21:30:53 +02:00
def reset_fields(self):
self.edit_type_jabberid_entry.set_text('')
self.edit_allow_radiobutton.set_active(True)
self.edit_type_jabberid_radiobutton.set_active(True)
self.active_rule = ''
self.edit_send_messages_checkbutton.set_active(False)
self.edit_queries_send_checkbutton.set_active(False)
self.edit_view_status_checkbutton.set_active(False)
self.edit_send_status_checkbutton.set_active(False)
self.edit_order_spinbutton.set_value(1)
2006-07-17 21:30:53 +02:00
self.edit_type_group_combobox.set_active(0)
self.edit_type_subscription_combobox.set_active(0)
self.add_edit_rule_label.set_label(
_('<b>Add a rule</b>'))
def get_current_tags(self):
if self.edit_type_jabberid_radiobutton.get_active():
edit_type = 'jid'
2006-11-18 21:52:28 +01:00
edit_value = self.edit_type_jabberid_entry.get_text()
2006-07-17 21:30:53 +02:00
elif self.edit_type_group_radiobutton.get_active():
edit_type = 'group'
2006-11-18 21:52:28 +01:00
edit_value = self.edit_type_group_combobox.get_active_text()
2006-07-17 21:30:53 +02:00
elif self.edit_type_subscription_radiobutton.get_active():
edit_type = 'subscription'
subs = ['none', 'both', 'from', 'to']
edit_value = subs[self.edit_type_subscription_combobox.get_active()]
elif self.edit_type_select_all_radiobutton.get_active():
edit_type = ''
edit_value = ''
edit_order = str(self.edit_order_spinbutton.get_value_as_int())
if self.edit_allow_radiobutton.get_active():
edit_deny = 'allow'
else:
edit_deny = 'deny'
child = []
if self.edit_send_messages_checkbutton.get_active():
child.append('message')
if self.edit_queries_send_checkbutton.get_active():
child.append('iq')
if self.edit_send_status_checkbutton.get_active():
child.append('presence-out')
if self.edit_view_status_checkbutton.get_active():
child.append('presence-in')
if edit_type != '':
return {'order': edit_order, 'action': edit_deny,
'type': edit_type, 'value': edit_value, 'child': child}
return {'order': edit_order, 'action': edit_deny, 'child': child}
def on_save_rule_button_clicked(self, widget):
tags=[]
current_tags = self.get_current_tags()
if self.active_rule == '':
tags.append(current_tags)
for rule in self.global_rules:
if rule != self.active_rule:
tags.append(self.global_rules[rule])
else:
tags.append(current_tags)
2006-11-18 21:52:28 +01:00
gajim.connections[self.account].set_privacy_list(
self.privacy_list_name, tags)
2007-06-03 12:04:20 +02:00
self.refresh_rules()
2006-07-17 21:30:53 +02:00
self.add_edit_vbox.hide()
2006-11-18 21:52:28 +01:00
if 'privacy_lists' in gajim.interface.instances[self.account]:
win = gajim.interface.instances[self.account]['privacy_lists']
win.add_privacy_list_to_combobox(self.privacy_list_name)
win.draw_widgets()
2006-07-17 21:30:53 +02:00
def on_list_of_rules_combobox_changed(self, widget):
self.add_edit_vbox.hide()
def on_edit_type_radiobutton_changed(self, widget, radiobutton):
active_bool = widget.get_active()
if active_bool:
self.edit_rule_type = radiobutton
def on_edit_allow_radiobutton_changed(self, widget, radiobutton):
active_bool = widget.get_active()
if active_bool:
self.allow_deny = radiobutton
2006-11-18 21:52:28 +01:00
def on_close_button_clicked(self, widget):
2006-07-17 21:30:53 +02:00
self.window.destroy()
class PrivacyListsWindow:
2006-11-18 21:52:28 +01:00
'''Window that is the main window for Privacy Lists;
we can list there the privacy lists and ask to create a new one
or edit an already there one'''
2006-07-17 21:30:53 +02:00
def __init__(self, account):
self.account = account
self.privacy_lists_save = []
2006-07-17 21:30:53 +02:00
2006-11-18 21:52:28 +01:00
self.xml = gtkgui_helpers.get_glade('privacy_lists_window.glade')
2006-07-17 21:30:53 +02:00
self.window = self.xml.get_widget('privacy_lists_first_window')
for widget_to_add in ('list_of_privacy_lists_combobox',
2006-11-18 21:52:28 +01:00
'delete_privacy_list_button', 'open_privacy_list_button',
'new_privacy_list_button', 'new_privacy_list_entry',
'privacy_lists_refresh_button', 'close_privacy_lists_window_button'):
2006-11-18 21:52:28 +01:00
self.__dict__[widget_to_add] = self.xml.get_widget(
widget_to_add)
2006-07-17 21:30:53 +02:00
2006-11-18 21:52:28 +01:00
self.draw_privacy_lists_in_combobox([])
2006-07-17 21:30:53 +02:00
self.privacy_lists_refresh()
self.enabled = True
if len(gajim.connections) > 1:
title = _('Privacy Lists for %s') % self.account
else:
title = _('Privacy Lists')
self.window.set_title(title)
self.window.show_all()
self.xml.signal_autoconnect(self)
def on_privacy_lists_first_window_destroy(self, widget):
2006-11-18 21:52:28 +01:00
if 'privacy_lists' in gajim.interface.instances[self.account]:
2006-07-17 21:30:53 +02:00
del gajim.interface.instances[self.account]['privacy_lists']
2006-11-18 21:52:28 +01:00
def remove_privacy_list_from_combobox(self, privacy_list):
if privacy_list not in self.privacy_lists_save:
return
privacy_list_index = self.privacy_lists_save.index(privacy_list)
self.list_of_privacy_lists_combobox.remove_text(privacy_list_index)
self.privacy_lists_save.remove(privacy_list)
def add_privacy_list_to_combobox(self, privacy_list):
if privacy_list in self.privacy_lists_save:
return
self.list_of_privacy_lists_combobox.append_text(privacy_list)
self.privacy_lists_save.append(privacy_list)
def draw_privacy_lists_in_combobox(self, privacy_lists):
2006-07-17 21:30:53 +02:00
self.list_of_privacy_lists_combobox.set_active(-1)
self.list_of_privacy_lists_combobox.get_model().clear()
2006-11-18 21:52:28 +01:00
self.privacy_lists_save = []
for add_item in privacy_lists:
self.add_privacy_list_to_combobox(add_item)
self.draw_widgets()
def draw_widgets(self):
if len(self.privacy_lists_save) == 0:
2006-07-17 21:30:53 +02:00
self.list_of_privacy_lists_combobox.set_sensitive(False)
2006-11-18 21:52:28 +01:00
self.open_privacy_list_button.set_sensitive(False)
self.delete_privacy_list_button.set_sensitive(False)
2006-07-17 21:30:53 +02:00
else:
self.list_of_privacy_lists_combobox.set_sensitive(True)
self.list_of_privacy_lists_combobox.set_active(0)
2006-11-18 21:52:28 +01:00
self.open_privacy_list_button.set_sensitive(True)
self.delete_privacy_list_button.set_sensitive(True)
2006-07-17 21:30:53 +02:00
def on_close_button_clicked(self, widget):
self.window.destroy()
def on_delete_privacy_list_button_clicked(self, widget):
active_list = self.privacy_lists_save[
self.list_of_privacy_lists_combobox.get_active()]
gajim.connections[self.account].del_privacy_list(active_list)
def privacy_list_removed(self, active_list):
2006-07-17 21:30:53 +02:00
self.privacy_lists_save.remove(active_list)
2006-11-18 21:52:28 +01:00
self.privacy_lists_received({'lists': self.privacy_lists_save})
2006-07-17 21:30:53 +02:00
def privacy_lists_received(self, lists):
if not lists:
return
2006-11-18 21:52:28 +01:00
privacy_lists = []
2006-07-17 21:30:53 +02:00
for privacy_list in lists['lists']:
2006-11-18 21:52:28 +01:00
privacy_lists.append(privacy_list)
self.draw_privacy_lists_in_combobox(privacy_lists)
2006-07-17 21:30:53 +02:00
def privacy_lists_refresh(self):
gajim.connections[self.account].get_privacy_lists()
def on_new_privacy_list_button_clicked(self, widget):
2006-11-18 21:52:28 +01:00
name = self.new_privacy_list_entry.get_text()
if not name:
ErrorDialog(_('Invalid List Name'),
_('You must enter a name to create a privacy list.'))
return
key_name = 'privacy_list_%s' % name
if key_name in gajim.interface.instances[self.account]:
2006-11-18 21:52:28 +01:00
gajim.interface.instances[self.account][key_name].window.present()
2006-07-17 21:30:53 +02:00
else:
2006-11-18 21:52:28 +01:00
gajim.interface.instances[self.account][key_name] = \
PrivacyListWindow(self.account, name, 'NEW')
2006-07-17 21:30:53 +02:00
self.new_privacy_list_entry.set_text('')
def on_privacy_lists_refresh_button_clicked(self, widget):
self.privacy_lists_refresh()
def on_open_privacy_list_button_clicked(self, widget):
name = self.privacy_lists_save[
self.list_of_privacy_lists_combobox.get_active()]
2006-11-18 21:52:28 +01:00
key_name = 'privacy_list_%s' % name
if key_name in gajim.interface.instances[self.account]:
2006-11-18 21:52:28 +01:00
gajim.interface.instances[self.account][key_name].window.present()
2006-07-17 21:30:53 +02:00
else:
2006-11-18 21:52:28 +01:00
gajim.interface.instances[self.account][key_name] = \
PrivacyListWindow(self.account, name, 'EDIT')
2006-07-17 21:30:53 +02:00
class InvitationReceivedDialog:
def __init__(self, account, room_jid, contact_jid, password=None,
comment=None, is_continued=False):
self.room_jid = room_jid
self.account = account
2007-08-09 17:39:18 +02:00
self.password = password
2007-12-12 09:44:46 +01:00
self.is_continued = is_continued
2006-07-17 21:30:53 +02:00
pritext = _('''You are invited to a groupchat''')
#Don't translate $Contact
2007-12-12 09:44:46 +01:00
if is_continued:
sectext = _('$Contact has invited you to join a discussion')
2007-12-12 09:44:46 +01:00
else:
sectext = _('$Contact has invited you to group chat %(room_jid)s')\
2007-12-12 09:44:46 +01:00
% {'room_jid': room_jid}
contact = gajim.contacts.get_first_contact_from_jid(account, contact_jid)
contact_text = contact and contact.name or contact_jid
sectext = sectext.replace('$Contact', contact_text)
2006-03-10 15:01:57 +01:00
if comment: # only if not None and not ''
2007-12-12 09:44:46 +01:00
comment = gobject.markup_escape_text(comment)
comment = _('Comment: %s') % comment
sectext += '\n\n%s' % comment
sectext += '\n\n' + _('Do you want to accept the invitation?')
def on_yes(checked):
try:
if self.is_continued:
gajim.interface.join_gc_room(self.account, self.room_jid,
gajim.nicks[self.account], None, is_continued=True)
else:
JoinGroupchatWindow(self.account, self.room_jid)
except GajimGeneralException:
pass
2008-12-02 16:53:23 +01:00
YesNoDialog(pritext, sectext, on_response_yes=on_yes)
class ProgressDialog:
2005-12-02 18:16:23 +01:00
def __init__(self, title_text, during_text, messages_queue):
'''during text is what to show during the procedure,
messages_queue has the message to show
in the textview'''
self.xml = gtkgui_helpers.get_glade('progress_dialog.glade')
self.dialog = self.xml.get_widget('progress_dialog')
2005-12-02 18:16:23 +01:00
self.label = self.xml.get_widget('label')
self.label.set_markup('<big>' + during_text + '</big>')
2005-12-02 18:16:23 +01:00
self.progressbar = self.xml.get_widget('progressbar')
self.dialog.set_title(title_text)
self.dialog.set_default_size(450, 250)
2009-04-05 20:35:59 +02:00
self.window.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
self.dialog.show_all()
2005-12-02 18:16:23 +01:00
self.xml.signal_autoconnect(self)
self.update_progressbar_timeout_id = gobject.timeout_add(100,
self.update_progressbar)
def update_progressbar(self):
if self.dialog:
self.progressbar.pulse()
return True # loop forever
return False
def on_progress_dialog_delete_event(self, widget, event):
return True # WM's X button or Escape key should not destroy the window
class SoundChooserDialog(FileChooserDialog):
2008-08-08 00:08:08 +02:00
def __init__(self, path_to_snd_file='', on_response_ok=None,
on_response_cancel=None):
'''optionally accepts path_to_snd_file so it has that as selected'''
def on_ok(widget, callback):
'''check if file exists and call callback'''
path_to_snd_file = self.get_filename()
path_to_snd_file = gtkgui_helpers.decode_filechooser_file_paths(
(path_to_snd_file,))[0]
if os.path.exists(path_to_snd_file):
callback(widget, path_to_snd_file)
FileChooserDialog.__init__(self,
title_text = _('Choose Sound'),
action = gtk.FILE_CHOOSER_ACTION_OPEN,
buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN, gtk.RESPONSE_OK),
default_response = gtk.RESPONSE_OK,
current_folder = gajim.config.get('last_sounds_dir'),
on_response_ok = (on_ok, on_response_ok),
on_response_cancel = on_response_cancel)
2008-12-03 18:16:04 +01:00
filter_ = gtk.FileFilter()
filter_.set_name(_('All files'))
filter_.add_pattern('*')
self.add_filter(filter_)
2008-12-03 18:16:04 +01:00
filter_ = gtk.FileFilter()
filter_.set_name(_('Wav Sounds'))
filter_.add_pattern('*.wav')
self.add_filter(filter_)
self.set_filter(filter_)
path_to_snd_file = helpers.check_soundfile_path(path_to_snd_file)
if path_to_snd_file:
# set_filename accept only absolute path
path_to_snd_file = os.path.abspath(path_to_snd_file)
self.set_filename(path_to_snd_file)
class ImageChooserDialog(FileChooserDialog):
2008-08-08 00:08:08 +02:00
def __init__(self, path_to_file='', on_response_ok=None,
on_response_cancel=None):
'''optionally accepts path_to_snd_file so it has that as selected'''
def on_ok(widget, callback):
'''check if file exists and call callback'''
path_to_file = self.get_filename()
2006-09-13 18:47:58 +02:00
if not path_to_file:
return
path_to_file = gtkgui_helpers.decode_filechooser_file_paths(
(path_to_file,))[0]
if os.path.exists(path_to_file):
2007-08-09 17:39:18 +02:00
if isinstance(callback, tuple):
callback[0](widget, path_to_file, *callback[1:])
else:
callback(widget, path_to_file)
try:
if os.name == 'nt':
path = helpers.get_my_pictures_path()
else:
path = os.environ['HOME']
except Exception:
path = ''
FileChooserDialog.__init__(self,
title_text = _('Choose Image'),
action = gtk.FILE_CHOOSER_ACTION_OPEN,
buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN, gtk.RESPONSE_OK),
default_response = gtk.RESPONSE_OK,
current_folder = path,
on_response_ok = (on_ok, on_response_ok),
on_response_cancel = on_response_cancel)
2007-12-12 09:44:46 +01:00
if on_response_cancel:
self.connect('destroy', on_response_cancel)
2008-12-03 18:16:04 +01:00
filter_ = gtk.FileFilter()
filter_.set_name(_('All files'))
filter_.add_pattern('*')
self.add_filter(filter_)
filter_ = gtk.FileFilter()
filter_.set_name(_('Images'))
filter_.add_mime_type('image/png')
filter_.add_mime_type('image/jpeg')
filter_.add_mime_type('image/gif')
filter_.add_mime_type('image/tiff')
filter_.add_mime_type('image/svg+xml')
filter_.add_mime_type('image/x-xpixmap') # xpm
self.add_filter(filter_)
self.set_filter(filter_)
if path_to_file:
self.set_filename(path_to_file)
self.set_use_preview_label(False)
self.set_preview_widget(gtk.Image())
self.connect('selection-changed', self.update_preview)
def update_preview(self, widget):
path_to_file = widget.get_preview_filename()
if path_to_file is None or os.path.isdir(path_to_file):
# nothing to preview or directory
# make sure you clean image do show nothing
widget.get_preview_widget().set_from_file(None)
return
try:
pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(path_to_file, 100, 100)
except gobject.GError:
return
widget.get_preview_widget().set_from_pixbuf(pixbuf)
2006-11-18 21:52:28 +01:00
class AvatarChooserDialog(ImageChooserDialog):
2008-08-08 00:08:08 +02:00
def __init__(self, path_to_file='', on_response_ok=None,
on_response_cancel=None, on_response_clear=None):
2006-11-18 21:52:28 +01:00
ImageChooserDialog.__init__(self, path_to_file, on_response_ok,
on_response_cancel)
button = gtk.Button(None, gtk.STOCK_CLEAR)
2007-08-09 17:39:18 +02:00
self.response_clear = on_response_clear
2006-11-18 21:52:28 +01:00
if on_response_clear:
2007-08-09 17:39:18 +02:00
button.connect('clicked', self.on_clear)
2006-11-18 21:52:28 +01:00
button.show_all()
self.action_area.pack_start(button)
self.action_area.reorder_child(button, 0)
2007-08-09 17:39:18 +02:00
def on_clear(self, widget):
if isinstance(self.response_clear, tuple):
self.response_clear[0](widget, *self.response_clear[1:])
else:
self.response_clear(widget)
class AddSpecialNotificationDialog:
def __init__(self, jid):
'''jid is the jid for which we want to add special notification
(sound and notification popups)'''
self.xml = gtkgui_helpers.get_glade('add_special_notification_window.glade')
self.window = self.xml.get_widget('add_special_notification_window')
self.condition_combobox = self.xml.get_widget('condition_combobox')
self.condition_combobox.set_active(0)
self.notification_popup_yes_no_combobox = self.xml.get_widget(
'notification_popup_yes_no_combobox')
self.notification_popup_yes_no_combobox.set_active(0)
self.listen_sound_combobox = self.xml.get_widget('listen_sound_combobox')
self.listen_sound_combobox.set_active(0)
self.jid = jid
self.xml.get_widget('when_foo_becomes_label').set_text(
_('When %s becomes:') % self.jid)
self.window.set_title(_('Adding Special Notification for %s') % jid)
self.window.show_all()
self.xml.signal_autoconnect(self)
def on_cancel_button_clicked(self, widget):
self.window.destroy()
def on_add_special_notification_window_delete_event(self, widget, event):
self.window.destroy()
def on_listen_sound_combobox_changed(self, widget):
active = widget.get_active()
if active == 1: # user selected 'choose sound'
def on_ok(widget, path_to_snd_file):
2008-12-15 22:06:08 +01:00
pass
#print path_to_snd_file
def on_cancel(widget):
widget.set_active(0) # go back to No Sound
2008-09-03 13:25:27 +02:00
self.dialog = SoundChooserDialog(on_response_ok=on_ok,
on_response_cancel=on_cancel)
def on_ok_button_clicked(self, widget):
conditions = ('online', 'chat', 'online_and_chat',
'away', 'xa', 'away_and_xa', 'dnd', 'xa_and_dnd', 'offline')
active = self.condition_combobox.get_active()
active_iter = self.listen_sound_combobox.get_active_iter()
listen_sound_model = self.listen_sound_combobox.get_model()
class AdvancedNotificationsWindow:
2006-07-17 21:30:53 +02:00
events_list = ['message_received', 'contact_connected',
'contact_disconnected', 'contact_change_status', 'gc_msg_highlight',
'gc_msg', 'ft_request', 'ft_started', 'ft_finished']
recipient_types_list = ['contact', 'group', 'all']
config_options = ['event', 'recipient_type', 'recipients', 'status',
'tab_opened', 'sound', 'sound_file', 'popup', 'auto_open',
'run_command', 'command', 'systray', 'roster', 'urgency_hint']
def __init__(self):
self.xml = gtkgui_helpers.get_glade('advanced_notifications_window.glade')
self.window = self.xml.get_widget('advanced_notifications_window')
2006-07-17 21:30:53 +02:00
for w in ('conditions_treeview', 'config_vbox', 'event_combobox',
'recipient_type_combobox', 'recipient_list_entry', 'delete_button',
'status_hbox', 'use_sound_cb', 'disable_sound_cb', 'use_popup_cb',
'disable_popup_cb', 'use_auto_open_cb', 'disable_auto_open_cb',
'use_systray_cb', 'disable_systray_cb', 'use_roster_cb',
'disable_roster_cb', 'tab_opened_cb', 'not_tab_opened_cb',
'sound_entry', 'sound_file_hbox', 'up_button', 'down_button',
'run_command_cb', 'command_entry', 'urgency_hint_cb'):
self.__dict__[w] = self.xml.get_widget(w)
# Contains status checkboxes
childs = self.status_hbox.get_children()
self.all_status_rb = childs[0]
self.special_status_rb = childs[1]
self.online_cb = childs[2]
self.away_cb = childs[3]
2006-07-17 21:30:53 +02:00
self.xa_cb = childs[4]
self.dnd_cb = childs[5]
self.invisible_cb = childs[6]
2006-07-17 21:30:53 +02:00
model = gtk.ListStore(int, str)
model.set_sort_column_id(0, gtk.SORT_ASCENDING)
model.clear()
self.conditions_treeview.set_model(model)
2006-07-17 21:30:53 +02:00
## means number
col = gtk.TreeViewColumn(_('#'))
self.conditions_treeview.append_column(col)
renderer = gtk.CellRendererText()
2008-09-03 13:25:27 +02:00
col.pack_start(renderer, expand=False)
col.set_attributes(renderer, text=0)
2006-07-17 21:30:53 +02:00
col = gtk.TreeViewColumn(_('Condition'))
self.conditions_treeview.append_column(col)
renderer = gtk.CellRendererText()
2008-09-03 13:25:27 +02:00
col.pack_start(renderer, expand=True)
col.set_attributes(renderer, text=1)
2006-07-17 21:30:53 +02:00
self.xml.signal_autoconnect(self)
# Fill conditions_treeview
num = 0
while gajim.config.get_per('notifications', str(num)):
2008-12-03 18:16:04 +01:00
iter_ = model.append((num, ''))
path = model.get_path(iter_)
2006-07-17 21:30:53 +02:00
self.conditions_treeview.set_cursor(path)
self.active_num = num
self.initiate_rule_state()
self.set_treeview_string()
num += 1
# No rule selected at init time
2006-07-17 21:30:53 +02:00
self.conditions_treeview.get_selection().unselect_all()
self.active_num = -1
self.config_vbox.set_sensitive(False)
self.delete_button.set_sensitive(False)
self.down_button.set_sensitive(False)
self.up_button.set_sensitive(False)
self.window.show_all()
def initiate_rule_state(self):
'''Set values for all widgets'''
2006-07-17 21:30:53 +02:00
if self.active_num < 0:
return
# event
value = gajim.config.get_per('notifications', str(self.active_num),
'event')
if value:
self.event_combobox.set_active(self.events_list.index(value))
else:
2006-09-13 18:47:58 +02:00
self.event_combobox.set_active(-1)
2006-07-17 21:30:53 +02:00
# recipient_type
value = gajim.config.get_per('notifications', str(self.active_num),
'recipient_type')
if value:
self.recipient_type_combobox.set_active(
self.recipient_types_list.index(value))
else:
2006-09-13 18:47:58 +02:00
self.recipient_type_combobox.set_active(-1)
2006-07-17 21:30:53 +02:00
# recipient
value = gajim.config.get_per('notifications', str(self.active_num),
'recipients')
if not value:
value = ''
self.recipient_list_entry.set_text(value)
# status
value = gajim.config.get_per('notifications', str(self.active_num),
'status')
if value == 'all':
self.all_status_rb.set_active(True)
else:
self.special_status_rb.set_active(True)
values = value.split()
for v in ('online', 'away', 'xa', 'dnd', 'invisible'):
2006-07-17 21:30:53 +02:00
if v in values:
self.__dict__[v + '_cb'].set_active(True)
else:
self.__dict__[v + '_cb'].set_active(False)
self.on_status_radiobutton_toggled(self.all_status_rb)
2006-07-17 21:30:53 +02:00
# tab_opened
value = gajim.config.get_per('notifications', str(self.active_num),
'tab_opened')
self.tab_opened_cb.set_active(True)
2006-07-17 21:30:53 +02:00
self.not_tab_opened_cb.set_active(True)
if value == 'no':
self.tab_opened_cb.set_active(False)
elif value == 'yes':
self.not_tab_opened_cb.set_active(False)
# sound_file
value = gajim.config.get_per('notifications', str(self.active_num),
'sound_file')
self.sound_entry.set_text(value)
# sound, popup, auto_open, systray, roster
for option in ('sound', 'popup', 'auto_open', 'systray', 'roster'):
2006-07-17 21:30:53 +02:00
value = gajim.config.get_per('notifications', str(self.active_num),
option)
if value == 'yes':
self.__dict__['use_' + option + '_cb'].set_active(True)
else:
self.__dict__['use_' + option + '_cb'].set_active(False)
if value == 'no':
self.__dict__['disable_' + option + '_cb'].set_active(True)
else:
self.__dict__['disable_' + option + '_cb'].set_active(False)
# run_command
value = gajim.config.get_per('notifications', str(self.active_num),
'run_command')
self.run_command_cb.set_active(value)
# command
value = gajim.config.get_per('notifications', str(self.active_num),
'command')
self.command_entry.set_text(value)
# urgency_hint
value = gajim.config.get_per('notifications', str(self.active_num),
'urgency_hint')
self.urgency_hint_cb.set_active(value)
def set_treeview_string(self):
2008-12-03 18:16:04 +01:00
(model, iter_) = self.conditions_treeview.get_selection().get_selected()
if not iter_:
2006-07-17 21:30:53 +02:00
return
event = self.event_combobox.get_active_text()
recipient_type = self.recipient_type_combobox.get_active_text()
recipient = ''
if recipient_type != 'everybody':
recipient = self.recipient_list_entry.get_text()
if self.all_status_rb.get_active():
status = ''
else:
status = _('when I am ')
for st in ('online', 'away', 'xa', 'dnd', 'invisible'):
2006-07-17 21:30:53 +02:00
if self.__dict__[st + '_cb'].get_active():
status += helpers.get_uf_show(st) + ' '
2008-12-03 18:16:04 +01:00
model[iter_][1] = "When %s for %s %s %s" % (event, recipient_type,
2006-07-17 21:30:53 +02:00
recipient, status)
def on_conditions_treeview_cursor_changed(self, widget):
2008-12-03 18:16:04 +01:00
(model, iter_) = widget.get_selection().get_selected()
if not iter_:
2006-07-17 21:30:53 +02:00
self.active_num = -1
return
2008-12-03 18:16:04 +01:00
self.active_num = model[iter_][0]
2006-07-17 21:30:53 +02:00
if self.active_num == 0:
self.up_button.set_sensitive(False)
else:
self.up_button.set_sensitive(True)
max = self.conditions_treeview.get_model().iter_n_children(None)
if self.active_num == max - 1:
self.down_button.set_sensitive(False)
else:
self.down_button.set_sensitive(True)
self.initiate_rule_state()
self.config_vbox.set_sensitive(True)
self.delete_button.set_sensitive(True)
def on_new_button_clicked(self, widget):
model = self.conditions_treeview.get_model()
num = self.conditions_treeview.get_model().iter_n_children(None)
gajim.config.add_per('notifications', str(num))
2008-12-03 18:16:04 +01:00
iter_ = model.append((num, ''))
path = model.get_path(iter_)
2006-07-17 21:30:53 +02:00
self.conditions_treeview.set_cursor(path)
self.active_num = num
self.set_treeview_string()
self.config_vbox.set_sensitive(True)
def on_delete_button_clicked(self, widget):
2008-12-03 18:16:04 +01:00
(model, iter_) = self.conditions_treeview.get_selection().get_selected()
if not iter_:
2006-07-17 21:30:53 +02:00
return
# up all others
2008-12-03 18:16:04 +01:00
iter2 = model.iter_next(iter_)
2006-07-17 21:30:53 +02:00
num = self.active_num
while iter2:
num = model[iter2][0]
model[iter2][0] = num - 1
for opt in self.config_options:
val = gajim.config.get_per('notifications', str(num), opt)
gajim.config.set_per('notifications', str(num - 1), opt, val)
iter2 = model.iter_next(iter2)
2008-12-03 18:16:04 +01:00
model.remove(iter_)
2006-07-17 21:30:53 +02:00
gajim.config.del_per('notifications', str(num)) # delete latest
self.active_num = -1
self.config_vbox.set_sensitive(False)
self.delete_button.set_sensitive(False)
self.up_button.set_sensitive(False)
self.down_button.set_sensitive(False)
def on_up_button_clicked(self, widget):
2008-12-03 18:16:04 +01:00
(model, iter_) = self.conditions_treeview.get_selection().\
2006-07-17 21:30:53 +02:00
get_selected()
2008-12-03 18:16:04 +01:00
if not iter_:
2006-07-17 21:30:53 +02:00
return
for opt in self.config_options:
val = gajim.config.get_per('notifications', str(self.active_num), opt)
val2 = gajim.config.get_per('notifications', str(self.active_num - 1),
opt)
gajim.config.set_per('notifications', str(self.active_num), opt, val2)
gajim.config.set_per('notifications', str(self.active_num - 1), opt,
val)
2008-12-03 18:16:04 +01:00
model[iter_][0] = self.active_num - 1
2006-07-17 21:30:53 +02:00
# get previous iter
2008-12-03 18:16:04 +01:00
path = model.get_path(iter_)
iter_ = model.get_iter((path[0] - 1,))
model[iter_][0] = self.active_num
2006-07-17 21:30:53 +02:00
self.on_conditions_treeview_cursor_changed(self.conditions_treeview)
def on_down_button_clicked(self, widget):
2008-12-03 18:16:04 +01:00
(model, iter_) = self.conditions_treeview.get_selection().get_selected()
if not iter_:
2006-07-17 21:30:53 +02:00
return
for opt in self.config_options:
val = gajim.config.get_per('notifications', str(self.active_num), opt)
val2 = gajim.config.get_per('notifications', str(self.active_num + 1),
opt)
gajim.config.set_per('notifications', str(self.active_num), opt, val2)
gajim.config.set_per('notifications', str(self.active_num + 1), opt,
val)
2008-12-03 18:16:04 +01:00
model[iter_][0] = self.active_num + 1
iter_ = model.iter_next(iter_)
model[iter_][0] = self.active_num
2006-07-17 21:30:53 +02:00
self.on_conditions_treeview_cursor_changed(self.conditions_treeview)
def on_event_combobox_changed(self, widget):
if self.active_num < 0:
return
2006-09-13 18:47:58 +02:00
active = self.event_combobox.get_active()
if active == -1:
event = ''
else:
event = self.events_list[active]
2006-07-17 21:30:53 +02:00
gajim.config.set_per('notifications', str(self.active_num), 'event',
event)
self.set_treeview_string()
def on_recipient_type_combobox_changed(self, widget):
if self.active_num < 0:
return
recipient_type = self.recipient_types_list[self.recipient_type_combobox.\
get_active()]
gajim.config.set_per('notifications', str(self.active_num),
'recipient_type', recipient_type)
if recipient_type == 'all':
self.recipient_list_entry.hide()
else:
self.recipient_list_entry.show()
self.set_treeview_string()
def on_recipient_list_entry_changed(self, widget):
if self.active_num < 0:
return
recipients = widget.get_text().decode('utf-8')
#TODO: do some check
gajim.config.set_per('notifications', str(self.active_num),
'recipients', recipients)
self.set_treeview_string()
def set_status_config(self):
if self.active_num < 0:
return
status = ''
for st in ('online', 'away', 'xa', 'dnd', 'invisible'):
2006-07-17 21:30:53 +02:00
if self.__dict__[st + '_cb'].get_active():
status += st + ' '
if status:
status = status[:-1]
gajim.config.set_per('notifications', str(self.active_num), 'status',
status)
self.set_treeview_string()
def on_status_radiobutton_toggled(self, widget):
2006-07-17 21:30:53 +02:00
if self.active_num < 0:
return
if self.all_status_rb.get_active():
2006-07-17 21:30:53 +02:00
gajim.config.set_per('notifications', str(self.active_num), 'status',
'all')
# 'All status' clicked
for st in ('online', 'away', 'xa', 'dnd', 'invisible'):
2006-07-17 21:30:53 +02:00
self.__dict__[st + '_cb'].hide()
self.special_status_rb.show()
else:
2006-07-17 21:30:53 +02:00
self.set_status_config()
# 'special status' clicked
for st in ('online', 'away', 'xa', 'dnd', 'invisible'):
2006-07-17 21:30:53 +02:00
self.__dict__[st + '_cb'].show()
self.special_status_rb.hide()
2006-07-17 21:30:53 +02:00
self.set_treeview_string()
def on_status_cb_toggled(self, widget):
if self.active_num < 0:
return
self.set_status_config()
# tab_opened OR (not xor) not_tab_opened must be active
def on_tab_opened_cb_toggled(self, widget):
2006-07-17 21:30:53 +02:00
if self.active_num < 0:
return
if self.tab_opened_cb.get_active():
if self.not_tab_opened_cb.get_active():
gajim.config.set_per('notifications', str(self.active_num),
'tab_opened', 'both')
else:
gajim.config.set_per('notifications', str(self.active_num),
'tab_opened', 'yes')
elif not self.not_tab_opened_cb.get_active():
self.not_tab_opened_cb.set_active(True)
2006-07-17 21:30:53 +02:00
gajim.config.set_per('notifications', str(self.active_num),
'tab_opened', 'no')
def on_not_tab_opened_cb_toggled(self, widget):
2006-07-17 21:30:53 +02:00
if self.active_num < 0:
return
if self.not_tab_opened_cb.get_active():
if self.tab_opened_cb.get_active():
gajim.config.set_per('notifications', str(self.active_num),
'tab_opened', 'both')
else:
gajim.config.set_per('notifications', str(self.active_num),
'tab_opened', 'no')
elif not self.tab_opened_cb.get_active():
self.tab_opened_cb.set_active(True)
2006-07-17 21:30:53 +02:00
gajim.config.set_per('notifications', str(self.active_num),
'tab_opened', 'yes')
def on_use_it_toggled(self, widget, oposite_widget, option):
if widget.get_active():
if oposite_widget.get_active():
oposite_widget.set_active(False)
gajim.config.set_per('notifications', str(self.active_num), option,
'yes')
elif oposite_widget.get_active():
gajim.config.set_per('notifications', str(self.active_num), option,
'no')
else:
gajim.config.set_per('notifications', str(self.active_num), option, '')
def on_disable_it_toggled(self, widget, oposite_widget, option):
if widget.get_active():
if oposite_widget.get_active():
oposite_widget.set_active(False)
gajim.config.set_per('notifications', str(self.active_num), option,
'no')
elif oposite_widget.get_active():
gajim.config.set_per('notifications', str(self.active_num), option,
'yes')
else:
gajim.config.set_per('notifications', str(self.active_num), option, '')
def on_use_sound_cb_toggled(self, widget):
2006-07-17 21:30:53 +02:00
self.on_use_it_toggled(widget, self.disable_sound_cb, 'sound')
if widget.get_active():
self.sound_file_hbox.set_sensitive(True)
else:
self.sound_file_hbox.set_sensitive(False)
2008-08-08 00:08:08 +02:00
def on_browse_for_sounds_button_clicked(self, widget, data=None):
2006-07-17 21:30:53 +02:00
if self.active_num < 0:
return
def on_ok(widget, path_to_snd_file):
dialog.destroy()
if not path_to_snd_file:
path_to_snd_file = ''
gajim.config.set_per('notifications', str(self.active_num),
'sound_file', path_to_snd_file)
self.sound_entry.set_text(path_to_snd_file)
path_to_snd_file = self.sound_entry.get_text().decode('utf-8')
path_to_snd_file = os.path.join(os.getcwd(), path_to_snd_file)
dialog = SoundChooserDialog(path_to_snd_file, on_ok)
def on_play_button_clicked(self, widget):
helpers.play_sound_file(self.sound_entry.get_text().decode('utf-8'))
def on_disable_sound_cb_toggled(self, widget):
2006-07-17 21:30:53 +02:00
self.on_disable_it_toggled(widget, self.use_sound_cb, 'sound')
def on_sound_entry_changed(self, widget):
gajim.config.set_per('notifications', str(self.active_num),
'sound_file', widget.get_text().decode('utf-8'))
def on_use_popup_cb_toggled(self, widget):
2006-07-17 21:30:53 +02:00
self.on_use_it_toggled(widget, self.disable_popup_cb, 'popup')
def on_disable_popup_cb_toggled(self, widget):
2006-07-17 21:30:53 +02:00
self.on_disable_it_toggled(widget, self.use_popup_cb, 'popup')
def on_use_auto_open_cb_toggled(self, widget):
2006-07-17 21:30:53 +02:00
self.on_use_it_toggled(widget, self.disable_auto_open_cb, 'auto_open')
def on_disable_auto_open_cb_toggled(self, widget):
2006-07-17 21:30:53 +02:00
self.on_disable_it_toggled(widget, self.use_auto_open_cb, 'auto_open')
def on_run_command_cb_toggled(self, widget):
gajim.config.set_per('notifications', str(self.active_num), 'run_command',
widget.get_active())
if widget.get_active():
self.command_entry.set_sensitive(True)
else:
self.command_entry.set_sensitive(False)
def on_command_entry_changed(self, widget):
gajim.config.set_per('notifications', str(self.active_num), 'command',
widget.get_text().decode('utf-8'))
def on_use_systray_cb_toggled(self, widget):
2006-07-17 21:30:53 +02:00
self.on_use_it_toggled(widget, self.disable_systray_cb, 'systray')
def on_disable_systray_cb_toggled(self, widget):
2006-07-17 21:30:53 +02:00
self.on_disable_it_toggled(widget, self.use_systray_cb, 'systray')
def on_use_roster_cb_toggled(self, widget):
2006-07-17 21:30:53 +02:00
self.on_use_it_toggled(widget, self.disable_roster_cb, 'roster')
def on_disable_roster_cb_toggled(self, widget):
2006-07-17 21:30:53 +02:00
self.on_disable_it_toggled(widget, self.use_roster_cb, 'roster')
def on_urgency_hint_cb_toggled(self, widget):
gajim.config.set_per('notifications', str(self.active_num),
'uregency_hint', widget.get_active())
def on_close_window(self, widget):
self.window.destroy()
2007-12-12 09:44:46 +01:00
class TransformChatToMUC:
# Keep a reference on windows so garbage collector don't restroy them
instances = []
2008-08-08 00:08:08 +02:00
def __init__(self, account, jids, preselected=None):
2007-12-12 09:44:46 +01:00
'''This window is used to trasform a one-to-one chat to a MUC.
We do 2 things: first select the server and then make a guests list.'''
self.instances.append(self)
self.account = account
self.auto_jids = jids
self.preselected_jids = preselected
self.xml = gtkgui_helpers.get_glade('chat_to_muc_window.glade')
self.window = self.xml.get_widget('chat_to_muc_window')
for widget_to_add in ('invite_button', 'cancel_button',
'server_list_comboboxentry', 'guests_treeview',
'server_and_guests_hseparator', 'server_select_label'):
self.__dict__[widget_to_add] = self.xml.get_widget(widget_to_add)
server_list = []
self.servers = gtk.ListStore(str)
self.server_list_comboboxentry.set_model(self.servers)
self.server_list_comboboxentry.set_text_column(0)
# get the muc server of our server
if 'jabber' in gajim.connections[account].muc_jid:
server_list.append(gajim.connections[account].muc_jid['jabber'])
# add servers or recently joined groupchats
recently_groupchat = gajim.config.get('recently_groupchat').split()
for g in recently_groupchat:
server = gajim.get_server_from_jid(g)
if server not in server_list and not server.startswith('irc'):
server_list.append(server)
# add a default server
if not server_list:
server_list.append('conference.jabber.org')
for s in server_list:
self.servers.append([s])
self.server_list_comboboxentry.set_active(0)
# set treeview
# name, jid
self.store = gtk.ListStore(gtk.gdk.Pixbuf, str, str)
self.store.set_sort_column_id(1, gtk.SORT_ASCENDING)
self.guests_treeview.set_model(self.store)
renderer1 = gtk.CellRendererText()
renderer2 = gtk.CellRendererPixbuf()
column = gtk.TreeViewColumn('Status', renderer2, pixbuf=0)
self.guests_treeview.append_column(column)
column = gtk.TreeViewColumn('Name', renderer1, text=1)
self.guests_treeview.append_column(column)
self.guests_treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
# All contacts beside the following can be invited:
# transports, zeroconf contacts, minimized groupchats
def invitable(contact, contact_transport=None):
return (contact.jid not in self.auto_jids and
contact.jid != gajim.get_jid_from_account(self.account) and
contact.jid not in gajim.interface.minimized_controls[account] and
not contact.is_transport() and
not contact_transport)
2007-12-12 09:44:46 +01:00
# set jabber id and pseudos
for account in gajim.contacts.get_accounts():
if gajim.connections[account].is_zeroconf:
continue
for jid in gajim.contacts.get_jid_list(account):
contact = \
gajim.contacts.get_contact_with_highest_priority(account, jid)
contact_transport = gajim.get_transport_name_from_jid(jid)
# Add contact if it can be invited
if invitable(contact, contact_transport) and \
contact.show not in ('offline', 'error'):
img = gajim.interface.jabber_state_images['16'][contact.show]
name = contact.name
if name == '':
name = jid.split('@')[0]
2008-12-03 18:16:04 +01:00
iter_ = self.store.append([img.get_pixbuf(), name, jid])
# preselect treeview rows
if self.preselected_jids and jid in self.preselected_jids:
2008-12-03 18:16:04 +01:00
path = self.store.get_path(iter_)
self.guests_treeview.get_selection().\
select_path(path)
2007-12-12 09:44:46 +01:00
# show all
self.window.show_all()
self.xml.signal_autoconnect(self)
def on_chat_to_muc_window_destroy(self, widget):
self.instances.remove(self)
def on_chat_to_muc_window_key_press_event(self, widget, event):
if event.keyval == gtk.keysyms.Escape: # ESCAPE
self.window.destroy()
def on_invite_button_clicked(self, widget):
server = self.server_list_comboboxentry.get_active_text()
if server == '':
return
gajim.connections[self.account].check_unique_room_id_support(server, self)
def unique_room_id_supported(self, server, room_id):
guest_list = []
guests = self.guests_treeview.get_selection().get_selected_rows()
for guest in guests[1]:
2008-12-03 18:16:04 +01:00
iter_ = self.store.get_iter(guest)
guest_list.append(self.store[iter_][2].decode('utf-8'))
2007-12-12 09:44:46 +01:00
for guest in self.auto_jids:
guest_list.append(guest)
room_jid = room_id + '@' + server
gajim.automatic_rooms[self.account][room_jid] = {}
gajim.automatic_rooms[self.account][room_jid]['invities'] = guest_list
2007-12-12 09:44:46 +01:00
gajim.automatic_rooms[self.account][room_jid]['continue_tag'] = True
gajim.interface.join_gc_room(self.account, room_jid,
2007-12-12 09:44:46 +01:00
gajim.nicks[self.account], None, is_continued=True)
self.window.destroy()
def on_cancel_button_clicked(self, widget):
self.window.destroy()
def unique_room_id_error(self, server):
self.unique_room_id_supported(server,
2008-08-08 00:08:08 +02:00
gajim.nicks[self.account].lower().replace(' ','') + str(randrange(
9999999)))
class DataFormWindow(Dialog):
def __init__(self, form, on_response_ok):
self.df_response_ok = on_response_ok
Dialog.__init__(self, None, 'test', [(gtk.STOCK_CANCEL,
gtk.RESPONSE_REJECT), (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)],
on_response_ok=self.on_ok)
self.set_resizable(True)
2008-03-02 22:44:43 +01:00
gtkgui_helpers.resize_window(self, 600, 400)
self.dataform_widget = dataforms_widget.DataFormWidget()
2008-09-03 13:25:27 +02:00
self.dataform = dataforms.ExtendForm(node=form)
self.dataform_widget.set_sensitive(True)
self.dataform_widget.data_form = self.dataform
self.dataform_widget.show_all()
self.vbox.pack_start(self.dataform_widget)
def on_ok(self):
form = self.dataform_widget.data_form
if isinstance(self.df_response_ok, tuple):
self.df_response_ok[0](form, *self.df_response_ok[1:])
else:
self.df_response_ok(form)
self.destroy()
class ESessionInfoWindow:
'''Class for displaying information about a XEP-0116 encrypted session'''
def __init__(self, session):
self.session = session
self.xml = gtkgui_helpers.get_glade('esession_info_window.glade')
self.xml.signal_autoconnect(self)
2008-08-13 23:25:26 +02:00
self.security_image = self.xml.get_widget('security_image')
self.verify_now_button = self.xml.get_widget('verify_now_button')
self.button_label = self.xml.get_widget('button_label')
2008-08-13 23:30:18 +02:00
self.window = self.xml.get_widget('esession_info_window')
self.update_info()
2008-08-13 23:25:26 +02:00
self.window.show_all()
def update_info(self):
2008-09-01 16:11:28 +02:00
labeltext = _('''Your chat session with <b>%(jid)s</b> is encrypted.\n\nThis session's Short Authentication String is <b>%(sas)s</b>.''') % {'jid': self.session.jid, 'sas': self.session.sas}
2008-12-03 18:16:04 +01:00
dir_ = os.path.join(gajim.DATA_DIR, 'pixmaps')
if self.session.verified_identity:
labeltext += '\n\n' + _('''You have already verified this contact's identity.''')
2008-08-13 23:25:26 +02:00
security_image = 'security-high-big.png'
2008-07-09 04:11:42 +02:00
if self.session.control:
self.session.control._show_lock_image(True, 'E2E', True,
self.session.is_loggable(), True)
verification_status = _('''Contact's identity verified''')
self.window.set_title(verification_status)
self.xml.get_widget('verification_status_label').set_markup(
'<b><span size="x-large">' +
verification_status +
'</span></b>')
self.xml.get_widget('dialog-action_area1').set_no_show_all(True)
2008-09-01 16:11:28 +02:00
self.button_label.set_text(_('Verify again...'))
2008-08-13 23:25:26 +02:00
else:
if self.session.control:
self.session.control._show_lock_image(True, 'E2E', True,
self.session.is_loggable(), False)
2008-09-01 16:11:28 +02:00
labeltext += '\n\n' + _('''To be certain that <b>only</b> the expected person can read your messages or send you messages, you need to verify their identity by clicking the button below.''')
2008-08-13 23:25:26 +02:00
security_image = 'security-low-big.png'
verification_status = _('''Contact's identity NOT verified''')
self.window.set_title(verification_status)
self.xml.get_widget('verification_status_label').set_markup(
'<b><span size="x-large">' +
verification_status +
'</span></b>')
2008-09-01 16:11:28 +02:00
self.button_label.set_text(_('Verify...'))
2008-08-13 23:25:26 +02:00
2008-12-03 18:16:04 +01:00
path = os.path.join(dir_, security_image)
2008-08-13 23:25:26 +02:00
filename = os.path.abspath(path)
self.security_image.set_from_file(filename)
2008-07-09 04:11:42 +02:00
self.xml.get_widget('info_display').set_markup(labeltext)
def on_close_button_clicked(self, widget):
self.window.destroy()
def on_verify_now_button_clicked(self, widget):
pritext = _('''Have you verified the contact's identity?''')
2008-09-01 16:11:28 +02:00
sectext = _('''To prevent talking to an unknown person, you should speak to <b>%(jid)s</b> directly (in person or on the phone) and verify that they see the same Short Authentication String (SAS) as you.\n\nThis session's Short Authentication String is <b>%(sas)s</b>.''') % {'jid': self.session.jid, 'sas': self.session.sas}
sectext += '\n\n' + _('Did you talk to the remote contact and verify the SAS?')
2008-08-07 15:25:25 +02:00
def on_yes(checked):
self.session._verified_srs_cb()
self.session.verified_identity = True
self.update_info()
def on_no():
self.session._unverified_srs_cb()
self.session.verified_identity = False
self.update_info()
YesNoDialog(pritext, sectext, on_response_yes=on_yes, on_response_no=on_no)
2008-08-07 15:25:25 +02:00
class GPGInfoWindow:
'''Class for displaying information about a XEP-0116 encrypted session'''
def __init__(self, control):
xml = gtkgui_helpers.get_glade('esession_info_window.glade')
security_image = xml.get_widget('security_image')
status_label = xml.get_widget('verification_status_label')
info_label = xml.get_widget('info_display')
verify_now_button = xml.get_widget('verify_now_button')
self.window = xml.get_widget('esession_info_window')
account = control.account
keyID = control.contact.keyID
error = None
verify_now_button.set_no_show_all(True)
verify_now_button.hide()
if keyID.endswith('MISMATCH'):
verification_status = _('''Contact's identity NOT verified''')
info = _('The contact\'s key (%s) <b>does not match</b> the key '
'assigned in Gajim.') % keyID[:8]
image = 'security-low-big.png'
elif not keyID:
# No key assigned nor a key is used by remote contact
verification_status = _('No GPG key assigned')
info = _('No GPG key is assigned to this contact. So you cannot '
'encrypt messages.')
image = 'security-low-big.png'
else:
2008-12-02 16:53:23 +01:00
error = gajim.connections[account].gpg.encrypt('test', [keyID])[1]
if error:
verification_status = _('''Contact's identity NOT verified''')
info = _('GPG key is assigned to this contact, but <b>you do not '
'trust his key</b>, so message <b>cannot</b> be encrypted. Use '
'your GPG client to trust this key.')
image = 'security-low-big.png'
else:
verification_status = _('''Contact's identity verified''')
info = _('GPG Key is assigned to this contact, and you trust his '
'key, so messages will be encrypted.')
image = 'security-high-big.png'
status_label.set_markup('<b><span size="x-large">%s</span></b>' % \
verification_status)
info_label.set_markup(info)
2008-12-03 18:16:04 +01:00
dir_ = os.path.join(gajim.DATA_DIR, 'pixmaps')
path = os.path.join(dir_, image)
filename = os.path.abspath(path)
security_image.set_from_file(filename)
xml.signal_autoconnect(self)
self.window.show_all()
def on_close_button_clicked(self, widget):
self.window.destroy()
# vim: se ts=3: