~straemer/ubuntu/quantal/update-manager/fix-for-1058070

« back to all changes in this revision

Viewing changes to UpdateManager/ChangelogViewer.py

  • Committer: Package Import Robot
  • Author(s): Michael Terry
  • Date: 2012-06-29 10:59:30 UTC
  • mfrom: (389.1.2 precise-security)
  • Revision ID: package-import@ubuntu.com-20120629105930-0oaj9vdvykmvkjum
Tags: 1:0.165
* Implementation of "update on start" feature from spec
  https://wiki.ubuntu.com/SoftwareUpdates
* Use a single main window that changes instead of having modal dialogs
* Implement several special-purpose dialogs like "No updates" or
  "Dist upgrade needed" accordingn to the above spec
* Split out release upgrader code and DistUpgrade module into a separate
  source package
* Drop python-update-manager, as it is unused
* debian/tests:
  - Add dep8 tests

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# ReleaseNotesViewer.py
2
 
#  
 
1
# ChangelogViewer.py
 
2
# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*-
 
3
#
3
4
#  Copyright (c) 2006 Sebastian Heinlein
4
5
#                2007 Canonical
5
 
#  
 
6
#
6
7
#  Author: Sebastian Heinlein <sebastian.heinlein@web.de>
7
8
#          Michael Vogt <michael.vogt@ubuntu.com>
8
9
#
9
 
#  This modul provides an inheritance of the Gtk.TextView that is 
 
10
#  This modul provides an inheritance of the Gtk.TextView that is
10
11
#  aware of http URLs and allows to open them in a browser.
11
12
#  It is based on the pygtk-demo "hypertext".
12
 
13
 
#  This program is free software; you can redistribute it and/or 
14
 
#  modify it under the terms of the GNU General Public License as 
 
13
#
 
14
#  This program is free software; you can redistribute it and/or
 
15
#  modify it under the terms of the GNU General Public License as
15
16
#  published by the Free Software Foundation; either version 2 of the
16
17
#  License, or (at your option) any later version.
17
 
 
18
#
18
19
#  This program is distributed in the hope that it will be useful,
19
20
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
20
21
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
22
#  GNU General Public License for more details.
22
 
 
23
#
23
24
#  You should have received a copy of the GNU General Public License
24
25
#  along with this program; if not, write to the Free Software
25
26
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
34
35
from gi.repository import Pango
35
36
from gettext import gettext as _
36
37
 
37
 
from .ReleaseNotesViewer import open_url
 
38
from DistUpgrade.ReleaseNotesViewer import open_url
 
39
 
38
40
 
39
41
class ChangelogViewer(Gtk.TextView):
40
42
    def __init__(self, changelog=None):
59
61
        #self.buffer.connect("changed", self.search_links)
60
62
        self.buffer.connect_after("insert-text", self.on_insert_text)
61
63
        # search for links in the changelog and make them clickable
62
 
        if changelog != None:
 
64
        if changelog is not None:
63
65
            self.buffer.set_text(changelog)
64
 
            
 
66
 
65
67
    def create_context_menu(self, url):
66
 
        """Create the context menu to be displayed when links are right clicked"""
 
68
        """Create the context menu to be displayed when links are right
 
69
           clicked"""
67
70
        self.menu = Gtk.Menu()
68
 
        
 
71
 
69
72
        # create menu items
70
73
        item_grey_link = Gtk.MenuItem()
71
74
        item_grey_link.set_label(url)
72
 
        item_grey_link.connect("activate", self.handle_context_menu, "open", url)
 
75
        item_grey_link.connect("activate", self.handle_context_menu, "open",
 
76
                               url)
73
77
        item_seperator = Gtk.MenuItem()
74
78
        item_open_link = Gtk.MenuItem()
75
79
        item_open_link.set_label(_("Open Link in Browser"))
76
 
        item_open_link.connect("activate", self.handle_context_menu, "open", url)
 
80
        item_open_link.connect("activate", self.handle_context_menu, "open",
 
81
                               url)
77
82
        item_copy_link = Gtk.MenuItem()
78
83
        item_copy_link.set_label(_("Copy Link to Clipboard"))
79
 
        item_copy_link.connect("activate", self.handle_context_menu, "copy", url)
80
 
        
 
84
        item_copy_link.connect("activate", self.handle_context_menu, "copy",
 
85
                               url)
 
