~jconti/recent-notifications/trunk

181 by Jason Conti
Adding MessageItem.py to test using regular widgets to display notifications.
1
"""
2
MessageItem.py
3
March 28, 2011
4
5
A widget to represent a notification.
6
"""
7
8
import logging
9
182 by Jason Conti
MessageItem labels now wrap, increased the icon size, and made links clickable.
10
from gi.repository import GLib, GObject, Gtk, Pango
181 by Jason Conti
Adding MessageItem.py to test using regular widgets to display notifications.
11
185 by Jason Conti
Adding an icon to MessageItem to show its unread status. Removed MessageList.py since it is no longer used.
12
import Icon
181 by Jason Conti
Adding MessageItem.py to test using regular widgets to display notifications.
13
import Timestamp
14
201 by Jason Conti
Using a bit of cairo to display icons with rounded edges and message items with rounded backgrounds. Still need to get the proper colors from the gtk theme and possibly add options for custom colors.
15
from RoundedWidgets import RoundedBox, RoundedIcon
205 by Jason Conti
Added theme support. User themes are stored in ~/.config/recent-notifications/themes/, see themes/default for the proper format. The desired theme is set with the theme property in ~/.config/recent-notifications/preferences. Still need to add support for acquiring the colors from the system gtk theme.
16
from Theme import Color
181 by Jason Conti
Adding MessageItem.py to test using regular widgets to display notifications.
17
from Translations import _
18
19
logger = logging.getLogger("MessageItem")
20
185 by Jason Conti
Adding an icon to MessageItem to show its unread status. Removed MessageList.py since it is no longer used.
21
def create_label():
22
  label = Gtk.Label()
23
  label.set_use_markup(True)
196 by Jason Conti
Updated the number of translatable strings and fixed the labels so they properly rewrap when the window is resized in the experimental unity version.
24
  label.set_selectable(True)
185 by Jason Conti
Adding an icon to MessageItem to show its unread status. Removed MessageList.py since it is no longer used.
25
  label.set_line_wrap(True)
26
  label.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR)
27
  label.set_alignment(0, 0)
28
  label.set_size_request(300, -1)
29
  return label
181 by Jason Conti
Adding MessageItem.py to test using regular widgets to display notifications.
30
31
def escape_text(text):
32
  return GLib.markup_escape_text(text, len(text))
33
201 by Jason Conti
Using a bit of cairo to display icons with rounded edges and message items with rounded backgrounds. Still need to get the proper colors from the gtk theme and possibly add options for custom colors.
34
class MessageItem(RoundedBox):
181 by Jason Conti
Adding MessageItem.py to test using regular widgets to display notifications.
35
  """A widget to represent a notification"""
36
  def __init__(self, message):
201 by Jason Conti
Using a bit of cairo to display icons with rounded edges and message items with rounded backgrounds. Still need to get the proper colors from the gtk theme and possibly add options for custom colors.
37
    RoundedBox.__init__(self)
181 by Jason Conti
Adding MessageItem.py to test using regular widgets to display notifications.
38
182 by Jason Conti
MessageItem labels now wrap, increased the icon size, and made links clickable.
39
    self.set_border_width(2)
207 by Jason Conti
Setting most of the colors with a gtk rc style now, except RoundedBox, because I can't figure out how to get the background style color. Seems like it should be widget.style.bg[state] however that list is always empty.
40
    self.set_name("message_item")
182 by Jason Conti
MessageItem labels now wrap, increased the icon size, and made links clickable.
41
185 by Jason Conti
Adding an icon to MessageItem to show its unread status. Removed MessageList.py since it is no longer used.
42
    self._unread = True
43
181 by Jason Conti
Adding MessageItem.py to test using regular widgets to display notifications.
44
    self._message = message
182 by Jason Conti
MessageItem labels now wrap, increased the icon size, and made links clickable.
45
    self._message_icon_size = 48
181 by Jason Conti
Adding MessageItem.py to test using regular widgets to display notifications.
46
47
    self._hbox = Gtk.HBox()
