Merge changes from default to refacotring branch

This commit is contained in:
Stephan Erb 2009-11-05 14:43:05 +01:00
commit c6448d0f2b
77 changed files with 4332 additions and 3824 deletions

View File

@ -1,3 +1,26 @@
Gajim 0.13 (XX November 2009)
* Improve gtkspell (fix memleak)
* BOSH connection
* Roster versioning
* Ability to send contacts
* GUI to send XHTML messages
* Improve sessions handling
* pubsub storage (for bookmarks)
* Ability to select account when joining a groupchat
* Better Gnome keyring support
* Ability to ignore occupants in groupchats
* Ability to show / hide self contact row
* Automatically go away when screensaver is enabled under windows
* Ability to enable / disable accounts
* better URL recognition
* groupchat autoreconnect
* Store passwords in KDE wallet if available
* Better MUC errors handling
* Fix sound player launch (don't create zombies anymore)
* Optional shell like completion
* New color theme
Gajim 0.12.5 (08 August 2009)
* Don't depend on GTK 2.14

View File

@ -2,7 +2,9 @@ Anders Ström
Christophe Got
Dennis Craven
Guillaume Morin
Gvorcek Spajreh
Josef Vybíral
Membris Khan
Rederick Asher
Jakub Szypulka

View File

@ -1,5 +1,5 @@
AC_INIT([Gajim - A Jabber Instant Messager],
[0.12.5.7-dev],[http://trac.gajim.org/],[gajim])
[0.12.5.8-dev],[http://trac.gajim.org/],[gajim])
AC_PREREQ([2.59])
AC_CONFIG_HEADER(config.h)

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 929 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 938 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 466 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 901 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 949 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 895 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 924 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 939 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 937 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 929 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 929 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 739 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -174,7 +174,6 @@ Section "Gajim" SecGajim
File "bin\pywintypes25.dll"
File "bin\OpenSSL.rand.pyd"
File "bin\select.pyd"
File "bin\Crypto.Hash.SHA256.pyd"
File "bin\sqlite3.dll"
File "bin\ssleay32.dll"
File "bin\OpenSSL.SSL.pyd"
@ -286,6 +285,11 @@ Section "sun" SecIconsetsSun
File /r "data\iconsets\sun"
SectionEnd
Section "wroop" SecIconsetsWroop
SetOutPath "$INSTDIR\data\iconsets"
File /r "data\iconsets\wroop"
SectionEnd
Section "transports" SecIconsetsTransports
SetOutPath "$INSTDIR\data\iconsets"
File /r "data\iconsets\transports"
@ -646,7 +650,6 @@ Section "Uninstall"
Delete "$INSTDIR\bin\bz2.pyd"
Delete "$INSTDIR\bin\cairo._cairo.pyd"
Delete "$INSTDIR\bin\Crypto.Cipher.AES.pyd"
Delete "$INSTDIR\bin\Crypto.Hash.SHA256.pyd"
Delete "$INSTDIR\bin\gajim.exe"
Delete "$INSTDIR\bin\gobject._gobject.pyd"
Delete "$INSTDIR\bin\gtk._gtk.pyd"
@ -692,6 +695,7 @@ Section "Uninstall"
RMDir /r "$INSTDIR\data\iconsets\gota"
RMDir /r "$INSTDIR\data\iconsets\jabberbulb"
RMDir /r "$INSTDIR\data\iconsets\sun"
RMDir /r "$INSTDIR\data\iconsets\wroop"
RMDir /r "$INSTDIR\data\iconsets\transports"
RMDir "$INSTDIR\data\iconsets"
RMDir "$INSTDIR\data"

View File

@ -65,7 +65,9 @@ class CommandProcessor(object):
Try to process text as a command. Returns True if it has been processed
as a command and False otherwise.
"""
if not text.startswith(self.COMMAND_PREFIX):
prefix = text.startswith(self.COMMAND_PREFIX)
length = len(text) > len(self.COMMAND_PREFIX)
if not (prefix and length):
return False
body = text[len(self.COMMAND_PREFIX):]
@ -158,7 +160,7 @@ class Command(object):
# in case if they was not set by the one who raised an exception.
except CommandError, error:
if not error.command and not error.name:
raise CommandError(exception.message, self)
raise CommandError(error.message, self)
raise
# This one is a little bit too wide, but as Python does not have

View File

@ -22,6 +22,7 @@ from common import gajim
from common import helpers
from common.exceptions import GajimGeneralException
from ..errors import CommandError
from ..framework import CommandContainer, command, documentation
from ..mapping import generate_usage

View File

@ -198,7 +198,7 @@ class NullClientCaps(AbstractClientCaps):
def _lookup_in_cache(self, caps_cache):
# lookup something which does not exist to get a new CacheItem created
cache_item = caps_cache[('old', '')]
cache_item = caps_cache[('dummy', '')]
assert cache_item.queried == 0
return cache_item
@ -359,10 +359,10 @@ class ConnectionCaps(object):
else:
hash_method, node, caps_hash = caps_tag['hash'], caps_tag['node'], caps_tag['ver']
if node is None or caps_hash is None:
if not node or not caps_hash:
# improper caps in stanza, ignore client capabilities.
client_caps = NullClientCaps()
elif hash_method is None:
elif not hash_method:
client_caps = OldClientCaps(caps_hash, node)
else:
client_caps = ClientCaps(caps_hash, node, hash_method)

View File

@ -326,8 +326,7 @@ class Config:
'http_auth': [opt_str, 'ask'], # yes, no, ask
'dont_ack_subscription': [opt_bool, False, _('Jabberd2 workaround')],
# proxy65 for FT
'file_transfer_proxies': [opt_str,
'proxy65.talkonaut.com, proxy.jabber.org, proxy.netlab.cz, transfer.jabber.freenet.de, proxy.jabber.cd.chalmers.se'],
'file_transfer_proxies': [opt_str, 'proxy.eu.jabber.org, proxy.jabber.ru, proxy.jabbim.cz'],
'use_ft_proxies': [opt_bool, True, _('If checked, Gajim will use your IP and proxies defined in file_transfer_proxies option for file transfer.'), True],
'msgwin-x-position': [opt_int, -1], # Default is to let the wm decide
'msgwin-y-position': [opt_int, -1], # Default is to let the wm decide

View File

@ -2259,7 +2259,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
is_gc = True
status = prs.getStatus() or ''
show = prs.getShow()
if not show in gajim.SHOW_LIST:
if show not in ('chat', 'away', 'xa', 'dnd'):
show = '' # We ignore unknown show
if not ptype and not show:
show = 'online'

View File

@ -27,7 +27,7 @@ docdir = '../'
datadir = '../'
localedir = '../po'
version = '0.12.5.7-dev'
version = '0.12.5.8-dev'
import sys, os.path
for base in ('.', 'common'):

View File

@ -216,12 +216,51 @@ class OptionsParser:
self.update_config_to_01256()
if old < [0, 12, 5, 7] and new >= [0, 12, 5, 7]:
self.update_config_to_01257()
if old < [0, 12, 5, 8] and new >= [0, 12, 5, 8]:
self.update_config_to_01258()
gajim.logger.init_vars()
gajim.config.set('version', new_version)
caps.capscache.initialize_from_db()
def assert_unread_msgs_table_exists(self):
'''create table unread_messages if there is no such table'''
back = os.getcwd()
os.chdir(logger.LOG_DB_FOLDER)
con = sqlite.connect(logger.LOG_DB_FILE)
os.chdir(back)
cur = con.cursor()
try:
cur.executescript(
'''
CREATE TABLE unread_messages (
message_id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
jid_id INTEGER
);
'''
)
con.commit()
gajim.logger.init_vars()
except sqlite.OperationalError:
pass
con.close()
def update_ft_proxies(self, to_remove=[], to_add=[]):
for account in gajim.config.get_per('accounts'):
proxies_str = gajim.config.get_per('accounts', account,
'file_transfer_proxies')
proxies = [p.strip() for p in proxies_str.split(',')]
for wrong_proxy in to_remove:
if wrong_proxy in proxies:
proxies.remove(wrong_proxy)
for new_proxy in to_add:
if new_proxy not in proxies:
proxies.append(new_proxy)
proxies_str = ', '.join(proxies)
gajim.config.set_per('accounts', account, 'file_transfer_proxies',
proxies_str)
def update_config_x_to_09(self):
# Var name that changed:
# avatar_width /height -> chat_avatar_width / height
@ -262,38 +301,10 @@ class OptionsParser:
theme = gajim.config.get_per('themes')[0]
gajim.config.set('roster_theme', theme)
# new proxies in accounts.name.file_transfer_proxies
for account in gajim.config.get_per('accounts'):
proxies = gajim.config.get_per('accounts', account,
'file_transfer_proxies')
if proxies.find('proxy.netlab.cz') < 0:
proxies += ', ' + 'proxy.netlab.cz'
gajim.config.set_per('accounts', account, 'file_transfer_proxies',
proxies)
self.update_ft_proxies(to_add=['proxy.netlab.cz'])
gajim.config.set('version', '0.9')
def assert_unread_msgs_table_exists(self):
'''create table unread_messages if there is no such table'''
back = os.getcwd()
os.chdir(logger.LOG_DB_FOLDER)
con = sqlite.connect(logger.LOG_DB_FILE)
os.chdir(back)
cur = con.cursor()
try:
cur.executescript(
'''
CREATE TABLE unread_messages (
message_id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
jid_id INTEGER
);
'''
)
con.commit()
gajim.logger.init_vars()
except sqlite.OperationalError:
pass
con.close()
def update_config_09_to_010(self):
if 'usetabbedchat' in self.old_values and not \
self.old_values['usetabbedchat']:
@ -311,21 +322,8 @@ class OptionsParser:
self.old_values['always_compact_view_gc'] != 'False':
gajim.config.set('always_hide_groupchat_buttons', True)
for account in gajim.config.get_per('accounts'):
proxies_str = gajim.config.get_per('accounts', account,
'file_transfer_proxies')
proxies = proxies_str.split(',')
for i in range(0, len(proxies)):
proxies[i] = proxies[i].strip()
for wrong_proxy in ('proxy65.jabber.autocom.pl',
'proxy65.jabber.ccc.de'):
if wrong_proxy in proxies:
proxies.remove(wrong_proxy)
if not 'transfer.jabber.freenet.de' in proxies:
proxies.append('transfer.jabber.freenet.de')
proxies_str = ', '.join(proxies)
gajim.config.set_per('accounts', account, 'file_transfer_proxies',
proxies_str)
self.update_ft_proxies(to_remove=['proxy65.jabber.autocom.pl',
'proxy65.jabber.ccc.de'], to_add=['transfer.jabber.freenet.de'])
# create unread_messages table if needed
self.assert_unread_msgs_table_exists()
@ -811,4 +809,12 @@ class OptionsParser:
'simplebulb', 'stellar'):
gajim.config.set('iconset', gajim.config.DEFAULT_ICONSET)
gajim.config.set('version', '0.12.5.7')
def update_config_to_01258(self):
self.update_ft_proxies(to_remove=['proxy65.talkonaut.com',
'proxy.jabber.org', 'proxy.netlab.cz', 'transfer.jabber.freenet.de',
'proxy.jabber.cd.chalmers.se'], to_add=['proxy.eu.jabber.org',
'proxy.jabber.ru', 'proxy.jabbim.cz'])
gajim.config.set('version', '0.12.5.8')
# vim: se ts=3:

View File

@ -84,8 +84,8 @@ class NonBlockingBOSH(NonBlockingTransport):
self.proxy_dict['type'] = 'http'
# with SSL over proxy, we do HTTP CONNECT to proxy to open a channel to
# BOSH Connection Manager
host, port = urisplit(self.bosh_uri)[1].split(':', 1)
self.proxy_dict['xmpp_server'] = (host, int(port))
host, port = urisplit(self.bosh_uri)[1:3]
self.proxy_dict['xmpp_server'] = (host, port)
self.proxy_dict['credentials'] = self.proxy_creds

View File

@ -35,30 +35,39 @@ import errno
import time
import traceback
import base64
import urlparse
import logging
log = logging.getLogger('gajim.c.x.transports_nb')
def urisplit(uri):
'''
Function for splitting URI string to tuple (protocol, host, path).
e.g. urisplit('http://httpcm.jabber.org/webclient') returns
('http', 'httpcm.jabber.org', '/webclient')
Function for splitting URI string to tuple (protocol, host, port, path).
e.g. urisplit('http://httpcm.jabber.org:123/webclient') returns
('http', 'httpcm.jabber.org', 123, '/webclient')
return 443 as default port if proto is https else 80
'''
import re
regex = '(([^:/]+)(://))?([^/]*)(/?.*)'
grouped = re.match(regex, uri).groups()
proto, host, path = grouped[1], grouped[3], grouped[4]
return proto, host, path
splitted = urlparse.urlsplit(uri)
proto, host, path = splitted.scheme, splitted.hostname, splitted.path
try:
port = splitted.port
except ValueError:
log.warn('port cannot be extracted from BOSH URL %s, using default port' \
% uri)
port = ''
if not port:
if proto == 'https':
port = 443
else:
port = 80
return proto, host, port, path
def get_proxy_data_from_dict(proxy):
tcp_host, tcp_port, proxy_user, proxy_pass = None, None, None, None
proxy_type = proxy['type']
if proxy_type == 'bosh' and not proxy['bosh_useproxy']:
# with BOSH not over proxy we have to parse the hostname from BOSH URI
tcp_host = urisplit(proxy['bosh_uri'])[1]
tcp_host, tcp_port = tcp_host.split(':', 1)
tcp_port = int(tcp_port)
proto, tcp_host, tcp_port, path = urisplit(proxy['bosh_uri'])
else:
# with proxy!=bosh or with bosh over HTTP proxy we're connecting to proxy
# machine
@ -602,10 +611,8 @@ class NonBlockingHTTP(NonBlockingTCP):
NonBlockingTCP.__init__(self, raise_event, on_disconnect, idlequeue,
estabilish_tls, certs, proxy_dict)
self.http_protocol, self.http_host, self.http_path = urisplit(
http_dict['http_uri'])
self.http_host, self.http_port = self.http_host.split(':', 1)
self.http_port = int(self.http_port)
self.http_protocol, self.http_host, self.http_port, self.http_path = \
urisplit(http_dict['http_uri'])
self.http_protocol = self.http_protocol or 'http'
self.http_path = self.http_path or '/'
self.http_version = http_dict['http_version']

View File

@ -228,25 +228,8 @@ class PreferencesWindow:
st = gajim.config.get('use_transports_iconsets')
self.xml.get_widget('transports_iconsets_checkbutton').set_active(st)
# Color for incoming messages
colSt = gajim.config.get('inmsgcolor')
self.xml.get_widget('incoming_msg_colorbutton').set_color(
gtk.gdk.color_parse(colSt))
# Color for outgoing messages
colSt = gajim.config.get('outmsgcolor')
self.xml.get_widget('outgoing_msg_colorbutton').set_color(
gtk.gdk.color_parse(colSt))
# Color for status messages
colSt = gajim.config.get('statusmsgcolor')
self.xml.get_widget('status_msg_colorbutton').set_color(
gtk.gdk.color_parse(colSt))
# Color for hyperlinks
colSt = gajim.config.get('urlmsgcolor')
self.xml.get_widget('url_msg_colorbutton').set_color(
gtk.gdk.color_parse(colSt))
# Color widgets
self.draw_color_widgets()
# Font for messages
font = gajim.config.get('conversation_font')
@ -823,12 +806,18 @@ class PreferencesWindow:
for win in gajim.interface.msg_win_mgr.windows():
win.update_font()
def on_incoming_msg_colorbutton_color_set(self, widget):
def on_incoming_nick_colorbutton_color_set(self, widget):
self.on_preference_widget_color_set(widget, 'inmsgcolor')
def on_outgoing_msg_colorbutton_color_set(self, widget):
def on_outgoing_nick_colorbutton_color_set(self, widget):
self.on_preference_widget_color_set(widget, 'outmsgcolor')
def on_incoming_msg_colorbutton_color_set(self, widget):
self.on_preference_widget_color_set(widget, 'inmsgtxtcolor')
def on_outgoing_msg_colorbutton_color_set(self, widget):
self.on_preference_widget_color_set(widget, 'outmsgtxtcolor')
def on_url_msg_colorbutton_color_set(self, widget):
self.on_preference_widget_color_set(widget, 'urlmsgcolor')
@ -846,22 +835,71 @@ class PreferencesWindow:
else:
font_widget.set_sensitive(True)
self.on_preference_widget_font_set(font_widget, 'conversation_font')
def draw_color_widgets(self):
col_to_widget = {'inmsgcolor': 'incoming_nick_colorbutton',
'outmsgcolor': 'outgoing_nick_colorbutton',
'inmsgtxtcolor': ['incoming_msg_colorbutton',
'incoming_msg_checkbutton'],
'outmsgtxtcolor': ['outgoing_msg_colorbutton',
'outgoing_msg_checkbutton'],
'statusmsgcolor': 'status_msg_colorbutton',
'urlmsgcolor': 'url_msg_colorbutton'}
for c in col_to_widget:
col = gajim.config.get(c)
if col:
if isinstance(col_to_widget[c], list):
self.xml.get_widget(col_to_widget[c][0]).set_color(
gtk.gdk.color_parse(col))
self.xml.get_widget(col_to_widget[c][0]).set_sensitive(True)
self.xml.get_widget(col_to_widget[c][1]).set_active(True)
else:
self.xml.get_widget(col_to_widget[c]).set_color(
gtk.gdk.color_parse(col))
else:
if isinstance(col_to_widget[c], list):
self.xml.get_widget(col_to_widget[c][0]).set_color(
gtk.gdk.color_parse('#000000'))
self.xml.get_widget(col_to_widget[c][0]).set_sensitive(False)
self.xml.get_widget(col_to_widget[c][1]).set_active(False)
else:
self.xml.get_widget(col_to_widget[c]).set_color(
gtk.gdk.color_parse('#000000'))
def on_reset_colors_button_clicked(self, widget):
for i in ('inmsgcolor', 'outmsgcolor', 'statusmsgcolor', 'urlmsgcolor'):
gajim.config.set(i, gajim.interface.default_colors[i])
col_to_widget = {'inmsgcolor': 'incoming_nick_colorbutton',
'outmsgcolor': 'outgoing_nick_colorbutton',
'inmsgtxtcolor': 'incoming_msg_colorbutton',
'outmsgtxtcolor': 'outgoing_msg_colorbutton',
'statusmsgcolor': 'status_msg_colorbutton',
'urlmsgcolor': 'url_msg_colorbutton'}
for c in col_to_widget:
gajim.config.set(c, gajim.interface.default_colors[c])
self.draw_color_widgets()
self.xml.get_widget('incoming_msg_colorbutton').set_color(\
gtk.gdk.color_parse(gajim.config.get('inmsgcolor')))
self.xml.get_widget('outgoing_msg_colorbutton').set_color(\
gtk.gdk.color_parse(gajim.config.get('outmsgcolor')))
self.xml.get_widget('status_msg_colorbutton').set_color(\
gtk.gdk.color_parse(gajim.config.get('statusmsgcolor')))
self.xml.get_widget('url_msg_colorbutton').set_color(\
gtk.gdk.color_parse(gajim.config.get('urlmsgcolor')))
self.update_text_tags()
gajim.interface.save_config()
def _set_color(self, state, widget_name, option):
''' set color value in prefs and update the UI '''
if state:
color = self.xml.get_widget(widget_name).get_color()
color_string = gtkgui_helpers.make_color_string(color)
else:
color_string = ''
gajim.config.set(option, color_string)
gajim.interface.save_config()
def on_incoming_msg_checkbutton_toggled(self, widget):
state = widget.get_active()
self.xml.get_widget('incoming_msg_colorbutton').set_sensitive(state)
self._set_color(state, 'incoming_msg_colorbutton', 'inmsgtxtcolor')
def on_outgoing_msg_checkbutton_toggled(self, widget):
state = widget.get_active()
self.xml.get_widget('outgoing_msg_colorbutton').set_sensitive(state)
self._set_color(state, 'outgoing_msg_colorbutton', 'outmsgtxtcolor')
def on_auto_away_checkbutton_toggled(self, widget):
self.on_checkbutton_toggled(widget, 'autoaway',
[self.auto_away_time_spinbutton, self.auto_away_message_entry])

View File

@ -853,7 +853,7 @@ class ConversationTextview(gobject.GObject):
gajim.interface.instances[self.account]['join_gc'].window.present()
else:
try:
dialogs.JoinGroupchatWindow(account=None, room_jid=room_jid)
dialogs.JoinGroupchatWindow(account=self.account, room_jid=room_jid)
except GajimGeneralException:
pass

View File

@ -1922,7 +1922,7 @@ class JoinGroupchatWindow:
'''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'''
self.xml = gtkgui_helpers.get_glade('join_groupchat_window.glade')
if account:
if room_jid != '' and room_jid in gajim.gc_connected[account] and\
gajim.gc_connected[account][room_jid]:
@ -1934,21 +1934,27 @@ class JoinGroupchatWindow:
ErrorDialog(_('You are not connected to the server'),
_('You can not join a group chat unless you are connected.'))
raise GajimGeneralException, 'You must be connected to join a groupchat'
else:
account_label = self.xml.get_widget('account_label')
account_combobox = self.xml.get_widget('account_combobox')
account_label.set_no_show_all(False)
account_combobox.set_no_show_all(False)
liststore = gtk.ListStore(str)
account_combobox.set_model(liststore)
cell = gtk.CellRendererText()
account_combobox.pack_start(cell, True)
account_combobox.add_attribute(cell, 'text', 0)
for acct in [a for a in gajim.connections if \
gajim.account_is_connected(a)]:
account_combobox.append_text(acct)
account_combobox.set_active(-1)
self.xml = gtkgui_helpers.get_glade('join_groupchat_window.glade')
account_label = self.xml.get_widget('account_label')
account_combobox = self.xml.get_widget('account_combobox')
account_label.set_no_show_all(False)
account_combobox.set_no_show_all(False)
liststore = gtk.ListStore(str)
account_combobox.set_model(liststore)
cell = gtk.CellRendererText()
account_combobox.pack_start(cell, True)
account_combobox.add_attribute(cell, 'text', 0)
account_combobox.set_active(-1)
# Add accounts, set current as active if it matches 'account'
for acct in [a for a in gajim.connections if \
gajim.account_is_connected(a)]:
account_combobox.append_text(acct)
if account and account == acct:
account_combobox.set_active(liststore.iter_n_children(None)-1)
self.account = account
self.automatic = automatic
self._empty_required_widgets = []
@ -2064,7 +2070,7 @@ class JoinGroupchatWindow:
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.'))
_('Please enter the group chat Jabber ID as room@server.'))
return
try:
room_jid = helpers.parse_jid(room_jid)
@ -4346,7 +4352,7 @@ class TransformChatToMUC:
gajim.automatic_rooms[self.account][room_jid]['invities'] = guest_list
gajim.automatic_rooms[self.account][room_jid]['continue_tag'] = True
gajim.interface.join_gc_room(self.account, room_jid,
gajim.nicks[self.account], None, is_continued=True)
gajim.nicks[self.account], None, is_continued=True)
self.window.destroy()
def on_cancel_button_clicked(self, widget):
@ -4354,8 +4360,8 @@ class TransformChatToMUC:
def unique_room_id_error(self, server):
self.unique_room_id_supported(server,
gajim.nicks[self.account].lower().replace(' ','') + str(randrange(
9999999)))
gajim.nicks[self.account].lower().replace(' ','') + str(randrange(
9999999)))
class DataFormWindow(Dialog):
def __init__(self, form, on_response_ok):

File diff suppressed because it is too large Load Diff

View File

@ -647,7 +647,7 @@ class GroupchatControl(ChatControlBase):
bookmark_separator = xml.get_widget('bookmark_separator')
separatormenuitem2 = xml.get_widget('separatormenuitem2')
if hide_buttonbar_entries:
if hide_buttonbar_items:
change_nick_menuitem.hide()
change_subject_menuitem.hide()
bookmark_room_menuitem.hide()

3475
src/gui_interface.py Normal file

File diff suppressed because it is too large Load Diff

View File

@ -83,15 +83,15 @@ common.configpaths.gajimpaths.init(config_path)
del config_path
common.configpaths.gajimpaths.init_profile()
from common import exceptions
import dialogs
from common import gajim
import gtkgui_helpers
from common.logger import LOG_DB_PATH, constants
#FIXME: constants should implement 2 way mappings
status = dict((constants.__dict__[i], i[5:].lower()) for i in \
constants.__dict__.keys() if i.startswith('SHOW_'))
from common import gajim
from common import helpers
import dialogs
# time, message, subject
(

View File

@ -1234,6 +1234,9 @@ class RosterWindow:
child_path = self.model.get_path(child_iter)
path = self.modelfilter.convert_child_path_to_path(child_path)
if not path:
continue
if not self.tree.row_expanded(path) and icon_name != 'event':
iterC = self.model.iter_children(child_iter)
while iterC:

View File

@ -0,0 +1,6 @@
'''
This package contains integration tests. Integration tests are tests
which require or include UI, network or both.
'''

View File

@ -14,34 +14,6 @@ gajim.logger = MockLogger()
Interface()
class TestMiscInterface(unittest.TestCase):
def test_links_regexp_entire(self):
def assert_matches_all(str_):
m = gajim.interface.basic_pattern_re.match(str_)
# the match should equal the string
str_span = (0, len(str_))
self.assertEqual(m.span(), str_span)
# these entire strings should be parsed as links
assert_matches_all('http://google.com/')
assert_matches_all('http://google.com')
assert_matches_all('http://www.google.ca/search?q=xmpp')
assert_matches_all('http://tools.ietf.org/html/draft-saintandre-rfc3920bis-05#section-12.3')
assert_matches_all('http://en.wikipedia.org/wiki/Protocol_(computing)')
assert_matches_all(
'http://en.wikipedia.org/wiki/Protocol_%28computing%29')
assert_matches_all('mailto:test@example.org')
assert_matches_all('xmpp:example-node@example.com')
assert_matches_all('xmpp:example-node@example.com/some-resource')
assert_matches_all('xmpp:example-node@example.com?message')
assert_matches_all('xmpp://guest@example.com/support@example.com?message')
import time
from data import *

View File

@ -1,5 +1,6 @@
'''
Unit test for tranports classes.
Integration test for tranports classes. See unit for the ordinary
unit tests of this module.
'''
import unittest
@ -12,62 +13,6 @@ from xmpp_mocks import IdleQueueThread, IdleMock
from common.xmpp import transports_nb
class TestModuleLevelFunctions(unittest.TestCase):
'''
Test class for functions defined at module level
'''
def test_urisplit(self):
def check_uri(uri, proto, host, path):
_proto, _host, _path = transports_nb.urisplit(uri)
self.assertEqual(proto, _proto)
self.assertEqual(host, _host)
self.assertEqual(path, _path)
check_uri('http://httpcm.jabber.org/webclient',
proto='http', host='httpcm.jabber.org', path='/webclient')
def test_get_proxy_data_from_dict(self):
def check_dict(proxy_dict, host, port, user, passwd):
_host, _port, _user, _passwd = transports_nb.get_proxy_data_from_dict(
proxy_dict)
self.assertEqual(_host, host)
self.assertEqual(_port, port)
self.assertEqual(_user, user)
self.assertEqual(_passwd, passwd)
bosh_dict = {'bosh_content': u'text/xml; charset=utf-8',
'bosh_hold': 2,
'bosh_http_pipelining': False,
'bosh_uri': u'http://gajim.org:5280/http-bind',
'bosh_useproxy': False,
'bosh_wait': 30,
'bosh_wait_for_restart_response': False,
'host': u'172.16.99.11',
'pass': u'pass',
'port': 3128,
'type': u'bosh',
'useauth': True,
'user': u'user'}
check_dict(bosh_dict, host=u'gajim.org', port=5280, user=u'user',
passwd=u'pass')
proxy_dict = {'bosh_content': u'text/xml; charset=utf-8',
'bosh_hold': 2,
'bosh_http_pipelining': False,
'bosh_port': 5280,
'bosh_uri': u'',
'bosh_useproxy': True,
'bosh_wait': 30,
'bosh_wait_for_restart_response': False,
'host': u'172.16.99.11',
'pass': u'pass',
'port': 3128,
'type': 'socks5',
'useauth': True,
'user': u'user'}
check_dict(proxy_dict, host=u'172.16.99.11', port=3128, user=u'user',
passwd=u'pass')
class AbstractTransportTest(unittest.TestCase):
''' Encapsulates Idlequeue instantiation for transports and more...'''

View File

@ -91,6 +91,7 @@ class MockChatControl(Mock):
def __eq__(self, other):
return self is other
class MockInterface(Mock):
def __init__(self, *args):
Mock.__init__(self, *args)
@ -113,14 +114,17 @@ class MockInterface(Mock):
self.jabber_state_images = {'16': Mock(), '32': Mock(),
'opened': Mock(), 'closed': Mock()}
class MockLogger(Mock):
def __init__(self):
Mock.__init__(self, {'write': None, 'get_transports_type': {}})
class MockContact(Mock):
def __nonzero__(self):
return True
import random
class MockSession(Mock):

View File

@ -4,7 +4,7 @@
'''
Runs Gajim's Test Suite
Non GUI related tests will be run on each commit.
Unit tests tests will be run on each commit.
'''
import sys
@ -35,19 +35,21 @@ for o, a in opts:
sys.exit(2)
# new test modules need to be added manually
modules = ( 'test_xmpp_dispatcher_nb',
'test_xmpp_client_nb',
'test_xmpp_transports_nb',
'test_resolver',
'test_caps',
'test_contacts',
modules = ( 'unit.test_xmpp_dispatcher_nb',
'unit.test_xmpp_transports_nb',
'unit.test_caps',
'unit.test_contacts',
'unit.test_gui_interface',
'unit.test_sessions',
)
#modules = ()
if use_x:
modules += ('test_misc_interface',
'test_roster',
'test_sessions',
modules += ('integration.test_gui_event_integration',
'integration.test_roster',
'integration.test_resolver',
'integration.test_xmpp_client_nb',
'integration.test_xmpp_transports_nb'
)
nb_errors = 0

5
test/unit/__init__.py Normal file
View File

@ -0,0 +1,5 @@
'''
This package just contains plain unit tests
'''

View File

@ -0,0 +1,112 @@
import unittest
import lib
lib.setup_env()
from common import logging_helpers
logging_helpers.set_quiet()
from common import gajim
from gajim_mocks import MockLogger
gajim.logger = MockLogger()
from gui_interface import Interface
class Test(unittest.TestCase):
def test_instantiation(self):
''' Test that we can proper initialize and do not fail on globals '''
interface = Interface()
interface.run()
def test_dispatch(self):
''' Test dispatcher forwarding network events to handler_* methods '''
sut = Interface()
success = sut.dispatch('No Such Event', None, None)
self.assertFalse(success, msg="Unexisting event handled")
success = sut.dispatch('STANZA_ARRIVED', None, None)
self.assertTrue(success, msg="Existing event must be handled")
def test_register_unregister_single_handler(self):
''' Register / Unregister a custom event handler '''
sut = Interface()
event = 'TESTS_ARE_COOL_EVENT'
self.called = False
def handler(account, data):
self.assertEqual(account, 'account')
self.assertEqual(data, 'data')
self.called = True
self.assertFalse(self.called)
sut.register_handler('TESTS_ARE_COOL_EVENT', handler)
sut.dispatch(event, 'account', 'data')
self.assertTrue(self.called, msg="Handler should have been called")
self.called = False
sut.unregister_handler('TESTS_ARE_COOL_EVENT', handler)
sut.dispatch(event, 'account', 'data')
self.assertFalse(self.called, msg="Handler should no longer be called")
def test_dispatch_to_multiple_handlers(self):
''' Register and dispatch a single event to multiple handlers '''
sut = Interface()
event = 'SINGLE_EVENT'
self.called_a = False
self.called_b = False
def handler_a(account, data):
self.assertFalse(self.called_a, msg="One must only be notified once")
self.called_a = True
def handler_b(account, data):
self.assertFalse(self.called_b, msg="One must only be notified once")
self.called_b = True
sut.register_handler(event, handler_a)
sut.register_handler(event, handler_b)
# register again
sut.register_handler('SOME_OTHER_EVENT', handler_b)
sut.register_handler(event, handler_a)
sut.dispatch(event, 'account', 'data')
self.assertTrue(self.called_a and self.called_b,
msg="Both handlers should have been called")
def test_links_regexp_entire(self):
sut = Interface()
def assert_matches_all(str_):
m = sut.basic_pattern_re.match(str_)
# the match should equal the string
str_span = (0, len(str_))
self.assertEqual(m.span(), str_span)
# these entire strings should be parsed as links
assert_matches_all('http://google.com/')
assert_matches_all('http://google.com')
assert_matches_all('http://www.google.ca/search?q=xmpp')
assert_matches_all('http://tools.ietf.org/html/draft-saintandre-rfc3920bis-05#section-12.3')
assert_matches_all('http://en.wikipedia.org/wiki/Protocol_(computing)')
assert_matches_all(
'http://en.wikipedia.org/wiki/Protocol_%28computing%29')
assert_matches_all('mailto:test@example.org')
assert_matches_all('xmpp:example-node@example.com')
assert_matches_all('xmpp:example-node@example.com/some-resource')
assert_matches_all('xmpp:example-node@example.com?message')
assert_matches_all('xmpp://guest@example.com/support@example.com?message')
if __name__ == "__main__":
#import sys;sys.argv = ['', 'Test.test']
unittest.main()

View File

@ -5,19 +5,27 @@ import time
import lib
lib.setup_env()
import notify
from common import gajim
from common import xmpp
from common.stanza_session import StanzaSession
from session import ChatControlSession
from mock import Mock, expectParams
from gajim_mocks import *
from common.stanza_session import StanzaSession
gajim.interface = MockInterface()
# name to use for the test account
account_name = 'test'
class TestStanzaSession(unittest.TestCase):
''' Testclass for common/stanzasession.py '''
def setUp(self):
self.jid = 'test@example.org/Gajim'
self.conn = MockConnection(account_name, {'send_stanza': None})
@ -68,14 +76,10 @@ class TestStanzaSession(unittest.TestCase):
calls = self.conn.mockGetNamedCalls('send_stanza')
self.assertEqual(0, len(calls))
from session import ChatControlSession
gajim.interface = MockInterface()
import notify
class TestChatControlSession(unittest.TestCase):
''' Testclass for session.py '''
def setUp(self):
self.jid = 'test@example.org/Gajim'
self.conn = MockConnection(account_name, {'send_stanza': None})

View File

@ -0,0 +1,80 @@
'''
Unit test for tranports classes.
'''
import unittest
import lib
lib.setup_env()
from common.xmpp import transports_nb
class TestModuleLevelFunctions(unittest.TestCase):
'''
Test class for functions defined at module level
'''
def test_urisplit(self):
def check_uri(uri, proto, host, port, path):
_proto, _host, _port, _path = transports_nb.urisplit(uri)
self.assertEqual(proto, _proto)
self.assertEqual(host, _host)
self.assertEqual(path, _path)
self.assertEqual(port, _port)
check_uri('http://httpcm.jabber.org:5280/webclient', proto='http',
host='httpcm.jabber.org', port=5280, path='/webclient')
check_uri('http://httpcm.jabber.org/webclient', proto='http',
host='httpcm.jabber.org', port=80, path='/webclient')
check_uri('https://httpcm.jabber.org/webclient', proto='https',
host='httpcm.jabber.org', port=443, path='/webclient')
def test_get_proxy_data_from_dict(self):
def check_dict(proxy_dict, host, port, user, passwd):
_host, _port, _user, _passwd = transports_nb.get_proxy_data_from_dict(
proxy_dict)
self.assertEqual(_host, host)
self.assertEqual(_port, port)
self.assertEqual(_user, user)
self.assertEqual(_passwd, passwd)
bosh_dict = {'bosh_content': u'text/xml; charset=utf-8',
'bosh_hold': 2,
'bosh_http_pipelining': False,
'bosh_uri': u'http://gajim.org:5280/http-bind',
'bosh_useproxy': False,
'bosh_wait': 30,
'bosh_wait_for_restart_response': False,
'host': u'172.16.99.11',
'pass': u'pass',
'port': 3128,
'type': u'bosh',
'useauth': True,
'user': u'user'}
check_dict(bosh_dict, host=u'gajim.org', port=5280, user=u'user',
passwd=u'pass')
proxy_dict = {'bosh_content': u'text/xml; charset=utf-8',
'bosh_hold': 2,
'bosh_http_pipelining': False,
'bosh_port': 5280,
'bosh_uri': u'',
'bosh_useproxy': True,
'bosh_wait': 30,
'bosh_wait_for_restart_response': False,
'host': u'172.16.99.11',
'pass': u'pass',
'port': 3128,
'type': 'socks5',
'useauth': True,
'user': u'user'}
check_dict(proxy_dict, host=u'172.16.99.11', port=3128, user=u'user',
passwd=u'pass')
if __name__ == '__main__':
unittest.main()
# vim: se ts=3: