[Florob] show in roster and message window geolocalisation of a contact. Fixes #5485

This commit is contained in:
Yann Leboulanger 2009-12-07 18:32:42 +01:00
parent 6f1c17e3d6
commit 07be0727de
11 changed files with 144 additions and 15 deletions

View file

@ -103,13 +103,31 @@
<child> <child>
<widget class="GtkImage" id="tune_image"> <widget class="GtkImage" id="tune_image">
<property name="no_show_all">True</property> <property name="no_show_all">True</property>
<property name="pixbuf">../emoticons/static/music.png</property> <property name="stock">None</property>
<property name="icon-size">1</property> <property name="icon-size">1</property>
</widget> </widget>
<packing> <packing>
<property name="position">2</property> <property name="position">2</property>
</packing> </packing>
</child> </child>
<child>
<widget class="GtkEventBox" id="location_eventbox">
<property name="visible">True</property>
<property name="visible_window">False</property>
<child>
<widget class="GtkImage" id="location_image">
<property name="no_show_all">True</property>
<property name="stock">None</property>
<property name="icon-size">1</property>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
</packing>
</child>
<child> <child>
<widget class="GtkImage" id="audio_banner_image"> <widget class="GtkImage" id="audio_banner_image">
<property name="visible">True</property> <property name="visible">True</property>
@ -117,7 +135,7 @@
<property name="icon-size">1</property> <property name="icon-size">1</property>
</widget> </widget>
<packing> <packing>
<property name="position">3</property> <property name="position">4</property>
</packing> </packing>
</child> </child>
<child> <child>
@ -127,7 +145,7 @@
<property name="icon-size">1</property> <property name="icon-size">1</property>
</widget> </widget>
<packing> <packing>
<property name="position">4</property> <property name="position">5</property>
</packing> </packing>
</child> </child>
<child> <child>
@ -139,7 +157,7 @@
</child> </child>
</widget> </widget>
<packing> <packing>
<property name="position">5</property> <property name="position">6</property>
</packing> </packing>
</child> </child>
</widget> </widget>

View file