201 by Jason Conti
Using a bit of cairo to display icons with rounded edges and message items with rounded backgrounds. Still need to get the proper colors from the gtk theme and possibly add options for custom colors.
48
    self._hbox.set_border_width(10)
181 by Jason Conti
Adding MessageItem.py to test using regular widgets to display notifications.
49
    self.add(self._hbox)
50
202 by Jason Conti
Ported Config.py to the unity app, promoting it to a proper GObject in the process, so value changes are handled by signals instead of calling functions. Adding a basic set of tests for the new Config class. Adding __init__.py to unity to make it a proper module for testing (will need renaming later). Changed the edge radius to 5px for the message icon.
51
    self._image = RoundedIcon(radius = 5)
182 by Jason Conti
MessageItem labels now wrap, increased the icon size, and made links clickable.
52
    self._hbox.pack_start(self._image, False, False, 10)
181 by Jason Conti
Adding MessageItem.py to test using regular widgets to display notifications.
53
    self.update_image()
54
185 by Jason Conti
Adding an icon to MessageItem to show its unread status. Removed MessageList.py since it is no longer used.
55
    self._vbox = Gtk.VBox()
56
    self._hbox.pack_start(self._vbox, True, True, 0)
57
58
    self._summary_hbox = Gtk.HBox()
59
    self._vbox.pack_start(self._summary_hbox, False, False, 1)
60
61
    self._image_unread = Gtk.Image()
62
    self._summary_hbox.pack_start(self._image_unread, False, False, 5)
63
64
    try:
65
      pixbuf = Icon.load("notification-new", 16)
66
    except:
67
      logger.exception("Failed to load notification-new icon.")
68
    else:
69
      self._image_unread.set_from_pixbuf(pixbuf)
70
71
    self._label_summary = create_label()
207 by Jason Conti
Setting most of the colors with a gtk rc style now, except RoundedBox, because I can't figure out how to get the background style color. Seems like it should be widget.style.bg[state] however that list is always empty.
72
    self._label_summary.set_name("message_label")
185 by Jason Conti
Adding an icon to MessageItem to show its unread status. Removed MessageList.py since it is no longer used.
73
    self._summary_hbox.pack_start(self._label_summary, True, True, 0)
74
75
    self._label_body = create_label()
207 by Jason Conti
Setting most of the colors with a gtk rc style now, except RoundedBox, because I can't figure out how to get the background style color. Seems like it should be widget.style.bg[state] however that list is always empty.
76
    self._label_body.set_name("message_label")
77
    logger.debug("FG: {0}".format(self._label_body.style.fg))
185 by Jason Conti
Adding an icon to MessageItem to show its unread status. Removed MessageList.py since it is no longer used.
78
    self._vbox.pack_start(self._label_body, True, True, 1)
79
80
    self._label_info = create_label()
207 by Jason Conti
Setting most of the colors with a gtk rc style now, except RoundedBox, because I can't figure out how to get the background style color. Seems like it should be widget.style.bg[state] however that list is always empty.
81
    self._label_info.set_name("message_label")
185 by Jason Conti
Adding an icon to MessageItem to show its unread status. Removed MessageList.py since it is no longer used.
82
    self._vbox.pack_start(self._label_info, False, False, 0)
83
    self.update_labels()
181 by Jason Conti
Adding MessageItem.py to test using regular widgets to display notifications.
84
189 by Jason Conti
Mostly implemented filtering. No decrement on the combobox yet. Reverted the icon by app_name, was throwing a seemingly uncatchable GError.
85
  def get_app_name(self):
86
    """Returns the app_name of this item"""
87
    return self._message.app_name
88
181 by Jason Conti
Adding MessageItem.py to test using regular widgets to display notifications.
89
  def escape_body(self, text):
90
    """Text needs to be escaped in case it contains characters that will cause errors
91
    parsing the markup, but some clients send text that is already escaped. This causes
92
    messages to have &, <, and > strings instead of the appropriate characters.
93
    This method replaces those with the appropriate characters and then escapes the text.
94
    TODO: Create a better HTML/entity parser. 
95
    """
96
    result = text.replace("&", "&")
97
    result = result.replace("'", "'")
98
    result = result.replace(">", ">")
