Merge lp:~thisfred/ubuntuone-client/lp-702055 into lp:ubuntuone-client
- lp-702055
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | dobey |
Approved revision: | 851 |
Merged at revision: | 854 |
Proposed branch: | lp:~thisfred/ubuntuone-client/lp-702055 |
Merge into: | lp:ubuntuone-client |
Diff against target: |
501 lines (+173/-63) 6 files modified
tests/platform/linux/test_messaging.py (+8/-3) tests/status/test_aggregator.py (+90/-27) ubuntuone/platform/linux/messaging.py (+28/-11) ubuntuone/platform/windows/messaging.py (+15/-8) ubuntuone/status/aggregator.py (+28/-12) ubuntuone/status/messaging.py (+4/-2) |
To merge this branch: | bzr merge lp:~thisfred/ubuntuone-client/lp-702055 |
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Natalia Bidart (community) | Approve | ||
Alejandro J. Cura (community) | Approve | ||
Review via email: mp+48987@code.launchpad.net |
Commit message
This adds notifications and messaging on new incoming shares and UDFs.
Description of the change
This adds notifications and messaging on new incoming shares and UDFs.
Alejandro J. Cura (alecu) wrote : | # |
Also, StatusAggregato
For instance, turning on the computer and finding out 3 new udfs are available. With this branch we'll see three bubbles one after the other, each popping up immediately after the previous is hidden. With an updating mechanism we would only see one bubble, and the message would be updated as soon as the second and third udfs are found.
Eric Casteleijn (thisfred) wrote : | # |
The reason share_available does not pass the callback, is because it does not need a special callback method that updates the count like new_udf. If no callback is passed in, the default is used, which opens the volumes tab in the control panel and hides the message.
I'll rename the _callback method.
And yes, we probably will want to aggregate the notifications (though maybe not for new shares.) I'll look into that on a new branch.
Eric Casteleijn (thisfred) wrote : | # |
method renamed in r851
Natalia Bidart (nataliabidart) : | # |
Ubuntu One Auto Pilot (otto-pilot) wrote : | # |
The attempt to merge lp:~thisfred/ubuntuone-client/lp-702055 into lp:ubuntuone-client failed. Below is the output from the failed tests.
/usr/bin/
checking for autoconf >= 2.53...
testing autoconf2.50... not found.
testing autoconf... found 2.67
checking for automake >= 1.10...
testing automake-1.11... found 1.11.1
checking for libtool >= 1.5...
testing libtoolize... found 2.2.6b
checking for intltool >= 0.30...
testing intltoolize... found 0.41.1
checking for pkg-config >= 0.14.0...
testing pkg-config... found 0.25
checking for gtk-doc >= 1.0...
testing gtkdocize... found 1.16
Checking for required M4 macros...
Checking for forbidden M4 macros...
Processing ./configure.ac
Running libtoolize...
libtoolize: putting auxiliary files in `.'.
libtoolize: copying file `./ltmain.sh'
libtoolize: putting macros in AC_CONFIG_
libtoolize: copying file `m4/libtool.m4'
libtoolize: copying file `m4/ltoptions.m4'
libtoolize: copying file `m4/ltsugar.m4'
libtoolize: copying file `m4/ltversion.m4'
libtoolize: copying file `m4/lt~obsolete.m4'
Running intltoolize...
Running gtkdocize...
Running aclocal-1.11...
Running autoconf...
Running autoheader...
Running automake-1.11...
Running ./configure --enable-gtk-doc --enable-debug ...
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for style of include used by make... GNU
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking dependency style of gcc... gcc3
checking for library containing strerror... none required
checking for gcc... (cached) gcc
checking whether we are using the GNU C compiler... (cached) yes
checking whether gcc accepts -g... (cached) yes
checking for gcc option to accept ISO C89... (cached) none needed
checking dependency style of gcc... (cached) gcc3
checking build system type... i686-pc-linux-gnu
checking host system type... i686-pc-linux-gnu
checking for a sed that does not truncate output... /bin/sed
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for fgrep... /bin/grep -F
checking for ld used by gcc... /usr/bin/ld
checking if the linker (/usr/bin/ld) is GNU ld... yes
checking for BSD- or MS-compatible name lister (nm)... /usr/bin/nm -B
checking the name lister (/usr/bin/nm -B) interface... BSD nm
checking whether ln -s works... yes
checking the maximum length of command line arguments... 1572864
checking whether the shell understands some XSI constructs... yes
checking whether the shell understands "+="... yes
checking for /usr/bin/ld option to reload object files... -r
checking for objdump... objdump
checking how to recognize dependent libraries...
Preview Diff
1 | === modified file 'tests/platform/linux/test_messaging.py' |
2 | --- tests/platform/linux/test_messaging.py 2011-02-03 17:50:53 +0000 |
3 | +++ tests/platform/linux/test_messaging.py 2011-02-09 13:12:13 +0000 |
4 | @@ -49,6 +49,7 @@ |
5 | self.mocker.restore() |
6 | self.mocker.verify() |
7 | |
8 | + # pylint: disable=R0913 |
9 | def _show_message_setup(self, message_time=None, message_count=None, |
10 | icon=None, update_count=None, hide=False): |
11 | """Set up the mocker expectations for show_method.""" |
12 | @@ -81,12 +82,15 @@ |
13 | mock_indicator.set_property("draw-attention", "true") |
14 | mock_server.show() |
15 | if update_count: |
16 | - mock_indicator.set_property("count", str(update_count)) |
17 | + mock_indicator.get_property("count") |
18 | + self.mocker.result("1200") |
19 | + mock_indicator.set_property("count", '2500') |
20 | if hide: |
21 | mock_indicator.set_property('draw-attention', 'false') |
22 | mock_indicator.hide() |
23 | mock_indicator.show() |
24 | self.mocker.replay() |
25 | + # pylint: enable=R0913 |
26 | |
27 | def test_show_message(self): |
28 | """On message, libnotify receives the proper calls.""" |
29 | @@ -116,8 +120,9 @@ |
30 | """On message count update, libnotify receives the proper calls.""" |
31 | self._show_message_setup(message_count='1200', update_count='1300') |
32 | messaging = Messaging() |
33 | - messaging.show_message(FAKE_SENDER, callback, message_count=1200) |
34 | - messaging.update_count(FAKE_SENDER, 1300) |
35 | + indicator = messaging.show_message( |
36 | + FAKE_SENDER, callback, message_count=1200) |
37 | + messaging.update_count(indicator, 1300) |
38 | |
39 | def test_hide_message(self): |
40 | """On message hide, libnotify receives the proper calls.""" |
41 | |
42 | === modified file 'tests/status/test_aggregator.py' |
43 | --- tests/status/test_aggregator.py 2011-02-04 02:25:03 +0000 |
44 | +++ tests/status/test_aggregator.py 2011-02-09 13:12:13 +0000 |
45 | @@ -25,6 +25,7 @@ |
46 | from ubuntuone.devtools.handlers import MementoHandler |
47 | from ubuntuone.status import aggregator |
48 | from ubuntuone.status.notification import AbstractNotification |
49 | +from ubuntuone.status.messaging import AbstractMessaging |
50 | from ubuntuone.syncdaemon import status_listener |
51 | from ubuntuone.syncdaemon.volume_manager import Share, UDF |
52 | |
53 | @@ -144,7 +145,7 @@ |
54 | notification] |
55 | if new_icon is not None: |
56 | icon = new_icon |
57 | - # we store it as a new notification, to ease testing |
58 | + # we store it as a new notification, to ease testing |
59 | notification_params = (new_title, new_message, icon, append) |
60 | self.notifications_shown.append(notification_params) |
61 | |
62 | @@ -160,30 +161,32 @@ |
63 | return get_instance |
64 | |
65 | |
66 | -class FakeMessaging(object): |
67 | +class FakeMessaging(AbstractMessaging): |
68 | """A fake messaging class.""" |
69 | |
70 | - def __init__(self, application_name="fake app"): |
71 | + def __init__(self): # pylint: disable=W0231 |
72 | self.messages_shown = {} |
73 | - self.application_name = application_name |
74 | + self.messages_updated = {} |
75 | |
76 | - def show_message(self, sender, callback, message_time=None, |
77 | + # pylint: disable=R0913 |
78 | + def show_message(self, sender, callback=None, message_time=None, |
79 | message_count=None, icon=None): |
80 | """Show a message to the user.""" |
81 | + if message_count and sender in self.messages_shown: |
82 | + self.update_count(sender, message_count) |
83 | self.messages_shown[sender] = ( |
84 | callback, message_time, message_count, icon) |
85 | + # pylint: enable=R0913 |
86 | |
87 | - def update_count(self, sender, new_count): |
88 | + def update_count(self, sender, add_count): |
89 | """Update the count for an existing indicator.""" |
90 | - callback, message_time, _, icon = self.messages_shown[sender] |
91 | - self.messages_shown[sender] = ( |
92 | - callback, message_time, new_count, icon) |
93 | + self.messages_updated[sender] = (sender, add_count) |
94 | |
95 | |
96 | class FakeStatusAggregator(object): |
97 | """A fake status aggregator.""" |
98 | |
99 | - def __init__(self, clock): |
100 | + def __init__(self, clock): # pylint: disable=W0613 |
101 | """Initialize this instance.""" |
102 | self.discovered = 0 |
103 | self.completed = 0 |
104 | @@ -523,13 +526,8 @@ |
105 | |
106 | def __init__(self, clock): |
107 | """Initialize this fake instance.""" |
108 | - self.interesting_events = [] |
109 | self.queued_commands = set() |
110 | |
111 | - def interesting_event(self, event): |
112 | - """A new interesting event was found.""" |
113 | - self.interesting_events.append(event) |
114 | - |
115 | def queue_done(self): |
116 | """The queue completed all operations.""" |
117 | self.queued_commands.clear() |
118 | @@ -554,23 +552,30 @@ |
119 | def setUp(self): |
120 | """Initialize this test instance.""" |
121 | self.patch(aggregator, "StatusAggregator", FakeAggregator) |
122 | + self.patch(aggregator, "Notification", FakeNotificationSingleton()) |
123 | + self.patch(aggregator, "Messaging", FakeMessaging) |
124 | self.fakefsm = None |
125 | self.fakevm = FakeVolumeManager() |
126 | self.status_frontend = aggregator.StatusFrontend() |
127 | self.listener = status_listener.StatusListener(self.fakefsm, |
128 | self.fakevm, |
129 | self.status_frontend) |
130 | + |
131 | def test_file_published(self): |
132 | """A file published event is processed.""" |
133 | share_id = "fake share id" |
134 | node_id = "fake node id" |
135 | is_public = True |
136 | public_url = "http://fake_public/url" |
137 | - |
138 | self.listener.handle_AQ_CHANGE_PUBLIC_ACCESS_OK(share_id, node_id, |
139 | is_public, public_url) |
140 | - event = self.status_frontend.aggregator.interesting_events[0] |
141 | - self.assertIsInstance(event, aggregator.FilePublishingStatus) |
142 | + self.assertEqual( |
143 | + 1, len(self.status_frontend.notification.notifications_shown)) |
144 | + self.assertEqual( |
145 | + (aggregator.UBUNTUONE_TITLE, |
146 | + 'A file was just made public at http://fake_public/url', None, |
147 | + False), |
148 | + self.status_frontend.notification.notifications_shown[0]) |
149 | |
150 | def test_file_unpublished(self): |
151 | """A file unpublished event is processed.""" |
152 | @@ -581,8 +586,12 @@ |
153 | |
154 | self.listener.handle_AQ_CHANGE_PUBLIC_ACCESS_OK(share_id, node_id, |
155 | is_public, public_url) |
156 | - event = self.status_frontend.aggregator.interesting_events[0] |
157 | - self.assertIsInstance(event, aggregator.FileUnpublishingStatus) |
158 | + self.assertEqual( |
159 | + 1, len(self.status_frontend.notification.notifications_shown)) |
160 | + self.assertEqual( |
161 | + (aggregator.UBUNTUONE_TITLE, 'A file is no longer published', None, |
162 | + False), |
163 | + self.status_frontend.notification.notifications_shown[0]) |
164 | |
165 | def test_download_started(self): |
166 | """A download was added to the queue.""" |
167 | @@ -644,22 +653,77 @@ |
168 | def test_new_share_available(self): |
169 | """A new share is available for subscription.""" |
170 | SHARE_ID = "fake share id" |
171 | - share = Share(volume_id=SHARE_ID) |
172 | + FAKE_SENDER = 'Mom' |
173 | + share = Share(volume_id=SHARE_ID, other_visible_name=FAKE_SENDER) |
174 | self.fakevm.volumes[SHARE_ID] = share |
175 | self.listener.handle_VM_SHARE_CREATED(SHARE_ID) |
176 | - event = self.status_frontend.aggregator.interesting_events[0] |
177 | - self.assertIsInstance(event, aggregator.ShareAvailableStatus) |
178 | + self.assertEqual( |
179 | + 1, len(self.status_frontend.notification.notifications_shown)) |
180 | + self.assertEqual( |
181 | + (aggregator.UBUNTUONE_TITLE, |
182 | + 'New cloud folder available: <%s> shared by <%s>' % ( |
183 | + 'None', FAKE_SENDER), None, False), |
184 | + self.status_frontend.notification.notifications_shown[0]) |
185 | + msg = self.status_frontend.messaging.messages_shown[FAKE_SENDER] |
186 | + # msg did not receive a time argument |
187 | + self.assertEqual(None, msg[1]) |
188 | + # msg did not receive a count argument |
189 | + self.assertEqual(None, msg[2]) |
190 | |
191 | def test_new_udf_available(self): |
192 | """A new udf is available for subscription.""" |
193 | udf = UDF() |
194 | self.listener.handle_VM_UDF_CREATED(udf) |
195 | - event = self.status_frontend.aggregator.interesting_events[0] |
196 | - self.assertIsInstance(event, aggregator.UDFAvailableStatus) |
197 | + self.assertEqual( |
198 | + 1, len(self.status_frontend.notification.notifications_shown)) |
199 | + self.assertEqual( |
200 | + (aggregator.UBUNTUONE_TITLE, 'New cloud folder available: None', |
201 | + None, False), |
202 | + self.status_frontend.notification.notifications_shown[0]) |
203 | + self.assertEqual( |
204 | + 1, len(self.status_frontend.messaging.messages_shown)) |
205 | + self.assertEqual( |
206 | + 0, len(self.status_frontend.messaging.messages_updated)) |
207 | + msg = self.status_frontend.messaging.messages_shown[ |
208 | + aggregator.NEW_UDFS_SENDER] |
209 | + # msg did not receive a time argument |
210 | + self.assertEqual(None, msg[1]) |
211 | + # msg did receive a count argument |
212 | + self.assertEqual(1, msg[2]) |
213 | + |
214 | + def test_two_new_udfs_available(self): |
215 | + """A new udf is available for subscription.""" |
216 | + udf1 = UDF() |
217 | + self.listener.handle_VM_UDF_CREATED(udf1) |
218 | + udf2 = UDF() |
219 | + self.listener.handle_VM_UDF_CREATED(udf2) |
220 | + self.assertEqual( |
221 | + 2, len(self.status_frontend.notification.notifications_shown)) |
222 | + self.assertEqual( |
223 | + (aggregator.UBUNTUONE_TITLE, 'New cloud folder available: None', |
224 | + None, False), |
225 | + self.status_frontend.notification.notifications_shown[0]) |
226 | + self.assertEqual( |
227 | + (aggregator.UBUNTUONE_TITLE, 'New cloud folder available: None', |
228 | + None, False), |
229 | + self.status_frontend.notification.notifications_shown[1]) |
230 | + self.assertEqual( |
231 | + 1, len(self.status_frontend.messaging.messages_shown)) |
232 | + self.assertEqual( |
233 | + 1, len(self.status_frontend.messaging.messages_updated)) |
234 | + msg = self.status_frontend.messaging.messages_shown[ |
235 | + aggregator.NEW_UDFS_SENDER] |
236 | + # msg did not receive a time argument |
237 | + self.assertEqual(None, msg[1]) |
238 | + # msg did receive a count argument |
239 | + self.assertEqual(1, msg[2]) |
240 | + self.assertEqual( |
241 | + (aggregator.NEW_UDFS_SENDER, 1), |
242 | + self.status_frontend.messaging.messages_updated[ |
243 | + aggregator.NEW_UDFS_SENDER]) |
244 | |
245 | |
246 | class StatusEventTestCase(TestCase): |
247 | - |
248 | """Test the status event class and children.""" |
249 | |
250 | CLASS = aggregator.StatusEvent |
251 | @@ -832,7 +896,6 @@ |
252 | self.assertEqual(self.aggregator.done_counter, 0) |
253 | self.assertEqual(len(self.aggregator.files_uploading), 0) |
254 | self.assertEqual(len(self.aggregator.files_downloading), 0) |
255 | - self.assertEqual(len(self.aggregator.interesting_events), 0) |
256 | |
257 | def assertMiscCommandQueued(self, fc): |
258 | """Assert that some command was queued.""" |
259 | |
260 | === modified file 'ubuntuone/platform/linux/messaging.py' |
261 | --- ubuntuone/platform/linux/messaging.py 2011-02-02 16:28:49 +0000 |
262 | +++ ubuntuone/platform/linux/messaging.py 2011-02-09 13:12:13 +0000 |
263 | @@ -21,6 +21,7 @@ |
264 | # of them are available, we should fall back to silently discarding |
265 | # messages. |
266 | |
267 | +import subprocess |
268 | from time import time |
269 | |
270 | try: |
271 | @@ -35,6 +36,22 @@ |
272 | APPLICATION_NAME = 'Ubuntu One Client' |
273 | |
274 | |
275 | +def hide_message(indicator): |
276 | + """Remove the message once it has been dealt with.""" |
277 | + if USE_INDICATE: |
278 | + indicator.set_property("draw-attention", "false") |
279 | + indicator.hide() |
280 | + |
281 | + |
282 | +# pylint: disable=W0613 |
283 | +def open_volumes(the_indicator, message_time=None): |
284 | + """Open the control panel to the shares tab.""" |
285 | + subprocess.Popen( |
286 | + ['ubuntuone-control-panel-gtk', '--switch-to', 'volumes']) |
287 | + hide_message(the_indicator) |
288 | +# pylint: enable=W0613 |
289 | + |
290 | + |
291 | class Messaging(AbstractMessaging): |
292 | """Notification of the end user.""" |
293 | |
294 | @@ -48,14 +65,18 @@ |
295 | self.server.set_desktop_file( |
296 | "/usr/share/applications/ubuntuone-control-panel-gtk.desktop") |
297 | |
298 | - def show_message(self, sender, callback, message_time=None, |
299 | + # pylint: disable=R0913 |
300 | + def show_message(self, sender, callback=None, message_time=None, |
301 | message_count=None, icon=None): |
302 | """Show a message in the messaging menu.""" |
303 | if USE_INDICATE: |
304 | - indicator = self.indicators[sender] = indicate.Indicator() |
305 | + indicator = indicate.Indicator() |
306 | indicator.set_property("subtype", "u1") |
307 | indicator.set_property("name", sender) |
308 | indicator.set_property("sender", sender) |
309 | + |
310 | + if callback is None: |
311 | + callback = open_volumes |
312 | indicator.connect("user-display", callback) |
313 | |
314 | if icon is not None: |
315 | @@ -70,14 +91,10 @@ |
316 | self.server.show() |
317 | indicator.show() |
318 | return indicator |
319 | + # pylint: enable=R0913 |
320 | |
321 | - def update_count(self, sender, new_count): |
322 | + def update_count(self, indicator, add_count): |
323 | """Update the count for an existing indicator.""" |
324 | - self.indicators[sender].set_property("count", str(new_count)) |
325 | - |
326 | - |
327 | -def hide_message(indicator): |
328 | - """Remove the message once it has been dealt with.""" |
329 | - if USE_INDICATE: |
330 | - indicator.set_property("draw-attention", "false") |
331 | - indicator.hide() |
332 | + if USE_INDICATE: |
333 | + new_count = int(indicator.get_property('count')) + add_count |
334 | + indicator.set_property('count', str(new_count)) |
335 | |
336 | === modified file 'ubuntuone/platform/windows/messaging.py' |
337 | --- ubuntuone/platform/windows/messaging.py 2011-02-01 13:51:48 +0000 |
338 | +++ ubuntuone/platform/windows/messaging.py 2011-02-09 13:12:13 +0000 |
339 | @@ -29,16 +29,23 @@ |
340 | class Messaging(AbstractMessaging): |
341 | """Notification of the end user.""" |
342 | |
343 | - def show_message(self, sender, callback, message_time=None, |
344 | + # pylint: disable=R0913 |
345 | + def show_message(self, sender, callback=None, message_time=None, |
346 | message_count=None, icon=None): |
347 | """Show a message in the messaging menu.""" |
348 | - pass |
349 | + # TODO: make this work |
350 | + # pylint: enable=R0913 |
351 | |
352 | - def update_count(self, sender, new_count): |
353 | + def update_count(self, sender, add_count): |
354 | """Update the count for an existing indicator.""" |
355 | - pass |
356 | - |
357 | - |
358 | -def hide_message(indicator): |
359 | + # TODO: make this work |
360 | + |
361 | + |
362 | +def hide_message(indicator): # pylint: disable=W0613 |
363 | """Remove the message once it has been dealt with.""" |
364 | - pass |
365 | + # TODO: make this work |
366 | + |
367 | + |
368 | +def open_volumes(the_indicator, message_time=None): # pylint: disable=W0613 |
369 | + """Open the control panel to the shares tab.""" |
370 | + # TODO: make this work |
371 | |
372 | === modified file 'ubuntuone/status/aggregator.py' |
373 | --- ubuntuone/status/aggregator.py 2011-02-04 00:56:30 +0000 |
374 | +++ ubuntuone/status/aggregator.py 2011-02-09 13:12:13 +0000 |
375 | @@ -26,7 +26,7 @@ |
376 | |
377 | from ubuntuone.logger import basic_formatter, logging |
378 | from ubuntuone.platform.notification import Notification |
379 | -from ubuntuone.platform.messaging import Messaging |
380 | +from ubuntuone.platform.messaging import Messaging, open_volumes |
381 | |
382 | LOG_LEVEL = logging.DEBUG |
383 | logger = logging.getLogger('ubuntuone.status') |
384 | @@ -39,6 +39,7 @@ |
385 | logger.addHandler(debug_handler) |
386 | |
387 | UBUNTUONE_TITLE = "Ubuntu One" |
388 | +NEW_UDFS_SENDER = "New Cloud Folder(s) Available" |
389 | FINAL_COMPLETED = "File synchronization completed." |
390 | FINAL_UPLOADED = "%d files were uploaded to your cloud." |
391 | FINAL_DOWNLOADED = "%d files were downloaded to your computer." |
392 | @@ -181,6 +182,7 @@ |
393 | def cleanup(self): |
394 | """Cleanup this instance.""" |
395 | |
396 | + |
397 | class FileDiscoveryIdleState(FileDiscoveryBaseState): |
398 | """Waiting for first file to appear.""" |
399 | |
400 | @@ -406,7 +408,6 @@ |
401 | """Initialize this instance.""" |
402 | self.clock = clock |
403 | self.reset() |
404 | - self.messaging = Messaging() |
405 | |
406 | def reset(self): |
407 | """Reset all counters and notifications.""" |
408 | @@ -418,7 +419,6 @@ |
409 | self.upload_done = 0 |
410 | self.files_uploading = [] |
411 | self.files_downloading = [] |
412 | - self.interesting_events = [] |
413 | |
414 | if self.file_discovery_bubble: |
415 | self.file_discovery_bubble.cleanup() |
416 | @@ -433,10 +433,6 @@ |
417 | self.final_status_bubble.cleanup() |
418 | self.final_status_bubble = FinalStatusBubble(self) |
419 | |
420 | - def interesting_event(self, event): |
421 | - """A new interesting event was found.""" |
422 | - self.interesting_events.append(event) |
423 | - |
424 | def get_discovery_message(self): |
425 | """Get the text for the discovery bubble.""" |
426 | lines = [] |
427 | @@ -546,20 +542,26 @@ |
428 | self.upload_done += 1 |
429 | self.misc_command_unqueued(command) |
430 | |
431 | + |
432 | class StatusFrontend(object): |
433 | """Frontend for the status aggregator, used by the StatusListener.""" |
434 | |
435 | def __init__(self, clock=reactor): |
436 | """Initialize this instance.""" |
437 | self.aggregator = StatusAggregator(clock=clock) |
438 | + self.notification = Notification() |
439 | + self.messaging = Messaging() |
440 | + self.udf_message = None |
441 | |
442 | def file_published(self, public_url): |
443 | """A file was published.""" |
444 | - self.aggregator.interesting_event(FilePublishingStatus(public_url)) |
445 | + self.notification.send_notification( |
446 | + UBUNTUONE_TITLE, FilePublishingStatus(public_url).one()) |
447 | |
448 | - def file_unpublished(self, public_url): |
449 | + def file_unpublished(self, public_url): # pylint: disable=W0613 |
450 | """A file was unpublished.""" |
451 | - self.aggregator.interesting_event(FileUnpublishingStatus(public_url)) |
452 | + self.notification.send_notification( |
453 | + UBUNTUONE_TITLE, FileUnpublishingStatus().one()) |
454 | |
455 | def download_started(self, command): |
456 | """A file was queued for download.""" |
457 | @@ -591,8 +593,22 @@ |
458 | |
459 | def new_share_available(self, share): |
460 | """A new share is available for subscription.""" |
461 | - self.aggregator.interesting_event(ShareAvailableStatus(share)) |
462 | + self.messaging.show_message(share.other_visible_name) |
463 | + self.notification.send_notification( |
464 | + UBUNTUONE_TITLE, ShareAvailableStatus(share).one()) |
465 | |
466 | def new_udf_available(self, udf): |
467 | """A new udf is available for subscription.""" |
468 | - self.aggregator.interesting_event(UDFAvailableStatus(udf)) |
469 | + if self.udf_message is not None: |
470 | + self.messaging.update_count(self.udf_message, 1) |
471 | + return |
472 | + self.udf_message = self.messaging.show_message( |
473 | + NEW_UDFS_SENDER, callback=self._reset_udf_message_callback, |
474 | + message_count=1) |
475 | + self.notification.send_notification( |
476 | + UBUNTUONE_TITLE, UDFAvailableStatus(udf).one()) |
477 | + |
478 | + def _reset_udf_message_callback(self, indicator, message_time=None): |
479 | + """A callback wrapper that resets the udf_message to None.""" |
480 | + self.udf_message = None |
481 | + open_volumes(indicator, message_time=message_time) |
482 | |
483 | === modified file 'ubuntuone/status/messaging.py' |
484 | --- ubuntuone/status/messaging.py 2011-02-01 19:07:16 +0000 |
485 | +++ ubuntuone/status/messaging.py 2011-02-09 13:12:13 +0000 |
486 | @@ -27,11 +27,13 @@ |
487 | |
488 | __metaclass__ = ABCMeta |
489 | |
490 | + # pylint: disable=R0913 |
491 | @abstractmethod |
492 | - def show_message(self, sender, callback, message_time=None, |
493 | + def show_message(self, sender, callback=None, message_time=None, |
494 | message_count=None, icon=None): |
495 | """Show a message in the messaging menu.""" |
496 | + # pylint: enable=R0913 |
497 | |
498 | @abstractmethod |
499 | - def update_count(self, sender, new_count): |
500 | + def update_count(self, sender, add_count): |
501 | """Update the count for an existing indicator.""" |
Great branch!
Two small issues: show_message, just like new_udf_available _callback should be named more descriptively.
* I think that new_share_available in StatusFrontend should also pass _callback to messaging.
* I think that StatusFrontend.
Otherwise great work :-)