~ubuntu-branches/debian/squeeze/f-spot/squeeze

« back to all changes in this revision

Viewing changes to src/PhotoQuery.cs

  • Committer: Bazaar Package Importer
  • Author(s): Iain Lane, Mirco Bauer, Iain Lane
  • Date: 2009-02-07 20:23:32 UTC
  • mfrom: (1.1.18 upstream)
  • Revision ID: james.westby@ubuntu.com-20090207202332-oc93rfjo1st0571s
Tags: 0.5.0.3-2
[ Mirco Bauer]
* Upload to unstable.
* debian/control:
  + Lowered GNOME# build-deps to 2.0 ABI as that transition didn't happen
    yet in unstable.

[ Iain Lane ]
* debian/patches/svn-r4545_locales-import.dpatch: Patch backported from SVN
  trunk revision 4545 - initialize the translation catalog earlier (LP: #293305)
  (Closes: #514457). Thanks to Florian Heinle for finding the patch and to
  Chris Coulson for preparing the update.
* debian/control: Build-depend on libmono-dev (>= 1.2.4) to match configure
  checks.
* debian/rules: Pass CSC=/usr/bin/csc to configure for gio-sharp to fix FTBFS

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
using System.Collections;
13
13
using System.Collections.Generic;
14
14
using FSpot.Query;
 
15
using FSpot.Utils;
15
16
 
16
17
namespace FSpot {
17
18
        public class PhotoQuery : FSpot.IBrowsableCollection {
18
 
                private Photo [] photos;
 
19
                class PhotoCache
 
20
                {
 
21
                        static int SIZE = 100;
 
22
                        public int Size {
 
23
                                get { return SIZE; }
 
24
                        }
 
25
 
 
26
                        Dictionary <int, Photo []> cache;
 
27
                        string temp_table;
 
28
                        PhotoStore store;
 
29
 
 
30
                        public PhotoCache (PhotoStore store, string temp_table)
 
31
                        {
 
32
                                this.temp_table = temp_table;
 
33
                                this.store = store;
 
34
                                cache = new Dictionary<int, Photo[]> ();
 
35
                        }
 
36
 
 
37
                        public bool TryGetPhoto (int index, out Photo photo)
 
38
                        {
 
39
                                photo = null;
 
40
                                Photo [] val;
 
41
                                int offset = index - index % SIZE;
 
42
                                if (!cache.TryGetValue (offset, out val))
 
43
                                        return false;
 
44
                                photo = val [index - offset];
 
45
                                return true;
 
46
                        }
 
47
 
 
48
                        public Photo Get (int index)
 
49
                        {
 
50
                                Photo [] val;
 
51
                                int offset = index - index % SIZE;
 
52
                                if (!cache.TryGetValue (offset, out val)) {
 
53
                                        val = store.QueryFromTemp (temp_table, offset, SIZE);
 
54
                                        cache [offset] = val;
 
55
                                }
 
56
                                return val [index - offset];
 
57
                        }
 
58
                }
 
59
 
 
60
                PhotoCache cache;
19
61
                private PhotoStore store;
20
62
                private Term terms;
21
63
                private Tag [] tags;
22
64
                private string extra_condition;
 
65
 
 
66
                static int query_count = 0;
 
67
                static int QueryCount {
 
68
                        get {return query_count ++;}
 
69
                }
 
70
 
 
71
                Dictionary<uint, int> reverse_lookup;
 
72
 
 
73
                int count = -1;
23
74
                
 
75
                string temp_table = String.Format ("photoquery_temp_{0}", QueryCount);
 
76
 
24
77
                // Constructor
25
 
                public PhotoQuery (PhotoStore store)
 
78
                public PhotoQuery (PhotoStore store, params IQueryCondition [] conditions)
26
79
                {
27
80
                        this.store = store;
28
81
                        // Note: this is to let the query pick up
29
82
                        //       photos that were added or removed over dbus
30
83
                        this.store.ItemsAddedOverDBus += delegate { RequestReload(); };
31
84
                        this.store.ItemsRemovedOverDBus += delegate { RequestReload(); };
32
 
 
33
 
                        photos = store.Query ((Tag [])null, null, Range, RollSet, RatingRange);
 
85
                        this.store.ItemsChanged += MarkChanged;
 
86
                        cache = new PhotoCache (store, temp_table);
 
87
                        reverse_lookup = new Dictionary<uint, int> ();
 
88
                        SetCondition (OrderByTime.OrderByTimeDesc);
 
89
 
 
90
                        foreach (IQueryCondition condition in conditions)
 
91
                                SetCondition (condition);
 
92
 
 
93
                        store.QueryToTemp (temp_table, (Tag [])null, null, Range, RollSet, RatingRange, OrderByTime);
34
94
                }
35
95
 
36
96
                public int Count {
37
 
                        get { return photos.Length;}
 
97
                        get {
 
98
                                if (count < 0)
 
99
                                        count = store.Count (temp_table);
 
100
                                return count;
 
101
                        }
38
102
                }
39
103
                
40
104
                public bool Contains (IBrowsableItem item) {
43
107
 
44
108
                // IPhotoCollection Interface
45
109
                public event FSpot.IBrowsableCollectionChangedHandler Changed;
46
 
                public event FSpot.IBrowsableCollectionChangedHandler PreChanged;
47
110
                public event FSpot.IBrowsableCollectionItemsChangedHandler ItemsChanged;
48
111
                
49
112
                public IBrowsableItem this [int index] {
50
 
                        get { return photos [index]; }
 
113
                        get { return cache.Get (index); }
51
114
                }
52
115
 
 
116
                [Obsolete ("DO NOT USE THIS, IT'S TOO SLOW")]
53
117
                public Photo [] Photos {
54
 
                        get { return photos; }
 
118
                        get { return store.QueryFromTemp (temp_table); }
55
119
                }
56
120
 
 
121
                [Obsolete ("DO NOT USE Items on PhotoQuery")]
57
122
                public IBrowsableItem [] Items {
58
 
                        get { return (IBrowsableItem [])photos; }
 
123
                        get { throw new NotImplementedException (); }
59
124
                }
60
 
                
 
125
 
61
126
                public PhotoStore Store {
62
127
                        get { return store; }
63
128
                }
64
129
                
65
 
 
66
130
                //Query Conditions
67
131
                private Dictionary<Type, IQueryCondition> conditions;
68
132
                private Dictionary<Type, IQueryCondition> Conditions {
83
147
                        return true;
84
148
                }
85
149
 
86
 
                internal IQueryCondition GetCondition<T> ()
 
150
                internal T GetCondition<T> () where T : IQueryCondition
87
151
                {
88
 
                        if (Conditions.ContainsKey (typeof (T)))
89
 
                                return Conditions [typeof (T)];
90
 
                        return null;
 
152
                        IQueryCondition val;
 
153
                        Conditions.TryGetValue (typeof (T), out val);
 
154
                        return (T)val;
91
155
                }
92
156
 
93
157
                internal bool UnSetCondition<T> ()
128
192
                }
129
193
                
130
194
                public DateRange Range {
131
 
                        get { return GetCondition<DateRange> () as DateRange; }
 
195
                        get { return GetCondition<DateRange> (); }
132
196
                        set {
133
197
                                if (value == null && UnSetCondition<DateRange> () || value != null && SetCondition (value))
134
198
                                        RequestReload ();
149
213
                }
150
214
 
151
215
                public RollSet RollSet {
152
 
                        get { return GetCondition<RollSet> () as RollSet; }
 
216
                        get { return GetCondition<RollSet> (); }
153
217
                        set {
154
218
                                if (value == null && UnSetCondition<RollSet> () || value != null && SetCondition (value))
155
219
                                        RequestReload ();
157
221
                }
158
222
 
159
223
                public RatingRange RatingRange {
160
 
                        get { return GetCondition<RatingRange> () as RatingRange; }
 
224
                        get { return GetCondition<RatingRange> (); }
161
225
                        set {
162
226
                                if (value == null && UnSetCondition<RatingRange>() || value != null && SetCondition (value))
163
227
                                        RequestReload ();
164
228
                        }
165
229
                }
166
230
 
 
231
                public OrderByTime OrderByTime {
 
232
                        get { return GetCondition<OrderByTime> (); }
 
233
                        set {
 
234
                                if (value != null && SetCondition (value))
 
235
                                        RequestReload ();
 
236
                        }
 
237
                }
 
238
 
 
239
                public bool TimeOrderAsc {
 
240
                        get { return OrderByTime.Asc; }
 
241
                        set {
 
242
                                if (value != OrderByTime.Asc)
 
243
                                        OrderByTime = new OrderByTime (value);
 
244
                        }
 
245
                }
 
246
 
167
247
                public void RequestReload ()
168
248
                {
 
249
                        uint timer = Log.DebugTimerStart ();
169
250
                        if (untagged)
170
 
                                photos = store.Query (new UntaggedCondition (), Range, RollSet, RatingRange);
 
251
                                store.QueryToTemp (temp_table, new UntaggedCondition (), Range, RollSet, RatingRange, OrderByTime);
171
252
                        else
172
 
                                photos = store.Query (terms, extra_condition, Range, RollSet, RatingRange);
 
253
                                store.QueryToTemp (temp_table, terms, extra_condition, Range, RollSet, RatingRange, OrderByTime);
173
254
 
174
 
                        //this event will allow resorting the query content
175
 
                        if (PreChanged != null)
176
 
                                PreChanged (this);
 
255
                        count = -1;
 
256
                        cache = new PhotoCache (store, temp_table);
 
257
                        reverse_lookup = new Dictionary<uint,int> ();
177
258
 
178
259
                        if (Changed != null)
179
260
                                Changed (this);
 
261
                        Log.DebugTimerPrint (timer, "Reloading the query took {0}");
180
262
                }
181
263
                
182
264
                public int IndexOf (IBrowsableItem photo)
183
265
                {
184
 
                        return System.Array.IndexOf (photos, photo);
185
 
                }
186
 
                
187
 
                public void Commit (int index) 
188
 
                {
189
 
                        store.Commit (photos[index]);
190
 
                        MarkChanged (index);
191
 
                }
192
 
                
193
 
                public void MarkChanged (int index)
194
 
                {
195
 
                        ItemsChanged (this, new BrowsableEventArgs (index));
 
266
                        if (photo == null || !(photo is Photo))
 
267
                                return -1;
 
268
                        return store.IndexOf (temp_table, photo as Photo);
 
269
                }
 
270
 
 
271
                private int [] IndicesOf (DbItem [] dbitems)
 
272
                {
 
273
                        uint timer = Log.DebugTimerStart ();
 
274
                        List<int> indices = new List<int> ();
 
275
                        List<uint> items_to_search = new List<uint> ();
 
276
                        int cur;
 
277
                        foreach (DbItem dbitem in dbitems) {
 
278
                                if (reverse_lookup.TryGetValue (dbitem.Id, out cur))
 
279
                                        indices.Add (cur);
 
280
                                else
 
281
                                        items_to_search.Add (dbitem.Id);
 
282
                        }
 
283
 
 
284
                        if (items_to_search.Count > 0)
 
285
                                indices.AddRange (store.IndicesOf (temp_table, items_to_search.ToArray ()));
 
286
                        Log.DebugTimerPrint (timer, "IndicesOf took {0}");
 
287
                        return indices.ToArray ();
 
288
                }
 
289
 
 
290
                public int LookupItem (System.DateTime date)
 
291
                {
 
292
                        return LookupItem (date, TimeOrderAsc);
 
293
                }
 
294
 
 
295
                private int LookupItem (System.DateTime date, bool asc)
 
296
                {
 
297
                        uint timer = Log.DebugTimerStart ();
 
298
                        int low = 0;
 
299
                        int high = Count - 1;
 
300
                        int mid = (low + high) / 2;
 
301
                        Photo current;
 
302
                        while (low <= high) {
 
303
                                mid = (low + high) / 2;
 
304
                                if (!cache.TryGetPhoto (mid, out current))
 
305
                                        //the item we're looking for is not in the cache
 
306
                                        //a binary search could take up to ln2 (N/cache.SIZE) request
 
307
                                        //lets reduce that number to 1
 
308
                                        return store.IndexOf (temp_table, date, asc);
 
309
 
 
310
                                int comp = this [mid].Time.CompareTo (date);
 
311
                                if (!asc && comp < 0 || asc && comp > 0)
 
312
                                        high = mid - 1;
 
313
                                else if (!asc && comp > 0 || asc && comp < 0)
 
314
                                        low = mid + 1;
 
315
                                else
 
316
                                        return mid;
 
317
                        }
 
318
                        Log.DebugTimerPrint (timer, "LookupItem took {0}");
 
319
                        if (asc)
 
320
                                return this[mid].Time < date ? mid + 1 : mid;
 
321
                        return this[mid].Time > date ? mid + 1 : mid;
 
322
 
 
323
                }
 
324
 
 
325
                public void Commit (int index)
 
326
                {
 
327
                        Commit (new int [] {index});
 
328
                }
 
329
 
 
330
                public void Commit (int [] indexes)
 
331
                {
 
332
                        List<Photo> to_commit = new List<Photo>();
 
333
                        foreach (int index in indexes) {
 
334
                                to_commit.Add (this [index] as Photo);
 
335
                                reverse_lookup [(this [index] as Photo).Id] = index;
 
336
                        }
 
337
                        store.Commit (to_commit.ToArray ());
 
338
                }
 
339
 
 
340
                private void MarkChanged (object sender, DbItemEventArgs args)
 
341
                {
 
342
                        int [] indexes = IndicesOf (args.Items);
 
343
 
 
344
                        if (indexes.Length > 0 && ItemsChanged != null)
 
345
                                ItemsChanged (this, new BrowsableEventArgs(indexes, (args as PhotoEventArgs).Changes));
 
346
                }
 
347
 
 
348
                public void MarkChanged (int index, IBrowsableItemChanges changes)
 
349
                {
 
350
                        MarkChanged (new int [] {index}, changes);
 
351
                }
 
352
 
 
353
                public void MarkChanged (int [] indexes, IBrowsableItemChanges changes)
 
354
                {
 
355
                        ItemsChanged (this, new BrowsableEventArgs (indexes, changes));
196
356
                }
197
357
        }
198
358
}