Merge lp:~pitti/software-properties/pygi into lp:software-properties
- pygi
- Merge into main
Status: | Merged |
---|---|
Merged at revision: | 643 |
Proposed branch: | lp:~pitti/software-properties/pygi |
Merge into: | lp:software-properties |
Diff against target: |
952 lines (+205/-173) 15 files modified
debian/changelog (+28/-0) debian/control (+1/-1) software-properties-gtk (+6/-11) softwareproperties/MirrorTest.py (+18/-5) softwareproperties/gtk/CdromProgress.py (+16/-16) softwareproperties/gtk/DialogAdd.py (+2/-2) softwareproperties/gtk/DialogAddSourcesList.py (+7/-6) softwareproperties/gtk/DialogCacheOutdated.py (+9/-5) softwareproperties/gtk/DialogEdit.py (+2/-2) softwareproperties/gtk/DialogMirror.py (+36/-55) softwareproperties/gtk/SimpleGtkbuilderApp.py (+7/-7) softwareproperties/gtk/SoftwarePropertiesGtk.py (+65/-55) softwareproperties/gtk/dialogs.py (+3/-3) softwareproperties/gtk/utils.py (+4/-4) softwareproperties/kde/DialogMirror.py (+1/-1) |
To merge this branch: | bzr merge lp:~pitti/software-properties/pygi |
Related bugs: | |
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Martin Pitt | Needs Resubmitting | ||
Michael Vogt | Pending | ||
Review via email:
|
Commit message
Description of the change
This ports the GTK UI from pygtk2 to gobject-

Martin Pitt (pitti) wrote : | # |

