~kamstrup/unity-lens-music/sorted-filters

« back to all changes in this revision

Viewing changes to src/simple-scope.vala

  • Committer: Alex Launi
  • Date: 2011-09-08 15:16:02 UTC
  • mfrom: (32.2.5 u1)
  • Revision ID: alex.launi@canonical.com-20110908151602-5vksqicwq07xucoh
merge scope simplification branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2011 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 Alex Launi <alex.launi@canonical.com>
 
17
 *
 
18
 */
 
19
 
 
20
using GLib;
 
21
 
 
22
namespace Unity.MusicLens
 
23
{
 
24
  public abstract class SimpleScope : Object
 
25
  {
 
26
    public Unity.Scope Scope { get; protected set; }
 
27
 
 
28
    protected abstract int num_results_without_search { get; }
 
29
    protected abstract int num_results_global_search { get; }
 
30
    protected abstract int num_results_lens_search { get; }
 
31
 
 
32
    protected abstract void perform_search (LensSearch? search, Dee.Model results_model, List<Filter> filters, int max_results = -1);
 
33
    
 
34
    protected bool is_dirty;
 
35
    protected LensSearch? previous_search;
 
36
 
 
37
    public SimpleScope ()
 
38
    {
 
39
      is_dirty = true;
 
40
      previous_search = null;
 
41
 
 
42
      /* Listen for filter changes */
 
43
      Scope.filters_changed.connect(
 
44
                                    () => { 
 
45
                                      if (Scope.active_search != null)
 
46
                                        {
 
47
                                          is_dirty = true;
 
48
                                          Scope.notify_property ("active-search");
 
49
                                        }
 
50
                                    }
 
51
                                    );
 
52
 
 
53
      /* Listen for changes to the lens search entry */
 
54
      Scope.notify["active-search"].connect (
 
55
                                             (obj, pspec) => { 
 
56
                                               var search = Scope.active_search;
 
57
                                               if (!(is_dirty || search_has_really_changed (previous_search, search)))
 
58
                                                 return;
 
59
                                               is_dirty = false;
 
60
                                               update_search_async.begin (search);
 
61
                                               previous_search = search;
 
62
                                             }
 
63
                                             );
 
64
 
 
65
      /* Listen for changes to the global search */
 
66
      Scope.notify["active-global-search"].connect (
 
67
                                                    (obj, pspec) => { 
 
68
                                                      var search = Scope.active_global_search;
 
69
                                                      
 
70
                                                      if (search_is_invalid (search))
 
71
                                                        return;
 
72
 
 
73
                                                      if (!search_has_really_changed (previous_search, search))
 
74
                                                        return;
 
75
 
 
76
                                                      update_global_search_async.begin (search);
 
77
                                                      previous_search = search;
 
78
                                                    }
 
79
                                                    );
 
80
    }
 
81
 
 
82
    /* based on the filters(?) get the default results to show when the music lens is
 
83
     * just opened without filters, like when someone hits Super+M
 
84
     */
 
85
    private async void update_without_search_async (LensSearch search)
 
86
    {
 
87
      perform_search_async.begin (search, num_results_without_search);
 
88
    }
 
89
    
 
90
    /**
 
91
     * results for a global search from just hitting Super. here we want to return
 
92
     * a smaller number of results with 0 filters.
 
93
     */
 
94
    private async void update_global_search_async (LensSearch search)
 
95
    {
 
96
      var results_model = Scope.global_results_model;
 
97
      
 
98
      if (search_is_invalid (search))
 
99
        {
 
100
          results_model.clear ();
 
101
          return;
 
102
        }
 
103
      
 
104
      perform_search_async.begin (search, num_results_global_search);
 
105
    }
 
106
    
 
107
    private async void update_search_async (LensSearch search)
 
108
    {
 
109
      // just pretend like there's no search
 
110
      if (search_is_invalid (search))
 
111
        {
 
112
          update_without_search_async.begin (search);
 
113
          return;
 
114
        }
 
115
      
 
116
      perform_search_async.begin (search, num_results_lens_search);
 
117
    }
 
118
 
 
119
    private async void perform_search_async (LensSearch search, int max_results)
 
120
    {
 
121
      var results_model = Scope.results_model;
 
122
            
 
123
      /* Prevent concurrent searches and concurrent updates of our models,
 
124
       * by preventing any notify signals from propagating to us.
 
125
       * Important: Remeber to thaw the notifys again! */
 
126
      List<Filter> filters = new List<Filter> ();
 
127
      Filter filter = Scope.get_filter ("genre");
 
128
      if (filter.filtering)
 
129
        filters.append (filter);
 
130
 
 
131
      filter = Scope.get_filter ("decade");
 
132
      if (filter.filtering)
 
133
        filters.append (filter);
 
134
 
 
135
      Scope.freeze_notify ();
 
136
      
 
137
      results_model.clear ();
 
138
      perform_search (search, results_model, filters, max_results);
 
139
      
 
140
      /* Allow new searches once we enter an idle again.
 
141
       * We don't do it directly from here as that could mean we start
 
142
       * changing the model even before we had flushed out current changes
 
143
       */
 
144
      Idle.add (() => {
 
145
          Scope.thaw_notify ();
 
146
          return false;
 
147
        });
 
148
      
 
149
      search.finished ();
 
150
    }
 
151
 
 
152
    private bool search_is_invalid (LensSearch? search)
 
153
    {
 
154
      /* This boolean expression is unfolded as we seem to get
 
155
       * some null dereference if we join them in a big || expression */
 
156
      if (search == null)
 
157
        return true;
 
158
      else if (search.search_string == null)
 
159
        return true;
 
160
      
 
161
      return search.search_string.strip() == "";
 
162
    }
 
163
    
 
164
    private bool search_has_really_changed (LensSearch? old_search,
 
165
                                            LensSearch? new_search)
 
166
    {
 
167
      if (old_search == null && new_search == null)
 
168
        return false;
 
169
      
 
170
      string s1, s2;
 
171
      
 
172
      if (old_search == null)
 
173
        {
 
174
          s1 = new_search.search_string;
 
175
          if (s1 == null || s1.strip() == "")
 
176
            return false;
 
177
          else
 
178
            return true;
 
179
        }
 
180
      else if (new_search == null)
 
181
        {
 
182
          s2 = old_search.search_string;
 
183
          if (s2 == null || s2.strip() == "")
 
184
            return false;
 
185
          else
 
186
            return true;
 
187
        }
 
188
      else
 
189
        {
 
190
          s1 = new_search.search_string;
 
191
          s2 = old_search.search_string;
 
192
          if (s1 == null)
 
193
            {
 
194
              if (s2 == null || s2.strip() == "")
 
195
                return false;
 
196
              else
 
197
                return true;
 
198
            }
 
199
          else if (s2 == null)
 
200
            {
 
201
              if (s1 == null || s1.strip() == "")
 
202
                return false;
 
203
              else
 
204
                return true;
 
205
            }
 
206
          else
 
207
            return s1.strip () != s2.strip ();
 
208
        }
 
209
    }
 
210
  }
 
211
}