Merge changes from default branch into refactoring branch

Hg: changed data/pixmaps/mic_active.png
This commit is contained in:
Stephan Erb 2009-11-11 23:37:46 +01:00
commit 022003239d
20 changed files with 151 additions and 41 deletions

View File

@ -465,7 +465,7 @@
<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 menu of advanced functions (Alt+A)</property>
<property name="tooltip" translatable="yes">Show a menu of advanced functions (Alt+D)</property>
<property name="relief">none</property>
<property name="focus_on_click">False</property>
<child>
@ -934,7 +934,7 @@
<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 menu of advanced functions (Alt+A)</property>
<property name="tooltip" translatable="yes">Show a menu of advanced functions (Alt+D)</property>
<property name="relief">none</property>
<property name="focus_on_click">False</property>
<child>

View File

@ -1777,7 +1777,7 @@ $T will be replaced by auto-not-available timeout</property>
<property name="receives_default">True</property>
<property name="xalign">0</property>
<property name="color">#000000000000</property>
<signal name="color_set" handler="on_incoming_msg_colorbutton_color_set"/>
<signal name="color_set" handler="on_incoming_nick_colorbutton_color_set"/>
</widget>
<packing>
<property name="expand">False</property>

View File

@ -85,12 +85,42 @@
</child>
<child>
<widget class="GtkButton" id="accept_button">
<property name="label" translatable="yes">gtk-ok</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="on_accept_button_clicked"/>
<child>
<widget class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="spacing">3</property>
<child>
<widget class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="xalign">1</property>
<property name="stock">gtk-ok</property>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="accept_button_label">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_OK</property>
<property name="use_underline">True</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>

BIN
data/pixmaps/cam_active.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 988 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 963 B

BIN
data/pixmaps/mic_active.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 788 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 773 B

View File

@ -65,6 +65,7 @@ opts = {
'excludes': [
'docutils'
],
'optimize': 2,
}
}

View File

@ -1213,10 +1213,22 @@ class ChatControl(ChatControlBase):
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
# add a special img
path_to_img = os.path.join(gajim.DATA_DIR, 'pixmaps',
'mic_inactive.png')
img = gtk.Image()
img.set_from_file(path_to_img)
self._audio_button.set_image(img)
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
# add a special img
path_to_img = os.path.join(gajim.DATA_DIR, 'pixmaps',
'cam_inactive.png')
img = gtk.Image()
img.set_from_file(path_to_img)
self._video_button.set_image(img)
self._send_file_button = self.xml.get_widget('send_file_button')
# add a special img for send file button
@ -1818,31 +1830,43 @@ class ChatControl(ChatControlBase):
def on_audio_button_toggled(self, widget):
if widget.get_active():
path_to_img = os.path.join(gajim.DATA_DIR, 'pixmaps',
'mic_active.png')
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:
path_to_img = os.path.join(gajim.DATA_DIR, 'pixmaps',
'mic_inactive.png')
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)
img = self._audio_button.get_property('image')
img.set_from_file(path_to_img)
def on_video_button_toggled(self, widget):
if widget.get_active():
path_to_img = os.path.join(gajim.DATA_DIR, 'pixmaps',
'cam_active.png')
if self.video_state == self.JINGLE_STATE_AVAILABLE:
sid = gajim.connections[self.account].startVideoIP(
self.contact.get_full_jid())
self.set_video_state('connecting', sid)
else:
path_to_img = os.path.join(gajim.DATA_DIR, 'pixmaps',
'cam_inactive.png')
session = gajim.connections[self.account].get_jingle_session(
self.contact.get_full_jid(), self.video_sid)
if session:
content = session.get_content('video')
if content:
session.remove_content(content.creator, content.name)
img = self._video_button.get_property('image')
img.set_from_file(path_to_img)
def _toggle_gpg(self):
if not self.gpg_is_active and not self.contact.keyID:

View File

