~mhr3/unity-lens-applications/fix-1052513

« back to all changes in this revision

Viewing changes to src/daemon.vala

  • Committer: Neil Jagdish Patel
  • Date: 2011-08-03 21:52:17 UTC
  • mto: This revision was merged to the branch mainline in revision 213.
  • Revision ID: neil.patel@canonical.com-20110803215217-qknalm7lu98tpcmm
Add a filter and move some stuff around

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
15
 *
16
16
 * Authored by Mikkel Kamstrup Erlandsen <mikkel.kamstrup@canonical.com>
 
17
 *             Neil Jagdish Patel <neil.patel@canonical.com>
17
18
 *
18
19
 */
19
20
using Dee;
43
44
    //FIXME:private Unity.ApplicationsLens.Runner runner;
44
45
 
45
46
    /* For each section we have a set filtering query we use to restrict
46
 
     * Xapian queries to that section */
47
 
    private Gee.List<string> section_queries;
 
47
     * Xapian queries to that type */
 
48
    private HashTable<string, string> type_queries;
48
49
 
49
50
    private Gee.List<string> image_extensions;
50
51
    private HashTable<string,Icon> file_icon_cache;
64
65
 
65
66
    construct
66
67
    {
67
 
      section_queries = new Gee.ArrayList<string> ();
68
 
      populate_section_queries();
 
68
      populate_type_queries ();
69
69
      populate_zg_templates ();
70
70
 
71
71
      log = new Zeitgeist.Log();
145
145
      lens.export ();
146
146
    }
147
147
 
148
 
    /* FIXME:
149
 
    private void populate_sections ()
 
148
    /* Pre-populates the type queries so it's easier/faster to build our search */
 
149
    private void populate_type_queries ()
150
150
    {
151
 
      var sections = applications.sections_model;
152
 
 
153
 
      if (sections.get_n_rows() != 0)
154
 
        {
155
 
          debug ("Sections model already populated. We probably cloned it off Unity. Rebuilding.");
156
 
          sections.clear ();
157
 
        }
158
 
 
159
 
      sections.append (_("All Applications"), "");
160
 
      sections.append (_("Accessories"), "");
161
 
      sections.append (_("Universal Access"), "");
162
 
      sections.append (_("Developer Tools"), "");
163
 
      sections.append (_("Education"), "");
164
 
      sections.append (_("Science & Engineering"), "");
165
 
      sections.append (_("Games"), "");
166
 
      sections.append (_("Graphics"), "");
167
 
      sections.append (_("Internet"), "");
168
 
      sections.append (_("Multimedia"), "");
169
 
      sections.append (_("Office"), "");
170
 
      sections.append (_("Themes & Tweaks"), "");
171
 
      sections.append (_("System"), "");
 
151
      type_queries = new HashTable<string, string> (null, null);
 
152
      type_queries.insert ("all", "NOT category:XYZ");
 
153
 
 
154
      type_queries.insert ("accessories", "(category:Utility AND NOT category:Accessibility)");
 
155
      type_queries.insert ("education", "(category:Education AND NOT category:Science)");
 
156
      type_queries.insert ("game", "category:Game");
 
157
      type_queries.insert ("graphics", "category:Graphics");
 
158
      type_queries.insert ("internet", "category:Network");
 
159
      type_queries.insert ("fonts", "category:Fonts"); // FIXME: wtf?
 
160
      type_queries.insert ("office", "category:Office");
 
161
      type_queries.insert ("media", "category:AudioVideo");
 
162
      type_queries.insert ("customization", "category:Settings");
 
163
      type_queries.insert ("accessibility", "(category:Accessibility AND NOT category:Settings)");
 
164
      type_queries.insert ("developer", "category:Development"); // FIXME emacs.desktop should be added
 
165
      type_queries.insert ("science-and-engineering", "(category:Science OR category:Engineering)");
 
166
      type_queries.insert ("system", "(category:System OR category:Security)");
172
167
    }
