1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """a view display messages containing warnings, errors and information."""
23
24 import gettext
25 import os
26 import time
27
28 import pango
29 import gtk
30
31 from flumotion.common import log
32 from flumotion.common.documentation import getMessageWebLink
33 from flumotion.common.i18n import Translator
34 from flumotion.common.messages import ERROR, WARNING, INFO
35 from flumotion.configure import configure
36
37 _ = gettext.gettext
38 __version__ = "$Rev: 7094 $"
39 _stock_icons = {
40 ERROR: gtk.STOCK_DIALOG_ERROR,
41 WARNING: gtk.STOCK_DIALOG_WARNING,
42 INFO: gtk.STOCK_DIALOG_INFO,
43 }
44 _headings = {
45 ERROR: _('Error'),
46 WARNING: _('Warning'),
47 INFO: _('Note'),
48 }
49
50
71
72
73
75 """
76 I am a widget that can show messages.
77 """
78
79
80
82 gtk.VBox.__init__(self)
83
84 h1 = gtk.HBox()
85 self.pack_start(h1, False, False, 0)
86 self.label = gtk.Label()
87 self.label.show()
88 h1.pack_start(self.label, False, False, 6)
89
90
91 h2 = gtk.HBox()
92 h1.pack_end(h2, False, False, 0)
93 s = gtk.HSeparator()
94 self.pack_start(s, False, False, 6)
95 sw = gtk.ScrolledWindow()
96 sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
97 sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
98 self.pack_start(sw, True, True, 0)
99
100
101
102 tv = gtk.TextView()
103 tv.set_wrap_mode(gtk.WRAP_WORD)
104 tv.set_left_margin(6)
105 tv.set_right_margin(6)
106 tv.set_accepts_tab(False)
107 tv.set_cursor_visible(False)
108 tv.set_editable(False)
109
110
111 tv.connect('event-after', self._after_textview__event)
112 tv.connect('motion-notify-event',
113 self._on_textview___motion_notify_event)
114 sw.add(tv)
115
116 self.active_button = None
117 self.buttonbox = h2
118 self.textview = tv
119
120 self.show_all()
121 self.clear()
122
123 self._translator = Translator()
124 localedir = os.path.join(configure.localedatadir, 'locale')
125
126 self._translator.addLocaleDir(configure.PACKAGE, localedir)
127
129 """
130 Remove all messages and hide myself.
131 """
132 for child in self.buttonbox.get_children():
133 self.clearMessage(child.message.id)
134 self.hide()
135
137 """
138 Add a message to me.
139 @type m: L{flumotion.common.messages.Message}
140 """
141
142
143
144 self.clearMessage(m.id)
145
146
147 b = MessageButton(m)
148 b.sigid = b.connect('toggled', self._on_message_button__toggled, m)
149 b.show()
150 self.buttonbox.pack_start(b, False, False, 0)
151
152 firstButton = self._sortMessages()
153
154 if not self.active_button:
155 b.set_active(True)
156 elif b == firstButton:
157 b.set_active(True)
158 self.show()
159
161 """
162 Clear all messages with the given id.
163 Will bring the remaining most important message to the front,
164 or hide the view completely if no messages are left.
165 """
166 for button in self.buttonbox.get_children():
167 if button.message.id != id:
168 continue
169
170 self.buttonbox.remove(button)
171 button.disconnect(button.sigid)
172 button.sigid = 0
173 if not self.buttonbox.get_children():
174 self.active_button = None
175 self.hide()
176 elif self.active_button == button:
177 self.active_button = self.buttonbox.get_children()[0]
178 self.active_button.set_active(True)
179 break
180
181
182
184
185
186 text = self._translator.translate(message)
187
188
189 if hasattr(message, 'timestamp'):
190 text += _("\nPosted on %s.\n") % time.strftime(
191 "%c", time.localtime(message.timestamp))
192
193 if message.debug:
194 text += "\n\n" + _("Debug information:\n") + message.debug + '\n'
195
196 textbuffer = gtk.TextBuffer()
197 textbuffer.set_text(text)
198 self.textview.set_buffer(textbuffer)
199 self.label.set_markup('<b>%s</b>' %
200 _headings.get(message.level, _('Message')))
201
202
203
204
205 description = getattr(message, 'description')
206 if description:
207 titer = textbuffer.get_end_iter()
208
209 translated = self._translator.translateTranslatable(description)
210 tag = textbuffer.create_tag(translated)
211 tag.set_property('underline', pango.UNDERLINE_SINGLE)
212 tag.set_property('foreground', 'blue')
213 tag.set_data('link', getMessageWebLink(message))
214 textbuffer.insert_with_tags_by_name(titer, translated,
215 tag.get_property('name'))
216
218
219 children = [(-w.message.level, w.message.priority, w)
220 for w in self.buttonbox.get_children()]
221 children.sort()
222 children.reverse()
223 children = [(i, children[i][2]) for i in range(len(children))]
224 for child in children:
225 self.buttonbox.reorder_child(child[1], child[0])
226
227
228 return children[0][1]
229
230
231
244
245
247 x, y = textview.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET,
248 int(event.x), int(event.y))
249 tags = textview.get_iter_at_location(x, y).get_tags()
250
251
252 textview.window.get_pointer()
253
254
255 cursor = None
256 for tag in tags:
257 if tag.get_data('link'):
258 cursor = gtk.gdk.Cursor(gtk.gdk.HAND2)
259 break
260 textview.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(cursor)
261 return False
262
263 - def _after_textview__event(self, textview, event):
264 if event.type != gtk.gdk.BUTTON_RELEASE:
265 return False
266 if event.button != 1:
267 return False
268
269 textbuffer = textview.get_buffer()
270
271 bounds = textbuffer.get_selection_bounds()
272 if bounds:
273 [start, end] = bounds
274 if start.get_offset() != end.get_offset():
275 return False
276
277 x, y = textview.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET,
278 int(event.x), int(event.y))
279 iter = textview.get_iter_at_location(x, y)
280
281 for tag in iter.get_tags():
282 link = tag.get_data('link')
283 if link:
284 import webbrowser
285 log.debug('messageview', 'opening %s' % link)
286 webbrowser.open(link)
287 break
288
289 return False
290