summaryrefslogtreecommitdiff
path: root/UpdateManager/ReleaseNotesViewer.py
diff options
context:
space:
mode:
authorSebastian Heinlein <sebastian.heinlein@web.de>2006-02-19 11:20:21 +0100
committerSebastian Heinlein <sebastian.heinlein@web.de>2006-02-19 11:20:21 +0100
commit53e9180e0aaafae7f93d939b5f97d377990aaeb5 (patch)
treee5c091087888c21b58910b9b738f0c600e1370c2 /UpdateManager/ReleaseNotesViewer.py
parent8abb01fb328c6e0c3da3263af149934b02949b8a (diff)
downloadpython-apt-53e9180e0aaafae7f93d939b5f97d377990aaeb5.tar.gz
* ReleaseNotesViewer:
- Add copyright, license, comments - Use the normal cursor instead of the xterm one - Set the cursor only if the hovering state changed to avoid flickering
Diffstat (limited to 'UpdateManager/ReleaseNotesViewer.py')
-rw-r--r--UpdateManager/ReleaseNotesViewer.py84
1 files changed, 73 insertions, 11 deletions
diff --git a/UpdateManager/ReleaseNotesViewer.py b/UpdateManager/ReleaseNotesViewer.py
index 9cecc895..33122be9 100644
--- a/UpdateManager/ReleaseNotesViewer.py
+++ b/UpdateManager/ReleaseNotesViewer.py
@@ -1,4 +1,28 @@
-#!/usr/bin/env python
+# ReleaseNotesViewer.py
+#
+# Copyright (c) 2006 Sebastian Heinlein
+#
+# Author: Sebastian Heinlein <sebastian.heinlein@web.de>
+#
+# This modul provides an inheritance of the gtk.TextView that is
+# aware of http URLs and allows to open them in a browser.
+# It is based on the pygtk-demo "hypertext".
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
import pygtk
import gtk
@@ -8,34 +32,49 @@ import os
class ReleaseNotesViewer(gtk.TextView):
def __init__(self, notes):
+ """Init the ReleaseNotesViewer as an Inheritance of the gtk.TextView.
+ Load the notes into the buffer and make links clickable"""
+ # init the parent
gtk.TextView.__init__(self)
+ # global hovering over link state
self.hovering = False
+ self.first = True
+ # setup the buffer and signals
+ self.set_property("editable", False)
+ self.set_cursor_visible(False)
self.buffer = gtk.TextBuffer()
self.set_buffer(self.buffer)
self.buffer.set_text(notes)
self.connect("event-after", self.event_after)
self.connect("motion-notify-event", self.motion_notify_event)
self.connect("visibility-notify-event", self.visibility_notify_event)
+ # search for links in the notes and make them clickable
self.search_links()
- self.set_property("editable", False)
- self.set_cursor_visible(False)
def tag_link(self, start, end, url):
+ """Apply the tag that marks links to the specified buffer selection"""
tag = self.buffer.create_tag(None, foreground="blue",
underline=pango.UNDERLINE_SINGLE)
tag.set_data("url", url)
self.buffer.apply_tag(tag , start, end)
def search_links(self):
+ """Search for http URLs in the buffer and call the tag_link method
+ for each one to tag them as links"""
+ # start at the beginning of the buffer
iter = self.buffer.get_iter_at_offset(0)
while 1:
+ # search for the next URL in the buffer
ret = iter.forward_search("http://", gtk.TEXT_SEARCH_VISIBLE_ONLY,
None)
+ # if we reach the end break the loop
if not ret:
break
+ # get the position of the protocol prefix
(match_start, match_end) = ret
match_tmp = match_end.copy()
while 1:
+ # extend the selection to the complete URL
if match_tmp.forward_char():
text = match_end.get_text(match_tmp)
if text in (" ", ")", "]", "\n", "\t"):
@@ -43,16 +82,21 @@ class ReleaseNotesViewer(gtk.TextView):
else:
break
match_end = match_tmp.copy()
+ # call the tagging method for the complete URL
url = match_start.get_text(match_end)
self.tag_link(match_start, match_end, url)
+ # set the starting point for the next search
iter = match_end
def event_after(self, text_view, event):
+ """callback for mouse click events"""
+ # we only react on left mouse clicks
if event.type != gtk.gdk.BUTTON_RELEASE:
return False
if event.button != 1:
return False
+ # try to get a selection
try:
(start, end) = self.buffer.get_selection_bounds()
except ValueError:
@@ -61,10 +105,12 @@ class ReleaseNotesViewer(gtk.TextView):
if start.get_offset() != end.get_offset():
return False
+ # get the iter at the mouse position
(x, y) = self.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET,
int(event.x), int(event.y))
iter = self.get_iter_at_location(x, y)
+ # call open_url if an URL is assigned to the iter
tags = iter.get_tags()
for tag in tags:
url = tag.get_data("url")
@@ -73,17 +119,22 @@ class ReleaseNotesViewer(gtk.TextView):
break
def open_url(self, url):
+ """Open the specified URL in a browser"""
+ # Find an appropiate browser
if os.path.exists('usr/bin/gnome-open'):
command = ['gnome-open', url]
else:
command = ['x-www-browser', url]
+ # Avoid to run the browser as user root
if os.getuid() == 0 and os.environ.has_key('SUDO_USER'):
command = ['sudo', '-u', os.environ['SUDO_USER']] + command
subprocess.Popen(command)
def motion_notify_event(self, text_view, event):
+ """callback for the mouse movement event, that calls the
+ check_hovering method with the mouse postition coordiantes"""
x, y = text_view.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET,
int(event.x), int(event.y))
self.check_hovering(x, y)
@@ -91,6 +142,9 @@ class ReleaseNotesViewer(gtk.TextView):
return False
def visibility_notify_event(self, text_view, event):
+ """callback if the widgets gets visible (e.g. moves to the foreground)
+ that calls the check_hovering method with the mouse position
+ coordinates"""
(wx, wy, mod) = text_view.window.get_pointer()
(bx, by) = text_view.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET, wx,
wy)
@@ -98,20 +152,28 @@ class ReleaseNotesViewer(gtk.TextView):
return False
def check_hovering(self, x, y):
+ """Check if the mouse is above a tagged link and if yes show
+ a hand cursor"""
_hovering = False
+ # get the iter at the mouse position
iter = self.get_iter_at_location(x, y)
-
+
+ # set _hovering if the iter has the tag "url"
tags = iter.get_tags()
for tag in tags:
url = tag.get_data("url")
if url != "":
_hovering = True
break
-
- if _hovering != self.hovering:
- self.hovering = _hovering
- if self.hovering:
- self.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2))
- else:
- self.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(gtk.gdk.Cursor(gtk.gdk.XTERM))
+ # change the global hovering state
+ if _hovering != self.hovering or self.first == True:
+ self.first = False
+ self.hovering = _hovering
+ # Set the appropriate cursur icon
+ if self.hovering:
+ self.get_window(gtk.TEXT_WINDOW_TEXT).\
+ set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2))
+ else:
+ self.get_window(gtk.TEXT_WINDOW_TEXT).\
+ set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))