From c8cae710995cfd1e9a55bacb677f7f7bb31f55cd Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Thu, 14 Feb 2008 02:20:07 +0000 Subject: [PATCH] merged trunk --- data/glade/preferences_window.glade | 1110 +++++++++++++-------------- src/chat_control.py | 2 +- src/common/config.py | 1 + src/common/connection.py | 40 +- src/common/connection_handlers.py | 41 +- src/config.py | 14 +- src/dialogs.py | 2 +- src/features_window.py | 5 +- src/gajim-remote.py | 82 +- src/gajim.py | 12 +- src/groupchat_control.py | 15 +- src/message_window.py | 16 +- src/roster_window.py | 8 +- 13 files changed, 686 insertions(+), 662 deletions(-) diff --git a/data/glade/preferences_window.glade b/data/glade/preferences_window.glade index c4e2ebea9..697d0e711 100644 --- a/data/glade/preferences_window.glade +++ b/data/glade/preferences_window.glade @@ -130,37 +130,61 @@ 6 6 - - 50 + True - Detached roster with detached chats -Detached roster with single chat -Single window for everything -Detached roster with chat grouped by account -Detached roster with chat grouped by type - + 0 + 1 + _Window behavior: + True + one_window_type_combobox + + + 1 + 2 + GTK_FILL + + + + + True + 1 2 - 1 - 2 - + + True + If not disabled, Gajim will replace ascii smilies like ':)' with equivalent animated or static graphical emoticons + + + True + 0 + 1 + Emoticons: + + + + + GTK_FILL + + + + True - If checked, Gajim will highlight spelling errors in input fields of chat windows. If no language is explicitly set via right click on the input field, the default language will be used for this contact or group chat. - _Highlight misspelled words + Hide all buttons in chat windows + _Make message windows compact True 0 True - + 2 - 4 - 5 + 2 + 3 GTK_FILL @@ -183,62 +207,38 @@ Detached roster with chat grouped by type - + True - Hide all buttons in chat windows - _Make message windows compact + If checked, Gajim will highlight spelling errors in input fields of chat windows. If no language is explicitly set via right click on the input field, the default language will be used for this contact or group chat. + _Highlight misspelled words True 0 True - + 2 - 2 - 3 + 4 + 5 GTK_FILL - + + 50 True - If not disabled, Gajim will replace ascii smilies like ':)' with equivalent animated or static graphical emoticons - - - True - 0 - 1 - Emoticons: - - - - - GTK_FILL - - - - - True - + Detached roster with detached chats +Detached roster with single chat +Single window for everything +Detached roster with chat grouped by account +Detached roster with chat grouped by type + 1 2 - - - - - True - 0 - 1 - _Window behavior: - True - one_window_type_combobox - - 1 2 - GTK_FILL @@ -478,51 +478,17 @@ Show only in roster True 6 - + True - 6 - True - - - True - True - Play _sounds - True - 0 - True - - - - - - 5 - - - True - _Player: - True - soundplayer_entry - - - - - True - True - - - - 1 - - - - - 1 - - + True + Play _sounds + True + 0 + True + False - False @@ -657,7 +623,7 @@ Show only in roster 6 6 - + True All chat states Composing only @@ -666,23 +632,8 @@ Disabled 1 2 - - - - - True - Gajim can send and receive meta-information related to a conversation you may have with a contact. Here you can specify which chatstates you want to send to the other party. - - - True - 0 - _Send chat state notifications: - True - - - - - GTK_FILL + 1 + 2 @@ -705,7 +656,24 @@ Disabled - + + True + Gajim can send and receive meta-information related to a conversation you may have with a contact. Here you can specify which chatstates you want to send to the other party. + + + True + 0 + _Send chat state notifications: + True + + + + + GTK_FILL + + + + True All chat states Composing only @@ -714,8 +682,6 @@ Disabled 1 2 - 1 - 2 @@ -759,89 +725,7 @@ Disabled 6 6 - - True - 0 - 1 - Allow others to see your: - True - one_window_type_combobox - - - GTK_FILL - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Tune - True - 0 - True - - - - 2 - 3 - 1 - 2 - GTK_FILL - - - - - True - 0 - 1 - Receive your contact's: - True - True - one_window_type_combobox - - - 1 - 2 - GTK_FILL - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Tune - True - 0 - True - - - - 2 - 3 - GTK_FILL - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Activity - True - 0 - True - - - - 3 - 4 - GTK_FILL - - - - + True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK @@ -849,11 +733,13 @@ Disabled True 0 True - + 1 2 + 1 + 2 GTK_FILL @@ -877,7 +763,7 @@ Disabled - + True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK @@ -885,16 +771,96 @@ Disabled True 0 True - + 1 2 + GTK_FILL + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Activity + True + 0 + True + + + + 3 + 4 + GTK_FILL + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Tune + True + 0 + True + + + + 2 + 3 + GTK_FILL + + + + + True + 0 + 1 + Receive your contact's: + True + True + one_window_type_combobox + + 1 2 GTK_FILL + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Tune + True + 0 + True + + + + 2 + 3 + 1 + 2 + GTK_FILL + + + + + True + 0 + 1 + Allow others to see your: + True + one_window_type_combobox + + + GTK_FILL + + @@ -957,33 +923,90 @@ Disabled 12 6 - + True True - The auto not available status message. If empty, Gajim will not change the current status message - + If checked, Gajim will change status to Away when the computer is unused. + _Away after: + True + 0 + True + - 3 - 4 - 1 - 2 + GTK_FILL - + True True - The auto away status message. If empty, Gajim will not change the current status message - + If checked, Gajim will change status to Not Available when the computer has not been used even longer + _Not available after: + True + 0 + True + - 3 - 4 + 1 + 2 + GTK_FILL + + + True + 0 + minutes + + + 2 + 3 + GTK_FILL + + + + + + True + 0 + minutes + + + 2 + 3 + 1 + 2 + GTK_FILL + + + + + + True + 1 + 0 + + + 50 + True + True + 12 1 720 1 10 10 + 1 + + + + + + 1 + 2 + GTK_FILL + GTK_FILL + + True @@ -1010,87 +1033,30 @@ Disabled - - True - 1 - 0 - - - 50 - True - True - 12 1 720 1 10 10 - 1 - - - - - - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - 0 - minutes - - - 2 - 3 - 1 - 2 - GTK_FILL - - - - - - True - 0 - minutes - - - 2 - 3 - GTK_FILL - - - - - + True True - If checked, Gajim will change status to Not Available when the computer has not been used even longer - _Not available after: - True - 0 - True - + The auto away status message. If empty, Gajim will not change the current status message + - 1 - 2 - GTK_FILL + 3 + 4 - + True True - If checked, Gajim will change status to Away when the computer is unused. - _Away after: - True - 0 - True - + The auto not available status message. If empty, Gajim will not change the current status message + - GTK_FILL + 3 + 4 + 1 + 2 @@ -1250,46 +1216,6 @@ Disabled - - - True - True - GTK_POLICY_NEVER - GTK_POLICY_NEVER - GTK_SHADOW_IN - - - True - True - 3 - GTK_WRAP_WORD - - - - - 1 - 2 - GTK_FILL - - - - - True - True - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - GTK_SHADOW_IN - - - True - True - False - - - - - - True @@ -1328,6 +1254,46 @@ Disabled GTK_FILL + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + + + True + True + False + + + + + + + + + True + True + GTK_POLICY_NEVER + GTK_POLICY_NEVER + GTK_SHADOW_IN + + + True + True + 3 + GTK_WRAP_WORD + + + + + 1 + 2 + GTK_FILL + + @@ -1390,14 +1356,14 @@ Disabled - + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Chat message: + True + 0 - GTK_FILL - GTK_FILL + 1 + 2 @@ -1418,14 +1384,14 @@ Disabled - + True - True - 0 + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Chat message: - 1 - 2 + GTK_FILL + GTK_FILL @@ -1475,18 +1441,62 @@ Disabled - + True - 0 - T_heme: + True + If checked, Gajim will use protocol-specific status icons. (eg. A contact from MSN will have the equivalent msn icon for status online, away, busy, etc...) + Use _transports icons True - theme_combobox + 0 + True + + 1 + 3 + 2 + 3 + + + + + True + + + + 1 + 2 + 1 + 2 GTK_FILL GTK_FILL + + + True + 0 + Status _iconset: + True + iconset_combobox + + + 1 + 2 + GTK_FILL + GTK_FILL + + + + + True + + + + 1 + 2 + + True @@ -1505,62 +1515,18 @@ Disabled - - True - - - - 1 - 2 - - - - + True 0 - Status _iconset: + T_heme: True - iconset_combobox + theme_combobox - 1 - 2 GTK_FILL GTK_FILL - - - True - - - - 1 - 2 - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - True - If checked, Gajim will use protocol-specific status icons. (eg. A contact from MSN will have the equivalent msn icon for status online, away, busy, etc...) - Use _transports icons - True - 0 - True - - - - 1 - 3 - 2 - 3 - - @@ -1599,6 +1565,135 @@ Disabled 4 12 6 + + + True + 0 + _Incoming message: + True + GTK_JUSTIFY_CENTER + True + incoming_msg_colorbutton + + + GTK_FILL + + + + + + True + True + True + True + True + 0 + + + + 1 + 2 + + + + + + + True + 0 + _Outgoing message: + True + GTK_JUSTIFY_CENTER + True + outgoing_msg_colorbutton + + + 2 + 3 + GTK_FILL + + + + + + True + True + 0 + + + + 3 + 4 + GTK_FILL + + + + + + True + 0 + _Status message: + True + GTK_JUSTIFY_CENTER + True + status_msg_colorbutton + + + 1 + 2 + GTK_FILL + + + + + + True + True + 0 + + + + 1 + 2 + 1 + 2 + + + + + + + True + 0 + _URL highlight: + True + url_msg_colorbutton + + + 2 + 3 + 1 + 2 + GTK_FILL + + + + + + True + True + 0 + + + + 3 + 4 + 1 + 2 + GTK_FILL + + + True @@ -1667,135 +1762,6 @@ Disabled GTK_FILL - - - True - True - 0 - - - - 3 - 4 - 1 - 2 - GTK_FILL - - - - - - True - 0 - _URL highlight: - True - url_msg_colorbutton - - - 2 - 3 - 1 - 2 - GTK_FILL - - - - - - True - True - 0 - - - - 1 - 2 - 1 - 2 - - - - - - - True - 0 - _Status message: - True - GTK_JUSTIFY_CENTER - True - status_msg_colorbutton - - - 1 - 2 - GTK_FILL - - - - - - True - True - 0 - - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - _Outgoing message: - True - GTK_JUSTIFY_CENTER - True - outgoing_msg_colorbutton - - - 2 - 3 - GTK_FILL - - - - - - True - True - True - True - True - 0 - - - - 1 - 2 - - - - - - - True - 0 - _Incoming message: - True - GTK_JUSTIFY_CENTER - True - incoming_msg_colorbutton - - - GTK_FILL - - - @@ -1880,56 +1846,16 @@ Custom 12 6 - - True - 0 - _Browser: - True - custom_browser_entry - - - GTK_FILL - - - - - - True - 0 - _Mail client: - True - custom_mail_client_entry - - - 1 - 2 - GTK_FILL - - - - - + True True - - - - 1 - 2 - 1 - 2 - - - - - - True - True - + 1 2 + 2 + 3 @@ -1949,16 +1875,56 @@ Custom - + True True - + 1 2 - 2 - 3 + + + + + + True + True + + + + 1 + 2 + 1 + 2 + + + + + + True + 0 + _Mail client: + True + custom_mail_client_entry + + + 1 + 2 + GTK_FILL + + + + + + True + 0 + _Browser: + True + custom_browser_entry + + + GTK_FILL @@ -2022,19 +1988,18 @@ Custom 6 6 - + True True - If checked, Gajim log GPG or E2E encrypted messages. However, when using E2E encryption the remote site has to agree on logging. If the other side has declined logging, your messages will NOT be logged. - Log _encrypted chat session + If checked, Gajim will ignore incoming events from unauthorized contacts. Use with caution, because it blocks all messages from any contact that is not in the roster + _Ignore events from contacts not in the roster True 0 True - + - 2 - 3 + GTK_FILL @@ -2054,18 +2019,19 @@ Custom - + True True - If checked, Gajim will ignore incoming events from unauthorized contacts. Use with caution, because it blocks all messages from any contact that is not in the roster - _Ignore events from contacts not in the roster + If checked, Gajim log GPG or E2E encrypted messages. However, when using E2E encryption the remote site has to agree on logging. If the other side has declined logging, your messages will NOT be logged. + Log _encrypted chat session True 0 True - + - GTK_FILL + 2 + 3 diff --git a/src/chat_control.py b/src/chat_control.py index a4faa3f6c..45963855c 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -281,7 +281,7 @@ class ChatControlBase(MessageControl): self.conv_textview.tv.show() self._paint_banner() - # For JEP-0172 + # For XEP-0172 self.user_nick = None self.smooth = True diff --git a/src/common/config.py b/src/common/config.py index 9eda27542..a8a0e6603 100644 --- a/src/common/config.py +++ b/src/common/config.py @@ -296,6 +296,7 @@ class Config: 'keep_alives_enabled': [ opt_bool, True], # send keepalive every N seconds of inactivity 'keep_alive_every_foo_secs': [ opt_int, 55 ], + 'time_for_keep_alive_answer': [ opt_int, 20, _('How many seconds to wait for the answer of keepalive packet before we try to reconnect.') ], # try for 2 minutes before giving up (aka. timeout after those seconds) 'try_connecting_for_foo_secs': [ opt_int, 60 ], 'http_auth': [opt_str, 'ask'], # yes, no, ask diff --git a/src/common/connection.py b/src/common/connection.py index 9606afc36..2c1177bbc 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -705,11 +705,21 @@ class Connection(ConnectionHandlers): return common.xmpp.features_nb.getPrivacyLists(self.connection) - def sendPing(self, pingTo): + def sendPing(self, pingTo=None): + '''Send XMPP Ping (XEP-0199) request. If pingTo is not set, ping is sent + to server to detect connection failure at application level.''' if not self.connection: return - iq = common.xmpp.Iq('get', to = pingTo.get_full_jid()) + id = self.connection.getAnID() + if pingTo: + to = pingTo.get_full_jid() + self.dispatch('PING_SENT', (pingTo)) + else: + to = gajim.config.get_per('accounts', self.name, 'hostname') + self.awaiting_xmpp_ping_id = id + iq = common.xmpp.Iq('get', to=to) iq.addChild(name = 'ping', namespace = common.xmpp.NS_PING) + iq.setID(id) def _on_response(resp): timePong = time_time() if not common.xmpp.isResultNode(resp): @@ -717,9 +727,13 @@ class Connection(ConnectionHandlers): return timeDiff = round(timePong - timePing,2) self.dispatch('PING_REPLY', (pingTo, timeDiff)) - self.dispatch('PING_SENT', (pingTo)) - timePing = time_time() - self.connection.SendAndCallForResponse(iq, _on_response) + if pingTo: + timePing = time_time() + self.connection.SendAndCallForResponse(iq, _on_response) + else: + self.connection.send(iq) + gajim.idlequeue.set_alarm(self.check_keepalive, gajim.config.get_per( + 'accounts', self.name, 'time_for_keep_alive_answer')) def get_active_default_lists(self): if not self.connection: @@ -877,7 +891,7 @@ class Connection(ConnectionHandlers): self.connection = con if not self.connection: return - self.connection.set_send_timeout(self.keepalives, self.send_keepalive) + self.connection.set_send_timeout(self.keepalives, self.sendPing) self.connection.onreceive(None) iq = common.xmpp.Iq('get', common.xmpp.NS_PRIVACY, xmlns = '') id = self.connection.getAnID() @@ -922,7 +936,7 @@ class Connection(ConnectionHandlers): if not auto and not show == 'offline': sign_msg = True self.status = msg - if show != 'offline' and not self.connected: + if show != 'offline' and self.connected < 1: # set old_show to requested 'show' in case we need to # recconect before we auth to server self.old_show = show @@ -955,7 +969,7 @@ class Connection(ConnectionHandlers): self.time_to_reconnect = None self._on_disconnected() - elif show != 'offline' and self.connected: + elif show != 'offline' and self.connected > 0: # dont'try to connect, when we are in state 'connecting' if self.connected == 1: return @@ -1257,6 +1271,7 @@ class Connection(ConnectionHandlers): iq.setID(id) if groupchat_jid: self.groupchat_jids[id] = groupchat_jid + self.last_ids.append(id) self.connection.send(iq) def request_os_info(self, jid, resource, groupchat_jid=None): @@ -1277,6 +1292,7 @@ class Connection(ConnectionHandlers): iq.setID(id) if groupchat_jid: self.groupchat_jids[id] = groupchat_jid + self.version_ids.append(id) self.connection.send(iq) def get_settings(self): @@ -1599,10 +1615,10 @@ class Connection(ConnectionHandlers): c.setTagData('reason', reason) self.connection.send(message) - def send_keepalive(self): - # nothing received for the last foo seconds (60 secs by default) - if self.connection: - self.connection.send(' ') + def check_keepalive(self): + if self.awaiting_xmpp_ping_id: + # We haven't got the pong in time, disco and reconnect + self._disconnectedReconnCB() def _reconnect_alarm(self): if self.time_to_reconnect: diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py index 789877a3d..24f6c6575 100644 --- a/src/common/connection_handlers.py +++ b/src/common/connection_handlers.py @@ -426,6 +426,9 @@ class ConnectionBytestream: # if we want to respect xep-0065 we have to check for proxy # activation result in any result iq real_id = unicode(iq_obj.getAttr('id')) + if real_id == self.awaiting_xmpp_ping_id: + self.awaiting_xmpp_ping_id = None + return if real_id[:3] != 'au_': return frm = helpers.get_full_jid_from_iq(iq_obj) @@ -667,8 +670,8 @@ class ConnectionDisco: query = iq.setTag('query') query.setAttr('node','http://gajim.org/caps#' + gajim.version.split('-', 1)[0]) - for f in (common.xmpp.NS_BYTESTREAM, common.xmpp.NS_SI, \ - common.xmpp.NS_FILE, common.xmpp.NS_COMMANDS): + for f in (common.xmpp.NS_BYTESTREAM, common.xmpp.NS_SI, + common.xmpp.NS_FILE, common.xmpp.NS_COMMANDS): feature = common.xmpp.Node('feature') feature.setAttr('var', f) query.addChild(node=feature) @@ -1240,6 +1243,12 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, # keep the latest subscribed event for each jid to prevent loop when we # acknoledge presences self.subscribed_events = {} + # IDs of jabber:iq:last requests + self.last_ids = [] + # IDs of jabber:iq:version requests + self.version_ids = [] + # ID of urn:xmpp:ping requests + self.awaiting_xmpp_ping_id = None # keep track of sessions this connection has with other JIDs self.sessions = {} @@ -1298,15 +1307,21 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, def _ErrorCB(self, con, iq_obj): gajim.log.debug('ErrorCB') - if iq_obj.getQueryNS() == common.xmpp.NS_VERSION: - who = helpers.get_full_jid_from_iq(iq_obj) - jid_stripped, resource = gajim.get_room_and_nick_from_fjid(who) + jid_from = helpers.get_full_jid_from_iq(iq_obj) + jid_stripped, resource = gajim.get_room_and_nick_from_fjid(jid_from) + id = unicode(iq_obj.getID()) + if id in self.version_ids: self.dispatch('OS_INFO', (jid_stripped, resource, '', '')) + self.version_ids.remove(id) return + if id in self.last_ids: + self.dispatch('LAST_STATUS_TIME', (jid_stripped, resource, -1, '')) + self.last_ids.remove(id) + return + if id == self.awaiting_xmpp_ping_id: + self.awaiting_xmpp_ping_id = None errmsg = iq_obj.getErrorMsg() errcode = iq_obj.getErrorCode() - jid_from = helpers.get_full_jid_from_iq(iq_obj) - id = unicode(iq_obj.getID()) self.dispatch('ERROR_ANSWER', (id, jid_from, errmsg, errcode)) def _PrivateCB(self, con, iq_obj): @@ -1393,9 +1408,9 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, qp.setTagData('os', helpers.get_os_info()) self.connection.send(iq_obj) raise common.xmpp.NodeProcessed - + def _LastCB(self, con, iq_obj): - gajim.log.debug('IdleCB') + gajim.log.debug('LastCB') iq_obj = iq_obj.buildReply('result') qp = iq_obj.getTag('query') if not HAS_IDLE: @@ -1405,7 +1420,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, self.connection.send(iq_obj) raise common.xmpp.NodeProcessed - + def _LastResultCB(self, con, iq_obj): gajim.log.debug('LastResultCB') qp = iq_obj.getTag('query') @@ -1421,9 +1436,11 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, del self.groupchat_jids[id] else: who = helpers.get_full_jid_from_iq(iq_obj) + if id in self.last_ids: + self.last_ids.remove(id) jid_stripped, resource = gajim.get_room_and_nick_from_fjid(who) self.dispatch('LAST_STATUS_TIME', (jid_stripped, resource, seconds, status)) - + def _VersionResultCB(self, con, iq_obj): gajim.log.debug('VersionResultCB') client_info = '' @@ -1442,6 +1459,8 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, else: who = helpers.get_full_jid_from_iq(iq_obj) jid_stripped, resource = gajim.get_room_and_nick_from_fjid(who) + if id in self.version_ids: + self.version_ids.remove(id) self.dispatch('OS_INFO', (jid_stripped, resource, client_info, os_info)) def _TimeCB(self, con, iq_obj): diff --git a/src/config.py b/src/config.py index 43ede20f8..7c58705e7 100644 --- a/src/config.py +++ b/src/config.py @@ -298,27 +298,20 @@ class PreferencesWindow: self.auto_popup_away_checkbutton.set_active(st) # sounds - if ((os.name == 'nt') or (sys.platform == 'darwin')): - # if windows, player must not become visible on show_all - soundplayer_hbox = self.xml.get_widget('soundplayer_hbox') - soundplayer_hbox.set_no_show_all(True) if gajim.config.get('sounds_on'): self.xml.get_widget('play_sounds_checkbutton').set_active(True) else: - self.xml.get_widget('soundplayer_hbox').set_sensitive(False) self.xml.get_widget('sounds_scrolledwindow').set_sensitive(False) self.xml.get_widget('browse_sounds_hbox').set_sensitive(False) # sound player player = gajim.config.get('soundplayer') - self.xml.get_widget('soundplayer_entry').set_text(player) if player == '': # only on first time Gajim starts commands = ('aplay', 'play', 'esdplay', 'artsplay') for command in commands: if helpers.is_in_path(command): if command == 'aplay': command += ' -q' - self.xml.get_widget('soundplayer_entry').set_text(command) gajim.config.set('soundplayer', command) break @@ -775,14 +768,9 @@ class PreferencesWindow: def on_play_sounds_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'sounds_on', - [self.xml.get_widget('soundplayer_hbox'), - self.xml.get_widget('sounds_scrolledwindow'), + [self.xml.get_widget('sounds_scrolledwindow'), self.xml.get_widget('browse_sounds_hbox')]) - def on_soundplayer_entry_changed(self, widget): - gajim.config.set('soundplayer', widget.get_text().decode('utf-8')) - gajim.interface.save_config() - def on_sounds_treemodel_row_changed(self, model, path, iter): sound_event = model[iter][3].decode('utf-8') gajim.config.set_per('soundevents', sound_event, 'enabled', diff --git a/src/dialogs.py b/src/dialogs.py index 073c0b78f..7cdcb39cf 100644 --- a/src/dialogs.py +++ b/src/dialogs.py @@ -936,7 +936,7 @@ class AboutDialog: dlg.set_transient_for(gajim.interface.roster.window) dlg.set_name('Gajim') dlg.set_version(gajim.version) - s = u'Copyright © 2003-2007 Gajim Team' + s = u'Copyright © 2003-2008 Gajim Team' dlg.set_copyright(s) copying_file_path = None if os.path.isfile(os.path.join(gajim.defs.docdir, 'COPYING')): diff --git a/src/features_window.py b/src/features_window.py index 59c5f3a1f..a57822959 100644 --- a/src/features_window.py +++ b/src/features_window.py @@ -142,7 +142,10 @@ class FeaturesWindow: selection = widget.get_selection() if not selection: return - path = selection.get_selected_rows()[1][0] + rows = selection.get_selected_rows()[1] + if not rows: + return + path = rows[0] available = self.model[path][1] feature = self.model[path][0].decode('utf-8') text = self.features[feature][1] + '\n' diff --git a/src/gajim-remote.py b/src/gajim-remote.py index 892375a39..6871edbca 100755 --- a/src/gajim-remote.py +++ b/src/gajim-remote.py @@ -59,7 +59,7 @@ BASENAME = 'gajim-remote' class GajimRemote: def __init__(self): - self.argv_len = len(sys.argv) + self.argv_len = len(sys.argv) # define commands dict. Prototype : # { # 'command': [comment, [list of arguments] ] @@ -73,14 +73,14 @@ class GajimRemote: _('Shows a help on specific command'), [ #User gets help for the command, specified by this parameter - (_('command'), + (_('command'), _('show help on command'), False) ] - ], + ], 'toggle_roster_appearance' : [ _('Shows or hides the roster window'), [] - ], + ], 'show_next_pending_event': [ _('Pops up a window with the next pending event'), [] @@ -93,27 +93,27 @@ class GajimRemote: False) ] - ], + ], 'list_accounts': [ _('Prints a list of registered accounts'), [] - ], + ], 'change_status': [ _('Changes the status of account or accounts'), [ #offline, online, chat, away, xa, dnd, invisible should not be translated - (_('status'), _('one of: offline, online, chat, away, xa, dnd, invisible '), True), - (_('message'), _('status message'), False), + (_('status'), _('one of: offline, online, chat, away, xa, dnd, invisible '), True), + (_('message'), _('status message'), False), (_('account'), _('change status of account "account". ' 'If not specified, try to change status of all accounts that have ' '"sync with global status" option set'), False) ] ], - 'open_chat': [ - _('Shows the chat dialog so that you can send messages to a contact'), + 'open_chat': [ + _('Shows the chat dialog so that you can send messages to a contact'), [ ('jid', _('JID of the contact that you want to chat with'), - True), + True), (_('account'), _('if specified, contact is taken from the ' 'contact list of this account'), False) ] @@ -121,7 +121,7 @@ class GajimRemote: 'send_chat_message':[ _('Sends new chat message to a contact in the roster. Both OpenPGP key ' 'and account are optional. If you want to set only \'account\', ' - 'without \'OpenPGP key\', just set \'OpenPGP key\' to \'\'.'), + 'without \'OpenPGP key\', just set \'OpenPGP key\' to \'\'.'), [ ('jid', _('JID of the contact that will receive the message'), True), (_('message'), _('message contents'), True), @@ -134,7 +134,7 @@ class GajimRemote: 'send_single_message':[ _('Sends new single message to a contact in the roster. Both OpenPGP key ' 'and account are optional. If you want to set only \'account\', ' - 'without \'OpenPGP key\', just set \'OpenPGP key\' to \'\'.'), + 'without \'OpenPGP key\', just set \'OpenPGP key\' to \'\'.'), [ ('jid', _('JID of the contact that will receive the message'), True), (_('subject'), _('message subject'), True), @@ -144,9 +144,9 @@ class GajimRemote: (_('account'), _('if specified, the message will be sent ' 'using this account'), False), ] - ], + ], 'send_groupchat_message':[ - _('Sends new message to a groupchat you\'ve joined.'), + _('Sends new message to a groupchat you\'ve joined.'), [ ('room_jid', _('JID of the room that will receive the message'), True), (_('message'), _('message contents'), True), @@ -155,13 +155,13 @@ class GajimRemote: ] ], 'contact_info': [ - _('Gets detailed info on a contact'), + _('Gets detailed info on a contact'), [ ('jid', _('JID of the contact'), True) ] ], 'account_info': [ - _('Gets detailed info on a account'), + _('Gets detailed info on a account'), [ ('account', _('Name of the account'), True) ] @@ -188,8 +188,8 @@ class GajimRemote: ], 'prefs_del': [ _('Deletes a preference item'), - [ - (_('key'), _('name of the preference to be deleted'), True) + [ + (_('key'), _('name of the preference to be deleted'), True) ] ], 'prefs_store': [ @@ -199,7 +199,7 @@ class GajimRemote: ], 'remove_contact': [ _('Removes contact from roster'), - [ + [ ('jid', _('JID of the contact'), True), (_('account'), _('if specified, contact is taken from the ' 'contact list of this account'), False) @@ -208,7 +208,7 @@ class GajimRemote: ], 'add_contact': [ _('Adds contact to roster'), - [ + [ (_('jid'), _('JID of the contact'), True), (_('account'), _('Adds new contact to this account'), False) ] @@ -226,7 +226,7 @@ class GajimRemote: [ (_('account'), _(''), False) ] - ], + ], 'get_unread_msgs_number': [ _('Returns number of unread messages'), @@ -239,7 +239,7 @@ class GajimRemote: ] ], 'send_xml': [ - _('Sends custom XML'), + _('Sends custom XML'), [ ('xml', _('XML to send'), True), ('account', _('Account in which the xml will be sent; ' @@ -263,8 +263,13 @@ class GajimRemote: (_('account'), _(''), False) ] ], + 'check_gajim_running':[ + _('Check if Gajim is running'), + [] + ], } + self.sbus = None if self.argv_len < 2 or \ sys.argv[1] not in self.commands.keys(): # no args or bad args send_error(self.compose_help()) @@ -277,6 +282,9 @@ class GajimRemote: sys.exit(0) if self.command == 'handle_uri': self.handle_uri() + if self.command == 'check_gajim_running': + print self.check_gajim_running() + sys.exit(0) self.init_connection() self.check_arguments() @@ -323,7 +331,7 @@ class GajimRemote: pref_keys.sort() for pref_key in pref_keys: result = '%s = %s' % (pref_key, res[pref_key]) - if isinstance(result, unicode): + if isinstance(result, unicode): print result.encode(PREFERRED_ENCODING) else: print result @@ -332,6 +340,22 @@ class GajimRemote: elif res: print unicode(res).encode(PREFERRED_ENCODING) + def check_gajim_running(self): + if not self.sbus: + try: + self.sbus = dbus.SessionBus() + except: + raise exceptions.SessionBusNotPresent + + test = False + if hasattr(self.sbus, 'name_has_owner'): + if self.sbus.name_has_owner(SERVICE): + test = True + elif dbus.dbus_bindings.bus_name_has_owner(self.sbus.get_connection(), + SERVICE): + test = True + return test + def init_connection(self): ''' create the onnection to the session dbus, or exit if it is not possible ''' @@ -340,6 +364,8 @@ class GajimRemote: except: raise exceptions.SessionBusNotPresent + if not self.check_gajim_running(): + send_error(_('It seems Gajim is not running. So you can\'t use gajim-remote.')) obj = self.sbus.get_object(SERVICE, OBJ_PATH) interface = dbus.Interface(obj, INTERFACE) @@ -368,7 +394,7 @@ class GajimRemote: if command in self.commands: command_props = self.commands[command] arguments_str = self.make_arguments_row(command_props[1]) - str = _('Usage: %s %s %s \n\t %s') % (BASENAME, command, + str = _('Usage: %s %s %s \n\t %s') % (BASENAME, command, arguments_str, command_props[0]) if len(command_props[1]) > 0: str += '\n\n' + _('Arguments:') + '\n' @@ -383,7 +409,7 @@ class GajimRemote: commands = self.commands.keys() commands.sort() for command in commands: - str += ' ' + command + str += ' ' + command for argument in self.commands[command][1]: str += ' ' if argument[2]: @@ -457,7 +483,7 @@ class GajimRemote: if len(args) > argv_len: if args[argv_len][2]: send_error(_('Argument "%s" is not specified. \n' - 'Type "%s help %s" for more info') % + 'Type "%s help %s" for more info') % (args[argv_len][0], BASENAME, self.command)) self.arguments = [] i = 0 @@ -485,7 +511,7 @@ class GajimRemote: if action == 'join': self.command = sys.argv[1] = 'join_room' return - + sys.exit(0) def call_remote_method(self): diff --git a/src/gajim.py b/src/gajim.py index ec798f6c0..3c84e56c7 100755 --- a/src/gajim.py +++ b/src/gajim.py @@ -720,12 +720,6 @@ class Interface: elif new_show > 1: # Status change (not connected/disconnected or error (<1)) notify.notify('status_change', jid, account, [new_show, status_message]) - else: - # FIXME: Msn transport (CMSN1.2.1 and PyMSN0.10) doesn't follow the JEP - # remove in 2007 - # It's maybe a GC_NOTIFY (specialy for MSN gc) - self.handle_event_gc_notify(account, (jid, array[1], status_message, - array[3], None, None, None, None, None, [], None, None)) def handle_event_msgerror(self, account, array): #'MSGERROR' (account, (jid, error_code, error_msg, msg, time)) @@ -989,6 +983,10 @@ class Interface: def handle_event_last_status_time(self, account, array): # ('LAST_STATUS_TIME', account, (jid, resource, seconds, status)) + tim = array[2] + if tim < 0: + # Ann error occured + return win = None if self.instances[account]['infos'].has_key(array[0]): win = self.instances[account]['infos'][array[0]] @@ -997,7 +995,7 @@ class Interface: if win: c = gajim.contacts.get_contact(account, array[0], array[1]) if c: # c can be none if it's a gc contact - c.last_status_time = time.localtime(time.time() - array[2]) + c.last_status_time = time.localtime(time.time() - tim) if array[3]: c.status = array[3] win.set_last_status_time() diff --git a/src/groupchat_control.py b/src/groupchat_control.py index c5b2ae487..0234ce5a1 100644 --- a/src/groupchat_control.py +++ b/src/groupchat_control.py @@ -939,19 +939,18 @@ class GroupchatControl(ChatControlBase): model[iter][C_TEXT] = name def draw_avatar(self, nick): + if not gajim.config.get('show_avatars_in_roster'): + return model = self.list_treeview.get_model() iter = self.get_contact_iter(nick) if not iter: return - if gajim.config.get('show_avatars_in_roster'): - pixbuf = gtkgui_helpers.get_avatar_pixbuf_from_cache(self.room_jid + \ - '/' + nick, True) - if pixbuf in ('ask', None): - scaled_pixbuf = None - else: - scaled_pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, 'roster') - else: + pixbuf = gtkgui_helpers.get_avatar_pixbuf_from_cache(self.room_jid + \ + '/' + nick, True) + if pixbuf in ('ask', None): scaled_pixbuf = None + else: + scaled_pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, 'roster') model[iter][C_AVATAR] = scaled_pixbuf def chg_contact_status(self, nick, show, status, role, affiliation, jid, diff --git a/src/message_window.py b/src/message_window.py index f882b86cc..0406559de 100644 --- a/src/message_window.py +++ b/src/message_window.py @@ -4,12 +4,12 @@ ## Vincent Hanquez ## Copyright (C) 2005 Yann Leboulanger ## Vincent Hanquez -## Nikos Kouremenos ## Dimitur Kirov ## Norman Rasmussen ## Copyright (C) 2005-2007 Travis Shirk ## Copyright (C) 2006 Geobert Quach ## Copyright (C) 2007 Stephan Erb +## Copyright (C) 2005-2008 Nikos Kouremenos ## ## This file is part of Gajim. ## @@ -123,7 +123,9 @@ class MessageWindow(object): else: nb_pos = gtk.POS_TOP self.notebook.set_tab_pos(nb_pos) - if gajim.config.get('tabs_always_visible'): + window_mode = gajim.interface.msg_win_mgr.mode + if gajim.config.get('tabs_always_visible') or \ + window_mode == MessageWindowMgr.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER: self.notebook.set_show_tabs(True) self.alignment.set_property('top-padding', 2) else: @@ -444,7 +446,9 @@ class MessageWindow(object): self.window.destroy() return # don't show_title, we are dead elif self.get_num_controls() == 1: # we are going from two tabs to one - show_tabs_if_one_tab = gajim.config.get('tabs_always_visible') + window_mode = gajim.interface.msg_win_mgr.mode + show_tabs_if_one_tab = gajim.config.get('tabs_always_visible') or \ + window_mode == MessageWindowMgr.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER self.notebook.set_show_tabs(show_tabs_if_one_tab) if not show_tabs_if_one_tab: self.alignment.set_property('top-padding', 0) @@ -624,11 +628,15 @@ class MessageWindow(object): self.show_title(control = new_ctrl) def _on_notebook_key_press(self, widget, event): - control = self.get_active_control() # Ctrl+PageUP / DOWN has to be handled by notebook if (event.state & gtk.gdk.CONTROL_MASK and event.keyval in (gtk.keysyms.Page_Down, gtk.keysyms.Page_Up)): return False + # when tab itself is selected, make sure <- and -> are allowed for navigating between tabs + if event.keyval in (gtk.keysyms.Left, gtk.keysyms.Right): + return False + + control = self.get_active_control() if isinstance(control, ChatControlBase): # we forwarded it to message textview control.msg_textview.emit('key_press_event', event) diff --git a/src/roster_window.py b/src/roster_window.py index b64751e90..54ce52e09 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -334,8 +334,7 @@ class RosterWindow: model.append(i, (None, name, 'contact', jid, account, None, None)) self.draw_contact(jid, account) - if gajim.config.get('show_avatars_in_roster'): - self.draw_avatar(jid, account) + self.draw_avatar(jid, account) self.draw_account(account) # Redraw parent to change icon self.draw_contact(big_brother_jid, big_brother_account) @@ -395,8 +394,7 @@ class RosterWindow: if gajim.groups[account][group]['expand']: self.tree.expand_row(model.get_path(iterG), False) self.draw_contact(jid, account) - if gajim.config.get('show_avatars_in_roster'): - self.draw_avatar(jid, account) + self.draw_avatar(jid, account) self.draw_account(account) # put the children under this iter for data in shown_family: @@ -762,6 +760,8 @@ class RosterWindow: def draw_avatar(self, jid, account): '''draw the avatar''' + if not gajim.config.get('show_avatars_in_roster'): + return model = self.tree.get_model() iters = self.get_contact_iter(jid, account) if gajim.config.get('show_avatars_in_roster'):