Refactor GC Roster tooltip
This commit is contained in:
parent
ec0a11fe1a
commit
7a278d9123
|
@ -0,0 +1,145 @@
|
|||
<?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="column_spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="nick">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="xalign">0</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</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="status">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="max_width_chars">40</property>
|
||||
<property name="xalign">0</property>
|
||||
<attributes>
|
||||
<attribute name="style" value="italic"/>
|
||||
</attributes>
|
||||
</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="jid_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="label" translatable="yes">Jabber ID:</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="avatar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</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">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="resource_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="label" translatable="yes">Resource:</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="affiliation">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="user_show">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="fillelement">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="vexpand">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">6</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="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="jid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
|
@ -360,6 +360,12 @@ class GroupchatControl(ChatControlBase):
|
|||
img = self.xml.get_object('history_image')
|
||||
img.set_from_icon_name('document-open-recent', Gtk.IconSize.MENU)
|
||||
widget = self.xml.get_object('list_treeview')
|
||||
widget.set_has_tooltip(True)
|
||||
widget.set_tooltip_window(tooltips.GCTooltip(self.parent_win.window))
|
||||
self.current_tooltip = None
|
||||
id_ = widget.connect('query-tooltip', self.query_tooltip)
|
||||
self.handlers[id_] = widget
|
||||
|
||||
id_ = widget.connect('row_expanded', self.on_list_treeview_row_expanded)
|
||||
self.handlers[id_] = widget
|
||||
|
||||
|
@ -379,14 +385,6 @@ class GroupchatControl(ChatControlBase):
|
|||
self.on_list_treeview_key_press_event)
|
||||
self.handlers[id_] = widget
|
||||
|
||||
id_ = widget.connect('motion_notify_event',
|
||||
self.on_list_treeview_motion_notify_event)
|
||||
self.handlers[id_] = widget
|
||||
|
||||
id_ = widget.connect('leave_notify_event',
|
||||
self.on_list_treeview_leave_notify_event)
|
||||
self.handlers[id_] = widget
|
||||
|
||||
self.room_jid = self.contact.jid
|
||||
self.nick = contact.name
|
||||
self.new_nick = ''
|
||||
|
@ -419,8 +417,6 @@ class GroupchatControl(ChatControlBase):
|
|||
|
||||
self.subject = ''
|
||||
|
||||
self.tooltip = tooltips.GCTooltip()
|
||||
|
||||
# nickname coloring
|
||||
self.gc_count_nicknames_colors = -1
|
||||
self.gc_custom_colors = {}
|
||||
|
@ -530,6 +526,46 @@ class GroupchatControl(ChatControlBase):
|
|||
# instance object
|
||||
gajim.plugin_manager.gui_extension_point('groupchat_control', self)
|
||||
|
||||
def query_tooltip(self, widget, x_pos, y_pos, keyboard_mode, tooltip):
|
||||
try:
|
||||
row = self.list_treeview.get_path_at_pos(x_pos, y_pos)[0]
|
||||
except TypeError:
|
||||
return False
|
||||
if not row:
|
||||
return False
|
||||
|
||||
iter_ = None
|
||||
try:
|
||||
iter_ = self.model.get_iter(row)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
typ = self.model[iter_][C_TYPE]
|
||||
nick = self.model[iter_][C_NICK]
|
||||
|
||||
if typ != 'contact':
|
||||
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
|
||||
|
||||
contact = gajim.contacts.get_gc_contact(
|
||||
self.account, self.room_jid, nick)
|
||||
if not contact:
|
||||
return False
|
||||
|
||||
tooltip.populate(contact)
|
||||
return True
|
||||
|
||||
def fill_column(self, col):
|
||||
for rend in self.renderers_list:
|
||||
col.pack_start(rend[1], rend[2])
|
||||
|
@ -2638,8 +2674,6 @@ class GroupchatControl(ChatControlBase):
|
|||
"""
|
||||
Popup user's group's or agent menu
|
||||
"""
|
||||
# hide tooltip, no matter the button is pressed
|
||||
self.tooltip.hide_tooltip()
|
||||
try:
|
||||
pos = widget.get_path_at_pos(int(event.x), int(event.y))
|
||||
path, x = pos[0], pos[2]
|
||||
|
@ -2697,55 +2731,6 @@ class GroupchatControl(ChatControlBase):
|
|||
add = gc_refer_to_nick_char + ' '
|
||||
message_buffer.insert_at_cursor(start + nick + add)
|
||||
|
||||
def on_list_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, col, x, y] = props
|
||||
iter_ = None
|
||||
try:
|
||||
iter_ = self.model.get_iter(row)
|
||||
except Exception:
|
||||
self.tooltip.hide_tooltip()
|
||||
return
|
||||
typ = self.model[iter_][C_TYPE]
|
||||
if typ == 'contact':
|
||||
account = self.account
|
||||
|
||||
if self.tooltip.timeout == 0 or self.tooltip.id != props[0]:
|
||||
self.tooltip.id = row
|
||||
nick = self.model[iter_][C_NICK]
|
||||
self.tooltip.timeout = GLib.timeout_add(500,
|
||||
self.show_tooltip, gajim.contacts.get_gc_contact(
|
||||
account, self.room_jid, nick))
|
||||
|
||||
def on_list_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 show_tooltip(self, contact):
|
||||
self.tooltip.timeout = 0
|
||||
if not self.list_treeview.get_window():
|
||||
# control has been destroyed since tooltip was requested
|
||||
return
|
||||
w = self.list_treeview.get_window()
|
||||
device = w.get_display().get_device_manager().get_client_pointer()
|
||||
pointer = w.get_device_position(device)
|
||||
props = self.list_treeview.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]:
|
||||
rect = self.list_treeview.get_cell_area(props[0], props[1])
|
||||
position = w.get_origin()[1:]
|
||||
self.tooltip.show_tooltip(contact, rect.height,
|
||||
position[1] + rect.y)
|
||||
else:
|
||||
self.tooltip.hide_tooltip()
|
||||
|
||||
def grant_voice(self, widget, nick):
|
||||
"""
|
||||
Grant voice privilege to a user
|
||||
|
|
218
src/tooltips.py
218
src/tooltips.py
|
@ -188,50 +188,6 @@ class BaseTooltip:
|
|||
self.check_last_time = None
|
||||
self.shown = False
|
||||
|
||||
@staticmethod
|
||||
def colorize_status(status):
|
||||
"""
|
||||
Colorize the status message inside the tooltip by it's
|
||||
semantics. Color palette is the Tango.
|
||||
"""
|
||||
formatted = "<span foreground='%s'>%s</span>"
|
||||
color = None
|
||||
if status.startswith(Q_("?user status:Available")):
|
||||
color = gajim.config.get('tooltip_status_online_color')
|
||||
elif status.startswith(_("Free for Chat")):
|
||||
color = gajim.config.get('tooltip_status_free_for_chat_color')
|
||||
elif status.startswith(_("Away")):
|
||||
color = gajim.config.get('tooltip_status_away_color')
|
||||
elif status.startswith(_("Busy")):
|
||||
color = gajim.config.get('tooltip_status_busy_color')
|
||||
elif status.startswith(_("Not Available")):
|
||||
color = gajim.config.get('tooltip_status_na_color')
|
||||
elif status.startswith(_("Offline")):
|
||||
color = gajim.config.get('tooltip_status_offline_color')
|
||||
if color:
|
||||
status = formatted % (color, status)
|
||||
return status
|
||||
|
||||
@staticmethod
|
||||
def colorize_affiliation(affiliation):
|
||||
"""
|
||||
Color the affiliation of a MUC participant inside the tooltip by
|
||||
it's semantics. Color palette is the Tango.
|
||||
"""
|
||||
formatted = "<span foreground='%s'>%s</span>"
|
||||
color = None
|
||||
if affiliation.startswith(Q_("?Group Chat Contact Affiliation:None")):
|
||||
color = gajim.config.get('tooltip_affiliation_none_color')
|
||||
elif affiliation.startswith(_("Member")):
|
||||
color = gajim.config.get('tooltip_affiliation_member_color')
|
||||
elif affiliation.startswith(_("Administrator")):
|
||||
color = gajim.config.get('tooltip_affiliation_administrator_color')
|
||||
elif affiliation.startswith(_("Owner")):
|
||||
color = gajim.config.get('tooltip_affiliation_owner_color')
|
||||
if color:
|
||||
affiliation = formatted % (color, affiliation)
|
||||
return affiliation
|
||||
|
||||
class StatusTable:
|
||||
"""
|
||||
Contains methods for creating status table. This is used in Roster and
|
||||
|
@ -356,68 +312,76 @@ class NotificationAreaTooltip(BaseTooltip, StatusTable):
|
|||
self.hbox.add(self.table)
|
||||
self.hbox.show_all()
|
||||
|
||||
class GCTooltip(BaseTooltip):
|
||||
"""
|
||||
Tooltip that is shown in the GC treeview
|
||||
"""
|
||||
class GCTooltip(Gtk.Window):
|
||||
# pylint: disable=E1101
|
||||
def __init__(self, parent):
|
||||
super().__init__(self, type=Gtk.WindowType.POPUP, transient_for=parent)
|
||||
self.row = None
|
||||
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)
|
||||
|
||||
def __init__(self):
|
||||
self.account = None
|
||||
self.text_label = Gtk.Label()
|
||||
self.text_label.set_line_wrap(True)
|
||||
self.text_label.set_halign(Gtk.Align.START)
|
||||
self.text_label.set_valign(Gtk.Align.START)
|
||||
self.text_label.set_selectable(False)
|
||||
self.avatar_image = Gtk.Image()
|
||||
self.xml = gtkgui_helpers.get_gtk_builder('tooltip_gc_contact.ui')
|
||||
for name in ('nick', 'status', 'jid', 'user_show', 'fillelement',
|
||||
'resource', 'affiliation', 'avatar', 'resource_label',
|
||||
'jid_label', 'tooltip_grid'):
|
||||
setattr(self, name, self.xml.get_object(name))
|
||||
|
||||
BaseTooltip.__init__(self)
|
||||
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()
|
||||
|
||||
def populate(self, contact):
|
||||
if not contact:
|
||||
return
|
||||
self.create_window()
|
||||
vcard_table = Gtk.Grid()
|
||||
vcard_table.insert_row(0)
|
||||
vcard_table.insert_row(0)
|
||||
vcard_table.insert_row(0)
|
||||
vcard_table.insert_column(0)
|
||||
vcard_table.set_property('column-spacing', 2)
|
||||
vcard_current_row = 1
|
||||
properties = []
|
||||
"""
|
||||
Populate the Tooltip Grid with data of from the contact
|
||||
"""
|
||||
self.clear_tooltip()
|
||||
|
||||
nick_markup = '<b>' + GLib.markup_escape_text(contact.get_shown_name())\
|
||||
+ '</b>'
|
||||
properties.append((nick_markup, None))
|
||||
self.nick.set_text(contact.get_shown_name())
|
||||
self.nick.show()
|
||||
|
||||
if contact.status: # status message
|
||||
# Status Message
|
||||
if contact.status:
|
||||
status = contact.status.strip()
|
||||
if status != '':
|
||||
# escape markup entities
|
||||
status = helpers.reduce_chars_newlines(status, 300, 5)
|
||||
status = '<i>' + GLib.markup_escape_text(status) + '</i>'
|
||||
properties.append((status, None))
|
||||
self.status.set_text(status)
|
||||
self.status.show()
|
||||
|
||||
# Status
|
||||
show = helpers.get_uf_show(contact.show)
|
||||
show = self.colorize_status(show)
|
||||
properties.append((show, None))
|
||||
self.user_show.set_markup(colorize_status(show))
|
||||
self.user_show.show()
|
||||
|
||||
# JID
|
||||
if contact.jid.strip():
|
||||
properties.append((_('Jabber ID: '), '\u200E' + "<b>%s</b>" % \
|
||||
contact.jid))
|
||||
|
||||
self.jid.set_text(contact.jid)
|
||||
self.jid.show()
|
||||
self.jid_label.show()
|
||||
# Resource
|
||||
if hasattr(contact, 'resource') and contact.resource.strip():
|
||||
properties.append((_('Resource: '), GLib.markup_escape_text(
|
||||
contact.resource)))
|
||||
self.resource.set_text(contact.resource)
|
||||
self.resource.show()
|
||||
self.resource_label.show()
|
||||
|
||||
# Affiliation
|
||||
if contact.affiliation != 'none':
|
||||
uf_affiliation = helpers.get_uf_affiliation(contact.affiliation)
|
||||
uf_affiliation = \
|
||||
_('%(owner_or_admin_or_member)s of this group chat') % \
|
||||
{'owner_or_admin_or_member': uf_affiliation}
|
||||
_('%(owner_or_admin_or_member)s of this group chat') \
|
||||
% {'owner_or_admin_or_member': uf_affiliation}
|
||||
uf_affiliation = self.colorize_affiliation(uf_affiliation)
|
||||
properties.append((uf_affiliation, None))
|
||||
self.affiliation.set_markup(uf_affiliation)
|
||||
self.affiliation.show()
|
||||
|
||||
# Add avatar
|
||||
# Avatar
|
||||
puny_name = helpers.sanitize_filename(contact.name)
|
||||
puny_room = helpers.sanitize_filename(contact.room_jid)
|
||||
file_ = helpers.get_avatar_path(os.path.join(gajim.AVATAR_PATH,
|
||||
|
@ -426,39 +390,29 @@ class GCTooltip(BaseTooltip):
|
|||
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)
|
||||
else:
|
||||
self.avatar_image.set_from_pixbuf(None)
|
||||
while properties:
|
||||
property_ = properties.pop(0)
|
||||
vcard_current_row += 1
|
||||
label = Gtk.Label()
|
||||
if not properties:
|
||||
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:
|
||||
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:
|
||||
label.set_markup(property_[0])
|
||||
label.set_line_wrap(True)
|
||||
vcard_table.attach(label, 1, vcard_current_row, 2, 1)
|
||||
self.avatar.set_from_pixbuf(pix)
|
||||
self.avatar.show()
|
||||
self.fillelement.show()
|
||||
|
||||
self.avatar_image.set_halign(Gtk.Align.START)
|
||||
self.avatar_image.set_valign(Gtk.Align.START)
|
||||
vcard_table.attach(self.avatar_image, 3, 2, 1, vcard_current_row - 1)
|
||||
gajim.plugin_manager.gui_extension_point('gc_tooltip_populate',
|
||||
self, contact, vcard_table)
|
||||
self.win.add(vcard_table)
|
||||
@staticmethod
|
||||
def colorize_affiliation(affiliation):
|
||||
"""
|
||||
Color the affiliation of a MUC participant inside the tooltip by
|
||||
it's semantics. Color palette is the Tango.
|
||||
"""
|
||||
formatted = "<span foreground='%s'>%s</span>"
|
||||
color = None
|
||||
if affiliation.startswith(Q_("?Group Chat Contact Affiliation:None")):
|
||||
color = gajim.config.get('tooltip_affiliation_none_color')
|
||||
elif affiliation.startswith(_("Member")):
|
||||
color = gajim.config.get('tooltip_affiliation_member_color')
|
||||
elif affiliation.startswith(_("Administrator")):
|
||||
color = gajim.config.get('tooltip_affiliation_administrator_color')
|
||||
elif affiliation.startswith(_("Owner")):
|
||||
color = gajim.config.get('tooltip_affiliation_owner_color')
|
||||
if color:
|
||||
affiliation = formatted % (color, affiliation)
|
||||
return affiliation
|
||||
|
||||
class RosterTooltip(NotificationAreaTooltip):
|
||||
"""
|
||||
|
@ -602,7 +556,7 @@ class RosterTooltip(NotificationAreaTooltip):
|
|||
show = _('Connected')
|
||||
else:
|
||||
show = _('Disconnected')
|
||||
show = self.colorize_status(show)
|
||||
show = colorize_status(show)
|
||||
|
||||
if contact.status:
|
||||
status = contact.status.strip()
|
||||
|
@ -816,3 +770,27 @@ class FileTransfersTooltip(BaseTooltip):
|
|||
Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL, 0, 0)
|
||||
|
||||
self.win.add(ft_table)
|
||||
|
||||
|
||||
def colorize_status(status):
|
||||
"""
|
||||
Colorize the status message inside the tooltip by it's
|
||||
semantics. Color palette is the Tango.
|
||||
"""
|
||||
formatted = "<span foreground='%s'>%s</span>"
|
||||
color = None
|
||||
if status.startswith(Q_("?user status:Available")):
|
||||
color = gajim.config.get('tooltip_status_online_color')
|
||||
elif status.startswith(_("Free for Chat")):
|
||||
color = gajim.config.get('tooltip_status_free_for_chat_color')
|
||||
elif status.startswith(_("Away")):
|
||||
color = gajim.config.get('tooltip_status_away_color')
|
||||
elif status.startswith(_("Busy")):
|
||||
color = gajim.config.get('tooltip_status_busy_color')
|
||||
elif status.startswith(_("Not Available")):
|
||||
color = gajim.config.get('tooltip_status_na_color')
|
||||
elif status.startswith(_("Offline")):
|
||||
color = gajim.config.get('tooltip_status_offline_color')
|
||||
if color:
|
||||
status = formatted % (color, status)
|
||||
return status
|
Loading…
Reference in New Issue