Merge lp:~3v1n0/ubuntuone-client/sync-menu-use-gappinfo-launch into lp:ubuntuone-client

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: dobey
Approved revision: 1399
Merged at revision: 1393
Proposed branch: lp:~3v1n0/ubuntuone-client/sync-menu-use-gappinfo-launch
Merge into: lp:ubuntuone-client
Diff against target: 352 lines (+205/-48)
2 files modified
tests/platform/sync_menu/test_linux.py (+139/-20)
ubuntuone/platform/sync_menu/linux.py (+66/-28)
To merge this branch: bzr merge lp:~3v1n0/ubuntuone-client/sync-menu-use-gappinfo-launch
Reviewer Review Type Date Requested Status
dobey (community) Approve
Diego Sarmentero (community) Approve
Roberto Alsina (community) Approve
Review via email: mp+158503@code.launchpad.net

Commit message

UbuntuOneSyncMenuLinux: use GAppInfo with proper context to launch URIs

This allows to correctly open the application with proper startup notify.

Description of the change

The linux sync-menu should use GAppInfo with LaunchContext to launch applications and URIs so that the window manager and the applications will be properly focused and launched with startup notification.

To post a comment you must log in.
Revision history for this message
Roberto Alsina (ralsina) :
review: Approve
1393. By Marco Trevisan (Treviño)

UbuntuOneSyncMenuLinux: protect the commandline-app-creation from error too

Revision history for this message
Diego Sarmentero (diegosarmentero) wrote :

Tests are failing, and there isn't new tests for the new code.

review: Needs Fixing
Revision history for this message
dobey (dobey) wrote :

+CLIENT_DESKTOP_ID = 'ubuntuone-control-panel-qt-gnome.desktop'
+INSTALLER_DESKTOP_ID = 'ubuntuone-installer.desktop'

Why are both of these being used? There is no more "installer" exactly, but the filename is unchanged, to avoid breaking the launcher. Also, the "-qt-gnome.desktop" file is only for GNOME, so I think we want to use the "ubuntuone-installer.desktop" everywhere. But I wouldn't call it "INSTALLER_DESKTOP_ID" as the variable, as it's not an installer. Maybe CONTROL_PANEL_DESKTOP_ID or CLIENT_DESKTOP_ID, and use that constant for all the instances.

Revision history for this message
dobey (dobey) :
review: Needs Fixing
1394. By Marco Trevisan (Treviño)

UbuntuOneSyncMenuLinux: don't crash if the display is not set, don't use the Context

1395. By Marco Trevisan (Treviño)

SyncMenuTestCase: add new tests to cover changes and update the old ones

1396. By Marco Trevisan (Treviño)

SyncMenuTestCase: use random values for timestasmp

1397. By Marco Trevisan (Treviño)

UbuntuOneSyncMenuLinux: always use CLIENT_DESKTOP_ID as client

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

> +CLIENT_DESKTOP_ID = 'ubuntuone-control-panel-qt-gnome.desktop'
> +INSTALLER_DESKTOP_ID = 'ubuntuone-installer.desktop'
>
> Why are both of these being used? There is no more "installer" exactly, but
> the filename is unchanged, to avoid breaking the launcher. Also, the "-qt-
> gnome.desktop" file is only for GNOME, so I think we want to use the
> "ubuntuone-installer.desktop" everywhere. But I wouldn't call it
> "INSTALLER_DESKTOP_ID" as the variable, as it's not an installer. Maybe
> CONTROL_PANEL_DESKTOP_ID or CLIENT_DESKTOP_ID, and use that constant for all
> the instances.

Fine, I've moved everything to CLIENT_DESKTOP_ID set to "ubuntuone-installer.desktop" now.

Revision history for this message
dobey (dobey) wrote :

There are some lint issues in the test file.

== Python Lint Notices ==

