~ubuntu-branches/ubuntu/raring/software-center/raring-proposed

« back to all changes in this revision

Viewing changes to softwarecenter/ui/gtk3/panes/availablepane.py

  • Committer: Package Import Robot
  • Author(s): Michael Vogt
  • Date: 2012-10-11 15:33:05 UTC
  • mfrom: (195.1.18 quantal)
  • Revision ID: package-import@ubuntu.com-20121011153305-fm5ln7if3rpzts4n
Tags: 5.4.1.1
* lp:~mvo/software-center/reinstall-previous-purchase-token-fix:
  - fix reinstall previous purchases that have a system-wide
    license key LP: #1065481
* lp:~mvo/software-center/lp1060106:
  - Add missing gettext init for utils/update-software-center-agent
    (LP: #1060106)

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
 
30
30
from gettext import gettext as _
31
31
 
 
32
from softwarecenter.config import get_config
32
33
from softwarecenter.enums import (
33
34
    ActionButtons,
34
35
    NavButtons,
36
37
    DEFAULT_SEARCH_LIMIT,
37
38
    TransactionTypes,
38
39
)
39
 
from softwarecenter.paths import APP_INSTALL_PATH
40
40
from softwarecenter.utils import (
 
41
    convert_desktop_file_to_installed_location,
 
42
    is_no_display_desktop_file,
41
43
    get_exec_line_from_desktop,
42
44
    get_file_path_from_iconname,
43
45
)
46
48
 
47
49
from softwarecenter.ui.gtk3.views.purchaseview import PurchaseView
48
50
 
49
 
from softwarecenter.ui.gtk3.views.catview_gtk import (LobbyViewGtk,
50
 
                                                      SubCategoryViewGtk)
 
51
from softwarecenter.ui.gtk3.views.lobbyview import LobbyView
 
52
from softwarecenter.ui.gtk3.views.catview import SubCategoryView
51
53
from softwarepane import SoftwarePane
52
54
from softwarecenter.ui.gtk3.session.viewmanager import get_viewmanager
53
55
from softwarecenter.ui.gtk3.session.appmanager import get_appmanager
93
95
                 db,
94
96
                 distro,
95
97
                 icons,
96
 
                 datadir,
97
98
                 navhistory_back_action,
98
99
                 navhistory_forward_action):
99
100
        # parent
100
 
        SoftwarePane.__init__(self, cache, db, distro, icons, datadir)
 
101
        SoftwarePane.__init__(self, cache, db, distro, icons)
101
102
        self.searchentry.set_sensitive(False)
102
103
        # navigation history actions
103
104
        self.navhistory_back_action = navhistory_back_action
119
120
        # keep track of applications that are queued to be added
120
121
        # to the Unity launcher
121
122
        self.unity_launcher_transaction_queue = {}
122
 
        # flag to indicate whether applications should be added to the
123
 
        # unity launcher when installed (this value is initialized by
124
 
        # the config load in app.py)
125
 
        self.add_to_launcher_enabled = True
126
123
 
127
124
    def init_view(self):
128
125
        if self.view_initialized:
171
168
        self.scroll_categories = Gtk.ScrolledWindow()
172
169
        self.scroll_categories.set_policy(Gtk.PolicyType.AUTOMATIC,
173
170
                                        Gtk.PolicyType.AUTOMATIC)
174
 
        with ExecutionTime("create LobbyViewGtk"):
175
 
            self.cat_view = LobbyViewGtk(self.datadir, APP_INSTALL_PATH,
176
 
                                       self.cache,
177
 
                                       self.db,
178
 
                                       self.icons,
179
 
                                       self.apps_filter)
 
171
        with ExecutionTime("create LobbyView"):
 
172
            self.cat_view = LobbyView(
 
173
                self.cache, self.db, self.icons, self.apps_filter)
180
174
        self.scroll_categories.add(self.cat_view)
181
175
        self.notebook.append_page(self.scroll_categories,
182
176
            Gtk.Label(label="categories"))
