~unity-team/unity-lens-files/trunk

« back to all changes in this revision

Viewing changes to src/utils.vala

* debian/changelog, debian/control, debian/copyright, debian/watch:
  - good bye place, welcome lens (massive rename)
  - add transitional package
  - add debian/unity-lens-files.install

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
using Gee;
23
23
using Dee;
24
24
 
25
 
namespace Unity.FilesLens.Utils {
26
 
 
27
 
    const string icon_attribs = FileAttribute.PREVIEW_ICON + "," +
28
 
                                FileAttribute.STANDARD_ICON + "," +
29
 
                                FileAttribute.THUMBNAIL_PATH;
30
 
 
31
 
    const string file_attribs = FileAttribute.STANDARD_NAME + "," +
32
 
                                FileAttribute.STANDARD_DISPLAY_NAME + "," +
33
 
                                FileAttribute.STANDARD_CONTENT_TYPE + "," +
34
 
                                FileAttribute.STANDARD_IS_HIDDEN + "," +
35
 
                                FileAttribute.STANDARD_IS_BACKUP + "," +
36
 
                                FileAttribute.STANDARD_SIZE + "," +
37
 
                                FileAttribute.TIME_MODIFIED + "," +
38
 
                                FileAttribute.TIME_ACCESS;
 
25
namespace Unity.FilesPlace.Utils {
 
26
 
 
27
    const string icon_attribs = FILE_ATTRIBUTE_PREVIEW_ICON + "," +
 
28
                                FILE_ATTRIBUTE_STANDARD_ICON + "," +
 
29
                                FILE_ATTRIBUTE_THUMBNAIL_PATH;
 
30
 
 
31
    const string file_attribs = FILE_ATTRIBUTE_STANDARD_NAME + "," +
 
32
                                FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + "," +
 
33
                                FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE + "," +
 
34
                                FILE_ATTRIBUTE_STANDARD_IS_HIDDEN + "," +
 
35
                                FILE_ATTRIBUTE_STANDARD_IS_BACKUP + "," +
 
36
                                FILE_ATTRIBUTE_TIME_MODIFIED + "," +
 
37
                                FILE_ATTRIBUTE_TIME_ACCESS;
39
38
    
40
 
    const string hide_attribs = FileAttribute.STANDARD_IS_BACKUP + "," +
41
 
                                FileAttribute.STANDARD_IS_HIDDEN;
 
39
    const string hide_attribs = FILE_ATTRIBUTE_STANDARD_IS_BACKUP + "," +
 
40
                                FILE_ATTRIBUTE_STANDARD_IS_HIDDEN;
42
41
    
43
42
    const string all_attribs = icon_attribs + "," + file_attribs + "," + hide_attribs;
44
43
 
85
84
 
86
85
    public string check_icon_string (string uri, string mimetype, FileInfo info)
87
86
    {
88
 
      Icon icon = info.get_icon ();
89
 
      string thumbnail_path = info.get_attribute_byte_string (FileAttribute.THUMBNAIL_PATH);
 
87
      Icon icon = info.get_icon();
 
88
      string thumbnail_path = info.get_attribute_byte_string (FILE_ATTRIBUTE_THUMBNAIL_PATH);
90
89
 
91
 
      if (thumbnail_path == null && icon != null)
92
 
        return icon.to_string ();
93
 
      else if (icon == null)
94
 
        return ContentType.get_icon (mimetype).to_string ();
 
90
      if (thumbnail_path == null)
 
91
        return icon.to_string();
95
92
      else
96
 
        return new FileIcon (File.new_for_path (thumbnail_path)).to_string ();
 
93
        return new FileIcon(File.new_for_path (thumbnail_path)).to_string ();
97
94
    }
98
95
    
99
 
    public int cmp_file_info_by_mtime (FileInfo info1, FileInfo info2)
100
 
