1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
4 * Copyright (C) 2007 OpenedHand Ltd
6 * Author: Matthew Allum <mallum@openedhand.com>
9 #include "aaina-library.h"
12 G_DEFINE_TYPE (AainaLibrary, aaina_library, G_TYPE_OBJECT);
14 #define LIBRARY_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), AAINA_TYPE_LIBRARY, AainaLibraryPrivate))
16 typedef struct _AainaLibraryPrivate AainaLibraryPrivate;
27 static guint _library_signals[LAST_SIGNAL] = { 0 };
29 struct _AainaLibraryPrivate
31 AainaFilterRowFunc filter;
33 AainaCompareRowFunc sort;
43 aaina_library_get_property (GObject *object, guint property_id,
44 GValue *value, GParamSpec *pspec)
46 switch (property_id) {
48 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id,
54 aaina_library_set_property (GObject *object, guint property_id,
55 const GValue *value, GParamSpec *pspec)
57 switch (property_id) {
59 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id,
65 aaina_library_dispose (GObject *object)
67 if (G_OBJECT_CLASS (aaina_library_parent_class)->dispose)
68 G_OBJECT_CLASS (aaina_library_parent_class)->dispose (object);
72 aaina_library_finalize (GObject *object)
74 G_OBJECT_CLASS (aaina_library_parent_class)->finalize (object);
78 aaina_library_class_init (AainaLibraryClass *klass)
80 GObjectClass *object_class = G_OBJECT_CLASS (klass);
82 g_type_class_add_private (klass, sizeof (AainaLibraryPrivate));
84 object_class->get_property = aaina_library_get_property;
85 object_class->set_property = aaina_library_set_property;
86 object_class->dispose = aaina_library_dispose;
87 object_class->finalize = aaina_library_finalize;
89 _library_signals[REORDERED] =
90 g_signal_new ("photos-reordered",
91 G_OBJECT_CLASS_TYPE (object_class),
93 G_STRUCT_OFFSET (AainaLibraryClass, reordered),
95 g_cclosure_marshal_VOID__VOID,
98 _library_signals[FILTER] =
99 g_signal_new ("filter-changed",
100 G_OBJECT_CLASS_TYPE (object_class),
102 G_STRUCT_OFFSET (AainaLibraryClass, filter_change),
104 g_cclosure_marshal_VOID__VOID,
107 _library_signals[PHOTO_CHANGED] =
108 g_signal_new ("photo-changed",
109 G_OBJECT_CLASS_TYPE (object_class),
111 G_STRUCT_OFFSET (AainaLibraryClass, photo_change),
113 g_cclosure_marshal_VOID__OBJECT,
114 G_TYPE_NONE, 1, AAINA_TYPE_PHOTO);
116 _library_signals[PHOTO_ADDED] =
117 g_signal_new ("photo-added",
118 G_OBJECT_CLASS_TYPE (object_class),
120 G_STRUCT_OFFSET (AainaLibraryClass, photo_added),
122 g_cclosure_marshal_VOID__OBJECT,
123 G_TYPE_NONE, 1, AAINA_TYPE_PHOTO);
128 aaina_library_init (AainaLibrary *self)
130 AainaLibraryPrivate *priv = LIBRARY_PRIVATE(self);
132 priv->photos = egg_sequence_new (NULL);
135 priv->max_photos = 100;
136 priv->pending = FALSE;
140 check_filter (AainaLibrary *library, EggSequenceIter *iter)
142 AainaLibraryPrivate *priv = LIBRARY_PRIVATE(library);
145 if (priv->filter == NULL)
148 res = priv->filter(library, (AainaPhoto*)egg_sequence_get (iter),
154 aaina_library_get_pending (AainaLibrary *library)
156 AainaLibraryPrivate *priv;
158 g_return_val_if_fail (AAINA_IS_LIBRARY (library), FALSE);
159 priv = LIBRARY_PRIVATE (library);
161 return priv->pending;
165 aaina_library_set_pending (AainaLibrary *library, gboolean pending)
167 AainaLibraryPrivate *priv;
169 g_return_if_fail (AAINA_IS_LIBRARY (library));
170 priv = LIBRARY_PRIVATE (library);
172 priv->pending = pending;
176 aaina_library_is_full (AainaLibrary *library)
178 AainaLibraryPrivate *priv;
180 g_return_val_if_fail (AAINA_IS_LIBRARY (library), FALSE);
181 priv = LIBRARY_PRIVATE (library);
183 if (priv->size >= priv->max_photos)
192 aaina_library_set_max (AainaLibrary *library, gint max_photos)
194 AainaLibraryPrivate *priv;
196 g_return_if_fail (AAINA_IS_LIBRARY (library));
197 priv = LIBRARY_PRIVATE (library);
199 priv->max_photos = max_photos;
203 aaina_library_photo_count (AainaLibrary *library)
205 AainaLibraryPrivate *priv = LIBRARY_PRIVATE(library);
206 EggSequenceIter *iter;
210 return g_list_length (priv->list);
212 if (priv->filter == NULL)
213 return egg_sequence_get_length (priv->photos);
215 iter = egg_sequence_get_begin_iter (priv->photos);
217 while (!egg_sequence_iter_is_end (iter)) {
218 if (check_filter (library, iter))
220 iter = egg_sequence_iter_next (iter);
227 aaina_library_get_photo (AainaLibrary *library, gint index)
229 AainaLibraryPrivate *priv = LIBRARY_PRIVATE(library);
230 EggSequenceIter *iter;
233 return (AainaPhoto*)g_list_nth_data (priv->list, index);
235 if (priv->filter == NULL)
236 return (AainaPhoto*)egg_sequence_get
237 (egg_sequence_get_iter_at_pos (priv->photos, index));
239 iter = egg_sequence_get_begin_iter (priv->photos);
241 while (!egg_sequence_iter_is_end (iter)) {
242 if (check_filter (library, iter)) {
244 return (AainaPhoto*)egg_sequence_get (iter);
247 iter = egg_sequence_iter_next (iter);
254 on_photo_changed (GObject *obj, GParamSpec *arg1,
258 AainaLibrary *library = AAINA_LIBRARY(data);
259 AainaLibraryPrivate *priv;
261 priv = LIBRARY_PRIVATE(library);
263 /* thumbnail changing does not effect ordering */
264 if (!strcmp(g_param_spec_get_name(arg1), "thumbnail"))
268 egg_sequence_sort (priv->photos,
269 (GCompareDataFunc)priv->sort, priv->sort_data);
270 g_signal_emit (library, _library_signals[REORDERED], 0);
273 g_signal_emit (library, _library_signals[PHOTO_CHANGED], 0,
278 aaina_library_append_photo (AainaLibrary *library, AainaPhoto *photo)
280 AainaLibraryPrivate *priv = LIBRARY_PRIVATE(library);
281 EggSequenceIter *iter;
283 g_signal_connect (photo, "notify", G_CALLBACK (on_photo_changed), library);
288 iter = egg_sequence_insert_sorted (priv->photos, (gpointer)photo,
289 (GCompareDataFunc)priv->sort,
292 iter = egg_sequence_append (priv->photos, (gpointer)photo);
294 priv->list = g_list_append (priv->list, photo);
296 g_signal_emit (library, _library_signals[PHOTO_ADDED], 0, photo);
300 aaina_library_remove_photo (AainaLibrary *library, const AainaPhoto *photo)
302 AainaLibraryPrivate *priv = LIBRARY_PRIVATE(library);
304 priv->list = g_list_remove (priv->list, (gconstpointer)photo);
310 aaina_library_foreach (AainaLibrary *library,
311 AainaForeachRowFunc func,
314 AainaLibraryPrivate *priv = LIBRARY_PRIVATE(library);
315 EggSequenceIter *iter;
318 for (l = priv->list; l != NULL; l = l->next)
320 if (AAINA_IS_PHOTO (l->data))
321 func (library, (AainaPhoto*)l->data, data );
325 iter = egg_sequence_get_begin_iter (priv->photos);
326 while (!egg_sequence_iter_is_end (iter)) {
327 if (check_filter (library, iter))
329 (AainaPhoto*)egg_sequence_get (iter, data) == FALSE)
332 iter = egg_sequence_iter_next (iter);
338 aaina_library_set_sort_func (AainaLibrary *library,
339 AainaCompareRowFunc func,
342 AainaLibraryPrivate *priv = LIBRARY_PRIVATE(library);
345 priv->sort_data = userdata;
348 egg_sequence_sort (priv->photos, (GCompareDataFunc)func, userdata);
349 g_signal_emit (library, _library_signals[REORDERED], 0);
354 aaina_library_set_filter (AainaLibrary *library,
355 AainaFilterRowFunc filter,
358 AainaLibraryPrivate *priv = LIBRARY_PRIVATE(library);
359 AainaFilterRowFunc prev_filter;
361 prev_filter = priv->filter;
363 priv->filter = filter;
364 priv->filter_data = data;
366 if (prev_filter != priv->filter)
367 g_signal_emit (library, _library_signals[FILTER], 0);
373 return g_object_new (AAINA_TYPE_LIBRARY, NULL);