Merge lp:~gary-lasker/software-center/add-to-launcher-after-auth-lp972710 into lp:software-center

Proposed by Gary Lasker
Status: Merged
Merged at revision: 2985
Proposed branch: lp:~gary-lasker/software-center/add-to-launcher-after-auth-lp972710
Merge into: lp:software-center
Diff against target: 160 lines (+57/-25)
2 files modified
softwarecenter/backend/unitylauncher.py (+18/-2)
softwarecenter/ui/gtk3/panes/availablepane.py (+39/-23)
To merge this branch: bzr merge lp:~gary-lasker/software-center/add-to-launcher-after-auth-lp972710
Reviewer Review Type Date Requested Status
Michael Vogt Approve
Review via email: mp+102605@code.launchpad.net

Description of the change

This branch fixes bug 972710 where cancelling out of the authorization dialog for an application install leaves a (broken) icon in the Unity launcher. To fix this we now maintain a simple queue of pending installs, and we do not fire the add-to-launcher dbus signal to Unity until we get the very first transactions-changed event that corresponds to each package in the queue. In this way, the add-to-launcher animation does not occur until *after* the user has entered their authorization.

To test:

1. Choose any application and click to install (either from the list view or the details view)
2. When the auth window appears, simply cancel it.
3. Verify that the corresponding application icon is NOT found in the Unity launcher.

4. Click the install button again, but this time complete the authorizations step.
5. Verify that, within a few seconds, the icon animation occurs and the application icon is added to the Unity launcher (and shows the installation progress there).

Please also test with multiple simultaneous installs. Each will add the icon as soon as the corresponding transaction begins. The queue is maintained and cleared as each transaction completes (either finishes or is otherwise stopped).

The Unity launcher unit tests continue to work.

Many thanks for your review!

To post a comment you must log in.
Revision history for this message
Michael Vogt (mvo) wrote :

Thanks, this looks fine and works great.

One tiny question/nitpick, I noticed that:
-class UnityLauncherInfo(object):
+class UnityLauncherInfo(GObject.GObject):

and also for TransactionDetails and UnityLauncher. It seems like we don't use properties/signals
or other gobject features so I was wondering about the change? Or am I simply overlooking something?

review: Approve
Revision history for this message
Michael Vogt (mvo) wrote :

And one more detail, in:
    def on_transactions_changed(self, *args):
I would prefer to have
    def on_transactions_changed(self, backend, pending_transactions):
here to make the code easier to read.

Revision history for this message
Michael Vogt (mvo) wrote :

Thanks for correcting my "explictly" typo along the way :)