183
177
 
184
178
        # sub-categories view
185
 
        with ExecutionTime("create SubCategoryViewGtk"):
186
 
            self.subcategories_view = SubCategoryViewGtk(self.datadir,
187
 
            APP_INSTALL_PATH,
188
 
            self.cache,
189
 
            self.db,
190
 
            self.icons,
191
 
            self.apps_filter,
192
 
            root_category=self.cat_view.categories[0])
 
179
        with ExecutionTime("create SubCategoryView"):
 
180
            self.subcategories_view = SubCategoryView(
 
181
                self.cache, self.db, self.icons, self.apps_filter,
 
182
                root_category=self.cat_view.categories[0])
193
183
        self.subcategories_view.connect(
194
184
            "category-selected", self.on_subcategory_activated)
195
185
        self.subcategories_view.connect(
196
 
            "application-activated", self.on_application_activated)
197
 
        self.subcategories_view.connect(
198
186
            "show-category-applist", self.on_show_category_applist)
199
 
        # FIXME: why do we have two application-{selected,activated] ?!?
200
 
        self.subcategories_view.connect(
201
 
            "application-selected", self.on_application_selected)
202
187
        self.subcategories_view.connect(
203
188
            "application-activated", self.on_application_activated)
204
189
        self.scroll_subcategories = Gtk.ScrolledWindow()
215
200
        self.cat_view.connect(
216
201
            "category-selected", self.on_category_activated)
217
202
        self.cat_view.connect(
218
 
            "application-selected", self.on_application_selected)
219
 
        self.cat_view.connect(
220
203
            "application-activated", self.on_application_activated)
221
204
 
222
205
        # details
234
217
            self.on_transactions_changed)
235
218
        self.backend.connect("transaction-finished",
236
219
            self.on_transaction_complete)
 
220
        self.backend.connect("transaction-cancelled",
 
221
            self.on_transaction_cancelled)
 
222
        # a transaction error is treated the same as a cancellation
237
223
        self.backend.connect("transaction-stopped",
238
 
            self.on_transaction_complete)
 
224
            self.on_transaction_cancelled)
239
225
 
240
226
        # now we are initialized
241
227
        self.searchentry.set_sensitive(True)
388
374
 
389
375
    def on_transaction_started(self, backend, pkgname, appname, trans_id,
390
376
                               trans_type):
391
 
        # we only care about installs for the launcher, queue here for
392
 
        # later, see #972710
393
 
        if trans_type == TransactionTypes.INSTALL:
394
 
            transaction_details = TransactionDetails(
395
 
                    pkgname, appname, trans_id, trans_type)
396
 
            self.unity_launcher_transaction_queue[pkgname] = (
397
 
                    transaction_details)
 
377
        self._register_unity_launcher_transaction_started(pkgname, appname,
 
378
                                                          trans_id, trans_type)
398
379
 
399
380
    def on_transactions_changed(self, backend, pending_transactions):
400
381
        """internal helper that keeps the action bar up-to-date by
402
383
        """
403
384
        if self._is_custom_list_search(self.state.search_term):
404
385
            self._update_action_bar()
405
 
        # add app to unity launcher on the first sign of progress
406
 
        # and remove from the pending queue once that is done
407
 
        for pkgname in pending_transactions:
408
 
            if pkgname in self.unity_launcher_transaction_queue:
409
 
                transaction_details = (
410
 
                    self.unity_launcher_transaction_queue.pop(pkgname))
411
 
                self._add_application_to_unity_launcher(transaction_details)
412
386
 
413
387
    def on_transaction_complete(self, backend, result):
 
388
        """ handle a transaction that has completed successfully
 
389
        """
 
390
        if result.pkgname in self.unity_launcher_transaction_queue:
 
391
            transaction_details = (
 
392
                self.unity_launcher_transaction_queue.pop(result.pkgname))
 
393
            self._add_application_to_unity_launcher(transaction_details)
 
394
 
 
395
    def on_transaction_cancelled(self, backend, result):
 