./tests/platform/sync_menu/test_linux.py:
    276: redefinition of unused 'time' from line 32
    286: redefinition of unused 'time' from line 32
    297: redefinition of unused 'time' from line 32
    306: redefinition of unused 'time' from line 32
    317: redefinition of unused 'time' from line 32
    326: redefinition of unused 'time' from line 32
    335: redefinition of unused 'time' from line 32
    344: redefinition of unused 'time' from line 32
    353: redefinition of unused 'time' from line 32

make: *** [lint] Error 1

Revision history for this message
dobey (dobey) wrote :

Also, is there any reason to use use randint() here instead of time.time()?

Revision history for this message
Diego Sarmentero (diegosarmentero) wrote :

This branch contains some lint issues:

== Python Lint Notices ==

./tests/platform/sync_menu/test_linux.py:
    276: redefinition of unused 'time' from line 32
    286: redefinition of unused 'time' from line 32
    297: redefinition of unused 'time' from line 32
    306: redefinition of unused 'time' from line 32
    317: redefinition of unused 'time' from line 32
    326: redefinition of unused 'time' from line 32
    335: redefinition of unused 'time' from line 32
    344: redefinition of unused 'time' from line 32
    353: redefinition of unused 'time' from line 32

review: Needs Fixing
1398. By Marco Trevisan (Treviño)

SyncMenuTestCase: use time.time() instead of random.randint().

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

> This branch contains some lint issues:

They should be fixed now, thanks for pointing out.

Revision history for this message
Diego Sarmentero (diegosarmentero) wrote :

+1

review: Approve
Revision history for this message
dobey (dobey) wrote :

8 +

E303 too many blank lines (3)

+ def __init__(self, command_line = "", name = "", flags = 0):
+ def __init__(self, desktop_id = ""):
+ def _open_uri(self, uri, timestamp = 0):
+ def _open_control_panel_by_command_line(self, timestamp, args = ''):
+ def open_control_panel(self, menuitem = None, timestamp = 0):
+ def open_ubuntu_one_folder(self, menuitem = None, timestamp = 0):
+ def open_share_file_tab(self, menuitem = None, timestamp = 0):
+ def open_go_to_web(self, menuitem = None, timestamp = 0):
+ def open_web_help(self, menuitem = None, timestamp = 0):
+ def open_get_more_storage(self, menuitem = None, timestamp = 0):

E251 no spaces around keyword / parameter equals

68 + self.context = context
69 +
70 +class FakeDesktopAppInfo(FakeAppInfo):

E302 expected 2 blank lines, found 1

1399. By Marco Trevisan (Treviño)

UbuntuOneSyncMenuLinux: fixing spaces issues

