Merge lp:~diegosarmentero/ubuntuone-control-panel/shares into lp:ubuntuone-control-panel

Proposed by Diego Sarmentero on 2012-08-20
Status: Merged
Approved by: Roberto Alsina on 2012-08-20
Approved revision: 349
Merged at revision: 346
Proposed branch: lp:~diegosarmentero/ubuntuone-control-panel/shares
Merge into: lp:ubuntuone-control-panel
Prerequisite: lp:~diegosarmentero/ubuntuone-control-panel/transfers
Diff against target: 317 lines (+175/-40)
5 files modified
ubuntuone/controlpanel/backend.py (+7/-0)
ubuntuone/controlpanel/gui/__init__.py (+2/-0)
ubuntuone/controlpanel/gui/qt/systray.py (+101/-39)
ubuntuone/controlpanel/gui/qt/tests/__init__.py (+4/-0)
ubuntuone/controlpanel/gui/qt/tests/test_systray.py (+61/-1)
To merge this branch: bzr merge lp:~diegosarmentero/ubuntuone-control-panel/shares
Reviewer Review Type Date Requested Status
Roberto Alsina (community) Approve on 2012-08-20
Brian Curtin (community) 2012-08-20 Approve on 2012-08-20
Review via email: mp+120394@code.launchpad.net

Commit Message

