~unity-team/unity-lens-files/unity-lens-files-5.0

« back to all changes in this revision

Viewing changes to src/daemon.vala

  • Committer: Tarmac
  • Author(s): Michal Hruby
  • Date: 2012-01-30 10:14:12 UTC
  • mfrom: (206.1.5 unity-lens-files)
  • Revision ID: tarmac-20120130101412-4d6ga6tvkcoec96x
Support selection of multiple filters at once, also simplify various code paths. UNBLOCK. Fixes: https://bugs.launchpad.net/bugs/841847. Approved by Mikkel Kamstrup Erlandsen.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 * Authored by Mikkel Kamstrup Erlandsen <mikkel.kamstrup@canonical.com>
17
17
 *
18
18
 */
19
 
using Dee;
20
19
using Zeitgeist;
21
20
using Zeitgeist.Timestamp;
22
21
using Config;
42
41
     * we use to query Zeitgeist */
43
42
    private HashTable<string, Event> type_templates;
44
43
 
45
 
    /* Keep track of the previous search, so we can determine when to
46
 
     * filter down the result set instead of rebuilding it */
47
 
    private LensSearch? previous_search;
48
 
    
49
44
    construct
50
45
    {
51
46
      prepare_type_templates();
62
57
      populate_filters();
63
58
      lens.add_local_scope (scope);
64
59
      
65
 
      previous_search = null;
66
 
      
67
60
      /* Bring up Zeitgeist interfaces */
68
61
      log = new Zeitgeist.Log();
69
62
      index = new Zeitgeist.Index();
145
138
 
146
139
      /* Type filter */
147
140
      {
148
 
        var filter = new RadioOptionFilter ("type", _("Type"));
 
141
        var filter = new CheckOptionFilter ("type", _("Type"));
149
142
        filter.sort_type = OptionsFilter.SortType.DISPLAY_NAME;
150
143
 
151
144
        filter.add_option ("documents", _("Documents"));
210
203
      type_templates = new HashTable<string, Event> (str_hash, str_equal);
211
204
      Event event;
212
205
 
213
 
      /* HACK ALERT: All the (event as GLib.Object).ref() are needed because
214
 
       *             GPtrArray doesn't grab a ref to the event objects */
215
 
 
216
206
      /* Section.ALL_FILES */
217
207
      event = new Event.full("", ZG_USER_ACTIVITY, "",
218
208
                             new Subject.full ("file:*",
219
209
                                               "", "", "", "", "", ""));
220
 
      type_templates.insert ("all", (event as GLib.Object).ref() as Event);
 
210
      type_templates["all"] = event;
221
211
      
222
212
      /* Section.DOCUMENTS */
223
213
      event = new Event.full("", ZG_USER_ACTIVITY, "",
227
217
                             new Subject.full ("file:*",
228
218
                                               "!"+NFO_PRESENTATION,
229
219
                                               "", "", "", "", ""));
230
 
      type_templates.insert ("documents", (event as GLib.Object).ref() as Event);
 
220
      type_templates["documents"] = event;
231
221
 
232
222
      /* Section.FOLDERS
233
223
       * - we're using special ORIGIN queries here */
234
224
      event = new Event.full("", ZG_USER_ACTIVITY, "",
235
225
                             new Subject.full ("file:*",
236
226
                                               "", "", "", "", "", ""));
237
 
      type_templates.insert ("folders", (event as GLib.Object).ref() as Event);
 
227
      type_templates["folders"] = event;
238
228
 
239
229
      /* Section.IMAGES */
240
230
      event = new Event.full("", ZG_USER_ACTIVITY, "",
241
231
                             new Subject.full ("file:*",
242
232
                                               NFO_IMAGE, "", "", "", "", ""));
243
 
      type_templates.insert ("images", (event as GLib.Object).ref() as Event);
 
233
      type_templates["images"] = event;
244
234
      
245
235
      /* Section.AUDIO */
246
236
      event = new Event.full("", ZG_USER_ACTIVITY, "",
247
237
                             new Subject.full ("file:*",
248
238
                                               NFO_AUDIO, "", "", "", "", ""));
249
 
      type_templates.insert ("audio", (event as GLib.Object).ref() as Event);
 
239
      type_templates["audio"] = event;
250
240
 
251
241
      /* Section.VIDEOS */
252
242
      event = new Event.full("", ZG_USER_ACTIVITY, "",
253
243
                             new Subject.full ("file:*",
254
244
                                               NFO_VIDEO, "", "", "", "", ""));
255
 
      type_templates.insert ("videos", (event as GLib.Object).ref() as Event);
 
245
      type_templates["videos"] = event;
256
246
 
257
247
      /* Section.PRESENTATIONS
258
248
       * FIXME: Zeitgeist logger needs to user finer granularity
261
251
      event = new Event.full("", ZG_USER_ACTIVITY, "",
262
252
                             new Subject.full ("file:*",
263
253
                                               NFO_PRESENTATION, "", "", "", "", ""));
264
 
      type_templates.insert ("presentations", (event as GLib.Object).ref() as Event);
 
254
      type_templates["presentations"] = event;
265
255
 
266
256
      /* Section.OTHER 
267
257
       * Note that subject templates are joined with logical AND */
284
274
                                           "!"+NFO_PRESENTATION,
285
275
                                           "",
286
276
                                           "", "", "", ""));