I merged this branch with some small tweaks (" def on_transactions_changed(self, backend, pending_transactions):" some comments added to the code. Please re-merge and double check that it makes sense. I left the GObject for now, its a minor thing but feedback on it is still welcome.

Revision history for this message
Gary Lasker (gary-lasker) wrote :

Hi Michael, thanks a lot, the merge looks good. Definitely agreed on the "pending_transactions" and the GObject is not necessary, so I'll fix that now. Thanks again!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'softwarecenter/backend/unitylauncher.py'
--- softwarecenter/backend/unitylauncher.py 2012-03-19 13:35:47 +0000
+++ softwarecenter/backend/unitylauncher.py 2012-04-18 23:53:20 +0000
@@ -16,13 +16,14 @@
16# this program; if not, write to the Free Software Foundation, Inc.,16# this program; if not, write to the Free Software Foundation, Inc.,
17# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA17# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1818
19from gi.repository import GObject
19import dbus20import dbus
20import logging21import logging
2122
22LOG = logging.getLogger(__name__)23LOG = logging.getLogger(__name__)
2324
2425
25class UnityLauncherInfo(object):26class UnityLauncherInfo(GObject.GObject):
26 """ Simple class to keep track of application details needed for27 """ Simple class to keep track of application details needed for
27 Unity launcher integration28 Unity launcher integration
28 """29 """
@@ -45,7 +46,22 @@
45 self.trans_id = trans_id46 self.trans_id = trans_id
4647
4748
48class UnityLauncher(object):49class TransactionDetails(GObject.GObject):
50 """ Simple class to keep track of aptdaemon transaction details for
51 use with the Unity launcher integration
52 """
53 def __init__(self,
54 pkgname,
55 appname,
56 trans_id,
57 trans_type):
58 self.pkgname = pkgname
59 self.appname = appname
60 self.trans_id = trans_id
61 self.trans_type = trans_type
62
63
64class UnityLauncher(GObject.GObject):
49 """ Implements the integration between Software Center and the Unity65 """ Implements the integration between Software Center and the Unity
50 launcher66 launcher
51 """67 """
5268
=== modified file 'softwarecenter/ui/gtk3/panes/availablepane.py'
--- softwarecenter/ui/gtk3/panes/availablepane.py 2012-04-13 11:30:48 +0000
+++ softwarecenter/ui/gtk3/panes/availablepane.py 2012-04-18 23:53:20 +0000
@@ -49,7 +49,8 @@
49from softwarecenter.ui.gtk3.session.viewmanager import get_viewmanager49from softwarecenter.ui.gtk3.session.viewmanager import get_viewmanager
50from softwarecenter.ui.gtk3.session.appmanager import get_appmanager50from softwarecenter.ui.gtk3.session.appmanager import get_appmanager
51from softwarecenter.backend.unitylauncher import (UnityLauncher,51from softwarecenter.backend.unitylauncher import (UnityLauncher,
52 UnityLauncherInfo)52 UnityLauncherInfo,
53 TransactionDetails)
5354
54LOG = logging.getLogger(__name__)55LOG = logging.getLogger(__name__)
5556
@@ -108,7 +109,9 @@
108109
109 # integrate with the Unity launcher110 # integrate with the Unity launcher
110 self.unity_launcher = UnityLauncher()111 self.unity_launcher = UnityLauncher()
111112 # keep track of applications that are queued to be added
113 # to the Unity launcher
114 self.unity_launcher_transaction_queue = {}
112 # flag to indicate whether applications should be added to the115 # flag to indicate whether applications should be added to the
113 # unity launcher when installed (this value is initialized by116 # unity launcher when installed (this value is initialized by
114 # the config load in app.py)117 # the config load in app.py)
@@ -213,10 +216,14 @@
213 Gtk.Label(label=NavButtons.PURCHASE))216 Gtk.Label(label=NavButtons.PURCHASE))
214217
215 # install backend218 # install backend
216 self.backend.connect("transactions-changed",
217 self._on_transactions_changed)
218 self.backend.connect("transaction-started",219 self.backend.connect("transaction-started",
219 self.on_transaction_started)220 self.on_transaction_started)
221 self.backend.connect("transactions-changed",
222 self.on_transactions_changed)
223 self.backend.connect("transaction-finished",
224 self.on_transaction_complete)
225 self.backend.connect("transaction-stopped",
226 self.on_transaction_complete)
220227
221 # now we are initialized228 # now we are initialized
222 self.searchentry.set_sensitive(True)229 self.searchentry.set_sensitive(True)
@@ -364,36 +371,44 @@
364 """ unset the current showing category, but keep e.g. the current371 """ unset the current showing category, but keep e.g. the current
365 search372 search
366 """373 """
367
368 self.state.category = None374 self.state.category = None
369 self.state.subcategory = None375 self.state.subcategory = None
370376
371 def _on_transactions_changed(self, *args):377 def on_transaction_started(self, backend, pkgname, appname, trans_id,
378 trans_type):
379 # we only care about installs for the launcher
380 if trans_type == TransactionTypes.INSTALL:
381 transaction_details = TransactionDetails(
382 pkgname, appname, trans_id, trans_type)
383 self.unity_launcher_transaction_queue[pkgname] = (
384 transaction_details)
385
386 def on_transactions_changed(self, *args):
372 """internal helper that keeps the action bar up-to-date by387 """internal helper that keeps the action bar up-to-date by
373 keeping track of the transaction-started signals388 keeping track of the transaction-started signals
374 """389 """
375 if self._is_custom_list_search(self.state.search_term):390 if self._is_custom_list_search(self.state.search_term):
376 self._update_action_bar()391 self._update_action_bar()
377392 for pkgname in args[1]:
378 def on_transaction_started(self, backend, pkgname, appname, trans_id,393 if pkgname in self.unity_launcher_transaction_queue:
379 trans_type):394 transaction_details = (
380 self._add_application_to_unity_launcher(395 self.unity_launcher_transaction_queue.pop(pkgname))
381 backend, pkgname, appname, trans_id, trans_type)396 self._add_application_to_unity_launcher(transaction_details)
382397
383 def _add_application_to_unity_launcher(self, backend, pkgname,398 def on_transaction_complete(self, backend, result):
384 appname, trans_id,399 if result.pkgname in self.unity_launcher_transaction_queue:
385 trans_type):400 self.unity_launcher_transaction_queue.pop(result.pkgname)
401
402 def _add_application_to_unity_launcher(self, transaction_details):
386 if not self.add_to_launcher_enabled:403 if not self.add_to_launcher_enabled:
387 return404 return
388 # mvo: use use softwarecenter.utils explictly so that we can monkey405 # mvo: use use softwarecenter.utils explicitly so that we can monkey
389 # patch it in the test406 # patch it in the test
390 if not softwarecenter.utils.is_unity_running():407 if not softwarecenter.utils.is_unity_running():
391 return408 return
392 # we only care about installs
393 if not trans_type == TransactionTypes.INSTALL:
394 return
395409
396 app = Application(pkgname=pkgname, appname=appname)410 app = Application(pkgname=transaction_details.pkgname,
411 appname=transaction_details.appname)
397 appdetails = app.get_details(self.db)412 appdetails = app.get_details(self.db)
398 # we only add items to the launcher that have a desktop file413 # we only add items to the launcher that have a desktop file
399 if not appdetails.desktop_file:414 if not appdetails.desktop_file:
@@ -408,9 +423,10 @@
408 # now gather up the unity launcher info items and send the app to the423 # now gather up the unity launcher info items and send the app to the
409 # launcher service424 # launcher service
410 launcher_info = self._get_unity_launcher_info(app, appdetails,425 launcher_info = self._get_unity_launcher_info(app, appdetails,
411 trans_id)426 transaction_details.trans_id)
412 self.unity_launcher.send_application_to_launcher(pkgname,427 self.unity_launcher.send_application_to_launcher(
413 launcher_info)428 transaction_details.pkgname,
429 launcher_info)
414430
415 def _get_unity_launcher_info(self, app, appdetails, trans_id):431 def _get_unity_launcher_info(self, app, appdetails, trans_id):
416 (icon_size, icon_x, icon_y) = (432 (icon_size, icon_x, icon_y) = (

Subscribers

People subscribed via source and target branches