- Show the not accepted shares (LP: #1034542).

To post a comment you must log in.
review: Approve
349. By Diego Sarmentero on 2012-08-20

fixed lint issues

Roberto Alsina (ralsina) wrote :

Looks god to me, tests pass, did not do a strict code review though

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ubuntuone/controlpanel/backend.py'
2--- ubuntuone/controlpanel/backend.py 2012-08-08 18:36:45 +0000
3+++ ubuntuone/controlpanel/backend.py 2012-08-20 18:55:44 +0000
4@@ -828,6 +828,13 @@
5 returnValue(result)
6
7 @log_call(logger.info)
8+ @inlineCallbacks
9+ def get_shares(self):
10+ """Obtain the data to create the sync menu."""
11+ result = yield self.sd_client.get_shares()
12+ returnValue(result)
13+
14+ @log_call(logger.info)
15 def shutdown(self):
16 """Stop this service."""
17 # do any other needed cleanup
18
19=== modified file 'ubuntuone/controlpanel/gui/__init__.py'
20--- ubuntuone/controlpanel/gui/__init__.py 2012-08-16 13:21:56 +0000
21+++ ubuntuone/controlpanel/gui/__init__.py 2012-08-20 18:55:44 +0000
22@@ -69,6 +69,7 @@
23
24 FILE_URI_PREFIX = u'file://'
25
26+ACCEPT_SHARES = 'https://one.ubuntu.com/files/shareoffer/%s/'
27 CONTACTS_LINK = UBUNTUONE_LINK
28 DASHBOARD = UBUNTUONE_LINK + u'dashboard/'
29 EDIT_ACCOUNT_LINK = UBUNTUONE_LINK + u'account/'
30@@ -220,6 +221,7 @@
31 NAME_NOT_SET = _('[unknown user name]')
32 NETWORK_OFFLINE = _('An internet connection is required to join or sign '
33 'in to %(app_name)s.')
34+NEW_SHARE_BY = _('New Share by %s')
35 NO_DEVICES = _('No devices to show.')
36 NO_FOLDERS = _('No folders to show.')
37 NO_PAIRING_RECORD = _('There is no Ubuntu One pairing record.')
38
39=== modified file 'ubuntuone/controlpanel/gui/qt/systray.py'
40--- ubuntuone/controlpanel/gui/qt/systray.py 2012-08-20 12:52:34 +0000
41+++ ubuntuone/controlpanel/gui/qt/systray.py 2012-08-20 18:55:44 +0000
42@@ -26,6 +26,7 @@
43 from ubuntuone.controlpanel import backend, cache
44 from ubuntuone.controlpanel.logger import setup_logging
45 from ubuntuone.controlpanel.gui import (
46+ ACCEPT_SHARES,
47 DASHBOARD,
48 GET_HELP_ONLINE,
49 GET_MORE_STORAGE,
50@@ -35,6 +36,7 @@
51 IN_PROGRESS,
52 IN_PROGRESS_FILE,
53 LOADING,
54+ NEW_SHARE_BY,
55 OPEN_UBUNTU_ONE,
56 OPEN_UBUNTU_ONE_FOLDER,
57 PLEASE_WAIT,
58@@ -80,9 +82,26 @@
59 text = IN_PROGRESS_FILE % (self._filename, progress)
60 self.setText(text)
61 self.label.setText(text)
62+ self.setText(text)
63 self.progress.setValue(progress)
64
65
66+class SharesAction(QtGui.QAction):
67+
68+ """New Shares action."""
69+
70+ def __init__(self, text, volume_id, parent=None):
71+ super(SharesAction, self).__init__(text, parent)
72+ self._volume_id = volume_id
73+
74+ self.triggered.connect(self.accept_share)
75+
76+ def accept_share(self):
77+ """Open the accept shares page."""
78+ url = ACCEPT_SHARES % self._volume_id
79+ QtGui.QDesktopServices.openUrl(QtCore.QUrl(url))
80+
81+
82 class TrayIcon(QtGui.QSystemTrayIcon, cache.Cache):
83
84 """System notification icon."""
85@@ -96,46 +115,89 @@
86 self.recent_transfers = {}
87 self.uploading = {}
88 self._backend_method = None
89-
90- # Items
91+ self._previous_shares = None
92+ self.close_callback = close_callback
93 self.context_menu = QtGui.QMenu()
94-
95- self.status = self.context_menu.addAction(LOADING)
96- self.status.setEnabled(False)
97- self.status_action = self.context_menu.addAction(PLEASE_WAIT)
98- self.refresh_status()
99- self.context_menu.addSeparator()
100-
101- self.open_u1 = self.context_menu.addAction(OPEN_UBUNTU_ONE)
102- # TODO: Share a file action when the Shares tab is ready in U1-CP
103- self.open_u1_folder = self.context_menu.addAction(
104- OPEN_UBUNTU_ONE_FOLDER)
105- self.go_to_web = self.context_menu.addAction(GO_TO_WEB)
106- self.context_menu.addSeparator()
107-
108- # TODO: Shares
109-
110- # Transfers
111- self.transfers = TransfersMenu(self)
112- self.context_menu.addMenu(self.transfers)
113-
114- self.get_more_storage = self.context_menu.addAction(GET_MORE_STORAGE)
115- self.get_help_online = self.context_menu.addAction(GET_HELP_ONLINE)
116- self.quit = self.context_menu.addAction("Quit")
117-
118- self.setContextMenu(self.context_menu)
119-
120- # Connect Signals
121- self.status_action.triggered.connect(self.change_status)
122- self.open_u1.triggered.connect(self.restore_window)
123- self.open_u1_folder.triggered.connect(self.open_u1_folder_action)
124- self.get_more_storage.triggered.connect(self.get_more_storage_action)
125- self.go_to_web.triggered.connect(self.go_to_web_action)
126- self.get_help_online.triggered.connect(self.get_help_action)
127- self.quit.triggered.connect(self.stop)
128-
129- self.close_callback = close_callback
130- self._get_volumes_info()
131+ self.status = None
132+ self.quit = None
133+ self.get_help_online = None
134+ self.open_u1 = None
135+ self.status_action = None
136+ self.go_to_web = None
137+ self.get_more_storage = None
138+ self.transfers = None
139+ self.open_u1_folder = None
140+
141+ self.load_menu()
142+ # Refresh the Shares every five minutes if needed.
143+ self._timer_id = self.startTimer(300000)
144+
145+ # pylint: disable=C0103
146+
147+ def timerEvent(self, event):
148+ """Update the menu on each iteration."""
149+ self.load_menu()
150+
151+ # pylint: enable=C0103
152+
153+ @inlineCallbacks
154+ def load_menu(self):
155+ """Load the content of the menu."""
156+ shares_info = yield self.backend.get_shares()
157+ shares_info = [share for share in shares_info if not share['accepted']]
158+ if shares_info != self._previous_shares:
159+ # Items
160+ self.context_menu.clear()
161+
162+ self.status = self.context_menu.addAction(LOADING)
163+ self.status.setEnabled(False)
164+ self.status_action = self.context_menu.addAction(PLEASE_WAIT)
165+ self.refresh_status()
166+ self.context_menu.addSeparator()
167+
168+ self.open_u1 = self.context_menu.addAction(OPEN_UBUNTU_ONE)
169+ # TODO: Share a file action when the Shares tab is ready in U1-CP
170+ self.open_u1_folder = self.context_menu.addAction(
171+ OPEN_UBUNTU_ONE_FOLDER)
172+ self.go_to_web = self.context_menu.addAction(GO_TO_WEB)
173+ self.context_menu.addSeparator()
174+
175+ # Shares
176+ self._previous_shares = shares_info
177+ max_shares = 0
178+ for share in self._previous_shares:
179+ if max_shares == 3:
180+ break
181+ max_shares += 1
182+ text = NEW_SHARE_BY % share['other_visible_name']
183+ share_action = SharesAction(text, share['volume_id'],
184+ self.context_menu)
185+ self.context_menu.addAction(share_action)
186+ if self._previous_shares:
187+ self.context_menu.addSeparator()
188+
189+ # Transfers
190+ self.transfers = TransfersMenu(self)
191+ self.context_menu.addMenu(self.transfers)
192+
193+ self.get_more_storage = self.context_menu.addAction(
194+ GET_MORE_STORAGE)
195+ self.get_help_online = self.context_menu.addAction(GET_HELP_ONLINE)
196+ self.quit = self.context_menu.addAction("Quit")
197+
198+ self.setContextMenu(self.context_menu)
199+
200+ # Connect Signals
201+ self.status_action.triggered.connect(self.change_status)
202+ self.open_u1.triggered.connect(self.restore_window)
203+ self.open_u1_folder.triggered.connect(self.open_u1_folder_action)
204+ self.get_more_storage.triggered.connect(
205+ self.get_more_storage_action)
206+ self.go_to_web.triggered.connect(self.go_to_web_action)
207+ self.get_help_online.triggered.connect(self.get_help_action)
208+ self.quit.triggered.connect(self.stop)
209+
210+ self._get_volumes_info()
211
212 @inlineCallbacks
213 def refresh_status(self):
214
215=== modified file 'ubuntuone/controlpanel/gui/qt/tests/__init__.py'
216--- ubuntuone/controlpanel/gui/qt/tests/__init__.py 2012-08-16 13:35:00 +0000
217+++ ubuntuone/controlpanel/gui/qt/tests/__init__.py 2012-08-20 18:55:44 +0000
218@@ -175,6 +175,10 @@
219 data[UPLOADING] = []
220 return data
221
222+ def get_shares(self):
223+ """Fake get_shares."""
224+ return []
225+
226
227 class CrashyBackendException(Exception):
228 """A faked backend crash."""
229
230=== modified file 'ubuntuone/controlpanel/gui/qt/tests/test_systray.py'
231--- ubuntuone/controlpanel/gui/qt/tests/test_systray.py 2012-08-20 12:52:34 +0000
232+++ ubuntuone/controlpanel/gui/qt/tests/test_systray.py 2012-08-20 18:55:44 +0000
233@@ -80,6 +80,9 @@
234
235 @inlineCallbacks
236 def setUp(self):
237+ # We need to patch the startTimer first, to avoid the timer
238+ # to get started on initialization.
239+ self.patch(systray.TrayIcon, "startTimer", lambda s, x: None)
240 self.patch(systray.TransfersMenu, "startTimer", lambda s, x: None)
241 yield super(SystrayTestCase, self).setUp()
242 self.patch(QtGui, "QDesktopServices", FakeDesktopService)
243@@ -339,12 +342,15 @@
244
245 class TransfersMenuTestCase(BaseTestCase):
246
247- """Test the notification area icon."""
248+ """Test the info to be display in the transfers menu."""
249
250 class_ui = systray.TrayIcon
251
252 @inlineCallbacks
253 def setUp(self):
254+ # We need to patch the startTimer first, to avoid the timer
255+ # to get started on initialization.
256+ self.patch(systray.TrayIcon, "startTimer", lambda s, x: None)
257 self.patch(systray.TransfersMenu, "startTimer", lambda s, x: None)
258 yield super(TransfersMenuTestCase, self).setUp()
259 self.patch(QtGui, "QDesktopServices", FakeDesktopService)
260@@ -537,3 +543,57 @@
261 current_actions = self.ui.transfers.actions()
262
263 self.assertNotEqual(previous_actions, current_actions)
264+
265+
266+class SharesTestCase(BaseTestCase):
267+
268+ """Test the info to be displayed in the shares section."""
269+
270+ class_ui = systray.TrayIcon
271+
272+ @inlineCallbacks
273+ def setUp(self):
274+ # We need to patch the startTimer first, to avoid the timer
275+ # to get started on initialization.
276+ self.patch(systray.TrayIcon, "startTimer", lambda s, x: None)
277+ self.patch(systray.TransfersMenu, "startTimer", lambda s, x: None)
278+ yield super(SharesTestCase, self).setUp()
279+ self.patch(QtGui, "QDesktopServices", FakeDesktopService)
280+ self.patch(self.ui.backend, "get_shares", self.fake_get_backend)
281+ self._shares_info = []
282+
283+ def fake_get_backend(self):
284+ """Fake get_backend."""
285+ return self._shares_info
286+
287+ def test_shares_refresh_not_reload(self):
288+ """Check that we get the new info of shares but not reload the menu."""
289+ actions = self.ui.context_menu.actions()
290+ self.ui.load_menu()
291+ post_actions = self.ui.context_menu.actions()
292+ self.assertEqual(actions, post_actions)
293+
294+ def test_shares_refresh_reload(self):
295+ """Check that we get the new info of shares but not reload the menu."""
296+ actions = self.ui.context_menu.actions()
297+ self._shares_info = [
298+ {'accepted': False, 'other_visible_name': 'name',
299+ 'volume_id': 'asd123-asd123-asd123-asd123'}
300+ ]
301+ self.ui.load_menu()
302+ post_actions = self.ui.context_menu.actions()
303+ self.assertNotEqual(actions, post_actions)
304+
305+ def test_share_triggered(self):
306+ """Check that we get the new info of shares but not reload the menu."""
307+ volume_id = 'asd123-asd123-asd123-asd123'
308+ self._shares_info = [
309+ {'accepted': False, 'other_visible_name': 'name',
310+ 'volume_id': volume_id}
311+ ]
312+ self.ui.load_menu()
313+ actions = self.ui.context_menu.actions()
314+ share_action = actions[7]
315+ share_action.trigger()
316+ expected = QtCore.QUrl(systray.ACCEPT_SHARES % volume_id)
317+ self.assertEqual(FakeDesktopService.data['url'], expected)

Subscribers

People subscribed via source and target branches