287
 
      type_templates.insert ("other", (event as GLib.Object).ref() as Event);
288
 
    }
289
 
 
290
 
    private bool search_is_invalid (LensSearch? search)
291
 
    {
292
 
      /* This boolean expression is unfolded as we seem to get
293
 
       * some null dereference if we join them in a big || expression */
294
 
      if (search == null)
295
 
        return true;
296
 
      else if (search.search_string == null)
297
 
        return true;
 
277
      type_templates["other"] = event;
 
278
    }
 
279
 
 
280
    private const string[] ALL_TYPES =
 
281
    {
 
282
      "documents",
 
283
      "folders",
 
284
      "images",
 
285
      "audio",
 
286
      "videos",
 
287
      "presentations",
 
288
      "other"
 
289
    };
 
290
 
 
291
    private GenericArray<Event> create_template (OptionsFilter? filter)
 
292
    {
 
293
      var templates = new GenericArray<Event> ();
 
294
 
 
295
      if (filter == null || !filter.filtering)
 
296
      {
 
297
        /* Section.ALL_FILES */
 
298
        templates.add (type_templates["all"]);
 
299
        return templates;
 
300
      }
 
301
 
 
302
      string[] types = {};
 
303
 
 
304
      foreach (unowned string type_id in ALL_TYPES)
 
305
      {
 
306
        var option = filter.get_option (type_id);
 
307
        if (option == null || !option.active) continue;
 
308
 
 
309
        types += type_id;
 
310
      }
 
311
 
 
312
      if (types.length == ALL_TYPES.length)
 
313
      {
 
314
        /* Section.ALL_FILES */
 
315
        templates.add (type_templates["all"]);
 
316
        return templates;
 
317
      }
 
318
 
 
319
      foreach (unowned string type_id in types)
 
320
      {
 
321
        // we need to handle folders separately
 
322
        if (type_id == "folders") continue;
 
323
 
 
324
        templates.add (type_templates[type_id]);
 
325
      }
 
326
 
 
327
      return templates;
 
328
    }
 
329
 
 
330
    private bool is_search_empty (LensSearch search)
 
331
    {
 
332
      if (search.search_string == null) return true;
298
333
      
299
 
      return search.search_string.strip() == "";
 
334
      return search.search_string.strip () == "";
300
335
    }
301
336
 
302
 
    private string prepare_search_string (LensSearch? search)
 
337
    private string prepare_search_string (LensSearch search)