173
 
    */
174
168
 
175
169
    private void populate_categories ()
176
170
    {
177
171
      Unity.Category[] categories = {};
178
172
 
179
 
      var cat = new Unity.GridCategory (_("Most Frequently Used"),
180
 
                                        ICON_PATH + "group-mostused.svg");
181
 
      categories += cat;
182
 
 
183
 
      cat = new Unity.GridCategory (_("Installed"),
184
 
                                    ICON_PATH + "group-installed.svg");
185
 
      categories += cat;
186
 
 
187
 
      cat = new Unity.GridCategory (_("Apps Available for Download"),
188
 
                                    ICON_PATH + "group-available.svg");
 
173
      var cat = new Unity.Category (_("Most Frequently Used"),
 
174
                                    ICON_PATH + "category-mostused.svg");
 
175
      categories += cat;
 
176
 
 
177
      cat = new Unity.Category (_("Installed"),
 
178
                                ICON_PATH + "category-installed.svg");
 
179
      categories += cat;
 
180
 
 
181
      cat = new Unity.Category (_("Apps Available for Download"),
 
182
                                ICON_PATH + "category-available.svg");
189
183
      categories += cat;
190
184
 
191
185
      lens.categories = categories;
192
 
      
193
 
      /* Always expand the Installed group */
194
 
      /* FIXME:
195
 
      applications.entry_renderer_info.set_hint ("ExpandedGroups",
196
 
                                                 @"$((uint)Category.INSTALLED)");
197
 
                                                 */
198
186
    }
199
187
 
200
 
    private void populate_section_queries ()
 
188
    private void populate_filters()
201
189
    {
202
 
      /* XDG category names. Not for translation. */
203
 
      /* We need the hack for ALL_APPLICATIONS below because Xapian doesn't
204
 
       * like '' or '*' queries */
205
 
      section_queries.add ("NOT category:XYZ"); //ALL_APPLICATIONS
206
 
      section_queries.add ("(category:Utility AND NOT category:Accessibility)"); //ACCESSORIES
207
 
      section_queries.add ("(category:Accessibility AND NOT category:Settings)"); //UNIVERSAL_ACCESS
208
 
      section_queries.add ("category:Development"); //DEVELOPER_TOOLS FIXME emacs.desktop should be added
209
 
      section_queries.add ("(category:Education AND NOT category:Science)"); // EDUCATION
210
 
      section_queries.add ("(category:Science OR category:Engineering)"); // SCIENCE
211
 
      section_queries.add ("category:Game"); // GAMES
212
 
      section_queries.add ("category:Graphics"); // GRAPHICS
213
 
      section_queries.add ("category:Network"); // INTERNET
214
 
      section_queries.add ("category:AudioVideo"); // MULTIMEDIA
215
 
      section_queries.add ("category:Office"); // OFFICE
216
 
      section_queries.add ("category:Settings"); // THEMES
217
 
      section_queries.add ("(category:System OR category:Security)"); // SYSTEM
 
190
      /* Type filter */
 
191
      {
 
192
        var filter = new RadioOptionFilter ("type", _("Type"));
 
193
        filter.add_option ("accessories", _("Accessories"));
 
194
        filter.add_option ("education", _("Education"));
 
195
        filter.add_option ("games", _("Games"));
 
196
        filter.add_option ("graphics", _("Graphics"));
 
197
        filter.add_option ("internet", _("Internet"));
 
198
        filter.add_option ("fonts", _("Fonts"));
 
199
        filter.add_option ("office", _("Office"));
 
200
        filter.add_option ("media", _("Media"));
 
201
        filter.add_option ("customization", _("Customization"));
 
202
        filter.add_option ("accessibility", _("Accessibility"));
 
203
        filter.add_option ("developer", _("Developer"));
 
204
        filter.add_option ("science-and-engineering", _("Science & Engineering"));
 
205
        filter.add_option ("system", _("System"));
 
206
      }
218
207
    }
