gajim.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2026
October
September
August
July
June
May
April
March
February
January
2025
December
November
October
September
August
July
June
May
April
March
February
January
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
List overview
Download
Commits
October 2009
----- 2026 -----
October 2026
September 2026
August 2026
July 2026
June 2026
May 2026
April 2026
March 2026
February 2026
January 2026
----- 2025 -----
December 2025
November 2025
October 2025
September 2025
August 2025
July 2025
June 2025
May 2025
April 2025
March 2025
February 2025
January 2025
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
commits@gajim.org
6 participants
172 discussions
Start a n
N
ew thread
gajim: Merge refactoring branch back to default
by Stephan Erb
31 Oct '09
31 Oct '09
changeset 200870540a1f in /home/hg/repos/gajim
details:http://hg.gajim.org/gajim?cmd=changeset;node=200870540a1f
description: Merge refactoring branch back to default diffstat: .hgignore | 1 + src/chat_control.py | 28 +- src/common/caps.py | 434 ++++++++++++++++++++++++++----------------- src/common/connection.py | 10 +- src/common/connection_handlers.py | 5 +- src/common/contacts.py | 138 ++++++++----- src/common/gajim.py | 8 +- src/common/helpers.py | 72 +------- src/common/optparser.py | 3 +- src/common/stanza_session.py | 2 +- src/gajim.py | 7 + src/gui_menu_builder.py | 13 +- src/roster_window.py | 13 +- test/lib/xmpp_mocks.py | 1 - test/runtests.py | 1 + test/test_caps.py | 157 ++++++++++++--- test/test_contacts.py | 51 +++++ test/test_roster.py | 1 - 18 files changed, 563 insertions(+), 382 deletions(-) diffs (truncated from 1417 to 300 lines): diff -r b82bcd6c8d7f -r 200870540a1f .hgignore --- a/.hgignore Fri Oct 30 20:08:33 2009 +0100 +++ b/.hgignore Sat Oct 31 18:08:06 2009 +0100 @@ -1,4 +1,5 @@ syntax: glob +*.orig *.gmo *.in *.la diff -r b82bcd6c8d7f -r 200870540a1f src/chat_control.py --- a/src/chat_control.py Fri Oct 30 20:08:33 2009 +0100 +++ b/src/chat_control.py Sat Oct 31 18:08:06 2009 +0100 @@ -1356,9 +1356,7 @@ def update_toolbar(self): # Formatting - if gajim.capscache.is_supported(self.contact, NS_XHTML_IM) \ - and not gajim.capscache.is_supported(self.contact, 'notexistant') \ - and not self.gpg_is_active: + if self.contact.supports(NS_XHTML_IM) and not self.gpg_is_active: self._formattings_button.set_sensitive(True) else: self._formattings_button.set_sensitive(False) @@ -1371,15 +1369,15 @@ self._add_to_roster_button.hide() # Jingle detection - if gajim.capscache.is_supported(self.contact, NS_JINGLE_ICE_UDP) and \ + if self.contact.supports(NS_JINGLE_ICE_UDP) and \ gajim.HAVE_FARSIGHT and self.contact.resource: - if gajim.capscache.is_supported(self.contact, NS_JINGLE_RTP_AUDIO): + if self.contact.supports(NS_JINGLE_RTP_AUDIO): if self.audio_state == self.JINGLE_STATE_NOT_AVAILABLE: self.set_audio_state('available') else: self.set_audio_state('not_available') - if gajim.capscache.is_supported(self.contact, NS_JINGLE_RTP_VIDEO): + if self.contact.supports(NS_JINGLE_RTP_VIDEO): if self.video_state == self.JINGLE_STATE_NOT_AVAILABLE: self.set_video_state('available') else: @@ -1403,12 +1401,11 @@ self._video_button.set_sensitive(True) # Send file - if gajim.capscache.is_supported(self.contact, NS_FILE) and \ - self.contact.resource: + if self.contact.supports(NS_FILE) and self.contact.resource: self._send_file_button.set_sensitive(True) else: self._send_file_button.set_sensitive(False) - if not gajim.capscache.is_supported(self.contact, NS_FILE): + if not self.contact.supports(NS_FILE): self._send_file_button.set_tooltip_text(_( "This contact does not support file transfer.")) else: @@ -1417,7 +1414,7 @@ "her a file.")) # Convert to GC - if gajim.capscache.is_supported(self.contact, NS_MUC): + if self.contact.supports(NS_MUC): self._convert_to_gc_button.set_sensitive(True) else: self._convert_to_gc_button.set_sensitive(False) @@ -1982,10 +1979,7 @@ self._schedule_activity_timers() def _on_sent(id_, contact, message, encrypted, xhtml): - # XXX: Once we have fallback to disco, remove notexistant check - if gajim.capscache.is_supported(contact, NS_RECEIPTS) \ - and not gajim.capscache.is_supported(contact, - 'notexistant') and gajim.config.get_per('accounts', + if contact.supports(NS_RECEIPTS) and gajim.config.get_per('accounts', self.account, 'request_receipt'): xep0184_id = id_ else: @@ -2504,12 +2498,8 @@ want_e2e = not e2e_is_active and not self.gpg_is_active \ and e2e_pref - # XXX: Once we have fallback to disco, remove notexistant check if want_e2e and not self.no_autonegotiation \ - and gajim.HAVE_PYCRYPTO \ - and gajim.capscache.is_supported(self.contact, - NS_ESESSION) and not gajim.capscache.is_supported( - self.contact, 'notexistant'): + and gajim.HAVE_PYCRYPTO and self.contact.supports(NS_ESESSION): self.begin_e2e_negotiation() else: self.send_chatstate('active', self.contact) diff -r b82bcd6c8d7f -r 200870540a1f src/common/caps.py --- a/src/common/caps.py Fri Oct 30 20:08:33 2009 +0100 +++ b/src/common/caps.py Sat Oct 31 18:08:06 2009 +0100 @@ -6,7 +6,7 @@ ## Copyright (C) 2007-2008 Yann Leboulanger <asterix AT
lagaule.org
> ## Copyright (C) 2008 Brendan Taylor <whateley AT
gmail.com
> ## Jonathan Schleifer <js-gajim AT
webkeks.org
> -## Stephan Erb <steve-e AT h3c.de> +## Copyright (C) 2008-2009 Stephan Erb <steve-e AT h3c.de> ## ## This file is part of Gajim. ## @@ -23,55 +23,198 @@ ## along with Gajim. If not, see <
http://www.gnu.org/licenses/
>. ## -from itertools import * +''' +Module containing all XEP-115 (Entity Capabilities) related classes + +Basic Idea: +CapsCache caches features to hash relationships. The cache is queried +through ClientCaps objects which are hold by contact instances. +''' + import gajim import helpers +import base64 +import hashlib + +from common.xmpp import NS_XHTML_IM, NS_RECEIPTS, NS_ESESSION, NS_CHATSTATES +# Features where we cannot safely assume that the other side supports them +FEATURE_BLACKLIST = [NS_CHATSTATES, NS_XHTML_IM, NS_RECEIPTS, NS_ESESSION] + + +capscache = None +def initialize(logger): + ''' Initializes the capscache global ''' + global capscache + capscache = CapsCache(logger) + + +def compute_caps_hash(identities, features, dataforms=[], hash_method='sha-1'): + '''Compute caps hash according to XEP-0115, V1.5 + + dataforms are xmpp.DataForms objects as common.dataforms don't allow several + values without a field type list-multi''' + + def sort_identities_func(i1, i2): + cat1 = i1['category'] + cat2 = i2['category'] + if cat1 < cat2: + return -1 + if cat1 > cat2: + return 1 + type1 = i1.get('type', '') + type2 = i2.get('type', '') + if type1 < type2: + return -1 + if type1 > type2: + return 1 + lang1 = i1.get('xml:lang', '') + lang2 = i2.get('xml:lang', '') + if lang1 < lang2: + return -1 + if lang1 > lang2: + return 1 + return 0 + + def sort_dataforms_func(d1, d2): + f1 = d1.getField('FORM_TYPE') + f2 = d2.getField('FORM_TYPE') + if f1 and f2 and (f1.getValue() < f2.getValue()): + return -1 + return 1 + + S = '' + identities.sort(cmp=sort_identities_func) + for i in identities: + c = i['category'] + type_ = i.get('type', '') + lang = i.get('xml:lang', '') + name = i.get('name', '') + S += '%s/%s/%s/%s<' % (c, type_, lang, name) + features.sort() + for f in features: + S += '%s<' % f + dataforms.sort(cmp=sort_dataforms_func) + for dataform in dataforms: + # fields indexed by var + fields = {} + for f in dataform.getChildren(): + fields[f.getVar()] = f + form_type = fields.get('FORM_TYPE') + if form_type: + S += form_type.getValue() + '<' + del fields['FORM_TYPE'] + for var in sorted(fields.keys()): + S += '%s<' % var + values = sorted(fields[var].getValues()) + for value in values: + S += '%s<' % value + + if hash_method == 'sha-1': + hash_ = hashlib.sha1(S) + elif hash_method == 'md5': + hash_ = hashlib.md5(S) + else: + return '' + return base64.b64encode(hash_.digest()) + + +class AbstractClientCaps(object): + ''' + Base class representing a client and its capabilities as advertised by + a caps tag in a presence. + ''' + def __init__(self, caps_hash, node): + self._hash = caps_hash + self._node = node + + def get_discover_strategy(self): + return self._discover + + def _discover(self, connection, jid): + ''' To be implemented by subclassess ''' + raise NotImplementedError() + + def get_cache_lookup_strategy(self): + return self._lookup_in_cache + + def _lookup_in_cache(self, caps_cache): + ''' To be implemented by subclassess ''' + raise NotImplementedError() + + def get_hash_validation_strategy(self): + return self._is_hash_valid + + def _is_hash_valid(self, identities, features, dataforms): + ''' To be implemented by subclassess ''' + raise NotImplementedError() + + +class ClientCaps(AbstractClientCaps): + ''' The current XEP-115 implementation ''' + + def __init__(self, caps_hash, node, hash_method): + AbstractClientCaps.__init__(self, caps_hash, node) + assert hash_method != 'old' + self._hash_method = hash_method + + def _lookup_in_cache(self, caps_cache): + return caps_cache[(self._hash_method, self._hash)] + + def _discover(self, connection, jid): + connection.discoverInfo(jid, '%s#%s' % (self._node, self._hash)) + + def _is_hash_valid(self, identities, features, dataforms): + computed_hash = compute_caps_hash(identities, features, + dataforms=dataforms, hash_method=self._hash_method) + return computed_hash == self._hash + + +class OldClientCaps(AbstractClientCaps): + ''' Old XEP-115 implemtation. Kept around for background competability. ''' + + def __init__(self, caps_hash, node): + AbstractClientCaps.__init__(self, caps_hash, node) + + def _lookup_in_cache(self, caps_cache): + return caps_cache[('old', self._node + '#' + self._hash)] + + def _discover(self, connection, jid): + connection.discoverInfo(jid) + + def _is_hash_valid(self, identities, features, dataforms): + return True + + +class NullClientCaps(AbstractClientCaps): + ''' + This is a NULL-Object to streamline caps handling if a client has not + advertised any caps or has advertised them in an improper way. + + Assumes (almost) everything is supported. + ''' + + def __init__(self): + AbstractClientCaps.__init__(self, None, None) + + def _lookup_in_cache(self, caps_cache): + # lookup something which does not exist to get a new CacheItem created + cache_item = caps_cache[('old', '')] + assert cache_item.queried == 0 + return cache_item + + def _discover(self, connection, jid): + pass + + def _is_hash_valid(self, identities, features, dataforms): + return False + class CapsCache(object): - ''' This object keeps the mapping between caps data and real disco + ''' + This object keeps the mapping between caps data and real disco features they represent, and provides simple way to query that info.
1
0
0
0
gajim: Merge changes from default branch into refactoring branch
by Stephan Erb
31 Oct '09
31 Oct '09
changeset 0bb45d6b6f58 in /home/hg/repos/gajim
details:http://hg.gajim.org/gajim?cmd=changeset;node=0bb45d6b6f58
description: Merge changes from default branch into refactoring branch diffstat: ChangeLog | 31 + README.html | 4 +- configure.ac | 2 +- data/glade/message_window.glade | 322 +- data/glade/voip_call_received_dialog.glade | 39 + data/iconsets/crystal/16x16/away.png | data/iconsets/crystal/16x16/chat.png | data/iconsets/crystal/16x16/closed.png | data/iconsets/crystal/16x16/connecting.gif | data/iconsets/crystal/16x16/dnd.png | data/iconsets/crystal/16x16/error.png | data/iconsets/crystal/16x16/event.gif | data/iconsets/crystal/16x16/invisible.png | data/iconsets/crystal/16x16/muc_active.png | data/iconsets/crystal/16x16/muc_inactive.png | data/iconsets/crystal/16x16/not_in_roster.png | data/iconsets/crystal/16x16/offline.png | data/iconsets/crystal/16x16/online.png | data/iconsets/crystal/16x16/opened.png | data/iconsets/crystal/16x16/requested.png | data/iconsets/crystal/16x16/xa.png | data/iconsets/crystal/32x32/muc_active.png | data/iconsets/crystal/32x32/muc_inactive.png | data/iconsets/crystal/48x48/offline.png | data/iconsets/crystal/48x48/online.png | data/iconsets/gossip/16x16/away.png | data/iconsets/gossip/16x16/chat.png | data/iconsets/gossip/16x16/closed.png | data/iconsets/gossip/16x16/connecting.gif | data/iconsets/gossip/16x16/dnd.png | data/iconsets/gossip/16x16/error.png | data/iconsets/gossip/16x16/event.png | data/iconsets/gossip/16x16/invisible.png | data/iconsets/gossip/16x16/muc_active.png | data/iconsets/gossip/16x16/muc_inactive.png | data/iconsets/gossip/16x16/not_in_roster.png | data/iconsets/gossip/16x16/offline.png | data/iconsets/gossip/16x16/online.png | data/iconsets/gossip/16x16/opened.png | data/iconsets/gossip/16x16/requested.png | data/iconsets/gossip/16x16/xa.png | data/iconsets/gossip/32x32/muc_active.png | data/iconsets/gossip/32x32/muc_inactive.png | data/iconsets/gossip/48x48/offline.png | data/iconsets/gossip/48x48/online.png | data/iconsets/nuvola/16x16/away.png | data/iconsets/nuvola/16x16/chat.png | data/iconsets/nuvola/16x16/closed.png | data/iconsets/nuvola/16x16/connecting.png | data/iconsets/nuvola/16x16/dnd.png | data/iconsets/nuvola/16x16/error.png | data/iconsets/nuvola/16x16/event.gif | data/iconsets/nuvola/16x16/invisible.png | data/iconsets/nuvola/16x16/muc_active.png | data/iconsets/nuvola/16x16/muc_inactive.png | data/iconsets/nuvola/16x16/not_in_roster.png | data/iconsets/nuvola/16x16/offline.png | data/iconsets/nuvola/16x16/online.png | data/iconsets/nuvola/16x16/opened.png | data/iconsets/nuvola/16x16/requested.png | data/iconsets/nuvola/16x16/xa.png | data/iconsets/nuvola/32x32/muc_active.png | data/iconsets/nuvola/32x32/muc_inactive.png | data/iconsets/nuvola/48x48/offline.png | data/iconsets/nuvola/48x48/online.png | data/iconsets/simplebulb/16x16/away.png | data/iconsets/simplebulb/16x16/chat.png | data/iconsets/simplebulb/16x16/closed.png | data/iconsets/simplebulb/16x16/connecting.png | data/iconsets/simplebulb/16x16/dnd.png | data/iconsets/simplebulb/16x16/error.png | data/iconsets/simplebulb/16x16/event.png | data/iconsets/simplebulb/16x16/invisible.png | data/iconsets/simplebulb/16x16/muc_active.png | data/iconsets/simplebulb/16x16/muc_inactive.png | data/iconsets/simplebulb/16x16/not_in_roster.png | data/iconsets/simplebulb/16x16/offline.png | data/iconsets/simplebulb/16x16/online.png | data/iconsets/simplebulb/16x16/opened.png | data/iconsets/simplebulb/16x16/requested.png | data/iconsets/simplebulb/16x16/xa.png | data/iconsets/simplebulb/32x32/muc_active.png | data/iconsets/simplebulb/32x32/muc_inactive.png | data/iconsets/simplebulb/48x48/offline.png | data/iconsets/simplebulb/48x48/online.png | data/iconsets/stellar/16x16/away.png | data/iconsets/stellar/16x16/chat.png | data/iconsets/stellar/16x16/closed.png | data/iconsets/stellar/16x16/connecting.gif | data/iconsets/stellar/16x16/dnd.png | data/iconsets/stellar/16x16/error.png | data/iconsets/stellar/16x16/event.gif | data/iconsets/stellar/16x16/invisible.png | data/iconsets/stellar/16x16/muc_active.png | data/iconsets/stellar/16x16/muc_inactive.png | data/iconsets/stellar/16x16/not_in_roster.png | data/iconsets/stellar/16x16/offline.png | data/iconsets/stellar/16x16/online.png | data/iconsets/stellar/16x16/opened.png | data/iconsets/stellar/16x16/requested.png | data/iconsets/stellar/16x16/xa.png | data/iconsets/stellar/32x32/muc_active.png | data/iconsets/stellar/32x32/muc_inactive.png | data/iconsets/stellar/48x48/offline.png | data/iconsets/stellar/48x48/online.png | doc/epydoc.conf | 2 +- gajim.nsi | 30 - po/be.po | 2988 ++++++++++++++------------- po/be(a)latin.po | 2998 ++++++++++++++------------- po/bg.po | 2959 ++++++++++++++------------ po/br.po | 3001 ++++++++++++++------------- po/cs.po | 2943 ++++++++++++++------------ po/da.po | 2957 ++++++++++++++------------ po/de.po | 2986 ++++++++++++++------------ po/el.po | 3008 ++++++++++++++------------- po/en_GB.po | 2958 ++++++++++++++------------ po/eo.po | 2982 ++++++++++++++------------- po/es.po | 2944 ++++++++++++++------------ po/eu.po | 2986 ++++++++++++++------------- po/fr.po | 2962 ++++++++++++++------------ po/gl.po | 2982 ++++++++++++++------------- po/hr.po | 2961 ++++++++++++++------------ po/it.po | 2973 ++++++++++++++------------ po/lt.po | 2996 ++++++++++++++------------- po/nb.po | 2960 ++++++++++++++------------ po/nl.po | 3028 ++++++++++++++------------- po/no.po | 2960 ++++++++++++++------------ po/pl.po | 2951 ++++++++++++++------------ po/pt.po | 3005 ++++++++++++++------------- po/pt_BR.po | 2139 ++++++++++--------- po/ru.po | 2951 ++++++++++++++------------ po/sk.po | 2960 ++++++++++++++------------ po/sr.po | 2962 ++++++++++++++------------ po/sr(a)Latn.po | 2964 ++++++++++++++------------ po/sv.po | 2959 ++++++++++++++------------ po/uk.po | 2963 ++++++++++++++------------ po/zh_CN.po | 2955 ++++++++++++++------------ src/atom_window.py | 8 +- src/chat_control.py | 173 +- src/command_system/implementation/standard.py | 2 +- src/common/connection_handlers.py | 15 +- src/common/defs.py | 2 +- src/common/events.py | 5 +- src/common/gajim.py | 5 + src/common/helpers.py | 6 + src/common/jingle.py | 1165 ++++++++++ src/common/meta.py | 36 + src/common/optparser.py | 17 + src/common/xmpp/protocol.py | 7 + src/common/xmpp/simplexml.py | 3 + src/common/zeroconf/client_zeroconf.py | 10 +- src/config.py | 2 + src/conversation_textview.py | 9 +- src/dataforms_widget.py | 4 +- src/dialogs.py | 111 +- src/features_window.py | 7 + src/gajim.py | 109 +- src/groupchat_control.py | 58 +- src/gui_menu_builder.py | 15 +- src/roster_window.py | 28 +- src/vcard.py | 16 +- 161 files changed, 48372 insertions(+), 42212 deletions(-) diffs (truncated from 210830 to 300 lines): diff -r 7a4ee9cbc58f -r 0bb45d6b6f58 ChangeLog --- a/ChangeLog Sat Oct 31 09:14:55 2009 +0100 +++ b/ChangeLog Sat Oct 31 17:25:47 2009 +0100 @@ -1,3 +1,34 @@ +Gajim 0.12.5 (08 August 2009) + + * Don't depend on GTK 2.14 + +Gajim 0.12.4 (07 August 2009) + + * Fix History manager + * Fix file transfer proxy discovering at connection + * Improve filetransfer with IPv6 + * Fix zeroconf when receiving badly encoded info + +Gajim 0.12.3 (12 June 2009) + + * Fix PLAIN authentication (in particular with Gtalk + * fix PEP discovery + +Gajim 0.12.2 (07 June 2009) + + * Better keepalive / ping behaviour + * Fix custom port handling + * Improve error messages handling + * Totem support for played music + * Fix SSL with some servers + * Handle XFCE notification-daemon + * Restore old behaviour of click on systray: left click to open events + * Network manager 0.7 support + * Move logs file under windows to $APPDATA/gajim + * Improve Kerberos support + * Many bugfixes here and there + * Add -c option to history_manager + Gajim 0.12.1 (21 December 2008) * Fix filetransfer diff -r 7a4ee9cbc58f -r 0bb45d6b6f58 README.html --- a/README.html Sat Oct 31 09:14:55 2009 +0100 +++ b/README.html Sat Oct 31 17:25:47 2009 +0100 @@ -37,8 +37,8 @@ <li>GnomePythonExtras 2.10 or above (aka gnome-python-desktop) so you can avoid compiling trayicon and gtkspell</li> <li>gnome-python-desktop (for GnomeKeyring support)</li> <li>notification-daemon or notify-python (and D-Bus) to get cooler popups</li> -<li>D-Bus running to have gajim-remote working. Some distributions split dbus-x11, which is needed for dbus to work with Gajim. Version >= 0.60 is required.</li> -<li>python-dbus bindings</li> +<li>D-Bus running to have gajim-remote working. Some distributions split dbus-x11, which is needed for dbus to work with Gajim. Version >= 0.80 is required.</li> +<li>python-dbus bindings (>=0.80)</li> <li>python-sexy to have clickable URLs in chat windows</li> <li>python-kerberos to use GSSAPI authentification. Note: version1.1 or higher is required</li> </ul> diff -r 7a4ee9cbc58f -r 0bb45d6b6f58 configure.ac --- a/configure.ac Sat Oct 31 09:14:55 2009 +0100 +++ b/configure.ac Sat Oct 31 17:25:47 2009 +0100 @@ -1,5 +1,5 @@ AC_INIT([Gajim - A Jabber Instant Messager], - [
0.12.5.6-dev],[http://trac.gajim.org/],[gajim
]) + [
0.12.5.7-dev],[http://trac.gajim.org/],[gajim
]) AC_PREREQ([2.59]) AC_CONFIG_HEADER(config.h) diff -r 7a4ee9cbc58f -r 0bb45d6b6f58 data/glade/message_window.glade --- a/data/glade/message_window.glade Sat Oct 31 09:14:55 2009 +0100 +++ b/data/glade/message_window.glade Sat Oct 31 17:25:47 2009 +0100 @@ -1,7 +1,7 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> -<!--*- mode: xml -*--> +<?xml version="1.0"?> <glade-interface> + <!-- interface-requires gtk+ 2.14 --> + <!-- interface-naming-policy toplevel-contextual --> <widget class="GtkWindow" id="message_window"> <property name="default_width">480</property> <property name="default_height">440</property> @@ -40,6 +40,7 @@ <property name="expand">False</property> <property name="fill">False</property> <property name="padding">5</property> + <property name="position">0</property> </packing> </child> <child> @@ -54,6 +55,9 @@ <property name="label"><span weight="heavy" size="large">Contact name</span></property> <property name="use_markup">True</property> </widget> + <packing> + <property name="position">0</property> + </packing> </child> <child> <placeholder/> @@ -71,14 +75,17 @@ <widget class="GtkImage" id="mood_image"> <property name="no_show_all">True</property> <property name="stock">None</property> - <property name="icon_size">1</property> + <property name="icon-size">1</property> </widget> + <packing> + <property name="position">0</property> + </packing> </child> <child> <widget class="GtkImage" id="activity_image"> <property name="no_show_all">True</property> <property name="stock">None</property> - <property name="icon_size">1</property> + <property name="icon-size">1</property> </widget> <packing> <property name="position">1</property> @@ -87,14 +94,34 @@ <child> <widget class="GtkImage" id="tune_image"> <property name="no_show_all">True</property> - <property name="pixbuf">../emoticons/static/music.png</property> - <property name="icon_size">1</property> + <property name="pixbuf">../emoticons/static/music.png</property> + <property name="icon-size">1</property> </widget> <packing> <property name="position">2</property> </packing> </child> <child> + <widget class="GtkImage" id="audio_banner_image"> + <property name="visible">True</property> + <property name="stock">None</property> + <property name="icon-size">1</property> + </widget> + <packing> + <property name="position">3</property> + </packing> + </child> + <child> + <widget class="GtkImage" id="video_banner_image"> + <property name="visible">True</property> + <property name="stock">None</property> + <property name="icon-size">1</property> + </widget> + <packing> + <property name="position">4</property> + </packing> + </child> + <child> <widget class="GtkAlignment" id="alignment3"> <property name="width_request">11</property> <property name="visible">True</property> @@ -103,7 +130,7 @@ </child> </widget> <packing> - <property name="position">3</property> + <property name="position">5</property> </packing> </child> </widget> @@ -138,6 +165,7 @@ <packing> <property name="expand">False</property> <property name="fill">False</property> + <property name="position">0</property> </packing> </child> <child> @@ -148,35 +176,40 @@ <property name="height_request">60</property> <property name="can_focus">True</property> <property name="border_width">3</property> - <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="hscrollbar_policy">automatic</property> + <property name="vscrollbar_policy">automatic</property> + <property name="shadow_type">in</property> <child> <placeholder/> </child> </widget> + <packing> + <property name="position">0</property> + </packing> </child> <child> - <widget class="GtkHBox" id="hbox1"> + <widget class="GtkHBox" id="hbox"> <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <child> <widget class="GtkButton" id="authentication_button"> + <property name="can_focus">False</property> + <property name="receives_default">False</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="no_show_all">True</property> - <property name="relief">GTK_RELIEF_NONE</property> + <property name="relief">none</property> <property name="focus_on_click">False</property> - <property name="response_id">0</property> <child> <widget class="GtkImage" id="lock_image"> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="stock">gtk-dialog-authentication</property> - <property name="icon_size">1</property> + <property name="icon-size">1</property> </widget> </child> </widget> <packing> <property name="expand">False</property> + <property name="position">0</property> </packing> </child> <child> @@ -184,9 +217,9 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="border_width">3</property> - <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> - <property name="vscrollbar_policy">GTK_POLICY_NEVER</property> - <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="hscrollbar_policy">never</property> + <property name="vscrollbar_policy">never</property> + <property name="shadow_type">in</property> <child> <placeholder/> </child> @@ -212,37 +245,40 @@ <child> <widget class="GtkButton" id="emoticons_button"> <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="receives_default">False</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="tooltip" translatable="yes">Show a list of emoticons (Alt+M)</property> - <property name="relief">GTK_RELIEF_NONE</property> + <property name="relief">none</property> <property name="focus_on_click">False</property> - <property name="response_id">0</property> <child> <widget class="GtkImage" id="emoticons_button_image"> <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="stock">gtk-missing-image</property> - <property name="icon_size">1</property> + <property name="icon-size">1</property> </widget> </child> </widget> <packing> <property name="expand">False</property> + <property name="position">0</property> </packing> </child> <child> <widget class="GtkButton" id="formattings_button"> <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="receives_default">False</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="tooltip" translatable="yes">Show a list of formattings</property> - <property name="relief">GTK_RELIEF_NONE</property> + <property name="relief">none</property> <property name="focus_on_click">False</property> - <property name="response_id">0</property> <child> <widget class="GtkImage" id="image10"> <property name="visible">True</property> <property name="stock">gtk-bold</property> - <property name="icon_size">1</property> + <property name="icon-size">1</property> </widget> </child> </widget> @@ -268,14 +304,13 @@ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="no_show_all">True</property> <property name="tooltip" translatable="yes">Add this contact to roster (Ctrl+D)</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="response_id">0</property> + <property name="relief">none</property> <child> <widget class="GtkImage" id="image9"> <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="stock">gtk-add</property> - <property name="icon_size">1</property> + <property name="icon-size">1</property> </widget> </child> </widget> @@ -288,16 +323,17 @@ <child> <widget class="GtkButton" id="send_file_button"> <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="receives_default">False</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
1
0
0
0
gajim: Rename CacheItem.update to CacheItem.set_and_store as thi...
by Stephan Erb
31 Oct '09
31 Oct '09
changeset 7a4ee9cbc58f in /home/hg/repos/gajim
details:http://hg.gajim.org/gajim?cmd=changeset;node=7a4ee9cbc58f
description: Rename CacheItem.update to CacheItem.set_and_store as this seems more intense giving. diffstat: src/common/caps.py | 4 ++-- test/test_caps.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diffs (38 lines): diff -r a87fa3bf81bb -r 7a4ee9cbc58f src/common/caps.py --- a/src/common/caps.py Fri Oct 30 23:55:03 2009 +0100 +++ b/src/common/caps.py Sat Oct 31 09:14:55 2009 +0100 @@ -278,7 +278,7 @@ identities = property(_get_identities, _set_identities) - def update(self, identities, features): + def set_and_store(self, identities, features): self.identities = identities self.features = features self._logger.add_caps_entry(self.hash_method, self.hash, @@ -391,7 +391,7 @@ hash_is_valid = validate(identities, features, dataforms) if hash_is_valid: - cache_item.update(identities, features) + cache_item.set_and_store(identities, features) else: contact.client_caps = NullClientCaps() diff -r a87fa3bf81bb -r 7a4ee9cbc58f test/test_caps.py --- a/test/test_caps.py Fri Oct 30 23:55:03 2009 +0100 +++ b/test/test_caps.py Sat Oct 31 09:14:55 2009 +0100 @@ -55,11 +55,11 @@ self.assertEqual('client', identity['category']) self.assertEqual('pc', identity['type']) - def test_update(self): + def test_set_and_store(self): ''' Test client_caps update gets logged into db ''' item = self.cc[self.client_caps] - item.update(self.identities, self.features) + item.set_and_store(self.identities, self.features) self.logger.mockCheckCall(0, "add_caps_entry", self.caps_method, self.caps_hash, self.identities, self.features)
1
0
0
0
gajim: Move compute_caps_hash from helpers to caps module.
by Stephan Erb
31 Oct '09
31 Oct '09
changeset a87fa3bf81bb in /home/hg/repos/gajim
details:http://hg.gajim.org/gajim?cmd=changeset;node=a87fa3bf81bb
description: Move compute_caps_hash from helpers to caps module. diffstat: src/common/caps.py | 74 ++++++++++++++++++++++++++++++++++++- src/common/helpers.py | 72 +----------------------------------- src/common/optparser.py | 3 +- test/test_caps.py | 4 +- 4 files changed, 78 insertions(+), 75 deletions(-) diffs (236 lines): diff -r 7fbd06477ce4 -r a87fa3bf81bb src/common/caps.py --- a/src/common/caps.py Fri Oct 30 23:01:25 2009 +0100 +++ b/src/common/caps.py Fri Oct 30 23:55:03 2009 +0100 @@ -33,6 +33,8 @@ import gajim import helpers +import base64 +import hashlib from common.xmpp import NS_XHTML_IM, NS_RECEIPTS, NS_ESESSION, NS_CHATSTATES # Features where we cannot safely assume that the other side supports them @@ -44,6 +46,76 @@ ''' Initializes the capscache global ''' global capscache capscache = CapsCache(logger) + + +def compute_caps_hash(identities, features, dataforms=[], hash_method='sha-1'): + '''Compute caps hash according to XEP-0115, V1.5 + + dataforms are xmpp.DataForms objects as common.dataforms don't allow several + values without a field type list-multi''' + + def sort_identities_func(i1, i2): + cat1 = i1['category'] + cat2 = i2['category'] + if cat1 < cat2: + return -1 + if cat1 > cat2: + return 1 + type1 = i1.get('type', '') + type2 = i2.get('type', '') + if type1 < type2: + return -1 + if type1 > type2: + return 1 + lang1 = i1.get('xml:lang', '') + lang2 = i2.get('xml:lang', '') + if lang1 < lang2: + return -1 + if lang1 > lang2: + return 1 + return 0 + + def sort_dataforms_func(d1, d2): + f1 = d1.getField('FORM_TYPE') + f2 = d2.getField('FORM_TYPE') + if f1 and f2 and (f1.getValue() < f2.getValue()): + return -1 + return 1 + + S = '' + identities.sort(cmp=sort_identities_func) + for i in identities: + c = i['category'] + type_ = i.get('type', '') + lang = i.get('xml:lang', '') + name = i.get('name', '') + S += '%s/%s/%s/%s<' % (c, type_, lang, name) + features.sort() + for f in features: + S += '%s<' % f + dataforms.sort(cmp=sort_dataforms_func) + for dataform in dataforms: + # fields indexed by var + fields = {} + for f in dataform.getChildren(): + fields[f.getVar()] = f + form_type = fields.get('FORM_TYPE') + if form_type: + S += form_type.getValue() + '<' + del fields['FORM_TYPE'] + for var in sorted(fields.keys()): + S += '%s<' % var + values = sorted(fields[var].getValues()) + for value in values: + S += '%s<' % value + + if hash_method == 'sha-1': + hash_ = hashlib.sha1(S) + elif hash_method == 'md5': + hash_ = hashlib.md5(S) + else: + return '' + return base64.b64encode(hash_.digest()) class AbstractClientCaps(object): @@ -92,7 +164,7 @@ connection.discoverInfo(jid, '%s#%s' % (self._node, self._hash)) def _is_hash_valid(self, identities, features, dataforms): - computed_hash = helpers.compute_caps_hash(identities, features, + computed_hash = compute_caps_hash(identities, features, dataforms=dataforms, hash_method=self._hash_method) return computed_hash == self._hash diff -r 7fbd06477ce4 -r a87fa3bf81bb src/common/helpers.py --- a/src/common/helpers.py Fri Oct 30 23:01:25 2009 +0100 +++ b/src/common/helpers.py Fri Oct 30 23:55:03 2009 +0100 @@ -37,8 +37,8 @@ import errno import select import base64 -import sys import hashlib +import caps from encodings.punycode import punycode_encode @@ -566,74 +566,6 @@ from time import strptime return strptime(timestamp, '%Y%m%dT%H:%M:%S') -def sort_identities_func(i1, i2): - cat1 = i1['category'] - cat2 = i2['category'] - if cat1 < cat2: - return -1 - if cat1 > cat2: - return 1 - type1 = i1.get('type', '') - type2 = i2.get('type', '') - if type1 < type2: - return -1 - if type1 > type2: - return 1 - lang1 = i1.get('xml:lang', '') - lang2 = i2.get('xml:lang', '') - if lang1 < lang2: - return -1 - if lang1 > lang2: - return 1 - return 0 - -def sort_dataforms_func(d1, d2): - f1 = d1.getField('FORM_TYPE') - f2 = d2.getField('FORM_TYPE') - if f1 and f2 and (f1.getValue() < f2.getValue()): - return -1 - return 1 - -def compute_caps_hash(identities, features, dataforms=[], hash_method='sha-1'): - '''Compute caps hash according to XEP-0115, V1.5 - - dataforms are xmpp.DataForms objects as common.dataforms don't allow several - values without a field type list-multi''' - S = '' - identities.sort(cmp=sort_identities_func) - for i in identities: - c = i['category'] - type_ = i.get('type', '') - lang = i.get('xml:lang', '') - name = i.get('name', '') - S += '%s/%s/%s/%s<' % (c, type_, lang, name) - features.sort() - for f in features: - S += '%s<' % f - dataforms.sort(cmp=sort_dataforms_func) - for dataform in dataforms: - # fields indexed by var - fields = {} - for f in dataform.getChildren(): - fields[f.getVar()] = f - form_type = fields.get('FORM_TYPE') - if form_type: - S += form_type.getValue() + '<' - del fields['FORM_TYPE'] - for var in sorted(fields.keys()): - S += '%s<' % var - values = sorted(fields[var].getValues()) - for value in values: - S += '%s<' % value - - if hash_method == 'sha-1': - hash_ = hashlib.sha1(S) - elif hash_method == 'md5': - hash_ = hashlib.md5(S) - else: - return '' - return base64.b64encode(hash_.digest()) - # import gajim only when needed (after decode_string is defined) see #4764 import gajim @@ -1357,7 +1289,7 @@ gajim.gajim_optional_features[a].append(xmpp.NS_ESESSION) if gajim.config.get_per('accounts', a, 'answer_receipts'): gajim.gajim_optional_features[a].append(xmpp.NS_RECEIPTS) - gajim.caps_hash[a] = compute_caps_hash([gajim.gajim_identity], + gajim.caps_hash[a] = caps.compute_caps_hash([gajim.gajim_identity], gajim.gajim_common_features + gajim.gajim_optional_features[a]) # re-send presence with new hash connected = gajim.connections[a].connected diff -r 7fbd06477ce4 -r a87fa3bf81bb src/common/optparser.py --- a/src/common/optparser.py Fri Oct 30 23:01:25 2009 +0100 +++ b/src/common/optparser.py Fri Oct 30 23:55:03 2009 +0100 @@ -31,6 +31,7 @@ import re from common import gajim from common import helpers +from common import caps import exceptions try: @@ -216,7 +217,7 @@ gajim.logger.init_vars() gajim.config.set('version', new_version) - gajim.capscache.initialize_from_db() + caps.capscache.initialize_from_db() def update_config_x_to_09(self): # Var name that changed: diff -r 7fbd06477ce4 -r a87fa3bf81bb test/test_caps.py --- a/test/test_caps.py Fri Oct 30 23:01:25 2009 +0100 +++ b/test/test_caps.py Fri Oct 30 23:55:03 2009 +0100 @@ -6,8 +6,6 @@ import lib lib.setup_env() -from common import gajim -from common import helpers from common.xmpp import NS_MUC, NS_PING, NS_XHTML_IM from common import caps from common.contacts import Contact @@ -95,7 +93,7 @@ def test_hash(self): '''tests the hash computation''' - computed_hash = helpers.compute_caps_hash(self.identities, self.features) + computed_hash = caps.compute_caps_hash(self.identities, self.features) self.assertEqual(self.caps_hash, computed_hash)
1
0
0
0
gajim: Move CapsCache global from gajim.capscache to caps.capsca...
by Stephan Erb
31 Oct '09
31 Oct '09
changeset 7fbd06477ce4 in /home/hg/repos/gajim
details:http://hg.gajim.org/gajim?cmd=changeset;node=7fbd06477ce4
description: Move CapsCache global from gajim.capscache to caps.capscache. diffstat: src/common/caps.py | 28 ++++++++++++++-------------- src/common/contacts.py | 35 +++++++++++++++-------------------- src/common/gajim.py | 3 +++ src/gajim.py | 7 +++++++ test/test_caps.py | 19 ++++++++----------- test/test_contacts.py | 9 +++++---- 6 files changed, 52 insertions(+), 49 deletions(-) diffs (truncated from 332 to 300 lines): diff -r 4d83b83c1d9d -r 7fbd06477ce4 src/common/caps.py --- a/src/common/caps.py Wed Oct 28 23:37:40 2009 +0100 +++ b/src/common/caps.py Fri Oct 30 23:01:25 2009 +0100 @@ -39,6 +39,13 @@ FEATURE_BLACKLIST = [NS_CHATSTATES, NS_XHTML_IM, NS_RECEIPTS, NS_ESESSION] +capscache = None +def initialize(logger): + ''' Initializes the capscache global ''' + global capscache + capscache = CapsCache(logger) + + class AbstractClientCaps(object): ''' Base class representing a client and its capabilities as advertised by @@ -66,6 +73,7 @@ return self._is_hash_valid def _is_hash_valid(self, identities, features, dataforms): + ''' To be implemented by subclassess ''' raise NotImplementedError() @@ -117,7 +125,10 @@ AbstractClientCaps.__init__(self, None, None) def _lookup_in_cache(self, caps_cache): - return caps_cache[('old', '')] + # lookup something which does not exist to get a new CacheItem created + cache_item = caps_cache[('old', '')] + assert cache_item.queried == 0 + return cache_item def _discover(self, connection, jid): pass @@ -202,15 +213,6 @@ identities, features) self.__CacheItem = CacheItem - - # prepopulate data which we are sure of; note: we do not log these info - for account in gajim.connections: - gajimcaps = self[('sha-1', gajim.caps_hash[account])] - gajimcaps.identities = [gajim.gajim_identity] - gajimcaps.features = gajim.gajim_common_features + \ - gajim.gajim_optional_features[account] - - # start logging data from the net self.logger = logger def initialize_from_db(self): @@ -248,8 +250,6 @@ discover = client_caps.get_discover_strategy() discover(connection, jid) -gajim.capscache = CapsCache(gajim.logger) - class ConnectionCaps(object): ''' @@ -295,7 +295,7 @@ else: client_caps = ClientCaps(caps_hash, node, hash_method) - gajim.capscache.query_client_of_jid_if_unknown(self, jid, client_caps) + capscache.query_client_of_jid_if_unknown(self, jid, client_caps) contact.client_caps = client_caps if pm_ctrl: @@ -310,7 +310,7 @@ return lookup = contact.client_caps.get_cache_lookup_strategy() - cache_item = lookup(gajim.capscache) + cache_item = lookup(capscache) if cache_item.queried == 2: return diff -r 4d83b83c1d9d -r 7fbd06477ce4 src/common/contacts.py --- a/src/common/contacts.py Wed Oct 28 23:37:40 2009 +0100 +++ b/src/common/contacts.py Fri Oct 30 23:01:25 2009 +0100 @@ -30,13 +30,14 @@ import common.gajim -from common.caps import NullClientCaps, FEATURE_BLACKLIST + +from common import caps class CommonContact(object): def __init__(self, jid, resource, show, status, name, our_chatstate, - composing_xep, chatstate, client_caps=None, caps_cache=None): + composing_xep, chatstate, client_caps=None): self.jid = jid self.resource = resource @@ -44,8 +45,7 @@ self.status = status self.name = name - self.client_caps = client_caps or NullClientCaps() - self._caps_cache = caps_cache or common.gajim.capscache + self.client_caps = client_caps or caps.NullClientCaps() # please read xep-85
http://www.xmpp.org/extensions/xep-0085.html
# we keep track of xep85 support with the peer by three extra states: @@ -84,7 +84,7 @@ def _client_supports(self, requested_feature): lookup_item = self.client_caps.get_cache_lookup_strategy() - cache_item = lookup_item(self._caps_cache) + cache_item = lookup_item(caps.capscache) supported_features = cache_item.features if requested_feature in supported_features: @@ -92,7 +92,7 @@ elif supported_features == [] and cache_item.queried in (0, 1): # assume feature is supported, if we don't know yet, what the client # is capable of - return requested_feature not in FEATURE_BLACKLIST + return requested_feature not in caps.FEATURE_BLACKLIST else: return False @@ -100,13 +100,12 @@ class Contact(CommonContact): '''Information concerning each contact''' def __init__(self, jid='', name='', groups=[], show='', status='', sub='', - ask='', resource='', priority=0, keyID='', client_caps=None, caps_cache=None, + ask='', resource='', priority=0, keyID='', client_caps=None, our_chatstate=None, chatstate=None, last_status_time=None, msg_id = None, composing_xep=None, mood={}, tune={}, activity={}): CommonContact.__init__(self, jid, resource, show, status, name, - our_chatstate, composing_xep, chatstate, client_caps=client_caps, - caps_cache=caps_cache) + our_chatstate, composing_xep, chatstate, client_caps=client_caps) self.contact_name = '' # nick choosen by contact self.groups = groups @@ -236,9 +235,8 @@ def create_contact(self, jid='', name='', groups=[], show='', status='', sub='', ask='', resource='', priority=0, keyID='', client_caps=None, - caps_cache=None, our_chatstate=None, - chatstate=None, last_status_time=None, composing_xep=None, - mood={}, tune={}, activity={}): + our_chatstate=None, chatstate=None, last_status_time=None, + composing_xep=None, mood={}, tune={}, activity={}): # We don't want duplicated group values groups_unique = [] @@ -248,18 +246,16 @@ return Contact(jid=jid, name=name, groups=groups_unique, show=show, status=status, sub=sub, ask=ask, resource=resource, priority=priority, - keyID=keyID, client_caps=client_caps, caps_cache=caps_cache, - our_chatstate=our_chatstate, chatstate=chatstate, - last_status_time=last_status_time, composing_xep=composing_xep, - mood=mood, tune=tune, activity=activity) + keyID=keyID, client_caps=client_caps, our_chatstate=our_chatstate, + chatstate=chatstate, last_status_time=last_status_time, + composing_xep=composing_xep, mood=mood, tune=tune, activity=activity) def copy_contact(self, contact): return self.create_contact(jid=contact.jid, name=contact.name, groups=contact.groups, show=contact.show, status=contact.status, sub=contact.sub, ask=contact.ask, resource=contact.resource, priority=contact.priority, keyID=contact.keyID, - client_caps=contact.client_caps, caps_cache=contact._caps_cache, - our_chatstate=contact.our_chatstate, + client_caps=contact.client_caps, our_chatstate=contact.our_chatstate, chatstate=contact.chatstate, last_status_time=contact.last_status_time) def add_contact(self, account, contact): @@ -629,8 +625,7 @@ jid = gc_contact.get_full_jid() return Contact(jid=jid, resource=gc_contact.resource, name=gc_contact.name, groups=[], show=gc_contact.show, - status=gc_contact.status, sub='none', client_caps=gc_contact.client_caps, - caps_cache=gc_contact._caps_cache) + status=gc_contact.status, sub='none', client_caps=gc_contact.client_caps) def create_gc_contact(self, room_jid='', name='', show='', status='', role='', affiliation='', jid='', resource=''): diff -r 4d83b83c1d9d -r 7fbd06477ce4 src/common/gajim.py --- a/src/common/gajim.py Wed Oct 28 23:37:40 2009 +0100 +++ b/src/common/gajim.py Fri Oct 30 23:01:25 2009 +0100 @@ -205,6 +205,9 @@ # Capabilities hash per account caps_hash = {} +import caps +caps.initialize(logger) + def get_nick_from_jid(jid): pos = jid.find('@') return jid[:pos] diff -r 4d83b83c1d9d -r 7fbd06477ce4 src/gajim.py --- a/src/gajim.py Wed Oct 28 23:37:40 2009 +0100 +++ b/src/gajim.py Fri Oct 30 23:01:25 2009 +0100 @@ -255,6 +255,7 @@ from common import dataforms from common import passwords from common import pep +from common import caps gajimpaths = common.configpaths.gajimpaths @@ -3536,6 +3537,12 @@ gajim.caps_hash[a] = '' helpers.update_optional_features() + # prepopulate data which we are sure of; note: we do not log these info + for account in gajim.connections: + gajimcaps = caps.capscache[('sha-1', gajim.caps_hash[account])] + gajimcaps.identities = [gajim.gajim_identity] + gajimcaps.features = gajim.gajim_common_features + \ + gajim.gajim_optional_features[account] self.remote_ctrl = None diff -r 4d83b83c1d9d -r 7fbd06477ce4 test/test_caps.py --- a/test/test_caps.py Wed Oct 28 23:37:40 2009 +0100 +++ b/test/test_caps.py Fri Oct 30 23:01:25 2009 +0100 @@ -9,7 +9,7 @@ from common import gajim from common import helpers from common.xmpp import NS_MUC, NS_PING, NS_XHTML_IM -from common.caps import CapsCache, ClientCaps, OldClientCaps +from common import caps from common.contacts import Contact from mock import Mock @@ -34,11 +34,8 @@ ('old', self.node + '#' + self.caps_hash, self.identities, self.features)] self.logger = Mock(returnValues={"iter_caps_data":db_caps_cache}) - self.cc = CapsCache(self.logger) - # This is a temporary hack required by the way contacts rely on the - # existance of a cache. Hopefully this can be refactored to work via - # dependency injection - gajim.capscache = self.cc + self.cc = caps.CapsCache(self.logger) + caps.capscache = self.cc class TestCapsCache(CommonCapsTest): @@ -78,7 +75,7 @@ def test_preload_triggering_query(self): ''' Make sure that preload issues a disco ''' connection = Mock() - client_caps = ClientCaps(self.caps_hash, self.node, self.caps_method) + client_caps = caps.ClientCaps(self.caps_hash, self.node, self.caps_method) self.cc.query_client_of_jid_if_unknown(connection, "test(a)gajim.org", client_caps) @@ -88,7 +85,7 @@ def test_no_preload_query_if_cashed(self): ''' Preload must not send a query if the data is already cached ''' connection = Mock() - client_caps = ClientCaps(self.caps_hash, self.node, self.caps_method) + client_caps = caps.ClientCaps(self.caps_hash, self.node, self.caps_method) self.cc.initialize_from_db() self.cc.query_client_of_jid_if_unknown(connection, "test(a)gajim.org", @@ -106,7 +103,7 @@ def setUp(self): CommonCapsTest.setUp(self) - self.client_caps = ClientCaps(self.caps_hash, self.node, self.caps_method) + self.client_caps = caps.ClientCaps(self.caps_hash, self.node, self.caps_method) def test_query_by_get_discover_strategy(self): ''' Client must be queried if the data is unkown ''' @@ -118,7 +115,7 @@ "
http://gajim.org#m3P2WeXPMGVH2tZPe7yITnfY0Dw=
") def test_client_supports(self): - contact = Contact(caps_cache=self.cc, client_caps=self.client_caps) + contact = Contact(client_caps=self.client_caps) self.assertTrue(contact.supports(NS_PING), msg="Assume supported, if we don't have caps") @@ -142,7 +139,7 @@ def setUp(self): TestClientCaps.setUp(self) - self.client_caps = OldClientCaps(self.caps_hash, self.node) + self.client_caps = caps.OldClientCaps(self.caps_hash, self.node) def test_query_by_get_discover_strategy(self): ''' Client must be queried if the data is unknown ''' diff -r 4d83b83c1d9d -r 7fbd06477ce4 test/test_contacts.py --- a/test/test_contacts.py Wed Oct 28 23:37:40 2009 +0100 +++ b/test/test_contacts.py Fri Oct 30 23:01:25 2009 +0100
1
0
0
0
gajim: Move common part of Contact and GC_Contact into a new Com...
by Stephan Erb
31 Oct '09
31 Oct '09
changeset 4d83b83c1d9d in /home/hg/repos/gajim
details:http://hg.gajim.org/gajim?cmd=changeset;node=4d83b83c1d9d
description: Move common part of Contact and GC_Contact into a new CommonContact class. The CommonClass helps to spot easily where GC_Contacts and Contacts differ. This is just the first step a potential refactoring in this area. diffstat: src/common/contacts.py | 155 ++++++++++++++++++++++++--------------------------- test/runtests.py | 1 + test/test_contacts.py | 6 +- 3 files changed, 78 insertions(+), 84 deletions(-) diffs (236 lines): diff -r 41fc09dcbb56 -r 4d83b83c1d9d src/common/contacts.py --- a/src/common/contacts.py Tue Oct 27 23:30:08 2009 +0100 +++ b/src/common/contacts.py Wed Oct 28 23:37:40 2009 +0100 @@ -33,29 +33,20 @@ from common.caps import NullClientCaps, FEATURE_BLACKLIST -class Contact(object): - '''Information concerning each contact''' - def __init__(self, jid='', name='', groups=[], show='', status='', sub='', - ask='', resource='', priority=0, keyID='', client_caps=None, caps_cache=None, - our_chatstate=None, chatstate=None, last_status_time=None, msg_id = None, - composing_xep = None, mood={}, tune={}, - activity={}): +class CommonContact(object): + + def __init__(self, jid, resource, show, status, name, our_chatstate, + composing_xep, chatstate, client_caps=None, caps_cache=None): + self.jid = jid - self.name = name - self.contact_name = '' # nick choosen by contact - self.groups = groups + self.resource = resource self.show = show self.status = status - self.sub = sub - self.ask = ask - self.resource = resource - self.priority = priority - self.keyID = keyID - - # Entity Capabilities + self.name = name + self.client_caps = client_caps or NullClientCaps() self._caps_cache = caps_cache or common.gajim.capscache - + # please read xep-85
http://www.xmpp.org/extensions/xep-0085.html
# we keep track of xep85 support with the peer by three extra states: # None, False and 'ask' @@ -64,14 +55,70 @@ # 'ask' if we sent the first 'active' chatstate and are waiting for reply # this holds what WE SEND to contact (our current chatstate) self.our_chatstate = our_chatstate - self.msg_id = msg_id # tell which XEP we're using for composing state # None = have to ask, XEP-0022 = use this xep, # XEP-0085 = use this xep, False = no composing support self.composing_xep = composing_xep # this is contact's chatstate self.chatstate = chatstate + + def get_full_jid(self): + raise NotImplementedError + + def get_shown_name(self): + raise NotImplementedError + + def supports(self, requested_feature): + ''' + Returns True if the contact has advertised to support the feature + identified by the given namespace. False otherwise. + ''' + if self.show == 'offline': + # Unfortunately, if all resources are offline, the contact + # includes the last resource that was online. Check for its + # show, so we can be sure it's existant. Otherwise, we still + # return caps for a contact that has no resources left. + return False + else: + return self._client_supports(requested_feature) + + def _client_supports(self, requested_feature): + lookup_item = self.client_caps.get_cache_lookup_strategy() + cache_item = lookup_item(self._caps_cache) + + supported_features = cache_item.features + if requested_feature in supported_features: + return True + elif supported_features == [] and cache_item.queried in (0, 1): + # assume feature is supported, if we don't know yet, what the client + # is capable of + return requested_feature not in FEATURE_BLACKLIST + else: + return False + + +class Contact(CommonContact): + '''Information concerning each contact''' + def __init__(self, jid='', name='', groups=[], show='', status='', sub='', + ask='', resource='', priority=0, keyID='', client_caps=None, caps_cache=None, + our_chatstate=None, chatstate=None, last_status_time=None, msg_id = None, + composing_xep=None, mood={}, tune={}, activity={}): + + CommonContact.__init__(self, jid, resource, show, status, name, + our_chatstate, composing_xep, chatstate, client_caps=client_caps, + caps_cache=caps_cache) + + self.contact_name = '' # nick choosen by contact + self.groups = groups + + self.sub = sub + self.ask = ask + + self.priority = priority + self.keyID = keyID + self.msg_id = msg_id self.last_status_time = last_status_time + self.mood = mood.copy() self.tune = tune.copy() self.activity = activity.copy() @@ -136,81 +183,25 @@ return False - def supports(self, requested_feature): - if self.show == 'offline': - # Unfortunately, if all resources are offline, the contact - # includes the last resource that was online. Check for its - # show, so we can be sure it's existant. Otherwise, we still - # return caps for a contact that has no resources left. - return False - else: - return self._client_supports(requested_feature) - - def _client_supports(self, requested_feature): - lookup = self.client_caps.get_cache_lookup_strategy() - cache_item = lookup(self._caps_cache) - - supported_features = cache_item.features - if requested_feature in supported_features: - return True - elif supported_features == [] and cache_item.queried in (0, 1): - # assume feature is supported, if we don't know yet, what the client - # is capable of - return requested_feature not in FEATURE_BLACKLIST - else: - return False - -class GC_Contact: +class GC_Contact(CommonContact): '''Information concerning each groupchat contact''' def __init__(self, room_jid='', name='', show='', status='', role='', - affiliation='', jid = '', resource = '', our_chatstate = None, - composing_xep = None, chatstate = None): + affiliation='', jid='', resource='', our_chatstate=None, + composing_xep=None, chatstate=None): + + CommonContact.__init__(self, jid, resource, show, status, name, + our_chatstate, composing_xep, chatstate) + self.room_jid = room_jid - self.name = name - self.show = show - self.status = status self.role = role self.affiliation = affiliation - self.jid = jid - self.resource = resource - # Entity Capabilities - self.client_caps = NullClientCaps() - self._caps_cache = common.gajim.capscache - - self.our_chatstate = our_chatstate - self.composing_xep = composing_xep - self.chatstate = chatstate - def get_full_jid(self): return self.room_jid + '/' + self.name def get_shown_name(self): return self.name - def supports(self, requested_feature): - if self.show == 'offline': - # Unfortunately, if all resources are offline, the contact - # includes the last resource that was online. Check for its - # show, so we can be sure it's existant. Otherwise, we still - # return caps for a contact that has no resources left. - return False - else: - return self._client_supports(requested_feature) - - def _client_supports(self, requested_feature): - lookup_item = self.client_caps.get_cache_lookup_strategy() - cache_item = lookup_item(self._caps_cache) - - supported_features = cache_item.features - if requested_feature in supported_features: - return True - elif supported_features == [] and cache_item.queried in (0, 1): - # assume feature is supported, if we don't know yet, what the client - # is capable of - return requested_feature not in FEATURE_BLACKLIST - else: - return False class Contacts: '''Information concerning all contacts and groupchat contacts''' diff -r 41fc09dcbb56 -r 4d83b83c1d9d test/runtests.py --- a/test/runtests.py Tue Oct 27 23:30:08 2009 +0100 +++ b/test/runtests.py Wed Oct 28 23:37:40 2009 +0100 @@ -40,6 +40,7 @@ 'test_xmpp_transports_nb', 'test_resolver', 'test_caps', + 'test_contacts', ) #modules = () diff -r 41fc09dcbb56 -r 4d83b83c1d9d test/test_contacts.py --- a/test/test_contacts.py Tue Oct 27 23:30:08 2009 +0100 +++ b/test/test_contacts.py Wed Oct 28 23:37:40 2009 +0100 @@ -6,14 +6,16 @@ import lib lib.setup_env() -from common.contacts import Contact, GC_Contact +from common.contacts import CommonContact, Contact, GC_Contact from common.caps import NullClientCaps from common.xmpp import NS_MUC class TestCommonContact(unittest.TestCase): def setUp(self): - self.contact = Contact() + self.contact = CommonContact(jid='', resource='', show='', status='', + name='', our_chatstate=None, composing_xep=None, chatstate=None, + client_caps=None, caps_cache=None) def test_default_client_supports(self): '''
1
0
0
0
gajim: merged in new chat control (esp. adapted GUI building)
by Kjell Braden
31 Oct '09
31 Oct '09
changeset 522be3ab029e in /home/hg/repos/gajim
details:http://hg.gajim.org/gajim?cmd=changeset;node=522be3ab029e
description: merged in new chat control (esp. adapted GUI building) diffstat: src/chat_control.py | 392 ++++++++++++++++++++++++------------------------ src/gui_menu_builder.py | 33 ++++- 2 files changed, 229 insertions(+), 196 deletions(-) diffs (truncated from 632 to 300 lines): diff -r 4f29e7a58d9c -r 522be3ab029e src/chat_control.py --- a/src/chat_control.py Sat Oct 31 13:46:10 2009 +0100 +++ b/src/chat_control.py Sat Oct 31 14:25:03 2009 +0100 @@ -33,6 +33,7 @@ import pango import gobject import gtkgui_helpers +import gui_menu_builder import message_control import dialogs import history_window @@ -50,6 +51,7 @@ from common.pep import MOODS, ACTIVITIES from common.xmpp.protocol import NS_XHTML, NS_XHTML_IM, NS_FILE, NS_MUC from common.xmpp.protocol import NS_RECEIPTS, NS_ESESSION +from common.xmpp.protocol import NS_JINGLE_RTP_AUDIO, NS_JINGLE_RTP_VIDEO, NS_JINGLE_ICE_UDP from command_system.implementation.middleware import ChatCommandProcessor from command_system.implementation.middleware import CommandTools @@ -874,7 +876,7 @@ def on_actions_button_clicked(self, widget): '''popup action menu''' - menu = self.prepare_context_menu(True) + menu = self.prepare_context_menu(hide_buttonbar_items=True) menu.show_all() gtkgui_helpers.popup_emoticons_under_button(menu, widget, self.parent_win) @@ -1172,6 +1174,15 @@ ################################################################################ class ChatControl(ChatControlBase): '''A control for standard 1-1 chat''' + ( + JINGLE_STATE_NOT_AVAILABLE, + JINGLE_STATE_AVAILABLE, + JINGLE_STATE_CONNECTING, + JINGLE_STATE_CONNECTION_RECEIVED, + JINGLE_STATE_CONNECTED, + JINGLE_STATE_ERROR + ) = range(6) + TYPE_ID = message_control.TYPE_CHAT old_msg_kind = None # last kind of the printed message @@ -1199,6 +1210,14 @@ self._on_add_to_roster_menuitem_activate) self.handlers[id_] = self._add_to_roster_button + self._audio_button = self.xml.get_widget('audio_togglebutton') + id_ = self._audio_button.connect('toggled', self.on_audio_button_toggled) + self.handlers[id_] = self._audio_button + + self._video_button = self.xml.get_widget('video_togglebutton') + id_ = self._video_button.connect('toggled', self.on_video_button_toggled) + self.handlers[id_] = self._video_button + self._send_file_button = self.xml.get_widget('send_file_button') # add a special img for send file button path_to_upload_img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'upload.png') @@ -1234,13 +1253,19 @@ # Add lock image to show chat encryption self.lock_image = self.xml.get_widget('lock_image') - self.lock_tooltip = gtk.Tooltips() # Convert to GC icon img = self.xml.get_widget('convert_to_gc_button_image') img.set_from_pixbuf(gtkgui_helpers.load_icon( 'muc_active').get_pixbuf()) + self._audio_banner_image = self.xml.get_widget('audio_banner_image') + self._video_banner_image = self.xml.get_widget('video_banner_image') + self.audio_sid = None + self.audio_state = self.JINGLE_STATE_NOT_AVAILABLE + self.video_sid = None + self.video_state = self.JINGLE_STATE_NOT_AVAILABLE + self.update_toolbar() self._mood_image = self.xml.get_widget('mood_image') @@ -1324,8 +1349,6 @@ self._show_lock_image(self.gpg_is_active, 'GPG', self.gpg_is_active, self.session and self.session.is_loggable(), True) - self.status_tooltip = gtk.Tooltips() - if gajim.otr_module: self.update_otr(True) @@ -1350,6 +1373,38 @@ else: self._add_to_roster_button.hide() + # Jingle detection + if gajim.capscache.is_supported(self.contact, NS_JINGLE_ICE_UDP) and \ + gajim.HAVE_FARSIGHT and self.contact.resource: + if gajim.capscache.is_supported(self.contact, NS_JINGLE_RTP_AUDIO): + if self.audio_state == self.JINGLE_STATE_NOT_AVAILABLE: + self.set_audio_state('available') + else: + self.set_audio_state('not_available') + + if gajim.capscache.is_supported(self.contact, NS_JINGLE_RTP_VIDEO): + if self.video_state == self.JINGLE_STATE_NOT_AVAILABLE: + self.set_video_state('available') + else: + self.set_video_state('not_available') + else: + if self.audio_state != self.JINGLE_STATE_NOT_AVAILABLE: + self.set_audio_state('not_available') + if self.video_state != self.JINGLE_STATE_NOT_AVAILABLE: + self.set_video_state('not_available') + + # Audio buttons + if self.audio_state == self.JINGLE_STATE_NOT_AVAILABLE: + self._audio_button.set_sensitive(False) + else: + self._audio_button.set_sensitive(True) + + # Video buttons + if self.video_state == self.JINGLE_STATE_NOT_AVAILABLE: + self._video_button.set_sensitive(False) + else: + self._video_button.set_sensitive(True) + # Send file if gajim.capscache.is_supported(self.contact, NS_FILE) and \ self.contact.resource: @@ -1482,6 +1537,34 @@ else: self._tune_image.hide() + def _update_jingle(self, jingle_type): + if jingle_type not in ('audio', 'video'): + return + if self.__dict__[jingle_type + '_state'] in ( + self.JINGLE_STATE_NOT_AVAILABLE, self.JINGLE_STATE_AVAILABLE): + self.__dict__['_' + jingle_type + '_banner_image'].hide() + else: + self.__dict__['_' + jingle_type + '_banner_image'].show() + if self.audio_state == self.JINGLE_STATE_CONNECTING: + self.__dict__['_' + jingle_type + '_banner_image'].set_from_stock( + gtk.STOCK_CONVERT, 1) + elif self.audio_state == self.JINGLE_STATE_CONNECTION_RECEIVED: + self.__dict__['_' + jingle_type + '_banner_image'].set_from_stock( + gtk.STOCK_NETWORK, 1) + elif self.audio_state == self.JINGLE_STATE_CONNECTED: + self.__dict__['_' + jingle_type + '_banner_image'].set_from_stock( + gtk.STOCK_CONNECT, 1) + elif self.audio_state == self.JINGLE_STATE_ERROR: + self.__dict__['_' + jingle_type + '_banner_image'].set_from_stock( + gtk.STOCK_DIALOG_WARNING, 1) + self.update_toolbar() + + def update_audio(self): + self._update_jingle('audio') + + def update_video(self): + self._update_jingle('video') + def change_resource(self, resource): old_full_jid = self.get_full_jid() self.resource = resource @@ -1495,6 +1578,52 @@ # update MessageWindow._controls self.parent_win.change_jid(self.account, old_full_jid, new_full_jid) + def _set_jingle_state(self, jingle_type, state, sid=None, reason=None): + if jingle_type not in ('audio', 'video'): + return + if state in ('connecting', 'connected', 'stop') and reason: + str = _('%(type)s state : %(state)s, reason: %(reason)s') % { + 'type': jingle_type.capitalize(), 'state': state, 'reason': reason} + self.print_conversation(str, 'info') + + states = {'not_available': self.JINGLE_STATE_NOT_AVAILABLE, + 'available': self.JINGLE_STATE_AVAILABLE, + 'connecting': self.JINGLE_STATE_CONNECTING, + 'connection_received': self.JINGLE_STATE_CONNECTION_RECEIVED, + 'connected': self.JINGLE_STATE_CONNECTED, + 'stop': self.JINGLE_STATE_AVAILABLE, + 'error': self.JINGLE_STATE_ERROR} + + if state in states: + jingle_state = states[state] + if self.__dict__[jingle_type + '_state'] == jingle_state: + return + self.__dict__[jingle_type + '_state'] = jingle_state + + # Destroy existing session with the user when he signs off + # We need to do that before modifying the sid + if state == 'not_available': + gajim.connections[self.account].delete_jingle_session( + self.contact.get_full_jid(), self.__dict__[jingle_type + '_sid']) + + if state in ('not_available', 'available', 'stop'): + self.__dict__[jingle_type + '_sid'] = None + if state in ('connection_received', 'connecting'): + self.__dict__[jingle_type + '_sid'] = sid + + if state in ('connecting', 'connected', 'connection_received'): + self.__dict__['_' + jingle_type + '_button'].set_active(True) + elif state in ('not_available', 'stop'): + self.__dict__['_' + jingle_type + '_button'].set_active(False) + + eval('self.update_' + jingle_type)() + + def set_audio_state(self, state, sid=None, reason=None): + self._set_jingle_state('audio', state, sid=sid, reason=reason) + + def set_video_state(self, state, sid=None, reason=None): + self._set_jingle_state('video', state, sid=sid, reason=reason) + def on_avatar_eventbox_enter_notify_event(self, widget, event): ''' we enter the eventbox area so we under conditions add a timeout @@ -1568,11 +1697,10 @@ return 0 ctx = gajim.otr_module.otrl_context_find( - gajim.connections[self.account].otr_userstates, - self.contact.get_full_jid().encode(), - gajim.get_jid_from_account(self.account).encode(), - gajim.OTR_PROTO, 1, (gajim.otr_add_appdata, - self.account))[0] + gajim.connections[self.account].otr_userstates, + self.contact.get_full_jid().encode(), + gajim.get_jid_from_account(self.account).encode(), + gajim.OTR_PROTO, 1, (gajim.otr_add_appdata, self.account))[0] if ctx.msgstate == gajim.otr_module.OTRL_MSGSTATE_ENCRYPTED: if ctx.active_fingerprint.trust: @@ -1594,11 +1722,9 @@ enc_status = False if otr_status == 1: - otr_status_text = u'*unauthenticated* secure OTR ' + \ - u'connection' + otr_status_text = u'*unauthenticated* secure OTR connection' elif otr_status == 2: - otr_status_text = u'authenticated secure OTR ' + \ - u'connection' + otr_status_text = u'authenticated secure OTR connection' authenticated = True elif otr_status == 3: otr_status_text = u'finished OTR connection' @@ -1606,8 +1732,8 @@ self._show_lock_image(enc_status, u'OTR', enc_status, True, authenticated) if print_status and otr_status_text != '': - self.print_conversation_line(u'[OTR] %s' % \ - otr_status_text, 'status', '', None) + self.print_conversation_line(u'[OTR] %s' % otr_status_text, + 'status', '', None) def _update_banner_state_image(self): contact = gajim.contacts.get_contact_with_highest_priority(self.account, @@ -1652,7 +1778,6 @@ jid = contact.jid banner_name_label = self.xml.get_widget('banner_name_label') - banner_name_tooltip = gtk.Tooltips() name = contact.get_shown_name() if self.resource: @@ -1727,8 +1852,7 @@ status_text = '<span %s>%s</span>' % (font_attrs_small, status_text) else: status_text = '<span %s>%s</span>' % (font_attrs_small, status_escaped) - self.status_tooltip.set_tip(self.banner_status_label, - status) + self.banner_status_label.set_tooltip_text(status) self.banner_status_label.show() self.banner_status_label.set_no_show_all(False) else: @@ -1739,7 +1863,35 @@ self.banner_status_label.set_markup(status_text) # setup the label that holds name and jid banner_name_label.set_markup(label_text) - banner_name_tooltip.set_tip(banner_name_label, label_tooltip) + banner_name_label.set_tooltip_text(label_tooltip) + + def on_audio_button_toggled(self, widget): + if widget.get_active(): + if self.audio_state == self.JINGLE_STATE_AVAILABLE: + sid = gajim.connections[self.account].startVoIP( + self.contact.get_full_jid()) + self.set_audio_state('connecting', sid) + else: + session = gajim.connections[self.account].get_jingle_session( + self.contact.get_full_jid(), self.audio_sid) + if session: + content = session.get_content('audio') + if content: + session.remove_content(content.creator, content.name) + + def on_video_button_toggled(self, widget): + if widget.get_active(): + if self.video_state == self.JINGLE_STATE_AVAILABLE: + sid = gajim.connections[self.account].startVideoIP(
1
0
0
0
gajim: merge changes from default branch into otr branch
by Kjell Braden
31 Oct '09
31 Oct '09
changeset 4f29e7a58d9c in /home/hg/repos/gajim
details:http://hg.gajim.org/gajim?cmd=changeset;node=4f29e7a58d9c
description: merge changes from default branch into otr branch diffstat: ChangeLog | 31 + Makefile.am | 9 + README.html | 4 +- configure.ac | 2 +- data/glade/chat_control_popup_menu.glade | 148 - data/glade/contact_context_menu.glade | 466 ++++ data/glade/message_window.glade | 322 +- data/glade/privacy_list_window.glade | 14 + data/glade/roster_contact_context_menu.glade | 360 --- data/glade/voip_call_received_dialog.glade | 39 + data/glade/zeroconf_contact_context_menu.glade | 169 - data/iconsets/crystal/16x16/away.png | data/iconsets/crystal/16x16/chat.png | data/iconsets/crystal/16x16/closed.png | data/iconsets/crystal/16x16/connecting.gif | data/iconsets/crystal/16x16/dnd.png | data/iconsets/crystal/16x16/error.png | data/iconsets/crystal/16x16/event.gif | data/iconsets/crystal/16x16/invisible.png | data/iconsets/crystal/16x16/muc_active.png | data/iconsets/crystal/16x16/muc_inactive.png | data/iconsets/crystal/16x16/not_in_roster.png | data/iconsets/crystal/16x16/offline.png | data/iconsets/crystal/16x16/online.png | data/iconsets/crystal/16x16/opened.png | data/iconsets/crystal/16x16/requested.png | data/iconsets/crystal/16x16/xa.png | data/iconsets/crystal/32x32/muc_active.png | data/iconsets/crystal/32x32/muc_inactive.png | data/iconsets/crystal/48x48/offline.png | data/iconsets/crystal/48x48/online.png | data/iconsets/gossip/16x16/away.png | data/iconsets/gossip/16x16/chat.png | data/iconsets/gossip/16x16/closed.png | data/iconsets/gossip/16x16/connecting.gif | data/iconsets/gossip/16x16/dnd.png | data/iconsets/gossip/16x16/error.png | data/iconsets/gossip/16x16/event.png | data/iconsets/gossip/16x16/invisible.png | data/iconsets/gossip/16x16/muc_active.png | data/iconsets/gossip/16x16/muc_inactive.png | data/iconsets/gossip/16x16/not_in_roster.png | data/iconsets/gossip/16x16/offline.png | data/iconsets/gossip/16x16/online.png | data/iconsets/gossip/16x16/opened.png | data/iconsets/gossip/16x16/requested.png | data/iconsets/gossip/16x16/xa.png | data/iconsets/gossip/32x32/muc_active.png | data/iconsets/gossip/32x32/muc_inactive.png | data/iconsets/gossip/48x48/offline.png | data/iconsets/gossip/48x48/online.png | data/iconsets/nuvola/16x16/away.png | data/iconsets/nuvola/16x16/chat.png | data/iconsets/nuvola/16x16/closed.png | data/iconsets/nuvola/16x16/connecting.png | data/iconsets/nuvola/16x16/dnd.png | data/iconsets/nuvola/16x16/error.png | data/iconsets/nuvola/16x16/event.gif | data/iconsets/nuvola/16x16/invisible.png | data/iconsets/nuvola/16x16/muc_active.png | data/iconsets/nuvola/16x16/muc_inactive.png | data/iconsets/nuvola/16x16/not_in_roster.png | data/iconsets/nuvola/16x16/offline.png | data/iconsets/nuvola/16x16/online.png | data/iconsets/nuvola/16x16/opened.png | data/iconsets/nuvola/16x16/requested.png | data/iconsets/nuvola/16x16/xa.png | data/iconsets/nuvola/32x32/muc_active.png | data/iconsets/nuvola/32x32/muc_inactive.png | data/iconsets/nuvola/48x48/offline.png | data/iconsets/nuvola/48x48/online.png | data/iconsets/simplebulb/16x16/away.png | data/iconsets/simplebulb/16x16/chat.png | data/iconsets/simplebulb/16x16/closed.png | data/iconsets/simplebulb/16x16/connecting.png | data/iconsets/simplebulb/16x16/dnd.png | data/iconsets/simplebulb/16x16/error.png | data/iconsets/simplebulb/16x16/event.png | data/iconsets/simplebulb/16x16/invisible.png | data/iconsets/simplebulb/16x16/muc_active.png | data/iconsets/simplebulb/16x16/muc_inactive.png | data/iconsets/simplebulb/16x16/not_in_roster.png | data/iconsets/simplebulb/16x16/offline.png | data/iconsets/simplebulb/16x16/online.png | data/iconsets/simplebulb/16x16/opened.png | data/iconsets/simplebulb/16x16/requested.png | data/iconsets/simplebulb/16x16/xa.png | data/iconsets/simplebulb/32x32/muc_active.png | data/iconsets/simplebulb/32x32/muc_inactive.png | data/iconsets/simplebulb/48x48/offline.png | data/iconsets/simplebulb/48x48/online.png | data/iconsets/stellar/16x16/away.png | data/iconsets/stellar/16x16/chat.png | data/iconsets/stellar/16x16/closed.png | data/iconsets/stellar/16x16/connecting.gif | data/iconsets/stellar/16x16/dnd.png | data/iconsets/stellar/16x16/error.png | data/iconsets/stellar/16x16/event.gif | data/iconsets/stellar/16x16/invisible.png | data/iconsets/stellar/16x16/muc_active.png | data/iconsets/stellar/16x16/muc_inactive.png | data/iconsets/stellar/16x16/not_in_roster.png | data/iconsets/stellar/16x16/offline.png | data/iconsets/stellar/16x16/online.png | data/iconsets/stellar/16x16/opened.png | data/iconsets/stellar/16x16/requested.png | data/iconsets/stellar/16x16/xa.png | data/iconsets/stellar/32x32/muc_active.png | data/iconsets/stellar/32x32/muc_inactive.png | data/iconsets/stellar/48x48/offline.png | data/iconsets/stellar/48x48/online.png | doc/epydoc.conf | 29 + epydoc.conf | 29 - gajim.nsi | 30 - po/be.po | 2988 ++++++++++++++------------- po/be(a)latin.po | 2998 ++++++++++++++------------- po/bg.po | 2959 ++++++++++++++------------ po/br.po | 3001 ++++++++++++++------------- po/cs.po | 2943 ++++++++++++++------------ po/da.po | 2957 ++++++++++++++------------ po/de.po | 2994 ++++++++++++++------------- po/el.po | 3008 ++++++++++++++------------- po/en_GB.po | 2958 ++++++++++++++------------ po/eo.po | 2982 ++++++++++++++------------- po/es.po | 2944 ++++++++++++++------------ po/eu.po | 2986 ++++++++++++++------------- po/fr.po | 2962 ++++++++++++++------------ po/gl.po | 2982 ++++++++++++++------------- po/hr.po | 2961 ++++++++++++++------------ po/it.po | 2973 ++++++++++++++------------ po/lt.po | 2996 ++++++++++++++------------- po/nb.po | 2960 ++++++++++++++------------ po/nl.po | 3028 ++++++++++++++------------- po/no.po | 2960 ++++++++++++++------------ po/pl.po | 2951 ++++++++++++++------------ po/pt.po | 3005 ++++++++++++++------------- po/pt_BR.po | 2139 ++++++++++--------- po/ru.po | 2951 ++++++++++++++------------ po/sk.po | 2960 ++++++++++++++------------ po/sr.po | 2962 ++++++++++++++------------ po/sr(a)Latn.po | 2964 ++++++++++++++------------ po/sv.po | 2959 ++++++++++++++------------ po/uk.po | 2963 ++++++++++++++------------ po/zh_CN.po | 2955 ++++++++++++++------------ scripts/dev/run-build-test.py | 22 + scripts/dev/run-pychecker.py | 14 - scripts/dev/run-pylint.py | 13 + src/advanced.py | 296 -- src/advanced_configuration_window.py | 288 ++ src/atom_window.py | 8 +- src/chat_control.py | 40 +- src/command_system/implementation/standard.py | 2 +- src/common/config.py | 2 + src/common/connection.py | 7 +- src/common/connection_handlers.py | 28 +- src/common/defs.py | 2 +- src/common/events.py | 5 +- src/common/gajim.py | 5 + src/common/helpers.py | 10 +- src/common/jingle.py | 1165 ++++++++++ src/common/meta.py | 36 + src/common/optparser.py | 17 + src/common/xmpp/protocol.py | 7 + src/common/xmpp/simplexml.py | 3 + src/common/zeroconf/client_zeroconf.py | 10 +- src/common/zeroconf/connection_zeroconf.py | 4 +- src/config.py | 8 +- src/conversation_textview.py | 9 +- src/dataforms_widget.py | 4 +- src/dialogs.py | 301 ++- src/features_window.py | 7 + src/gajim.py | 157 +- src/groupchat_control.py | 60 +- src/gui_menu_builder.py | 476 ++++ src/message_control.py | 2 +- src/message_window.py | 26 + src/roster_window.py | 552 +---- src/systray.py | 2 +- src/vcard.py | 16 +- 179 files changed, 49776 insertions(+), 43829 deletions(-) diffs (truncated from 214168 to 300 lines): diff -r 942f1c3a1d95 -r 4f29e7a58d9c ChangeLog --- a/ChangeLog Thu Oct 15 21:17:53 2009 +0200 +++ b/ChangeLog Sat Oct 31 13:46:10 2009 +0100 @@ -1,3 +1,34 @@ +Gajim 0.12.5 (08 August 2009) + + * Don't depend on GTK 2.14 + +Gajim 0.12.4 (07 August 2009) + + * Fix History manager + * Fix file transfer proxy discovering at connection + * Improve filetransfer with IPv6 + * Fix zeroconf when receiving badly encoded info + +Gajim 0.12.3 (12 June 2009) + + * Fix PLAIN authentication (in particular with Gtalk + * fix PEP discovery + +Gajim 0.12.2 (07 June 2009) + + * Better keepalive / ping behaviour + * Fix custom port handling + * Improve error messages handling + * Totem support for played music + * Fix SSL with some servers + * Handle XFCE notification-daemon + * Restore old behaviour of click on systray: left click to open events + * Network manager 0.7 support + * Move logs file under windows to $APPDATA/gajim + * Improve Kerberos support + * Many bugfixes here and there + * Add -c option to history_manager + Gajim 0.12.1 (21 December 2008) * Fix filetransfer diff -r 942f1c3a1d95 -r 4f29e7a58d9c Makefile.am --- a/Makefile.am Thu Oct 15 21:17:53 2009 +0200 +++ b/Makefile.am Sat Oct 31 13:46:10 2009 +0100 @@ -57,3 +57,12 @@ autom4te.cache \ build \ dist + + +test: + python test/runtests.py +.PHONY: test + +doc: + epydoc --config=doc/epydoc.conf +.PHONY: doc diff -r 942f1c3a1d95 -r 4f29e7a58d9c README.html --- a/README.html Thu Oct 15 21:17:53 2009 +0200 +++ b/README.html Sat Oct 31 13:46:10 2009 +0100 @@ -37,8 +37,8 @@ <li>GnomePythonExtras 2.10 or above (aka gnome-python-desktop) so you can avoid compiling trayicon and gtkspell</li> <li>gnome-python-desktop (for GnomeKeyring support)</li> <li>notification-daemon or notify-python (and D-Bus) to get cooler popups</li> -<li>D-Bus running to have gajim-remote working. Some distributions split dbus-x11, which is needed for dbus to work with Gajim. Version >= 0.60 is required.</li> -<li>python-dbus bindings</li> +<li>D-Bus running to have gajim-remote working. Some distributions split dbus-x11, which is needed for dbus to work with Gajim. Version >= 0.80 is required.</li> +<li>python-dbus bindings (>=0.80)</li> <li>python-sexy to have clickable URLs in chat windows</li> <li>python-kerberos to use GSSAPI authentification. Note: version1.1 or higher is required</li> </ul> diff -r 942f1c3a1d95 -r 4f29e7a58d9c configure.ac --- a/configure.ac Thu Oct 15 21:17:53 2009 +0200 +++ b/configure.ac Sat Oct 31 13:46:10 2009 +0100 @@ -1,5 +1,5 @@ AC_INIT([Gajim - A Jabber Instant Messager], - [
0.12.5.6-dev],[http://trac.gajim.org/],[gajim
]) + [
0.12.5.7-dev],[http://trac.gajim.org/],[gajim
]) AC_PREREQ([2.59]) AC_CONFIG_HEADER(config.h) diff -r 942f1c3a1d95 -r 4f29e7a58d9c data/glade/chat_control_popup_menu.glade --- a/data/glade/chat_control_popup_menu.glade Thu Oct 15 21:17:53 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,148 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> -<!--*- mode: xml -*--> -<glade-interface> - <widget class="GtkMenu" id="chat_control_popup_menu"> - <child> - <widget class="GtkImageMenuItem" id="add_to_roster_menuitem"> - <property name="no_show_all">True</property> - <property name="label" translatable="yes">_Add to Roster</property> - <property name="use_underline">True</property> - <signal name="activate" handler="_on_add_to_roster_menuitem_activate"/> - <child internal-child="image"> - <widget class="GtkImage" id="image1372"> - <property name="visible">True</property> - <property name="stock">gtk-add</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="send_file_menuitem"> - <property name="no_show_all">True</property> - <property name="label" translatable="yes">Send _File</property> - <property name="use_underline">True</property> - <signal name="activate" handler="_on_send_file_menuitem_activate"/> - <child internal-child="image"> - <widget class="GtkImage" id="image1371"> - <property name="visible">True</property> - <property name="stock">gtk-save</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="convert_to_groupchat"> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="no_show_all">True</property> - <property name="label" translatable="yes">Invite _Contacts</property> - <property name="use_underline">True</property> - <child internal-child="image"> - <widget class="GtkImage" id="menu-item-image4"> - <property name="visible">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="stock">gtk-missing-image</property> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkSeparatorMenuItem" id="separatormenuitem2"> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="no_show_all">True</property> - </widget> - </child> - <child> - <widget class="GtkCheckMenuItem" id="toggle_gpg_menuitem"> - <property name="visible">True</property> - <property name="label" translatable="yes">Toggle Open_PGP Encryption</property> - <property name="use_underline">True</property> - <signal name="activate" handler="_on_toggle_gpg_menuitem_activate"/> - </widget> - </child> - <child> - <widget class="GtkCheckMenuItem" id="toggle_e2e_menuitem"> - <property name="visible">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="label" translatable="yes">Toggle End to End Encryption</property> - <property name="use_underline">True</property> - <signal name="activate" handler="_on_toggle_e2e_menuitem_activate"/> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="otr_submenu"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="label" translatable="yes">Off-the-Record Encryption</property> - <property name="use_underline">True</property> - <child> - <widget class="GtkMenu" id="otr_submenu_menu"> - <child> - <widget class="GtkMenuItem" id="otr_settings_menuitem"> - <property name="visible">True</property> - <property name="label" translatable="yes">OTR settings / fingerprint</property> - <property name="use_underline">True</property> - <signal name="activate" handler="_on_otr_settings_menuitem_activate"/> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="smp_otr_menuitem"> - <property name="visible">True</property> - <property name="label" translatable="yes">Authenticate contact</property> - <property name="use_underline">True</property> - <signal name="activate" handler="_on_smp_otr_menuitem_activate"/> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="start_otr_menuitem"> - <property name="visible">True</property> - <property name="label" translatable="yes">Start / Refresh OTR</property> - <property name="use_underline">True</property> - <signal name="activate" handler="_on_start_otr_menuitem_activate"/> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="end_otr_menuitem"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="label" translatable="yes">End OTR </property> - <property name="use_underline">True</property> - <signal name="activate" handler="_on_end_otr_menuitem_activate"/> - </widget> - </child> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkSeparatorMenuItem" id="separatormenuitem1"> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="no_show_all">True</property> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="information_menuitem"> - <property name="no_show_all">True</property> - <property name="label">gtk-info</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="history_menuitem"> - <property name="no_show_all">True</property> - <property name="label" translatable="yes">_History</property> - <property name="use_underline">True</property> - <child internal-child="image"> - <widget class="GtkImage" id="image1370"> - <property name="visible">True</property> - <property name="stock">gtk-justify-fill</property> - <property name="icon_size">1</property> - </widget> - </child> - </widget> - </child> - </widget> -</glade-interface> diff -r 942f1c3a1d95 -r 4f29e7a58d9c data/glade/contact_context_menu.glade --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/glade/contact_context_menu.glade Sat Oct 31 13:46:10 2009 +0100 @@ -0,0 +1,466 @@ +<?xml version="1.0"?> +<glade-interface> + <!-- interface-requires gtk+ 2.16 --> + <!-- interface-naming-policy toplevel-contextual --> + <widget class="GtkMenu" id="contact_context_menu"> + <child> + <widget class="GtkImageMenuItem" id="start_chat_menuitem"> + <property name="label" translatable="yes">Start _Chat</property> + <property name="visible">True</property> + <property name="use_underline">True</property> + <property name="use_stock">False</property> + <child internal-child="image"> + <widget class="GtkImage" id="image2"> + <property name="visible">True</property> + <property name="stock">gtk-jump-to</property> + <property name="icon-size">1</property> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkImageMenuItem" id="send_single_message_menuitem"> + <property name="label" translatable="yes">Send Single _Message...</property> + <property name="visible">True</property> + <property name="use_underline">True</property> + <property name="use_stock">False</property> + <child internal-child="image"> + <widget class="GtkImage" id="image3"> + <property name="visible">True</property> + <property name="stock">gtk-new</property> + <property name="icon-size">1</property> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkImageMenuItem" id="send_file_menuitem"> + <property name="label" translatable="yes">Send _File...</property> + <property name="visible">True</property> + <property name="use_underline">True</property> + <property name="use_stock">False</property> + <child internal-child="image"> + <widget class="GtkImage" id="image4"> + <property name="visible">True</property> + <property name="stock">gtk-save</property> + <property name="icon-size">1</property> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkImageMenuItem" id="invite_menuitem"> + <property name="label" translatable="yes">In_vite to</property> + <property name="visible">True</property> + <property name="use_underline">True</property> + <property name="use_stock">False</property> + <child internal-child="image"> + <widget class="GtkImage" id="image5"> + <property name="visible">True</property> + <property name="stock">gtk-missing-image</property> + <property name="icon-size">1</property> + </widget> + </child> + </widget> + </child> + <child>
1
0
0
0
gajim: import Changelog file from 0.12 branch. Fixes #5380
by Yann Leboulanger
30 Oct '09
30 Oct '09
changeset b82bcd6c8d7f in /home/hg/repos/gajim
details:http://hg.gajim.org/gajim?cmd=changeset;node=b82bcd6c8d7f
description: import Changelog file from 0.12 branch. Fixes #5380 diffstat: ChangeLog | 31 +++++++++++++++++++++++++++++++ 1 files changed, 31 insertions(+), 0 deletions(-) diffs (38 lines): diff -r 5d41044f1cc3 -r b82bcd6c8d7f ChangeLog --- a/ChangeLog Fri Oct 30 20:04:20 2009 +0100 +++ b/ChangeLog Fri Oct 30 20:08:33 2009 +0100 @@ -1,3 +1,34 @@ +Gajim 0.12.5 (08 August 2009) + + * Don't depend on GTK 2.14 + +Gajim 0.12.4 (07 August 2009) + + * Fix History manager + * Fix file transfer proxy discovering at connection + * Improve filetransfer with IPv6 + * Fix zeroconf when receiving badly encoded info + +Gajim 0.12.3 (12 June 2009) + + * Fix PLAIN authentication (in particular with Gtalk + * fix PEP discovery + +Gajim 0.12.2 (07 June 2009) + + * Better keepalive / ping behaviour + * Fix custom port handling + * Improve error messages handling + * Totem support for played music + * Fix SSL with some servers + * Handle XFCE notification-daemon + * Restore old behaviour of click on systray: left click to open events + * Network manager 0.7 support + * Move logs file under windows to $APPDATA/gajim + * Improve Kerberos support + * Many bugfixes here and there + * Add -c option to history_manager + Gajim 0.12.1 (21 December 2008) * Fix filetransfer
1
0
0
0
gajim: fix variable name. Fixes #5379
by Yann Leboulanger
30 Oct '09
30 Oct '09
changeset 5d41044f1cc3 in /home/hg/repos/gajim
details:http://hg.gajim.org/gajim?cmd=changeset;node=5d41044f1cc3
description: fix variable name. Fixes #5379 diffstat: src/groupchat_control.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 5d5f16e7d63b -r 5d41044f1cc3 src/groupchat_control.py --- a/src/groupchat_control.py Fri Oct 30 09:51:16 2009 +0100 +++ b/src/groupchat_control.py Fri Oct 30 20:04:20 2009 +0100 @@ -632,7 +632,7 @@ self.banner_status_label.set_markup(subject_text) - def prepare_context_menu(self, hide_buttonbar_entries=False): + def prepare_context_menu(self, hide_buttonbar_items=False): '''sets sensitivity state for configure_room''' xml = gtkgui_helpers.get_glade('gc_control_popup_menu.glade') menu = xml.get_widget('gc_control_popup_menu')
1
0
0
0
← Newer
1
2
3
4
5
...
18
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Results per page:
10
25
50
100
200