396
        """ handle a transaction that has been cancelled
 
397
        """
414
398
        if result.pkgname in self.unity_launcher_transaction_queue:
415
399
            self.unity_launcher_transaction_queue.pop(result.pkgname)
416
400
 
 
401
    def _register_unity_launcher_transaction_started(self, pkgname, appname,
 
402
                                                     trans_id, trans_type):
 
403
        # at the start of the transaction, we gather details for use later
 
404
        # when it is time to add the installed app to the Unity launcher,
 
405
        # (see #972710). we only care about installs for the launcher
 
406
        # mvo: use softwarecenter.utils explicitly here so that we can monkey
 
407
        #      patch it in the test
 
408
        config = get_config()
 
409
        if (trans_type == TransactionTypes.INSTALL and
 
410
                config.add_to_unity_launcher and
 
411
                softwarecenter.utils.is_unity_running()):
 
412
            transaction_details = TransactionDetails(
 
413
                    pkgname, appname, trans_id, trans_type)
 
414
            self.unity_launcher_transaction_queue[pkgname] = (
 
415
                    transaction_details)
 
416
 
417
417
    def _add_application_to_unity_launcher(self, transaction_details):
418
 
        if not self.add_to_launcher_enabled:
419
 
            return
420
 
        # mvo: use use softwarecenter.utils explicitly so that we can monkey
421
 
        #      patch it in the test
422
 
        if not softwarecenter.utils.is_unity_running():
423
 
            return
424
 
 
425
418
        app = Application(pkgname=transaction_details.pkgname,
426
419
                          appname=transaction_details.appname)
427
420
        appdetails = app.get_details(self.db)
 
421
        # convert the app-install desktop file location to the actual installed
 
422
        # desktop file location (or in the case of a purchased item from the
 
423
        # agent, generate the correct installed desktop file location)
 
424
        installed_desktop_file_path = (
 
425
            convert_desktop_file_to_installed_location(appdetails.desktop_file,
 
426
                                                       app.pkgname))
428
427
        # we only add items to the launcher that have a desktop file
429
 
        if not appdetails.desktop_file:
 
428
        if not installed_desktop_file_path:
430
429
            return
431
430
        # do not add apps that have no Exec entry in their desktop file
432
431
        # (e.g. wine, see LP: #848437 or ubuntu-restricted-extras,
433
 
        # see LP: #913756)
434
 
        if (os.path.exists(appdetails.desktop_file) and
435
 
            not get_exec_line_from_desktop(appdetails.desktop_file)):
 
432
        # see LP: #913756), also, don't add the item if NoDisplay is
 
433
        # specified (see LP: #1006483)
 
434
        if (os.path.exists(installed_desktop_file_path) and
 
435
            (not get_exec_line_from_desktop(installed_desktop_file_path) or
 
436
            is_no_display_desktop_file(installed_desktop_file_path))):
436
437
            return
437
438
 
438
439
        # now gather up the unity launcher info items and send the app to the
439
440
        # launcher service
440
441
        launcher_info = self._get_unity_launcher_info(app, appdetails,
 
442
                installed_desktop_file_path,
441
443
                transaction_details.trans_id)
442
444
        self.unity_launcher.send_application_to_launcher(
443
445
                transaction_details.pkgname,
444
446
                launcher_info)
445
447
 
446
 
    def _get_unity_launcher_info(self, app, appdetails, trans_id):
 
448
    def _get_unity_launcher_info(
 
449
            self, app, appdetails, installed_desktop_file_path, trans_id):
447
450
        (icon_size, icon_x, icon_y) = (
448
451
                self._get_onscreen_icon_details_for_launcher_service(app))
449
452
        icon_path = get_file_path_from_iconname(
450
453
                                self.icons,
451
 
                                iconname=appdetails.icon_file_name)
 
454
                                iconname=appdetails.icon)
 
455
        # Note that the transaction ID is not specified because we are firing
 
456
        # the dbus signal at the very end of the installation now, and the
 
