Refactor Roster Tooltip
This commit is contained in:
parent
ec99e93a7c
commit
3296c23e32
5 changed files with 762 additions and 352 deletions
|
@ -366,12 +366,9 @@
|
|||
<signal name="button-press-event" handler="on_roster_treeview_button_press_event" swapped="no"/>
|
||||
<signal name="button-release-event" handler="on_roster_treeview_button_release_event" swapped="no"/>
|
||||
<signal name="key-press-event" handler="on_roster_treeview_key_press_event" swapped="no"/>
|
||||
<signal name="leave-notify-event" handler="on_roster_treeview_leave_notify_event" swapped="no"/>
|
||||
<signal name="motion-notify-event" handler="on_roster_treeview_motion_notify_event" swapped="no"/>
|
||||
<signal name="row-activated" handler="on_roster_treeview_row_activated" swapped="no"/>
|
||||
<signal name="row-collapsed" handler="on_roster_treeview_row_collapsed" swapped="no"/>
|
||||
<signal name="row-expanded" handler="on_roster_treeview_row_expanded" swapped="no"/>
|
||||
<signal name="scroll-event" handler="on_roster_treeview_scroll_event" swapped="no"/>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="treeview-selection1"/>
|
||||
</child>
|
||||
|
|
370
data/gui/tooltip_roster_contact.ui
Normal file
370
data/gui/tooltip_roster_contact.ui
Normal file
|
@ -0,0 +1,370 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.18.3 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.12"/>
|
||||
<object class="GtkGrid" id="tooltip_grid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="column_spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="name">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="jid_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="label" translatable="yes">Jabber ID:</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="avatar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="stock">gtk-missing-image</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="height">14</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="resource_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Resource:</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="user_show">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="resource">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="jid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="status_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="label" translatable="yes">Status:</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="max_width_chars">40</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="idle_since_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Idle since:</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">12</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="idle_for_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Idle for:</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">13</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="idle_since">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">12</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="idle_for">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">13</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="mood_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Mood:</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="activity_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Activity:</property>
|
||||
<property name="lines">2</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="tune_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Tune:</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">8</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="location_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Location:</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">9</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="mood">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="activity">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="tune">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">8</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="location">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">9</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="pgp_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">OpenPGP:</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">10</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="pgp">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">10</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="sub_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Subscription:</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">11</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="sub">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">11</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="status">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="max_width_chars">30</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
<attributes>
|
||||
<attribute name="style" value="italic"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
|
@ -562,11 +562,14 @@ class Interface:
|
|||
|
||||
def handle_event_last_status_time(self, obj):
|
||||
# ('LAST_STATUS_TIME', account, (jid, resource, seconds, status))
|
||||
if obj.seconds < 0:
|
||||
# Ann error occured
|
||||
return
|
||||
account = obj.conn.name
|
||||
c = gajim.contacts.get_contact(account, obj.jid, obj.resource)
|
||||
tooltip_window = self.roster.tree.get_tooltip_window()
|
||||
if obj.seconds < 0:
|
||||
if tooltip_window:
|
||||
tooltip_window.update_last_time(c, True)
|
||||
return
|
||||
|
||||
if c: # c can be none if it's a gc contact
|
||||
if obj.status:
|
||||
c.status = obj.status
|
||||
|
@ -576,8 +579,10 @@ class Interface:
|
|||
c.last_status_time = last_time
|
||||
else:
|
||||
c.last_activity_time = last_time
|
||||
if self.roster.tooltip.id and self.roster.tooltip.win:
|
||||
self.roster.tooltip.update_last_time(last_time)
|
||||
|
||||
# Set last time on roster tooltip
|
||||
if tooltip_window:
|
||||
tooltip_window.update_last_time(c)
|
||||
|
||||
def handle_event_gc_config(self, obj):
|
||||
#('GC_CONFIG', account, (jid, form_node)) config is a dict
|
||||
|
|
|
@ -2063,25 +2063,6 @@ class RosterWindow:
|
|||
vb.hide()
|
||||
vb.set_no_show_all(True)
|
||||
|
||||
def show_tooltip(self, contact):
|
||||
self.tooltip.timeout = 0
|
||||
device = self.tree.get_window().get_display().get_device_manager().\
|
||||
get_client_pointer()
|
||||
pointer = self.tree.get_window().get_device_position(device)
|
||||
props = self.tree.get_path_at_pos(pointer[1], pointer[2])
|
||||
# check if the current pointer is at the same path
|
||||
# as it was before setting the timeout
|
||||
if props and self.tooltip.id == props[0]:
|
||||
# bounding rectangle of coordinates for the cell within the treeview
|
||||
rect = self.tree.get_cell_area(props[0], props[1])
|
||||
|
||||
# position of the treeview on the screen
|
||||
position = self.tree.get_window().get_origin()
|
||||
self.tooltip.show_tooltip(contact, rect.height, position[2] + \
|
||||
rect.y)
|
||||
else:
|
||||
self.tooltip.hide_tooltip()
|
||||
|
||||
def authorize(self, widget, jid, account):
|
||||
"""
|
||||
Authorize a contact (by re-sending auth menuitem)
|
||||
|
@ -2443,7 +2424,6 @@ class RosterWindow:
|
|||
if not gajim.config.get('quit_on_roster_x_button') and (
|
||||
(gajim.interface.systray_enabled and gajim.config.get('trayicon') != \
|
||||
'on_event') or gajim.config.get('allow_hide_roster')):
|
||||
self.tooltip.hide_tooltip()
|
||||
if gajim.config.get('save-roster-position'):
|
||||
x, y = self.window.get_position()
|
||||
gajim.config.set('roster_x-position', x)
|
||||
|
@ -2894,119 +2874,6 @@ class RosterWindow:
|
|||
return
|
||||
info[contact.jid] = vcard.ZeroconfVcardWindow(contact, account)
|
||||
|
||||
def on_roster_treeview_leave_notify_event(self, widget, event):
|
||||
props = widget.get_path_at_pos(int(event.x), int(event.y))
|
||||
if self.tooltip.timeout > 0 or self.tooltip.shown:
|
||||
if not props or self.tooltip.id == props[0]:
|
||||
self.tooltip.hide_tooltip()
|
||||
|
||||
def on_roster_treeview_motion_notify_event(self, widget, event):
|
||||
model = widget.get_model()
|
||||
props = widget.get_path_at_pos(int(event.x), int(event.y))
|
||||
if self.tooltip.timeout > 0 or self.tooltip.shown:
|
||||
if not props or self.tooltip.id != props[0]:
|
||||
self.tooltip.hide_tooltip()
|
||||
if props:
|
||||
row = props[0]
|
||||
titer = None
|
||||
try:
|
||||
titer = model.get_iter(row)
|
||||
except Exception:
|
||||
self.tooltip.hide_tooltip()
|
||||
return
|
||||
if model[titer][C_TYPE] in ('contact', 'self_contact'):
|
||||
# we're on a contact entry in the roster
|
||||
if (not self.tooltip.shown and self.tooltip.timeout == 0) or \
|
||||
self.tooltip.id != props[0]:
|
||||
account = model[titer][C_ACCOUNT]
|
||||
jid = model[titer][C_JID]
|
||||
self.tooltip.id = row
|
||||
contacts = gajim.contacts.get_contacts(account, jid)
|
||||
connected_contacts = []
|
||||
for c in contacts:
|
||||
if c.show not in ('offline', 'error'):
|
||||
connected_contacts.append(c)
|
||||
if not connected_contacts:
|
||||
# no connected contacts, show the ofline one
|
||||
connected_contacts = contacts
|
||||
self.tooltip.account = account
|
||||
self.tooltip.timeout = GLib.timeout_add(500,
|
||||
self.show_tooltip, connected_contacts)
|
||||
elif model[titer][C_TYPE] == 'groupchat':
|
||||
if (not self.tooltip.shown and self.tooltip.timeout == 0) or \
|
||||
self.tooltip.id != props[0]:
|
||||
account = model[titer][C_ACCOUNT]
|
||||
jid = model[titer][C_JID]
|
||||
self.tooltip.id = row
|
||||
contact = gajim.contacts.get_contacts(account, jid)
|
||||
self.tooltip.account = account
|
||||
self.tooltip.timeout = GLib.timeout_add(500,
|
||||
self.show_tooltip, contact)
|
||||
elif model[titer][C_TYPE] == 'account':
|
||||
# we're on an account entry in the roster
|
||||
if (not self.tooltip.shown and self.tooltip.timeout == 0) or \
|
||||
self.tooltip.id != props[0]:
|
||||
account = model[titer][C_ACCOUNT]
|
||||
if account == 'all':
|
||||
self.tooltip.id = row
|
||||
self.tooltip.account = None
|
||||
self.tooltip.timeout = GLib.timeout_add(500,
|
||||
self.show_tooltip, [])
|
||||
return
|
||||
jid = gajim.get_jid_from_account(account)
|
||||
contacts = []
|
||||
connection = gajim.connections[account]
|
||||
# get our current contact info
|
||||
|
||||
nbr_on, nbr_total = gajim.\
|
||||
contacts.get_nb_online_total_contacts(
|
||||
accounts=[account])
|
||||
account_name = account
|
||||
if gajim.account_is_connected(account):
|
||||
account_name += ' (%s/%s)' % (repr(nbr_on),
|
||||
repr(nbr_total))
|
||||
contact = gajim.contacts.create_self_contact(jid=jid,
|
||||
account=account, name=account_name,
|
||||
show=connection.get_status(), status=connection.status,
|
||||
resource=connection.server_resource,
|
||||
priority=connection.priority)
|
||||
if gajim.connections[account].gpg:
|
||||
contact.keyID = gajim.config.get_per('accounts',
|
||||
connection.name, 'keyid')
|
||||
contacts.append(contact)
|
||||
# if we're online ...
|
||||
if connection.connection:
|
||||
roster = connection.connection.getRoster()
|
||||
# in threadless connection when no roster stanza is sent
|
||||
# 'roster' is None
|
||||
if roster and roster.getItem(jid):
|
||||
resources = roster.getResources(jid)
|
||||
# ...get the contact info for our other online
|
||||
# resources
|
||||
for resource in resources:
|
||||
# Check if we already have this resource
|
||||
found = False
|
||||
for contact_ in contacts:
|
||||
if contact_.resource == resource:
|
||||
found = True
|
||||
break
|
||||
if found:
|
||||
continue
|
||||
show = roster.getShow(jid+'/'+resource)
|
||||
if not show:
|
||||
show = 'online'
|
||||
contact = gajim.contacts.create_self_contact(
|
||||
jid=jid, account=account, show=show,
|
||||
status=roster.getStatus(
|
||||
jid + '/' + resource),
|
||||
priority=roster.getPriority(
|
||||
jid + '/' + resource), resource=resource)
|
||||
contacts.append(contact)
|
||||
self.tooltip.id = row
|
||||
self.tooltip.account = None
|
||||
self.tooltip.timeout = GLib.timeout_add(500,
|
||||
self.show_tooltip, contacts)
|
||||
|
||||
def on_agent_logging(self, widget, jid, state, account):
|
||||
"""
|
||||
When an agent is requested to log in or off
|
||||
|
@ -3449,15 +3316,10 @@ class RosterWindow:
|
|||
def on_add_to_roster(self, widget, contact, account):
|
||||
dialogs.AddNewContactWindow(account, contact.jid, contact.name)
|
||||
|
||||
|
||||
def on_roster_treeview_scroll_event(self, widget, event):
|
||||
self.tooltip.hide_tooltip()
|
||||
|
||||
def on_roster_treeview_key_press_event(self, widget, event):
|
||||
"""
|
||||
When a key is pressed in the treeviews
|
||||
"""
|
||||
self.tooltip.hide_tooltip()
|
||||
if event.keyval == Gdk.KEY_Escape:
|
||||
if self.rfilter_enabled:
|
||||
self.disable_rfilter()
|
||||
|
@ -3577,8 +3439,6 @@ class RosterWindow:
|
|||
self.enable_rfilter('')
|
||||
|
||||
def on_roster_treeview_button_press_event(self, widget, event):
|
||||
# hide tooltip, no matter the button is pressed
|
||||
self.tooltip.hide_tooltip()
|
||||
try:
|
||||
pos = self.tree.get_path_at_pos(int(event.x), int(event.y))
|
||||
path, x = pos[0], pos[2]
|
||||
|
@ -4079,7 +3939,6 @@ class RosterWindow:
|
|||
'quit_on_roster_x_button') and ((gajim.interface.systray_enabled and\
|
||||
gajim.config.get('trayicon') == 'always') or gajim.config.get(
|
||||
'allow_hide_roster')):
|
||||
self.tooltip.hide_tooltip()
|
||||
self.window.hide()
|
||||
elif event.get_state() & Gdk.ModifierType.CONTROL_MASK and event.keyval == \
|
||||
Gdk.KEY_i:
|
||||
|
@ -6268,6 +6127,54 @@ class RosterWindow:
|
|||
renderer.set_property(self.renderers_propertys[renderer][0],
|
||||
self.renderers_propertys[renderer][1])
|
||||
|
||||
def query_tooltip(self, widget, x_pos, y_pos, keyboard_mode, tooltip):
|
||||
try:
|
||||
row = widget.get_path_at_pos(x_pos, y_pos)[0]
|
||||
except TypeError:
|
||||
return False
|
||||
if not row:
|
||||
return False
|
||||
|
||||
iter_ = None
|
||||
try:
|
||||
model = widget.get_model()
|
||||
iter_ = model.get_iter(row)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
typ = model[iter_][C_TYPE]
|
||||
account = model[iter_][C_ACCOUNT]
|
||||
jid = model[iter_][C_JID]
|
||||
connected_contacts = []
|
||||
|
||||
if typ in ('contact', 'self_contact'):
|
||||
contacts = gajim.contacts.get_contacts(account, jid)
|
||||
|
||||
for c in contacts:
|
||||
if c.show not in ('offline', 'error'):
|
||||
connected_contacts.append(c)
|
||||
if not connected_contacts:
|
||||
# no connected contacts, show the offline one
|
||||
connected_contacts = contacts
|
||||
elif typ == 'groupchat':
|
||||
connected_contacts = gajim.contacts.get_contacts(account, jid)
|
||||
elif typ != 'account':
|
||||
return False
|
||||
|
||||
if self.current_tooltip != row:
|
||||
# If the row changes we hide the current tooltip
|
||||
self.current_tooltip = row
|
||||
return False
|
||||
|
||||
tooltip = widget.get_tooltip_window()
|
||||
|
||||
if tooltip.row == row:
|
||||
# We already populated the window with the row data
|
||||
return True
|
||||
tooltip.row = row
|
||||
tooltip.populate(connected_contacts, account, typ)
|
||||
return True
|
||||
|
||||
################################################################################
|
||||
###
|
||||
################################################################################
|
||||
|
@ -6515,7 +6422,10 @@ class RosterWindow:
|
|||
self.combobox_callback_active = True
|
||||
|
||||
self.collapsed_rows = gajim.config.get('collapsed_rows').split('\t')
|
||||
self.tooltip = tooltips.RosterTooltip()
|
||||
self.tree.set_has_tooltip(True)
|
||||
self.tree.set_tooltip_window(tooltips.RosterTooltip(self.window))
|
||||
self.current_tooltip = None
|
||||
self.tree.connect('query-tooltip', self.query_tooltip)
|
||||
# Workaroung: For strange reasons signal is behaving like row-changed
|
||||
self._toggeling_row = False
|
||||
self.setup_and_draw_roster()
|
||||
|
|
532
src/tooltips.py
532
src/tooltips.py
|
@ -195,28 +195,28 @@ class StatusTable:
|
|||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.current_row = 1
|
||||
self.current_row = 0
|
||||
self.table = None
|
||||
self.text_label = None
|
||||
self.spacer_label = ' '
|
||||
|
||||
def create_table(self):
|
||||
self.table = Gtk.Grid()
|
||||
self.table.insert_row(0)
|
||||
self.table.insert_row(0)
|
||||
self.table.insert_column(0)
|
||||
self.table.set_property('column-spacing', 2)
|
||||
|
||||
def add_text_row(self, text, col_inc = 0):
|
||||
self.current_row += 1
|
||||
def add_text_row(self, text, col_inc=0):
|
||||
self.table.insert_row(self.current_row)
|
||||
self.text_label = Gtk.Label()
|
||||
self.text_label.set_line_wrap(True)
|
||||
self.text_label.set_max_width_chars(35)
|
||||
self.text_label.set_halign(Gtk.Align.START)
|
||||
self.text_label.set_valign(Gtk.Align.START)
|
||||
self.text_label.set_selectable(False)
|
||||
self.text_label.set_markup(text)
|
||||
self.table.attach(self.text_label, 1 + col_inc, self.current_row,
|
||||
3 - col_inc, 1)
|
||||
self.current_row += 1
|
||||
|
||||
def get_status_info(self, resource, priority, show, status):
|
||||
str_status = resource + ' (' + str(priority) + ')'
|
||||
|
@ -235,9 +235,7 @@ class StatusTable:
|
|||
"""
|
||||
Append a new row with status icon to the table
|
||||
"""
|
||||
self.table.insert_row(0)
|
||||
self.table.insert_row(0)
|
||||
self.current_row += 1
|
||||
self.table.insert_row(self.current_row)
|
||||
state_file = show.replace(' ', '_')
|
||||
files = []
|
||||
files.append(os.path.join(file_path, state_file + '.png'))
|
||||
|
@ -265,6 +263,7 @@ class StatusTable:
|
|||
lock_image.set_from_stock(Gtk.STOCK_DIALOG_AUTHENTICATION,
|
||||
Gtk.IconSize.MENU)
|
||||
self.table.attach(lock_image, 4, self.current_row, 1, 1)
|
||||
self.current_row += 1
|
||||
|
||||
class NotificationAreaTooltip(BaseTooltip, StatusTable):
|
||||
"""
|
||||
|
@ -414,83 +413,181 @@ class GCTooltip(Gtk.Window):
|
|||
affiliation = formatted % (color, affiliation)
|
||||
return affiliation
|
||||
|
||||
class RosterTooltip(NotificationAreaTooltip):
|
||||
"""
|
||||
Tooltip that is shown in the roster treeview
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.account = None
|
||||
self.avatar_image = Gtk.Image()
|
||||
NotificationAreaTooltip.__init__(self)
|
||||
|
||||
def populate(self, contacts):
|
||||
self.create_window()
|
||||
|
||||
class RosterTooltip(Gtk.Window, StatusTable):
|
||||
# pylint: disable=E1101
|
||||
def __init__(self, parent):
|
||||
Gtk.Window.__init__(self, type=Gtk.WindowType.POPUP, transient_for=parent)
|
||||
StatusTable.__init__(self)
|
||||
self.create_table()
|
||||
if not contacts or len(contacts) == 0:
|
||||
self.row = None
|
||||
self.check_last_time = {}
|
||||
self.contact_jid = None
|
||||
self.last_widget = None
|
||||
self.num_resources = 0
|
||||
self.set_title('tooltip')
|
||||
self.set_border_width(3)
|
||||
self.set_resizable(False)
|
||||
self.set_name('gtk-tooltips')
|
||||
self.set_type_hint(Gdk.WindowTypeHint.TOOLTIP)
|
||||
|
||||
self.xml = gtkgui_helpers.get_gtk_builder('tooltip_roster_contact.ui')
|
||||
for name in ('name', 'status', 'jid', 'user_show', 'fillelement',
|
||||
'resource', 'avatar', 'resource_label', 'pgp', 'pgp_label',
|
||||
'jid_label', 'tooltip_grid', 'idle_since', 'idle_for',
|
||||
'idle_since_label', 'idle_for_label', 'mood', 'tune',
|
||||
'activity', 'location', 'tune_label', 'location_label',
|
||||
'activity_label', 'mood_label', 'sub_label', 'sub',
|
||||
'status_label'):
|
||||
setattr(self, name, self.xml.get_object(name))
|
||||
|
||||
self.add(self.tooltip_grid)
|
||||
self.tooltip_grid.show()
|
||||
|
||||
def clear_tooltip(self):
|
||||
"""
|
||||
Hide all Elements of the Tooltip Grid
|
||||
"""
|
||||
for child in self.tooltip_grid.get_children():
|
||||
child.hide()
|
||||
status_table = self.tooltip_grid.get_child_at(0, 3)
|
||||
if status_table:
|
||||
status_table.destroy()
|
||||
self.create_table()
|
||||
|
||||
def fill_table_with_accounts(self, accounts):
|
||||
iconset = gajim.config.get('iconset')
|
||||
if not iconset:
|
||||
iconset = 'dcraven'
|
||||
file_path = os.path.join(helpers.get_iconset_path(iconset), '16x16')
|
||||
for acct in accounts:
|
||||
message = acct['message']
|
||||
message = helpers.reduce_chars_newlines(message, 100, 1)
|
||||
message = GLib.markup_escape_text(message)
|
||||
if acct['name'] in gajim.con_types and \
|
||||
gajim.con_types[acct['name']] in ('tls', 'ssl'):
|
||||
show_lock = True
|
||||
else:
|
||||
show_lock = False
|
||||
if message:
|
||||
self.add_status_row(file_path, acct['show'],
|
||||
GLib.markup_escape_text(acct['name']) + ' - ' + message,
|
||||
show_lock=show_lock, indent=False)
|
||||
else:
|
||||
self.add_status_row(file_path, acct['show'],
|
||||
GLib.markup_escape_text(acct['name']), show_lock=show_lock,
|
||||
indent=False)
|
||||
for line in acct['event_lines']:
|
||||
self.add_text_row(' ' + line, 1)
|
||||
|
||||
def populate(self, contacts, account, typ):
|
||||
"""
|
||||
Populate the Tooltip Grid with data of from the contact
|
||||
"""
|
||||
self.current_row = 0
|
||||
self.account = account
|
||||
if self.last_widget:
|
||||
self.last_widget.set_vexpand(False)
|
||||
|
||||
self.clear_tooltip()
|
||||
|
||||
if account == 'all':
|
||||
# Tooltip for merged accounts row
|
||||
accounts = helpers.get_notification_icon_tooltip_dict()
|
||||
self.spacer_label = ''
|
||||
self.fill_table_with_accounts(accounts)
|
||||
self.win.add(self.table)
|
||||
self.tooltip_grid.attach(self.table, 0, 3, 2, 1)
|
||||
self.table.show_all()
|
||||
return
|
||||
|
||||
# primary contact
|
||||
prim_contact = gajim.contacts.get_highest_prio_contact_from_contacts(
|
||||
if typ == 'account':
|
||||
jid = gajim.get_jid_from_account(account)
|
||||
contacts = []
|
||||
connection = gajim.connections[account]
|
||||
# get our current contact info
|
||||
|
||||
nbr_on, nbr_total = gajim.\
|
||||
contacts.get_nb_online_total_contacts(
|
||||
accounts=[account])
|
||||
account_name = account
|
||||
if gajim.account_is_connected(account):
|
||||
account_name += ' (%s/%s)' % (repr(nbr_on),
|
||||
repr(nbr_total))
|
||||
contact = gajim.contacts.create_self_contact(jid=jid,
|
||||
account=account, name=account_name,
|
||||
show=connection.get_status(), status=connection.status,
|
||||
resource=connection.server_resource,
|
||||
priority=connection.priority)
|
||||
if gajim.connections[account].gpg:
|
||||
contact.keyID = gajim.config.get_per('accounts',
|
||||
connection.name, 'keyid')
|
||||
contacts.append(contact)
|
||||
# if we're online ...
|
||||
if connection.connection:
|
||||
roster = connection.connection.getRoster()
|
||||
# in threadless connection when no roster stanza is sent
|
||||
# 'roster' is None
|
||||
if roster and roster.getItem(jid):
|
||||
resources = roster.getResources(jid)
|
||||
# ...get the contact info for our other online
|
||||
# resources
|
||||
for resource in resources:
|
||||
# Check if we already have this resource
|
||||
found = False
|
||||
for contact_ in contacts:
|
||||
if contact_.resource == resource:
|
||||
found = True
|
||||
break
|
||||
if found:
|
||||
continue
|
||||
show = roster.getShow(jid + '/' + resource)
|
||||
if not show:
|
||||
show = 'online'
|
||||
contact = gajim.contacts.create_self_contact(
|
||||
jid=jid, account=account, show=show,
|
||||
status=roster.getStatus(
|
||||
jid + '/' + resource),
|
||||
priority=roster.getPriority(
|
||||
jid + '/' + resource), resource=resource)
|
||||
contacts.append(contact)
|
||||
|
||||
# Username/Account/Groupchat
|
||||
self.prim_contact = gajim.contacts.get_highest_prio_contact_from_contacts(
|
||||
contacts)
|
||||
|
||||
puny_jid = helpers.sanitize_filename(prim_contact.jid)
|
||||
table_size = 3
|
||||
|
||||
file_ = helpers.get_avatar_path(os.path.join(gajim.AVATAR_PATH,
|
||||
puny_jid))
|
||||
if file_:
|
||||
with open(file_, 'rb') as file_data:
|
||||
pix = gtkgui_helpers.get_pixbuf_from_data(file_data.read())
|
||||
pix = gtkgui_helpers.get_scaled_pixbuf(pix, 'tooltip')
|
||||
self.avatar_image.set_from_pixbuf(pix)
|
||||
table_size = 4
|
||||
else:
|
||||
self.avatar_image.set_from_pixbuf(None)
|
||||
vcard_table = Gtk.Grid()
|
||||
vcard_table.insert_row(0)
|
||||
for i in range(0, table_size):
|
||||
vcard_table.insert_column(0)
|
||||
vcard_table.set_property('column-spacing', 2)
|
||||
vcard_current_row = 1
|
||||
properties = []
|
||||
|
||||
name_markup = '<span weight="bold">' + GLib.markup_escape_text(
|
||||
prim_contact.get_shown_name()) + '</span>'
|
||||
self.contact_jid = self.prim_contact.jid
|
||||
name = GLib.markup_escape_text(self.prim_contact.get_shown_name())
|
||||
name_markup = '<b>{}</b>'.format(name)
|
||||
if gajim.config.get('mergeaccounts'):
|
||||
name_markup += " <span foreground='%s'>(%s)</span>" % (
|
||||
gajim.config.get('tooltip_account_name_color'),
|
||||
GLib.markup_escape_text(prim_contact.account.name))
|
||||
color = gajim.config.get('tooltip_account_name_color')
|
||||
account_name = GLib.markup_escape_text(self.prim_contact.account.name)
|
||||
name_markup += " <span foreground='{}'>({})</span>".format(
|
||||
color, account_name)
|
||||
|
||||
if self.account and helpers.jid_is_blocked(self.account,
|
||||
prim_contact.jid):
|
||||
if account and helpers.jid_is_blocked(account, self.prim_contact.jid):
|
||||
name_markup += _(' [blocked]')
|
||||
if self.account and \
|
||||
self.account in gajim.interface.minimized_controls and \
|
||||
prim_contact.jid in gajim.interface.minimized_controls[self.account]:
|
||||
name_markup += _(' [minimized]')
|
||||
properties.append((name_markup, None))
|
||||
|
||||
num_resources = 0
|
||||
try:
|
||||
if self.prim_contact.jid in gajim.interface.minimized_controls[account]:
|
||||
name_markup += _(' [minimized]')
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
self.name.set_markup(name_markup)
|
||||
self.name.show()
|
||||
|
||||
self.num_resources = 0
|
||||
# put contacts in dict, where key is priority
|
||||
contacts_dict = {}
|
||||
for contact in contacts:
|
||||
if contact.resource:
|
||||
num_resources += 1
|
||||
if contact.priority in contacts_dict:
|
||||
contacts_dict[int(contact.priority)].append(contact)
|
||||
self.num_resources += 1
|
||||
priority = int(contact.priority)
|
||||
if priority in contacts_dict:
|
||||
contacts_dict[priority].append(contact)
|
||||
else:
|
||||
contacts_dict[int(contact.priority)] = [contact]
|
||||
|
||||
if num_resources > 1:
|
||||
properties.append((_('Status: '), ' '))
|
||||
transport = gajim.get_transport_name_from_jid(prim_contact.jid)
|
||||
contacts_dict[priority] = [contact]
|
||||
if self.num_resources > 1:
|
||||
self.status_label.show()
|
||||
transport = gajim.get_transport_name_from_jid(self.prim_contact.jid)
|
||||
if transport:
|
||||
file_path = os.path.join(helpers.get_transport_path(transport),
|
||||
'16x16')
|
||||
|
@ -505,98 +602,140 @@ class RosterTooltip(NotificationAreaTooltip):
|
|||
contact_keys.reverse()
|
||||
for priority in contact_keys:
|
||||
for acontact in contacts_dict[priority]:
|
||||
status_line = self.get_status_info(acontact.resource,
|
||||
acontact.priority, acontact.show, acontact.status)
|
||||
|
||||
icon_name = self._get_icon_name_for_tooltip(acontact)
|
||||
if acontact.status and len(acontact.status) > 25:
|
||||
status = ''
|
||||
add_text = True
|
||||
else:
|
||||
status = acontact.status
|
||||
add_text = False
|
||||
|
||||
status_line = self.get_status_info(acontact.resource,
|
||||
acontact.priority, acontact.show, status)
|
||||
self.add_status_row(file_path, icon_name, status_line,
|
||||
acontact.last_status_time)
|
||||
properties.append((self.table, None))
|
||||
if add_text:
|
||||
self.add_text_row(acontact.status, 2)
|
||||
|
||||
else: # only one resource
|
||||
self.tooltip_grid.attach(self.table, 0, 3, 2, 1)
|
||||
self.table.show_all()
|
||||
|
||||
else: # only one resource
|
||||
if contact.show:
|
||||
show = helpers.get_uf_show(contact.show)
|
||||
if not self.check_last_time and self.account:
|
||||
request_time = False
|
||||
try:
|
||||
last_time = self.check_last_time[contact]
|
||||
if isinstance(last_time, float) and last_time < time.time() - 60:
|
||||
request_time = True
|
||||
except KeyError:
|
||||
request_time = True
|
||||
|
||||
if request_time:
|
||||
if contact.show == 'offline':
|
||||
if not contact.last_status_time:
|
||||
gajim.connections[self.account].\
|
||||
request_last_status_time(contact.jid, '')
|
||||
else:
|
||||
self.check_last_time = contact.last_status_time
|
||||
gajim.connections[account].\
|
||||
request_last_status_time(contact.jid, '')
|
||||
elif contact.resource:
|
||||
gajim.connections[self.account].\
|
||||
gajim.connections[account].\
|
||||
request_last_status_time(
|
||||
contact.jid, contact.resource)
|
||||
if contact.last_activity_time:
|
||||
self.check_last_time = contact.last_activity_time
|
||||
else:
|
||||
self.check_last_time = None
|
||||
if contact.last_status_time:
|
||||
vcard_current_row += 1
|
||||
if contact.show == 'offline':
|
||||
text = ' - ' + _('Last status: %s')
|
||||
else:
|
||||
text = _(' since %s')
|
||||
|
||||
if time.strftime('%j', time.localtime()) == \
|
||||
time.strftime('%j', contact.last_status_time):
|
||||
# it's today, show only the locale hour representation
|
||||
local_time = time.strftime('%X',
|
||||
contact.last_status_time)
|
||||
else:
|
||||
# time.strftime returns locale encoded string
|
||||
local_time = time.strftime('%c',
|
||||
contact.last_status_time)
|
||||
|
||||
text = text % local_time
|
||||
show += text
|
||||
if self.account and \
|
||||
prim_contact.jid in gajim.gc_connected[self.account]:
|
||||
if gajim.gc_connected[self.account][prim_contact.jid]:
|
||||
show = _('Connected')
|
||||
else:
|
||||
show = _('Disconnected')
|
||||
show = colorize_status(show)
|
||||
self.check_last_time[contact] = time.time()
|
||||
|
||||
if contact.status:
|
||||
status = contact.status.strip()
|
||||
if status:
|
||||
# reduce long status
|
||||
# (no more than 300 chars on line and no more than
|
||||
# 5 lines)
|
||||
# status is wrapped
|
||||
status = helpers.reduce_chars_newlines(status, 300, 5)
|
||||
# escape markup entities.
|
||||
status = GLib.markup_escape_text(status)
|
||||
properties.append(('<i>%s</i>' % status, None))
|
||||
properties.append((show, None))
|
||||
self.status.set_text(status)
|
||||
self.status.show()
|
||||
self.status_label.show()
|
||||
|
||||
self._append_pep_info(contact, properties)
|
||||
# PEP Info
|
||||
self._append_pep_info(contact)
|
||||
|
||||
properties.append((_('Jabber ID: '), '\u200E' + "<b>%s</b>" % \
|
||||
prim_contact.jid))
|
||||
# JID
|
||||
self.jid.set_text(self.prim_contact.jid)
|
||||
self.jid.show()
|
||||
self.jid_label.show()
|
||||
|
||||
# contact has only one ressource
|
||||
if num_resources == 1 and contact.resource:
|
||||
properties.append((_('Resource: '), GLib.markup_escape_text(
|
||||
contact.resource) + ' (' + str(contact.priority) + ')'))
|
||||
if self.num_resources == 1 and contact.resource:
|
||||
res = GLib.markup_escape_text(contact.resource)
|
||||
prio = str(contact.priority)
|
||||
self.resource.set_text("{} ({})".format(res, prio))
|
||||
self.resource.show()
|
||||
self.resource_label.show()
|
||||
|
||||
if self.account and prim_contact.sub and prim_contact.sub != 'both' and\
|
||||
prim_contact.jid not in gajim.gc_connected[self.account]:
|
||||
# ('both' is the normal sub so we don't show it)
|
||||
properties.append(( _('Subscription: '), GLib.markup_escape_text(
|
||||
helpers.get_uf_sub(prim_contact.sub))))
|
||||
if self.prim_contact.jid not in gajim.gc_connected[account]:
|
||||
if (account and
|
||||
self.prim_contact.sub and
|
||||
self.prim_contact.sub != 'both'):
|
||||
# ('both' is the normal sub so we don't show it)
|
||||
self.sub.set_text(helpers.get_uf_sub(self.prim_contact.sub))
|
||||
self.sub.show()
|
||||
self.sub_label.show()
|
||||
|
||||
if prim_contact.keyID:
|
||||
if self.prim_contact.keyID:
|
||||
keyID = None
|
||||
if len(prim_contact.keyID) == 8:
|
||||
keyID = prim_contact.keyID
|
||||
elif len(prim_contact.keyID) == 16:
|
||||
keyID = prim_contact.keyID[8:]
|
||||
if len(self.prim_contact.keyID) == 8:
|
||||
keyID = self.prim_contact.keyID
|
||||
elif len(self.prim_contact.keyID) == 16:
|
||||
keyID = self.prim_contact.keyID[8:]
|
||||
if keyID:
|
||||
properties.append((_('OpenPGP: '), GLib.markup_escape_text(
|
||||
keyID)))
|
||||
self.pgp.set_text(keyID)
|
||||
self.pgp.show()
|
||||
self.pgp_label.show()
|
||||
|
||||
self._set_idle_time(contact)
|
||||
|
||||
# Avatar
|
||||
puny_jid = helpers.sanitize_filename(self.prim_contact.jid)
|
||||
file_ = helpers.get_avatar_path(os.path.join(gajim.AVATAR_PATH,
|
||||
puny_jid))
|
||||
if file_:
|
||||
with open(file_, 'rb') as file_data:
|
||||
pix = gtkgui_helpers.get_pixbuf_from_data(file_data.read())
|
||||
pix = gtkgui_helpers.get_scaled_pixbuf(pix, 'tooltip')
|
||||
self.avatar.set_from_pixbuf(pix)
|
||||
self.avatar.show()
|
||||
|
||||
# Sets the Widget that is at the bottom to expand.
|
||||
# This is needed in case the Picture takes more Space then the Labels
|
||||
i = 1
|
||||
while i < 15:
|
||||
if self.tooltip_grid.get_child_at(0, i):
|
||||
if self.tooltip_grid.get_child_at(0, i).get_visible():
|
||||
self.last_widget = self.tooltip_grid.get_child_at(0, i)
|
||||
i += 1
|
||||
self.last_widget.set_vexpand(True)
|
||||
|
||||
def _append_pep_info(self, contact):
|
||||
"""
|
||||
Append Tune, Mood, Activity, Location information of the specified contact
|
||||
to the given property list.
|
||||
"""
|
||||
if 'mood' in contact.pep:
|
||||
mood = contact.pep['mood'].asMarkupText()
|
||||
self.mood.set_markup(mood)
|
||||
self.mood.show()
|
||||
self.mood_label.show()
|
||||
|
||||
if 'activity' in contact.pep:
|
||||
activity = contact.pep['activity'].asMarkupText()
|
||||
self.activity.set_markup(activity)
|
||||
self.activity.show()
|
||||
self.activity_label.show()
|
||||
|
||||
if 'tune' in contact.pep:
|
||||
tune = contact.pep['tune'].asMarkupText()
|
||||
self.tune.set_markup(tune)
|
||||
self.tune.show()
|
||||
self.tune_label.show()
|
||||
|
||||
if 'location' in contact.pep:
|
||||
location = contact.pep['location'].asMarkupText()
|
||||
self.location.set_markup(location)
|
||||
self.location.show()
|
||||
self.location_label.show()
|
||||
|
||||
def _set_idle_time(self, contact):
|
||||
if contact.last_activity_time:
|
||||
last_active = datetime(*contact.last_activity_time[:6])
|
||||
current = datetime.now()
|
||||
|
@ -613,78 +752,67 @@ class RosterTooltip(NotificationAreaTooltip):
|
|||
# is no meaningful difference between last activity time and
|
||||
# current time.
|
||||
if diff.days > 0 or diff.seconds > 0:
|
||||
cs = "<span foreground='%s'>" % gajim.config.get(
|
||||
'tooltip_idle_color')
|
||||
cs += '%s</span>'
|
||||
properties.append((str(), None))
|
||||
idle_since = cs % _("Idle since %s")
|
||||
properties.append((idle_since % formatted, None))
|
||||
idle_for = cs % _("Idle for %s")
|
||||
properties.append((idle_for % str(diff), None))
|
||||
idle_color = gajim.config.get('tooltip_idle_color')
|
||||
idle_markup = "<span foreground='{}'>{}</span>".format(idle_color, formatted)
|
||||
self.idle_since.set_markup(idle_markup)
|
||||
self.idle_since.show()
|
||||
self.idle_since_label.show()
|
||||
idle_markup = "<span foreground='{}'>{}</span>".format(idle_color, str(diff))
|
||||
self.idle_for.set_markup(idle_markup)
|
||||
self.idle_for_label.show()
|
||||
self.idle_for.show()
|
||||
|
||||
while properties:
|
||||
property_ = properties.pop(0)
|
||||
vcard_current_row += 1
|
||||
label = Gtk.Label()
|
||||
if not properties and table_size == 4:
|
||||
label.set_vexpand(True)
|
||||
label.set_halign(Gtk.Align.START)
|
||||
label.set_valign(Gtk.Align.START)
|
||||
if property_[1]:
|
||||
label.set_markup(property_[0])
|
||||
vcard_table.attach(label, 1, vcard_current_row, 1, 1)
|
||||
label = Gtk.Label()
|
||||
if not properties and table_size == 4:
|
||||
label.set_vexpand(True)
|
||||
label.set_halign(Gtk.Align.START)
|
||||
label.set_valign(Gtk.Align.START)
|
||||
label.set_markup(property_[1])
|
||||
label.set_line_wrap(True)
|
||||
vcard_table.attach(label, 2, vcard_current_row, 1, 1)
|
||||
else:
|
||||
if isinstance(property_[0], str):
|
||||
label.set_markup(property_[0])
|
||||
label.set_line_wrap(True)
|
||||
if contact.show and self.num_resources < 2:
|
||||
show = helpers.get_uf_show(contact.show)
|
||||
if contact.last_status_time:
|
||||
if contact.show == 'offline':
|
||||
text = ' - ' + _('Last status: %s')
|
||||
else:
|
||||
label = property_[0]
|
||||
vcard_table.attach(label, 1, vcard_current_row, 2, 1)
|
||||
self.avatar_image.set_halign(Gtk.Align.START)
|
||||
self.avatar_image.set_valign(Gtk.Align.START)
|
||||
if table_size == 4:
|
||||
vcard_table.attach(self.avatar_image, 3, 2, 1, vcard_current_row - 1)
|
||||
text = _(' since %s')
|
||||
|
||||
gajim.plugin_manager.gui_extension_point('roster_tooltip_populate',
|
||||
self, contacts, vcard_table)
|
||||
self.win.add(vcard_table)
|
||||
if time.strftime('%j', time.localtime()) == \
|
||||
time.strftime('%j', contact.last_status_time):
|
||||
# it's today, show only the locale hour representation
|
||||
local_time = time.strftime('%X', contact.last_status_time)
|
||||
else:
|
||||
# time.strftime returns locale encoded string
|
||||
local_time = time.strftime('%c', contact.last_status_time)
|
||||
|
||||
def update_last_time(self, last_time):
|
||||
if not self.check_last_time or time.strftime('%x %I:%M %p', last_time) !=\
|
||||
time.strftime('%x %I:%M %p', self.check_last_time):
|
||||
self.win.destroy()
|
||||
self.win = None
|
||||
self.populate(self.cur_data)
|
||||
self.win.show_all()
|
||||
text = text % local_time
|
||||
show += text
|
||||
|
||||
def _append_pep_info(self, contact, properties):
|
||||
# Contact is Groupchat
|
||||
if (self.account and
|
||||
self.prim_contact.jid in gajim.gc_connected[self.account]):
|
||||
if gajim.gc_connected[self.account][self.prim_contact.jid]:
|
||||
show = _('Connected')
|
||||
else:
|
||||
show = _('Disconnected')
|
||||
|
||||
self.user_show.set_markup(colorize_status(show))
|
||||
self.user_show.show()
|
||||
|
||||
def _get_icon_name_for_tooltip(self, contact):
|
||||
"""
|
||||
Append Tune, Mood, Activity, Location information of the specified contact
|
||||
to the given property list.
|
||||
Helper function used for tooltip contacts/acounts
|
||||
|
||||
Tooltip on account has fake contact with sub == '', in this case we show
|
||||
real status of the account
|
||||
"""
|
||||
if 'mood' in contact.pep:
|
||||
mood = contact.pep['mood'].asMarkupText()
|
||||
properties.append((_('Mood: '), "%s" % mood, None))
|
||||
if contact.ask == 'subscribe':
|
||||
return 'requested'
|
||||
elif contact.sub in ('both', 'to', ''):
|
||||
return contact.show
|
||||
return 'not in roster'
|
||||
|
||||
if 'activity' in contact.pep:
|
||||
activity = contact.pep['activity'].asMarkupText()
|
||||
properties.append((_('Activity: '), "%s" % activity, None))
|
||||
|
||||
if 'tune' in contact.pep:
|
||||
tune = contact.pep['tune'].asMarkupText()
|
||||
properties.append((_('Tune: '), "%s" % tune, None))
|
||||
|
||||
if 'location' in contact.pep:
|
||||
location = contact.pep['location'].asMarkupText()
|
||||
properties.append((_('Location: '), "%s" % location, None))
|
||||
def update_last_time(self, contact, error=False):
|
||||
if not contact:
|
||||
return
|
||||
if error:
|
||||
self.check_last_time[contact] = 'error'
|
||||
return
|
||||
if contact.jid == self.contact_jid:
|
||||
self._set_idle_time(contact)
|
||||
|
||||
|
||||
class FileTransfersTooltip(BaseTooltip):
|
||||
|
|
Loading…
Add table
Reference in a new issue