@ -127,6 +127,24 @@
<property name="position">4</property> <property name="position">4</property>
</packing> </packing>
</child> </child>
<child>
<widget class="GtkCheckButton" id="show_location_in_roster_checkbutton">
<property name="label" translatable="yes">Display _location of contacts in roster</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="has_tooltip">True</property>
<property name="tooltip" translatable="yes">If checked, Gajim will display the location of contacts in the roster window</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_show_location_in_roster_checkbutton_toggled"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">5</property>
</packing>
</child>
<child> <child>
<widget class="GtkHBox" id="hbox3"> <widget class="GtkHBox" id="hbox3">
<property name="visible">True</property> <property name="visible">True</property>
@ -172,7 +190,7 @@
</child> </child>
</widget> </widget>
<packing> <packing>
<property name="position">5</property> <property name="position">6</property>
</packing> </packing>
</child> </child>
</widget> </widget>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -1338,6 +1338,7 @@ class ChatControl(ChatControlBase):
self._pep_images['mood'] = self.xml.get_widget('mood_image') self._pep_images['mood'] = self.xml.get_widget('mood_image')
self._pep_images['activity'] = self.xml.get_widget('activity_image') self._pep_images['activity'] = self.xml.get_widget('activity_image')
self._pep_images['tune'] = self.xml.get_widget('tune_image') self._pep_images['tune'] = self.xml.get_widget('tune_image')
self._pep_images['location'] = self.xml.get_widget('location_image')
self.update_all_pep_types() self.update_all_pep_types()
# keep timeout id and window obj for possible big avatar # keep timeout id and window obj for possible big avatar
@ -1375,6 +1376,11 @@ class ChatControl(ChatControlBase):
self.on_avatar_eventbox_button_press_event) self.on_avatar_eventbox_button_press_event)
self.handlers[id_] = widget self.handlers[id_] = widget
widget = self.xml.get_widget('location_eventbox')
id_ = widget.connect('button-release-event',
self.on_location_eventbox_button_release_event)
self.handlers[id_] = widget
for key in ('1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '0', '#'): for key in ('1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '0', '#'):
widget = self.xml.get_widget(key + '_button') widget = self.xml.get_widget(key + '_button')
id_ = widget.connect('pressed', self.on_num_button_pressed, key) id_ = widget.connect('pressed', self.on_num_button_pressed, key)
@ -1678,6 +1684,14 @@ class ChatControl(ChatControlBase):
menu.show_all() menu.show_all()
menu.popup(None, None, None, event.button, event.time) menu.popup(None, None, None, event.button, event.time)
return True return True
def on_location_eventbox_button_release_event(self, widget, event):
if 'location' in self.contact.pep:
location = self.contact.pep['location']._pep_specific_data
if ('lat' in location) and ('lon' in location):
uri = 'http://www.openstreetmap.org/?mlat=%(lat)s&mlon=%(lon)s&' + \
'zoom=16' % {'lat': location['lat'], 'lon': location['lon']}
helpers.launch_browser_mailer('url', uri)
def _on_window_motion_notify(self, widget, event): def _on_window_motion_notify(self, widget, event):
""" """

View file

@ -225,6 +225,7 @@ class Config:
'show_mood_in_roster': [opt_bool, True, '', True], 'show_mood_in_roster': [opt_bool, True, '', True],
'show_activity_in_roster': [opt_bool, True, '', True], 'show_activity_in_roster': [opt_bool, True, '', True],
'show_tunes_in_roster': [opt_bool, True, '', True], 'show_tunes_in_roster': [opt_bool, True, '', True],
'show_location_in_roster': [opt_bool, True, '', True],
'avatar_position_in_roster': [opt_str, 'right', _('Define the position of the avatar in roster. Can be left or right'), True], 'avatar_position_in_roster': [opt_str, 'right', _('Define the position of the avatar in roster. Can be left or right'), True],
'ask_avatars_on_startup': [opt_bool, True, _('If True, Gajim will ask for avatar each contact that did not have an avatar last time or has one cached that is too old.')], 'ask_avatars_on_startup': [opt_bool, True, _('If True, Gajim will ask for avatar each contact that did not have an avatar last time or has one cached that is too old.')],
'print_status_in_chats': [opt_bool, True, _('If False, Gajim will no longer print status line in chats when a contact changes his or her status and/or his or her status message.')], 'print_status_in_chats': [opt_bool, True, _('If False, Gajim will no longer print status line in chats when a contact changes his or her status and/or his or her status message.')],
@ -353,6 +354,7 @@ class Config:
'subscribe_activity': [opt_bool, True], 'subscribe_activity': [opt_bool, True],
'subscribe_tune': [opt_bool, True], 'subscribe_tune': [opt_bool, True],
'subscribe_nick': [opt_bool, True], 'subscribe_nick': [opt_bool, True],
'subscribe_location': [opt_bool, True],
'ignore_unknown_contacts': [ opt_bool, False ], 'ignore_unknown_contacts': [ opt_bool, False ],
'send_os_info': [ opt_bool, True ], 'send_os_info': [ opt_bool, True ],
'log_encrypted_sessions': [opt_bool, True, _('When negotiating an encrypted session, should Gajim assume you want your messages to be logged?')], 'log_encrypted_sessions': [opt_bool, True, _('When negotiating an encrypted session, should Gajim assume you want your messages to be logged?')],

View file

@ -1294,6 +1294,8 @@ def update_optional_features(account = None):
gajim.gajim_optional_features[a].append(xmpp.NS_TUNE + '+notify') gajim.gajim_optional_features[a].append(xmpp.NS_TUNE + '+notify')
if gajim.config.get_per('accounts', a, 'subscribe_nick'): if gajim.config.get_per('accounts', a, 'subscribe_nick'):
gajim.gajim_optional_features[a].append(xmpp.NS_NICK + '+notify') gajim.gajim_optional_features[a].append(xmpp.NS_NICK + '+notify')
if gajim.config.get_per('accounts', a, 'subscribe_location'):
gajim.gajim_optional_features[a].append(xmpp.NS_LOCATION + '+notify')
if gajim.config.get('outgoing_chat_state_notifactions') != 'disabled': if gajim.config.get('outgoing_chat_state_notifactions') != 'disabled':
gajim.gajim_optional_features[a].append(xmpp.NS_CHATSTATES) gajim.gajim_optional_features[a].append(xmpp.NS_CHATSTATES)
if not gajim.config.get('ignore_incoming_xhtml'): if not gajim.config.get('ignore_incoming_xhtml'):

View file

@ -191,6 +191,11 @@ ACTIVITIES = {
TUNE_DATA = ['artist', 'title', 'source', 'track', 'length'] TUNE_DATA = ['artist', 'title', 'source', 'track', 'length']
LOCATION_DATA = ['accuracy', 'alt', 'area', 'bearing', 'building', 'country',
'countrycode', 'datum', 'description', 'error', 'floor', 'lat',
'locality', 'lon', 'postalcode', 'region', 'room', 'speed', 'street',
'text', 'timestamp', 'uri']
import gobject import gobject
import gtk import gtk
@ -442,8 +447,47 @@ class UserNicknamePEP(AbstractPEP):
gajim.nicks[account] = self._pep_specific_data gajim.nicks[account] = self._pep_specific_data
class UserLocationPEP(AbstractPEP):
'''XEP-0080: User Location'''
type = 'location'
namespace = xmpp.NS_LOCATION
def _extract_info(self, items):
location_dict = {}
for item in items.getTags('item'):
location_tag = item.getTag('geoloc')
if location_tag:
for child in location_tag.getChildren():
name = child.getName().strip()
data = child.getData().strip()
if child.getName() in LOCATION_DATA:
location_dict[name] = data
retracted = items.getTag('retract') or not location_dict
return (location_dict, retracted)
def asPixbufIcon(self):
gtkgui_helpers.get_icon_path('gajim-earth')
return gtk.gdk.pixbuf_new_from_file(path)
def asMarkupText(self):
assert not self._retracted
location = self._pep_specific_data
location_string = ''
for entry in location.keys():
text = location[entry]
text = gobject.markup_escape_text(text)
location_string += '\n<b>%(tag)s</b>: %(text)s' % \
{'tag': entry.capitalize(), 'text': text}
return location_string.strip()
SUPPORTED_PERSONAL_USER_EVENTS = [UserMoodPEP, UserTunePEP, UserActivityPEP, SUPPORTED_PERSONAL_USER_EVENTS = [UserMoodPEP, UserTunePEP, UserActivityPEP,
UserNicknamePEP] UserNicknamePEP, UserLocationPEP]
class ConnectionPEP(object): class ConnectionPEP(object):

View file

@ -72,6 +72,7 @@ NS_JINGLE_RTP_VIDEO='urn:xmpp:jingle:apps:rtp:video' # XEP-01
NS_JINGLE_RAW_UDP='urn:xmpp:jingle:transports:raw-udp:1' # XEP-0177 NS_JINGLE_RAW_UDP='urn:xmpp:jingle:transports:raw-udp:1' # XEP-0177
NS_JINGLE_ICE_UDP='urn:xmpp:jingle:transports:ice-udp:1' # XEP-0176 NS_JINGLE_ICE_UDP='urn:xmpp:jingle:transports:ice-udp:1' # XEP-0176
NS_LAST ='jabber:iq:last' NS_LAST ='jabber:iq:last'
NS_LOCATION ='http://jabber.org/protocol/geoloc' # XEP-0080
NS_MESSAGE ='message' # Jabberd2 NS_MESSAGE ='message' # Jabberd2
NS_MOOD ='http://jabber.org/protocol/mood' # XEP-0107 NS_MOOD ='http://jabber.org/protocol/mood' # XEP-0107
NS_MUC ='http://jabber.org/protocol/muc' NS_MUC ='http://jabber.org/protocol/muc'

View file

@ -137,6 +137,11 @@ class PreferencesWindow:
self.xml.get_widget('show_tunes_in_roster_checkbutton'). \ self.xml.get_widget('show_tunes_in_roster_checkbutton'). \
set_active(st) set_active(st)
# Display location in roster
st = gajim.config.get('show_location_in_roster')
self.xml.get_widget('show_location_in_roster_checkbutton'). \
set_active(st)
# Sort contacts by show # Sort contacts by show
st = gajim.config.get('sort_by_show_in_roster') st = gajim.config.get('sort_by_show_in_roster')
self.xml.get_widget('sort_by_show_in_roster_checkbutton').set_active(st) self.xml.get_widget('sort_by_show_in_roster_checkbutton').set_active(st)
@ -615,6 +620,10 @@ class PreferencesWindow:
self.on_checkbutton_toggled(widget, 'show_tunes_in_roster') self.on_checkbutton_toggled(widget, 'show_tunes_in_roster')
gajim.interface.roster.setup_and_draw_roster() gajim.interface.roster.setup_and_draw_roster()
def on_show_location_in_roster_checkbutton_toggled(self, widget):
self.on_checkbutton_toggled(widget, 'show_location_in_roster')
gajim.interface.roster.setup_and_draw_roster()
def on_emoticons_combobox_changed(self, widget): def on_emoticons_combobox_changed(self, widget):
active = widget.get_active() active = widget.get_active()
model = widget.get_model() model = widget.get_model()

View file

@ -79,9 +79,10 @@ from common.pep import MOODS, ACTIVITIES
C_MOOD_PIXBUF, C_MOOD_PIXBUF,
C_ACTIVITY_PIXBUF, C_ACTIVITY_PIXBUF,
C_TUNE_PIXBUF, C_TUNE_PIXBUF,
C_LOCATION_PIXBUF,
C_AVATAR_PIXBUF, # avatar_pixbuf C_AVATAR_PIXBUF, # avatar_pixbuf
C_PADLOCK_PIXBUF, # use for account row only C_PADLOCK_PIXBUF, # use for account row only
) = range(10) ) = range(11)
class RosterWindow: class RosterWindow:
""" """
@ -293,7 +294,7 @@ class RosterWindow:
self.model.append(None, [ self.model.append(None, [
gajim.interface.jabber_state_images['16'][show], gajim.interface.jabber_state_images['16'][show],
gobject.markup_escape_text(account), 'account', gobject.markup_escape_text(account), 'account',
our_jid, account, None, None, None, None, our_jid, account, None, None, None, None, None,
tls_pixbuf]) tls_pixbuf])
self.draw_account(account) self.draw_account(account)
@ -370,7 +371,7 @@ class RosterWindow:
child_iterG = self.model.append(child_iterA, child_iterG = self.model.append(child_iterA,
[gajim.interface.jabber_state_images['16']['closed'], [gajim.interface.jabber_state_images['16']['closed'],
gobject.markup_escape_text(group), gobject.markup_escape_text(group),
'group', group, account, None, None, None, None, None]) 'group', group, account, None, None, None, None, None, None])
self.draw_group(group, account) self.draw_group(group, account)
if contact.is_transport(): if contact.is_transport():
@ -385,7 +386,7 @@ class RosterWindow:
i_ = self.model.append(child_iterG, (None, i_ = self.model.append(child_iterG, (None,
contact.get_shown_name(), typestr, contact.get_shown_name(), typestr,
contact.jid, account, None, None, None, contact.jid, account, None, None, None,
None, None)) None, None, None))
added_iters.append(i_) added_iters.append(i_)
# Restore the group expand state # Restore the group expand state
@ -627,7 +628,7 @@ class RosterWindow:
child_iterA = self._get_account_iter(account, self.model) child_iterA = self._get_account_iter(account, self.model)
self.model.append(child_iterA, (None, gajim.nicks[account], self.model.append(child_iterA, (None, gajim.nicks[account],
'self_contact', jid, account, None, None, None, None, 'self_contact', jid, account, None, None, None, None,
None)) None, None))
self.draw_completely(jid, account) self.draw_completely(jid, account)
self.draw_account(account) self.draw_account(account)
@ -1050,6 +1051,11 @@ class RosterWindow:
self.model[child_iter][C_TUNE_PIXBUF] = pep['tune'].asPixbufIcon() self.model[child_iter][C_TUNE_PIXBUF] = pep['tune'].asPixbufIcon()
else: else:
self.model[child_iter][C_TUNE_PIXBUF] = None self.model[child_iter][C_TUNE_PIXBUF] = None
if gajim.config.get('show_location_in_roster') and 'location' in pep:
self.model[child_iter][C_LOCATION_PIXBUF] = pep['location'].asPixbufIcon()
else:
self.model[child_iter][C_LOCATION_PIXBUF] = None
return False return False
def draw_group(self, group, account): def draw_group(self, group, account):
@ -1264,6 +1270,8 @@ class RosterWindow:
return gajim.config.get('show_activity_in_roster') return gajim.config.get('show_activity_in_roster')
elif pep_type == 'tune': elif pep_type == 'tune':
return gajim.config.get('show_tunes_in_roster') return gajim.config.get('show_tunes_in_roster')
elif pep_type == 'location':
return gajim.config.get('show_location_in_roster')
else: else:
return False return False
@ -1362,10 +1370,11 @@ class RosterWindow:
""" """
self.modelfilter = None self.modelfilter = None
# (icon, name, type, jid, account, editable, mood_pixbuf, # (icon, name, type, jid, account, editable, mood_pixbuf,
# activity_pixbuf, tune_pixbuf avatar_pixbuf, padlock_pixbuf) # activity_pixbuf, tune_pixbuf, location_pixbuf, avatar_pixbuf,
# padlock_pixbuf)
self.model = gtk.TreeStore(gtk.Image, str, str, str, str, self.model = gtk.TreeStore(gtk.Image, str, str, str, str,
gtk.gdk.Pixbuf, gtk.gdk.Pixbuf, gtk.gdk.Pixbuf, gtk.gdk.Pixbuf, gtk.gdk.Pixbuf, gtk.gdk.Pixbuf,
gtk.gdk.Pixbuf, gtk.gdk.Pixbuf) gtk.gdk.Pixbuf, gtk.gdk.Pixbuf, gtk.gdk.Pixbuf)
self.model.set_sort_func(1, self._compareIters) self.model.set_sort_func(1, self._compareIters)
self.model.set_sort_column_id(1, gtk.SORT_ASCENDING) self.model.set_sort_column_id(1, gtk.SORT_ASCENDING)
@ -5892,9 +5901,16 @@ class RosterWindow:
col.set_cell_data_func(render_pixbuf, col.set_cell_data_func(render_pixbuf,
self._fill_pep_pixbuf_renderer, C_TUNE_PIXBUF) self._fill_pep_pixbuf_renderer, C_TUNE_PIXBUF)
render_pixbuf = gtk.CellRendererPixbuf()
col.pack_start(render_pixbuf, expand=False)
col.add_attribute(render_pixbuf, 'pixbuf', C_LOCATION_PIXBUF)
col.set_cell_data_func(render_pixbuf,
self._fill_pep_pixbuf_renderer, C_LOCATION_PIXBUF)
self._pep_type_to_model_column = {'mood': C_MOOD_PIXBUF, self._pep_type_to_model_column = {'mood': C_MOOD_PIXBUF,
'activity': C_ACTIVITY_PIXBUF, 'activity': C_ACTIVITY_PIXBUF,
'tune': C_TUNE_PIXBUF} 'tune': C_TUNE_PIXBUF,
'location': C_LOCATION_PIXBUF}
if gajim.config.get('avatar_position_in_roster') == 'right': if gajim.config.get('avatar_position_in_roster') == 'right':
add_avatar_renderer() add_avatar_renderer()

View file

@ -600,7 +600,7 @@ class RosterTooltip(NotificationAreaTooltip):
def _append_pep_info(self, contact, properties): def _append_pep_info(self, contact, properties):
""" """
Append Tune, Mood, Activity information of the specified contact Append Tune, Mood, Activity, Location information of the specified contact
to the given property list. to the given property list.
""" """
if 'mood' in contact.pep: if 'mood' in contact.pep:
@ -618,6 +618,11 @@ class RosterTooltip(NotificationAreaTooltip):
tune_string = _('Tune:') + ' %s' % tune tune_string = _('Tune:') + ' %s' % tune
properties.append((tune_string, None)) properties.append((tune_string, None))
if 'location' in contact.pep:
location = contact.pep['location'].asMarkupText()
location_string = _('Location:') + ' %s' % location
properties.append((location_string, None))
class FileTransfersTooltip(BaseTooltip): class FileTransfersTooltip(BaseTooltip):
""" """