86
 
81
87
        # add menu items
82
88
        self.menu.add(item_grey_link)
83
89
        self.menu.add(item_seperator)
84
90
        self.menu.add(item_open_link)
85
91
        self.menu.add(item_copy_link)
86
92
        self.menu.show_all()
87
 
    
 
93
 
88
94
    def handle_context_menu(self, menuitem, action, url):
89
95
        """Handle activate event for the links' context menu"""
90
96
        if action == "open":
95
101
            #cb = Gtk.Clipboard()
96
102
            #cb.set_text(url)
97
103
            display = Gdk.Display.get_default()
98
 
            selection = Gdk.Atom.intern ("CLIPBOARD", False)
 
104
            selection = Gdk.Atom.intern("CLIPBOARD", False)
99
105
            cb = Gtk.Clipboard.get_for_display(display, selection)
100
106
            cb.set_text(url, -1)
101
107
            cb.store()
110
116
        tag = self.buffer.create_tag(None, foreground="blue",
111
117
                                     underline=Pango.Underline.SINGLE)
112
118
        tag.url = url
113
 
        self.buffer.apply_tag(tag , start, end)
 
119
        self.buffer.apply_tag(tag, start, end)
114
120
 
115
121
    def on_insert_text(self, buffer, iter_end, text, *args):
116
 
        """Search for http URLs in newly inserted text  
 
122
        """Search for http URLs in newly inserted text
117
123
           and tag them accordingly"""
118
124
 
119
125
        # some convenient urls
121
127
        DEBIAN = "http://bugs.debian.org/"
122
128
        CVE = "http://cve.mitre.org/cgi-bin/cvename.cgi?name="
123
129
        # some convinient end-markers
124
 
        ws = [" ","\t","\n"]
125
 
        brak = [")","]",">"]
126
 
        punct = [",","!",":"]
127
 
        dot = ["."]+punct
 
130
        ws = [" ", "\t", "\n"]
 
131
        brak = [")", "]", ">"]
 
132
        punct = [",", "!", ":"]
 
133
        dot = ["."] + punct
128
134
        dot_cr = [".\n"]
129
135
 
130
136
        # search items are start-str, list-of-end-strs, url-prefix
131
137
        # a lot of this search is "TEH SUCK"(tm) because of limitations
132
138
        # in iter.forward_search()
133
139
        # - i.e. no insensitive searching, no regexp
134
 
        search_items = [ ("http://", ws+brak+punct+dot_cr, "http://"),
135
 
                         ("LP#", ws+brak+dot, MALONE),
136
 
                         ("LP: #", ws+brak+dot, MALONE),
137
 
                         ("lp: #", ws+brak+dot, MALONE),
138
 
                         ("LP:#",  ws+brak+dot, MALONE),
139
 
                         ("Malone: #", ws+brak+dot, MALONE),
140
 
                         ("Malone:#", ws+brak+dot, MALONE),
141
 
                         ("Ubuntu: #", ws+brak+dot, MALONE),
142
 
                         ("Ubuntu:#", ws+brak+dot, MALONE),
143
 
                         ("Closes: #",ws+brak+dot, DEBIAN),
144
 
                         ("Closes:#",ws+brak+dot, DEBIAN),
145
 
                         ("closes:#",ws+brak+dot, DEBIAN),
146
 
                         ("closes: #",ws+brak+dot, DEBIAN),
147
 
                         ("CVE-", ws+brak+dot, CVE),
148
 
                       ]
 
140
        search_items = [("http://", ws + brak + punct + dot_cr, "http://"),
 
141
                        ("LP#", ws + brak + dot, MALONE),
 
142
                        ("LP: #", ws + brak + dot, MALONE),
 
143
                        ("lp: #", ws + brak + dot, MALONE),
 
144
                        ("LP:#", ws + brak + dot, MALONE),
 
145
                        ("Malone: #", ws + brak + dot, MALONE),
 
146
                        ("Malone:#", ws + brak + dot, MALONE),
 
147
                        ("Ubuntu: #", ws + brak + dot, MALONE),
 
148
                        ("Ubuntu:#", ws + brak + dot, MALONE),
 
149
                        ("Closes: #", ws + brak + dot, DEBIAN),
 
150
                        ("Closes:#", ws + brak + dot, DEBIAN),
 
151
                        ("closes:#", ws + brak + dot, DEBIAN),
 
152
                        ("closes: #", ws + brak + dot, DEBIAN),
 
153
                        ("CVE-", ws + brak + dot, CVE),
 
154
                        ]
149
155
        # init
150
156
        iter = buffer.get_iter_at_offset(iter_end.get_offset() - len(text))
151
157
 
165
171
                while True:
166
172
                    # extend the selection to the complete search item
167
173
                    if match_tmp.forward_char():
168
 
                        text =  match_end.get_text(match_tmp)
 
174
                        text = match_end.get_text(match_tmp)
169
175
                        if text in end_list:
170
176
                            break
171
177
                        # move one char futher to get two char
172
178
                        # end-markers (and back later) LP: #396393
173
179
                        match_tmp.forward_char()
174
 
                        text =  match_end.get_text(match_tmp)
 
180
                        text = match_end.get_text(match_tmp)
175
181
                        if text in end_list:
176
182
                            break
177
183
                        match_tmp.backward_char()
205
211
        (x, y) = self.window_to_buffer_coords(Gtk.TextWindowType.WIDGET,
206
212
                                              int(event.x), int(event.y))
207
213
        iter = self.get_iter_at_location(x, y)
208
 
        
 
214
 
209
215
        # call open_url or menu.popup if an URL is assigned to the iter
210
216
        tags = iter.get_tags()
211
217
        for tag in tags:
212
218
            if hasattr(tag, "url"):
213
 
                if event.button == 1: 
 
219
                if event.button == 1:
214
220
                    open_url(tag.url)
215
221
                    break
216
222
                if event.button == 3:
217
223
                    self.create_context_menu(tag.url)
218
 
                    self.menu.popup(None, None, None, None, event.button, event.time)
 
224
                    self.menu.popup(None, None, None, None, event.button,
 
225
                                    event.time)
219
226
                    return True
220
227
 
221
228
    def motion_notify_event(self, text_view, event):
226
233
        self.check_hovering(x, y)
227
234
        self.get_window(Gtk.TextWindowType.TEXT).get_pointer()
228
235
        return False
229
 
    
 
236
 
230
237
    def visibility_notify_event(self, text_view, event):
231
238
        """callback if the widgets gets visible (e.g. moves to the foreground)