Revision history for this message
dobey (dobey) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'tests/platform/sync_menu/test_linux.py'
--- tests/platform/sync_menu/test_linux.py 2013-04-16 13:14:42 +0000
+++ tests/platform/sync_menu/test_linux.py 2013-04-16 15:23:26 +0000
@@ -70,6 +70,73 @@
70 self.callback = callback70 self.callback = callback
7171
7272
73class FakeAppLaunchContext(object):
74 def set_timestamp(self, timestamp):
75 self.timestamp = timestamp
76
77
78class FakeGdkDisplay(object):
79 """Fake Gdk.Display"""
80 def get_app_launch_context(self):
81 return FakeAppLaunchContext()
82
83
84class FakeNullGdk(object):
85 """Fake Gdk.Display with no default"""
86 @staticmethod
87 def get_default():
88 return None
89
90
91class FakeAppInfo(object):
92 """Fake Gio.AppInfo"""
93 instance = None
94 name = ""
95 desktop_id = ""
96 command_line = ""
97 opened_uri = ""
98 launched = True
99 context = None
100 files = []
101 flags = 0
102
103 def __new__(cls, *args, **kwargs):
104 cls.instance = super(FakeAppInfo, cls).__new__(cls, *args, **kwargs)
105 return cls.instance
106
107 def __init__(self, command_line="", name="", flags=0):
108 self.command_line = command_line
109 self.name = name
110 self.flags = flags
111
112 @classmethod
113 def launch_default_for_uri(cls, uri, context):
114 cls.opened_uri = uri
115 cls.context = context
116
117 @classmethod
118 def create_from_commandline(cls, command_line, name, flags):
119 cls.instance.__init__(command_line, name, flags)
120 return cls.instance
121
122 def launch(self, files, context):
123 self.launched = True
124 self.files = files
125 self.context = context
126
127
128class FakeDesktopAppInfo(FakeAppInfo):
129 """Fake Gio.DestkopAppInfo"""
130 def __init__(self, desktop_id=""):
131 super(FakeDesktopAppInfo, self).__init__()
132 self.desktop_id = desktop_id
133
134 @classmethod
135 def new(cls, desktop_id):
136 cls.instance.__init__(desktop_id)
137 return cls.instance
138
139
73class FakeSyncdaemonService(object):140class FakeSyncdaemonService(object):
74 """Fake SyncdaemonService."""141 """Fake SyncdaemonService."""
75142
@@ -142,6 +209,7 @@
142 def setUp(self):209 def setUp(self):
143 yield super(SyncMenuTestCase, self).setUp()210 yield super(SyncMenuTestCase, self).setUp()
144 self.patch(linux.SyncMenu, "App", FakeSyncMenuApp)211 self.patch(linux.SyncMenu, "App", FakeSyncMenuApp)
212 self.patch(linux.Gdk.Display, "get_default", FakeGdkDisplay)
145 FakeSyncMenuApp.clean()213 FakeSyncMenuApp.clean()
146 self.syncdaemon_service = FakeSyncdaemonService()214 self.syncdaemon_service = FakeSyncdaemonService()
147 self.status_frontend = FakeStatusFrontend()215 self.status_frontend = FakeStatusFrontend()
@@ -187,54 +255,105 @@
187 self.assertIsInstance(self.sync_menu.transfers.separator,255 self.assertIsInstance(self.sync_menu.transfers.separator,
188 linux.Dbusmenu.Menuitem)256 linux.Dbusmenu.Menuitem)
189257
258 def test_get_launch_context_with_display(self):
259 """Check that the proper context is returned."""
260 timestamp = time.time()
261 context = self.sync_menu._get_launch_context(timestamp)
262 self.assertEqual(timestamp, context.timestamp)
263
264 def test_get_launch_context_with_no_display(self):
265 """Check that the proper context is returned."""
266 self.patch(linux.Gdk, "Display", FakeNullGdk)
267 context = self.sync_menu._get_launch_context(time.time())
268 self.assertEqual(context, None)
269
270 def test_open_control_panel_by_command_line(self):
271 """Check that the proper action is executed."""
272 appinfo = FakeAppInfo()
273 self.patch(linux.Gio, "AppInfo", appinfo)
274 timestamp = time.time()
275 self.sync_menu._open_control_panel_by_command_line(timestamp)
276
277 self.assertEqual(appinfo.command_line, linux.CLIENT_COMMAND_LINE)
278 self.assertEqual(appinfo.context.timestamp, timestamp)
279
280 def test_open_control_panel_by_command_line_with_arg(self):
281 """Check that the proper action is executed."""
282 appinfo = FakeAppInfo()
283 self.patch(linux.Gio, "AppInfo", appinfo)
284 timestamp = time.time()
285 arg = "--test-arg"
286 self.sync_menu._open_control_panel_by_command_line(timestamp, arg)
287
288 self.assertEqual(appinfo.command_line, "%s %s" % (linux.CLIENT_COMMAND_LINE, arg))
289 self.assertEqual(appinfo.context.timestamp, timestamp)
290
291 def test_open_uri(self):
292 """Check that the proper action is executed."""
293 appinfo = FakeAppInfo()
294 self.patch(linux.Gio, "AppInfo", appinfo)
295 timestamp = time.time()
296
297 self.sync_menu._open_uri(linux.UBUNTUONE_LINK, timestamp)
298 self.assertEqual(appinfo.opened_uri, linux.UBUNTUONE_LINK)
299 self.assertEqual(appinfo.context.timestamp, timestamp)
300
190 def test_open_u1(self):301 def test_open_u1(self):
191 """Check that the proper action is executed."""302 """Check that the proper action is executed."""
192 data = []303 appinfo = FakeDesktopAppInfo()
304 timestamp = time.time()
305 self.patch(linux.Gio, "DesktopAppInfo", appinfo)
193306
194 self.patch(linux.glib, "spawn_command_line_async", data.append)307 self.sync_menu.open_control_panel(timestamp=timestamp)
195 self.sync_menu.open_control_panel()308 self.assertEqual(appinfo.desktop_id, linux.CLIENT_DESKTOP_ID)
196 self.assertEqual(data, ['ubuntuone-control-panel-qt'])309 self.assertTrue(appinfo.launched)
310 self.assertEqual(appinfo.files, [])
311 self.assertEqual(appinfo.context.timestamp, timestamp)
197312
198 def test_open_share_tab(self):313 def test_open_share_tab(self):
199 """Check that the proper action is executed."""314 """Check that the proper action is executed."""
315 timestamp = time.time()
200 data = []316 data = []
201317
202 self.patch(linux.glib, "spawn_command_line_async", data.append)318 self.patch(self.sync_menu, "_open_control_panel_by_command_line", lambda t, a: data.append((t, a)))
203 self.sync_menu.open_share_file_tab()319 self.sync_menu.open_share_file_tab(timestamp=timestamp)
204 self.assertEqual(data, [320 self.assertEqual(data, [(timestamp, "--switch-to share_links")])
205 'ubuntuone-control-panel-qt --switch-to share_links'])
206321
207 def test_go_to_web(self):322 def test_go_to_web(self):
208 """Check that the proper action is executed."""323 """Check that the proper action is executed."""
324 timestamp = time.time()
209 data = []325 data = []
210326
211 self.patch(linux.webbrowser, "open", data.append)327 self.patch(self.sync_menu, "_open_uri", lambda u, t: data.append((t, u)))
212 self.sync_menu.open_go_to_web()328 self.sync_menu.open_go_to_web(timestamp=timestamp)
213 self.assertEqual(data, [linux.DASHBOARD])329 self.assertEqual(data, [(timestamp, linux.DASHBOARD)])
214330
215 def test_open_ubuntu_one_folder(self):331 def test_open_ubuntu_one_folder(self):
216 """Check that the proper action is executed."""332 """Check that the proper action is executed."""
333 timestamp = time.time()
217 data = []334 data = []
218335
219 self.patch(linux.webbrowser, "open", data.append)336 self.patch(self.sync_menu, "_open_uri", lambda u, t: data.append((t, u)))
220 self.sync_menu.open_ubuntu_one_folder()337 self.sync_menu.open_ubuntu_one_folder(timestamp=timestamp)
221 self.assertEqual(data, [self.syncdaemon_service.fake_root_path])338 self.assertEqual(data, [(timestamp, "file://" + self.syncdaemon_service.fake_root_path)])
222339
223 def test_get_help(self):340 def test_get_help(self):
224 """Check that the proper action is executed."""341 """Check that the proper action is executed."""
342 timestamp = time.time()
225 data = []343 data = []
226344
227 self.patch(linux.webbrowser, "open", data.append)345 self.patch(self.sync_menu, "_open_uri", lambda u, t: data.append((t, u)))
228 self.sync_menu.open_web_help()346 self.sync_menu.open_web_help(timestamp=timestamp)
229 self.assertEqual(data, [linux.HELP_LINK])347 self.assertEqual(data, [(timestamp, linux.HELP_LINK)])
230348
231 def test_more_storage(self):349 def test_more_storage(self):
232 """Check that the proper action is executed."""350 """Check that the proper action is executed."""
351 timestamp = time.time()
233 data = []352 data = []
234353
235 self.patch(linux.webbrowser, "open", data.append)354 self.patch(self.sync_menu, "_open_uri", lambda u, t: data.append((t, u)))
236 self.sync_menu.open_get_more_storage()355 self.sync_menu.open_get_more_storage(timestamp=timestamp)
237 self.assertEqual(data, [linux.GET_STORAGE_LINK])356 self.assertEqual(data, [(timestamp, linux.GET_STORAGE_LINK)])
238357
239 def test_empty_transfers(self):358 def test_empty_transfers(self):
240 """Check that the Transfers menu is empty."""359 """Check that the Transfers menu is empty."""
241360
=== modified file 'ubuntuone/platform/sync_menu/linux.py'
--- ubuntuone/platform/sync_menu/linux.py 2013-02-20 22:41:12 +0000
+++ ubuntuone/platform/sync_menu/linux.py 2013-04-16 15:23:26 +0000
@@ -31,7 +31,6 @@
31import gettext31import gettext
32import logging32import logging
33import time33import time
34import webbrowser
35from twisted.python.util import OrderedDict34from twisted.python.util import OrderedDict
36from operator import itemgetter35from operator import itemgetter
3736
@@ -39,6 +38,8 @@
39 from gi.repository import GLib as glib38 from gi.repository import GLib as glib
40 from gi.repository import (39 from gi.repository import (
41 Dbusmenu,40 Dbusmenu,
41 Gdk,
42 Gio,
42 SyncMenu,43 SyncMenu,
43 )44 )
44 use_syncmenu = True45 use_syncmenu = True
@@ -69,6 +70,8 @@
69DASHBOARD = UBUNTUONE_LINK + u'dashboard/'70DASHBOARD = UBUNTUONE_LINK + u'dashboard/'
70HELP_LINK = UBUNTUONE_LINK + u'support/'71HELP_LINK = UBUNTUONE_LINK + u'support/'
71GET_STORAGE_LINK = UBUNTUONE_LINK + u'services/add-storage/'72GET_STORAGE_LINK = UBUNTUONE_LINK + u'services/add-storage/'
73CLIENT_COMMAND_LINE = 'ubuntuone-control-panel-qt'
74CLIENT_DESKTOP_ID = 'ubuntuone-installer.desktop'
7275
7376
74class UbuntuOneSyncMenuLinux(object):77class UbuntuOneSyncMenuLinux(object):
@@ -133,7 +136,7 @@
133136
134 self.server = Dbusmenu.Server()137 self.server = Dbusmenu.Server()
135 self.server.set_root(self.root_menu)138 self.server.set_root(self.root_menu)
136 self.app = SyncMenu.App.new("ubuntuone-installer.desktop")139 self.app = SyncMenu.App.new(CLIENT_DESKTOP_ID)
137 self.app.set_menu(self.server)140 self.app.set_menu(self.server)
138 self.app.connect("notify::paused", self.change_sync_status)141 self.app.connect("notify::paused", self.change_sync_status)
139142
@@ -155,36 +158,70 @@
155 self._syncdaemon_service.connect()158 self._syncdaemon_service.connect()
156 self._connected = True159 self._connected = True
157160
158 def open_control_panel(self, *args):161 def _get_launch_context(self, timestamp):
162 """Returns the launch context for the current display"""
163 dpy = Gdk.Display.get_default()
164
165 if dpy:
166 context = dpy.get_app_launch_context()
167 context.set_timestamp(timestamp)
168 return context
169
170 return None
171
172 def _open_uri(self, uri, timestamp=0):
173 """Open an uri Using the default handler and the action timestamp"""
174 try:
175 Gio.AppInfo.launch_default_for_uri(uri, self._get_launch_context(timestamp))
176 except glib.GError as e:
177 logger.warning('Failed to open the uri %s: %s.' % (uri, e))
178
179 def _open_control_panel_by_command_line(self, timestamp, args = ''):
180 """Open the control panel by command line"""
181 flags = Gio.AppInfoCreateFlags.SUPPORTS_STARTUP_NOTIFICATION
182 command_line = CLIENT_COMMAND_LINE
183 if len(args):
184 command_line += ' ' + args
185
186 try:
187 app = Gio.AppInfo.create_from_commandline(command_line, 'Ubuntu One', flags)
188
189 if app:
190 app.launch([], self._get_launch_context(timestamp))
191 except glib.GError as e:
192 logger.warning('Failed to open the control panel: %s.' % e)
193
194 def open_control_panel(self, menuitem=None, timestamp=0):
159 """Open the Ubuntu One Control Panel."""195 """Open the Ubuntu One Control Panel."""
160 try:196 app = Gio.DesktopAppInfo.new(CLIENT_DESKTOP_ID)
161 glib.spawn_command_line_async('ubuntuone-control-panel-qt')197
162 except glib.GError as e:198 if app:
163 logger.warning('Failed to open the control panel: %s.' % e)199 try:
164200 app.launch([], self._get_launch_context(timestamp))
165 def open_ubuntu_one_folder(self, *args):201 except glib.GError as e:
202 logger.warning('Failed to open the control panel: %s.' % e)
203 else:
204 self._open_control_panel_by_command_line(timestamp)
205
206 def open_ubuntu_one_folder(self, menuitem=None, timestamp=0):
166 """Open the Ubuntu One folder."""207 """Open the Ubuntu One folder."""
167 webbrowser.open(self._syncdaemon_service.get_rootdir())208 self._open_uri("file://" + self._syncdaemon_service.get_rootdir(), timestamp)
168209
169 def open_share_file_tab(self, *args):210 def open_share_file_tab(self, menuitem=None, timestamp=0):
170 """Open the Control Panel in the Share Tab."""211 """Open the Control Panel in the Share Tab."""
171 try:212 self._open_control_panel_by_command_line(timestamp, "--switch-to share_links")
172 glib.spawn_command_line_async('ubuntuone-control-panel-qt '213
173 '--switch-to share_links')214 def open_go_to_web(self, menuitem=None, timestamp=0):
174 except glib.GError as e:215 """Open the Ubuntu One Help Page"""
175 logger.warning('Failed to open the control panel: %s.' % e)216 self._open_uri(DASHBOARD, timestamp)
176217
177 def open_go_to_web(self, *args):218 def open_web_help(self, menuitem=None, timestamp=0):
178 """Open the Ubunto One Help Page"""219 """Open the Ubuntu One Help Page"""
179 webbrowser.open(DASHBOARD)220 self._open_uri(HELP_LINK, timestamp)
180221
181 def open_web_help(self, *args):222 def open_get_more_storage(self, menuitem=None, timestamp=0):
182 """Open the Ubunto One Help Page"""223 """Open the Ubuntu One Help Page"""
183 webbrowser.open(HELP_LINK)224 self._open_uri(GET_STORAGE_LINK, timestamp)
184
185 def open_get_more_storage(self, *args):
186 """Open the Ubunto One Help Page"""
187 webbrowser.open(GET_STORAGE_LINK)
188225
189 def _timeout(self, result):226 def _timeout(self, result):
190 """The aggregating timer has expired, so update the UI."""227 """The aggregating timer has expired, so update the UI."""
@@ -284,3 +321,4 @@
284 UbuntuOneSyncMenu = UbuntuOneSyncMenuLinux321 UbuntuOneSyncMenu = UbuntuOneSyncMenuLinux
285else:322else:
286 UbuntuOneSyncMenu = DummySyncMenu323 UbuntuOneSyncMenu = DummySyncMenu
324

Subscribers

People subscribed via source and target branches