Merge lp:~ilidrissi.amine/update-manager/window-main-alerts into lp:update-manager
- window-main-alerts
- Merge into main
Proposed by
Mohamed Amine Ilidrissi
Status: | Merged |
---|---|
Merged at revision: | 1881 |
Proposed branch: | lp:~ilidrissi.amine/update-manager/window-main-alerts |
Merge into: | lp:update-manager |
Diff against target: |
413 lines (+249/-18) 4 files modified
UpdateManager/Core/AlertWatcher.py (+73/-0) UpdateManager/UpdateManager.py (+69/-6) data/glade/UpdateManager.ui (+100/-12) debian/changelog (+7/-0) |
To merge this branch: | bzr merge lp:~ilidrissi.amine/update-manager/window-main-alerts |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Vogt (community) | Needs Fixing | ||
Review via email:
|
Commit message
Description of the change
This branch introduces alerts handling for the update manager, as described in https:/
To post a comment you must log in.
- 1879. By Mohamed Amine Ilidrissi
-
merge with trunk
- 1880. By Mohamed Amine Ilidrissi
-
modified debian/changelog
- 1881. By Mohamed Amine Ilidrissi
-
included another bug in debian/changelog
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Vogt (mvo) wrote : | # |
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Vogt (mvo) : | # |
review:
Needs Fixing
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file 'UpdateManager/Core/AlertWatcher.py' |
2 | --- UpdateManager/Core/AlertWatcher.py 1970-01-01 00:00:00 +0000 |
3 | +++ UpdateManager/Core/AlertWatcher.py 2010-08-10 10:01:00 +0000 |
4 | @@ -0,0 +1,73 @@ |
5 | +# AlertWatcher.py |
6 | +# |
7 | +# Copyright (c) 2010 Mohamed Amine IL Idrissi |
8 | +# |
9 | +# Author: Mohamed Amine IL Idrissi <ilidrissiamine@gmail.com> |
10 | +# |
11 | +# This program is free software; you can redistribute it and/or |
12 | +# modify it under the terms of the GNU General Public License as |
13 | +# published by the Free Software Foundation; either version 2 of the |
14 | +# License, or (at your option) any later version. |
15 | +# |
16 | +# This program is distributed in the hope that it will be useful, |
17 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 | +# GNU General Public License for more details. |
20 | +# |
21 | +# You should have received a copy of the GNU General Public License |
22 | +# along with this program; if not, write to the Free Software |
23 | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
24 | +# USA |
25 | + |
26 | +import gobject |
27 | +import dbus |
28 | +from dbus.mainloop.glib import DBusGMainLoop |
29 | + |
30 | +class AlertWatcher(gobject.GObject): |
31 | + """ a class that checks for alerts and reports them, like a battery |
32 | + or network warning """ |
33 | + |
34 | + __gsignals__ = {"network-alert": (gobject.SIGNAL_RUN_FIRST, |
35 | + gobject.TYPE_NONE, |
36 | + (gobject.TYPE_INT,)), |
37 | + "battery-alert": (gobject.SIGNAL_RUN_FIRST, |
38 | + gobject.TYPE_NONE, |
39 | + (gobject.TYPE_BOOLEAN,)) |
40 | + } |
41 | + |
42 | + def __init__(self): |
43 | + gobject.GObject.__init__(self) |
44 | + DBusGMainLoop(set_as_default=True) |
45 | + self.bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM) |
46 | + self.network_state = 3 # make it always connected if NM isn't available |
47 | + |
48 | + def check_alert_state(self): |
49 | + try: |
50 | + obj = self.bus.get_object("org.freedesktop.NetworkManager", \ |
51 | + "/org/freedesktop/NetworkManager") |
52 | + obj.connect_to_signal("StateChanged", self._network_alert, \ |
53 | + dbus_interface="org.freedesktop.NetworkManager") |
54 | + interface = dbus.Interface(obj, "org.freedesktop.DBus.Properties") |
55 | + self.network_state = interface.Get("org.freedesktop.NetworkManager", "State") |
56 | + self._network_alert(self.network_state) |
57 | + |
58 | + obj = self.bus.get_object('org.freedesktop.UPower', |
59 | + '/org/freedesktop/UPower') |
60 | + obj.connect_to_signal("Changed", self._power_changed, |
61 | + dbus_interface="org.freedesktop.UPower") |
62 | + self._power_changed() |
63 | + except dbus.exceptions.DBusException, e: |
64 | + pass |
65 | + |
66 | + def _network_alert(self, state): |
67 | + self.network_state = state |
68 | + self.emit("network-alert", state) |
69 | + |
70 | + def _power_changed(self): |
71 | + obj = self.bus.get_object("org.freedesktop.UPower", \ |
72 | + "/org/freedesktop/UPower") |
73 | + interface = dbus.Interface(obj, "org.freedesktop.DBus.Properties") |
74 | + on_battery = interface.Get("org.freedesktop.UPower", "OnBattery") |
75 | + self.emit("battery-alert", on_battery) |
76 | + |
77 | + |
78 | |
79 | === modified file 'UpdateManager/UpdateManager.py' |
80 | --- UpdateManager/UpdateManager.py 2010-07-28 13:57:54 +0000 |
81 | +++ UpdateManager/UpdateManager.py 2010-08-10 10:01:00 +0000 |
82 | @@ -3,10 +3,12 @@ |
83 | # Copyright (c) 2004-2008 Canonical |
84 | # 2004 Michiel Sikkes |
85 | # 2005 Martin Willemoes Hansen |
86 | +# 2010 Mohamed Amine IL Idrissi |
87 | # |
88 | # Author: Michiel Sikkes <michiel@eyesopened.nl> |
89 | # Michael Vogt <mvo@debian.org> |
90 | # Martin Willemoes Hansen <mwh@sysrq.dk> |
91 | +# Mohamed Amine IL Idrissi <ilidrissiamine@gmail.com> |
92 | # |
93 | # This program is free software; you can redistribute it and/or |
94 | # modify it under the terms of the GNU General Public License as |
95 | @@ -73,6 +75,7 @@ |
96 | from Core.UpdateList import UpdateList |
97 | from Core.MyCache import MyCache, NotEnoughFreeSpaceError |
98 | from Core.MetaRelease import Dist |
99 | +from Core.AlertWatcher import AlertWatcher |
100 | from SafeGConfClient import SafeGConfClient |
101 | |
102 | from DistUpgradeFetcher import DistUpgradeFetcherGtk |
103 | @@ -95,6 +98,13 @@ |
104 | # file that signals if we need to reboot |
105 | REBOOT_REQUIRED_FILE = "/var/run/reboot-required" |
106 | |
107 | +# NetworkManager enums |
108 | +NM_STATE_UNKNOWN = 0 |
109 | +NM_STATE_ASLEEP = 1 |
110 | +NM_STATE_CONNECTING = 2 |
111 | +NM_STATE_CONNECTED = 3 |
112 | +NM_STATE_DISCONNECTED = 4 |
113 | + |
114 | class UpdateManagerDbusControler(dbus.service.Object): |
115 | """ this is a helper to provide the UpdateManagerIFace """ |
116 | def __init__(self, parent, bus_name, |
117 | @@ -224,15 +234,17 @@ |
118 | self.window_main.set_urgency_hint(True) |
119 | self.initial_focus_id = self.window_main.connect( |
120 | "focus-in-event", self.on_initial_focus_in) |
121 | - else: |
122 | - self.warn_on_battery() |
123 | + |
124 | + # Alert watcher |
125 | + self.alert_watcher = AlertWatcher() |
126 | + self.alert_watcher.connect("network-alert", self._on_network_alert) |
127 | + self.alert_watcher.connect("battery-alert", self._on_battery_alert) |
128 | |
129 | def on_initial_focus_in(self, widget, event): |
130 | """callback run on initial focus-in (if started unmapped)""" |
131 | widget.unstick() |
132 | widget.set_urgency_hint(False) |
133 | self.window_main.disconnect(self.initial_focus_id) |
134 | - self.warn_on_battery() |
135 | return False |
136 | |
137 | def warn_on_battery(self): |
138 | @@ -458,12 +470,36 @@ |
139 | try: |
140 | inst_count = self.cache.installCount |
141 | self.dl_size = self.cache.requiredDownload |
142 | - t = _("Download size: %s\n%s selected.") % ( |
143 | - humanize_size(self.dl_size),inst_count) |
144 | + t = "" |
145 | + if inst_count >= 1: |
146 | + t = ngettext("One update has been selected. ", |
147 | + "%s updates have been selected. " % inst_count, |
148 | + inst_count) |
149 | + if self.dl_size != 0: |
150 | + t += _("%s will be downloaded.") % (humanize_size(self.dl_size)) |
151 | + self.image_downsize.set_sensitive(True) |
152 | + if self.alert_watcher.network_state != NM_STATE_CONNECTED: |
153 | + self.button_install.set_sensitive(False) |
154 | + else: |
155 | + self.button_install.set_sensitive(True) |
156 | + else: |
157 | + if inst_count >= 1: |
158 | + t += ngettext("The update has already been downloaded, but not installed", |
159 | + "The updates have already been downloaded, but not installed", inst_count) |
160 | + self.button_install.set_sensitive(True) |
161 | + else: |
162 | + t += _("There is no updates to install") |
163 | + self.button_install.set_sensitive(False) |
164 | + self.image_downsize.set_sensitive(False) |
165 | self.label_downsize.set_text(t) |
166 | + self.hbox_downsize.show() |
167 | + self.vbox_alerts.show() |
168 | except SystemError, e: |
169 | print "requiredDownload could not be calculated: %s" % e |
170 | - self.label_downsize.set_markup(_("Unknown download size")) |
171 | + self.label_downsize.set_markup(_("Unknown download size.")) |
172 | + self.image_downsize.set_sensitive(False) |
173 | + self.hbox_downsize.show() |
174 | + self.vbox_alerts.show() |
175 | |
176 | def _get_last_apt_get_update_text(self): |
177 | """ |
178 | @@ -666,6 +702,31 @@ |
179 | self.window_main.set_sensitive(True) |
180 | self.window_main.window.set_cursor(None) |
181 | |
182 | + def _on_network_alert(self, watcher, state): |
183 | + if state == NM_STATE_CONNECTING: |
184 | + self.label_offline.set_text(_("Connecting...")) |
185 | + self.button_reload.set_sensitive(False) |
186 | + self.refresh_updates_count() |
187 | + self.hbox_offline.show() |
188 | + self.vbox_alerts.show() |
189 | + elif state == NM_STATE_CONNECTED: |
190 | + self.button_reload.set_sensitive(True) |
191 | + self.refresh_updates_count() |
192 | + self.hbox_offline.hide() |
193 | + else: |
194 | + self.label_offline.set_text(_("You may not be able to check for updates or download new updates.")) |
195 | + self.button_reload.set_sensitive(False) |
196 | + self.refresh_updates_count() |
197 | + self.hbox_offline.show() |
198 | + self.vbox_alerts.show() |
199 | + |
200 | + def _on_battery_alert(self, watcher, on_battery): |
201 | + if on_battery: |
202 | + self.hbox_battery.show() |
203 | + self.vbox_alerts.show() |
204 | + else: |
205 | + self.hbox_battery.hide() |
206 | + |
207 | def row_activated(self, treeview, path, column): |
208 | iter = self.store.get_iter(path) |
209 | pkg = self.store.get_value(iter, LIST_PKG) |
210 | @@ -842,6 +903,7 @@ |
211 | self.update_count() |
212 | self.setBusy(False) |
213 | self.check_all_updates_installable() |
214 | + self.refresh_updates_count() |
215 | return False |
216 | |
217 | def dist_no_longer_supported(self, meta_release): |
218 | @@ -999,4 +1061,5 @@ |
219 | |
220 | self.fillstore() |
221 | self.check_auto_update() |
222 | + self.alert_watcher.check_alert_state() |
223 | gtk.main() |
224 | |
225 | === modified file 'data/glade/UpdateManager.ui' |
226 | --- data/glade/UpdateManager.ui 2010-06-10 14:42:23 +0000 |
227 | +++ data/glade/UpdateManager.ui 2010-08-10 10:01:00 +0000 |
228 | @@ -48,7 +48,7 @@ |
229 | <property name="wrap">True</property> |
230 | <attributes> |
231 | <attribute name="weight" value="bold"/> |
232 | - <attribute name="scale" value="1,000000"/> |
233 | + <attribute name="scale" value="1.000000"/> |
234 | </attributes> |
235 | </object> |
236 | <packing> |
237 | @@ -179,7 +179,6 @@ |
238 | <child> |
239 | <object class="GtkVBox" id="vbox12"> |
240 | <property name="visible">True</property> |
241 | - <property name="spacing">6</property> |
242 | <child> |
243 | <object class="GtkScrolledWindow" id="scrolledwindow_update"> |
244 | <property name="visible">True</property> |
245 | @@ -208,15 +207,106 @@ |
246 | </packing> |
247 | </child> |
248 | <child> |
249 | + <object class="GtkVBox" id="vbox_alerts"> |
250 | + <property name="spacing">3</property> |
251 | + <child> |
252 | + <object class="GtkHBox" id="hbox_downsize"> |
253 | + <property name="spacing">12</property> |
254 | + <child> |
255 | + <object class="GtkImage" id="image_downsize"> |
256 | + <property name="visible">True</property> |
257 | + <property name="icon_name">aptdaemon-download</property> |
258 | + </object> |
259 | + <packing> |
260 | + <property name="expand">False</property> |
261 | + <property name="position">0</property> |
262 | + </packing> |
263 | + </child> |
264 | + <child> |
265 | + <object class="GtkLabel" id="label_downsize"> |
266 | + <property name="visible">True</property> |
267 | + <property name="xalign">0</property> |
268 | + <property name="label"> |
269 | +</property> |
270 | + </object> |
271 | + <packing> |
272 | + <property name="position">1</property> |
273 | + </packing> |
274 | + </child> |
275 | + </object> |
276 | + <packing> |
277 | + <property name="position">0</property> |
278 | + </packing> |
279 | + </child> |
280 | + <child> |
281 | + <object class="GtkHBox" id="hbox_battery"> |
282 | + <property name="spacing">12</property> |
283 | + <child> |
284 | + <object class="GtkImage" id="image_battery"> |
285 | + <property name="visible">True</property> |
286 | + <property name="icon_name">battery</property> |
287 | + </object> |
288 | + <packing> |
289 | + <property name="expand">False</property> |
290 | + <property name="position">0</property> |
291 | + </packing> |
292 | + </child> |
293 | + <child> |
294 | + <object class="GtkLabel" id="label_battery"> |
295 | + <property name="visible">True</property> |
296 | + <property name="label" translatable="yes">It’s safer to connect the computer to AC power before updating.</property> |
297 | + </object> |
298 | + <packing> |
299 | + <property name="expand">False</property> |
300 | + <property name="position">1</property> |
301 | + </packing> |
302 | + </child> |
303 | + </object> |
304 | + <packing> |
305 | + <property name="position">1</property> |
306 | + </packing> |
307 | + </child> |
308 | + <child> |
309 | + <object class="GtkHBox" id="hbox_offline"> |
310 | + <property name="spacing">12</property> |
311 | + <child> |
312 | + <object class="GtkImage" id="image_offline"> |
313 | + <property name="visible">True</property> |
314 | + <property name="icon_name">network-offline</property> |
315 | + </object> |
316 | + <packing> |
317 | + <property name="expand">False</property> |
318 | + <property name="position">0</property> |
319 | + </packing> |
320 | + </child> |
321 | + <child> |
322 | + <object class="GtkLabel" id="label_offline"> |
323 | + <property name="visible">True</property> |
324 | + </object> |
325 | + <packing> |
326 | + <property name="expand">False</property> |
327 | + <property name="position">1</property> |
328 | + </packing> |
329 | + </child> |
330 | + </object> |
331 | + <packing> |
332 | + <property name="position">2</property> |
333 | + </packing> |
334 | + </child> |
335 | + </object> |
336 | + <packing> |
337 | + <property name="expand">False</property> |
338 | + <property name="fill">False</property> |
339 | + <property name="position">1</property> |
340 | + </packing> |
341 | + </child> |
342 | + <child> |
343 | <object class="GtkHBox" id="hbox15"> |
344 | <property name="visible">True</property> |
345 | <property name="spacing">12</property> |
346 | <child> |
347 | - <object class="GtkLabel" id="label_downsize"> |
348 | + <object class="GtkLabel" id="label_placeholder"> |
349 | <property name="visible">True</property> |
350 | - <property name="xalign">0</property> |
351 | - <property name="label"> |
352 | -</property> |
353 | </object> |
354 | <packing> |
355 | <property name="position">0</property> |
356 | @@ -228,7 +318,7 @@ |
357 | <property name="spacing">6</property> |
358 | <property name="homogeneous">True</property> |
359 | <child> |
360 | - <object class="GtkButton" id="button1"> |
361 | + <object class="GtkButton" id="button_reload"> |
362 | <property name="visible">True</property> |
363 | <property name="can_focus">True</property> |
364 | <property name="can_default">True</property> |
365 | @@ -326,9 +416,6 @@ |
366 | <property name="position">1</property> |
367 | </packing> |
368 | </child> |
369 | - <child> |
370 | - <placeholder/> |
371 | - </child> |
372 | </object> |
373 | <packing> |
374 | <property name="expand">False</property> |
375 | @@ -338,11 +425,12 @@ |
376 | </object> |
377 | <packing> |
378 | <property name="expand">False</property> |
379 | - <property name="position">1</property> |
380 | + <property name="position">2</property> |
381 | </packing> |
382 | </child> |
383 | </object> |
384 | <packing> |
385 | + <property name="padding">6</property> |
386 | <property name="position">3</property> |
387 | </packing> |
388 | </child> |
389 | @@ -508,8 +596,8 @@ |
390 | <property name="can_default">True</property> |
391 | <property name="receives_default">False</property> |
392 | <property name="use_stock">True</property> |
393 | + <accelerator key="Q" signal="clicked" modifiers="GDK_CONTROL_MASK"/> |
394 | <accelerator key="W" signal="clicked" modifiers="GDK_CONTROL_MASK"/> |
395 | - <accelerator key="Q" signal="clicked" modifiers="GDK_CONTROL_MASK"/> |
396 | </object> |
397 | <packing> |
398 | <property name="expand">False</property> |
399 | |
400 | === modified file 'debian/changelog' |
401 | --- debian/changelog 2010-08-05 20:55:55 +0000 |
402 | +++ debian/changelog 2010-08-10 10:01:00 +0000 |
403 | @@ -1,3 +1,10 @@ |
404 | +update-manager (1:0.142.6) UNRELEASED; urgency=low |
405 | + |
406 | + * Implemented battery and network alerts directly in the main window. |
407 | + LP: #484249, #426708, #426710, #494772 |
408 | + |
409 | + -- Michael Vogt <michael.vogt@ubuntu.com> Wed, 28 Jul 2010 15:18:20 +0200 |
410 | + |
411 | update-manager (1:0.142.5) maverick; urgency=low |
412 | |
413 | * more python-apt 0.8 porting |
Thanks a lot for the branch.
I looked over it and discovered some small issues. If I start update-manager and
I'm not on AC power then I don't get a battery warning. This is because there is
no "change" signal emit (nothing in the power state has changed). So we need to
add a additional check for this on startup.
There is also the lines: install. set_sensitive( True) install. set_sensitive( True)
137 if inst_count > 1:
138 + t = _("The updates have already been downloaded, but not installed")
139 + self.button_
140 + elif inst_count == 1:
141 + t = _("The update has already been downloaded, but not installed")
142 + self.button_
143 + else:
144 + t = _("There is no updates to install")
Those are better written with ngettext, so:
inst_ count)
t = ngettext("The update has already been downloaded, but not installed",
"The updates have already been downloaded, but not installed",
This will ensure the text can be translated into languages with different plural forms
(there are eg languages that have a different on for one, below 10, more than 10).
I also like the display "Nr items selected" :) I guess its not very important, but it
would be cool to have it back.
All minor nitpicks, if you could address them, that would be very nice.
Thanks,
Michael