~dobey/unity-scope-click/finite-search

« back to all changes in this revision

Viewing changes to src/utils.vala

  • Committer: Rodney Dawes
  • Date: 2013-10-08 20:25:26 UTC
  • mfrom: (60.2.12 trunk)
  • Revision ID: rodney.dawes@canonical.com-20131008202526-zxhoxi6nh3xmsijk
[ Alejandro J. Cura ]
* Pass the publisher field if available to the app preview. (LP:
  #1226265)
* Include the framework in the search query. (LP: #1234255)
* Catch more download errors, and ask for credentials on 401. (LP:
  #1234742)
[ Ubuntu daily release ]
* Automatic snapshot from revision 70
[ Alejandro J. Cura ]
* Do not show suggested apps when internet search is off. (LP:
  #1231378)
* Don't show Uninstall button if manifest has _removable:0, and remove
  pin-to-launcher. (LP: #1233641, #1233653)
* Show download manager failures. (LP: #1226021)
* Ask for confirmation before uninstall . (LP: #1233643)
[ Rodney Dawes ]
* Remove the fake ratings and reviews data from the app previews. (LP:
  #1209213)
* Remove the noauth=1 appendage to the URL.
* Refactor the error handling, to separate credentials errors from
  other errors. Show a "Go to Accounts" button in the credentials
  error preview. (LP: #1231517)
* Don't add the Install button, if there was an error. (LP: #1233169)
[ Ubuntu daily release ]
* Automatic snapshot from revision 66

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010-2013 Canonical Ltd
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License version 3 as
 
6
 * published by the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License
 
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 *
 
16
 * Authored by Michal Hruby <michal.hruby@canonical.com>
 
17
 *
 
18
 */
 
19
 
 
20
namespace Utils
 
21
{
 
22
  private static Dee.ICUTermFilter icu_filter;
 
23
 
 
24
  public Dee.Index prepare_index (Dee.Model model,
 
25
                                  uint sort_column,
 
26
                                  owned Dee.ModelReaderFunc reader_func,
 
27
                                  out Dee.Analyzer out_analyzer)
 
28
  {
 
29
    // reuse the icu_filter
 
30
    if (icu_filter == null)
 
31
    {
 
32
      icu_filter = new Dee.ICUTermFilter.ascii_folder ();
 
33
    }
 
34
 
 
35
    var sort_filter = Dee.Filter.new_collator (sort_column);
 
36
    var filter_model = new Dee.FilterModel (model, sort_filter);
 
37
 
 
38
    var analyzer = new Dee.TextAnalyzer ();
 
39
    analyzer.add_term_filter ((terms_in, terms_out) =>
 
40
    {
 
41
      for (uint i = 0; i < terms_in.num_terms (); i++)
 
42
      {
 
43
        unowned string term = terms_in.get_term (i);
 
44
        var folded = icu_filter.apply (term);
 
45
        terms_out.add_term (term);
 
46
        if (folded != term) terms_out.add_term (folded);
 
47
      }
 
48
    });
 
49
    out_analyzer = analyzer;
 
50
 
 
51
    var reader = Dee.ModelReader.new ((owned) reader_func);
 
52
    return new Dee.TreeIndex (filter_model, analyzer, reader);
 
53
  }
 
54
 
 
55
  public SList<Dee.ModelIter> search_index (Dee.Index index,
 
56
                                            Dee.Analyzer analyzer,
 
57
                                            string query)
 
58
  {
 
59
    if (query.strip ().length == 0)
 
60
    {
 
61
      var model = index.get_model ();
 
62
      var iter = model.get_first_iter ();
 
63
      var end_iter = model.get_last_iter ();
 
64
 
 
65
      var result = new SList<Dee.ModelIter> ();
 
66
      while (iter != end_iter)
 
67
      {
 
68
        result.prepend (iter);
 
69
        iter = model.next (iter);
 
70
      }
 
71
      result.reverse ();
 
72
      return result;
 
73
    }
 
74
 
 
75
    var term_list = Object.new (typeof (Dee.TermList)) as Dee.TermList;
 
76
    analyzer.tokenize (query, term_list);
 
77
    var matches = new Sequence<Dee.ModelIter> ();
 
78
 
 
79
    uint num_terms = term_list.num_terms ();
 
80
    for (uint i = 0; i < num_terms; i++)
 
81
    {
 
82
      var rs = index.lookup (term_list.get_term (i),
 
83
                             i < num_terms - 1 ? Dee.TermMatchFlag.EXACT : Dee.TermMatchFlag.PREFIX);
 
84
 
 
85
      bool first_pass = i == 0;
 
86
      CompareDataFunc<Dee.ModelIter> cmp_func = (a, b) =>
 
87
      {
 
88
        return a == b ? 0 : ((void*) a > (void*) b ? 1 : -1);
 
89
      };
 
90
      // intersect the results (cause we want to AND the terms)
 
91
      var remaining = new Sequence<Dee.ModelIter> ();
 
92
      foreach (var item in rs)
 
93
      {
 
94
        if (first_pass)
 
95
          matches.insert_sorted (item, cmp_func);
 
96
        else if (matches.lookup (item, cmp_func) != null)
 
97
          remaining.insert_sorted (item, cmp_func);
 
98
      }
 
99
      if (!first_pass) matches = (owned) remaining;
 
100
      // final result set empty already?
 
101
      if (matches.get_begin_iter () == matches.get_end_iter ()) break;
 
102
    }
 
103
 
 
104
    var result = new SList<Dee.ModelIter> ();
 
105
    var iter = matches.get_begin_iter ();
 
106
    var end_iter = matches.get_end_iter ();
 
107
    while (iter != end_iter)
 
108
    {
 
109
      result.prepend (iter.get ());
 
110
      iter = iter.next ();
 
111
    }
 
112
 
 
113
    result.reverse ();
 
114
    return result;
 
115
  }
 
116
}