219
 
    
 
208
  
220
209
    /* Load xdg menu info and build a Xapian index over it.
221
210
     * Do throttled re-index if the menu changes */
222
211
    private bool build_app_menu_index ()
226
215
          debug ("Building initial application menu");
227
216
        
228
217
          /* We need INCLUDE_NODISPLAY to employ proper de-duping between
229
 
           * the Installed and Availabale groups. If a NoDisplay app is installed,
 
218
           * the Installed and Availabale categorys. If a NoDisplay app is installed,
230
219
           * eg. Evince, it wont otherwise be in the menu index, only in the
231
 
           * S-C index - thus show up in the Available group */
 
220
           * S-C index - thus show up in the Available category */
232
221
          app_menu = GMenu.Tree.lookup ("unity-place-applications.menu",
233
222
                                        GMenu.TreeFlags.INCLUDE_NODISPLAY);
234
223
          
281
270
    }
282
271
 
283
272
    private string prepare_zg_search_string (Unity.LensSearch? search,
284
 
                                             Section section = Section.ALL_APPLICATIONS)
 
273
                                             string type_id="all")
285
274
    {
286
275
      
287
276
      string s;
298
287
      if (s != "")
299
288
        s = @"app:($s)";
300
289
      else
301
 
        return section_queries.get(section);
 
290
        return type_queries.lookup(type_id);
302
291
      
303
 
      if (section == Section.ALL_APPLICATIONS)
 
292
      if (type_id == "all")
304
293
        return s;
305
294
      else
306
 
        return s + @" AND $(section_queries.get(section))";
 
295
        return s + @" AND $(type_queries.lookup(type_id))";
307
296
 
308
297
      return s;
309
298
    }
318
307
      var model = scope.results_model;
319
308
      model.clear ();
320
309
      
321
 
      string pkg_search_string = prepare_pkg_search_string (search);
 
310
      var filter = scope.get_filter ("type") as RadioOptionFilter;
 
311
      Unity.FilterOption? option =  filter.get_active_option ();
 
312
      string type_id = option == null ? "all" : option.id;
 
313
 
 
314
      string pkg_search_string = prepare_pkg_search_string (search, type_id);
 
315
 
322
316
      bool has_search = !Utils.search_is_invalid (search);
323
317
      
324
318
      Timer timer = new Timer ();
342
336
       * So we can update the UI quicker */
343
337
      (model as Dee.SharedModel).flush_revision_queue ();
344
338
      
345
 
      var zg_search_string = prepare_zg_search_string (search);
 
339
      var zg_search_string = prepare_zg_search_string (search, type_id);
346
340
 
347
341
      try {
348
342
        timer.start ();
354
348
                                             Zeitgeist.ResultType.MOST_POPULAR_SUBJECTS,
355
349
                                             null);
356
350
 
357
 
        append_events_with_group (results, model, Category.MOST_USED);
 
351
        append_events_with_category (results, model, Category.MOST_USED);
358
352
        
359
353
        timer.stop ();
360
354
        debug ("Entry search found %u/%u Most Used apps in %fms for query '%s'",
426
420
       * Important: Remember to thaw the notifys again! */
427
421
      scope.freeze_notify ();      
428
422
      
429
 
      var search_string = prepare_pkg_search_string (search,
430
 
                                                     Section.ALL_APPLICATIONS);
 
423
      var search_string = prepare_pkg_search_string (search, "all");
431
424
      Set<string> installed_uris = new HashSet<string> ();
432
425
      Set<string> available_uris = new HashSet<string> ();
433
426
      var timer = new Timer ();
477
470
        search.finished ();
478
471
    }
479
472
    
480
 
    private string prepare_pkg_search_string (Unity.LensSearch? search, Section section=Section.ALL_APPLICATIONS)
 