@ -98,6 +98,28 @@ class StandardChatCommands(CommandContainer):
raise CommandError(_('Command is not supported for zeroconf accounts'))
gajim.connections[self.account].sendPing(self.contact)
@command('audio')
@documentation(_("Toggle audio session"))
def audio(self):
if self.audio_state == self.JINGLE_STATE_NOT_AVAILABLE:
raise CommandError(_("Video sessions are not available"))
else:
# A state of an audio session is toggled by inverting a state of the
# appropriate button.
state = self._audio_button.get_active()
self._audio_button.set_active(not state)
@command('video')
@documentation(_("Toggle video session"))
def video(self):
if self.video_state == self.JINGLE_STATE_NOT_AVAILABLE:
raise CommandError(_("Video sessions are not available"))
else:
# A state of a video session is toggled by inverting a state of the
# appropriate button.
state = self._video_button.get_active()
self._video_button.set_active(not state)
class StandardPrivateChatCommands(CommandContainer):
"""
This command container contains standard command which are unique to a

View File

@ -172,7 +172,7 @@ class AbstractClientCaps(object):
def _is_hash_valid(self, identities, features, dataforms):
''' To be implemented by subclassess '''
raise NotImplementedError()
class ClientCaps(AbstractClientCaps):
''' The current XEP-115 implementation '''
@ -252,7 +252,7 @@ class CapsCache(object):
# another object, and we will have plenty of identical long
# strings. therefore we can cache them
__names = {}
def __init__(self, hash_method, hash_, logger):
# cached into db
self.hash_method = hash_method

View File

@ -777,7 +777,10 @@ class Connection(ConnectionHandlers):
self.server_resource = con.Resource
if gajim.config.get_per('accounts', self.name, 'anonymous_auth'):
# Get jid given by server
old_jid = gajim.get_jid_from_account(self.name)
gajim.config.set_per('accounts', self.name, 'name', con.User)
new_jid = gajim.get_jid_from_account(self.name)
self.dispatch('NEW_JID', (old_jid, new_jid))
if auth:
self.last_io = gajim.idlequeue.current_time()
self.connected = 2
@ -1298,7 +1301,7 @@ class Connection(ConnectionHandlers):
# chatstates - if peer supports xep85 or xep22, send chatstates
# please note that the only valid tag inside a message containing a <body>
# tag is the active event
if chatstate is not None:
if chatstate is not None and contact:
if ((composing_xep == 'XEP-0085' or not composing_xep) \
and composing_xep != 'asked_once') or \
contact.supports(common.xmpp.NS_CHATSTATES):
@ -1327,7 +1330,8 @@ class Connection(ConnectionHandlers):
# XEP-0184
if msgtxt and gajim.config.get_per('accounts', self.name,
'request_receipt') and contact.supports(common.xmpp.NS_RECEIPTS):
'request_receipt') and contact and contact.supports(
common.xmpp.NS_RECEIPTS):
msg_iq.setTag('request', namespace=common.xmpp.NS_RECEIPTS)
if session:
@ -1576,8 +1580,8 @@ class Connection(ConnectionHandlers):
to_whom_jid = jid
if resource:
to_whom_jid += '/' + resource
iq = common.xmpp.Iq(to=to_whom_jid, typ='get', queryNS=\
common.xmpp.NS_TIME_REVISED)
iq = common.xmpp.Iq(to=to_whom_jid, typ='get')
iq.addChild('time', namespace=common.xmpp.NS_TIME_REVISED)
id_ = self.connection.getAnID()
iq.setID(id_)
if groupchat_jid:

View File

@ -73,7 +73,7 @@ class CommonContact(XMPPEntity):
def get_shown_name(self):
raise NotImplementedError
def supports(self, requested_feature):
'''
Returns True if the contact has advertised to support the feature
@ -297,6 +297,9 @@ class Contacts:
def get_jid_list(self, account):
return self._accounts[account].contacts.get_jid_list()
def change_contact_jid(self, old_jid, new_jid, account):
return self._accounts[account].change_contact_jid(old_jid, new_jid)
def get_highest_prio_contact_from_contacts(self, contacts):
if not contacts:
return None
@ -486,9 +489,17 @@ class Contacts_New():
if group in contacts[0].groups:
group_contacts += contacts
return group_contacts
def change_contact_jid(self, old_jid, new_jid):
if old_jid not in self._contacts:
return
self._contacts[new_jid] = []
for _contact in self._contacts[old_jid]:
_contact.jid = new_jid
self._contacts[new_jid].append(_contact)
del self._contacts[old_jid]
class GC_Contacts():
def __init__(self):

View File

@ -286,7 +286,10 @@ class HostTester(Socks5, IdleObject):
elif self.state == 3:
log.debug('Host authenticated to %s:%s' % (self.host, self.port))
self.on_success()
self.disconnect()
self.state += 1
else:
assert False, 'unexpected state: %d' % self.state
def do_connect(self):
try:
@ -402,7 +405,10 @@ class ReceiverTester(Socks5, IdleObject):
return
log.debug('Receiver authenticated to %s:%s' % (self.host, self.port))
self.on_success()
self.disconnect()
self.state += 1
else:
assert False, 'unexpected state: %d' % self.state
def do_connect(self):
try:

View File

@ -41,14 +41,6 @@ except ImportError:
USE_LIBASYNCNS = False
log.debug("Import of libasyncns-python failed, getaddrinfo will block", exc_info=True)
# FIXME: Remove these prints before release, replace with a warning dialog.
print >> sys.stderr, "=" * 79
print >> sys.stderr, "libasyncns-python not installed which means:"
print >> sys.stderr, " - nslookup will be used for SRV and TXT requests"
print >> sys.stderr, " - getaddrinfo will block"
print >> sys.stderr, "libasyncns-python can be found at https://launchpad.net/libasyncns-python"
print >> sys.stderr, "=" * 79
def get_resolver(idlequeue):
if USE_LIBASYNCNS:

View File

@ -2860,7 +2860,7 @@ class RosterItemExchangeWindow:
self.window = self.xml.get_widget('roster_item_exchange_window')
# Add Widgets.
for widget_to_add in ['cancel_button', 'accept_button', 'type_label',
for widget_to_add in ['accept_button_label', 'type_label',
'body_scrolledwindow', 'body_textview', 'items_list_treeview']:
self.__dict__[widget_to_add] = self.xml.get_widget(widget_to_add)
@ -2928,9 +2928,7 @@ class RosterItemExchangeWindow:
model.set(iter, 0, True, 1, jid, 2, name, 3, groups)
# Change label for accept_button to action name instead of 'OK'.
accept_button_label = self.accept_button.get_children()[0].\
get_children()[0].get_children()[1]
accept_button_label.set_label(_('Add'))
self.accept_button_label.set_label(_('Add'))
elif action == 'modify':
for jid in self.exchange_list:
groups = ''
@ -2961,9 +2959,7 @@ class RosterItemExchangeWindow:
model.set(iter, 0, True, 1, jid, 2, name, 3, groups)
# Change label for accept_button to action name instead of 'OK'.
accept_button_label = self.accept_button.get_children()[0].\
get_children()[0].get_children()[1]
accept_button_label.set_label(_('Modify'))
self.accept_button_label.set_label(_('Modify'))
elif action == 'delete':
for jid in self.exchange_list:
groups = ''
@ -2987,9 +2983,7 @@ class RosterItemExchangeWindow:
model.set(iter, 0, True, 1, jid, 2, name, 3, groups)
# Change label for accept_button to action name instead of 'OK'.
accept_button_label = self.accept_button.get_children()[0].\
get_children()[0].get_children()[1]
accept_button_label.set_label(_('Delete'))
self.accept_button_label.set_label(_('Delete'))
if show_dialog:
self.window.show_all()

View File

@ -263,6 +263,14 @@ class Interface:
if self.remote_ctrl:
self.remote_ctrl.raise_signal('AccountPresence', (show, account))
def handle_event_new_jid(self, account, data):
#('NEW_JID', account, (old_jid, new_jid))
'''
This event is raised when our JID changed (most probably because we use
anonymous account. We update contact and roster entry in this case.
'''
self.roster.rename_self_contact(data[0], data[1], account)
def edit_own_details(self, account):
jid = gajim.get_jid_from_account(account)
if 'profile' not in self.instances[account]:
@ -1512,6 +1520,7 @@ class Interface:
def handle_event_signed_in(self, account, empty):
'''SIGNED_IN event is emitted when we sign in, so handle it'''
# ('SIGNED_IN', account, ())
# block signed in notifications for 30 seconds
gajim.block_signed_in_notifications[account] = True
self.roster.set_actions_menu_needs_rebuild()
@ -1998,6 +2007,7 @@ class Interface:
'INFORMATION': [self.handle_event_information],
'ERROR_ANSWER': [self.handle_event_error_answer],
'STATUS': [self.handle_event_status],
'NEW_JID': [self.handle_event_new_jid],
'NOTIFY': [self.handle_event_notify],
'MSGERROR': [self.handle_event_msgerror],
'MSGSENT': [self.handle_event_msgsent],

View File

@ -473,7 +473,7 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
tag.href = href
tag.type_ = type_ # to be used by the URL handler
tag.connect('event', self.textview.html_hyperlink_handler, 'url', href)
tag.set_property('foreground', '#0000ff')
tag.set_property('foreground', gajim.config.get('urlmsgcolor'))
tag.set_property('underline', pango.UNDERLINE_SINGLE)
tag.is_anchor = True
if title:

View File

@ -103,7 +103,7 @@ class MessageWindow(object):
'<Control>l', '<Control>L', '<Control>n', '<Control>u',
'<Control>b', '<Control><Shift>Tab', '<Control>Tab', '<Control>F4',
'<Control>w', '<Control>Page_Up', '<Control>Page_Down', '<Alt>Right',
'<Alt>Left', '<Alt>a', '<Alt>c', '<Alt>m', '<Alt>t', 'Escape'] + \
'<Alt>Left', '<Alt>d', '<Alt>c', '<Alt>m', '<Alt>t', 'Escape'] + \
['<Alt>'+str(i) for i in xrange(10)]
accel_group = gtk.AccelGroup()
for key in keys:
@ -165,6 +165,8 @@ class MessageWindow(object):
return
if old_jid not in self._controls[account]:
return
if old_jid == new_jid:
return
self._controls[account][new_jid] = self._controls[account][old_jid]
del self._controls[account][old_jid]
@ -403,7 +405,7 @@ class MessageWindow(object):
control.chat_buttons_set_visible(not control.hide_chat_buttons)
elif keyval == gtk.keysyms.m: # ALT + M show emoticons menu
control.show_emoticons_menu()
elif keyval == gtk.keysyms.a: # ALT + A show actions menu
elif keyval == gtk.keysyms.d: # ALT + D show actions menu
control.on_actions_button_clicked(control.actions_button)
elif control.type_id == message_control.TYPE_GC and \
keyval == gtk.keysyms.t: # ALT + t

View File

@ -134,11 +134,10 @@ class RosterWindow:
return group_iter
def _get_self_contact_iter(self, jid, account, model=None):
def _get_self_contact_iter(self, account, model=None):
''' Return the gtk.TreeIter of SelfContact or None if not found.
Keyword arguments:
jid -- the jid of SelfContact
account -- the account of SelfContact
model -- the data model (default TreeFilterModel)
@ -153,8 +152,8 @@ class RosterWindow:
while iterC:
if model[iterC][C_TYPE] != 'self_contact':
break
iter_jid = model[iterC][C_JID]
if iter_jid and jid == iter_jid.decode('utf-8'):
iter_account = model[iterC][C_ACCOUNT]
if account == iter_account.decode('utf-8'):
return iterC
iterC = model.iter_next(iterC)
return None
@ -177,7 +176,7 @@ class RosterWindow:
return []
if jid == gajim.get_jid_from_account(account):
contact_iter = self._get_self_contact_iter(jid, account, model)
contact_iter = self._get_self_contact_iter(account, model)
if contact_iter:
return [contact_iter]
else:
@ -783,6 +782,21 @@ class RosterWindow:
return True
def rename_self_contact(self, old_jid, new_jid, account):
'''Rename the self_contact jid
Keyword arguments:
old_jid -- our old jid
new_jid -- our new jid
account -- the corresponding account.
'''
gajim.contacts.change_contact_jid(old_jid, new_jid, account)
self_iter = self._get_self_contact_iter(account, model=self.model)
if not self_iter:
return
self.model[self_iter][C_JID] = new_jid
self.draw_contact(new_jid, account)
def add_groupchat(self, jid, account, status=''):
'''Add groupchat to roster and draw it.
Return the added contact instance.