99
    result = result.replace("&lt;", "<")
100
    result = result.replace("&quot;", '"')
182 by Jason Conti
MessageItem labels now wrap, increased the icon size, and made links clickable.
101
    return self.markup_links(escape_text(result))
102
185 by Jason Conti
Adding an icon to MessageItem to show its unread status. Removed MessageList.py since it is no longer used.
103
  def is_unread(self):
104
    """Get the unread status of this message"""
105
    return self._unread
106
107
  def set_unread(self, unread):
108
    """Sets the unread status of this messages and the visibility of the icon"""
109
    if unread and not self._unread:
110
      self._unread = True
111
      self._image_unread.show()
112
      self._summary_hbox.pack_start(self._image_unread, False, False, 5)
113
      self._summary_hbox.reorder_child(self._image_unread, 0)
114
115
    elif not unread and self._unread:
116
      self._unread = False
117
      self._image_unread.hide()
118
      self._summary_hbox.remove(self._image_unread)
119
196 by Jason Conti
Updated the number of translatable strings and fixed the labels so they properly rewrap when the window is resized in the experimental unity version.
120
  def set_width(self, width):
121
    """Updates the wrap width of the labels in this message item, minus the icon
122
    size and various padding."""
201 by Jason Conti
Using a bit of cairo to display icons with rounded edges and message items with rounded backgrounds. Still need to get the proper colors from the gtk theme and possibly add options for custom colors.
123
    new_width = width - self._message_icon_size - 60
196 by Jason Conti
Updated the number of translatable strings and fixed the labels so they properly rewrap when the window is resized in the experimental unity version.
124
    self._label_summary.set_size_request(new_width, -1)
125
    self._label_body.set_size_request(new_width, -1)
126
    self._label_info.set_size_request(new_width, -1)
127
182 by Jason Conti
MessageItem labels now wrap, increased the icon size, and made links clickable.
128
  def markup_links(self, text):
129
    """Filters escaped text for web links and makes them clickable"""
130
    result = []
131
    for s in text.split():
132
      if s.startswith("http://"):
133
        name = s
134
        url = s
135
        result.append('<a href="{0}">{1}</a>'.format(url, name))
136
      elif s.startswith("www."):
137
        name = s
138
        url = "http://" + s
139
        result.append('<a href="{0}">{1}</a>'.format(url, name))
140
      else:
141
        result.append(s)
142
143
    return " ".join(result)
181 by Jason Conti
Adding MessageItem.py to test using regular widgets to display notifications.
144
145
  def update_image(self):
146
    """Updates the image"""
147
    try:
148
      pixbuf = self._message.get_icon(self._message_icon_size)
149
    except:
150
      logger.exception("Failed to get icon: {0}".format(self._message.app_icon))
151
    else:
152
      self._image.set_from_pixbuf(pixbuf)
153
185 by Jason Conti
Adding an icon to MessageItem to show its unread status. Removed MessageList.py since it is no longer used.
154
  def update_labels(self):
181 by Jason Conti
Adding MessageItem.py to test using regular widgets to display notifications.
155
    """Updates the label markup"""
185 by Jason Conti
Adding an icon to MessageItem to show its unread status. Removed MessageList.py since it is no longer used.
156
    summary = escape_text(self._message.summary.encode("utf8"))
157
    body = self.escape_body(self._message.body.encode("utf8"))
158
    timestamp = escape_text(Timestamp.locale_datetime(self._message.timestamp))
159
    app_name = escape_text(self._message.app_name)
196 by Jason Conti
Updated the number of translatable strings and fixed the labels so they properly rewrap when the window is resized in the experimental unity version.
160
185 by Jason Conti
Adding an icon to MessageItem to show its unread status. Removed MessageList.py since it is no longer used.
161
    self._label_summary.set_markup("<b>{0}</b>".format(summary))
162
    self._label_body.set_markup(body)
163
    self._label_info.set_markup("<small><i>{0} {1} <b>{2}</b></i></small>".format(timestamp,
164
      _("from"), app_name))
181 by Jason Conti
Adding MessageItem.py to test using regular widgets to display notifications.
165