    {
101
 
      TimeVal tv1, tv2;
102
 
      tv1 = info1.get_modification_time ();
103
 
      tv2 = info2.get_modification_time ();
104
 
      long cmp = tv1.tv_sec - tv2.tv_sec;
105
 
      return cmp < 0 ? 1 : ( cmp > 0 ? -1 : 0);
106
 
    }
 
96
  public int cmp_file_info_by_mtime (FileInfo info1, FileInfo info2)
 
97
  {
 
98
    TimeVal tv1, tv2;
 
99
    info1.get_modification_time (out tv1);
 
100
    info2.get_modification_time (out tv2);
 
101
    long cmp = tv1.tv_sec - tv2.tv_sec;
 
102
    return cmp < 0 ? 1 : ( cmp > 0 ? -1 : 0);
 
103
  }
107
104
 
108
105
    public string get_month_name (DateMonth month)
109
106
    {
163
160
        }
164
161
    }
165
162
    
166
 
#if 0
167
163
    /* Calculate the time group of the event returning the group id
168
164
     * of the group @event belongs to. It may be necessary for this method
169
165
     * to add a row to @groups_model if the group is one of the variadic
264
260
      else
265
261
        return Group.LAST_YEAR;
266
262
    }
267
 
#endif
268
 
 
269
 
    private async SList<FileInfo> list_dir_internal (File folder,
270
 
        string? name_filter) throws Error
 
263
  
 
264
  
 
265
    /**
 
266
     * Asynchrnously list the contents of a directory given by a path,
 
267
     * and return a list of FileInfos filled with the attributes specified
 
268
     * by Utils.all_attribs
 
269
     */
 
270
    public async SList<FileInfo> list_dir (File folder) throws Error
271
271
    {
272
 
      string? filter = null;
273
 
      if (name_filter != null) filter = name_filter.strip ().casefold ();
274
 
 
275
272
      var result = new SList<FileInfo> ();
276
273
      var e = yield folder.enumerate_children_async (Utils.all_attribs,
277
274
                                                     0, Priority.DEFAULT,
286
283
        foreach (var info in file_infos) {
287
284
          if (info.get_is_hidden() || info.get_is_backup ())
288
285
            continue;
289
 
          if (filter != null &&
290
 
            info.get_display_name ().casefold ().index_of (filter) < 0)
291
 
            continue;
292
286
          var colkey = info.get_display_name().collate_key_for_filename ();
293
287
          info.set_attribute_string ("unity::collation-key", colkey);
294
288
          result.prepend (info);
304
298
      result.sort (cmpfunc);
305
299
      return result;
306
300
    }
307
 
    /**
308
 
     * Asynchronously list the contents of a directory given by a path,
309
 
     * and return a list of FileInfos filled with the attributes specified
310
 
     * by Utils.all_attribs
311
 
     */
312
 
    public async SList<FileInfo> list_dir (File folder) throws Error
313
 
    {
314
 
      return yield list_dir_internal (folder, null);
315
 
    }
316
 
 
317
 
    /**
318
 
     * Similar to list_dir, but only return list of FileInfos matching
319
 
     * name_filter name.
320
 
     */
321
 
    public async SList<FileInfo> list_dir_filtered (File folder,
322
 
        string name_filter) throws Error
323
 
    {
324
 
      return yield list_dir_internal (folder, name_filter);
325
 
    }
326
 
 
327
 
    public bool file_info_matches_any (FileInfo info, string[] types)
328
 
    {
329
 
      foreach (unowned string type_id in types)
330
 
      {
331
 
        if (file_info_matches_type (info, type_id)) return true;
332
 
      }
 
301
    
 
302
  /* Run through @filter_set and remove any row from the result set's model
 
303
   * in which URI is not in @valid_uris */
 
304
  public void apply_uri_filter (Set<string> valid_uris,
 
305
                                Dee.ResultSet filter_set)
 
306
  {
 
307
    var model = filter_set.get_model ();
 
308
    uint n_removed = 0;
 
309
    string uri;
 
310
    
 
311
    /* Anything in filter_set that is not in the event_uris set, is removed
 
312
     * from the results_model */
 
313
    foreach (var row in filter_set)
 
314
    {
 
315
      uri = model.get_string (row, ResultsColumn.URI);
 
316
      if (!(uri in valid_uris))
 
317
        {
 
318
          model.remove (row);
 
319
          n_removed++;
 
320
          //debug ("  - %s", uri);
 
321
        }
 
322
    }
 
323
    
 
324
    if (n_removed > 0)
 
325
      debug ("Removed %u rows from result set", n_removed);
 
326
  }
 
327
  
 
328
  /* Returns true iff new_search is a query that simply restricts the
 
329
   * result set of old_query */
 
330
  public bool check_is_filter_search (PlaceSearch new_search, PlaceSearch? old_search)
 
331
  {
 
332
    bool is_filter_search = false;      
 
333
    if (old_search != null)
 
334
      {
 
335
        string previous_search_string = old_search.get_search_string();
 
336
        if (previous_search_string != null && previous_search_string != "")
 
337
          is_filter_search = new_search.get_search_string().has_prefix (
 
338
                                                      previous_search_string);
 
339
      }
 
340
    
 
341
    return is_filter_search;
 
342
  }
 
343
  
 
344
  /* Extract a hash set of all subject uris in a Zeitgeist.ResultSet */
 
345
  public Set<string> get_uri_set (Zeitgeist.ResultSet results)
 
346
  {
 
347
    Set<string> uris = new HashSet<string> ();
 
348
    
 
349
    foreach (var ev in results)
 
350
      {
 
351
        for (int i = 0; i  < ev.num_subjects(); i++)
 
352
          uris.add (ev.get_subject (i).get_uri ());
 
353
      }
 
354
    
 
355
    return uris;
 
356
  }
 
357
  
 
358
  /* Sloppy and null-safe equality checking. null == "" and strings
 
359
   * are stripped of whitespace before comparison */
 
360
  private bool search_has_really_changed (PlaceSearch? old_search,
 
361
                                          PlaceSearch? new_search)
 
362
  {
 
363
    if (old_search == null && new_search == null)
333
364
      return false;
334
 
    }
335
 
 
336
 
    public bool file_info_matches_type (FileInfo info, string type_id)
337
 
    {
338
 
      unowned string interpretation;
339
 
      unowned string content_type = info.get_content_type ();
340
 
      if (content_type == null)
341
 
        content_type = info.get_attribute_string (FileAttribute.STANDARD_FAST_CONTENT_TYPE);
342
 
 
343
 
      if (content_type == null) content_type = "application/octet-stream";
344
 
 
345
 
      interpretation = Zeitgeist.interpretation_for_mimetype (content_type);
346
 
      if (interpretation == null) return type_id == "other" || type_id == "all";
347
 
 
348
 
      /* type_id is one of: documents, folders, images, audio, videos,
349
 
       *   presentations, other */
350
 
      switch (type_id)
351
 
      {
352
 
        case "documents":
353
 
          return Zeitgeist.Symbol.is_a (interpretation, Zeitgeist.NFO.DOCUMENT)
354
 
            && !Zeitgeist.Symbol.is_a (interpretation, Zeitgeist.NFO.PRESENTATION);
355
 
        case "folders":
356
 
          return content_type == "inode/directory";
357
 
        case "images":
358
 
          return Zeitgeist.Symbol.is_a (interpretation, Zeitgeist.NFO.IMAGE);
359
 
        case "audio":
360
 
          return Zeitgeist.Symbol.is_a (interpretation, Zeitgeist.NFO.AUDIO);
361
 
        case "videos":
362
 
          return Zeitgeist.Symbol.is_a (interpretation, Zeitgeist.NFO.VIDEO);
363
 
        case "presentations":
364
 
          return Zeitgeist.Symbol.is_a (interpretation, Zeitgeist.NFO.PRESENTATION);
365
 
        case "other":
366
 
          bool is_recognized = false;
367
 
          is_recognized |= content_type == "inode/directory";
368
 
          // DOCUMENT includes PRESENTATION
369
 
          is_recognized |= Zeitgeist.Symbol.is_a (interpretation, Zeitgeist.NFO.DOCUMENT);
370
 
          // MEDIA includes AUDIO, VIDEO, IMAGE
371
 
          is_recognized |= Zeitgeist.Symbol.is_a (interpretation, Zeitgeist.NFO.MEDIA);
372
 
          return !is_recognized;
373
 
        case "all":
374
 
          return true;
375
 
        default:
376
 
          warning ("Unrecognized type: \"%s\"", type_id);
377
 
          return false;
378
 
      }
379
 
    }
380
 
    
381
 
    /* Extract a hash set of all subject uris in a Zeitgeist.ResultSet */
382
 
    public Set<string> get_uri_set (Zeitgeist.ResultSet results)
383
 
    {
384
 
      Set<string> uris = new HashSet<string> ();
385
 
      
386
 
      foreach (var ev in results)
387
 
        {
388
 
          for (int i = 0; i  < ev.num_subjects(); i++)
389
 
            uris.add (ev.get_subject (i).uri);
390
 
        }
391
 
      
392
 
      return uris;
393
 
    }
394
 
    
395
 
    public string normalize_string (string input)
396
 
    {
397
 
      return input.normalize (-1, NormalizeMode.ALL_COMPOSE).casefold ();
398
 
    }
 
365
    
 
366
    string s1, s2;
 
367
   
 
368
    if (old_search == null)
 
369
      {
 
370
        s1 = new_search.get_search_string ();
 
371
        if (s1 == null || s1.strip() == "")
 
372
          return false;
 
373
        else
 
374
          return true;
 
375
      }
 
376
    else if (new_search == null)
 
377
      {
 
378
        s2 = old_search.get_search_string ();
 
379
        if (s2 == null || s2.strip() == "")
 
380
          return false;
 
381
        else
 
382
          return true;
 
383
      }
 
384
    else
 
385
      {
 
386
        s1 = new_search.get_search_string ();
 
387
        s2 = old_search.get_search_string ();
 
388
        if (s1 == null)
 
389
          {
 
390
            if (s2 == null || s2.strip() == "")
 
391
              return false;
 
392
            else
 
393
              return true;
 
394
          }
 
395
        else if (s2 == null)
 
396
          {
 
397
            if (s1 == null || s1.strip() == "")
 
398
              return false;
 
399
            else
 
400
              return true;
 
401
          }
 
402
        else
 
403
          return s1.strip () != s2.strip ();
 
404
      }
 
405
  }
 
406
  
 
407
  public string normalize_string (string input)
 
408
  {
 
409
    return input.normalize (-1, NormalizeMode.ALL_COMPOSE).casefold ();
 
410
  }
399
411
   
400
412
} /* namespace */