5
A widget to represent a notification.
10
from gi.repository import GLib, GObject, Gtk, Pango
15
from RoundedWidgets import RoundedBox, RoundedIcon
16
from Translations import _
18
logger = logging.getLogger("MessageItem")
22
label.set_use_markup(True)
23
label.set_selectable(True)
24
label.set_line_wrap(True)
25
label.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR)
26
label.set_alignment(0, 0)
27
label.set_size_request(300, -1)
30
def escape_text(text):
31
return GLib.markup_escape_text(text, len(text))
33
class MessageItem(RoundedBox):
34
"""A widget to represent a notification"""
35
def __init__(self, message):
36
RoundedBox.__init__(self)
38
self.set_border_width(2)
42
self._message = message
43
self._message_icon_size = 48
45
self._hbox = Gtk.HBox()
46
self._hbox.set_border_width(10)
49
self._image = RoundedIcon(radius = 5)
50
self._hbox.pack_start(self._image, False, False, 10)
53
self._vbox = Gtk.VBox()
54
self._hbox.pack_start(self._vbox, True, True, 0)
56
self._summary_hbox = Gtk.HBox()
57
self._vbox.pack_start(self._summary_hbox, False, False, 1)
59
self._image_unread = Gtk.Image()
60
self._summary_hbox.pack_start(self._image_unread, False, False, 5)
63
pixbuf = Icon.load("notification-new", 16)
65
logger.exception("Failed to load notification-new icon.")
67
self._image_unread.set_from_pixbuf(pixbuf)
69
self._label_summary = create_label()
70
self._summary_hbox.pack_start(self._label_summary, True, True, 0)
72
self._label_body = create_label()
73
self._vbox.pack_start(self._label_body, True, True, 1)
75
self._label_info = create_label()
76
self._vbox.pack_start(self._label_info, False, False, 0)
79
def get_app_name(self):
80
"""Returns the app_name of this item"""
81
return self._message.app_name
83
def escape_body(self, text):
84
"""Text needs to be escaped in case it contains characters that will cause errors
85
parsing the markup, but some clients send text that is already escaped. This causes
86
messages to have &, <, and > strings instead of the appropriate characters.
87
This method replaces those with the appropriate characters and then escapes the text.
88
TODO: Create a better HTML/entity parser.
90
result = text.replace("&", "&")
91
result = result.replace("'", "'")
92
result = result.replace(">", ">")
93
result = result.replace("<", "<")
94
result = result.replace(""", '"')
95
return self.markup_links(escape_text(result))
98
"""Get the unread status of this message"""
101
def set_unread(self, unread):
102
"""Sets the unread status of this messages and the visibility of the icon"""
103
if unread and not self._unread:
105
self._image_unread.show()
106
self._summary_hbox.pack_start(self._image_unread, False, False, 5)
107
self._summary_hbox.reorder_child(self._image_unread, 0)
109
elif not unread and self._unread:
111
self._image_unread.hide()
112
self._summary_hbox.remove(self._image_unread)
114
def set_width(self, width):
115
"""Updates the wrap width of the labels in this message item, minus the icon
116
size and various padding."""
117
new_width = width - self._message_icon_size - 60
118
self._label_summary.set_size_request(new_width, -1)
119
self._label_body.set_size_request(new_width, -1)
120
self._label_info.set_size_request(new_width, -1)
122
def markup_links(self, text):
123
"""Filters escaped text for web links and makes them clickable"""
125
for s in text.split():
126
if s.startswith("http://"):
129
result.append('<a href="{0}">{1}</a>'.format(url, name))
130
elif s.startswith("www."):
133
result.append('<a href="{0}">{1}</a>'.format(url, name))
137
return " ".join(result)
139
def update_image(self):
140
"""Updates the image"""
142
pixbuf = self._message.get_icon(self._message_icon_size)
144
logger.exception("Failed to get icon: {0}".format(self._message.app_icon))
146
self._image.set_from_pixbuf(pixbuf)
148
def update_labels(self):
149
"""Updates the label markup"""
150
summary = escape_text(self._message.summary.encode("utf8"))
151
body = self.escape_body(self._message.body.encode("utf8"))
152
timestamp = escape_text(Timestamp.locale_datetime(self._message.timestamp))
153
app_name = escape_text(self._message.app_name)
155
self._label_summary.set_markup("<b>{0}</b>".format(summary))
156
self._label_body.set_markup(body)
157
self._label_info.set_markup("<small><i>{0} {1} <b>{2}</b></i></small>".format(timestamp,
158
_("from"), app_name))