~stolowski/unity-scope-home/direct-search

« back to all changes in this revision

Viewing changes to src/scope.vala

  • Committer: Tarmac
  • Author(s): Pawel Stolowski
  • Date: 2013-03-22 16:27:12 UTC
  • mfrom: (65.2.14 advanced-filters)
  • Revision ID: tarmac-20130322162712-zxj2hwa59j4tk06p
Implemented advanced filter behaviour (e.g. default view where user can modify default filters when search query is empty).

Approved by Michal Hruby, PS Jenkins bot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
{
32
32
  private ScopeManager scope_mgr = new ScopeManager ();
33
33
  private SearchQueryState query_state = new SearchQueryState ();
 
34
  private FilterState filter_state = new FilterState ();
34
35
  private KeywordSearch keywords_search = new KeywordSearch ();
35
36
  private bool smart_scopes_initialized = false;
36
37
  private bool smart_scopes_ready = false;
170
171
    var src_filter = new Unity.CheckOptionFilter ("sources", _("Sources"));
171
172
    foreach (var node in ScopeRegistry.instance ().scopes)
172
173
    {
173
 
      debug ("Category filter add: %s", node.scope_info.id);
174
 
      cat_filter.add_option (node.scope_info.id, node.scope_info.name); //add master scope id to 'Categories'
 
174
      if (node.scope_info.visible)
 
175
      {
 
176
        debug ("Category filter add: %s", node.scope_info.id);
 
177
        cat_filter.add_option (node.scope_info.id, node.scope_info.name); //add master scope id to 'Categories'
 
178
      }
175
179
      foreach (var scope in node.sub_scopes)
176
180
      {
177
 
        debug ("Sources filter add: %s", scope.id);
178
 
        src_filter.add_option (scope.id, scope.name);
 
181
        if (scope.visible) // should we also hide subsope if master is not visible?
 
182
        {
 
183
          debug ("Sources filter add: %s", scope.id);
 
184
          src_filter.add_option (scope.id, scope.name);
 
185
        }
179
186
      }
180
187
    }
181
188
    src_filter.show_all_button = false;
364
371
 
365
372
  public override async void search (Unity.AggregatedScopeSearch scope_search)
366
373
  {
367
 
    debug ("Search query: %s", scope_search.search_string);
 
374
    debug ("------------ Search query: %s, channel %s -----------", scope_search.search_string, scope_search.channel_id);
368
375
 
369
376
    init_sss_client ();
370
377
 
408
415
    // may map to null, in that case there is no filtering based on sub-scopes (all subscopes of given master will be queried).
409
416
    var search_scopes = new HashTable<string, Gee.Set<string>?> (str_hash, str_equal);
410
417
 
411
 
    // apply user filters only if search string is unchanged (or smart scopes are disabled completly).
 
418
    // filters are updated during the search, but may need to be updated again afterwards if we find out there wero no results for some categories
 
419
    bool needs_filter_update = false;
 
420
 
 
421
    // default filter view flag; default view is kind of a special case that kicks in when search query is empty:
 
422
    // user can modify filters at will, and they are stored in gsettings key.
 
423
    // this flag prevents filter updates based on what scopes were actually searched and if they had results, so that user can comfortably
 
424
    // edit the all the filters without loosing them every second.
 
425
    bool default_view = false;
 
426
 
 
427
    bool empty_query = (scope_search.search_string.strip ().length == 0);
 
428
 
 
429
    // apply user filters only if search string is unchanged, the query is empty or smart scopes are disabled completly.
412
430
    // this mean user set filters *after* entering a query and we apply them;
413
431
    // otherwise smart scopes recommendations will take precedence.
414
 
    if (search_query_changed == SearchQueryChange.NOT_CHANGED || sss_client == null)
 
432
    // if search query is empty, then apply default user's filters.
 
433
    if (search_query_changed == SearchQueryChange.NOT_CHANGED || empty_query || sss_client == null)
 
434
    {
 
435
      // if query is empty but it's not just a filter change (i.e. state is REMOVES_FROM_PREVIOUS_QUERY or NEW_QUERY),
 
436
      // then apply default user filters.
 
437
      if (empty_query && search_query_changed != SearchQueryChange.NOT_CHANGED)
 
438
      {
 
439
        var default_filters = scope_mgr.home_lens_default_view;
 
440
        if (default_filters.length > 0)
 
441
        {
 
442
          debug ("Empty query, applying default filter view");
 
443
          needs_filter_update |= FilterState.set_filters (scope_search, default_filters);
 
444
        }
 
445
        default_view = true;
 
446
      }
 
447
 
 
448
      debug ("Updating filter interrelationships");
 
449
      needs_filter_update |= filter_state.update_filter_relations (scope_search);
 
450
      debug ("Filter interrelationships changed: %s", needs_filter_update.to_string ());
 
451
 
415
452
      SearchUtil.scopes_to_query_from_filters (scope_search.get_filter ("sources") as Unity.OptionsFilter,
416
453
                                               scope_search.get_filter ("categories") as Unity.OptionsFilter,
417
454
                                               search_scopes);
418
455
 
 
456
      // if this search request is a filter change only, then update user's default view in gsettings
 
457
      if (search_query_changed == SearchQueryChange.NOT_CHANGED && empty_query)
 
458
      {
 
459
        default_view = true;
 
460
        debug ("Updating user's default filter view");
 
461
        scope_mgr.home_lens_default_view = SearchUtil.scopes_to_query_to_array (search_scopes);
 
462
      }
 
463
    }
 
464
 
419
465
    // initiate Smart Scopes Search (if enabled and query not empty)
420
466
    if (smart_scopes_ready == true)
421
467
    {
422
 
      if (search_query_changed == SearchQueryChange.EMPTY_QUERY)
 
468
      if (empty_query)
423
469
      { 
424
470
        if (channel_id_map.has_session_id_for_channel (scope_search.channel_id))
425
471
        {
498
544
 
499
545
    // no filters set / no scopes to search, use always-search scopes
500
546
    if (search_scopes.size () == 0)
 
547
    {
 
548
      debug ("No scopes to search based on filters. Defaulting to always-search-scopes");
501
549
      SearchUtil.scopes_to_query_from_requested_ids (scope_mgr.get_always_run_scopes (), search_scopes);
 
550
    }
502
551
 
503
552
    // handle keywords
504
553
    string search_string;
529
578
 
530
579
    bool use_recommended_scopes = false;
531
580
    
532
 
    // filters are updated during the search, but may need to be updated again afterwards if we find out there wero no results for some categories
533
 
    bool needs_filter_update = false;
534
 
 
535
581
    // dispatch search to scopes recommended by smart scopes service
536
 
    if (smart_scopes_ready  && search_query_changed != SearchQueryChange.EMPTY_QUERY)
 
582
    if (smart_scopes_ready && !empty_query)
537
583
    {
538
584
      // wait for smart scopes service query to finish
539
585
      if (wait_for_sss_query_finished == true)
552
598
    if (search_query_changed != SearchQueryChange.NOT_CHANGED && !direct_search && recommended_search_scopes.length () > 0)
553
599
      use_recommended_scopes = true;
554
600
 
555
 
    debug ("Updating filter state");
556
 
    var filters = SearchUtil.update_filters (search_scopes, use_recommended_scopes ? recommended_search_scopes : null, scope_search, false, out needs_filter_update);
557
 
    if (filters != null)
558
 
    {
 
601
    // only update filters with searched scopes when not in the default view, otherwise default view filters may get de-selected
 
602
    if (!default_view)
 
603
    {
 
604
      debug ("Updating filter state");
 
605
      needs_filter_update |= SearchUtil.update_filters (search_scopes, use_recommended_scopes ? recommended_search_scopes : null,
 
606
                                                        scope_search, false);
 
607
    }
 
608
 
 
609
    if (needs_filter_update)
 
610
    {
 
611
      var filters = FilterState.create_filter_set (scope_search);
559
612
      debug ("Sending updated filters");
560
613
      scope_search.push_filter_settings (filters);
561
614
    }
600
653
      yield;
601
654
    
602
655
    debug ("search finished");
603
 
    
604
 
    //FIXME: make sure we're synchronized after pushing data
605
656
 
606
657
    signal_categories_order (scope_search, recommended_search_scopes);
607
658
 
608
659
    // update filter state again, but this time check result counts and send the update only if any of the highlighted masters has no results
609
 
    filters = SearchUtil.update_filters (search_scopes, use_recommended_scopes ? recommended_search_scopes : null, scope_search, true, out needs_filter_update);
610
 
    if (filters != null && needs_filter_update)
 
660
    if (!default_view)
 
661
      needs_filter_update |= SearchUtil.update_filters (search_scopes, use_recommended_scopes ? recommended_search_scopes : null, scope_search, true);
 
662
 
 
663
    if (needs_filter_update)
611
664
    {
 
665
      var filters = FilterState.create_filter_set (scope_search);
612
666
      debug ("Sending updated filters");
613
667
      scope_search.push_filter_settings (filters);
614
668
    }
622
676
 
623
677
      yield handle_found_metrics (scope_search.channel_id, session_id, server_sid, recommended_search_scopes);
624
678
    }
 
679
 
 
680
    debug ("All search activities finished");
625
681
  }
626
682
 
627
683
  public override int category_index_for_scope_id (string scope_id)