Michael Vogt (mvo) wrote : | # |
Thanks, code looks good. However when I run it on my box I get:
sudo ./software-
** (software-
I guess that is ok for now?

Michael Vogt (mvo) wrote : | # |
The other thing that does not work is the ping test on:
"Download from: Other…", "Select best server"
Its supposed to open a window with a lot of pings. That does not work currently, it hangs instead.

Martin Pitt (pitti) wrote : | # |
Right, the get_cursor() warning is expected; that eventually needs to be fixed in the GTK overrides or pygobject. It doesn't hurt, though.
I'll look at the ping window, thanks for the review!

Martin Pitt (pitti) wrote : | # |
So the problem is that this uses GTK from two different threads: the main one, and the MirrorTestGtk class, which is instantiated and run in a parallel one. Apparently pygtk had some magic to have that work, but with plain GTK it has never worked well. In particular, the worker thread doesn't seem to have a main loop, so there are no updates.
It would be a lot better if the GTK bits could be in the main thread only, and the worker thread would just do the pings and update callbacks, and the main thread would receive the callbacks and continue to run the main loop. Michael, would you mind if I reorganized the code accordingly?

Michael Vogt (mvo) wrote : | # |
Thanks for looking into this Martin! I am absolutely in favour for this reorganizing.
- 649. By Martin Pitt
-
software-
properties- gtk, softwarepropert ies/gtk/ DialogMirror. py: Drop
calls to Gdk.threads_*(). They were insufficient and causing lockups, and
since multi-threaded Gtk is a pain to get right, we'll rather change the
code structure to only use Gtk from the main thread. - 650. By Martin Pitt
-
softwarepropert
ies/gtk/ DialogMirror. py: Run GTK operations in main thread,
to avoid thread lockups. - 651. By Martin Pitt
-
softwarepropert
ies/MirrorTest. py: Move additional MirrorTestGtk
functionality (setting threading.Event flag and storing current
action/progress into main MirrorTest class, so that we can entirely drop
MirrorTestGtk from softwareproperties/gtk/ DialogMirror. py. KDE still uses
its own implementation with real threads, as this is still easier to do.

Martin Pitt (pitti) wrote : | # |
r650 moved all GTK operations to the main thread, to avoid the thread lockups. r649 removed all the Gdk.thread_* stuff, as this is now obsolete.
r651 is not a functional change, but simplifies the code a bit.
This now works fine, so I resubmit this. I verified that the kde frontend still works well, too.
Preview Diff
1 | === modified file 'debian/changelog' |
2 | --- debian/changelog 2010-12-13 08:42:40 +0000 |
3 | +++ debian/changelog 2011-02-11 12:13:56 +0000 |
4 | @@ -1,3 +1,31 @@ |
5 | +software-properties (0.79) UNRELEASED; urgency=low |
6 | + |
7 | + * software-properties-gtk, ./softwareproperties/gtk/*: Port from pygtk to |
8 | + gobject-introspection. This works with both GTK 2 and 3, but in GTK2 we |
9 | + have to disable the drag&drop functionality (as current GTK2 does not have |
10 | + a gtk_target_entry_new() and thus you can't construct those). |
11 | + * softwareproperties/gtk/SoftwarePropertiesGtk.py: When doing string |
12 | + interpolation with translated text and unicode objects, encode the latter |
13 | + into UTF-8 first. pygtk did that for us using some black magic (by calling |
14 | + PyUnicode_SetDefaultEncoding()). |
15 | + * software-properties-gtk: Force using GTK 2 for now, as in Natty we don't |
16 | + currently ship GTK 3 on the default installation (we don't have a theme |
17 | + yet). |
18 | + * debian/control: Update dependencies for the pygtk → pygi switch. |
19 | + * software-properties-gtk, softwareproperties/gtk/DialogMirror.py: Drop |
20 | + calls to Gdk.threads_*(). They were insufficient and causing lockups, and |
21 | + since multi-threaded Gtk is a pain to get right, we'll rather change the |
22 | + code structure to only use Gtk from the main thread. |
23 | + * softwareproperties/gtk/DialogMirror.py: Run GTK operations in main thread, |
24 | + to avoid thread lockups. |
25 | + * softwareproperties/MirrorTest.py: Move additional MirrorTestGtk |
26 | + functionality (setting threading.Event flag and storing current |
27 | + action/progress into main MirrorTest class, so that we can entirely drop |
28 | + MirrorTestGtk from softwareproperties/gtk/DialogMirror.py. KDE still uses |
29 | + its own implementation with real threads, as this is still easier to do. |
30 | + |
31 | + -- Martin Pitt <martin.pitt@ubuntu.com> Tue, 25 Jan 2011 18:54:54 +0100 |
32 | + |
33 | software-properties (0.78.1) natty; urgency=low |
34 | |
35 | * use port 80 by default when getting gpg keys for PPAs |
36 | |
37 | === modified file 'debian/control' |
38 | --- debian/control 2010-08-25 18:06:17 +0000 |
39 | +++ debian/control 2011-02-11 12:13:56 +0000 |
40 | @@ -22,7 +22,7 @@ |
41 | Replaces: update-manager (<< 0.55) |
42 | Conflicts: update-manager (<< 0.55) |
43 | XB-Python-Version: ${python:Versions} |
44 | -Depends: ${python:Depends}, ${misc:Depends}, python, synaptic (>= 0.57.8), gksu, python-software-properties, python-gtk2 |
45 | +Depends: ${python:Depends}, ${misc:Depends}, python, synaptic (>= 0.57.8), gksu, python-software-properties, python-gobject (>= 2.27), gir1.2-gtk-2.0 (>= 2.23.90-0ubuntu3) |
46 | Description: manage the repositories that you install software from |
47 | This software provides an abstraction of the used apt repositories. |
48 | It allows you to easily manage your distribution and independent software |
49 | |
50 | === modified file 'software-properties-gtk' |
51 | --- software-properties-gtk 2010-08-25 08:51:00 +0000 |
52 | +++ software-properties-gtk 2011-02-11 12:13:56 +0000 |
53 | @@ -22,16 +22,13 @@ |
54 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
55 | # USA |
56 | |
57 | -import pygtk |
58 | -pygtk.require('2.0') |
59 | -import gtk |
60 | -import gtk.gdk |
61 | +from gi.repository import Gtk |
62 | +Gtk.require_version('2.0') |
63 | import gobject |
64 | import gettext |
65 | import os |
66 | import sys |
67 | - |
68 | -gtk.gdk.threads_init() |
69 | +import locale |
70 | |
71 | from optparse import OptionParser |
72 | |
73 | @@ -75,21 +72,19 @@ |
74 | parser.add_option("--data-dir", "", |
75 | action="store", type="string", default="/usr/share/software-properties/", |
76 | help="Use data files (UI) from the given directory") |
77 | - gtk.init_check() |
78 | |
79 | (options, args) = parser.parse_args() |
80 | # Check for root permissions |
81 | if os.geteuid() != 0: |
82 | - dialog = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, |
83 | + dialog = Gtk.MessageDialog(None, 0, Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, |
84 | _("You need to be root to run this program") ) |
85 | - dialog.set_default_response(gtk.RESPONSE_CLOSE) |
86 | + dialog.set_default_response(Gtk.ResponseType.CLOSE) |
87 | dialog.run() |
88 | dialog.destroy() |
89 | sys.exit(1) |
90 | |
91 | + locale.setlocale(locale.LC_ALL, '') |
92 | localesApp="software-properties" |
93 | - localesDir="/usr/share/locale" |
94 | - gettext.bindtextdomain(localesApp, localesDir) |
95 | gettext.textdomain(localesApp) |
96 | |
97 | # force new files to be 644 (LP: #497778) |
98 | |
99 | === modified file 'softwareproperties/MirrorTest.py' |
100 | --- softwareproperties/MirrorTest.py 2009-11-14 14:13:30 +0000 |
101 | +++ softwareproperties/MirrorTest.py 2011-02-11 12:13:56 +0000 |
102 | @@ -52,8 +52,12 @@ |
103 | self.results.append([float(result[0]), host, mirror]) |
104 | MirrorTest.completed_lock.release() |
105 | |
106 | - def __init__(self, mirrors, test_file, running=None): |
107 | + def __init__(self, mirrors, test_file, event, running=None): |
108 | threading.Thread.__init__(self) |
109 | + self.action = '' |
110 | + self.progress = (0, 0, 0.0) # cur, max, % |
111 | + self.event = event |
112 | + self.best = None |
113 | self.test_file = test_file |
114 | self.threads = [] |
115 | MirrorTest.completed = 0 |
116 | @@ -66,14 +70,18 @@ |
117 | self.running = running |
118 | |
119 | def report_action(self, text): |
120 | - """Subclasses should override this method to receive |
121 | - action message updates""" |
122 | - print text |
123 | + self.action = text |
124 | + if self.event: |
125 | + self.event.set() |
126 | |
127 | def report_progress(self, current, max, borders=(0,100), mod=(0,0)): |
128 | """Subclasses should override this method to receive |
129 | progress status updates""" |
130 | - print "Completed %s of %s" % (current + mod[0], max + mod[1]) |
131 | + self.progress = (current + mod[0], |
132 | + max + mod[1], |
133 | + borders[0] + (borders[1] - borders[0]) / max * current) |
134 | + if self.event: |
135 | + self.event.set() |
136 | |
137 | def run_full_test(self): |
138 | # Determinate the 5 top ping servers |
139 | @@ -149,6 +157,11 @@ |
140 | results.sort() |
141 | return results[0:max] |
142 | |
143 | + def run(self): |
144 | + """Complete test exercise, set self.best when done""" |
145 | + self.best = self.run_full_test() |
146 | + self.running.clear() |
147 | + |
148 | if __name__ == "__main__": |
149 | distro = aptsources.distro.get_distro() |
150 | distro.get_sources(aptsources.SourcesList()) |
151 | |
152 | === modified file 'softwareproperties/gtk/CdromProgress.py' |
153 | --- softwareproperties/gtk/CdromProgress.py 2010-09-20 12:58:51 +0000 |
154 | +++ softwareproperties/gtk/CdromProgress.py 2011-02-11 12:13:56 +0000 |
155 | @@ -20,7 +20,7 @@ |
156 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
157 | # USA |
158 | import apt |
159 | -import gtk |
160 | +from gi.repository import Gtk |
161 | from gettext import gettext as _ |
162 | |
163 | from softwareproperties.gtk.utils import * |
164 | @@ -43,34 +43,34 @@ |
165 | self.button_cdrom_close.set_sensitive(True) |
166 | if text != "": |
167 | self.label_cdrom.set_text(text) |
168 | - while gtk.events_pending(): |
169 | - gtk.main_iteration() |
170 | + while Gtk.events_pending(): |
171 | + Gtk.main_iteration() |
172 | def askCdromName(self): |
173 | - dialog = gtk.MessageDialog(parent=self.dialog_cdrom_progress, |
174 | - flags=gtk.DIALOG_MODAL, |
175 | - type=gtk.MESSAGE_QUESTION, |
176 | - buttons=gtk.BUTTONS_OK_CANCEL, |
177 | + dialog = Gtk.MessageDialog(parent=self.dialog_cdrom_progress, |
178 | + flags=Gtk.DialogFlags.MODAL, |
179 | + type=Gtk.MessageType.QUESTION, |
180 | + buttons=Gtk.ButtonsType.OK_CANCEL, |
181 | message_format=None) |
182 | dialog.set_markup(_("Please enter a name for the disc")) |
183 | - entry = gtk.Entry() |
184 | + entry = Gtk.Entry() |
185 | entry.show() |
186 | - dialog.vbox.pack_start(entry) |
187 | + dialog.vbox.pack_start(entry, True, True, 0) |
188 | res = dialog.run() |
189 | dialog.destroy() |
190 | - if res == gtk.RESPONSE_OK: |
191 | + if res == Gtk.ResponseType.OK: |
192 | name = entry.get_text() |
193 | return (True,name) |
194 | return (False,"") |
195 | def changeCdrom(self): |
196 | - dialog = gtk.MessageDialog(parent=self.dialog_cdrom_progress, |
197 | - flags=gtk.DIALOG_MODAL, |
198 | - type=gtk.MESSAGE_QUESTION, |
199 | - buttons=gtk.BUTTONS_OK_CANCEL, |
200 | + dialog = Gtk.MessageDialog(parent=self.dialog_cdrom_progress, |
201 | + flags=Gtk.DialogFlags.MODAL, |
202 | + type=Gtk.MessageType.QUESTION, |
203 | + buttons=Gtk.ButtonsType.OK_CANCEL, |
204 | message_format=None) |
205 | dialog.set_markup(_("Please insert a disk in the drive:")) |
206 | - dialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT) |
207 | + dialog.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) |
208 | res = dialog.run() |
209 | dialog.destroy() |
210 | - if res == gtk.RESPONSE_OK: |
211 | + if res == Gtk.ResponseType.OK: |
212 | return True |
213 | return False |
214 | |
215 | === modified file 'softwareproperties/gtk/DialogAdd.py' |
216 | --- softwareproperties/gtk/DialogAdd.py 2010-09-20 12:58:51 +0000 |
217 | +++ softwareproperties/gtk/DialogAdd.py 2011-02-11 12:13:56 +0000 |
218 | @@ -25,7 +25,7 @@ |
219 | |
220 | import os |
221 | import gobject |
222 | -import gtk |
223 | +from gi.repository import Gtk |
224 | from gettext import gettext as _ |
225 | |
226 | from aptsources.sourceslist import SourceEntry |
227 | @@ -65,7 +65,7 @@ |
228 | def run(self): |
229 | res = self.dialog.run() |
230 | self.dialog.hide() |
231 | - if res == gtk.RESPONSE_OK: |
232 | + if res == Gtk.ResponseType.OK: |
233 | line = self.entry.get_text() + "\n" |
234 | else: |
235 | line = None |
236 | |
237 | === modified file 'softwareproperties/gtk/DialogAddSourcesList.py' |
238 | --- softwareproperties/gtk/DialogAddSourcesList.py 2010-09-20 12:58:51 +0000 |
239 | +++ softwareproperties/gtk/DialogAddSourcesList.py 2011-02-11 12:13:56 +0000 |
240 | @@ -1,6 +1,7 @@ |
241 | #!/usr/bin/env python |
242 | import pygtk |
243 | -import gtk |
244 | +from gi.repository import Gdk |
245 | +from gi.repository import Gtk |
246 | import gobject |
247 | import os |
248 | from optparse import OptionParser |
249 | @@ -34,15 +35,15 @@ |
250 | self.dialog.set_transient_for(parent) |
251 | else: |
252 | self.dialog.set_title(_("Add Software Channels")) |
253 | - self.dialog.window.set_functions(gtk.gdk.FUNC_MOVE) |
254 | + self.dialog.get_window().set_functions(Gdk.FUNC_MOVE) |
255 | |
256 | # Setup the treeview |
257 | - self.store = gtk.ListStore(gobject.TYPE_STRING) |
258 | + self.store = Gtk.ListStore(gobject.TYPE_STRING) |
259 | self.treeview.set_model(self.store) |
260 | - cell = gtk.CellRendererText() |
261 | + cell = Gtk.CellRendererText() |
262 | cell.set_property("xpad", 2) |
263 | cell.set_property("ypad", 2) |
264 | - column = gtk.TreeViewColumn("Software Channel", cell, markup=0) |
265 | + column = Gtk.TreeViewColumn("Software Channel", cell, markup=0) |
266 | column.set_max_width(500) |
267 | self.treeview.append_column(column) |
268 | |
269 | @@ -93,7 +94,7 @@ |
270 | self.button_cancel.set_label("gtk-close") |
271 | self.button_replace.hide() |
272 | self.scrolled.hide() |
273 | - self.image.set_from_stock(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_DIALOG) |
274 | + self.image.set_from_stock(Gtk.STOCK_DIALOG_ERROR, Gtk.IconSize.DIALOG) |
275 | header = _("There are no sources to install software from") |
276 | body = _("The file '%s' does not contain any valid " |
277 | "software sources." % self.file) |
278 | |
279 | === modified file 'softwareproperties/gtk/DialogCacheOutdated.py' |
280 | --- softwareproperties/gtk/DialogCacheOutdated.py 2010-09-20 12:58:51 +0000 |
281 | +++ softwareproperties/gtk/DialogCacheOutdated.py 2011-02-11 12:13:56 +0000 |
282 | @@ -25,7 +25,7 @@ |
283 | import thread |
284 | import time |
285 | import gobject |
286 | -import gtk |
287 | +from gi.repository import Gtk |
288 | import apt_pkg |
289 | |
290 | from softwareproperties.gtk.utils import * |
291 | @@ -56,15 +56,19 @@ |
292 | """run the dialog, and if reload was pressed run synaptic""" |
293 | res = self.dialog.run() |
294 | self.dialog.hide() |
295 | - if res == gtk.RESPONSE_APPLY: |
296 | + if res == Gtk.ResponseType.APPLY: |
297 | self.parent.set_sensitive(False) |
298 | lock = thread.allocate_lock() |
299 | lock.acquire() |
300 | + try: |
301 | + xid = self.parent.get_window().get_xid() |
302 | + except AttributeError: |
303 | + xid = '' |
304 | t = thread.start_new_thread(self.update_cache, |
305 | - (self.parent.window.xid, lock)) |
306 | + (xid, lock)) |
307 | while lock.locked(): |
308 | - while gtk.events_pending(): |
309 | - gtk.main_iteration() |
310 | + while Gtk.events_pending(): |
311 | + Gtk.main_iteration() |
312 | time.sleep(0.05) |
313 | self.parent.set_sensitive(True) |
314 | return res |
315 | |
316 | === modified file 'softwareproperties/gtk/DialogEdit.py' |
317 | --- softwareproperties/gtk/DialogEdit.py 2010-09-20 12:58:51 +0000 |
318 | +++ softwareproperties/gtk/DialogEdit.py 2011-02-11 12:13:56 +0000 |
319 | @@ -24,7 +24,7 @@ |
320 | |
321 | import os |
322 | import gobject |
323 | -import gtk |
324 | +from gi.repository import Gtk |
325 | |
326 | from aptsources.sourceslist import SourceEntry |
327 | from softwareproperties.gtk.utils import * |
328 | @@ -115,7 +115,7 @@ |
329 | |
330 | def run(self): |
331 | res = self.main.run() |
332 | - if res == gtk.RESPONSE_OK: |
333 | + if res == Gtk.ResponseType.OK: |
334 | line = self.get_line() |
335 | |
336 | # change repository |
337 | |
338 | === modified file 'softwareproperties/gtk/DialogMirror.py' |
339 | --- softwareproperties/gtk/DialogMirror.py 2010-09-20 12:58:51 +0000 |
340 | +++ softwareproperties/gtk/DialogMirror.py 2011-02-11 12:13:56 +0000 |
341 | @@ -22,7 +22,7 @@ |
342 | |
343 | import os |
344 | import gobject |
345 | -import gtk |
346 | +from gi.repository import Gtk |
347 | from gettext import gettext as _ |
348 | import threading |
349 | import string |
350 | @@ -35,22 +35,11 @@ |
351 | from softwareproperties.gtk.utils import * |
352 | |
353 | |
354 | -testing = threading.Event() |
355 | - |
356 | (COLUMN_PROTO, COLUMN_DIR) = range(2) |
357 | (COLUMN_URI, COLUMN_SEPARATOR, COLUMN_CUSTOM, COLUMN_MIRROR) = range(4) |
358 | |
359 | from softwareproperties.CountryInformation import CountryInformation |
360 | |
361 | -def threaded(f): |
362 | - ''' Thanks to Ross Burton for this piece of code ''' |
363 | - def wrapper(*args, **kwargs): |
364 | - t = threading.Thread(target=f, args=args, kwargs=kwargs) |
365 | - t.setDaemon(True) |
366 | - t.start() |
367 | - wrapper.__name__ = f.__name__ |
368 | - return wrapper |
369 | - |
370 | def sort_mirrors(model, iter1, iter2, data=None): |
371 | ''' sort function for the mirror list: |
372 | - at first show all custom urls |
373 | @@ -103,31 +92,31 @@ |
374 | self.label_action = self.label_test_mirror |
375 | |
376 | # store each proto and its dir |
377 | - model_proto = gtk.ListStore(gobject.TYPE_STRING, |
378 | + model_proto = Gtk.ListStore(gobject.TYPE_STRING, |
379 | gobject.TYPE_STRING) |
380 | self.combobox.set_model(model_proto) |
381 | - cr = gtk.CellRendererText() |
382 | - self.combobox.pack_start(cr) |
383 | + cr = Gtk.CellRendererText() |
384 | + self.combobox.pack_start(cr, True) |
385 | self.combobox.add_attribute(cr, "markup", 0) |
386 | |
387 | - self.model = gtk.TreeStore(gobject.TYPE_STRING, # COLUMN_URI |
388 | + self.model = Gtk.TreeStore(gobject.TYPE_STRING, # COLUMN_URI |
389 | gobject.TYPE_BOOLEAN, # COLUMN_SEPARATOR |
390 | gobject.TYPE_BOOLEAN, # COLUMN_CUSTOM |
391 | gobject.TYPE_PYOBJECT)# COLUMN_MIRROR |
392 | - self.treeview.set_row_separator_func(is_separator) |
393 | - self.model_sort = gtk.TreeModelSort(self.model) |
394 | - self.model_sort.set_default_sort_func(sort_mirrors) |
395 | + self.treeview.set_row_separator_func(is_separator, None) |
396 | + self.model_sort = Gtk.TreeModelSort(model=self.model) |
397 | + self.model_sort.set_default_sort_func(sort_mirrors, None) |
398 | |
399 | self.distro = distro |
400 | |
401 | self.treeview.set_model(self.model_sort) |
402 | # the cell renderer for the mirror uri |
403 | - self.renderer_mirror = gtk.CellRendererText() |
404 | + self.renderer_mirror = Gtk.CellRendererText() |
405 | self.renderer_mirror.connect('edited', |
406 | self.on_edited_custom_mirror, |
407 | self.model) |
408 | # the visible column that holds the mirror uris |
409 | - self.column_mirror = gtk.TreeViewColumn("URI", |
410 | + self.column_mirror = Gtk.TreeViewColumn("URI", |
411 | self.renderer_mirror, |
412 | text=COLUMN_URI) |
413 | self.treeview.append_column(self.column_mirror) |
414 | @@ -161,9 +150,9 @@ |
415 | model.append(None, [hostname, False, False, mirror]) |
416 | # Scroll to the local mirror set |
417 | if patriot != None: |
418 | - path_sort = self.model_sort.get_path(self.model_sort.convert_child_iter_to_iter(None, patriot)) |
419 | + path_sort = self.model_sort.get_path(self.model_sort.convert_child_iter_to_iter(patriot)[1]) |
420 | self.treeview.expand_row(path_sort, False) |
421 | - self.treeview.set_cursor(path_sort) |
422 | + self.treeview.set_cursor(path_sort, None, False) |
423 | self.treeview.scroll_to_cell(path_sort, use_align=True, row_align=0.5) |
424 | |
425 | def on_edited_custom_mirror(self, cell, path, new_text, model): |
426 | @@ -273,7 +262,7 @@ |
427 | mirror = model.get_value(iter, COLUMN_MIRROR) |
428 | |
429 | # FIXME: we should also return the list of custom servers |
430 | - if res == gtk.RESPONSE_OK: |
431 | + if res == Gtk.ResponseType.OK: |
432 | if mirror == None: |
433 | # Return the URL of the selected custom mirror |
434 | return model.get_value(iter, COLUMN_URI) |
435 | @@ -288,63 +277,55 @@ |
436 | else: |
437 | return None |
438 | |
439 | - @threaded |
440 | def on_button_test_clicked(self, button, data=None): |
441 | ''' Perform a test to find the best mirror and select it |
442 | afterwards in the treeview ''' |
443 | - class MirrorTestGtk(MirrorTest): |
444 | - def __init__(self, mirrors, test_file, running, progressbar, label): |
445 | - MirrorTest.__init__(self, mirrors, test_file, running) |
446 | - self.progress = progressbar |
447 | - self.label = label |
448 | - def report_action(self, text): |
449 | - gtk.gdk.threads_enter() |
450 | - self.label.set_label(str("<i>%s</i>" % text)) |
451 | - gtk.gdk.threads_leave() |
452 | - def report_progress(self, current, max, borders=(0,1), mod=(0,0)): |
453 | - gtk.gdk.threads_enter() |
454 | - self.progress.set_text(_("Completed %s of %s tests") % \ |
455 | - (current + mod[0], max + mod[1])) |
456 | - frac = borders[0] + (borders[1] - borders[0]) / max * current |
457 | - self.progress.set_fraction(frac) |
458 | - gtk.gdk.threads_leave() |
459 | - |
460 | - gtk.gdk.threads_enter() |
461 | self.button_cancel.set_sensitive(True) |
462 | self.dialog_test.show() |
463 | - gtk.gdk.threads_leave() |
464 | self.running = threading.Event() |
465 | self.running.set() |
466 | + progress_update = threading.Event() |
467 | pipe = os.popen("dpkg --print-architecture") |
468 | arch = pipe.read().strip() |
469 | test_file = "dists/%s/%s/binary-%s/Packages.gz" % \ |
470 | (self.distro.source_template.name, |
471 | self.distro.source_template.components[0].name, |
472 | arch) |
473 | - test = MirrorTestGtk(self.distro.source_template.mirror_set.values(), |
474 | + test = MirrorTest(self.distro.source_template.mirror_set.values(), |
475 | test_file, |
476 | - self.running, |
477 | - self.progress, |
478 | - self.label_action) |
479 | + progress_update, |
480 | + self.running) |
481 | test.start() |
482 | - rocker = test.run_full_test() |
483 | - gtk.gdk.threads_enter() |
484 | - testing.clear() |
485 | + |
486 | + # now run the tests in a background thread, and update the UI on each event |
487 | + while self.running.is_set(): |
488 | + while Gtk.events_pending(): |
489 | + Gtk.main_iteration_do(False) |
490 | + |
491 | + # don't spin the CPU until there's something to update; but update the |
492 | + # UI at least every 100 ms |
493 | + progress_update.wait(0.1) |
494 | + |
495 | + if progress_update.is_set(): |
496 | + self.progress.set_text(_("Completed %s of %s tests") % \ |
497 | + (test.progress[0], test.progress[1])) |
498 | + self.progress.set_fraction(test.progress[2]) |
499 | + progress_update.clear() |
500 | + |
501 | self.dialog_test.hide() |
502 | # Select the mirror in the list or show an error dialog |
503 | - if rocker != None: |
504 | - self.model_sort.foreach(self.select_mirror, rocker) |
505 | + if test.best != None: |
506 | + self.model_sort.foreach(self.select_mirror, test.best) |
507 | else: |
508 | dialogs.show_error_dialog(self.dialog, |
509 | _("No suitable download server was found"), |
510 | _("Please check your Internet connection.")) |
511 | - gtk.gdk.threads_leave() |
512 | |
513 | def select_mirror(self, model, path, iter, mirror): |
514 | """Select and expand the path to a matching mirror in the list""" |
515 | if model.get_value(iter, COLUMN_URI) == mirror: |
516 | self.treeview.expand_to_path(path) |
517 | - self.treeview.set_cursor(path) |
518 | + self.treeview.set_cursor(path, None, False) |
519 | self.treeview.scroll_to_cell(path, use_align=True, row_align=0.5) |
520 | self.treeview.grab_focus() |
521 | # breaks foreach |
522 | |
523 | === modified file 'softwareproperties/gtk/SimpleGtkbuilderApp.py' |
524 | --- softwareproperties/gtk/SimpleGtkbuilderApp.py 2010-08-25 08:51:00 +0000 |
525 | +++ softwareproperties/gtk/SimpleGtkbuilderApp.py 2011-02-11 12:13:56 +0000 |
526 | @@ -20,19 +20,19 @@ |
527 | # USA |
528 | |
529 | import sys |
530 | -import gtk |
531 | +from gi.repository import Gtk |
532 | |
533 | # based on SimpleGladeApp |
534 | class SimpleGtkbuilderApp: |
535 | |
536 | def __init__(self, path, domain): |
537 | - self.builder = gtk.Builder() |
538 | + self.builder = Gtk.Builder() |
539 | self.builder.set_translation_domain(domain) |
540 | self.builder.add_from_file(path) |
541 | self.builder.connect_signals(self) |
542 | for o in self.builder.get_objects(): |
543 | - if issubclass(type(o), gtk.Buildable): |
544 | - name = gtk.Buildable.get_name(o) |
545 | + if issubclass(type(o), Gtk.Buildable): |
546 | + name = Gtk.Buildable.get_name(o) |
547 | setattr(self, name, o) |
548 | else: |
549 | print >> sys.stderr, "WARNING: can not get name for '%s'" % o |
550 | @@ -47,7 +47,7 @@ |
551 | Use this method for starting programs. |
552 | """ |
553 | try: |
554 | - gtk.main() |
555 | + Gtk.main() |
556 | except KeyboardInterrupt: |
557 | self.on_keyboard_interrupt() |
558 | |
559 | @@ -61,11 +61,11 @@ |
560 | def quit(self): |
561 | """ |
562 | Quit processing events. |
563 | - The default implementation calls gtk.main_quit() |
564 | + The default implementation calls Gtk.main_quit() |
565 | |
566 | Useful for applications that needs a non gtk main loop. |
567 | For example, applications based on gstreamer needs to override |
568 | this method with gst.main_quit() |
569 | """ |
570 | - gtk.main_quit() |
571 | + Gtk.main_quit() |
572 | |
573 | |
574 | === modified file 'softwareproperties/gtk/SoftwarePropertiesGtk.py' |
575 | --- softwareproperties/gtk/SoftwarePropertiesGtk.py 2010-09-13 08:15:42 +0000 |
576 | +++ softwareproperties/gtk/SoftwarePropertiesGtk.py 2011-02-11 12:13:56 +0000 |
577 | @@ -30,7 +30,8 @@ |
578 | import re |
579 | from xml.sax.saxutils import escape |
580 | |
581 | -import gtk |
582 | +from gi.repository import Gdk |
583 | +from gi.repository import Gtk |
584 | import gobject |
585 | |
586 | from SimpleGtkbuilderApp import SimpleGtkbuilderApp |
587 | @@ -68,10 +69,10 @@ |
588 | |
589 | def error(parent_window, summary, msg): |
590 | " show a error dialog " |
591 | - dialog = gtk.MessageDialog(parent=parent_window, |
592 | - flags=gtk.DIALOG_MODAL, |
593 | - type=gtk.MESSAGE_ERROR, |
594 | - buttons=gtk.BUTTONS_OK, |
595 | + dialog = Gtk.MessageDialog(parent=parent_window, |
596 | + flags=Gtk.DialogFlags.MODAL, |
597 | + type=Gtk.MessageType.ERROR, |
598 | + buttons=Gtk.ButtonsType.OK, |
599 | message_format=None) |
600 | dialog.set_markup("<big><b>%s</b></big>\n\n%s" % (summary, msg)) |
601 | res = dialog.run() |
602 | @@ -84,13 +85,13 @@ |
603 | the used software repositories, corresponding authentication keys |
604 | and update automation """ |
605 | SoftwareProperties.__init__(self, options=options, datadir=datadir) |
606 | - gtk.window_set_default_icon_name("software-properties") |
607 | + Gtk.Window.set_default_icon_name("software-properties") |
608 | |
609 | SimpleGtkbuilderApp.__init__(self, os.path.join(datadir, "gtkbuilder", "main.ui"), |
610 | domain="software-properties") |
611 | |
612 | if parent: |
613 | - self.window_main.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) |
614 | + self.window_main.set_type_hint(Gdk.WindowTypeHint.DIALOG) |
615 | self.window_main.show() |
616 | try: |
617 | self.window_main.set_transient_for(parent) |
618 | @@ -100,12 +101,12 @@ |
619 | # If externally called, reparent to external application. |
620 | self.options = options |
621 | if options and options.toplevel != None: |
622 | - self.window_main.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) |
623 | + self.window_main.set_type_hint(Gdk.WindowTypeHint.DIALOG) |
624 | self.window_main.show() |
625 | - toplevel = gtk.gdk.window_foreign_new(int(options.toplevel)) |
626 | + toplevel = Gdk.window_foreign_new(int(options.toplevel)) |
627 | if (toplevel): |
628 | try: |
629 | - self.window_main.window.set_transient_for(toplevel) |
630 | + self.window_main.set_transient_for(toplevel) |
631 | except: |
632 | pass |
633 | if options and options.open_tab: |
634 | @@ -147,8 +148,8 @@ |
635 | |
636 | def update_interface(self): |
637 | " abstract interface to keep the UI alive " |
638 | - while gtk.events_pending(): |
639 | - gtk.main_iteration() |
640 | + while Gtk.events_pending(): |
641 | + Gtk.main_iteration() |
642 | |
643 | def init_popcon(self): |
644 | """ If popcon is enabled show the statistics tab and an explanation |
645 | @@ -167,8 +168,8 @@ |
646 | |
647 | def init_auto_update(self): |
648 | """ Set up the widgets that allow to configure the update automation """ |
649 | - self.combobox_update_interval = gtk.combo_box_new_text() |
650 | - self.hbox_check_for_updates.pack_start(self.combobox_update_interval) |
651 | + self.combobox_update_interval = Gtk.ComboBoxText.new_with_entry() |
652 | + self.hbox_check_for_updates.pack_start(self.combobox_update_interval, True, True, 0) |
653 | self.combobox_update_interval.show() |
654 | |
655 | # this maps the key (combo-box-index) to the auto-update-interval value |
656 | @@ -185,7 +186,7 @@ |
657 | self.combobox_update_interval.append_text(_("Weekly")) |
658 | self.combobox_update_interval.append_text(_("Every two weeks")) |
659 | |
660 | - model_check_interval = gtk.ListStore(gobject.TYPE_STRING, |
661 | + model_check_interval = Gtk.ListStore(gobject.TYPE_STRING, |
662 | gobject.TYPE_INT) |
663 | update_days = self.get_update_interval() |
664 | |
665 | @@ -261,9 +262,9 @@ |
666 | |
667 | # TRANS: %s stands for the distribution name e.g. Debian or Ubuntu |
668 | self.label_updates.set_label("<b>%s</b>" % (_("%s updates") %\ |
669 | - self.distro.id)) |
670 | + self.distro.id.encode('UTF-8'))) |
671 | # TRANS: %s stands for the distribution name e.g. Debian or Ubuntu |
672 | - self.label_dist_name.set_label(_("%s Software") % self.distro.id) |
673 | + self.label_dist_name.set_label(_("%s Software") % self.distro.id.encode('UTF-8')) |
674 | |
675 | |
676 | self.handlers.append((self.checkbutton_source_code, |
677 | @@ -278,7 +279,7 @@ |
678 | # first %s is the description of the component |
679 | # second %s is the code name of the comp, eg main, universe |
680 | label = _("%s (%s)") % (comp.get_description(), comp.name) |
681 | - checkbox = gtk.CheckButton(label) |
682 | + checkbox = Gtk.CheckButton(label) |
683 | |
684 | checkbox.comp = comp |
685 | # setup the callback and show the checkbutton |
686 | @@ -295,7 +296,7 @@ |
687 | if len(self.distro.source_template.children) < 1: |
688 | self.frame_children.hide() |
689 | for template in self.distro.source_template.children: |
690 | - checkbox = gtk.CheckButton(label="%s (%s)" % (template.description, |
691 | + checkbox = Gtk.CheckButton(label="%s (%s)" % (template.description, |
692 | template.name)) |
693 | checkbox.template = template |
694 | self.handlers.append((checkbox, |
695 | @@ -307,13 +308,13 @@ |
696 | |
697 | |
698 | # setup the server chooser |
699 | - cell = gtk.CellRendererText() |
700 | + cell = Gtk.CellRendererText() |
701 | self.combobox_server.pack_start(cell, True) |
702 | self.combobox_server.add_attribute(cell, 'text', 0) |
703 | self.handlers.append((self.combobox_server, |
704 | self.combobox_server.connect("changed", |
705 | self.on_combobox_server_changed))) |
706 | - server_store = gtk.ListStore(gobject.TYPE_STRING, |
707 | + server_store = Gtk.ListStore(gobject.TYPE_STRING, |
708 | gobject.TYPE_STRING, |
709 | gobject.TYPE_BOOLEAN) |
710 | self.combobox_server.set_model(server_store) |
711 | @@ -421,7 +422,7 @@ |
712 | '''Call the backend to set the update automation level to the given |
713 | value''' |
714 | if widget.get_active() == True: |
715 | - self.vbox_auto_updates.foreach(lambda b: b.set_inconsistent(False)) |
716 | + self.vbox_auto_updates.foreach(lambda b, d: b.set_inconsistent(False), None) |
717 | SoftwareProperties.set_update_automation_level(self, state) |
718 | self.set_modified_config() |
719 | |
720 | @@ -536,13 +537,13 @@ |
721 | # STORE_SOURCE - the source entry object |
722 | # STORE_SEPARATOR - if the entry is a separator |
723 | # STORE_VISIBLE - if the entry is shown or hidden |
724 | - self.cdrom_store = gtk.ListStore(gobject.TYPE_BOOLEAN, |
725 | + self.cdrom_store = Gtk.ListStore(gobject.TYPE_BOOLEAN, |
726 | gobject.TYPE_STRING, |
727 | gobject.TYPE_PYOBJECT, |
728 | gobject.TYPE_BOOLEAN, |
729 | gobject.TYPE_BOOLEAN) |
730 | self.treeview_cdroms.set_model(self.cdrom_store) |
731 | - self.source_store = gtk.ListStore(gobject.TYPE_BOOLEAN, |
732 | + self.source_store = Gtk.ListStore(gobject.TYPE_BOOLEAN, |
733 | gobject.TYPE_STRING, |
734 | gobject.TYPE_PYOBJECT, |
735 | gobject.TYPE_BOOLEAN, |
736 | @@ -551,51 +552,55 @@ |
737 | self.treeview_sources.set_row_separator_func(self.is_separator, |
738 | STORE_SEPARATOR) |
739 | |
740 | - cell_desc = gtk.CellRendererText() |
741 | + cell_desc = Gtk.CellRendererText() |
742 | cell_desc.set_property("xpad", 2) |
743 | cell_desc.set_property("ypad", 2) |
744 | - col_desc = gtk.TreeViewColumn(_("Software Sources"), cell_desc, |
745 | + col_desc = Gtk.TreeViewColumn(_("Software Sources"), cell_desc, |
746 | markup=COLUMN_DESC) |
747 | col_desc.set_max_width(1000) |
748 | |
749 | - cell_toggle = gtk.CellRendererToggle() |
750 | + cell_toggle = Gtk.CellRendererToggle() |
751 | cell_toggle.set_property("xpad", 2) |
752 | cell_toggle.set_property("ypad", 2) |
753 | self.handlers.append([cell_toggle, |
754 | cell_toggle.connect('toggled', |
755 | self.on_isv_source_toggled, |
756 | self.cdrom_store)]) |
757 | - col_active = gtk.TreeViewColumn(_("Active"), cell_toggle, |
758 | + col_active = Gtk.TreeViewColumn(_("Active"), cell_toggle, |
759 | active=COLUMN_ACTIVE) |
760 | |
761 | self.treeview_cdroms.append_column(col_active) |
762 | self.treeview_cdroms.append_column(col_desc) |
763 | |
764 | - cell_desc = gtk.CellRendererText() |
765 | + cell_desc = Gtk.CellRendererText() |
766 | cell_desc.set_property("xpad", 2) |
767 | cell_desc.set_property("ypad", 2) |
768 | - col_desc = gtk.TreeViewColumn(_("Software Sources"), cell_desc, |
769 | + col_desc = Gtk.TreeViewColumn(_("Software Sources"), cell_desc, |
770 | markup=COLUMN_DESC) |
771 | col_desc.set_max_width(1000) |
772 | |
773 | - cell_toggle = gtk.CellRendererToggle() |
774 | + cell_toggle = Gtk.CellRendererToggle() |
775 | cell_toggle.set_property("xpad", 2) |
776 | cell_toggle.set_property("ypad", 2) |
777 | self.handlers.append([cell_toggle, |
778 | cell_toggle.connect('toggled', |
779 | self.on_isv_source_toggled, |
780 | self.source_store)]) |
781 | - col_active = gtk.TreeViewColumn(_("Active"), cell_toggle, |
782 | + col_active = Gtk.TreeViewColumn(_("Active"), cell_toggle, |
783 | active=COLUMN_ACTIVE) |
784 | |
785 | self.treeview_sources.append_column(col_active) |
786 | self.treeview_sources.append_column(col_desc) |
787 | # drag and drop support for sources.list |
788 | - self.treeview_sources.drag_dest_set(gtk.DEST_DEFAULT_ALL, |
789 | - [('text/uri-list',0, 0)], |
790 | - gtk.gdk.ACTION_COPY) |
791 | - self.treeview_sources.connect("drag_data_received", |
792 | - self.on_sources_drag_data_received) |
793 | + try: |
794 | + Gtk.drag_dest_set(self.treeview_sources, Gtk.DestDefaults.ALL, |
795 | + [Gtk.TargetEntry.new('text/uri-list', 0, 0)], |
796 | + Gdk.DragAction.COPY) |
797 | + self.treeview_sources.connect("drag_data_received", |
798 | + self.on_sources_drag_data_received) |
799 | + except AttributeError: |
800 | + # does not work with Gtk2/GI |
801 | + pass |
802 | |
803 | def on_isv_source_activate(self, treeview, path, column): |
804 | """Open the edit dialog if a channel was double clicked""" |
805 | @@ -621,22 +626,27 @@ |
806 | |
807 | def init_keys(self): |
808 | """Setup the user interface parts needed for the key handling""" |
809 | - self.keys_store = gtk.ListStore(str) |
810 | + self.keys_store = Gtk.ListStore(str) |
811 | self.treeview_auth.set_model(self.keys_store) |
812 | - tr = gtk.CellRendererText() |
813 | - keys_col = gtk.TreeViewColumn("Key", tr, text=0) |
814 | + tr = Gtk.CellRendererText() |
815 | + keys_col = Gtk.TreeViewColumn("Key", tr, text=0) |
816 | self.treeview_auth.append_column(keys_col) |
817 | - self.treeview_auth.enable_model_drag_dest( |
818 | - [('text/plain', 0, 0)], gtk.gdk.ACTION_COPY) |
819 | - self.treeview_auth.connect("drag_data_received", |
820 | - self.on_auth_drag_data_received) |
821 | + try: |
822 | + self.treeview_auth.enable_model_drag_dest( |
823 | + [('text/plain', 0, 0)], Gdk.DragAction.COPY) |
824 | + self.treeview_auth.connect("drag_data_received", |
825 | + self.on_auth_drag_data_received) |
826 | + except AttributeError: |
827 | + # Does not work with GTK 2/GI |
828 | + pass |
829 | + |
830 | self.treeview_auth.connect("button-press-event", |
831 | self.show_auth_context_menu) |
832 | |
833 | def show_auth_context_menu(self, widget, event): |
834 | - if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3: |
835 | - menu = gtk.Menu() |
836 | - item_paste = gtk.MenuItem(_("_Add key from paste data")) |
837 | + if event.type == Gdk.EventType.BUTTON_PRESS and event.button == 3: |
838 | + menu = Gtk.Menu() |
839 | + item_paste = Gtk.MenuItem(_("_Add key from paste data")) |
840 | item_paste.connect("activate", self.on_auth_add_key_from_paste) |
841 | menu.add(item_paste) |
842 | menu.popup(None, None, None, 0, event.time) |
843 | @@ -644,7 +654,7 @@ |
844 | return True |
845 | |
846 | def on_auth_add_key_from_paste(self, widget): |
847 | - keydata = gtk.Clipboard().wait_for_text() |
848 | + keydata = Gtk.Clipboard().wait_for_text() |
849 | if not keydata: |
850 | return |
851 | if not self.add_key_from_data(keydata): |
852 | @@ -744,7 +754,7 @@ |
853 | self.combobox_update_interval.set_active(i) |
854 | value = self.combobox_interval_mapping[i] |
855 | # A little hack to re-set the former selected update automation level |
856 | - self.vbox_auto_updates.foreach(lambda b: b.toggled()) |
857 | + self.vbox_auto_updates.foreach(lambda b, d: b.toggled(), None) |
858 | else: |
859 | self.combobox_update_interval.set_sensitive(False) |
860 | self.vbox_auto_updates.set_sensitive(False) |
861 | @@ -770,7 +780,7 @@ |
862 | source_entry = model.get_value(iter, LIST_ENTRY_OBJ) |
863 | dialog = DialogEdit(self.window_main, self.sourceslist, |
864 | source_entry, self.datadir) |
865 | - if dialog.run() == gtk.RESPONSE_OK: |
866 | + if dialog.run() == Gtk.ResponseType.OK: |
867 | self.set_modified_sourceslist() |
868 | |
869 | # FIXME:outstanding from merge |
870 | @@ -812,17 +822,17 @@ |
871 | def add_key_clicked(self, widget): |
872 | """Provide a file chooser that allows to add the gnupg of a trusted |
873 | software vendor""" |
874 | - chooser = gtk.FileChooserDialog(title=_("Import key"), |
875 | + chooser = Gtk.FileChooserDialog(title=_("Import key"), |
876 | parent=self.window_main, |
877 | - buttons=(gtk.STOCK_CANCEL, |
878 | - gtk.RESPONSE_REJECT, |
879 | - gtk.STOCK_OK,gtk.RESPONSE_ACCEPT)) |
880 | + buttons=(Gtk.STOCK_CANCEL, |
881 | + Gtk.ResponseType.REJECT, |
882 | + Gtk.STOCK_OK,Gtk.ResponseType.ACCEPT)) |
883 | if "SUDO_USER" in os.environ: |
884 | home = os.path.expanduser("~%s" % os.environ["SUDO_USER"]) |
885 | chooser.set_current_folder(home) |
886 | res = chooser.run() |
887 | chooser.hide() |
888 | - if res == gtk.RESPONSE_ACCEPT: |
889 | + if res == Gtk.ResponseType.ACCEPT: |
890 | if not self.add_key(chooser.get_filename()): |
891 | error(self.window_main, |
892 | _("Error importing selected file"), |
893 | |
894 | === modified file 'softwareproperties/gtk/dialogs.py' |
895 | --- softwareproperties/gtk/dialogs.py 2007-02-02 19:45:52 +0000 |
896 | +++ softwareproperties/gtk/dialogs.py 2011-02-11 12:13:56 +0000 |
897 | @@ -21,12 +21,12 @@ |
898 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
899 | # USA |
900 | |
901 | -import gtk |
902 | +from gi.repository import Gtk |
903 | |
904 | def show_error_dialog(parent, primary, secondary): |
905 | p = "<span weight=\"bold\" size=\"larger\">%s</span>" % primary |
906 | - dialog = gtk.MessageDialog(parent,gtk.DIALOG_MODAL, |
907 | - gtk.MESSAGE_ERROR,gtk.BUTTONS_CLOSE,"") |
908 | + dialog = Gtk.MessageDialog(parent,Gtk.DialogFlags.MODAL, |
909 | + Gtk.MessageType.ERROR,Gtk.ButtonsType.CLOSE,"") |
910 | dialog.set_markup(p); |
911 | dialog.format_secondary_text(secondary); |
912 | dialog.run() |
913 | |
914 | === modified file 'softwareproperties/gtk/utils.py' |
915 | --- softwareproperties/gtk/utils.py 2010-09-20 12:58:51 +0000 |
916 | +++ softwareproperties/gtk/utils.py 2011-02-11 12:13:56 +0000 |
917 | @@ -16,19 +16,19 @@ |
918 | # this program; if not, write to the Free Software Foundation, Inc., |
919 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
920 | |
921 | -import gtk |
922 | +from gi.repository import Gtk |
923 | import os |
924 | import sys |
925 | |
926 | def setup_ui(self, path, domain): |
927 | # setup ui |
928 | - self.builder = gtk.Builder() |
929 | + self.builder = Gtk.Builder() |
930 | self.builder.set_translation_domain(domain) |
931 | self.builder.add_from_file(path) |
932 | self.builder.connect_signals(self) |
933 | for o in self.builder.get_objects(): |
934 | - if issubclass(type(o), gtk.Buildable): |
935 | - name = gtk.Buildable.get_name(o) |
936 | + if issubclass(type(o), Gtk.Buildable): |
937 | + name = Gtk.Buildable.get_name(o) |
938 | setattr(self, name, o) |
939 | else: |
940 | print >> sys.stderr, "WARNING: can not get name for '%s'" % o |
941 | |
942 | === modified file 'softwareproperties/kde/DialogMirror.py' |
943 | --- softwareproperties/kde/DialogMirror.py 2010-08-16 12:31:06 +0000 |
944 | +++ softwareproperties/kde/DialogMirror.py 2011-02-11 12:13:56 +0000 |
945 | @@ -160,7 +160,7 @@ |
946 | afterwards in the treeview ''' |
947 | class MirrorTestKDE(MirrorTest): |
948 | def __init__(self, mirrors, test_file, running, dialog, parent): |
949 | - MirrorTest.__init__(self, mirrors, test_file, running) |
950 | + MirrorTest.__init__(self, mirrors, test_file, None, running) |
951 | self.dialog = dialog |
952 | self.parent = parent |
953 |
Note that with our current GTK package I get crashes when clicking wildly in the mirror selection tree view. I just debugged that and fixed it in upstream GTK:
http:// git.gnome. org/browse/ gtk+/commit/ ?h=gtk- 2-24&id= 461d71f6aa7f93a 7a57a1d19053cd7 9597a09070
So we'll get this fix into Natty.