457
        # corresponding fix in Unity is expecting this value to be empty (it
 
458
        # would not be useful to the Unity launcher at this point anyway,
 
459
        # as the corresponding transaction would be complete).
 
460
        # Please see bug LP: #925014 and corresponding Unity branch for
 
461
        # further details.
 
462
        # TODO: If and when we re-implement firing the dbus signal at the
 
463
        # start of the transaction, at that time we will need to replace
 
464
        # the empty string below with the trans_id value.
452
465
        launcher_info = UnityLauncherInfo(app.name,
453
466
                                          appdetails.icon,
454
467
                                          icon_path,
455
468
                                          icon_x,
456
469
                                          icon_y,
457
470
                                          icon_size,
458
 
                                          appdetails.desktop_file,
459
 
                                          trans_id)
 
471
                                          installed_desktop_file_path,
 
472
                                          "")
460
473
        return launcher_info
461
474
 
462
475
    def _get_onscreen_icon_details_for_launcher_service(self, app):
647
660
        self.app_view.vadj = view_state.vadjustment
648
661
 
649
662
        self.refresh_apps()
650
 
        self.cat_view.stop_carousels()
651
663
        return True
652
664
 
653
665
    def display_search_page(self, view_state):
672
684
        self.subcategories_view.set_subcategory(category, n_matches)
673
685
 
674
686
        self.action_bar.clear()
675
 
        self.cat_view.stop_carousels()
676
687
        return True
677
688
 
678
689
    def display_app_view_page(self, view_state):
679
690
        category = view_state.category
 
691
        subcategory = view_state.subcategory
680
692
        self.set_category(category)
 
693
        self.set_subcategory(subcategory)
681
694
 
682
695
        result = self.display_list_page(view_state)
683
696
 
693
706
        self.action_bar.clear()
694
707
 
695
708
        SoftwarePane.display_details_page(self, view_state)
696
 
        self.cat_view.stop_carousels()
697
709
        return True
698
710
 
699
711
    def display_purchase(self, view_state):
700
712
        self.notebook.set_current_page(self.Pages.PURCHASE)
701
713
        self.action_bar.clear()
702
 
        self.cat_view.stop_carousels()
703
714
 
704
715
    def display_previous_purchases(self, view_state):
705
716
        self.nonapps_visible = NonAppVisibility.ALWAYS_VISIBLE
710
721
        self._clear_search()
711
722
        self.refresh_apps()
712
723
        self.action_bar.clear()
713
 
        self.cat_view.stop_carousels()
714
724
        return True
715
725
 
716
726
    def on_subcategory_activated(self, subcat_view, category):
740
750
        vm = get_viewmanager()
741
751
        vm.display_page(self, page, self.state)
742
752
 
743
 
    def on_application_selected(self, appview, app):
744
 
        """Callback for when an app is selected."""
745
 
        super(AvailablePane, self).on_application_selected(appview, app)
 
753
    def on_application_activated(self, appview, app):
 
754
        """Callback for when an app is activated."""
 
755
        super(AvailablePane, self).on_application_activated(appview, app)
746
756
        if self.state.subcategory:
747
757
            self.current_app_by_subcategory[self.state.subcategory] = app
748
758
        else:
771
781
        current_page = self.notebook.get_current_page()
772
782
        return current_page == self.Pages.PURCHASE
773
783
 
 
784
    def set_subcategory(self, subcategory):
 
785
        LOG.debug('set_subcategory: %s' % subcategory)
 
786
        self.state.subcategory = subcategory
 
787
        self._apply_filters_for_category_or_subcategory(subcategory)
 
788
 
774
789
    def set_category(self, category):
775
790
        LOG.debug('set_category: %s' % category)
776
791
        self.state.category = category
 
792
        self._apply_filters_for_category_or_subcategory(category)
777
793
 
 
794
    def _apply_filters_for_category_or_subcategory(self, category):
778
795
        # apply flags
779
796
        if category:
780
797
            if 'nonapps-visible' in category.flags: