Merge lp:~gary-lasker/software-center/launcher-integration-lp761851 into lp:software-center
- launcher-integration-lp761851
- Merge into trunk
Proposed by
Gary Lasker
Status: | Merged |
---|---|
Merged at revision: | 2710 |
Proposed branch: | lp:~gary-lasker/software-center/launcher-integration-lp761851 |
Merge into: | lp:software-center |
Diff against target: |
309 lines (+75/-95) 4 files modified
debian/changelog (+6/-1) softwarecenter/backend/unitylauncher.py (+8/-27) softwarecenter/ui/gtk3/panes/availablepane.py (+20/-36) test/gtk3/test_unity_launcher_integration.py (+41/-31) |
To merge this branch: | bzr merge lp:~gary-lasker/software-center/launcher-integration-lp761851 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
software-store-developers | Pending | ||
Review via email: mp+90354@code.launchpad.net |
Commit message
Description of the change
This branch completes the software-center side implementation of the new Unity launcher functionality as specified at https:/
I've updated the corresponding unit test for the changes.
NOTE: This branch should land and be released as soon as possible after the corresponding Unity release (scheduled for tonight? but no sign of it yet).
Many thanks!
To post a comment you must log in.
- 2601. By Gary Lasker
-
sync up with latest trunk
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'debian/changelog' | |||
2 | --- debian/changelog 2012-01-30 03:59:38 +0000 | |||
3 | +++ debian/changelog 2012-01-30 04:08:26 +0000 | |||
4 | @@ -15,7 +15,12 @@ | |||
5 | 15 | - add a test function in test_utils.py which covers all of | 15 | - add a test function in test_utils.py which covers all of |
6 | 16 | get_nice_date_string | 16 | get_nice_date_string |
7 | 17 | 17 | ||
9 | 18 | -- Gary Lasker <gary.lasker@canonical.com> Sun, 29 Jan 2012 22:57:47 -0500 | 18 | [ Gary Lasker ] |
10 | 19 | * lp:~gary-lasker/software-center/launcher-integration-lp761851: | ||
11 | 20 | - update to the Unity launcher integration implementation to | ||
12 | 21 | support the revamped functionality on the Unity side (LP: #761851) | ||
13 | 22 | |||
14 | 23 | -- Gary Lasker <gary.lasker@canonical.com> Sun, 29 Jan 2012 23:04:52 -0500 | ||
15 | 19 | 24 | ||
16 | 20 | software-center (5.1.7) precise; urgency=low | 25 | software-center (5.1.7) precise; urgency=low |
17 | 21 | 26 | ||
18 | 22 | 27 | ||
19 | === modified file 'softwarecenter/backend/unitylauncher.py' | |||
20 | --- softwarecenter/backend/unitylauncher.py 2011-11-29 21:50:55 +0000 | |||
21 | +++ softwarecenter/backend/unitylauncher.py 2012-01-30 04:08:26 +0000 | |||
22 | @@ -33,7 +33,6 @@ | |||
23 | 33 | icon_y, | 33 | icon_y, |
24 | 34 | icon_size, | 34 | icon_size, |
25 | 35 | app_install_desktop_file_path, | 35 | app_install_desktop_file_path, |
26 | 36 | installed_desktop_file_path, | ||
27 | 37 | trans_id): | 36 | trans_id): |
28 | 38 | self.name = name | 37 | self.name = name |
29 | 39 | self.icon_name = icon_name | 38 | self.icon_name = icon_name |
30 | @@ -42,43 +41,25 @@ | |||
31 | 42 | self.icon_y = icon_y | 41 | self.icon_y = icon_y |
32 | 43 | self.icon_size = icon_size | 42 | self.icon_size = icon_size |
33 | 44 | self.app_install_desktop_file_path = app_install_desktop_file_path | 43 | self.app_install_desktop_file_path = app_install_desktop_file_path |
34 | 45 | self.installed_desktop_file_path = installed_desktop_file_path | ||
35 | 46 | self.trans_id = trans_id | 44 | self.trans_id = trans_id |
36 | 47 | 45 | ||
37 | 48 | class UnityLauncher(object): | 46 | class UnityLauncher(object): |
38 | 49 | """ Implements the integration between Software Center and the Unity | 47 | """ Implements the integration between Software Center and the Unity |
39 | 50 | launcher | 48 | launcher |
40 | 51 | """ | 49 | """ |
59 | 52 | def __init__(self): | 50 | |
42 | 53 | # keep track of applications that are candidates for adding | ||
43 | 54 | # to the Unity launcher | ||
44 | 55 | self.launcher_queue = {} | ||
45 | 56 | |||
46 | 57 | def add_to_launcher_queue(self, pkgname, launcher_info): | ||
47 | 58 | """ add an application and its associated info to the set of candidates | ||
48 | 59 | for adding to the Unity launcher | ||
49 | 60 | """ | ||
50 | 61 | self.launcher_queue[pkgname] = launcher_info | ||
51 | 62 | |||
52 | 63 | def remove_from_launcher_queue(self, pkgname): | ||
53 | 64 | """ remove an application and its associated info from the set of | ||
54 | 65 | candidates for adding to the Unity launcher | ||
55 | 66 | """ | ||
56 | 67 | if pkgname in self.launcher_queue: | ||
57 | 68 | return self.launcher_queue.pop(pkgname) | ||
58 | 69 | |||
60 | 70 | def send_application_to_launcher(self, pkgname, launcher_info): | 51 | def send_application_to_launcher(self, pkgname, launcher_info): |
61 | 52 | """ send a dbus message to the Unity launcher service to initiate | ||
62 | 53 | the add to launcher functionality for the specified application | ||
63 | 54 | """ | ||
64 | 71 | LOG.debug("sending dbus signal to Unity launcher for application: ", | 55 | LOG.debug("sending dbus signal to Unity launcher for application: ", |
65 | 72 | launcher_info.name) | 56 | launcher_info.name) |
66 | 73 | LOG.debug(" launcher_info.icon_file_path: ", | 57 | LOG.debug(" launcher_info.icon_file_path: ", |
67 | 74 | launcher_info.icon_file_path) | 58 | launcher_info.icon_file_path) |
70 | 75 | LOG.debug(" launcher_info.installed_desktop_file_path: ", | 59 | LOG.debug(" launcher_info.app_install_desktop_file_path: ", |
71 | 76 | launcher_info.installed_desktop_file_path) | 60 | launcher_info.app_install_desktop_file_path) |
72 | 77 | LOG.debug(" launcher_info.trans_id: ", launcher_info.trans_id) | 61 | LOG.debug(" launcher_info.trans_id: ", launcher_info.trans_id) |
77 | 78 | # the application is being added to the launcher, so clear it from the | 62 | |
74 | 79 | # list of candidates in the launcher queue | ||
75 | 80 | self.remove_from_launcher_queue(pkgname) | ||
76 | 81 | # add the application by sending a dbus signal to the Unity launcher | ||
78 | 82 | try: | 63 | try: |
79 | 83 | bus = dbus.SessionBus() | 64 | bus = dbus.SessionBus() |
80 | 84 | launcher_obj = bus.get_object('com.canonical.Unity.Launcher', | 65 | launcher_obj = bus.get_object('com.canonical.Unity.Launcher', |
81 | @@ -91,7 +72,7 @@ | |||
82 | 91 | launcher_info.icon_x, | 72 | launcher_info.icon_x, |
83 | 92 | launcher_info.icon_y, | 73 | launcher_info.icon_y, |
84 | 93 | launcher_info.icon_size, | 74 | launcher_info.icon_size, |
86 | 94 | launcher_info.installed_desktop_file_path, | 75 | launcher_info.app_install_desktop_file_path, |
87 | 95 | launcher_info.trans_id) | 76 | launcher_info.trans_id) |
88 | 96 | except Exception as e: | 77 | except Exception as e: |
89 | 97 | LOG.warn("could not send dbus signal to the Unity launcher: (%s)", | 78 | LOG.warn("could not send dbus signal to the Unity launcher: (%s)", |
90 | 98 | 79 | ||
91 | === modified file 'softwarecenter/ui/gtk3/panes/availablepane.py' | |||
92 | --- softwarecenter/ui/gtk3/panes/availablepane.py 2012-01-12 20:18:16 +0000 | |||
93 | +++ softwarecenter/ui/gtk3/panes/availablepane.py 2012-01-30 04:08:26 +0000 | |||
94 | @@ -37,7 +37,6 @@ | |||
95 | 37 | from softwarecenter.paths import APP_INSTALL_PATH | 37 | from softwarecenter.paths import APP_INSTALL_PATH |
96 | 38 | from softwarecenter.utils import (wait_for_apt_cache_ready, | 38 | from softwarecenter.utils import (wait_for_apt_cache_ready, |
97 | 39 | get_exec_line_from_desktop, | 39 | get_exec_line_from_desktop, |
98 | 40 | convert_desktop_file_to_installed_location, | ||
99 | 41 | get_file_path_from_iconname) | 40 | get_file_path_from_iconname) |
100 | 42 | from softwarecenter.db.appfilter import AppFilter | 41 | from softwarecenter.db.appfilter import AppFilter |
101 | 43 | from softwarecenter.db.database import Application | 42 | from softwarecenter.db.database import Application |
102 | @@ -199,8 +198,6 @@ | |||
103 | 199 | # install backend | 198 | # install backend |
104 | 200 | self.backend.connect("transactions-changed", self._on_transactions_changed) | 199 | self.backend.connect("transactions-changed", self._on_transactions_changed) |
105 | 201 | self.backend.connect("transaction-started", self.on_transaction_started) | 200 | self.backend.connect("transaction-started", self.on_transaction_started) |
106 | 202 | self.backend.connect("transaction-finished", self.on_transaction_finished) | ||
107 | 203 | self.backend.connect("transaction-stopped", self.on_transaction_stopped) | ||
108 | 204 | 201 | ||
109 | 205 | # now we are initialized | 202 | # now we are initialized |
110 | 206 | self.searchentry.set_sensitive(True) | 203 | self.searchentry.set_sensitive(True) |
111 | @@ -352,22 +349,22 @@ | |||
112 | 352 | 349 | ||
113 | 353 | def on_transaction_started(self, backend, pkgname, appname, trans_id, | 350 | def on_transaction_started(self, backend, pkgname, appname, trans_id, |
114 | 354 | trans_type): | 351 | trans_type): |
117 | 355 | self._register_unity_launcher_transaction_started( | 352 | self._add_application_to_unity_launcher( |
118 | 356 | backend, pkgname, appname, trans_id, trans_type) | 353 | backend, pkgname, appname, trans_id, trans_type) |
119 | 357 | 354 | ||
123 | 358 | def _register_unity_launcher_transaction_started(self, backend, pkgname, | 355 | def _add_application_to_unity_launcher(self, backend, pkgname, |
124 | 359 | appname, trans_id, | 356 | appname, trans_id, |
125 | 360 | trans_type): | 357 | trans_type): |
126 | 361 | if not self.add_to_launcher_enabled: | 358 | if not self.add_to_launcher_enabled: |
127 | 362 | return | 359 | return |
128 | 363 | # mvo: use use softwarecenter.utils explictly so that we can monkey | 360 | # mvo: use use softwarecenter.utils explictly so that we can monkey |
129 | 364 | # patch it in the test | 361 | # patch it in the test |
130 | 365 | if not softwarecenter.utils.is_unity_running(): | 362 | if not softwarecenter.utils.is_unity_running(): |
131 | 366 | return | 363 | return |
133 | 367 | # we only care about getting the launcher information on an install | 364 | # we only care about installs |
134 | 368 | if not trans_type == TransactionTypes.INSTALL: | 365 | if not trans_type == TransactionTypes.INSTALL: |
135 | 369 | return | 366 | return |
137 | 370 | # gather details for this transaction and create the launcher_info object | 367 | |
138 | 371 | app = Application(pkgname=pkgname, appname=appname) | 368 | app = Application(pkgname=pkgname, appname=appname) |
139 | 372 | appdetails = app.get_details(self.db) | 369 | appdetails = app.get_details(self.db) |
140 | 373 | # we only add items to the launcher that have a desktop file | 370 | # we only add items to the launcher that have a desktop file |
141 | @@ -380,17 +377,26 @@ | |||
142 | 380 | not get_exec_line_from_desktop(appdetails.desktop_file)): | 377 | not get_exec_line_from_desktop(appdetails.desktop_file)): |
143 | 381 | return | 378 | return |
144 | 382 | 379 | ||
146 | 383 | (icon_size, icon_x, icon_y) = self._get_onscreen_icon_details_for_launcher_service(app) | 380 | # now gather up the unity launcher info items and send the app to the |
147 | 381 | # launcher service | ||
148 | 382 | launcher_info = self._get_unity_launcher_info(app, appdetails, trans_id) | ||
149 | 383 | self.unity_launcher.send_application_to_launcher(pkgname, launcher_info) | ||
150 | 384 | |||
151 | 385 | def _get_unity_launcher_info(self, app, appdetails, trans_id): | ||
152 | 386 | (icon_size, icon_x, icon_y) = ( | ||
153 | 387 | self._get_onscreen_icon_details_for_launcher_service(app)) | ||
154 | 388 | icon_path = get_file_path_from_iconname( | ||
155 | 389 | self.icons, | ||
156 | 390 | iconname=appdetails.icon_file_name) | ||
157 | 384 | launcher_info = UnityLauncherInfo(app.name, | 391 | launcher_info = UnityLauncherInfo(app.name, |
158 | 385 | appdetails.icon, | 392 | appdetails.icon, |
160 | 386 | "", # we set the icon_file_path value *after* install | 393 | icon_path, |
161 | 387 | icon_x, | 394 | icon_x, |
162 | 388 | icon_y, | 395 | icon_y, |
163 | 389 | icon_size, | 396 | icon_size, |
164 | 390 | appdetails.desktop_file, | 397 | appdetails.desktop_file, |
165 | 391 | "", # we set the installed_desktop_file_path *after* install | ||
166 | 392 | trans_id) | 398 | trans_id) |
168 | 393 | self.unity_launcher.add_to_launcher_queue(app.pkgname, launcher_info) | 399 | return launcher_info |
169 | 394 | 400 | ||
170 | 395 | def _get_onscreen_icon_details_for_launcher_service(self, app): | 401 | def _get_onscreen_icon_details_for_launcher_service(self, app): |
171 | 396 | if self.is_app_details_view_showing(): | 402 | if self.is_app_details_view_showing(): |
172 | @@ -399,28 +405,6 @@ | |||
173 | 399 | # TODO: implement the app list view case once it has been specified | 405 | # TODO: implement the app list view case once it has been specified |
174 | 400 | return (0, 0, 0) | 406 | return (0, 0, 0) |
175 | 401 | 407 | ||
176 | 402 | def on_transaction_finished(self, backend, result): | ||
177 | 403 | self._check_unity_launcher_transaction_finished(result) | ||
178 | 404 | |||
179 | 405 | def _check_unity_launcher_transaction_finished(self, result): | ||
180 | 406 | # add the completed transaction details to the corresponding | ||
181 | 407 | # launcher_item | ||
182 | 408 | if result.pkgname in self.unity_launcher.launcher_queue: | ||
183 | 409 | launcher_info = self.unity_launcher.launcher_queue[result.pkgname] | ||
184 | 410 | launcher_info.icon_file_path = get_file_path_from_iconname( | ||
185 | 411 | self.icons, launcher_info.icon_name) | ||
186 | 412 | installed_path = convert_desktop_file_to_installed_location( | ||
187 | 413 | launcher_info.app_install_desktop_file_path, result.pkgname) | ||
188 | 414 | launcher_info.installed_desktop_file_path = installed_path | ||
189 | 415 | if result.success: | ||
190 | 416 | self.unity_launcher.send_application_to_launcher( | ||
191 | 417 | result.pkgname, launcher_info) | ||
192 | 418 | else: | ||
193 | 419 | self.unity_launcher.remove_from_launcher_queue(result.pkgname) | ||
194 | 420 | |||
195 | 421 | def on_transaction_stopped(self, backend, result): | ||
196 | 422 | self.unity_launcher.remove_from_launcher_queue(result.pkgname) | ||
197 | 423 | |||
198 | 424 | def on_app_list_changed(self, pane, length): | 408 | def on_app_list_changed(self, pane, length): |
199 | 425 | """internal helper that keeps the status text and the action | 409 | """internal helper that keeps the status text and the action |
200 | 426 | bar up-to-date by keeping track of the app-list-changed | 410 | bar up-to-date by keeping track of the app-list-changed |
201 | 427 | 411 | ||
202 | === modified file 'test/gtk3/test_unity_launcher_integration.py' | |||
203 | --- test/gtk3/test_unity_launcher_integration.py 2012-01-16 14:42:49 +0000 | |||
204 | +++ test/gtk3/test_unity_launcher_integration.py 2012-01-30 04:08:26 +0000 | |||
205 | @@ -4,8 +4,6 @@ | |||
206 | 4 | import time | 4 | import time |
207 | 5 | import unittest | 5 | import unittest |
208 | 6 | 6 | ||
209 | 7 | from mock import Mock | ||
210 | 8 | |||
211 | 9 | from testutils import setup_test_env | 7 | from testutils import setup_test_env |
212 | 10 | setup_test_env() | 8 | setup_test_env() |
213 | 11 | 9 | ||
214 | @@ -16,6 +14,7 @@ | |||
215 | 16 | from softwarecenter.utils import convert_desktop_file_to_installed_location | 14 | from softwarecenter.utils import convert_desktop_file_to_installed_location |
216 | 17 | from softwarecenter.db.application import Application | 15 | from softwarecenter.db.application import Application |
217 | 18 | from softwarecenter.ui.gtk3.panes.availablepane import get_test_window | 16 | from softwarecenter.ui.gtk3.panes.availablepane import get_test_window |
218 | 17 | from softwarecenter.backend.unitylauncher import UnityLauncherInfo | ||
219 | 19 | 18 | ||
220 | 20 | # we can only have one instance of availablepane, so create it here | 19 | # we can only have one instance of availablepane, so create it here |
221 | 21 | win = get_test_window() | 20 | win = get_test_window() |
222 | @@ -51,47 +50,58 @@ | |||
223 | 51 | TransactionTypes.INSTALL) | 50 | TransactionTypes.INSTALL) |
224 | 52 | # wait a wee bit | 51 | # wait a wee bit |
225 | 53 | self._zzz() | 52 | self._zzz() |
226 | 54 | |||
227 | 55 | def test_unity_launcher_integration(self): | ||
228 | 56 | # test the automatic add to launcher enabled functionality | ||
229 | 57 | available_pane.add_to_launcher_enabled = True | ||
230 | 58 | test_pkgname = "lincity-ng" | ||
231 | 59 | mock_result = Mock() | ||
232 | 60 | mock_result.pkgname = test_pkgname | ||
233 | 61 | mock_result.success = True | ||
234 | 62 | # now pretend | ||
235 | 63 | self._navigate_to_appdetails_and_install(test_pkgname) | ||
236 | 64 | 53 | ||
244 | 65 | # check that a correct UnityLauncherInfo object has been created and | 54 | def _fake_send_application_to_launcher_and_check(self, |
245 | 66 | # added to the queue | 55 | pkgname, launcher_info): |
246 | 67 | self.assertTrue(test_pkgname in available_pane.unity_launcher.launcher_queue) | 56 | self.assertEqual(pkgname, self.expected_pkgname) |
247 | 68 | launcher_info = available_pane.unity_launcher.remove_from_launcher_queue(test_pkgname) | 57 | self.assertEqual(launcher_info.name, self.expected_launcher_info.name) |
248 | 69 | # check the UnityLauncherInfo values themselves | 58 | self.assertEqual(launcher_info.icon_name, |
249 | 70 | self.assertEqual(launcher_info.name, "lincity-ng") | 59 | self.expected_launcher_info.icon_name) |
243 | 71 | self.assertEqual(launcher_info.icon_name, "lincity-ng") | ||
250 | 72 | self.assertTrue(launcher_info.icon_x > 5) | 60 | self.assertTrue(launcher_info.icon_x > 5) |
251 | 73 | self.assertTrue(launcher_info.icon_y > 5) | 61 | self.assertTrue(launcher_info.icon_y > 5) |
252 | 74 | self.assertEqual(launcher_info.icon_size, 96) | 62 | self.assertEqual(launcher_info.icon_size, 96) |
253 | 75 | self.assertEqual(launcher_info.app_install_desktop_file_path, | 63 | self.assertEqual(launcher_info.app_install_desktop_file_path, |
259 | 76 | "/usr/share/app-install/desktop/lincity-ng:lincity-ng.desktop") | 64 | self.expected_launcher_info.app_install_desktop_file_path) |
260 | 77 | self.assertEqual(launcher_info.trans_id, "testid101") | 65 | self.assertEqual(launcher_info.trans_id, |
261 | 78 | # finally, make sure the the app has been removed from the launcher | 66 | self.expected_launcher_info.trans_id) |
262 | 79 | # queue | 67 | |
263 | 80 | self.assertFalse(test_pkgname in available_pane.unity_launcher.launcher_queue) | 68 | def test_unity_launcher_integration(self): |
264 | 69 | # test the automatic add to launcher enabled functionality | ||
265 | 70 | available_pane.add_to_launcher_enabled = True | ||
266 | 71 | test_pkgname = "lincity-ng" | ||
267 | 72 | # now pretend | ||
268 | 73 | # for testing, we substitute a fake version of UnityLauncher's | ||
269 | 74 | # send_application_to_launcher method that lets us check for the | ||
270 | 75 | # correct values and also avoids firing the actual dbus signal | ||
271 | 76 | # to the unity launcher service | ||
272 | 77 | self.expected_pkgname = test_pkgname | ||
273 | 78 | self.expected_launcher_info = UnityLauncherInfo("lincity-ng", | ||
274 | 79 | "lincity-ng", | ||
275 | 80 | 0, 0, 0, 0, # these values are set in availablepane | ||
276 | 81 | "/usr/share/app-install/desktop/lincity-ng:lincity-ng.desktop", | ||
277 | 82 | "testid101") | ||
278 | 83 | available_pane.unity_launcher.send_application_to_launcher = ( | ||
279 | 84 | self._fake_send_application_to_launcher_and_check) | ||
280 | 85 | self._navigate_to_appdetails_and_install(test_pkgname) | ||
281 | 81 | 86 | ||
282 | 82 | def test_unity_launcher_integration_disabled(self): | 87 | def test_unity_launcher_integration_disabled(self): |
283 | 83 | # test the case where automatic add to launcher is disabled | 88 | # test the case where automatic add to launcher is disabled |
284 | 84 | available_pane.add_to_launcher_enabled = False | 89 | available_pane.add_to_launcher_enabled = False |
285 | 85 | test_pkgname = "lincity-ng" | 90 | test_pkgname = "lincity-ng" |
286 | 86 | mock_result = Mock() | ||
287 | 87 | mock_result.pkgname = test_pkgname | ||
288 | 88 | mock_result.success = True | ||
289 | 89 | # now pretend | 91 | # now pretend |
290 | 92 | # for testing, we substitute a fake version of UnityLauncher's | ||
291 | 93 | # send_application_to_launcher method that lets us check for the | ||
292 | 94 | # correct values and also avoids firing the actual dbus signal | ||
293 | 95 | # to the unity launcher service | ||
294 | 96 | # in the disabled add to launcher case, we just want to insure | ||
295 | 97 | # that we never call send_application_to_launcher, so we can just | ||
296 | 98 | # plug in bogus values and we will catch a call if it occurs | ||
297 | 99 | self.expected_pkgname = "" | ||
298 | 100 | self.expected_launcher_info = UnityLauncherInfo("", "", | ||
299 | 101 | 0, 0, 0, 0, "", "") | ||
300 | 102 | available_pane.unity_launcher.send_application_to_launcher = ( | ||
301 | 103 | self._fake_send_application_to_launcher_and_check) | ||
302 | 90 | self._navigate_to_appdetails_and_install(test_pkgname) | 104 | self._navigate_to_appdetails_and_install(test_pkgname) |
303 | 91 | |||
304 | 92 | # check that no corresponding unity_launcher info object has been added | ||
305 | 93 | # to the queue | ||
306 | 94 | self.assertFalse(test_pkgname in available_pane.unity_launcher.launcher_queue) | ||
307 | 95 | 105 | ||
308 | 96 | def test_desktop_file_path_conversion(self): | 106 | def test_desktop_file_path_conversion(self): |
309 | 97 | # test 'normal' case | 107 | # test 'normal' case |