473
    private string prepare_pkg_search_string (Unity.LensSearch? search, string type_id="all")
481
474
    {       
482
475
      if (Utils.search_is_invalid (search))
483
476
        {
484
 
          if (section == Section.ALL_APPLICATIONS)
 
477
          if (type_id == "all")
485
478
            return "type:Application";
486
479
          else
487
 
            return @"type:Application AND $(section_queries.get(section))";
 
480
            return @"type:Application AND $(type_queries.lookup(type_id))";
488
481
        }
489
482
      else
490
483
        {
499
492
           * match 'd-feet' etc. */
500
493
          s = s.delimit ("-", ' ');
501
494
 
502
 
          if (section == Section.ALL_APPLICATIONS)
 
495
          if (type_id == "all")
503
496
            return @"type:Application AND $s";
504
497
          else
505
 
            return @"type:Application AND $(section_queries.get(section)) AND $s";
 
498
            return @"type:Application AND $(type_queries.lookup(type_id)) AND $s";
506
499
        }
507
500
    }
508
501
    
574
567
                                        Set<string> installed_uris,
575
568
                                        Set<string> available_uris,
576
569
                                        Dee.Model model,
577
 
                                        Category group,
 
570
                                        Category category,
578
571
                                        uint max_add=0)
579
572
    {
580
573
      var appmanager = AppInfoManager.get_instance();
598
591
        /* Extract basic metadata and register de-dupe keys */
599
592
        string display_name;
600
593
        string comment;
601
 
        switch (group)
 
594
        switch (category)
602
595
        {
603
596
          case Category.INSTALLED:
604
597
            installed_uris.add (uri);
611
604
            comment = "";
612
605
            break;
613
606
          default:
614
 
            warning (@"Illegal group for package search $(group)");
 
607
            warning (@"Illegal category for package search $(category)");
615
608
            continue;
616
609
        } 
617
610
        
621
614
        if (app != null && !app.should_show ())
622
615
          continue;
623
616
                
624
 
        if (group == Category.AVAILABLE)
 
617
        if (category == Category.AVAILABLE)
625
618
          {
626
619
            /* If we have an available item, which is not a dupe, but is
627
620
             * installed anyway, we weed it out here, because it's probably
630
623
            if (app != null)
631
624
              continue;            
632
625
            
633
 
            /* Apps that are not installed, ie. in the Available group
 
626
            /* Apps that are not installed, ie. in the Available category
634
627
             * use the 'unity-install://pkgname/Full App Name' URI scheme,
635
628
             * but only use that after we've de-duped the results.
636
629
             * But only change the URI *after* we've de-duped the results! */
641
634
        Icon icon = find_pkg_icon (pkginfo);
642
635
        
643
636
        model.append (uri, icon.to_string (),
644
 
                      group,"application/x-desktop",
 
637
                      category,"application/x-desktop",
645
638
                      display_name != null ? display_name : "",
646
639
                      comment != null ? comment : "");
647
640
        
722
715
#endif
723
716
    /* Appends the subject URIs from a set of Zeitgeist.Events to our Dee.Model
724
717
     * assuming that these events are already sorted */
725
 
    public void append_events_with_group (Zeitgeist.ResultSet events,
 
718
    public void append_events_with_category (Zeitgeist.ResultSet events,
726
719
                                          Dee.Model results,
727
 
                                          uint group_id,
728
 
                                          int section_filter = -1)
 
720
                                          uint category_id)
729
721
    {
730
722
      foreach (var ev in events)
731
723
        {
747
739
          if (!app.should_show ())
748
740
            continue;          
749
741
          
750
 
          results.append (app_uri, app.get_icon().to_string(), group_id,
 
742
          results.append (app_uri, app.get_icon().to_string(), category_id,
751
743
                          "application/x-desktop", app.get_display_name (),
752
744
                          app.get_description ());
753
745
        }