232
239
           that calls the check_hovering method with the mouse position
233
240
           coordinates"""
234
 
        (screen, wx, wy, mod) = text_view.get_window(Gtk.TextWindowType.TEXT).get_pointer()
235
 
        (bx, by) = text_view.window_to_buffer_coords(Gtk.TextWindowType.WIDGET, wx,
236
 
                                                     wy)
 
241
        window = text_view.get_window(Gtk.TextWindowType.TEXT)
 
242
        (screen, wx, wy, mod) = window.get_pointer()
 
243
        (bx, by) = text_view.window_to_buffer_coords(Gtk.TextWindowType.WIDGET,
 
244
                                                     wx, wy)
237
245
        self.check_hovering(bx, by)
238
246
        return False
239
247
 
243
251
        _hovering = False
244
252
        # get the iter at the mouse position
245
253
        iter = self.get_iter_at_location(x, y)
246
 
        
 
254
 
247
255
        # set _hovering if the iter has the tag "url"
248
256
        tags = iter.get_tags()
249
257
        for tag in tags:
252
260
                break
253
261
 
254
262
        # change the global hovering state
255
 
        if _hovering != self.hovering or self.first == True:
 
263
        if _hovering != self.hovering or self.first:
256
264
            self.first = False
257
265
            self.hovering = _hovering
258
266
            # Set the appropriate cursur icon
259
267
            if self.hovering:
260
 
                self.get_window(Gtk.TextWindowType.TEXT).\
261
 
                        set_cursor(Gdk.Cursor.new(Gdk.CursorType.HAND2))
 
268
                self.get_window(Gtk.TextWindowType.TEXT).set_cursor(
 
269
                    Gdk.Cursor.new(Gdk.CursorType.HAND2))
262
270
            else:
263
 
                self.get_window(Gtk.TextWindowType.TEXT).\
264
 
                        set_cursor(Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR))
 
271
                self.get_window(Gtk.TextWindowType.TEXT).set_cursor(
 
272
                    Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR))
265
273
 
266
274
 
267
275
if __name__ == "__main__":