303
338
    {
304
339
      var s = search.search_string;
305
340
 
322
357
    private async void update_global_search_async (LensSearch search,
323
358
                                                   Cancellable cancellable)
324
359
    {
325
 
      if (search_is_invalid (search))
326
 
        {
327
 
          yield update_global_without_search_async (search, cancellable);
328
 
          return;
329
 
        }
330
 
    
 
360
      var has_search = !is_search_empty (search);
 
361
      var results_model = search.results_model;
 
362
 
331
363
      /*
332
364
       * For global searches we collate all results under one category heading
333
365
       * called Files & Folders
334
366
       */
335
 
    
336
 
      var results_model = search.results_model;
337
 
      
338
 
      var search_string = prepare_search_string (search);
339
 
 
340
 
      var templates = new PtrArray.sized(1);
341
 
      templates.add (type_templates.lookup ("all"));
342
367
 
343
368
      try {
344
369
        /* Get results ranked by recency */
345
 
        var timer = new Timer ();
346
 
        var results = yield index.search (search_string,
347
 
                                          new Zeitgeist.TimeRange.anytime(),
348
 
                                          templates,
349
 
                                          0,
 
370
        var results = yield run_zg_query (search,
 
371
                                          new Zeitgeist.TimeRange.anytime (),
 
372
                                          ResultType.MOST_RECENT_SUBJECTS,
 
373
                                          null,
350
374
                                          20,
351
 
                                          ResultType.MOST_RECENT_SUBJECTS,
352
375
                                          cancellable);
353
376
 
354
 
        timer.stop ();
355
 
        debug ("Found %u/%u global results for search '%s' in %fms",
356
 
               results.size (), results.estimated_matches (),
357
 
               search_string, timer.elapsed()*1000);
358
 
 
359
 
 
360
377
        results_model.clear ();
361
378
 
362
 
        var checked_url = urls.check_url (search.search_string);
363
 
        if (checked_url != null)
 
379
        /* check if the thing typed isn't a url (like facebook.com) */
 
380
        if (has_search)
 
381
        {
 
382
          var checked_url = urls.check_url (search.search_string);
 
383
          if (checked_url != null)
364
384
          {
365
385
            results_model.append (checked_url, urls.icon,
366
386
                                  Categories.FILES_AND_FOLDERS,
367
387
                                  "text/html", search.search_string,
368
388
                                  checked_url, checked_url);
369
389
          }
370
 
        
371
 
        int64 min_size, max_size;
372
 
        get_current_size_limits (out min_size, out max_size);
 
390
        }
373
391
 
374
392
        Unity.FilesLens.append_events_sorted (results, results_model,
375
 
                                              min_size, max_size, false,
 
393
                                              0, int64.MAX, false,
376
394
                                              Categories.FILES_AND_FOLDERS);
377
 
        
 
395
 
378
396
        /* Add downloads catagory if we don't have a search */
379
 
        if (search_is_invalid (search))
 
397
        if (has_search == false)
380
398
        {
381
399
          yield update_downloads_async (results_model, cancellable,
382
400
                                        search.search_string,
394
412
    private async void update_search_async (LensSearch search,
395
413
                                            Cancellable cancellable)
396
414
    {
397
 
      if (search_is_invalid (search))
398
 
        {
399
 
          yield update_without_search_async (search, cancellable);
400
 
          return;
401
 
        }
402
 
 
403
415
      var results_model = search.results_model;
404
 
 
405
 
      var search_string = prepare_search_string (search);
406
 
 
407
 
      string type_id = get_current_type ();
408
 
 
409
 
      bool origin_grouping = type_id == "folders";
410
 
      var result_type = origin_grouping ? ResultType.MOST_RECENT_ORIGIN
411
 
                                        : ResultType.MOST_RECENT_SUBJECTS;
412
 
 
413
 
      /* Grab the pre-compiled template we're going to use */
414
 
      var templates = new PtrArray.sized(1);
415
 
      templates.add (type_templates.lookup (type_id));
416
 
 
417
 
      try {
 
416
      var txn = new Dee.Transaction (results_model);
 
417
      var has_search = !is_search_empty (search);
 
418
 
 
419
      var filter = scope.get_filter ("type") as OptionsFilter;
 
420
 
 
421
      var active_filters = get_current_types ();
 
422
      bool only_folders = active_filters != null &&
 
423
        active_filters.length == 1 && active_filters[0] == "folders";
 
424
      uint timer_id = 0;
 
425
 
 
426
      try
 
427
      {
418
428
        /* Get results ranked by recency */
419
 
        var timer = new Timer ();
420
 
        var results = yield index.search (search_string,
421
 
                                          get_current_timerange (),
422
 
                                          templates,
423
 
                                          0,
424
 
                                          50,
425
 
                                          result_type,
426
 
                                          cancellable);
427
 
 
428
 
        timer.stop ();
429
 
        debug ("Found %u/%u results for search '%s' in %fms",
430
 
               results.size (), results.estimated_matches (),
431
 
               search_string, timer.elapsed()*1000);
432
 
 
433
 
        results_model.clear ();
434
 
 
435
 
        var checked_url = urls.check_url (search.search_string);
436
 
        if (checked_url != null)
 
429
        ResultSet? results = null;
 
430
        if (!only_folders)
 
431
        {
 
432
          results = yield run_zg_query (search,
 
433
                                        get_current_timerange (),
 
434
                                        ResultType.MOST_RECENT_SUBJECTS,
 
435
                                        filter,
 
436
                                        50,
 
437
                                        cancellable);
 
438
        }
 
439
 
 
440
        txn.clear ();
 
441
 
 
442
        /* check if the thing typed isn't a url (like facebook.com) */
 
443
        if (has_search)
 
444
        {
 
445
          var checked_url = urls.check_url (search.search_string);
 
446
          if (checked_url != null)
437
447
          {
438
 
            results_model.append (checked_url, urls.icon, Categories.RECENT,
439
 
                                  "text/html", search.search_string,
440
 
                                  checked_url, checked_url);
 
448
            txn.append (checked_url, urls.icon, Categories.RECENT,
 
449
                        "text/html", search.search_string,
 
450
                        checked_url, checked_url);
441
451
          }
442
 
 
443
 
        var bookmark_matches = bookmarks.prefix_search (search.search_string);
444
 
        append_bookmarks (bookmark_matches, results_model, Categories.FOLDERS);
445
 
 
 
452
        }
 
453
 
 
454
        /* apply filters to results found by zeitgeist */
446
455
        int64 min_size, max_size;
447
456
        get_current_size_limits (out min_size, out max_size);
448
457
 
449
 
        Unity.FilesLens.append_events_sorted (results, results_model,
450
 
                                              min_size, max_size,
451
 
                                              origin_grouping);
 
458
        if (results != null)
 
459
        {
 
460
          Unity.FilesLens.append_events_sorted (results, txn,
 
461
                                                min_size, max_size,
 
462
                                                false);
 
463
        }
452
464
 
453
 
        yield update_downloads_async (results_model, cancellable,
 
465
        /* get recently downloaded files */
 
466
        yield update_downloads_async (txn, cancellable,
454
467
                                      search.search_string);
455
468
 
 
469
        /* commit if the origin query is taking too long, if we committed right
 
470
         * away, we'd cause flicker */
 
471
        if (txn.get_n_rows () > 0)
 
472
        {
 
473
          /* here be something magical */
 
474
          timer_id = Timeout.add (200, () =>
 
475
          {
 
476
            if (!cancellable.is_cancelled () && !txn.is_committed ())
 
477
            {
 
478
              txn.commit ();
 
479
            }
 
480
            timer_id = 0;
 
481
            return false;
 
482
          });
 
483
        }
 
484
 
 
485
        /* folders are last category we need, update the model directly */
 
486
        if (filter == null ||
 
487
            !filter.filtering || filter.get_option ("folders").active)
 
488
        {
 
489
          results = yield run_zg_query (search, get_current_timerange (),
 
490
                                        ResultType.MOST_RECENT_ORIGIN,
 
491
                                        null, 50, cancellable);
 
492
 
 
493
          if (!txn.is_committed ()) txn.commit ();
 
494
 
 
495
          /* add bookmarks first */
 
496
          append_bookmarks (has_search ?
 
497
            bookmarks.prefix_search (search.search_string) : bookmarks.list (),
 
498
            results_model,
 
499
            Categories.FOLDERS);
 
500
 
 
501
          Unity.FilesLens.append_events_sorted (results, results_model,
 
502
                                                min_size, max_size,
 
503
                                                true);
 
504
        }
 
505
        else
 
506
        {
 
507
          /* just commit */
 
508
          if (!txn.is_committed ()) txn.commit ();
 
509
        }
 
510
 
456
511
      } catch (IOError.CANCELLED ioe) {
457
512
        return;
458
513
      } catch (GLib.Error e) {
 
514
        /* if we weren't cancelled, commit the transaction */
459
515
        warning ("Error performing global search '%s': %s",
460
516
                 search.search_string, e.message);
 
517
        if (!txn.is_committed ()) txn.commit ();
 
518
      } finally {
 
519
        if (timer_id != 0) Source.remove (timer_id);
461
520
      }
462
521
    }
463
522
 
464
 
    private string get_current_type ()
 
523
    private string[]? get_current_types ()
465
524
    {
466
 
      /* Get the current type to filter by */
467
 
      var filter = scope.get_filter ("type") as RadioOptionFilter;
468
 
      Unity.FilterOption? option =  filter.get_active_option ();
469
 
      return option == null ? "all" : option.id;
 
525
      /* returns null if the filter is disabled / all options selected */
 
526
      var filter = scope.get_filter ("type") as CheckOptionFilter;
 
527
 
 
528
      if (filter == null || !filter.filtering) return null;
 
529
      string[] types = {};
 
530
 
 
531
      foreach (unowned string type_id in ALL_TYPES)
 
532
      {
 
533
        var option = filter.get_option (type_id);
 
534
        if (option == null || !option.active) continue;
 
535
 
 
536
        types += type_id;
 
537
      }
 
538
 
 
539
      if (types.length == ALL_TYPES.length) return null;
 
540
 
 
541
      return types;
470
542
    }
471
543
 
472
544
    private TimeRange get_current_timerange ()
556
628
      }
557
629
    }
558
630
 
559
 
    private async void update_without_search_async (LensSearch search,
560
 
                                                    Cancellable cancellable)
561
 
    {
562
 
      var results_model = search.results_model;
563
 
 
564
 
      string type_id = get_current_type ();
565
 
 
566
 
      bool origin_grouping = type_id == "folders";
567
 
      var result_type = origin_grouping ? ResultType.MOST_RECENT_ORIGIN
568
 
                                        : ResultType.MOST_RECENT_SUBJECTS;
569
 
 
570
 
 
571
 
      /* Grab the pre-compiled template we're going to use */
572
 
      var templates = new PtrArray.sized(1);
573
 
      templates.add (type_templates.lookup (type_id));
574
 
 
575
 
      try {
576
 
        /* Get results ranked by recency */
577
 
        var timer = new Timer ();
578
 
        var results = yield log.find_events (get_current_timerange (),
579
 
                                             templates,
580
 
                                             Zeitgeist.StorageState.ANY,
581
 
                                             100,
582
 
                                             result_type,
583
 
                                             cancellable);
584
 
 
585
 
        timer.stop ();
586
 
        debug ("Found %u/%u no search results in %fms",
587
 
               results.size (), results.estimated_matches (),
588
 
               timer.elapsed()*1000);
589
 
 
590
 
        results_model.clear ();
591
 
 
592
 
        if (type_id == "all" || type_id == "folders")
593
 
        {
594
 
          append_bookmarks (bookmarks.list (), results_model, Categories.FOLDERS);
595
 
        }
596
 
 
597
 
        int64 min_size, max_size;
598
 
        get_current_size_limits (out min_size, out max_size);
599
 
 
600
 
        Unity.FilesLens.append_events_sorted (results, results_model,
601
 
                                              min_size, max_size,
602
 
                                              origin_grouping);
603
 
 
604
 
        yield update_downloads_async (results_model, cancellable);
605
 
 
606
 
      } catch (IOError.CANCELLED ioe) {
607
 
        return;
608
 
      } catch (GLib.Error e) {
609
 
        warning ("Error performing empty search: %s",
610
 
                 e.message);
611
 
      }
612
 
    }
613
 
    
614
 
    private async void update_global_without_search_async (LensSearch search,
615
 
                                                           Cancellable cancellable)
616
 
    {
617
 
      var results_model = search.results_model;
618
 
 
619
 
      /* Grab the pre-compiled template we're going to use */
620
 
      var templates = new PtrArray.sized(1);
621
 
      templates.add (type_templates.lookup ("all"));
622
 
 
623
 
      try {
624
 
        /* Get results ranked by recency */
625
 
        var timer = new Timer ();
626
 
        var results = yield log.find_events (new Zeitgeist.TimeRange.anytime(),
627
 
                                             templates,
628
 
                                             Zeitgeist.StorageState.ANY,
629
 
                                             20,
630
 
                                             ResultType.MOST_RECENT_SUBJECTS,
631
 
                                             cancellable);
632
 
 
633
 
        timer.stop ();
634
 
        debug ("Found %u/%u global results in %fms",
635
 
               results.size (), results.estimated_matches (),
636
 
               timer.elapsed()*1000);
637
 
 
638
 
        results_model.clear ();
639
 
 
640
 
        Unity.FilesLens.append_events_sorted (results, results_model,
641
 
                                              int64.MIN, int64.MAX,
642
 
                                              false, Categories.RECENT_FILES);
643
 
 
644
 
        yield update_downloads_async (results_model, cancellable);
645
 
        
646
 
      } catch (IOError.CANCELLED ioe) {
647
 
        return;
648
 
      } catch (GLib.Error e) {
649
 
        warning ("Error performing empty search: %s",
650
 
                 e.message);
651
 
      }
 
631
    private async ResultSet run_zg_query (LensSearch search,
 
632
                                          TimeRange time_range,
 
633
                                          ResultType result_type,
 
634
                                          OptionsFilter? filters,
 
635
                                          uint num_results,
 
636
                                          Cancellable cancellable) throws Error
 
637
    {
 
638
      ResultSet results;
 
639
      var timer = new Timer ();
 
640
      var templates = create_template (filters);
 
641
 
 
642
      /* Copy the templates to a PtrArray which libzg expects */
 
643
      var ptr_arr = new PtrArray ();
 
644
      for (int i = 0; i < templates.length; i++)
 
645
      {
 
646
        ptr_arr.add (templates[i]);
 
647
      }
 
648
 
 
649
      /* Get results ranked by recency */
 
650
      if (is_search_empty (search))
 
651
      {
 
652
        results = yield log.find_events (time_range,
 
653
                                         (owned) ptr_arr,
 
654
                                         Zeitgeist.StorageState.ANY,
 
655
                                         num_results,
 
656
                                         result_type,
 
657
                                         cancellable);
 
658
      }
 
659
      else
 
660
      {
 
661
        var search_string = prepare_search_string (search);
 
662
 
 
663
        results = yield index.search (search_string,
 
664
                                      time_range,
 
665
                                      (owned) ptr_arr,
 
666
                                      0, // offset
 
667
                                      num_results,
 
668
                                      result_type,
 
669
                                      cancellable);
 
670
      }
 
671
 
 
672
      debug ("Found %u/%u no search results in %fms",
 
673
             results.size (), results.estimated_matches (),
 
674
             timer.elapsed()*1000);
 
675
 
 
676
      return results;
652
677
    }
653
678
 
654
679
    private void append_bookmarks (GLib.List<Bookmark> bookmarks,
709
734
          continue;
710
735
 
711
736
        // check if type matches
712
 
        var type_id = get_current_type ();
713
 
        if (type_id != "all" && !Utils.file_info_matches_type (info, type_id))
 
737
        var types = get_current_types ();
 
738
        if (types != null && !Utils.file_info_matches_any (info, types))
714
739
          continue;
715
740
        
716
741
        // check if size is within bounds
762
787
                                    bool use_origin,
763
788
                                    int category_override = -1)
764
789
  {
765
 
     foreach (var ev in events)
 
790
    foreach (var ev in events)
 
791
    {
 
792
      if (ev.num_subjects() > 0)
766
793
      {
767
 
        if (ev.num_subjects() > 0)
768
 
          {
769
 
            // FIXME: We only use the first subject...
770
 
            Zeitgeist.Subject su = ev.get_subject(0);
771
 
 
772
 
            string uri;
773
 
            string display_name;
774
 
            string mimetype;
775
 
 
776
 
            if (use_origin)
777
 
            {
778
 
              uri = su.get_origin ();
779
 
              display_name = "";
780
 
              mimetype = "inode/directory";
781
 
            }
782
 
            else
783
 
            {
784
 
              uri = su.get_uri ();
785
 
              display_name = su.get_text ();
786
 
              mimetype = su.get_mimetype ();
787
 
              mimetype = su.get_mimetype () != null ?
788
 
                         su.get_mimetype () : "application/octet-stream";
789
 
            }
790
 
            if (uri == null) continue;
791
 
            File file = File.new_for_uri (uri);
792
 
 
793
 
            if (display_name == null || display_name == "")
794
 
            {
795
 
              display_name = Path.get_basename (file.get_parse_name ());
796
 
            }
797
 
 
798
 
            bool check_size = min_size > 0 || max_size < int64.MAX;
799
 
            /* Don't check existence on non-native files as http:// and
800
 
             * friends are *very* expensive to query */
801
 
            if (file.is_native()) {
802
 
              // hidden files should be ignored
803
 
              try {
804
 
                FileInfo info = file.query_info (check_size ?
805
 
                  ATTR_SIZE_AND_HIDDEN : ATTR_HIDDEN, 0, null);
806
 
                if (info.get_is_hidden())
807
 
                  continue;
808
 
                if (check_size &&
809
 
                  (info.get_size () < min_size || info.get_size () > max_size))
810
 
                {
811
 
                  continue;
812
 
                }
813
 
              } catch (GLib.Error e) {
814
 
                // as error occurred file must be missing therefore ignoring it
815
 
                continue;
816
 
              }
817
 
            }
818
 
            string icon = Utils.get_icon_for_uri (uri, mimetype);
819
 
 
820
 
            uint category_id;
821
 
            string comment = file.get_parse_name ();
 
794
        // FIXME: We only use the first subject...
 
795
        Zeitgeist.Subject su = ev.get_subject(0);
 
796
 
 
797
        string uri;
 
798
        string display_name;
 
799
        string mimetype;
 
800
 
 
801
        if (use_origin)
 
802
        {
 
803
          uri = su.get_origin ();
 
804
          display_name = "";
 
805
          mimetype = "inode/directory";
 
806
        }
 
807
        else
 
808
        {
 
809
          uri = su.get_uri ();
 
810
          display_name = su.get_text ();
 
811
          mimetype = su.get_mimetype ();
 
812
          mimetype = su.get_mimetype () != null ?
 
813
                     su.get_mimetype () : "application/octet-stream";
 
814
        }
 
815
        if (uri == null) continue;
 
816
        File file = File.new_for_uri (uri);
 
817
 
 
818
        if (display_name == null || display_name == "")
 
819
        {
 
820
          display_name = Path.get_basename (file.get_parse_name ());
 
821
        }
 
822
 
 
823
        bool check_size = min_size > 0 || max_size < int64.MAX;
 
824
        /* Don't check existence on non-native files as http:// and
 
825
         * friends are *very* expensive to query */
 
826
        if (file.is_native()) {
 
827
          // hidden files should be ignored
 
828
          try {
 
829
            FileInfo info = file.query_info (check_size ?
 
830
              ATTR_SIZE_AND_HIDDEN : ATTR_HIDDEN, 0, null);
 
831
            if (info.get_is_hidden())
 
832
              continue;
 
833
            if (check_size &&
 
834
              (info.get_size () < min_size || info.get_size () > max_size))
 
835
            {
 
836
              continue;
 
837
            }
 
838
          } catch (GLib.Error e) {
 
839
            // as error occurred file must be missing therefore ignoring it
 
840
            continue;
 
841
          }
 
842
        }
 
843
        string icon = Utils.get_icon_for_uri (uri, mimetype);
 
844
 
 
845
        uint category_id;
 
846
        string comment = file.get_parse_name ();
 
847
        
 
848
        if (category_override >= 0)
 
849
          category_id = category_override;
 
850
        else
 
851
          category_id = file.query_file_type (0, null) == FileType.DIRECTORY ?
 
852
                                     Categories.FOLDERS : Categories.RECENT;
822
853
            
823
 
            if (category_override >= 0)
824
 
              category_id = category_override;
825
 
            else
826
 
              category_id = file.query_file_type (0, null) == FileType.DIRECTORY ?
827
 
                                         Categories.FOLDERS : Categories.RECENT;
828
 
                
829
 
            results.append (uri, icon, category_id, mimetype,
830
 
                            display_name, comment);
 
854
        results.append (uri, icon, category_id, mimetype,
 
855
                        display_name, comment);
831
856
 
832
 
          }
833
857
      }
834
 
   }
 
858
    }
 
859
  }
835
860
} /* namespace */
836
861