1 /*
2 * frogr-photoset.c -- An set in frogr (a photoset from flickr)
3 *
4 * Copyright (C) 2010-2020 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 * Parts of this file based on code from GConf, licensed as GPL
20 * version 2 or later (Copyright (C) 1999, 2000 Red Hat Inc)
21 */
22
23 #include "frogr-photoset.h"
24
25 #include <sys/types.h>
26 #include <unistd.h>
27
28 struct _FrogrPhotoSet
29 {
30 GObject parent;
31
32 gchar *title;
33 gchar *description;
34 gchar *id;
35 gchar *local_id; /* For locally created sets only */
36 gchar *primary_photo_id;
37 gint n_photos;
38 };
39
40 G_DEFINE_TYPE (FrogrPhotoSet, frogr_photoset, G_TYPE_OBJECT)
41
42
43 /* Properties */
44 enum {
45 PROP_0,
46 PROP_TITLE,
47 PROP_DESCRIPTION,
48 PROP_ID,
49 PROP_LOCAL_ID,
50 PROP_PRIMARY_PHOTO_ID,
51 PROP_N_PHOTOS
52 };
53
54 /* Prototypes */
55
56 static gchar *_create_temporary_id_for_photoset (void);
57
58
59 /* Private API */
60
61 /* The following function is based in gconf_unique_key(), licensed as
62 GPL version 2 or later (Copyright (C) 1999, 2000 Red Hat Inc) */
63 static gchar *
_create_temporary_id_for_photoset(void)64 _create_temporary_id_for_photoset (void)
65 {
66 /* This function is hardly cryptographically random but should be
67 "good enough" */
68 static guint serial = 0;
69 gchar* key;
70 gint64 tv, t, ut;
71 pid_t p;
72 uid_t u;
73 guint32 r;
74
75 tv = g_get_real_time ();
76
77 t = tv / G_USEC_PER_SEC;
78 ut = tv;
79
80 p = getpid();
81 u = getuid();
82
83 /* don't bother to seed; if it's based on the time or any other
84 changing info we can get, we may as well just use that changing
85 info. since we don't seed we'll at least get a different number
86 on every call to this function in the same executable. */
87 r = g_random_int();
88
89 /* The letters may increase uniqueness by preventing "melds"
90 i.e. 01t01k01 and 0101t0k1 are not the same */
91 key = g_strdup_printf("%" G_GUINT32_FORMAT "t"
92 "%" G_GINT64_FORMAT "ut"
93 "%" G_GINT64_FORMAT "u"
94 "%" G_GUINT32_FORMAT "p"
95 "%" G_GINT32_FORMAT "r"
96 "%" G_GUINT32_FORMAT "k"
97 "%" G_GUINT32_FORMAT,
98 /* Duplicate keys must be generated
99 by two different program instances */
100 serial,
101 /* Duplicate keys must be generated
102 in the same microsecond */
103 t,
104 ut,
105 /* Duplicate keys must be generated by
106 the same user */
107 u,
108 /* Duplicate keys must be generated by
109 two programs that got the same PID */
110 p,
111 /* Duplicate keys must be generated with the
112 same random seed and the same index into
113 the series of pseudorandom values */
114 r,
115 /* Duplicate keys must result from running
116 this function at the same stack location */
117 GPOINTER_TO_UINT(&key));
118 ++serial;
119
120 return key;
121 }
122
123 static void
_frogr_photoset_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)124 _frogr_photoset_set_property (GObject *object,
125 guint prop_id,
126 const GValue *value,
127 GParamSpec *pspec)
128 {
129 FrogrPhotoSet *self = FROGR_PHOTOSET (object);
130
131 switch (prop_id)
132 {
133 case PROP_TITLE:
134 frogr_photoset_set_title (self, g_value_get_string (value));
135 break;
136 case PROP_DESCRIPTION:
137 frogr_photoset_set_description (self, g_value_get_string (value));
138 break;
139 case PROP_ID:
140 frogr_photoset_set_id (self, g_value_get_string (value));
141 break;
142 case PROP_LOCAL_ID:
143 frogr_photoset_set_local_id (self, g_value_get_string (value));
144 break;
145 case PROP_PRIMARY_PHOTO_ID:
146 frogr_photoset_set_primary_photo_id (self, g_value_get_string (value));
147 break;
148 case PROP_N_PHOTOS:
149 frogr_photoset_set_n_photos (self, g_value_get_int (value));
150 break;
151 default:
152 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
153 break;
154 }
155 }
156
157 static void
_frogr_photoset_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)158 _frogr_photoset_get_property (GObject *object,
159 guint prop_id,
160 GValue *value,
161 GParamSpec *pspec)
162 {
163 FrogrPhotoSet *self = FROGR_PHOTOSET (object);
164
165 switch (prop_id)
166 {
167 case PROP_TITLE:
168 g_value_set_string (value, frogr_photoset_get_title (self));
169 break;
170 case PROP_DESCRIPTION:
171 g_value_set_string (value, frogr_photoset_get_description (self));
172 break;
173 case PROP_ID:
174 g_value_set_string (value, frogr_photoset_get_id (self));
175 break;
176 case PROP_LOCAL_ID:
177 g_value_set_string (value, frogr_photoset_get_local_id (self));
178 break;
179 case PROP_PRIMARY_PHOTO_ID:
180 g_value_set_string (value, frogr_photoset_get_primary_photo_id (self));
181 break;
182 case PROP_N_PHOTOS:
183 g_value_set_int (value, frogr_photoset_get_n_photos (self));
184 break;
185 default:
186 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
187 break;
188 }
189 }
190
191 static void
_frogr_photoset_finalize(GObject * object)192 _frogr_photoset_finalize (GObject *object)
193 {
194 FrogrPhotoSet *self = FROGR_PHOTOSET (object);
195
196 /* free strings */
197 g_free (self->title);
198 g_free (self->description);
199 g_free (self->id);
200 g_free (self->local_id);
201 g_free (self->primary_photo_id);
202
203 /* call super class */
204 G_OBJECT_CLASS (frogr_photoset_parent_class)->finalize(object);
205 }
206
207 static void
frogr_photoset_class_init(FrogrPhotoSetClass * klass)208 frogr_photoset_class_init(FrogrPhotoSetClass *klass)
209 {
210 GObjectClass *obj_class = G_OBJECT_CLASS(klass);
211
212 /* GtkObject signals */
213 obj_class->set_property = _frogr_photoset_set_property;
214 obj_class->get_property = _frogr_photoset_get_property;
215 obj_class->finalize = _frogr_photoset_finalize;
216
217 /* Install properties */
218 g_object_class_install_property (obj_class,
219 PROP_TITLE,
220 g_param_spec_string ("title",
221 "title",
222 "Set's title",
223 NULL,
224 G_PARAM_READWRITE));
225 g_object_class_install_property (obj_class,
226 PROP_DESCRIPTION,
227 g_param_spec_string ("description",
228 "description",
229 "Set's description",
230 NULL,
231 G_PARAM_READWRITE));
232 g_object_class_install_property (obj_class,
233 PROP_ID,
234 g_param_spec_string ("id",
235 "id",
236 "Photoset ID from flickr",
237 NULL,
238 G_PARAM_READWRITE));
239 g_object_class_install_property (obj_class,
240 PROP_LOCAL_ID,
241 g_param_spec_string ("local-id",
242 "local-id",
243 "Photoset ID locally generated"
244 "(for new sets only)",
245 NULL,
246 G_PARAM_READWRITE));
247 g_object_class_install_property (obj_class,
248 PROP_PRIMARY_PHOTO_ID,
249 g_param_spec_string ("primary-photo-id",
250 "primary-photo-id",
251 "ID of the primary photo "
252 "for the set",
253 NULL,
254 G_PARAM_READWRITE));
255 g_object_class_install_property (obj_class,
256 PROP_N_PHOTOS,
257 g_param_spec_int ("n-photos",
258 "n-photos",
259 "Number of photos "
260 "inside the set",
261 0,
262 G_MAXINT,
263 0,
264 G_PARAM_READWRITE));
265 }
266
267 static void
frogr_photoset_init(FrogrPhotoSet * self)268 frogr_photoset_init (FrogrPhotoSet *self)
269 {
270 /* Default values */
271 self->title = NULL;
272 self->description = NULL;
273 self->id = NULL;
274 self->local_id = NULL;
275 self->primary_photo_id = NULL;
276 self->n_photos = 0;
277 }
278
279
280 /* Public API */
281
282 FrogrPhotoSet *
frogr_photoset_new(const gchar * id,const gchar * title,const gchar * description)283 frogr_photoset_new (const gchar *id,
284 const gchar *title,
285 const gchar *description)
286 {
287 g_return_val_if_fail (title, NULL);
288 g_return_val_if_fail (description, NULL);
289
290 return FROGR_PHOTOSET (g_object_new(FROGR_TYPE_PHOTOSET,
291 "id", id,
292 "title", title,
293 "description", description,
294 NULL));
295 }
296
297 FrogrPhotoSet *
frogr_photoset_new_local(const gchar * title,const gchar * description)298 frogr_photoset_new_local (const gchar *title,
299 const gchar *description)
300 {
301 FrogrPhotoSet *new_set;
302 g_autofree gchar *id = NULL;
303
304 g_return_val_if_fail (title, NULL);
305 g_return_val_if_fail (description, NULL);
306
307 new_set = frogr_photoset_new (NULL, title, description);
308
309 /* We always need to have an id in locally created photosets */
310 id = _create_temporary_id_for_photoset ();
311 frogr_photoset_set_local_id (new_set, id);
312
313 return new_set;
314 }
315
316 /* Data Managing functions */
317
318 const gchar *
frogr_photoset_get_title(FrogrPhotoSet * self)319 frogr_photoset_get_title (FrogrPhotoSet *self)
320 {
321 g_return_val_if_fail(FROGR_IS_PHOTOSET(self), NULL);
322 return (const gchar *)self->title;
323 }
324
325 void
frogr_photoset_set_title(FrogrPhotoSet * self,const gchar * title)326 frogr_photoset_set_title (FrogrPhotoSet *self,
327 const gchar *title)
328 {
329 g_return_if_fail(FROGR_IS_PHOTOSET(self));
330 g_return_if_fail(title != NULL);
331
332 g_free (self->title);
333 self->title = g_strdup (title);
334 }
335
336 const gchar *
frogr_photoset_get_description(FrogrPhotoSet * self)337 frogr_photoset_get_description (FrogrPhotoSet *self)
338 {
339 g_return_val_if_fail(FROGR_IS_PHOTOSET(self), NULL);
340 return (const gchar *)self->description;
341 }
342
343 void
frogr_photoset_set_description(FrogrPhotoSet * self,const gchar * description)344 frogr_photoset_set_description (FrogrPhotoSet *self,
345 const gchar *description)
346 {
347 g_return_if_fail(FROGR_IS_PHOTOSET(self));
348 g_free (self->description);
349 self->description = g_strdup (description);
350 }
351
352 const gchar *
frogr_photoset_get_id(FrogrPhotoSet * self)353 frogr_photoset_get_id (FrogrPhotoSet *self)
354 {
355 g_return_val_if_fail(FROGR_IS_PHOTOSET(self), NULL);
356 return (const gchar *)self->id;
357 }
358
359 void
frogr_photoset_set_id(FrogrPhotoSet * self,const gchar * id)360 frogr_photoset_set_id (FrogrPhotoSet *self,
361 const gchar *id)
362 {
363 g_return_if_fail(FROGR_IS_PHOTOSET(self));
364 g_free (self->id);
365 self->id = g_strdup (id);
366 }
367
368 const gchar *
frogr_photoset_get_local_id(FrogrPhotoSet * self)369 frogr_photoset_get_local_id (FrogrPhotoSet *self)
370 {
371 g_return_val_if_fail(FROGR_IS_PHOTOSET(self), NULL);
372 return (const gchar *)self->local_id;
373 }
374
375 void
frogr_photoset_set_local_id(FrogrPhotoSet * self,const gchar * id)376 frogr_photoset_set_local_id (FrogrPhotoSet *self,
377 const gchar *id)
378 {
379 g_return_if_fail(FROGR_IS_PHOTOSET(self));
380 g_free (self->local_id);
381 self->local_id = g_strdup (id);
382 }
383
384 const gchar *
frogr_photoset_get_primary_photo_id(FrogrPhotoSet * self)385 frogr_photoset_get_primary_photo_id (FrogrPhotoSet *self)
386 {
387 g_return_val_if_fail(FROGR_IS_PHOTOSET(self), NULL);
388 return (const gchar *)self->primary_photo_id;
389 }
390
391 void
frogr_photoset_set_primary_photo_id(FrogrPhotoSet * self,const gchar * primary_photo_id)392 frogr_photoset_set_primary_photo_id (FrogrPhotoSet *self,
393 const gchar *primary_photo_id)
394 {
395 g_return_if_fail(FROGR_IS_PHOTOSET(self));
396 g_free (self->primary_photo_id);
397 self->primary_photo_id = g_strdup (primary_photo_id);
398 }
399
400 gint
frogr_photoset_get_n_photos(FrogrPhotoSet * self)401 frogr_photoset_get_n_photos (FrogrPhotoSet *self)
402 {
403 g_return_val_if_fail(FROGR_IS_PHOTOSET(self), FALSE);
404 return self->n_photos;
405 }
406
407 void
frogr_photoset_set_n_photos(FrogrPhotoSet * self,gint n)408 frogr_photoset_set_n_photos (FrogrPhotoSet *self,
409 gint n)
410 {
411 g_return_if_fail(FROGR_IS_PHOTOSET(self));
412 self->n_photos = n;
413 }
414
415 gboolean
frogr_photoset_is_local(FrogrPhotoSet * self)416 frogr_photoset_is_local (FrogrPhotoSet *self)
417 {
418 g_return_val_if_fail(FROGR_IS_PHOTOSET(self), FALSE);
419 return self->id == NULL && self->local_id != NULL;
420 }
421
422 gint
frogr_photoset_compare(FrogrPhotoSet * self,FrogrPhotoSet * other)423 frogr_photoset_compare (FrogrPhotoSet *self, FrogrPhotoSet *other)
424 {
425 g_return_val_if_fail (FROGR_IS_PHOTOSET (self), 1);
426 g_return_val_if_fail (FROGR_IS_PHOTOSET (other), -1);
427
428 if (self == other)
429 return 0;
430
431 if (self->id != NULL && other->id != NULL)
432 return g_strcmp0 (self->id, other->id);
433
434 if (self->local_id != NULL && other->local_id != NULL)
435 return g_strcmp0 (self->local_id, other->local_id);
436
437 if (self->id != NULL)
438 return 1;
439 else
440 return -1;
441 }
442