Replace ServiceDiscoveryTooltip with gtk_tree_view.set_tooltip_column().

This commit is contained in:
Emmanuel Gil Peyrot 2016-11-12 23:54:33 +00:00
parent c64ad72cae
commit ec0a11fe1a
2 changed files with 33 additions and 115 deletions

View File

@ -54,7 +54,6 @@ from gi.repository import GdkPixbuf
from gi.repository import Pango from gi.repository import Pango
import dialogs import dialogs
import tooltips
import gtkgui_helpers import gtkgui_helpers
import groups import groups
import adhoc_commands import adhoc_commands
@ -66,6 +65,12 @@ from common.exceptions import GajimGeneralException
from common import helpers from common import helpers
from common import ged from common import ged
LABELS = {
1: _('This service has not yet responded with detailed information'),
2: _('This service could not respond with detailed information.\n'
'It is most likely legacy or broken'),
}
# Dictionary mapping category, type pairs to browser class, image pairs. # Dictionary mapping category, type pairs to browser class, image pairs.
# This is a function, so we can call it after the classes are declared. # This is a function, so we can call it after the classes are declared.
# For the browser class, None means that the service will only be browsable # For the browser class, None means that the service will only be browsable
@ -119,13 +124,13 @@ def _gen_agent_type_info():
('gateway', 'twitter'): (False, 'twitter'), ('gateway', 'twitter'): (False, 'twitter'),
} }
# Category type to "human-readable" description string, and sort priority # Category type to "human-readable" description string
_cat_to_descr = { _cat_to_descr = {
'other': (_('Others'), 2), 'other': _('Others'),
'gateway': (_('Transports'), 0), 'gateway': _('Transports'),
'_jid': (_('Transports'), 0), '_jid': _('Transports'),
#conference is a category for listing mostly groupchats in service discovery #conference is a category for listing mostly groupchats in service discovery
'conference': (_('Conference'), 1), 'conference': _('Conference'),
} }
@ -1217,7 +1222,6 @@ class ToplevelAgentBrowser(AgentBrowser):
self._progressbar_sourceid = None self._progressbar_sourceid = None
self._renderer = None self._renderer = None
self._progress = 0 self._progress = 0
self.tooltip = tooltips.ServiceDiscoveryTooltip()
self.register_button = None self.register_button = None
self.join_button = None self.join_button = None
self.execute_button = None self.execute_button = None
@ -1238,7 +1242,7 @@ class ToplevelAgentBrowser(AgentBrowser):
identities.append(identity) identities.append(identity)
# Set the pixmap for the row # Set the pixmap for the row
pix = self.cache.get_icon(identities, addr=addr) pix = self.cache.get_icon(identities, addr=addr)
self.model.append(None, (self.jid, self.node, pix, descr, 1)) self.model.append(None, (self.jid, self.node, pix, descr, LABELS[1]))
# Grab info on the service # Grab info on the service
self.cache.get_info(self.jid, self.node, self._agent_info, force=False) self.cache.get_info(self.jid, self.node, self._agent_info, force=False)
@ -1264,8 +1268,8 @@ class ToplevelAgentBrowser(AgentBrowser):
cell.set_property('markup', markup) cell.set_property('markup', markup)
if jid: if jid:
cell.set_property('cell_background_set', False) cell.set_property('cell_background_set', False)
if state > 0: if state is not None:
# 1 = fetching, 2 = error # fetching or error
cell.set_property('foreground_set', True) cell.set_property('foreground_set', True)
else: else:
# Normal/succes # Normal/succes
@ -1284,9 +1288,9 @@ class ToplevelAgentBrowser(AgentBrowser):
# Compare state # Compare state
state1 = model.get_value(iter1, 4) state1 = model.get_value(iter1, 4)
state2 = model.get_value(iter2, 4) state2 = model.get_value(iter2, 4)
if state1 > state2: if state1 is not None:
return 1 return 1
if state1 < state2: if state2 is not None:
return -1 return -1
descr1 = model.get_value(iter1, 3) descr1 = model.get_value(iter1, 3)
descr2 = model.get_value(iter2, 3) descr2 = model.get_value(iter2, 3)
@ -1297,64 +1301,12 @@ class ToplevelAgentBrowser(AgentBrowser):
return -1 return -1
return 0 return 0
def _show_tooltip(self, state):
self.tooltip.timeout = 0
view = self.window.services_treeview
w = view.get_window()
device = w.get_display().get_device_manager().get_client_pointer()
pointer = w.get_device_position(device)
props = view.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 = view.get_cell_area(props[0], props[1])
# position of the treeview on the screen
position = w.get_origin()[1:]
self.tooltip.show_tooltip(state, rect.height, position[1] + rect.y)
else:
self.tooltip.hide_tooltip()
# These are all callbacks to make tooltips work
def on_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_treeview_motion_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()
if props:
row = props[0]
iter_ = None
try:
iter_ = self.model.get_iter(row)
except Exception:
self.tooltip.hide_tooltip()
return
jid = self.model[iter_][0]
state = self.model[iter_][4]
# Not a category, and we have something to say about state
if jid and state > 0 and \
(self.tooltip.timeout == 0 or self.tooltip.id != props[0]):
self.tooltip.id = row
self.tooltip.timeout = GLib.timeout_add(500, self._show_tooltip,
state)
def on_treeview_event_hide_tooltip(self, widget, event):
"""
This happens on scroll_event, key_press_event and button_press_event
"""
self.tooltip.hide_tooltip()
def _create_treemodel(self): def _create_treemodel(self):
# JID, node, icon, description, state # JID, node, icon, description, state
# State means 2 when error, 1 when fetching, 0 when succes. # state is None on sucess or has a string
# from LABELS on error or while fetching
view = self.window.services_treeview view = self.window.services_treeview
self.model = Gtk.TreeStore(str, str, GdkPixbuf.Pixbuf, str, int) self.model = Gtk.TreeStore(str, str, GdkPixbuf.Pixbuf, str, str)
self.model.set_sort_func(4, self._treemodel_sort_func) self.model.set_sort_func(4, self._treemodel_sort_func)
self.model.set_sort_column_id(4, Gtk.SortType.ASCENDING) self.model.set_sort_column_id(4, Gtk.SortType.ASCENDING)
view.set_model(self.model) view.set_model(self.model)
@ -1374,22 +1326,10 @@ class ToplevelAgentBrowser(AgentBrowser):
self._renderer = renderer self._renderer = renderer
self.update_theme() self.update_theme()
view.set_tooltip_column(4)
view.insert_column(col, -1) view.insert_column(col, -1)
col.set_resizable(True) col.set_resizable(True)
# Connect signals
scrollwin = self.window.services_scrollwin
self._view_signals.append(view.connect('leave-notify-event',
self.on_treeview_leave_notify_event))
self._view_signals.append(view.connect('motion-notify-event',
self.on_treeview_motion_notify_event))
self._view_signals.append(view.connect('key-press-event',
self.on_treeview_event_hide_tooltip))
self._view_signals.append(view.connect('button-press-event',
self.on_treeview_event_hide_tooltip))
self._scroll_signal = scrollwin.connect('scroll-event',
self.on_treeview_event_hide_tooltip)
def _clean_treemodel(self): def _clean_treemodel(self):
# Disconnect signals # Disconnect signals
view = self.window.services_treeview view = self.window.services_treeview
@ -1468,7 +1408,6 @@ class ToplevelAgentBrowser(AgentBrowser):
search_window.SearchWindow(self.account, service) search_window.SearchWindow(self.account, service)
def cleanup(self): def cleanup(self):
self.tooltip.hide_tooltip()
AgentBrowser.cleanup(self) AgentBrowser.cleanup(self)
def update_theme(self): def update_theme(self):
@ -1536,7 +1475,7 @@ class ToplevelAgentBrowser(AgentBrowser):
if not model[iter_][0]: if not model[iter_][0]:
# We're on a category row # We're on a category row
return return
if model[iter_][4] != 0: if model[iter_][4] is not None:
# We don't have the info (yet) # We don't have the info (yet)
# It's either unknown or a transport, register button should be active # It's either unknown or a transport, register button should be active
if self.register_button: if self.register_button:
@ -1644,34 +1583,34 @@ class ToplevelAgentBrowser(AgentBrowser):
def _friendly_category(self, category, type_=None): def _friendly_category(self, category, type_=None):
""" """
Get the friendly category name and priority Get the friendly category name
""" """
cat = None cat = None
if type_: if type_:
# Try type-specific override # Try type-specific override
try: try:
cat, prio = _cat_to_descr[(category, type_)] cat = _cat_to_descr[(category, type_)]
except KeyError: except KeyError:
pass pass
if not cat: if not cat:
try: try:
cat, prio = _cat_to_descr[category] cat = _cat_to_descr[category]
except KeyError: except KeyError:
cat, prio = _cat_to_descr['other'] cat = _cat_to_descr['other']
return cat, prio return cat
def _create_category(self, cat, type_=None): def _create_category(self, cat, type_=None):
""" """
Creates a category row Creates a category row
""" """
cat, prio = self._friendly_category(cat, type_) cat = self._friendly_category(cat, type_)
return self.model.append(None, ('', '', None, cat, prio)) return self.model.append(None, ('', '', None, cat, None))
def _find_category(self, cat, type_=None): def _find_category(self, cat, type_=None):
""" """
Looks up a category row and returns the iterator to it, or None Looks up a category row and returns the iterator to it, or None
""" """
cat = self._friendly_category(cat, type_)[0] cat = self._friendly_category(cat, type_)
iter_ = self.model.get_iter_first() iter_ = self.model.get_iter_first()
while iter_: while iter_:
if self.model.get_value(iter_, 3) == cat: if self.model.get_value(iter_, 3) == cat:
@ -1726,7 +1665,7 @@ class ToplevelAgentBrowser(AgentBrowser):
cat = self._find_category(*cat_args) cat = self._find_category(*cat_args)
if not cat: if not cat:
cat = self._create_category(*cat_args) cat = self._create_category(*cat_args)
self.model.append(cat, (jid, node, pix, descr, 1)) self.model.append(cat, (jid, node, pix, descr, LABELS[1]))
GLib.idle_add(self._expand_all) GLib.idle_add(self._expand_all)
# Grab info on the service # Grab info on the service
self.cache.get_info(jid, node, self._agent_info, force=force) self.cache.get_info(jid, node, self._agent_info, force=force)
@ -1768,7 +1707,7 @@ class ToplevelAgentBrowser(AgentBrowser):
# Already in the right category, just update # Already in the right category, just update
self.model[iter_][2] = pix self.model[iter_][2] = pix
self.model[iter_][3] = descr self.model[iter_][3] = descr
self.model[iter_][4] = 0 self.model[iter_][4] = None
return return
# Not in the right category, move it. # Not in the right category, move it.
self.model.remove(iter_) self.model.remove(iter_)
@ -1783,11 +1722,11 @@ class ToplevelAgentBrowser(AgentBrowser):
cat_iter = self._find_category(cat, type_) cat_iter = self._find_category(cat, type_)
if not cat_iter: if not cat_iter:
cat_iter = self._create_category(cat, type_) cat_iter = self._create_category(cat, type_)
self.model.append(cat_iter, (jid, node, pix, descr, 0)) self.model.append(cat_iter, (jid, node, pix, descr, None))
self._expand_all() self._expand_all()
def _update_error(self, iter_, jid, node): def _update_error(self, iter_, jid, node):
self.model[iter_][4] = 2 self.model[iter_][4] = LABELS[2]
self._progress += 1 self._progress += 1
self._update_progressbar() self._update_progressbar()

View File

@ -816,24 +816,3 @@ class FileTransfersTooltip(BaseTooltip):
Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL, 0, 0) Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL, 0, 0)
self.win.add(ft_table) self.win.add(ft_table)
class ServiceDiscoveryTooltip(BaseTooltip):
"""
Tooltip that is shown when hovering over a service discovery row
"""
def populate(self, status):
self.create_window()
label = Gtk.Label()
label.set_line_wrap(True)
label.set_halign(Gtk.Align.START)
label.set_valign(Gtk.Align.START)
label.set_selectable(False)
if status == 1:
label.set_text(
_('This service has not yet responded with detailed information'))
elif status == 2:
label.set_text(
_('This service could not respond with detailed information.\n'
'It is most likely legacy or broken'))
self.win.add(label)