Merge lp:~pitti/computer-janitor/pygi into lp:computer-janitor

Proposed by Martin Pitt
Status: Merged
Approved by: Barry Warsaw
Approved revision: 257
Merged at revision: 254
Proposed branch: lp:~pitti/computer-janitor/pygi
Merge into: lp:computer-janitor
Diff against target: 365 lines (+74/-51)
7 files modified
computerjanitorapp/gtk/dialogs.py (+14/-14)
computerjanitorapp/gtk/store.py (+5/-5)
computerjanitorapp/gtk/ui.py (+31/-23)
data/ComputerJanitor.ui (+0/-2)
debian/changelog (+18/-0)
debian/control (+6/-6)
run_from_checkout.sh (+0/-1)
To merge this branch: bzr merge lp:~pitti/computer-janitor/pygi
Reviewer Review Type Date Requested Status
Barry Warsaw Approve
Martin Pitt Needs Resubmitting
Review via email: mp+46779@code.launchpad.net

Description of the change

This branch ports from pygtk to pygi. With GTK3 it works perfectly, with GTK2 we have to disable the "select all/none" right-click popup menu, but I think we can live with that (see changelog and code comment for details).

Note that I had to fix some stuff in pygobject for this, so I bumped the dependency to a not-yet-released version. I'll upload a new git snapshot of pygobject to natty soon, but for now if you want to play with this, do

  git clone git://git.gnome.org/pygobject
  ./autogen.sh && make
  export PYTHONPATH=`pwd`:$PYTHONPATH

and then run "./run_from_checkout.sh" in the computer-janitor branch.

I think it should work with the current gtk2 that we have in Natty (I tested it), but I also did a lot of fixes there recently for porting other software. So please let me know if you get crashes or malfunctions.

To post a comment you must log in.
Revision history for this message
Martin Pitt (pitti) wrote :

Note that I just uploaded a recent git snapshot of pygobject into natty, which now works with this branch. We also have the hot and fresh gtk 2.24.0 release with lots of annotation fixes, so this branch works fine on current natty now.

Revision history for this message
Barry Warsaw (barry) wrote :

Thanks Martin! I'll give it another try tomorrow.

lp:~pitti/computer-janitor/pygi updated
257. By Martin Pitt

merge with trunk

Revision history for this message
Martin Pitt (pitti) wrote :

I merged my branch with trunk for yesterday's upload, and ported the new bits.

review: Needs Resubmitting
Revision history for this message
Barry Warsaw (barry) wrote :

Thanks Martin, this looks really good. I'm going to go ahead and merge it, with a few minor changes (which I'll make after the merge):

* Bump version number to 2.1
* Update copyright years
* Tweak a few Python style things
* Use logging instead of stderr for the popup message

On the latter, what do you think about adding an Edit menu that has the following items:

Select all
Select all packages
Select all other
---
Unselect all
Unselect all packages
Unselect all other

That would at least provide the missing functionality elsewhere, and we could even keep that when using gtk3.

review: Approve
Revision history for this message
Martin Pitt (pitti) wrote :

