~mvo/software-center/small-sso-fixes

« back to all changes in this revision

Viewing changes to softwarecenter/ui/gtk3/views/catview_gtk.py

minor cleanup from lp:~gary-lasker/software-center/recommends-ui-lobby

Show diffs side-by-side

added added

removed removed

Lines of Context:
52
52
from softwarecenter.db.utils import get_query_for_pkgnames
53
53
from softwarecenter.distro import get_distro
54
54
from softwarecenter.backend.scagent import SoftwareCenterAgent
 
55
from softwarecenter.backend.recommends import RecommenderAgent
55
56
 
56
57
LOG=logging.getLogger(__name__)
57
58
 
248
249
        self.right_column = Gtk.Box.new(Gtk.Orientation.VERTICAL, self.SPACING)
249
250
        self.top_hbox.pack_start(self.right_column, True, True, 0)
250
251
 
251
 
        self._append_new()
252
 
        #~ self._append_recommendations()
 
252
        self._append_whats_new()
253
253
        self._append_top_rated()
254
 
 
 
254
        self._append_recommended_for_you()
255
255
        self._append_appcount()
256
256
 
257
257
        #self._append_video_clips()
363
363
            cat_vbox.pack_start(label, False, False, 0)
364
364
        return
365
365
 
366
 
    def _get_toprated_category_content(self):
367
 
        toprated_cat = get_category_by_name(self.categories, 
368
 
                                            u"Top Rated")  # unstranslated name
369
 
        if toprated_cat is None:
370
 
            LOG.warn("No 'toprated' category found!!")
 
366
    def _get_top_rated_category_content(self):
 
367
        top_rated_cat = get_category_by_name(self.categories, 
 
368
                                             u"Top Rated")  # untranslated name
 
369
        if top_rated_cat is None:
 
370
            LOG.warn("No 'top_rated' category found!!")
371
371
            return None, []
372
372
 
373
373
        enq = AppEnquire(self.cache, self.db)
374
374
        app_filter = AppFilter(self.db, self.cache)
375
 
        enq.set_query(toprated_cat.query,
 
375
        enq.set_query(top_rated_cat.query,
376
376
                      limit=TOP_RATED_CAROUSEL_LIMIT,
377
 
                      sortmode=toprated_cat.sortmode,
 
377
                      sortmode=top_rated_cat.sortmode,
378
378
                      filter=app_filter,
379
379
                      nonapps_visible=NonAppVisibility.ALWAYS_VISIBLE,
380
380
                      nonblocking_load=False)
384
384
                                              self.cache,
385
385
                                              self.icons)
386
386
 
387
 
        return toprated_cat, enq.get_documents()
 
387
        return top_rated_cat, enq.get_documents()
388
388
 
389
 
    def _update_toprated_content(self):
 
389
    def _update_top_rated_content(self):
390
390
        # remove any existing children from the grid widget
391
 
        self.toprated.remove_all()
392
 
        # get toprated category and docs
393
 
        toprated_cat, docs = self._get_toprated_category_content()
 
391
        self.top_rated.remove_all()
 
392
        # get top_rated category and docs
 
393
        top_rated_cat, docs = self._get_top_rated_category_content()
394
394
        # display docs
