1 /*
2 *  RAL -- Rubrica Addressbook Library
3 *  file: groups.c
4 *
5 *  Copyright (C) Nicola Fragale <nicolafragale@libero.it>
6 *
7 *  This program is free software; you can redistribute it and/or modify
8 *  it under the terms of the GNU General Public License as published by
9 *  the Free Software Foundation; either version 3 of the License
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
14 *  GNU 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, write to the Free Software
18 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20 
21 #include <time.h>
22 #include <glib.h>
23 #include <glib-object.h>
24 
25 #include "group_box.h"
26 #include "group.h"
27 
28 enum {
29   GROUP_ADDED,
30   GROUP_REMOVED,
31   GROUP_MODIFYED,
32 
33   LAST_SIGNAL
34 };
35 
36 static guint r_group_box_signals[LAST_SIGNAL] = {0};
37 
38 
39 struct _RGroupBoxPrivate {
40   GList* lst;
41   GList* iter;
42   GList* find;
43 
44   gboolean dispose_has_run;
45 };
46 
47 
48 static void r_group_box_class_init (RGroupBoxClass* klass);
49 static void r_group_box_init       (RGroupBox* obj);
50 
51 static void r_group_box_dispose    (RGroupBox* obj);
52 static void r_group_box_finalize   (RGroupBox* obj);
53 
54 /* Private
55 */
56 static gboolean delete_group(RGroupBox* box, gchar* name);
57 
58 
59 GType
r_group_box_get_type()60 r_group_box_get_type()
61 {
62   static GType group_box_type = 0;
63 
64   if (!group_box_type)
65     {
66       static const GTypeInfo group_box_info =
67 	{
68 	  sizeof(RGroupBoxClass),
69 	  NULL,
70 	  NULL,
71 	  (GClassInitFunc) r_group_box_class_init,
72 	  NULL,
73 	  NULL,
74 	  sizeof(RGroupBox),
75 	  0,
76 	  (GInstanceInitFunc) r_group_box_init
77 	};
78 
79       group_box_type = g_type_register_static (G_TYPE_OBJECT,
80 					       "RGroupBox",
81 					       &group_box_info, 0);
82     }
83 
84   return group_box_type;
85 }
86 
87 
88 static void
r_group_box_class_init(RGroupBoxClass * klass)89 r_group_box_class_init(RGroupBoxClass* klass)
90 {
91   GObjectClass *class;
92 
93   class           = G_OBJECT_CLASS (klass);
94   class->dispose  = (GObjectFinalizeFunc) r_group_box_dispose;
95   class->finalize = (GObjectFinalizeFunc) r_group_box_finalize;
96 
97 
98   /* class signals */
99   /**
100    * RGroupBox::group-added
101    * @box: the #RGroupBox that receives the signal
102    * @group: the group added to the box
103    *
104    * signal emitted when a new group is added to the group's box.
105    */
106   r_group_box_signals[GROUP_ADDED] =
107     g_signal_new("group_added",
108 		 R_GROUP_BOX_TYPE,
109 		 G_SIGNAL_RUN_LAST,
110 		 G_STRUCT_OFFSET(RGroupBoxClass, group_added),
111 		 NULL,
112 		 NULL,
113 		 g_cclosure_marshal_VOID__INT,
114 		 G_TYPE_NONE,            /* return type */
115 		 1,                      /* params      */
116 		 G_TYPE_POINTER);        /* params type */
117 
118   /**
119    * RGroupbox::group-removed
120    * @set: the #RGroupBox that receives the signal
121    * @group: the group removed from the set
122    *
123    * signal emitted when a group is removed from the group's set.
124    */
125   r_group_box_signals[GROUP_REMOVED] =
126     g_signal_new("group_removed",
127 		 R_GROUP_BOX_TYPE,
128 		 G_SIGNAL_RUN_LAST,
129 		 G_STRUCT_OFFSET(RGroupBoxClass, group_removed),
130 		 NULL,
131 		 NULL,
132 		 g_cclosure_marshal_VOID__INT,
133 		 G_TYPE_NONE,            /* return type */
134 		 1,                      /* params      */
135 		 G_TYPE_INT);            /* params type */
136 
137   /**
138    * RGroupbox::group-remamed
139    * @set: the #RGroupBox that receives the signal
140    * @group: the group remamed from the set
141    *
142    * signal emitted when a group is removed from the group's set.
143    */
144   r_group_box_signals[GROUP_MODIFYED] =
145     g_signal_new("group_modifyed",
146 		 R_GROUP_BOX_TYPE,
147 		 G_SIGNAL_RUN_LAST,
148 		 G_STRUCT_OFFSET(RGroupBoxClass, group_removed),
149 		 NULL,
150 		 NULL,
151 		 g_cclosure_marshal_VOID__INT,
152 		 G_TYPE_NONE,            /* return type */
153 		 1,                      /* params      */
154 		 G_TYPE_POINTER);       /* params type */
155 }
156 
157 
158 static void
r_group_box_init(RGroupBox * self)159 r_group_box_init(RGroupBox* self)
160 {
161   self->priv = g_new(RGroupBoxPrivate, 1);
162 
163   self->priv->lst  = NULL;
164   self->priv->iter = NULL;
165   self->priv->dispose_has_run = FALSE;
166 }
167 
168 
169 
170 static void
r_group_box_dispose(RGroupBox * self)171 r_group_box_dispose (RGroupBox* self)
172 {
173   GList* list;
174 
175   g_return_if_fail(IS_R_GROUP_BOX(self));
176 
177   if (self->priv->dispose_has_run)
178     return;
179 
180   for (list = self->priv->lst; list; list = g_list_next(list))
181     r_group_free(R_GROUP(list->data));
182 
183   g_list_free(self->priv->lst);
184 
185   self->priv->dispose_has_run = TRUE;
186 }
187 
188 
189 static void
r_group_box_finalize(RGroupBox * self)190 r_group_box_finalize (RGroupBox* self)
191 {
192   g_return_if_fail(IS_R_GROUP_BOX(self));
193 
194   g_free(self->priv);
195   self->priv = NULL;
196 }
197 
198 
199 static gboolean
delete_group(RGroupBox * box,gchar * name)200 delete_group(RGroupBox* box, gchar* name)
201 {
202   gint id;
203 
204   box->priv->iter = box->priv->lst;
205   for (; box->priv->iter; box->priv->iter = box->priv->iter->next)
206     {
207       RGroup* group = box->priv->iter->data;
208 
209       if (r_group_has_name(R_GROUP(group), name))
210 	{
211 	  g_object_get(group, "id", &id, NULL);
212 
213 	  box->priv->lst = g_list_remove_link(box->priv->lst, box->priv->iter);
214 
215 	  r_group_free(R_GROUP(box->priv->iter->data));
216 
217 	  g_list_free_1(box->priv->iter);
218 	  box->priv->iter = NULL;
219 
220 	  g_signal_emit_by_name(box, "group_removed", id, G_TYPE_INT);
221 
222 	  return TRUE;
223 	}
224     }
225 
226   return FALSE;
227 }
228 
229 
230 /*    Public
231 */
232 
233 /**
234  * r_group_box_
235  * @box: a #RGroupBox
236  *
237  * create a new #RGroupBox
238  *
239  * returns: a new allocated #RGroupBox*
240  */
241 RGroupBox*
r_group_box_new(void)242 r_group_box_new(void)
243 {
244   RGroupBox* box;
245 
246   box = g_object_new(r_group_box_get_type(), NULL);
247 
248   return box;
249 }
250 
251 
252 /**
253  * r_group_box_free
254  * @box: a #RGroupBox
255  *
256  * free memory owned by a #RGroupBox
257  */
258 void
r_group_box_free(RGroupBox * box)259 r_group_box_free(RGroupBox* box)
260 {
261   g_return_if_fail(IS_R_GROUP_BOX(box));
262 
263   g_object_unref(box);
264 }
265 
266 
267 /**
268  * r_group_box_is_empty
269  * @box: a #RGroupBox
270  *
271  * Test if the given group_box is empty
272  *
273  * Returns: %TRUE if the box is empty, %FALSE otherwise
274  */
275 gboolean
r_group_box_is_empty(RGroupBox * box)276 r_group_box_is_empty (RGroupBox* box)
277 {
278    g_return_val_if_fail(IS_R_GROUP_BOX(box), TRUE);
279 
280    return (box->priv->lst == NULL);
281 }
282 
283 
284 /**
285  * r_group_box_find
286  * @box: a #RGroupBox
287  * @group_name: a #RGroup's name
288  *
289  * find a group by name
290  *
291  * returns: a gpointer to the group with the given name, or %NULL if
292  * box haven't the group.
293  */
294 gpointer
r_group_box_find(RGroupBox * box,const gchar * group_name)295 r_group_box_find (RGroupBox* box, const gchar* group_name)
296 {
297   g_return_val_if_fail(IS_R_GROUP_BOX(box), NULL);
298   g_return_val_if_fail(group_name != NULL, NULL);
299 
300   box->priv->find = box->priv->lst;
301   for (; box->priv->find; box->priv->find = box->priv->find->next)
302     {
303       RGroup* grp = box->priv->find->data;
304 
305       if (r_group_has_name(R_GROUP(grp), group_name))
306 	return (gpointer) grp;
307     }
308 
309   return NULL;
310 }
311 
312 
313 /**
314  * r_group_box_find_groups_owned_by
315  * @box: a #RGroupBox
316  * @owner: a gchar*
317  *
318  * search for all groups owned by the given "owner"
319  *
320  * Returns: a #GList of #RGroup or NULL
321  */
322 GList*
r_group_box_find_groups_owned_by(RGroupBox * box,const gchar * owner)323 r_group_box_find_groups_owned_by (RGroupBox* box, const gchar* owner)
324 {
325   GList* ret = NULL;
326 
327   g_return_val_if_fail(IS_R_GROUP_BOX(box), NULL);
328   g_return_val_if_fail(owner != NULL, NULL);
329 
330   box->priv->find = box->priv->lst;
331   for (; box->priv->find; box->priv->find = box->priv->find->next)
332     {
333       RGroup* grp = box->priv->find->data;
334 
335       if (r_group_has_owner(R_GROUP(grp), owner))
336 	ret = g_list_append(ret, grp);
337     }
338 
339   return ret;
340 }
341 
342 
343 /**
344  * r_group_box_owns_group
345  * @box: a #RGroupBox
346  * @group_name: a #RGroup's name
347  *
348  * test if box owns the given group
349  *
350  * returns: a gboolean, %TRUE if box owns group, %FALSE otherwise
351  */
352 gboolean
r_group_box_owns_group(RGroupBox * box,const gchar * group_name)353 r_group_box_owns_group (RGroupBox* box, const gchar* group_name)
354 {
355   g_return_val_if_fail(IS_R_GROUP_BOX(box), FALSE);
356   g_return_val_if_fail(group_name != NULL, FALSE);
357 
358   if (r_group_box_find(box, group_name))
359     return TRUE;
360 
361   return FALSE;
362 }
363 
364 
365 /**
366  * r_group_box_add_group
367  * @box: a #RGroupBox
368  * @group: a #RGroup
369  *
370  * add the group to te box
371  *
372  * returns: a gboolean. %TRUE if group if added successfully, %FALSE otherwise
373  */
374 gboolean
r_group_box_add_group(RGroupBox * box,RGroup * group)375 r_group_box_add_group (RGroupBox* box, RGroup* group)
376 {
377   gchar* name;
378 
379   g_return_val_if_fail(IS_R_GROUP_BOX(box), FALSE);
380   g_return_val_if_fail(IS_R_GROUP(group), FALSE);
381 
382   /* test if group is already known
383    */
384   g_object_get(group, "group-name", &name, NULL);
385   if (r_group_box_owns_group(box, name))
386     return TRUE;
387 
388   /* else add to the box
389    */
390   box->priv->lst = g_list_append(box->priv->lst, group);
391 
392   /* init group iterator */
393   if (!box->priv->iter)
394     box->priv->iter = box->priv->lst;
395 
396   g_signal_emit_by_name(box, "group_added", group, G_TYPE_POINTER);
397 
398   return TRUE;
399 }
400 
401 
402 /**
403  * r_group_box_delete_group_by_name
404  * @box: a #RGroupBox
405  * @name: group's name
406  *
407  * delete a group from box
408  *
409  * returns: a gboolean. %TRUE if group is deleted, %FALSE otherwise
410  */
411 gboolean
r_group_box_delete_group_by_name(RGroupBox * box,gchar * name)412 r_group_box_delete_group_by_name (RGroupBox* box, gchar* name)
413 {
414   g_return_val_if_fail(IS_R_GROUP_BOX(box), FALSE);
415   g_return_val_if_fail(name != NULL, FALSE);
416 
417   return delete_group(box, name);
418 }
419 
420 
421 /**
422  * r_group_box_delete_group
423  * @box: a #RGroupBox
424  * @group: a #RGroup
425  *
426  * delete a group from box
427  *
428  * returns: a gboolean. %TRUE if group is deleted, %FALSE otherwise
429  */
430 gboolean
r_group_box_delete_group(RGroupBox * box,RGroup * group)431 r_group_box_delete_group (RGroupBox* box, RGroup* group)
432 {
433   gchar* name;
434 
435   g_return_val_if_fail(IS_R_GROUP_BOX(box), FALSE);
436   g_return_val_if_fail(IS_R_GROUP(group), FALSE);
437 
438   g_object_get(group, "group-name", &name, NULL);
439 
440   return r_group_box_delete_group_by_name(box, name);
441 }
442 
443 
444 /**
445  * r_group_box_modify_group_name
446  * @box: a #RGroupBox
447  * @oldname:
448  * @newname:
449  *
450  * rename a group in the box
451  *
452  * returns: a gboolean. %TRUE if group is modifyed, %FALSE otherwise
453  * If group is modifyed, the "group_modifyed" signal is emitted
454  */
455 gboolean
r_group_box_modify_group_name(RGroupBox * box,gchar * oldname,gchar * newname)456 r_group_box_modify_group_name (RGroupBox* box, gchar* oldname, gchar* newname)
457 {
458   RGroup* group;
459   //  gint id;
460 
461   g_return_val_if_fail(IS_R_GROUP_BOX(box), FALSE);
462   g_return_val_if_fail(oldname != NULL, FALSE);
463   g_return_val_if_fail(newname != NULL, FALSE);
464 
465   group = r_group_box_find(box, oldname);
466   if (r_group_rename(group, newname))
467     {
468       g_object_set(group, "group-label", newname, NULL);
469       //      g_object_get(group, "id", &id, NULL);
470 
471       g_signal_emit_by_name(box, "group_modifyed", group, G_TYPE_POINTER);
472 
473       return TRUE;
474     }
475 
476   return FALSE;
477 }
478 
479 /**
480  * r_group_box_modify_group_pixmap
481  * @box: a #RGroupBox
482  * @group_name:
483  * @newpixmap:
484  *
485  * modify the group's pixmap
486  *
487  * returns: a gboolean. %TRUE if group is modifyed, %FALSE otherwise.
488  * If group is modifyed, the "group_modifyed" signal is emitted
489  */
490 gboolean
r_group_box_modify_group_pixmap(RGroupBox * box,gchar * group_name,gchar * newpixmap)491 r_group_box_modify_group_pixmap (RGroupBox* box, gchar* group_name,
492 				 gchar* newpixmap)
493 {
494   RGroup* group;
495 
496   g_return_val_if_fail(IS_R_GROUP_BOX(box), FALSE);
497   g_return_val_if_fail(group_name != NULL, FALSE);
498   g_return_val_if_fail(newpixmap != NULL, FALSE);
499 
500   group = r_group_box_find(box, group_name);
501   if (r_group_change_pixmap (group, newpixmap))
502     {
503       g_signal_emit_by_name(box, "group_modifyed", group, G_TYPE_POINTER);
504 
505       return TRUE;
506     }
507 
508   return FALSE;
509 }
510 
511 
512 /**
513  * r_group_box_disable_all
514  * @box: a #RGroupBox
515  *
516  * disable all groups in box
517  */
518 void
r_group_box_disable_all(RGroupBox * box)519 r_group_box_disable_all (RGroupBox* box)
520 {
521   RGroup* group;
522 
523   g_return_if_fail(IS_R_GROUP_BOX(box));
524 
525   r_group_box_reset(box);
526   group = r_group_box_get_group(box);
527   for(; group; group = r_group_box_get_next_group(box))
528     g_object_set(group, "enabled", FALSE, NULL);
529 }
530 
531 
532 /**
533  * r_group_box_enable_group
534  * @box: a #RGroupBox
535  * @group: a #RGroup
536  *
537  * enable the given group
538  */
539 void
r_group_box_enable_group(RGroupBox * box,RGroup * grp)540 r_group_box_enable_group (RGroupBox* box, RGroup* grp)
541 {
542   gchar* name;
543   RGroup* group = NULL;
544 
545   g_return_if_fail(IS_R_GROUP_BOX(box));
546   g_return_if_fail(IS_R_GROUP(grp));
547 
548   g_object_get(grp, "group-name", &name, NULL);
549   group = r_group_box_find(box, name);
550 
551   if (group)
552     g_object_set(group, "enabled", TRUE, NULL);
553 }
554 
555 
556 /**
557  * r_group_box_disable_group
558  * @box: a #RGroupBox
559  * @group: a #RGroup
560  *
561  * disable the given group
562  */
563 void
r_group_box_disable_group(RGroupBox * box,RGroup * grp)564 r_group_box_disable_group (RGroupBox* box, RGroup* grp)
565 {
566   gchar* name;
567   RGroup* group = NULL;
568 
569   g_return_if_fail(IS_R_GROUP_BOX(box));
570   g_return_if_fail(IS_R_GROUP(grp));
571 
572   g_object_get(grp, "group-name", &name, NULL);
573   group = r_group_box_find(box, name);
574   if (group)
575     g_object_set(group, "enabled", FALSE, NULL);
576 }
577 
578 
579 
580 
581 /**
582  * r_group_box_merge_boxes
583  * @box: a #RGroupBox
584  * @second: a #RGroupBox
585  *
586  * merges the #RGroupBoxs
587  *
588  *returns: a RGroupBox*
589  */
590 RGroupBox*
r_group_box_merge_boxes(RGroupBox * box,RGroupBox * second)591 r_group_box_merge_boxes (RGroupBox* box, RGroupBox* second)
592 {
593   g_return_val_if_fail(IS_R_GROUP_BOX(box), NULL);
594   g_return_val_if_fail(IS_R_GROUP_BOX(second), box);
595 
596   box->priv->lst = g_list_concat(box->priv->lst, second->priv->lst);
597 
598   return box;
599 }
600 
601 
602 /**
603  * r_group_box_reset
604  * @box: a #RGroupBox
605  *
606  * reset the private #RGroupBox iterator to the head of group's list.
607  */
608 void
r_group_box_reset(RGroupBox * box)609 r_group_box_reset(RGroupBox* box)
610 {
611   g_return_if_fail(IS_R_GROUP_BOX(box));
612 
613   box->priv->iter = box->priv->lst;
614 }
615 
616 
617 /**
618  * r_group_box_get_group
619  * @box: a #RGroupBox
620  *
621  * get the first group in box
622  *
623  * returns: a gpointer or NULL if box is void
624  */
625 RGroup*
r_group_box_get_group(RGroupBox * box)626 r_group_box_get_group (RGroupBox* box)
627 {
628   g_return_val_if_fail(IS_R_GROUP_BOX(box), NULL);
629 
630   if (box->priv->iter)
631     return (RGroup*) box->priv->iter->data;
632 
633   return NULL;
634 }
635 
636 
637 /**
638  * r_group_box_get_next_group
639  * @box: a #RGroupBox
640  *
641  * get the next group in box.
642  *
643  * returns: a gpointer or NULL if the groups's end list is reached.
644  */
645 RGroup*
r_group_box_get_next_group(RGroupBox * box)646 r_group_box_get_next_group (RGroupBox* box)
647 {
648   g_return_val_if_fail(IS_R_GROUP_BOX(box), NULL);
649 
650   box->priv->iter = g_list_next(box->priv->iter);
651   if (box->priv->iter)
652     return (RGroup*) box->priv->iter->data;
653   else
654     box->priv->iter = box->priv->lst;
655 
656   return NULL;
657 }
658 
659 
660 /**
661  * r_group_box_get_prev_group
662  * @box: a #RGroupBox
663  *
664  * get the previous group in box.
665  *
666  * returns: a gpointer or NULL if the groups's head list is reached.
667  */
668 RGroup*
r_group_box_get_prev_group(RGroupBox * box)669 r_group_box_get_prev_group (RGroupBox* box)
670 {
671   g_return_val_if_fail(IS_R_GROUP_BOX(box), NULL);
672 
673   g_return_val_if_fail(IS_R_GROUP_BOX(box), NULL);
674 
675   box->priv->iter = g_list_previous(box->priv->iter);
676   if (box->priv->iter)
677     return (RGroup*) box->priv->iter->data;
678   else
679     box->priv->iter = box->priv->lst;
680 
681   return NULL;
682 }
683 
684 
685 
686 
687 
688 
689 
690