Thanks Barry! An Edit menu sounds fine to me, and it's also more obvious than the right click menu. But in the next Ubuntu release we'll have GTK 3, and thus can have the menu back.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'computerjanitorapp/gtk/dialogs.py'
--- computerjanitorapp/gtk/dialogs.py 2011-02-15 22:24:27 +0000
+++ computerjanitorapp/gtk/dialogs.py 2011-02-16 13:45:44 +0000
@@ -23,7 +23,7 @@
23 ]23 ]
2424
2525
26import gtk26from gi.repository import Gtk
2727
28from operator import mod as interpolate28from operator import mod as interpolate
2929
@@ -71,15 +71,15 @@
71 if ok_button is None:71 if ok_button is None:
72 # The user de-selected all cruft from the ui, so there's actually72 # The user de-selected all cruft from the ui, so there's actually
73 # nothing to clean up.73 # nothing to clean up.
74 dialog = gtk.MessageDialog(74 dialog = Gtk.MessageDialog(
75 parent=self._ui.widgets['window'],75 parent=self._ui.widgets['window'],
76 type=gtk.MESSAGE_WARNING,76 type=Gtk.MessageType.WARNING,
77 buttons=gtk.BUTTONS_NONE,77 buttons=Gtk.ButtonsType.NONE,
78 message_format=_('There is nothing to clean up'),78 message_format=_('There is nothing to clean up'),
79 )79 )
80 dialog.set_title(_('Clean up'))80 dialog.set_title(_('Clean up'))
81 dialog.format_secondary_markup(message)81 dialog.format_secondary_markup(message)
82 dialog.add_button(_('Ok'), gtk.RESPONSE_YES)82 dialog.add_button(_('Ok'), Gtk.ResponseType.YES)
83 dialog.show_all()83 dialog.show_all()
84 dialog.run()84 dialog.run()
85 dialog.hide()85 dialog.hide()
@@ -88,20 +88,20 @@
88 # but that would require a richer interface to the dbus service,88 # but that would require a richer interface to the dbus service,
89 # and probably to the cruft plugin architecture underneath that.89 # and probably to the cruft plugin architecture underneath that.
90 message = _('Are you sure you want to clean your system?')90 message = _('Are you sure you want to clean your system?')
91 dialog = gtk.MessageDialog(91 dialog = Gtk.MessageDialog(
92 parent=self._ui.widgets['window'],92 parent=self._ui.widgets['window'],
93 type=gtk.MESSAGE_WARNING,93 type=Gtk.MessageType.WARNING,
94 buttons=gtk.BUTTONS_NONE,94 buttons=Gtk.ButtonsType.NONE,
95 message_format=message)95 message_format=message)
96 dialog.set_title(_('Clean up'))96 dialog.set_title(_('Clean up'))
97 dialog.format_secondary_markup(message)97 dialog.format_secondary_markup(message)
98 dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CLOSE)98 dialog.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CLOSE)
99 dialog.add_button(ok_button, gtk.RESPONSE_YES)99 dialog.add_button(ok_button, Gtk.ResponseType.YES)
100 # Show the dialog and get the user's response.100 # Show the dialog and get the user's response.
101 dialog.show_all()101 dialog.show_all()
102 response = dialog.run()102 response = dialog.run()
103 dialog.hide()103 dialog.hide()
104 return response == gtk.RESPONSE_YES104 return response == Gtk.ResponseType.YES
105105
106106
107class CleanupProblem(DialogBase):107class CleanupProblem(DialogBase):
@@ -116,10 +116,10 @@
116 message = _('System clean up could not complete. '116 message = _('System clean up could not complete. '
117 'Be sure no other package manager such as Synaptic or '117 'Be sure no other package manager such as Synaptic or '
118 'Update Manager is running.')118 'Update Manager is running.')
119 dialog = gtk.MessageDialog(119 dialog = Gtk.MessageDialog(
120 parent=self._ui.widgets['window'],120 parent=self._ui.widgets['window'],
121 type=gtk.MESSAGE_ERROR,121 type=Gtk.MessageType.ERROR,
122 buttons=gtk.BUTTONS_OK,122 buttons=Gtk.ButtonsType.OK,
123 message_format=message)123 message_format=message)
124 dialog.set_title(_('System clean up failure'))124 dialog.set_title(_('System clean up failure'))
125 dialog.show_all()125 dialog.show_all()
126126
=== modified file 'computerjanitorapp/gtk/store.py'
--- computerjanitorapp/gtk/store.py 2010-03-22 18:17:11 +0000
+++ computerjanitorapp/gtk/store.py 2011-02-16 13:45:44 +0000
@@ -24,7 +24,7 @@
24 ]24 ]
2525
2626
27import gtk27from gi.repository import Gtk
28import gobject28import gobject
2929
3030
@@ -49,7 +49,7 @@
4949
5050
51class Store:51class Store:
52 """The higher level wrapper around the gtk.ListStore."""52 """The higher level wrapper around the Gtk.ListStore."""
5353
54 def __init__(self, janitord):54 def __init__(self, janitord):
55 """Create the Store.55 """Create the Store.
@@ -63,7 +63,7 @@
63 # of cruft. See ListStoreColumns for details.63 # of cruft. See ListStoreColumns for details.
64 #64 #
65 # XXX 2010-03-04 barry: pygtk does not like 'unicode'.65 # XXX 2010-03-04 barry: pygtk does not like 'unicode'.
66 self.store = gtk.ListStore(str, str, str, bool, bool, bool, bool, bool)66 self.store = Gtk.ListStore(str, str, str, bool, bool, bool, bool, bool)
6767
68 def find_cruft(self):68 def find_cruft(self):
69 """Find cruft and populate the backing store.69 """Find cruft and populate the backing store.
@@ -139,7 +139,7 @@
139139
140# Filter functions for use with TreeView column display.140# Filter functions for use with TreeView column display.
141141
142def unused(store, iter):142def unused(store, iter, data):
143 """True if the cruft is not being ignored and is package cruft.143 """True if the cruft is not being ignored and is package cruft.
144144
145 :param store: The ListStore instance.145 :param store: The ListStore instance.
@@ -150,7 +150,7 @@
150 return show and is_package_cruft150 return show and is_package_cruft
151151
152152
153def optimize(store, iter):153def optimize(store, iter, data):
154 """True if the cruft is not package cruft.154 """True if the cruft is not package cruft.
155155
156 :param store: The ListStore instance.156 :param store: The ListStore instance.
157157
=== modified file 'computerjanitorapp/gtk/ui.py'
--- computerjanitorapp/gtk/ui.py 2010-08-23 13:56:29 +0000
+++ computerjanitorapp/gtk/ui.py 2011-02-16 13:45:44 +0000
@@ -23,11 +23,12 @@
2323
2424
25import os25import os
26import gtk26from gi.repository import Gtk
27Gtk.require_version('2.0')
27import sys28import sys
28import dbus29import dbus
29import glib30import glib
30import pango31from gi.repository import Pango
31import gobject32import gobject
3233
33from operator import mod34from operator import mod
@@ -86,7 +87,7 @@
8687
87 def run(self):88 def run(self):
88 """Set up the widgets and run the main loop."""89 """Set up the widgets and run the main loop."""
89 builder = gtk.Builder()90 builder = Gtk.Builder()
90 builder.set_translation_domain('computerjanitor')91 builder.set_translation_domain('computerjanitor')
91 # Load the glade ui file, which can be overridden from the environment92 # Load the glade ui file, which can be overridden from the environment
92 # for testing purposes.93 # for testing purposes.
@@ -109,7 +110,7 @@
109 root.set_default_size(ROOT_WIDTH, ROOT_HEIGHT)110 root.set_default_size(ROOT_WIDTH, ROOT_HEIGHT)
110 # Map the root window and go!111 # Map the root window and go!
111 root.show()112 root.show()
112 gtk.main()113 Gtk.main()
113114
114 def find_and_bind_widgets(self, builder):115 def find_and_bind_widgets(self, builder):
115 """Bind widgets and callbacks."""116 """Bind widgets and callbacks."""
@@ -117,8 +118,8 @@
117 # keeping track of them as mapped to their name.118 # keeping track of them as mapped to their name.
118 self.widgets = {}119 self.widgets = {}
119 for ui_object in builder.get_objects():120 for ui_object in builder.get_objects():
120 if issubclass(type(ui_object), gtk.Buildable):121 if issubclass(type(ui_object), Gtk.Buildable):
121 widget_name = gtk.Buildable.get_name(ui_object)122 widget_name = Gtk.Buildable.get_name(ui_object)
122 self.widgets[widget_name] = ui_object123 self.widgets[widget_name] = ui_object
123 # Search through the attributes of this instance looking for124 # Search through the attributes of this instance looking for
124 # callbacks for this widget. We use the naming convention125 # callbacks for this widget. We use the naming convention
@@ -143,29 +144,29 @@
143 # Each TreeView contains two columns. The leftmost one is a toggle144 # Each TreeView contains two columns. The leftmost one is a toggle
144 # that when select tells c-j to act on that cruft. Deselecting the145 # that when select tells c-j to act on that cruft. Deselecting the
145 # toggle ignores the package for next time.146 # toggle ignores the package for next time.
146 toggle_cr = gtk.CellRendererToggle()147 toggle_cr = Gtk.CellRendererToggle()
147 toggle_cr.connect('toggled', self._toggled, treeview)148 toggle_cr.connect('toggled', self._toggled, treeview)
148 toggle_cr.set_property('yalign', 0)149 toggle_cr.set_property('yalign', 0)
149 toggle_col = gtk.TreeViewColumn()150 toggle_col = Gtk.TreeViewColumn()
150 toggle_col.pack_start(toggle_cr)151 toggle_col.pack_start(toggle_cr, True)
151 toggle_col.add_attribute(toggle_cr, 'active', ListStoreColumns.active)152 toggle_col.add_attribute(toggle_cr, 'active', ListStoreColumns.active)
152 treeview.append_column(toggle_col)153 treeview.append_column(toggle_col)
153 # The rightmost column contains the details of the cruft. It will154 # The rightmost column contains the details of the cruft. It will
154 # always contain the cruft name and can be expanded to display cruft155 # always contain the cruft name and can be expanded to display cruft
155 # details. Tell the column to get its toggle's active state from the156 # details. Tell the column to get its toggle's active state from the
156 # model.157 # model.
157 name_cr = gtk.CellRendererText()158 name_cr = Gtk.CellRendererText()
158 name_cr.set_property('yalign', 0)159 name_cr.set_property('yalign', 0)
159 name_cr.set_property('wrap-mode', pango.WRAP_WORD)160 name_cr.set_property('wrap-mode', Pango.WrapMode.WORD)
160 name_col = gtk.TreeViewColumn()161 name_col = Gtk.TreeViewColumn()
161 name_col.pack_start(name_cr)162 name_col.pack_start(name_cr, True)
162 name_col.add_attribute(name_cr, 'markup', ListStoreColumns.text)163 name_col.add_attribute(name_cr, 'markup', ListStoreColumns.text)
163 treeview.append_column(name_col)164 treeview.append_column(name_col)
164 self.cruft_name_columns.add(name_col)165 self.cruft_name_columns.add(name_col)
165 # The individual crufts may or may not be visible in this TreeView.166 # The individual crufts may or may not be visible in this TreeView.
166 # It's the filter function that controls this, so set that now.167 # It's the filter function that controls this, so set that now.
167 filter_store = self.store.filter_new()168 filter_store = self.store.filter_new(None)
168 filter_store.set_visible_func(filter_func)169 filter_store.set_visible_func(filter_func, None)
169 treeview.set_model(filter_store)170 treeview.set_model(filter_store)
170 # Each TreeView has a popup menu for select or deselecting all visible171 # Each TreeView has a popup menu for select or deselecting all visible
171 # cruft.172 # cruft.
@@ -176,12 +177,12 @@
176177
177 :param treeview: The `TreeView` to attach the menu to.178 :param treeview: The `TreeView` to attach the menu to.
178 """179 """
179 select_all = gtk.MenuItem(label='Select all')180 select_all = Gtk.MenuItem(label='Select all')
180 select_all.connect('activate', self.popup_menu_select_all, treeview)181 select_all.connect('activate', self.popup_menu_select_all, treeview)
181 unselect_all = gtk.MenuItem(label='Unselect all')182 unselect_all = Gtk.MenuItem(label='Unselect all')
182 unselect_all.connect('activate',183 unselect_all.connect('activate',
183 self.popup_menu_unselect_all, treeview)184 self.popup_menu_unselect_all, treeview)
184 menu = gtk.Menu()185 menu = Gtk.Menu()
185 menu.append(select_all)186 menu.append(select_all)
186 menu.append(unselect_all)187 menu.append(unselect_all)
187 menu.show_all()188 menu.show_all()
@@ -389,7 +390,7 @@
389 # Don't quit while we're working.390 # Don't quit while we're working.
390 if self.working:391 if self.working:
391 return True392 return True
392 gtk.main_quit()393 Gtk.main_quit()
393394
394 on_window_delete_event = on_quit_menuitem_activate395 on_window_delete_event = on_quit_menuitem_activate
395396
@@ -402,7 +403,7 @@
402 """403 """
403 # Original comment: This is slightly tricky and probably a source of404 # Original comment: This is slightly tricky and probably a source of
404 # bugs. Oh well.405 # bugs. Oh well.
405 if event.button == 1:406 if event.button.button == 1:
406 # Left button event. Select the row being clicked on. If the407 # Left button event. Select the row being clicked on. If the
407 # click is on the cruft name, show or hide its long description.408 # click is on the cruft name, show or hide its long description.
408 # If the click the click is elsewhere do not handle it. This409 # If the click the click is elsewhere do not handle it. This
@@ -423,7 +424,7 @@
423 # We are not handling this event so that the toggle button424 # We are not handling this event so that the toggle button
424 # handling can occur.425 # handling can occur.
425 return False426 return False
426 elif event.button == 3:427 elif event.button.button == 3:
427 # Right button event. Pop up the select/deselect all menu.428 # Right button event. Pop up the select/deselect all menu.
428 treeview.grab_focus()429 treeview.grab_focus()
429 x = int(event.x)430 x = int(event.x)
@@ -434,7 +435,14 @@
434 path, column, cell_x, cell_y = pathinfo435 path, column, cell_x, cell_y = pathinfo
435 treeview.set_cursor(path, column, False)436 treeview.set_cursor(path, column, False)
436 menu = self.popup_menus[treeview]437 menu = self.popup_menus[treeview]
437 menu.popup(None, None, None, event.button, time)438 try:
439 menu.popup_for_device(None, None, None, None, None,
440 event.button.button, time)
441 except AttributeError:
442 # popup_for_device() is introspection safe, but only exists in
443 # GTK3. popup() isn't introspectable, so in GTK 2 we need to
444 # disable the popup menu functionality
445 print >> sys.stderr, 'popup menu not supported when using GTK2'
438 return True446 return True
439 else:447 else:
440 # No other events are handled by us.448 # No other events are handled by us.
@@ -454,7 +462,7 @@
454 # Get the rightmost of the two columns in the TreeView, i.e. the one462 # Get the rightmost of the two columns in the TreeView, i.e. the one
455 # containing the text.463 # containing the text.
456 column = treeview.get_column(1)464 column = treeview.get_column(1)
457 name_cr = column.get_cell_renderers()[0]465 name_cr = column.get_cells()[0]
458 # Wrap to the entire width of the column.466 # Wrap to the entire width of the column.
459 width = column.get_width()467 width = column.get_width()
460 name_cr.set_property('wrap-width', width)468 name_cr.set_property('wrap-width', width)
461469
=== modified file 'data/ComputerJanitor.ui'
--- data/ComputerJanitor.ui 2010-09-20 12:31:47 +0000
+++ data/ComputerJanitor.ui 2011-02-16 13:45:44 +0000
@@ -266,7 +266,6 @@
266 <property name="border_width">5</property>266 <property name="border_width">5</property>
267 <property name="type_hint">normal</property>267 <property name="type_hint">normal</property>
268 <property name="transient_for">window</property>268 <property name="transient_for">window</property>
269 <property name="has_separator">False</property>
270 <property name="program_name">Computer Janitor</property>269 <property name="program_name">Computer Janitor</property>
271 <property name="version">x.y</property>270 <property name="version">x.y</property>
272 <property name="copyright" translatable="yes">Copyright 2008, 2009, 2010 Canonical Ltd.271 <property name="copyright" translatable="yes">Copyright 2008, 2009, 2010 Canonical Ltd.
@@ -305,7 +304,6 @@
305 <property name="destroy_with_parent">True</property>304 <property name="destroy_with_parent">True</property>
306 <property name="type_hint">normal</property>305 <property name="type_hint">normal</property>
307 <property name="transient_for">window</property>306 <property name="transient_for">window</property>
308 <property name="has_separator">False</property>
309 <child internal-child="vbox">307 <child internal-child="vbox">
310 <object class="GtkVBox" id="dialog-vbox2">308 <object class="GtkVBox" id="dialog-vbox2">
311 <property name="visible">True</property>309 <property name="visible">True</property>
312310
=== modified file 'debian/changelog'
--- debian/changelog 2011-02-15 23:20:27 +0000
+++ debian/changelog 2011-02-16 13:45:44 +0000
@@ -1,3 +1,21 @@
1computer-janitor (2.0.6-0ubuntu1) UNRELEASED; urgency=low
2
3 * data/ComputerJanitor.ui: Drop obsolete has_separator properties.
4 * run_from_checkout.sh: Drop setting of $PYTHONPATH. Current directory is
5 there by default anyway, and this breaks setting it from the environment.
6 * computerjanitorapp/gtk/*: Port from pygtk2 to pygi. Works fully with GTK3
7 now, with GTK2 we need to disable the right-click popup menu
8 (popup_for_device() is introspection safe, but only exists in GTK3.
9 popup() isn't introspectable).
10 * computerjanitorapp/gtk/ui.py: Force GTK2 for now, as we do not yet have a
11 GTK3 theme in Natty, and don't carry the GTK3 stack in the default
12 install.
13 * debian/control: Update dependencies for the pygtk → pygi switch.
14 * debian/control: Drop obsolete system-cleaner conflicts and gksu
15 dependency.
16
17 -- Martin Pitt <martin.pitt@ubuntu.com> Sat, 15 Jan 2011 11:31:02 -0600
18
1computer-janitor (2.0.5-0ubuntu1) natty; urgency=low19computer-janitor (2.0.5-0ubuntu1) natty; urgency=low
220
3 * python-dbus cannot type-convert a set, so use a tuple for the package21 * python-dbus cannot type-convert a set, so use a tuple for the package
422
=== modified file 'debian/control'
--- debian/control 2011-01-12 19:16:56 +0000
+++ debian/control 2011-02-16 13:45:44 +0000
@@ -18,8 +18,6 @@
18 python-argparse (>= 1.1),18 python-argparse (>= 1.1),
19 dbus,19 dbus,
20 update-manager-core (>= 1:0.98.1)20 update-manager-core (>= 1:0.98.1)
21Conflicts: system-cleaner
22Replaces: system-cleaner
23XB-Python-Version: ${python:Versions}21XB-Python-Version: ${python:Versions}
24Description: Clean up a system so it's more like a freshly installed one22Description: Clean up a system so it's more like a freshly installed one
25 Over time, a computer system tends to get cluttered. For example,23 Over time, a computer system tends to get cluttered. For example,
@@ -35,10 +33,12 @@
3533
36Package: computer-janitor-gtk34Package: computer-janitor-gtk
37Architecture: all35Architecture: all
38Depends: ${python:Depends}, computer-janitor (=${source:Version}), 36Depends: ${python:Depends},
39 python-gtk2 (>= 2.16), ${misc:Depends}, gksu37 computer-janitor (=${source:Version}),
40Conflicts: system-cleaner-gtk38 python-gobject (>= 2.27.0+git20110116),
41Replaces: system-cleaner-gtk39 gir1.2-gtk-2.0 (>= 2.23.90-0ubuntu3),
40 gir1.2-pango-2.0,
41 ${misc:Depends}
42XB-Python-Version: ${python:Versions}42XB-Python-Version: ${python:Versions}
43Description: Clean up a system so it's more like a freshly installed one43Description: Clean up a system so it's more like a freshly installed one
44 Over time, a computer system tends to get cluttered. For example,44 Over time, a computer system tends to get cluttered. For example,
4545
=== modified file 'run_from_checkout.sh'
--- run_from_checkout.sh 2009-11-10 20:09:40 +0000
+++ run_from_checkout.sh 2011-02-16 13:45:44 +0000
@@ -3,7 +3,6 @@
3# wrapper to make it easy to run c-j from a bzr checkout3# wrapper to make it easy to run c-j from a bzr checkout
4#4#
55
6export PYTHONPATH=.
7export COMPUTER_JANITOR_PLUGINS=./plugins 6export COMPUTER_JANITOR_PLUGINS=./plugins
8export COMPUTER_JANITOR_GLADE=./data/ComputerJanitor.ui7export COMPUTER_JANITOR_GLADE=./data/ComputerJanitor.ui
9export COMPUTER_JANITOR_DEBUG=yes8export COMPUTER_JANITOR_DEBUG=yes

Subscribers

People subscribed via source and target branches