395
 
        self._add_tiles_to_flowgrid(docs, self.toprated,
 
395
        self._add_tiles_to_flowgrid(docs, self.top_rated,
396
396
                                    TOP_RATED_CAROUSEL_LIMIT)
397
 
        self.toprated.show_all()
398
 
        return toprated_cat
 
397
        self.top_rated.show_all()
 
398
        return top_rated_cat
399
399
 
400
400
    def _append_top_rated(self):
401
 
        self.toprated = FlowableGrid()
402
 
        #~ self.featured.row_spacing = StockEms.SMALL
403
 
        frame = FramedHeaderBox()
404
 
        frame.set_header_label(_("Top Rated"))
405
 
        frame.add(self.toprated)
406
 
        self.toprated_frame = frame
407
 
        self.right_column.pack_start(frame, True, True, 0)
 
401
        self.top_rated = FlowableGrid()
 
402
        #~ self.top_rated.row_spacing = StockEms.SMALL
 
403
        self.top_rated_frame = FramedHeaderBox()
 
404
        self.top_rated_frame.set_header_label(_("Top Rated"))
 
405
        self.top_rated_frame.add(self.top_rated)
 
406
        self.right_column.pack_start(self.top_rated_frame, True, True, 0)
408
407
 
409
 
        toprated_cat = self._update_toprated_content()
410
 
        # only display the 'More' LinkButton if we have toprated content
411
 
        if toprated_cat is not None:
412
 
            frame.header_implements_more_button()
413
 
            frame.more.connect('clicked', self.on_category_clicked, toprated_cat) 
 
408
        top_rated_cat = self._update_top_rated_content()
 
409
        # only display the 'More' LinkButton if we have top_rated content
 
410
        if top_rated_cat is not None:
 
411
            self.top_rated_frame.header_implements_more_button()
 
412
            self.top_rated_frame.more.connect('clicked', 
 
413
                               self.on_category_clicked, top_rated_cat) 
414
414
        return
415
415
 
416
 
    def _get_new_category_content(self):
417
 
        whatsnew_cat = get_category_by_name(self.categories, 
418
 
                                            u"What\u2019s New") # unstranslated name
419
 
        if whatsnew_cat is None:
420
 
            LOG.warn("No 'new' category found!!")
 
416
    def _get_whats_new_category_content(self):
 
417
        whats_new_cat = get_category_by_name(
 
418
                                        self.categories, 
 
419
                                        u"What\u2019s New") # untranslated name
 
420
        if whats_new_cat is None:
 
421
            LOG.warn("No 'whats_new' category found!!")
421
422
            return None, []
422
423
 
423
424
        enq = AppEnquire(self.cache, self.db)
424
425
        app_filter = AppFilter(self.db, self.cache)
425
426
        app_filter.set_available_only(True)
426
427
        app_filter.set_not_installed_only(True)
427
 
        enq.set_query(whatsnew_cat.query,
 
428
        enq.set_query(whats_new_cat.query,
428
429
                      limit=8,
429
430
                      filter=app_filter,
430
431
                      sortmode=SortMethods.BY_CATALOGED_TIME,
436
437
                                              self.cache,
437
438
                                              self.icons)
438
439
 
439
 
        return whatsnew_cat, enq.get_documents()
 
440
        return whats_new_cat, enq.get_documents()
440
441
 
441
 
    def _update_new_content(self):
 
442
    def _update_whats_new_content(self):
442
443
        # remove any existing children from the grid widget
443
 
        self.featured.remove_all()
444
 
        # get toprated category and docs
445
 
        whatsnew_cat, docs = self._get_new_category_content()
 
444
        self.whats_new.remove_all()
 
445
        # get top_rated category and docs
 
446
        whats_new_cat, docs = self._get_whats_new_category_content()
446
447
        # display docs
447
 
        self._add_tiles_to_flowgrid(docs, self.featured, 8)
448
 
        self.featured.show_all()
449
 
        return whatsnew_cat
450
 
 
451
 
    def _append_new(self):
452
 
        self.featured = FlowableGrid()
453
 
        frame = FramedHeaderBox()
454
 
        frame.set_header_label(_(u"What\u2019s New"))
455
 
        frame.add(self.featured)
456
 
        self.new_frame = frame
457
 
 
458
 
        whatsnew_cat = self._update_new_content()
459
 
        if whatsnew_cat is not None:
 
448
        self._add_tiles_to_flowgrid(docs, self.whats_new, 8)
 
449
        self.whats_new.show_all()
 
450
        return whats_new_cat
 
451
 
 
452
    def _append_whats_new(self):
 
453
        self.whats_new = FlowableGrid()
 
454
        self.whats_new_frame = FramedHeaderBox()
 
455
        self.whats_new_frame.set_header_label(_(u"What\u2019s New"))
 
456
        self.whats_new_frame.add(self.whats_new)
 
457
 
 
458
        whats_new_cat = self._update_whats_new_content()
 
459
        if whats_new_cat is not None:
460
460
            # only add to the visible right_frame if we actually have it
461
 
            self.right_column.pack_start(frame, True, True, 0)
462
 
            frame.header_implements_more_button()
463
 
            frame.more.connect('clicked', self.on_category_clicked, whatsnew_cat) 
 
461
            self.right_column.pack_start(self.whats_new_frame, True, True, 0)
 
462
            self.whats_new_frame.header_implements_more_button()
 
463
            self.whats_new_frame.more.connect('clicked', self.on_category_clicked, whats_new_cat) 
464
464
        return
465
465
 
466
466
    #~ def _append_recommendations(self):
467
467
        #~ featured_cat = get_category_by_name(self.categories, 
468
 
                                            #~ u"Featured")  # unstranslated name
 
468
                                            #~ u"Featured")  # untranslated name
469
469
#~ 
470
470
        #~ enq = AppEnquire(self.cache, self.db)
471
471
        #~ app_filter = AppFilter(self.db, self.cache)
486
486
        #~ docs = enq.get_documents()
487
487
        #~ self._add_tiles_to_flowgrid(docs, self.featured, 12)
488
488
        #~ return
 
489
        
 
490
    def _get_recommended_for_you_category_content(self, pkgs):
 
491
            
 
492
        query = get_query_for_pkgnames(pkgs)
 
493
        recommended_for_you_cat = Category(
 
494
                               u"Recommended for You", 
 
495
                               _("Recommended for You"),
 
496
                               None, 
 
497
                               query,
 
498
                               flags=['available-only', 'not-installed-only'],
 
499
                               item_limit=60)
 
500
            
 
501
        enq = AppEnquire(self.cache, self.db)
 
502
        app_filter = AppFilter(self.db, self.cache)
 
503
        app_filter.set_available_only(True)
 
504
        app_filter.set_not_installed_only(True)
 
505
        enq.set_query(recommended_for_you_cat.query,
 
506
                      limit=60,
 
507
                      filter=app_filter,
 
508
                      sortmode=SortMethods.UNSORTED,
 
509
                      nonapps_visible=NonAppVisibility.ALWAYS_VISIBLE,
 
510
                      nonblocking_load=False)
 
511
 
 
512
        if not hasattr(self, "helper"):
 
513
            self.helper = AppPropertiesHelper(self.db,
 
514
                                              self.cache,
 
515
                                              self.icons)
 
516
 
 
517
        return recommended_for_you_cat, enq.get_documents()
 
518
        
 
519
    def _recommend_top_result(self, recommender_agent, result_list):
 
520
        
 
521
        pkgs = []
 
522
        for item in result_list['recommendations']:
 
523
            pkgs.append(item['package_name'])
 
524
        
 
525
        ##### test data : TO BE REMOVED, obviously (test list of uninstalled apps)
 
526
        pkgs = ['clementine', 'hedgewars', 'gelemental', 'nexuiz', 'fgo', 'musique', 'pybik', 'radiotray', 'cherrytree', 'phlipple']
 
527
        #####    
 
528
            
 
529
        recommended_for_you_cat, docs = self._get_recommended_for_you_category_content(pkgs)
 
530
        
 
531
        # display docs
 
532
        if len(docs) > 0:
 
533
            self._add_tiles_to_flowgrid(docs, self.recommended_for_you, 8)
 
534
            self.recommended_for_you.show_all()
 
535
            self.recommended_for_you_frame.hide_spinner()
 
536
            self.recommended_for_you_frame.more.connect('clicked',
 
537
                                                        self.on_category_clicked,
 
538
                                                        recommended_for_you_cat)
 
539
        else:
 
540
            # TODO: this test for zero docs is temporary and will not be
 
541
            # needed once the recommendation service is up and running
 
542
            self._hide_recommended_for_you()
 
543
        return
 
544
        
 
545
    def _recommender_service_error(self, recommender_agent, error_type):
 
546
        LOG.warn("Error while accessing the recommender service: %s" 
 
547
                                                            % error_type)
 
548
        # TODO: temporary, instead we display cached recommendations here
 
549
        self._hide_recommended_for_you()
 
550
 
 
551
    def _update_recommended_for_you_content(self):
 
552
        # remove any existing children from the grid widget
 
553
        self.recommended_for_you.remove_all()
 
554
        self.recommended_for_you_frame.show_spinner()
 
555
        
 
556
        # get a list of top recommendations via the recommender agent
 
557
        self.recommender_agent = RecommenderAgent()
 
558
        self.recommender_agent.connect("recommend-top", self._recommend_top_result)
 
559
        self.recommender_agent.connect("error", self._recommender_service_error)
 
560
        self.recommender_agent.query_recommend_top()
 
561
 
 
562
    def _append_recommended_for_you(self):
 
563
    
 
564
        # TODO: This space will initially contain an opt-in screen, and this
 
565
        #       will update to the tile view of recommended apps when ready
 
566
        #       see https://wiki.ubuntu.com/SoftwareCenter#Home_screen
 
567
        self.bottom_hbox = Gtk.HBox(spacing=StockEms.SMALL)
 
568
        bottom_hbox_alignment = Gtk.Alignment()
 
569
        bottom_hbox_alignment.set_padding(0, 0, StockEms.MEDIUM-2, StockEms.MEDIUM-2)
 
570
        bottom_hbox_alignment.add(self.bottom_hbox)
 
571
        self.vbox.pack_start(bottom_hbox_alignment, False, False, 0)
 
572
        
 
573
        # TODO: During development, place the "Recommended for You" panel
 
574
        #       at the bottom, but swap this with the Top Rated panel once
 
575
        #       the recommended for you pieces are done and deployed
 
576
        #       see https://wiki.ubuntu.com/SoftwareCenter#Home_screen
 
577
        self.recommended_for_you = FlowableGrid()
 
578
        self.recommended_for_you_frame = FramedHeaderBox()
 
579
        self.recommended_for_you_frame.set_header_label(
 
580
                                                _(u"Recommended for You"))
 
581
        self.recommended_for_you_frame.add(self.recommended_for_you)
 
582
        self.recommended_for_you_frame.header_implements_more_button()
 
583
        self.bottom_hbox.pack_start(self.recommended_for_you_frame, 
 
584
                                    True, True, 0)
 
585
        
 
586
        # get the recommendations from the recommender agent
 
587
        self._update_recommended_for_you_content()
 
588
        
 
589
    def _hide_recommended_for_you(self):
 
590
        # remove the listeners
 
591
        self.recommender_agent.disconnect_by_func(self._recommend_top_result)
 
592
        self.recommender_agent.disconnect_by_func(self._recommender_service_error)
 
593
        # and hide the pane
 
594
        self.recommended_for_you_frame.hide()
489
595
 
490
596
    def _update_appcount(self):
491
597
        enq = AppEnquire(self.cache, self.db)
523
629
            return
524
630
        self._supported_only = supported_only
525
631
 
526
 
        self._update_toprated_content()
527
 
        self._update_new_content()
 
632
        self._update_top_rated_content()
 
633
        self._update_whats_new_content()
528
634
        self._update_appcount()
529
635
        return
530
636
 
554
660
        # sections
555
661
        self.current_category = None
556
662
        self.departments = None
557
 
        self.toprated = None
 
663
        self.top_rated = None
 
664
        self.recommended_for_you = None
558
665
        self.appcount = None
559
666
 
560
667
        # widgetry
563
670
        self.vbox.set_margin_top(StockEms.MEDIUM)
564
671
        return
565
672
 
566
 
    def _get_sub_toprated_content(self, category):
 
673
    def _get_sub_top_rated_content(self, category):
567
674
        app_filter = AppFilter(self.db, self.cache)
568
675
        self.enquire.set_query(category.query,
569
676
                               limit=TOP_RATED_CAROUSEL_LIMIT,
574
681
        return self.enquire.get_documents()
575
682
 
576
683
    @wait_for_apt_cache_ready # be consistent with new apps
577
 
    def _update_sub_toprated_content(self, category):
578
 
        self.toprated.remove_all()
 
684
    def _update_sub_top_rated_content(self, category):
 
685
        self.top_rated.remove_all()
579
686
        # FIXME: should this be m = "%s %s" % (_(gettext text), header text) ??
580
687
        # TRANSLATORS: %s is a category name, like Internet or Development Tools
581
688
        m = _('Top Rated %(category)s') % { 'category' : GObject.markup_escape_text(self.header)}
582
 
        self.toprated_frame.set_header_label(m)
583
 
        docs = self._get_sub_toprated_content(category)
584
 
        self._add_tiles_to_flowgrid(docs, self.toprated, TOP_RATED_CAROUSEL_LIMIT)
 
689
        self.top_rated_frame.set_header_label(m)
 
690
        docs = self._get_sub_top_rated_content(category)
 
691
        self._add_tiles_to_flowgrid(docs, self.top_rated, 
 
692
                                    TOP_RATED_CAROUSEL_LIMIT)
585
693
        return
586
694
 
587
 
    def _append_sub_toprated(self):
588
 
        self.toprated = FlowableGrid()
589
 
        self.toprated.set_row_spacing(6)
590
 
        self.toprated.set_column_spacing(6)
591
 
        self.toprated_frame = FramedHeaderBox()
592
 
        self.toprated_frame.pack_start(self.toprated, True, True, 0)
593
 
        self.vbox.pack_start(self.toprated_frame, False, True, 0)
 
695
    def _append_sub_top_rated(self):
 
696
        self.top_rated = FlowableGrid()
 
697
        self.top_rated.set_row_spacing(6)
 
698
        self.top_rated.set_column_spacing(6)
 
699
        self.top_rated_frame = FramedHeaderBox()
 
700
        self.top_rated_frame.pack_start(self.top_rated, True, True, 0)
 
701
        self.vbox.pack_start(self.top_rated_frame, False, True, 0)
594
702
        return
595
703
 
596
704
    def _update_subcat_departments(self, category, num_items):
637
745
        self.departments = FlowableGrid(paint_grid_pattern=False)
638
746
        self.departments.set_row_spacing(StockEms.SMALL)
639
747
        self.departments.set_column_spacing(StockEms.SMALL)
640
 
        frame = FramedBox(spacing=StockEms.MEDIUM,
641
 
                          padding=StockEms.MEDIUM)
 
748
        self.departments_frame = FramedBox(spacing=StockEms.MEDIUM,
 
749
                                           padding=StockEms.MEDIUM)
642
750
        # set x/y-alignment and x/y-expand
643
 
        frame.set(0.5, 0.0, 1.0, 1.0)
644
 
        frame.pack_start(self.subcat_label, False, False, 0)
645
 
        frame.pack_start(self.departments, True, True, 0)
 
751
        self.departments_frame.set(0.5, 0.0, 1.0, 1.0)
 
752
        self.departments_frame.pack_start(self.subcat_label, False, False, 0)
 
753
        self.departments_frame.pack_start(self.departments, True, True, 0)
646
754
        # append the departments section to the page
647
 
        self.vbox.pack_start(frame, False, True, 0)
 
755
        self.vbox.pack_start(self.departments_frame, False, True, 0)
648
756
        return
649
757
 
650
758
    def _update_appcount(self, appcount):
666
774
        # these methods add sections to the page
667
775
        # changing order of methods changes order that they appear in the page
668
776
        self._append_subcat_departments()
669
 
        self._append_sub_toprated()
 
777
        self._append_sub_top_rated()
670
778
        self._append_appcount()
671
779
        self._built = True
672
780
        return
673
781
 
674
782
    def _update_subcat_view(self, category, num_items=0):
675
783
        num_items = self._update_subcat_departments(category, num_items)
676
 
        self._update_sub_toprated_content(category)
 
784
        self._update_sub_top_rated_content(category)
677
785
        self._update_appcount(num_items)
678
786
        self.show_all()
679
787
        return