1 /*
2 * frogr-model.c -- Model in frogr
3 *
4 * Copyright (C) 2009-2012 Mario Sanchez Prada
5 * Authors: Mario Sanchez Prada <msanchez@gnome.org>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 3 of the GNU General Public
9 * License as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>
18 *
19 */
20
21 #include "frogr-model.h"
22
23 #include "frogr-account.h"
24 #include "frogr-file-loader.h"
25
26 #define TAGS_DELIMITER " "
27
28
29 struct _FrogrModel
30 {
31 GObject parent;
32
33 GSList *pictures;
34
35 /* For sequential access of groups and sets */
36 GSList *remote_sets;
37 GSList *local_sets;
38 GSList *all_sets;
39 GSList *groups;
40
41 /* For random acces (e.g. get a group by ID) */
42 GHashTable *sets_table;
43 GHashTable *groups_table;
44
45 GSList *remote_tags;
46 GSList *local_tags;
47 GSList *all_tags;
48 };
49
50 G_DEFINE_TYPE (FrogrModel, frogr_model, G_TYPE_OBJECT)
51
52
53 /* Signals */
54 enum {
55 PICTURE_ADDED,
56 PICTURE_REMOVED,
57 MODEL_CHANGED,
58 MODEL_DESERIALIZED,
59 N_SIGNALS
60 };
61
62 static guint signals[N_SIGNALS] = { 0 };
63
64 /* Private API */
65
66 static void
_remove_remote_photosets(FrogrModel * self)67 _remove_remote_photosets (FrogrModel *self)
68 {
69 FrogrPhotoSet *set = NULL;
70 GSList *item = NULL;
71 const gchar *id = NULL;
72
73 g_return_if_fail(FROGR_IS_MODEL (self));
74
75 if (!self->remote_sets)
76 return;
77
78 /* Remove from the hash table first */
79 for (item = self->remote_sets; item; item = g_slist_next (item))
80 {
81 set = FROGR_PHOTOSET (item->data);
82 id = frogr_photoset_get_id (set);
83 if (id)
84 g_hash_table_remove (self->sets_table, id);
85
86 /* A remote photo set might be still indexed by its local ID */
87 id = frogr_photoset_get_local_id (set);
88 if (id)
89 g_hash_table_remove (self->sets_table, id);
90 }
91
92 g_slist_free_full (self->remote_sets, g_object_unref);
93 self->remote_sets = NULL;
94 }
95
96 static void
_remove_local_photosets(FrogrModel * self)97 _remove_local_photosets (FrogrModel *self)
98 {
99 FrogrPhotoSet *set = NULL;
100 GSList *item = NULL;
101
102 g_return_if_fail(FROGR_IS_MODEL (self));
103
104 if (!self->local_sets)
105 return;
106
107 /* Remove from the hash table first */
108 for (item = self->remote_sets; item; item = g_slist_next (item))
109 {
110 set = FROGR_PHOTOSET (item->data);
111 g_hash_table_remove (self->sets_table, frogr_photoset_get_local_id (set));
112 }
113
114 g_slist_free_full (self->local_sets, g_object_unref);
115 self->local_sets = NULL;
116 }
117
118 static void
_remove_pictures(FrogrModel * self)119 _remove_pictures (FrogrModel *self)
120 {
121 FrogrPicture *picture = NULL;
122
123 g_return_if_fail(FROGR_IS_MODEL (self));
124
125 while (self->pictures)
126 {
127 picture = FROGR_PICTURE (self->pictures->data);
128 self->pictures = g_slist_remove (self->pictures, picture);
129 g_signal_emit (self, signals[PICTURE_REMOVED], 0, picture);
130 g_object_unref (picture);
131 }
132
133 g_slist_free (self->pictures);
134 self->pictures = NULL;
135
136 g_signal_emit (self, signals[MODEL_CHANGED], 0);
137 }
138
139 static void
_remove_all_photosets(FrogrModel * self)140 _remove_all_photosets (FrogrModel *self)
141 {
142 g_return_if_fail(FROGR_IS_MODEL (self));
143
144 if (self->all_sets)
145 {
146 g_slist_free (self->all_sets);
147 self->all_sets = NULL;
148 }
149
150 _remove_remote_photosets (self);
151 _remove_local_photosets (self);
152
153 if (self->sets_table)
154 g_hash_table_remove_all (self->sets_table);
155 }
156
157 static void
_remove_groups(FrogrModel * self)158 _remove_groups (FrogrModel *self)
159 {
160 g_return_if_fail(FROGR_IS_MODEL (self));
161
162 if (self->groups)
163 {
164 g_slist_free_full (self->groups, g_object_unref);
165 self->groups = NULL;
166 }
167
168 if (self->groups_table)
169 g_hash_table_remove_all (self->groups_table);
170 }
171
172 static void
_remove_remote_tags(FrogrModel * self)173 _remove_remote_tags (FrogrModel *self)
174 {
175 g_return_if_fail(FROGR_IS_MODEL (self));
176
177 if (!self->remote_tags)
178 return;
179
180 g_slist_free_full (self->remote_tags, g_free);
181 self->remote_tags = NULL;
182 }
183
184 static void
_remove_local_tags(FrogrModel * self)185 _remove_local_tags (FrogrModel *self)
186 {
187 g_return_if_fail(FROGR_IS_MODEL (self));
188
189 if (!self->local_tags)
190 return;
191
192 g_slist_free_full (self->local_tags, g_free);
193 self->local_tags = NULL;
194 }
195
196 static void
_remove_all_tags(FrogrModel * self)197 _remove_all_tags (FrogrModel *self)
198 {
199 g_return_if_fail(FROGR_IS_MODEL (self));
200
201 if (self->all_tags)
202 {
203 g_slist_free (self->all_tags);
204 self->all_tags = NULL;
205 }
206
207 _remove_remote_tags (self);
208 _remove_local_tags (self);
209 }
210
211 static void
_set_local_tags(FrogrModel * self,GSList * tags_list)212 _set_local_tags (FrogrModel *self, GSList *tags_list)
213 {
214 g_return_if_fail(FROGR_IS_MODEL (self));
215 _remove_local_tags (self);
216 self->local_tags = tags_list;
217 }
218
219 static JsonArray *
_serialize_list_to_json_array(GSList * list,GType g_type)220 _serialize_list_to_json_array (GSList *list, GType g_type)
221 {
222 JsonArray *json_array = NULL;
223 JsonNode *json_node = NULL;
224 GSList *item = NULL;
225
226 /* Generate a JsonArray with contents */
227 json_array = json_array_new ();
228 for (item = list; item; item = g_slist_next (item))
229 {
230 if (g_type == G_TYPE_OBJECT)
231 json_node = json_gobject_serialize (G_OBJECT (item->data));
232 else if (g_type == G_TYPE_STRING)
233 {
234 json_node = json_node_new (JSON_NODE_VALUE);
235 json_node_set_string (json_node, (const gchar*)item->data);
236 }
237
238 if (json_node)
239 json_array_add_element (json_array, json_node);
240 }
241
242 return json_array;
243 }
244
245 static GSList *
_deserialize_list_from_json_array(JsonArray * array,GType g_type)246 _deserialize_list_from_json_array (JsonArray *array, GType g_type)
247 {
248 JsonNode *json_node = NULL;
249 GSList *result_list = NULL;
250 gpointer element = NULL;
251 guint n_elements = 0;
252 guint i = 0;
253
254 n_elements = json_array_get_length (array);
255 if (!n_elements)
256 return NULL;
257
258 for (i = 0; i < n_elements; i++)
259 {
260 json_node = json_array_get_element (array, i);
261 if (JSON_NODE_HOLDS_OBJECT (json_node))
262 element = json_gobject_deserialize (g_type, json_node);
263 else if (g_type == G_TYPE_STRING)
264 element = json_node_dup_string (json_node);
265
266 if (element)
267 result_list = g_slist_append (result_list, element);
268 }
269
270 return result_list;
271 }
272
273 static void
_on_file_loaded(FrogrFileLoader * loader,FrogrPicture * picture,FrogrModel * self)274 _on_file_loaded (FrogrFileLoader *loader, FrogrPicture *picture, FrogrModel *self)
275 {
276 g_return_if_fail (FROGR_IS_MODEL (self));
277 frogr_model_add_picture (self, picture);
278 }
279
280 static void
_on_files_loaded(FrogrFileLoader * loader,FrogrModel * self)281 _on_files_loaded (FrogrFileLoader *loader, FrogrModel *self)
282 {
283 g_signal_emit (self, signals[MODEL_DESERIALIZED], 0);
284 }
285
286 static void
_frogr_model_dispose(GObject * object)287 _frogr_model_dispose (GObject* object)
288 {
289 FrogrModel *self = FROGR_MODEL (object);
290
291 _remove_pictures (self);
292 _remove_all_photosets (self);
293 _remove_groups (self);
294 _remove_all_tags (self);
295
296 if (self->sets_table)
297 {
298 g_hash_table_destroy (self->sets_table);
299 self->sets_table = NULL;
300 }
301
302 if (self->groups_table)
303 {
304 g_hash_table_destroy (self->groups_table);
305 self->groups_table = NULL;
306 }
307
308 G_OBJECT_CLASS (frogr_model_parent_class)->dispose (object);
309 }
310
311 static void
frogr_model_class_init(FrogrModelClass * klass)312 frogr_model_class_init(FrogrModelClass *klass)
313 {
314 GObjectClass *obj_class = G_OBJECT_CLASS(klass);
315 obj_class->dispose = _frogr_model_dispose;
316
317 signals[PICTURE_ADDED] =
318 g_signal_new ("picture-added",
319 G_OBJECT_CLASS_TYPE (klass),
320 G_SIGNAL_RUN_FIRST,
321 0, NULL, NULL,
322 g_cclosure_marshal_VOID__OBJECT,
323 G_TYPE_NONE, 1, FROGR_TYPE_PICTURE);
324
325 signals[PICTURE_REMOVED] =
326 g_signal_new ("picture-removed",
327 G_OBJECT_CLASS_TYPE (klass),
328 G_SIGNAL_RUN_FIRST,
329 0, NULL, NULL,
330 g_cclosure_marshal_VOID__OBJECT,
331 G_TYPE_NONE, 1, FROGR_TYPE_PICTURE);
332
333 signals[MODEL_CHANGED] =
334 g_signal_new ("model-changed",
335 G_OBJECT_CLASS_TYPE (klass),
336 G_SIGNAL_RUN_FIRST,
337 0, NULL, NULL,
338 g_cclosure_marshal_VOID__VOID,
339 G_TYPE_NONE, 0);
340
341 signals[MODEL_DESERIALIZED] =
342 g_signal_new ("model-deserialized",
343 G_OBJECT_CLASS_TYPE (klass),
344 G_SIGNAL_RUN_FIRST,
345 0, NULL, NULL,
346 g_cclosure_marshal_VOID__VOID,
347 G_TYPE_NONE, 0);
348 }
349
350 static void
frogr_model_init(FrogrModel * self)351 frogr_model_init (FrogrModel *self)
352 {
353 /* Init private data */
354 self->pictures = NULL;
355 self->remote_sets = NULL;
356 self->local_sets = NULL;
357 self->all_sets = NULL;
358 self->groups = NULL;
359
360 /* For random access */
361 self->sets_table = g_hash_table_new_full (g_str_hash, g_str_equal,
362 (GDestroyNotify)g_free,
363 (GDestroyNotify)g_object_unref);
364
365 self->groups_table = g_hash_table_new_full (g_str_hash, g_str_equal,
366 (GDestroyNotify)g_free,
367 (GDestroyNotify)g_object_unref);
368
369 self->remote_tags = NULL;
370 self->local_tags = NULL;
371 self->all_tags = NULL;
372 }
373
374 /* Public API */
375
376 FrogrModel *
frogr_model_new(void)377 frogr_model_new (void)
378 {
379 GObject *new = g_object_new(FROGR_TYPE_MODEL, NULL);
380 return FROGR_MODEL (new);
381 }
382
383 void
frogr_model_add_picture(FrogrModel * self,FrogrPicture * picture)384 frogr_model_add_picture (FrogrModel *self,
385 FrogrPicture *picture)
386 {
387 g_return_if_fail(FROGR_IS_MODEL (self));
388 g_return_if_fail(FROGR_IS_PICTURE (picture));
389
390 self->pictures = g_slist_append (self->pictures, g_object_ref (picture));
391
392 g_signal_emit (self, signals[PICTURE_ADDED], 0, picture);
393 g_signal_emit (self, signals[MODEL_CHANGED], 0);
394 }
395
396 void
frogr_model_remove_picture(FrogrModel * self,FrogrPicture * picture)397 frogr_model_remove_picture (FrogrModel *self,
398 FrogrPicture *picture)
399 {
400 g_return_if_fail(FROGR_IS_MODEL (self));
401
402 self->pictures = g_slist_remove (self->pictures, picture);
403
404 g_signal_emit (self, signals[PICTURE_REMOVED], 0, picture);
405 g_signal_emit (self, signals[MODEL_CHANGED], 0);
406 g_object_unref (picture);
407 }
408
409 guint
frogr_model_n_pictures(FrogrModel * self)410 frogr_model_n_pictures (FrogrModel *self)
411 {
412 g_return_val_if_fail(FROGR_IS_MODEL (self), 0);
413 return g_slist_length (self->pictures);
414 }
415
416 GSList *
frogr_model_get_pictures(FrogrModel * self)417 frogr_model_get_pictures (FrogrModel *self)
418 {
419 g_return_val_if_fail(FROGR_IS_MODEL (self), NULL);
420 return self->pictures;
421 }
422
423 void
frogr_model_notify_changes_in_pictures(FrogrModel * self)424 frogr_model_notify_changes_in_pictures (FrogrModel *self)
425 {
426 /* Just emit the signal so the main view gets notified too */
427 g_signal_emit (self, signals[MODEL_CHANGED], 0);
428 }
429
430 void
frogr_model_set_remote_photosets(FrogrModel * self,GSList * remote_sets)431 frogr_model_set_remote_photosets (FrogrModel *self,
432 GSList *remote_sets)
433 {
434 FrogrPhotoSet *set = NULL;
435 GSList *item = NULL;
436
437 g_return_if_fail(FROGR_IS_MODEL (self));
438
439 /* Remove all the remote photosets */
440 _remove_remote_photosets (self);
441
442 /* Set photosets now (and update the hash table) */
443 for (item = remote_sets; item; item = g_slist_next (item))
444 {
445 set = FROGR_PHOTOSET (item->data);
446 g_hash_table_insert (self->sets_table,
447 g_strdup (frogr_photoset_get_id (set)),
448 g_object_ref (set));
449 }
450 self->remote_sets = remote_sets;
451 }
452
453 void
frogr_model_add_local_photoset(FrogrModel * self,FrogrPhotoSet * set)454 frogr_model_add_local_photoset (FrogrModel *self,
455 FrogrPhotoSet *set)
456 {
457 g_return_if_fail(FROGR_IS_MODEL (self));
458 g_return_if_fail(FROGR_IS_PHOTOSET (set));
459
460 /* When adding one by one we prepend always to keep the order */
461 self->local_sets = g_slist_prepend (self->local_sets, g_object_ref (set));
462
463 /* Update the hash table too! */
464 g_hash_table_insert (self->sets_table,
465 g_strdup (frogr_photoset_get_local_id (set)),
466 g_object_ref (set));
467
468 g_signal_emit (self, signals[MODEL_CHANGED], 0);
469 }
470
471 GSList *
frogr_model_get_photosets(FrogrModel * self)472 frogr_model_get_photosets (FrogrModel *self)
473 {
474 GSList *list = NULL;
475 GSList *current = NULL;
476
477 g_return_val_if_fail(FROGR_IS_MODEL (self), 0);
478
479 /* Copy the list of remote sets and add those locally added */
480 list = g_slist_copy (self->remote_sets);
481 for (current = self->local_sets; current; current = g_slist_next (current))
482 {
483 if (!g_slist_find_custom (list, current->data, (GCompareFunc)frogr_photoset_compare))
484 list = g_slist_prepend (list, current->data);
485 }
486
487 /* Update internal pointers to the result list */
488 if (self->all_sets)
489 g_slist_free (self->all_sets);
490 self->all_sets = list;
491
492 return self->all_sets;
493 }
494
495 void
frogr_model_set_photosets(FrogrModel * self,GSList * photosets)496 frogr_model_set_photosets (FrogrModel *self,
497 GSList *photosets)
498 {
499 FrogrPhotoSet *set = NULL;
500 GSList *item = NULL;
501 GSList *next_item = NULL;
502
503 g_return_if_fail(FROGR_IS_MODEL (self));
504
505 /* Remove all sets */
506 _remove_all_photosets (self);
507
508 /* Set groups now, separating them into two lists: local and remote */
509 item = photosets;
510 while (item)
511 {
512 set = FROGR_PHOTOSET(item->data);
513 if (frogr_photoset_is_local (set))
514 {
515 next_item = item->next;
516 photosets = g_slist_remove_link (photosets, item);
517 frogr_model_add_local_photoset (self, set);
518 g_object_unref (set);
519 g_slist_free (item);
520
521 item = next_item;
522 }
523 else
524 item = g_slist_next (item);
525 }
526
527 /* Once separated the local photosets, we assign the remote ones */
528 frogr_model_set_remote_photosets (self, photosets);
529 }
530
531 guint
frogr_model_n_photosets(FrogrModel * self)532 frogr_model_n_photosets (FrogrModel *self)
533 {
534 g_return_val_if_fail(FROGR_IS_MODEL (self), 0);
535 return g_slist_length (self->remote_sets) + g_slist_length (self->local_sets);
536 }
537
538 FrogrPhotoSet *
frogr_model_get_photoset_by_id(FrogrModel * self,const gchar * id)539 frogr_model_get_photoset_by_id (FrogrModel *self, const gchar *id)
540 {
541 g_return_val_if_fail(FROGR_IS_MODEL (self), NULL);
542 return g_hash_table_lookup (self->sets_table, id);
543 }
544
545 guint
frogr_model_n_groups(FrogrModel * self)546 frogr_model_n_groups (FrogrModel *self)
547 {
548 g_return_val_if_fail(FROGR_IS_MODEL (self), 0);
549 return g_slist_length (self->groups);
550 }
551
552 GSList *
frogr_model_get_groups(FrogrModel * self)553 frogr_model_get_groups (FrogrModel *self)
554 {
555 g_return_val_if_fail(FROGR_IS_MODEL (self), NULL);
556 return self->groups;
557 }
558
559 void
frogr_model_set_groups(FrogrModel * self,GSList * groups)560 frogr_model_set_groups (FrogrModel *self,
561 GSList *groups)
562 {
563 FrogrGroup *group = NULL;
564 GSList *item = NULL;
565
566 g_return_if_fail(FROGR_IS_MODEL (self));
567
568 /* Remove all groups */
569 _remove_groups (self);
570
571 /* Set groups now (and update the hash table) */
572 for (item = groups; item; item = g_slist_next (item))
573 {
574 group = FROGR_GROUP (item->data);
575 g_hash_table_insert (self->groups_table,
576 g_strdup (frogr_group_get_id (group)),
577 g_object_ref (group));
578 }
579
580 /* Set groups now */
581 self->groups = groups;
582 }
583
584 FrogrGroup *
frogr_model_get_group_by_id(FrogrModel * self,const gchar * id)585 frogr_model_get_group_by_id (FrogrModel *self, const gchar *id)
586 {
587 g_return_val_if_fail(FROGR_IS_MODEL (self), NULL);
588 return g_hash_table_lookup (self->groups_table, id);
589 }
590
591 void
frogr_model_set_remote_tags(FrogrModel * self,GSList * tags_list)592 frogr_model_set_remote_tags (FrogrModel *self, GSList *tags_list)
593 {
594 g_return_if_fail(FROGR_IS_MODEL (self));
595 _remove_remote_tags (self);
596 self->remote_tags = tags_list;
597 }
598
599 void
frogr_model_remove_remote_tags(FrogrModel * self)600 frogr_model_remove_remote_tags (FrogrModel *self)
601 {
602 g_return_if_fail(FROGR_IS_MODEL (self));
603
604 g_slist_free_full (self->remote_tags, g_free);
605 self->remote_tags = NULL;
606 }
607
608 void
frogr_model_add_local_tags_from_string(FrogrModel * self,const gchar * tags_string)609 frogr_model_add_local_tags_from_string (FrogrModel *self,
610 const gchar *tags_string)
611 {
612 g_autofree gchar *stripped_tags = NULL;
613 gboolean added_new_tags = FALSE;
614
615 g_return_if_fail(FROGR_IS_MODEL (self));
616
617 if (!tags_string || !tags_string[0])
618 return;
619
620 stripped_tags = g_strstrip (g_strdup (tags_string));
621 if (!g_str_equal (stripped_tags, ""))
622 {
623 g_auto(GStrv) tags_array = NULL;
624 gchar *tag;
625 gint i;
626
627 /* Now iterate over every token, adding it to the list */
628 tags_array = g_strsplit (stripped_tags, TAGS_DELIMITER, -1);
629 for (i = 0; tags_array[i]; i++)
630 {
631 /* add stripped tag if not already set*/
632 tag = g_strstrip(g_strdup (tags_array[i]));
633 if (!g_str_equal (tag, "") && !g_slist_find_custom (self->local_tags, tag, (GCompareFunc)g_strcmp0))
634 {
635 self->local_tags = g_slist_prepend (self->local_tags, g_strdup (tag));
636 added_new_tags = TRUE;
637 }
638
639 g_free (tag);
640 }
641
642 self->local_tags = g_slist_sort (self->local_tags, (GCompareFunc)g_strcmp0);
643 }
644
645 if (added_new_tags)
646 g_signal_emit (self, signals[MODEL_CHANGED], 0);
647 }
648
649 GSList *
frogr_model_get_tags(FrogrModel * self)650 frogr_model_get_tags (FrogrModel *self)
651 {
652 GSList *list = NULL;
653 GSList *current = NULL;
654
655 g_return_val_if_fail(FROGR_IS_MODEL (self), 0);
656
657 /* Copy the list of remote tags and add those locally added */
658 list = g_slist_copy (self->remote_tags);
659 for (current = self->local_tags; current; current = g_slist_next (current))
660 {
661 if (!g_slist_find_custom (list, current->data, (GCompareFunc)g_strcmp0))
662 list = g_slist_prepend (list, current->data);
663 }
664 list = g_slist_sort (list, (GCompareFunc)g_strcmp0);
665
666 /* Update internal pointers to the result list */
667 if (self->all_tags)
668 g_slist_free (self->all_tags);
669 self->all_tags = list;
670
671 return self->all_tags;
672 }
673
674 guint
frogr_model_n_tags(FrogrModel * self)675 frogr_model_n_tags (FrogrModel *self)
676 {
677 g_return_val_if_fail(FROGR_IS_MODEL (self), 0);
678 return g_slist_length (frogr_model_get_tags (self));
679 }
680
681 guint
frogr_model_n_local_tags(FrogrModel * self)682 frogr_model_n_local_tags (FrogrModel *self)
683 {
684 g_return_val_if_fail(FROGR_IS_MODEL (self), 0);
685 return g_slist_length (self->local_tags);
686 }
687
688 JsonObject *
frogr_model_serialize(FrogrModel * self)689 frogr_model_serialize (FrogrModel *self)
690 {
691 JsonArray *json_array = NULL;
692 JsonObject *root_object = NULL;
693 GSList *data_list = NULL;
694
695 g_return_val_if_fail(FROGR_IS_MODEL (self), NULL);
696
697 root_object = json_object_new ();
698
699 data_list = frogr_model_get_pictures (self);
700 json_array = _serialize_list_to_json_array (data_list, G_TYPE_OBJECT);
701 json_object_set_array_member (root_object, "pictures", json_array);
702
703 data_list = frogr_model_get_photosets (self);
704 json_array = _serialize_list_to_json_array (data_list, G_TYPE_OBJECT);
705 json_object_set_array_member (root_object, "photosets", json_array);
706
707 data_list = frogr_model_get_groups (self);
708 json_array = _serialize_list_to_json_array (data_list, G_TYPE_OBJECT);
709 json_object_set_array_member (root_object, "groups", json_array);
710
711 /* Only serialize the local tags, not to bloat the project file too much */
712 json_array = _serialize_list_to_json_array (self->local_tags,
713 G_TYPE_STRING);
714 json_object_set_array_member (root_object, "tags", json_array);
715
716 return root_object;
717 }
718
719 void
frogr_model_deserialize(FrogrModel * self,JsonObject * root_object)720 frogr_model_deserialize (FrogrModel *self, JsonObject *root_object)
721 {
722 JsonArray *array_member = NULL;
723 GSList *pictures = NULL;
724 GSList *sets = NULL;
725 GSList *groups = NULL;
726 GSList *tags = NULL;
727
728 g_return_if_fail(FROGR_IS_MODEL (self));
729
730 /* First we get the different lists with data for sets, groups and tags */
731 array_member = json_object_get_array_member (root_object, "photosets");
732 if (array_member)
733 sets = _deserialize_list_from_json_array (array_member, FROGR_TYPE_PHOTOSET);
734
735 array_member = json_object_get_array_member (root_object, "groups");
736 if (array_member)
737 groups = _deserialize_list_from_json_array (array_member, FROGR_TYPE_GROUP);
738
739 array_member = json_object_get_array_member (root_object, "tags");
740 if (array_member)
741 tags = _deserialize_list_from_json_array (array_member, G_TYPE_STRING);
742
743 /* We set the sets and groups */
744 frogr_model_set_photosets (self, sets);
745 frogr_model_set_groups (self, groups);
746
747 /* We only serialized local tags */
748 _set_local_tags (self, tags);
749
750 /* Pictures must be deserialized at the end, since they will hold
751 references to sets and groups previously imported in the model */
752 array_member = json_object_get_array_member (root_object, "pictures");
753 if (array_member)
754 pictures = _deserialize_list_from_json_array (array_member, FROGR_TYPE_PICTURE);
755
756 if (pictures)
757 {
758 FrogrFileLoader *loader = NULL;
759
760 /* Now we take the list of pictures and add them into the
761 model as the associated thumbnails are being loaded */
762 loader = frogr_file_loader_new_from_pictures (pictures);
763
764 g_signal_connect (G_OBJECT (loader), "file-loaded",
765 G_CALLBACK (_on_file_loaded),
766 self);
767
768 g_signal_connect (G_OBJECT (loader), "files-loaded",
769 G_CALLBACK (_on_files_loaded),
770 self);
771 /* Load the pictures! */
772 _remove_pictures (self);
773 frogr_file_loader_load (loader);
774 }
775 else
776 {
777 /* We are done deserializing already now if there are no pictures */
778 g_signal_emit (self, signals[MODEL_DESERIALIZED], 0);
779 }
780 }
781