1 /*
2 * RAL -- Rubrica Addressbook Library
3 * file: abook.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 <string.h>
23 #include <glib.h>
24 #include <glib-object.h>
25 #include <glib/gstdio.h>
26 #include <glib/gi18n-lib.h>
27
28 #include "rlib.h"
29 #include "manager.h"
30 #include "plugin.h"
31 #include "abook.h"
32 #include "card.h"
33 #include "personal.h"
34 #include "company.h"
35 #include "group_box.h"
36 #include "utils.h"
37 #include "error.h"
38
39
40 /* property enumeration
41 */
42 enum {
43 ABOOK_NAME = 1,
44 ABOOK_PATH,
45 DELETED_CARDS,
46 SELECTED_ID,
47 MARKED_CARDS,
48 PRINTABLE_CARDS,
49 MODIFYED,
50 FILE_FILTER,
51 };
52
53
54 struct _RAbookPrivate {
55 gchar* name; /* the addressbook (the file) name */
56 gchar* path; /* the addressbook (the file) path */
57 gchar* filter; /* filter/plugin setted from filechooser */
58
59 gboolean modifyed; /* was addressbook modifyed? */
60 gulong selected_id; /* selected card id */
61 gint deleted; /* cards marked deleted in addressbook */
62 gint marked; /* how many marked cards */
63 gint printable; /* how many printable cards */
64
65 RGroupBox* box;
66
67 GList* cards;
68 GList* trash;
69 GList* iter;
70
71 RPluginManager* manager;
72 RPlugin* plugin; /* RPlugin */
73 gpointer engine; /* ptr to the real plugin (a gobject) */
74
75 gboolean dispose_has_run;
76 };
77
78
79 #define R_ABOOK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
80 R_ABOOK_TYPE, RAbookPrivate))
81
82
83 /* signals enumeration
84 */
85 enum {
86 OPEN_FAIL, /* file not opened */
87 SAVE_FAIL, /* file not saved */
88
89 ADDRESSBOOK_CHANGED, /* addressbook changed */
90 ADDRESSBOOK_READ, /* file read */
91 ADDRESSBOOK_SAVED, /* file saved */
92 ADDRESSBOOK_CLOSED,
93
94 CARD_READ, /* card read */
95 CARD_ADDED, /* card added to addressbook */
96 CARD_DELETED, /* card deleted from addressbook and moved to trash */
97 CARD_DESTROYED, /* card destroyed */
98 CARD_RECOVERED, /* card recoverd from trash */
99 CARD_REPLACED, /* card replaced in addressbook */
100
101 CARD_CUTTED,
102 CARD_PASTED,
103 NEED_NAME,
104
105 LAST_SIGNAL
106 };
107
108 static guint r_abook_signals[LAST_SIGNAL] = {0};
109
110
111 static void r_abook_class_init (RAbookClass* klass);
112 static void r_abook_init (RAbook* obj);
113
114 static void r_abook_dispose (RAbook* obj);
115 static void r_abook_finalize (RAbook* obj);
116
117 static void r_abook_set_property (GObject* obj, guint property_id,
118 GValue* value, GParamSpec* spec);
119 static void r_abook_get_property (GObject* obj, guint property_id,
120 GValue* value, GParamSpec* spec);
121
122
123
124 static gchar* _r_get_file_extension (gchar* string);
125 static gchar* _r_get_plugin_extension (RPlugin* plugin);
126 static gboolean _r_try_all_plugins (RAbook *abook, gchar* fname);
127 static void _r_abook_add_card (RAbook* abook, RCard* card,
128 gboolean emit_signals);
129
130 static void on_group_removed (RGroupBox *box, gint grp_id,
131 gpointer data);
132 static void on_group_modifyed (RGroupBox *box, gpointer grp,
133 gpointer data);
134
135
136
137
138
139 GType
r_abook_get_type()140 r_abook_get_type()
141 {
142 static GType r_abook_type = 0;
143
144 if (!r_abook_type)
145 {
146 static const GTypeInfo r_abook_info =
147 {
148 sizeof(RAbookClass),
149 NULL,
150 NULL,
151 (GClassInitFunc) r_abook_class_init,
152 NULL,
153 NULL,
154 sizeof(RAbook),
155 0,
156 (GInstanceInitFunc) r_abook_init
157 };
158
159 r_abook_type = g_type_register_static (G_TYPE_OBJECT, "RAbook",
160 &r_abook_info, 0);
161 }
162
163 return r_abook_type;
164 }
165
166
167 static void
r_abook_class_init(RAbookClass * klass)168 r_abook_class_init(RAbookClass* klass)
169 {
170 GObjectClass *class;
171 GParamSpec* pspec;
172
173 class = G_OBJECT_CLASS (klass);
174
175 class->dispose = (GObjectFinalizeFunc) r_abook_dispose;
176 class->finalize = (GObjectFinalizeFunc) r_abook_finalize;
177 class->set_property = (gpointer) r_abook_set_property;
178 class->get_property = (gpointer) r_abook_get_property;
179
180 klass->abook_open_file = NULL;
181 klass->abook_save_file = NULL;
182 klass->abook_overwrite = NULL;
183
184 g_type_class_add_private (klass, sizeof(RAbookPrivate));
185
186 /* class signals
187 */
188 /**
189 * RAbook::open-fail:
190 * @abook: the #RAbook object that receives the signal
191 * @err: an #RError
192 *
193 * the "open-fail" signal is emitted if the given file can't be read
194 */
195 r_abook_signals[OPEN_FAIL] =
196 g_signal_new("open_fail",
197 R_ABOOK_TYPE,
198 G_SIGNAL_RUN_LAST,
199 G_STRUCT_OFFSET(RAbookClass, open_fail),
200 NULL,
201 NULL,
202 g_cclosure_marshal_VOID__INT,
203 G_TYPE_NONE, /* return type */
204 1, /* params */
205 G_TYPE_INT); /* params type: error code */
206
207 /**
208 * RAbook::save-fail:
209 * @abook: the #RAbook object that receives the signal
210 * @err: an #RError
211 *
212 * the "save-fail" signal is emitted if the given file can't be read
213 */
214 r_abook_signals[SAVE_FAIL] =
215 g_signal_new("save_fail",
216 R_ABOOK_TYPE,
217 G_SIGNAL_RUN_LAST,
218 G_STRUCT_OFFSET(RAbookClass, save_fail),
219 NULL,
220 NULL,
221 g_cclosure_marshal_VOID__INT,
222 G_TYPE_NONE, /* return type */
223 1, /* params */
224 G_TYPE_INT); /* params type: error code */
225
226 /**
227 * RAbook::card-read:
228 * @abook: the #RAbook object that receives the signal
229 * @data: a pointer to the readed card
230 *
231 * The "card-read" signal is emitted after the addressbook has been readed
232 */
233 r_abook_signals[CARD_READ] =
234 g_signal_new("card_read",
235 R_ABOOK_TYPE,
236 G_SIGNAL_RUN_LAST,
237 G_STRUCT_OFFSET(RAbookClass, card_read),
238 NULL,
239 NULL,
240 g_cclosure_marshal_VOID__POINTER,
241 G_TYPE_NONE,
242 1,
243 G_TYPE_POINTER);
244
245 /**
246 * RAbook::card-added:
247 * @abook: the #RAbook object that receives the signal
248 * @data: a pointer to the readed card
249 *
250 * The "card-added" signal is emitted after a card is added to addressbook.
251 * A pointer to the card is passed to the callback function
252 */
253 r_abook_signals[CARD_ADDED] =
254 g_signal_new("card_added",
255 R_ABOOK_TYPE,
256 G_SIGNAL_RUN_LAST,
257 G_STRUCT_OFFSET(RAbookClass, card_added),
258 NULL,
259 NULL,
260 g_cclosure_marshal_VOID__POINTER,
261 G_TYPE_NONE,
262 1,
263 G_TYPE_POINTER);
264
265 /**
266 * RAbook::card-deleted:
267 * @abook: the #RAbook object that receives the signal
268 *
269 * The "card-removed" signal is emitted when a card is
270 * (deleted) removed from addressbook. The removed cards are
271 * marked as deleted, to really delete (remove) the card
272 * you must destroy it. You can recover (deleted) removed cards.
273 * Destroyed cards are unrecoverable
274 */
275 r_abook_signals[CARD_DELETED] =
276 g_signal_new("card_deleted",
277 R_ABOOK_TYPE,
278 G_SIGNAL_RUN_LAST,
279 G_STRUCT_OFFSET(RAbookClass, card_deleted),
280 NULL,
281 NULL,
282 g_cclosure_marshal_VOID__POINTER,
283 G_TYPE_NONE,
284 1,
285 G_TYPE_POINTER);
286
287 /**
288 * RAbook::card-destroyed:
289 * @abook: the #RAbook object that receives the signal
290 *
291 * The "card-destroyed" signal is emitted when a card is
292 * deleted from addressbook. Destroyed cards are unrecoverable.
293 */
294 r_abook_signals[CARD_DESTROYED] =
295 g_signal_new("card_destroyed",
296 R_ABOOK_TYPE,
297 G_SIGNAL_RUN_LAST,
298 G_STRUCT_OFFSET(RAbookClass, card_destroyed),
299 NULL,
300 NULL,
301 g_cclosure_marshal_VOID__STRING,
302 G_TYPE_NONE,
303 1,
304 G_TYPE_STRING);
305
306 /**
307 * RAbook::card-recovered:
308 * @abook: the #RAbook object that receives the signal
309 *
310 * The "card-recovered" signal is emitted when a previously deleted
311 * marked card is unmarked.
312 */
313 r_abook_signals[CARD_RECOVERED] =
314 g_signal_new("card_recovered",
315 R_ABOOK_TYPE,
316 G_SIGNAL_RUN_LAST,
317 G_STRUCT_OFFSET(RAbookClass, card_recovered),
318 NULL,
319 NULL,
320 g_cclosure_marshal_VOID__POINTER,
321 G_TYPE_NONE,
322 1,
323 G_TYPE_POINTER);
324
325 /**
326 * RAbook::card-replaced:
327 * @abook: the #RAbook object that receives the signal
328 * @data: a pointer to the readed card
329 *
330 * The "card-replaced" signal is emitted on a card replacement.
331 * A pointer to the new card is passed to the callback function
332 */
333 r_abook_signals[CARD_REPLACED] =
334 g_signal_new("card_replaced",
335 R_ABOOK_TYPE,
336 G_SIGNAL_RUN_LAST,
337 G_STRUCT_OFFSET(RAbookClass, card_replaced),
338 NULL,
339 NULL,
340 g_cclosure_marshal_VOID__POINTER,
341 G_TYPE_NONE,
342 1,
343 G_TYPE_POINTER);
344
345 /**
346 * RAbook::card-cutted
347 * @abook: the #RAbook object that receives the signal
348 * @data: a pointer to the cutted card
349 *
350 * The "card-cutted" signal is emitted when a card in the
351 * addressbook is cutted.
352 * A pointer to the cutted card is passed to the callback function
353 */
354 r_abook_signals[CARD_CUTTED] =
355 g_signal_new("card_cutted",
356 R_ABOOK_TYPE,
357 G_SIGNAL_RUN_LAST,
358 G_STRUCT_OFFSET(RAbookClass, card_cutted),
359 NULL,
360 NULL,
361 g_cclosure_marshal_VOID__POINTER,
362 G_TYPE_NONE,
363 1,
364 G_TYPE_POINTER);
365
366
367 /**
368 * RAbook::need-name:
369 * @abook: the #RAbook object that receives the signal
370 *
371 * The "need-name" signal is emitted if user
372 * tries to save an addressbook without giving a filename to it
373 */
374 r_abook_signals[NEED_NAME] =
375 g_signal_new("need_name",
376 R_ABOOK_TYPE,
377 G_SIGNAL_RUN_LAST,
378 G_STRUCT_OFFSET(RAbookClass, need_name),
379 NULL,
380 NULL,
381 g_cclosure_marshal_VOID__VOID,
382 G_TYPE_NONE,
383 0,
384 G_TYPE_NONE);
385
386 /**
387 * RAbook::addressbook-read:
388 * @abook: the #RAbook object that receives the signal
389 *
390 * The "addressbook-read" signal is emitted when the
391 * addressbook is read
392 */
393 r_abook_signals[ADDRESSBOOK_READ] =
394 g_signal_new("addressbook_read",
395 R_ABOOK_TYPE,
396 G_SIGNAL_RUN_LAST,
397 G_STRUCT_OFFSET(RAbookClass, addressbook_read),
398 NULL,
399 NULL,
400 g_cclosure_marshal_VOID__VOID,
401 G_TYPE_NONE,
402 0,
403 G_TYPE_NONE);
404
405 /**
406 * RAbook::addressbook-saved:
407 * @abook: the #RAbook object that receives the signal
408 *
409 * The "addressbook_saved" signal
410 */
411 r_abook_signals[ADDRESSBOOK_SAVED] =
412 g_signal_new("addressbook_saved",
413 R_ABOOK_TYPE,
414 G_SIGNAL_RUN_LAST,
415 G_STRUCT_OFFSET(RAbookClass, addressbook_saved),
416 NULL,
417 NULL,
418 g_cclosure_marshal_VOID__VOID,
419 G_TYPE_NONE,
420 0,
421 G_TYPE_NONE);
422
423 /**
424 * RAbook::addressbook-changed:
425 * @abook: the #RAbook object that receives the signal
426 *
427 * The "addressbook_changed" signal
428 */
429 r_abook_signals[ADDRESSBOOK_CHANGED] =
430 g_signal_new("addressbook_changed",
431 R_ABOOK_TYPE,
432 G_SIGNAL_RUN_LAST,
433 G_STRUCT_OFFSET(RAbookClass, addressbook_changed),
434 NULL,
435 NULL,
436 g_cclosure_marshal_VOID__VOID,
437 G_TYPE_NONE,
438 0,
439 G_TYPE_NONE);
440
441
442 /**
443 * RAbook::addressbook-closed:
444 * @abook: the #RAbook object that receives the signal
445 *
446 * The "addressbook_closed" signal
447 */
448 r_abook_signals[ADDRESSBOOK_CLOSED] =
449 g_signal_new("addressbook_closed",
450 R_ABOOK_TYPE,
451 G_SIGNAL_RUN_LAST,
452 G_STRUCT_OFFSET(RAbookClass, addressbook_closed),
453 NULL,
454 NULL,
455 g_cclosure_marshal_VOID__VOID,
456 G_TYPE_NONE,
457 0,
458 G_TYPE_NONE);
459
460
461 /**
462 * ABook:addressbook-name
463 *
464 * address book's name
465 */
466 pspec = g_param_spec_string("addressbook-name",
467 "addressbook's name",
468 "the name (filename) of the addressbook",
469 NULL,
470 G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
471 g_object_class_install_property(class, ABOOK_NAME, pspec);
472
473 /**
474 * ABook:addressbook-path
475 *
476 * address book's path
477 */
478 pspec = g_param_spec_string("addressbook-path",
479 "addressbook's path",
480 "the path of the addressbook",
481 NULL,
482 G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
483 g_object_class_install_property(class, ABOOK_PATH, pspec);
484
485
486 /**
487 * ABook:deleted-cards
488 *
489 * the number of cards marked as deleted in the addressbook
490 */
491 pspec = g_param_spec_int("deleted-cards",
492 "deleted cards",
493 "number of cards marked as deleted "
494 "in the addressbook",
495 G_MININT,
496 G_MAXINT,
497 0,
498 G_PARAM_READABLE);
499 g_object_class_install_property(class, DELETED_CARDS, pspec);
500
501
502 /**
503 * ABook:selected-id
504 *
505 * the id of the selected card
506 */
507 pspec = g_param_spec_long("selected-id",
508 "selected card's id",
509 "The id of the selected card",
510 G_MINLONG,
511 G_MAXLONG,
512 0,
513 G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
514 g_object_class_install_property(class, SELECTED_ID, pspec);
515
516 /**
517 * ABook:addressbook-modifyed
518 *
519 * Check if the addressbook was modifyed
520 */
521 pspec = g_param_spec_boolean("addressbook-modifyed",
522 "addressbook modifyed",
523 "check if addressbook was modifyed",
524 FALSE,
525 G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
526 g_object_class_install_property(class, MODIFYED, pspec);
527
528 /**
529 * ABook:cards-marked
530 *
531 * Check if the all addressbook's cards are marked
532 */
533 pspec = g_param_spec_int("marked-cards",
534 "marked cards",
535 "check how many addressbooks's cards are marked",
536 0,
537 G_MAXINT,
538 0,
539 G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
540 g_object_class_install_property(class, MARKED_CARDS, pspec);
541
542 /**
543 * ABook:printable-cards
544 *
545 * how many cards are marked as printable
546 */
547 pspec = g_param_spec_int("printable-cards",
548 "printable cards",
549 "how many cards are marked printable",
550 0,
551 G_MAXINT,
552 0,
553 G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
554 g_object_class_install_property(class, MARKED_CARDS, pspec);
555
556 /**
557 * ABook:file-filter
558 *
559 * File filter. It indentifies the addressbook's fileformat and
560 * the plugin that will be loaded to manage this fileformat.
561 */
562 pspec = g_param_spec_string("file-filter",
563 "file filter",
564 "filter used to identify the file's type",
565 NULL,
566 G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
567 g_object_class_install_property(class, FILE_FILTER, pspec);
568 }
569
570
571
572 static void
r_abook_set_property(GObject * obj,guint property_id,GValue * value,GParamSpec * spec)573 r_abook_set_property (GObject* obj, guint property_id,
574 GValue* value, GParamSpec* spec)
575 {
576 RAbook *self = (RAbook*) obj;
577
578 switch(property_id)
579 {
580 case ABOOK_NAME:
581 if (self->priv->name)
582 g_free(self->priv->name);
583 self->priv->name = g_value_dup_string(value);
584 break;
585
586 case ABOOK_PATH:
587 g_free(self->priv->path);
588 self->priv->path = g_value_dup_string(value);
589 break;
590
591 case DELETED_CARDS:
592 break;
593
594 case SELECTED_ID:
595 self->priv->selected_id = g_value_get_long(value);
596 break;
597
598 case MODIFYED:
599 self->priv->modifyed = g_value_get_boolean(value);
600 break;
601
602 case MARKED_CARDS:
603 self->priv->marked = g_value_get_int(value);
604 break;
605
606 case PRINTABLE_CARDS:
607 self->priv->printable = g_value_get_int(value);
608 break;
609
610 case FILE_FILTER:
611 self->priv->filter = g_value_dup_string(value);
612 break;
613
614 default:
615 break;
616 }
617 }
618
619
620 static void
r_abook_get_property(GObject * obj,guint property_id,GValue * value,GParamSpec * spec)621 r_abook_get_property (GObject* obj, guint property_id,
622 GValue* value, GParamSpec* spec)
623 {
624 RAbook *self = (RAbook*) obj;
625
626 switch(property_id)
627 {
628 case ABOOK_NAME:
629 g_value_set_string(value, self->priv->name);
630 break;
631
632 case ABOOK_PATH:
633 g_value_set_string(value, self->priv->path);
634 break;
635
636 case DELETED_CARDS:
637 g_value_set_int(value, self->priv->deleted);
638 break;
639
640 case MODIFYED:
641 g_value_set_boolean(value, self->priv->modifyed);
642 break;
643
644 case MARKED_CARDS:
645 g_value_set_int(value, self->priv->marked);
646 break;
647
648 case PRINTABLE_CARDS:
649 g_value_set_int(value, self->priv->printable);
650 break;
651
652 case SELECTED_ID:
653 g_value_set_long(value, self->priv->selected_id);
654 break;
655
656 default:
657 break;
658 }
659 }
660
661
662 static void
r_abook_init(RAbook * self)663 r_abook_init(RAbook* self)
664 {
665 self->priv = R_ABOOK_GET_PRIVATE(self);
666
667 self->priv->name = NULL;
668 self->priv->path = NULL;
669 self->priv->filter = NULL;
670
671 self->priv->modifyed = FALSE;
672 self->priv->selected_id = 0L;
673 self->priv->deleted = 0;
674 self->priv->marked = 0;
675 self->priv->printable = 0;
676
677 self->priv->box = r_lib_get_group_box();
678
679 self->priv->cards = NULL;
680 self->priv->trash = NULL;
681 self->priv->iter = NULL;
682
683 self->priv->manager = r_lib_get_manager();
684 self->priv->plugin = r_plugin_manager_get_plugin(self->priv->manager,
685 "rubrica");
686 self->priv->engine = r_plugin_get_engine(self->priv->plugin);
687
688 r_lib_admit (self);
689
690 self->priv->dispose_has_run = FALSE;
691
692 g_signal_connect(G_OBJECT (self->priv->box), "group_removed",
693 G_CALLBACK (on_group_removed), self);
694
695 g_signal_connect(G_OBJECT (self->priv->box), "group_modifyed",
696 G_CALLBACK (on_group_modifyed), self);
697 }
698
699
700
701 static void
r_abook_dispose(RAbook * self)702 r_abook_dispose (RAbook* self)
703 {
704 RAbookPrivate* priv;
705
706 g_return_if_fail(IS_R_ABOOK(self));
707
708 priv = R_ABOOK_GET_PRIVATE(self);
709
710 /* free the list's items (PersonalCard or CompanyCard)
711 */
712 priv->iter = priv->cards;
713 for (; priv->iter; priv->iter = priv->iter->next)
714 {
715 RCard* card = priv->iter->data;
716
717 if (IS_R_CARD(card))
718 r_card_free(R_CARD(card));
719 }
720
721 g_list_free(priv->cards);
722 g_list_free(priv->trash);
723 priv->cards = NULL;
724 priv->trash = NULL;
725 priv->iter = NULL;
726
727 r_plugin_free(priv->plugin);
728
729 if (priv->dispose_has_run)
730 return;
731
732 priv->dispose_has_run = TRUE;
733 }
734
735
736 static void
r_abook_finalize(RAbook * self)737 r_abook_finalize (RAbook* self)
738 {
739 RAbookPrivate* priv;
740
741 g_return_if_fail(IS_R_ABOOK(self));
742
743 priv = R_ABOOK_GET_PRIVATE(self);
744
745 r_utils_free_string(priv->name);
746 r_utils_free_string(priv->path);
747 r_utils_free_string(priv->filter);
748 }
749
750
751 static gchar*
_r_get_file_extension(gchar * string)752 _r_get_file_extension (gchar* string)
753 {
754 gint len;
755
756 if (!string)
757 return NULL;
758
759 len = strlen(string);
760 for(; len; len --)
761 {
762 if (string[len] == '.')
763 {
764 char* tmp;
765
766 tmp = g_strdup(&string[len+1]);
767
768 return tmp;
769 }
770 }
771
772 return NULL;
773 }
774
775 static gchar*
_r_get_plugin_extension(RPlugin * plugin)776 _r_get_plugin_extension(RPlugin* plugin)
777 {
778 GList *filters = NULL;
779 RFilter* filter;
780 gchar* ext = NULL;
781
782 g_return_val_if_fail(IS_R_PLUGIN(plugin), NULL);
783
784 filters = r_plugin_get_filters(plugin);
785
786 if (filters && filters->data)
787 {
788 filter = (RFilter*) filters->data;
789 g_object_get(filter, "filter-extension", &ext, NULL);
790 }
791
792 return ext;
793 }
794
795
796 static gboolean
_r_try_all_plugins(RAbook * abook,gchar * fname)797 _r_try_all_plugins(RAbook *abook, gchar* fname)
798 {
799 RAbookClass* class;
800 gint n, i = 0;
801
802 g_return_val_if_fail(IS_R_ABOOK(abook), FALSE);
803
804 class = R_ABOOK_GET_CLASS(abook);
805
806 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, " ");
807
808 n = r_plugin_manager_how_many(abook->priv->manager);
809 for (; i < n; i++)
810 {
811 RPlugin* plugin;
812 gchar *name, *label;
813
814 plugin = r_plugin_manager_get_nth_plugin(abook->priv->manager, i);
815 g_object_get(plugin, "plugin-name", &name, "plugin-label", &label, NULL);
816
817 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Trying plugin: %s (%s)",
818 name, label);
819
820 if (r_abook_load_plugin(abook, name))
821 {
822 if(class->abook_open_file(abook, fname))
823 {
824 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Used %s plugin", name);
825 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, " ");
826
827 return TRUE;
828 }
829 }
830 else
831 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Can't load %s plugin", name);
832 }
833
834 return FALSE;
835 }
836
837
838 static void
_r_abook_add_card(RAbook * abook,RCard * card,gboolean emit_signals)839 _r_abook_add_card(RAbook* abook, RCard* card, gboolean emit_signals)
840 {
841 GList* user_groups = NULL;
842 RAbookPrivate* priv;
843 gboolean deleted = FALSE;
844 glong id;
845
846 g_return_if_fail(IS_R_ABOOK(abook));
847
848 priv = R_ABOOK_GET_PRIVATE(abook);
849
850 user_groups = r_card_get_groups_owned_by(R_CARD(card), "user");
851 for (; user_groups; user_groups = user_groups->next)
852 r_group_box_add_group(abook->priv->box, R_GROUP(user_groups->data));
853
854 /* check if the card is marked deleted */
855 g_object_get(card, "card-id", &id, "card-deleted", &deleted, NULL);
856 if (deleted)
857 {
858 priv->deleted++;
859 priv->trash = g_list_append(priv->trash, (gpointer) id);
860 }
861
862 priv->cards = g_list_append(priv->cards, card);
863 priv->iter = priv->cards;
864
865 if (emit_signals)
866 {
867 g_signal_emit_by_name(abook, "card_added", card, G_TYPE_POINTER);
868 g_signal_emit_by_name(abook, "addressbook_changed", NULL, G_TYPE_NONE);
869 }
870 }
871
872
873
874 static void
on_group_removed(RGroupBox * box,gint grp_id,gpointer data)875 on_group_removed (RGroupBox *box, gint grp_id, gpointer data)
876 {
877 RAbook *book = R_ABOOK(data);
878 RAbookPrivate* priv = R_ABOOK_GET_PRIVATE(book);
879
880 priv->modifyed = TRUE;
881 g_signal_emit_by_name(book, "addressbook_changed", NULL, G_TYPE_NONE);
882 }
883
884
885 static void
on_group_modifyed(RGroupBox * box,gpointer grp,gpointer data)886 on_group_modifyed (RGroupBox *box, gpointer grp, gpointer data)
887 {
888 RAbook *book = R_ABOOK(data);
889 RAbookPrivate* priv = R_ABOOK_GET_PRIVATE(book);;
890
891 priv->modifyed = TRUE;
892 g_signal_emit_by_name(book, "addressbook_changed", NULL, G_TYPE_NONE);
893 }
894
895
896
897 /* ***************************** Public *****************************
898 */
899
900
901 /**
902 * r_abook_new
903 *
904 * create a #RAbook
905 *
906 * Returns: a new #RAbook
907 */
908 RAbook*
r_abook_new(void)909 r_abook_new(void)
910 {
911 RAbook* abook;
912
913 if (!r_lib_is_running())
914 g_error("\nLibral is not running");
915
916 abook = g_object_new(r_abook_get_type(), NULL);
917
918 return abook;
919 }
920
921
922 /**
923 * r_abook_free
924 * @abook: a #RAbook
925 *
926 * free the #RAbook
927 * The "addressbook_closed" signal is emitted
928 */
929 void
r_abook_free(RAbook * abook)930 r_abook_free(RAbook* abook)
931 {
932 g_return_if_fail(IS_R_ABOOK(abook));
933
934 g_signal_emit_by_name(abook, "addressbook_closed", NULL, G_TYPE_NONE);
935
936 g_object_unref(abook);
937 }
938
939
940
941 /**
942 * r_abook_open_file
943 * @abook: a #RAbook
944 * @fname: the name of the addressbook
945 *
946 * open the addressbook with given name
947 *
948 * Returns: %TRUE if file is opened successfully, %FALSE otherwise
949 */
950 gboolean
r_abook_open_file(RAbook * abook,gchar * fname)951 r_abook_open_file (RAbook* abook, gchar* fname)
952 {
953 RAbookClass* class;
954 RAbookPrivate* priv;
955 gboolean result = FALSE;
956
957 g_return_val_if_fail(IS_R_ABOOK(abook), FALSE);
958
959 priv = R_ABOOK_GET_PRIVATE(abook);
960 class = R_ABOOK_GET_CLASS(abook);
961
962 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, " ");
963 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Opening %s ...", fname);
964
965 if (g_ascii_strcasecmp(priv->filter, "autodetect") == 0)
966 {
967 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_INFO, "Try to determine the file's type");
968
969 result = _r_try_all_plugins(abook, fname);
970 }
971 else
972 {
973 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Opening file with %s plugin",
974 priv->filter);
975
976 if (r_abook_load_plugin(abook, priv->filter))
977 result = class->abook_open_file(abook, fname);
978 }
979
980 if (result)
981 {
982 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "addressbook: %s",
983 abook->priv->name);
984 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "path: %s", abook->priv->path);
985
986 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "%s opened successfully", fname);
987 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Cards in this addressbook: %d",
988 r_abook_get_items(R_ABOOK(abook)));
989 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Cards marked as deleted: %d",
990 abook->priv->deleted);
991 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, " ");
992
993 return TRUE;
994 }
995
996 // error occurred during file loading
997 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "%s open failed", fname);
998 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, " ");
999
1000 return FALSE;
1001 }
1002
1003
1004
1005 /**
1006 * r_abook_save_file
1007 * @abook: a #RAbook
1008 * @fname: the name of file
1009 *
1010 * save the addressbook with given filename
1011 *
1012 * Returns: %TRUE if file is saved successfully, %FALSE otherwise
1013 */
1014 gboolean
r_abook_save_file(RAbook * abook,gchar * fname,gint compression_rate)1015 r_abook_save_file (RAbook* abook, gchar* fname, gint compression_rate)
1016 {
1017 RAbookClass* class;
1018 RAbookPrivate* priv;
1019 gchar* ext = NULL, *tmp;
1020 gboolean result = FALSE;
1021
1022 g_return_val_if_fail(IS_R_ABOOK(abook), FALSE);
1023
1024 if (!fname)
1025 {
1026 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "addressbook needs a filename");
1027
1028 g_signal_emit_by_name(abook, "need_name", NULL, G_TYPE_NONE);
1029
1030 return FALSE;
1031 }
1032
1033 class = R_ABOOK_GET_CLASS(abook);
1034 priv = R_ABOOK_GET_PRIVATE(abook);
1035 ext = _r_get_file_extension(g_path_get_basename(fname));
1036
1037 if (!ext)
1038 ext = _r_get_plugin_extension(abook->priv->plugin);
1039
1040 tmp = g_strdup_printf("%s.%s", fname, ext);
1041 g_free(fname);
1042 fname = tmp;
1043
1044 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO,
1045 "Trying plugin %s to save the file", r_abook_get_plugin_name(abook));
1046
1047 result = class->abook_save_file(abook, fname, compression_rate);
1048
1049 if (result)
1050 {
1051 g_signal_emit_by_name(abook, "addressbook_saved", NULL, G_TYPE_NONE);
1052
1053 g_free(fname);
1054 return TRUE;
1055 }
1056 else
1057 g_signal_emit_by_name(abook, "save_fail", WRITING_FILE, G_TYPE_INT);
1058
1059 g_free(fname);
1060 return FALSE;
1061 }
1062
1063
1064 /**
1065 * r_abook_overwrite_file
1066 * @abook: a #RAbook
1067 * @backup: boolean
1068 *
1069 * overwrite an existing addressbook with a new one.
1070 * If backup is %TRUE the old addressbook is backuped.
1071 *
1072 * Returns: a %TRUE if old addressbook was successfully overwited,
1073 * %FALSE otherwise
1074 **/
1075 gboolean
r_abook_overwrite_file(RAbook * abook,gboolean backup,gint compression_rate)1076 r_abook_overwrite_file(RAbook* abook, gboolean backup, gint compression_rate)
1077 {
1078 gchar *old, *new;
1079 RAbookClass* class;
1080
1081 g_return_val_if_fail(IS_R_ABOOK(abook), FALSE);
1082
1083 class = R_ABOOK_GET_CLASS(abook);
1084
1085 if (backup)
1086 {
1087 old = g_strdup_printf("%s%s%s", abook->priv->path,
1088 G_DIR_SEPARATOR_S, abook->priv->name);
1089
1090 if (!old || (g_ascii_strcasecmp(old, _("no name")) == 0))
1091 {
1092 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
1093 "addressbook needs a filename");
1094
1095 g_signal_emit_by_name(abook, "need_name", NULL, G_TYPE_NONE);
1096
1097 return FALSE;
1098 }
1099
1100 new = g_strdup_printf("%s~", old);
1101 g_rename(old, new);
1102 g_free(new);
1103 g_free(old);
1104 }
1105
1106 /* write the file */
1107 if (class->abook_overwrite)
1108 return class->abook_overwrite(abook, compression_rate);
1109
1110 return FALSE;
1111 }
1112
1113
1114 /**
1115 * r_abook_copy
1116 * @abook: a #RAbook
1117 *
1118 * copy the addressbook pointed by abook
1119 *
1120 * Returns: a new #RAbook
1121 */
1122 RAbook*
r_abook_copy(RAbook * abook)1123 r_abook_copy (RAbook* abook)
1124 {
1125 RAbook* new;
1126 gpointer engine;
1127 RPlugin* plugin;
1128 RAbookClass* class = NULL;
1129 gpointer card;
1130
1131 g_return_val_if_fail(IS_R_ABOOK(abook), NULL);
1132
1133 new = r_abook_new();
1134
1135 engine = r_abook_get_engine(abook);
1136 plugin = r_abook_get_plugin(abook);
1137
1138 new->priv->engine = engine;
1139 new->priv->plugin = plugin;
1140 g_object_ref(engine);
1141 g_object_ref(plugin);
1142
1143 class = R_ABOOK_GET_CLASS(new);
1144 if (class)
1145 {
1146 class->abook_open_file = r_plugin_get_handle(plugin, "read");
1147 class->abook_save_file = r_plugin_get_handle(plugin, "write");
1148 class->abook_overwrite = r_plugin_get_handle(plugin, "overwrite");
1149 }
1150
1151 card = r_abook_get_card(abook);
1152 for (; card; card = r_abook_get_next_card(abook))
1153 {
1154 gpointer new_card;
1155
1156 new_card = r_card_copy(R_CARD(card));
1157
1158 if (new_card)
1159 r_abook_add_card(new, new_card);
1160 }
1161 r_abook_reset_book(abook);
1162
1163 return new;
1164 }
1165
1166
1167 /**
1168 * r_abook_plugin_from_file
1169 * @abook: a #RAbook
1170 * @filename: gchar*
1171 *
1172 * Try to load the plugin using the file extension. If the file has a
1173 * known extension the rigth plugin is loaded.
1174 *
1175 * Returns: %TRUE if plugin is loaded, %FALSE otherwise
1176 **/
1177 gboolean
r_abook_plugin_from_file(RAbook * abook,gchar * filename)1178 r_abook_plugin_from_file (RAbook* abook, gchar* filename)
1179 {
1180 GList* filters = NULL;
1181
1182 filters = r_plugin_manager_get_all_filters(abook->priv->manager);
1183 for (; filters; filters = filters->next)
1184 {
1185 gchar *name, *pattern;
1186 RFilter* filter = (RFilter*) filters->data;
1187
1188 g_object_get(filter, "filter-name", &name, NULL);
1189
1190 r_filter_reset(filter);
1191 pattern = r_filter_get_pattern(filter);
1192 for (; pattern; pattern = r_filter_get_next_pattern(filter))
1193 if (g_str_has_suffix(filename, pattern))
1194 {
1195 gchar* name;
1196
1197 g_object_get(filter, "filter-name", &name, NULL);
1198 return r_abook_load_plugin (abook, name);
1199 }
1200 }
1201
1202 return FALSE;
1203 }
1204
1205
1206
1207 /**
1208 * r_abook_load_plugin
1209 * @abook: a #RAbook
1210 * @plugin_name: const gchar*
1211 *
1212 * Load the "plugin_name" plugin.
1213 *
1214 * Returns: %TRUE if plugin is loaded, %FALSE otherwise
1215 **/
1216 gboolean
r_abook_load_plugin(RAbook * abook,const gchar * plugin_name)1217 r_abook_load_plugin (RAbook* abook, const gchar* plugin_name)
1218 {
1219 RPlugin* plugin;
1220 RAbookClass* class = NULL;
1221
1222 g_return_val_if_fail(IS_R_ABOOK(abook), FALSE);
1223 g_return_val_if_fail(plugin_name != NULL, FALSE);
1224
1225 class = R_ABOOK_GET_CLASS(abook);
1226 if (!class)
1227 {
1228 g_warning("\nR_ABOOK_GET_CLASS");
1229
1230 return FALSE;
1231 }
1232
1233 plugin = r_plugin_manager_get_plugin(abook->priv->manager, plugin_name);
1234 if (plugin)
1235 {
1236 abook->priv->plugin = plugin;
1237 abook->priv->engine = r_plugin_get_engine(plugin);
1238
1239 class->abook_open_file = r_plugin_get_handle(plugin, "read");
1240 class->abook_save_file = r_plugin_get_handle(plugin, "write");
1241 class->abook_overwrite = r_plugin_get_handle(plugin, "overwrite");
1242
1243 return TRUE;
1244 }
1245
1246 return FALSE;
1247 }
1248
1249
1250
1251 /**
1252 * r_abook_get_plugin_extension
1253 * @abook: a #RAbook
1254 *
1255 * Get the extension that is associate to the current active plugin
1256 *
1257 * Returns: a gchar* or NULL if an error occured
1258 **/
1259 gchar*
r_abook_get_plugin_extension(RAbook * abook)1260 r_abook_get_plugin_extension (RAbook* abook)
1261 {
1262 GList* filters = NULL;
1263 RFilter* filter;
1264
1265 g_return_val_if_fail(IS_R_ABOOK(abook), NULL);
1266
1267 filters = r_plugin_get_filters (abook->priv->plugin);
1268 filter = (RFilter*) filters->data;
1269 r_filter_reset(filter);
1270
1271 return r_filter_get_pattern(filter);
1272 }
1273
1274
1275 /**
1276 * r_abook_get_plugin_name
1277 * @abook: a #RAbook
1278 *
1279 * get the name of the active plugin
1280 *
1281 * Returns: a gchar*
1282 */
1283 gchar*
r_abook_get_plugin_name(RAbook * abook)1284 r_abook_get_plugin_name (RAbook* abook)
1285 {
1286 g_return_val_if_fail(IS_R_ABOOK(abook), NULL);
1287
1288 return r_plugin_get_name(R_PLUGIN(abook->priv->plugin));
1289 }
1290
1291
1292 /**
1293 * r_abook_get_engine
1294 * @abook: a #RAbook
1295 *
1296 * Get the active engine (the real plugin)
1297 *
1298 * Currently are available those engines (plugins) with rubrica:
1299 * Rubrica (manages the rubrica's file format)
1300 * VCard (manages the vcard's file format)
1301 * CsvGmail (manages the gmail's csv file format)
1302 * CsvThunderbird (managed the thunderbird's csv file format)
1303 *
1304 * working on CsvOutlook and generic csv
1305 *
1306 * Returns: a %gpointer to the engine
1307 **/
1308 gpointer
r_abook_get_engine(RAbook * abook)1309 r_abook_get_engine (RAbook* abook)
1310 {
1311 g_return_val_if_fail(IS_R_ABOOK(abook), NULL);
1312
1313 return abook->priv->engine;
1314 }
1315
1316
1317
1318 /**
1319 * r_abook_get_r_plugin
1320 * @abook: a #RAbook
1321 *
1322 * Get the currently active plugin (ptr to an #RPlugin struct)
1323 *
1324 * Returns: a %gpointer to the plugin
1325 **/
1326 gpointer
r_abook_get_plugin(RAbook * abook)1327 r_abook_get_plugin (RAbook* abook)
1328 {
1329 g_return_val_if_fail(IS_R_ABOOK(abook), NULL);
1330
1331 return abook->priv->plugin;
1332 }
1333
1334
1335 /**
1336 * r_abook_get_items
1337 * @abook: a #RAbook
1338 *
1339 * get the number of cards into addressbok
1340 *
1341 * Returns: an integer
1342 */
1343 gint
r_abook_get_items(RAbook * abook)1344 r_abook_get_items (RAbook* abook)
1345 {
1346 g_return_val_if_fail(IS_R_ABOOK(abook), -1);
1347
1348 return g_list_length(abook->priv->cards);
1349 }
1350
1351 /**
1352 * r_abook_get_deleted
1353 * @abook: a #RAbook
1354 *
1355 * get the number of cards marked as deleted into addressbok
1356 *
1357 * Returns: an integer. If an error occurred -1 is returne
1358 */
1359 gint
r_abook_get_deleted(RAbook * abook)1360 r_abook_get_deleted (RAbook* abook)
1361 {
1362 g_return_val_if_fail(IS_R_ABOOK(abook), -1);
1363
1364 return abook->priv->deleted;
1365 }
1366
1367
1368
1369 /**
1370 * r_abook_is_empty
1371 * @abook: a #RAbook
1372 *
1373 * is the addressbook empty?
1374 *
1375 * Returns: a boolean. %TRUE if addressbook is empty, %FALSE otherwise
1376 */
1377 gboolean
r_abook_is_empty(RAbook * abook)1378 r_abook_is_empty (RAbook* abook)
1379 {
1380 g_return_val_if_fail(IS_R_ABOOK(abook), TRUE);
1381
1382 return (r_abook_get_items(abook) == 0);
1383 }
1384
1385
1386
1387 /**
1388 * r_abook_add_card
1389 * @abook: a #RAbook
1390 * @card: an #RCard object
1391 *
1392 * append the given card into the addressbook
1393 * The "card_added" and "addressbook_changed" signals are emitted
1394 */
1395 void
r_abook_add_card(RAbook * abook,RCard * card)1396 r_abook_add_card (RAbook* abook, RCard* card)
1397 {
1398 _r_abook_add_card(abook, card, TRUE);
1399 }
1400
1401
1402
1403 /**
1404 * r_abook_add_loaded_card
1405 * @abook: a #RAbook
1406 * @card: an #RCard object
1407 *
1408 * append a card read from disk into the addressbook
1409 */
1410 void
r_abook_add_loaded_card(RAbook * abook,RCard * card)1411 r_abook_add_loaded_card (RAbook* abook, RCard* card)
1412 {
1413 _r_abook_add_card(abook, card, FALSE);
1414 }
1415
1416
1417
1418 /**
1419 * r_abook_paste_card
1420 * @abook: a #RAbook
1421 * @card: an #RCard object
1422 *
1423 * peste the given card into the addressbook (append the card)
1424 */
1425 void
r_abook_paste_card(RAbook * abook,RCard * card)1426 r_abook_paste_card (RAbook* abook, RCard* card)
1427 {
1428 _r_abook_add_card(abook, card, TRUE);
1429 }
1430
1431
1432
1433 /**
1434 * r_abook_empty_trash
1435 * @abook: a #RAbook
1436 *
1437 * Destroy all cards in the trash. The destroyed cards are unrecoverable
1438 * the "addressbook_changed" signal is emitted
1439 */
1440 void
r_abook_empty_trash(RAbook * abook)1441 r_abook_empty_trash(RAbook* abook)
1442 {
1443 GList* iter;
1444
1445 g_return_if_fail(IS_R_ABOOK(abook));
1446
1447 for (iter = abook->priv->trash; iter; iter = iter->next)
1448 {
1449 RCard* card = NULL;
1450
1451 card = r_abook_get_card_by_id(abook, (glong) iter->data);
1452 g_object_set(card, "card-destroyed", TRUE, NULL);
1453
1454 abook->priv->deleted--;
1455 }
1456
1457 g_list_free(abook->priv->trash);
1458 abook->priv->trash = NULL;
1459
1460 g_signal_emit_by_name(abook, "addressbook_changed", NULL, G_TYPE_NONE);
1461 }
1462
1463
1464 /**
1465 * r_abook_destroy_card
1466 * @abook: a #RAbook
1467 * @card: an #RCard object
1468 *
1469 * Destroy the given card. The destroyed cards are unrecoverable
1470 * The "card_destroyed" and "addressbook_changed" signals are emitted
1471 */
1472 void
r_abook_destroy_card(RAbook * abook,RCard * card)1473 r_abook_destroy_card(RAbook* abook, RCard* card)
1474 {
1475 gchar* name;
1476
1477 g_return_if_fail(IS_R_ABOOK(abook));
1478 g_return_if_fail(IS_R_CARD(card));
1479
1480 g_object_get(card, "card-name", &name, NULL);
1481 g_object_set(card, "card-destroyed", TRUE, NULL);
1482
1483 abook->priv->cards = g_list_remove(abook->priv->cards, card);
1484 abook->priv->deleted--;
1485
1486 g_signal_emit_by_name(abook, "card_destroyed", name, G_TYPE_STRING);
1487 g_signal_emit_by_name(abook, "addressbook_changed", NULL, G_TYPE_NONE);
1488 }
1489
1490
1491 /**
1492 * r_abook_delete_card
1493 * @abook: a #RAbook
1494 * @card: an #RCard object
1495 *
1496 * mark the given card as delete.
1497 * The id of the card is appended to the addressbook's trash
1498 * The "card_removed" and "addressbook_changed" signals are emitted
1499 */
1500 void
r_abook_delete_card(RAbook * abook,RCard * card)1501 r_abook_delete_card (RAbook* abook, RCard* card)
1502 {
1503 gint id;
1504
1505 g_return_if_fail(IS_R_ABOOK(abook));
1506 g_return_if_fail(IS_R_CARD(card));
1507
1508 g_object_set(card, "card-deleted", TRUE, NULL);
1509 g_object_get(card, "card-id", &id, NULL);
1510
1511 abook->priv->deleted++;
1512 abook->priv->trash = g_list_append(abook->priv->trash, GINT_TO_POINTER(id));
1513
1514 g_signal_emit_by_name(abook, "card_deleted", card, G_TYPE_POINTER);
1515 g_signal_emit_by_name(abook, "addressbook_changed", NULL, G_TYPE_NONE);
1516 }
1517
1518
1519 /**
1520 * r_abook_recovery_card
1521 * @abook: a #RAbook
1522 * @card: an #RCard object
1523 *
1524 * unmark the card previously marked as deleted.
1525 * The "card_recovered" and "addressbook_changed" signals are emitted
1526 *
1527 * Returns: %TRUE if card is successfully recovered, %FALSE otherwise
1528 */
1529 gboolean
r_abook_recovery_card(RAbook * abook,RCard * card)1530 r_abook_recovery_card (RAbook* abook, RCard* card)
1531 {
1532 g_return_val_if_fail(IS_R_ABOOK(abook), FALSE);
1533 g_return_val_if_fail(IS_R_CARD(card), FALSE);
1534
1535
1536 g_object_set(card, "card-deleted", FALSE, NULL);
1537 abook->priv->deleted--;
1538
1539 g_signal_emit_by_name(abook, "card_recovered", card, G_TYPE_POINTER);
1540 g_signal_emit_by_name(abook, "addressbook_changed", NULL, G_TYPE_NONE);
1541
1542 return TRUE;
1543 }
1544
1545
1546
1547 /**
1548 * r_abook_replace_card
1549 * @abook: a #RAbook
1550 * @old: an #RCard object
1551 * @new: an #RCard object
1552 *
1553 * replace the old card with the new one
1554 * The "card_replaced" and "addressbook_changed" signals are emitted
1555 */
1556 void
r_abook_replace_card(RAbook * abook,RCard * old,RCard * new)1557 r_abook_replace_card (RAbook* abook, RCard* old, RCard* new)
1558 {
1559 gint pos;
1560 GList* node = NULL;
1561 gpointer card = NULL;
1562
1563 g_return_if_fail(IS_R_ABOOK(abook));
1564
1565 pos = g_list_index(abook->priv->cards, old);
1566 node = g_list_nth(abook->priv->cards, pos);
1567 if (node)
1568 {
1569 abook->priv->cards = g_list_remove_link(abook->priv->cards, node);
1570
1571 card = node->data;
1572 r_card_free(R_CARD(card));
1573
1574 g_list_free_1(node);
1575
1576 abook->priv->cards = g_list_insert(abook->priv->cards, new, pos);
1577
1578 g_signal_emit_by_name(abook, "addressbook_changed", NULL, G_TYPE_NONE);
1579 g_signal_emit_by_name(abook, "card_replaced", new, G_TYPE_POINTER);
1580 }
1581 }
1582
1583
1584
1585 /**
1586 * r_abook_get_card
1587 * @abook: a #RAbook
1588 *
1589 * Get the first card in addressbook.
1590 *
1591 * Returns: a pointer to the card or NULL if addressbook is empty
1592 */
1593 gpointer
r_abook_get_card(RAbook * abook)1594 r_abook_get_card (RAbook* abook)
1595 {
1596 g_return_val_if_fail(IS_R_ABOOK(abook), NULL);
1597
1598 if (abook->priv->iter)
1599 return abook->priv->iter->data;
1600
1601 return NULL;
1602 }
1603
1604
1605
1606 /**
1607 * r_abook_get_selected_card
1608 * @abook: a #RAbook
1609 *
1610 * Get the selected card in the addressbook
1611 *
1612 * Returns:
1613 */
1614 gpointer
r_abook_get_selected_card(RAbook * abook)1615 r_abook_get_selected_card (RAbook* abook)
1616 {
1617 g_return_val_if_fail(IS_R_ABOOK(abook), NULL);
1618
1619 return r_abook_get_card_by_id(abook, abook->priv->selected_id);
1620 }
1621
1622
1623 /**
1624 * r_abook_unselect_cards
1625 * @abook: a #RAbook
1626 *
1627 * unselect card. Clear previpus selections
1628 */
1629 void
r_abook_unselect_cards(RAbook * abook)1630 r_abook_unselect_cards (RAbook* abook)
1631 {
1632 g_return_if_fail(IS_R_ABOOK(abook));
1633
1634 abook->priv->selected_id = 0L;
1635 }
1636
1637
1638 /**
1639 * r_abook_get_card_by_id
1640 * @abook: a #RAbook
1641 * @id: the card id
1642 *
1643 * get the card with "id" id
1644 *
1645 * Returns: a pointer to the card or NULL if addressbook doesn't own that card
1646 */
1647 gpointer
r_abook_get_card_by_id(RAbook * abook,glong id)1648 r_abook_get_card_by_id (RAbook* abook, glong id)
1649 {
1650 gpointer card = NULL;
1651
1652 g_return_val_if_fail(IS_R_ABOOK(abook), NULL);
1653 g_return_val_if_fail(id > 0L, NULL);
1654
1655 r_abook_reset_book(abook);
1656 for (card = r_abook_get_card(abook); card;
1657 card = r_abook_get_next_card(abook))
1658 {
1659 glong card_id;
1660
1661 g_object_get(R_CARD(card), "card-id", &card_id, NULL);
1662 if (id == card_id)
1663 {
1664 abook->priv->selected_id = id;
1665
1666 return card;
1667 }
1668 }
1669
1670 return NULL;
1671 }
1672
1673 /**
1674 * r_abook_get_group_box(RAbook* abook)
1675 * @abook: a #RAbook
1676 *
1677 * get the default groups set
1678 *
1679 * returns: a #gpointer (caller must cast to #RGroupSet*) or NULL
1680 */
1681 gpointer
r_abook_get_groups_box(RAbook * abook)1682 r_abook_get_groups_box(RAbook* abook)
1683 {
1684 g_return_val_if_fail(IS_R_ABOOK(abook), NULL);
1685
1686 return (gpointer) abook->priv->box;
1687 }
1688
1689
1690
1691
1692 /**
1693 * r_abook_reset_book
1694 * @abook: a #RAbook
1695 *
1696 * reset the private addressbook iterator. The iterator
1697 * will point the head of cards's list.
1698 */
1699 void
r_abook_reset_book(RAbook * abook)1700 r_abook_reset_book (RAbook* abook)
1701 {
1702 g_return_if_fail(IS_R_ABOOK(abook));
1703
1704 abook->priv->iter = abook->priv->cards;
1705 }
1706
1707
1708 /**
1709 * r_abook_get_next_card
1710 * @abook: a #RAbook
1711 *
1712 * get the next card in addressbook
1713 *
1714 * Returns: a pointer to the card or NULL if the cards's end list is reached.
1715 */
1716 gpointer
r_abook_get_next_card(RAbook * abook)1717 r_abook_get_next_card (RAbook* abook)
1718 {
1719 g_return_val_if_fail(IS_R_ABOOK(abook), NULL);
1720
1721 abook->priv->iter = g_list_next(abook->priv->iter);
1722 if (abook->priv->iter)
1723 return abook->priv->iter->data;
1724 else
1725 abook->priv->iter = g_list_last(abook->priv->cards);
1726
1727 return NULL;
1728 }
1729
1730
1731 /**
1732 * r_abook_get_prev_card
1733 * @abook: a #RAbook
1734 *
1735 * get the previous card in addressbook
1736 *
1737 * Returns: a pointer to the card or NULL if the cards's head list is reached.
1738 */
1739 gpointer
r_abook_get_prev_card(RAbook * abook)1740 r_abook_get_prev_card (RAbook* abook)
1741 {
1742 g_return_val_if_fail(IS_R_ABOOK(abook), NULL);
1743
1744 abook->priv->iter = g_list_previous(abook->priv->iter);
1745 if (abook->priv->iter)
1746 return abook->priv->iter->data;
1747 else
1748 abook->priv->iter = abook->priv->cards;
1749
1750 return NULL;
1751 }
1752
1753
1754 /**
1755 * r_abook_foreach_card
1756 * @abook: a #RAbook
1757 * @func: the #RFunc that will be called for each card in addressbook
1758 * @data: user's data to pass to func
1759 *
1760 * Call the function func() for each card in the #RAbook.
1761 */
1762 void
r_abook_foreach_card(RAbook * abook,RFunc func,gpointer data)1763 r_abook_foreach_card (RAbook* abook, RFunc func, gpointer data)
1764 {
1765 gpointer card;
1766
1767 r_abook_reset_book(abook);
1768 card = r_abook_get_card(abook);
1769 for (; card; card = r_abook_get_next_card(abook))
1770 func(card, data);
1771 }
1772
1773
1774 /**
1775 * r_abook_find_cards_by_group
1776 * @abook: a #RAbook
1777 * @group_name: the name of the group
1778 *
1779 * Find all cards that belongs to the given group.
1780 * Found cards's ID has inserted in a GList. Caller must free returned GList
1781 *
1782 * returns: a GList* or %NULL if no cards belong to group
1783 */
1784 GList*
r_abook_find_cards_by_group(RAbook * abook,const gchar * group_name)1785 r_abook_find_cards_by_group (RAbook* abook, const gchar* group_name)
1786 {
1787 gpointer data;
1788 GList* found = NULL;
1789
1790 g_return_val_if_fail(IS_R_ABOOK(abook), NULL);
1791 g_return_val_if_fail(group_name != NULL, NULL);
1792
1793 r_abook_reset_book(abook);
1794 data = r_abook_get_card(abook);
1795 for (; data; data = r_abook_get_next_card(abook))
1796 {
1797 glong id;
1798
1799 if (!r_card_is_deleted(R_CARD(data)) &&
1800 (r_card_belong_to_group(R_CARD(data), group_name) ||
1801 (g_ascii_strcasecmp(group_name, "all groups") == 0)))
1802 {
1803 g_object_get(R_CARD(data), "card-id", &id, NULL);
1804
1805 found = g_list_append(found, GINT_TO_POINTER(id));
1806 }
1807 }
1808
1809 return found;
1810 }
1811
1812
1813 /**
1814 * r_abook_find_cards_by_type
1815 * @abook: a #RAbook
1816 * @type: the type
1817 *
1818 * Find all cards that belongs to the given type.
1819 * Found cards's ID has inserted in a GList. Caller must free returned GList
1820 *
1821 * returns: a GList* or %NULL if no cards belong to the given type
1822 */
1823 GList*
r_abook_find_cards_by_type(RAbook * abook,const gchar * type)1824 r_abook_find_cards_by_type (RAbook* abook, const gchar* type)
1825 {
1826 gpointer data;
1827 GList* found = NULL;
1828
1829 g_return_val_if_fail(IS_R_ABOOK(abook), NULL);
1830 g_return_val_if_fail(type != NULL, NULL);
1831
1832 r_abook_reset_book(abook);
1833 data = r_abook_get_card(abook);
1834 for (; data; data = r_abook_get_next_card(abook))
1835 {
1836 gchar* card_type = NULL;
1837 gboolean deleted;
1838 glong id;
1839
1840 g_object_get(R_CARD(data), "card-id", &id,
1841 "card-deleted", &deleted,
1842 "card-type", &card_type, NULL);
1843
1844 if (!card_type)
1845 {
1846 gchar* name;
1847
1848 g_object_get(R_CARD(data), "card-name", &name, NULL);
1849
1850 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
1851 "This card (%s) has a wrong type.", name);
1852
1853 continue;
1854 }
1855
1856 if (!deleted)
1857 {
1858 if (g_ascii_strcasecmp(type, "all") == 0)
1859 found = g_list_append(found, GINT_TO_POINTER(id));
1860 else
1861 if (g_ascii_strcasecmp(type, card_type) == 0)
1862 found = g_list_append(found, GINT_TO_POINTER(id));
1863 }
1864 }
1865
1866 return found;
1867 }
1868
1869
1870
1871 /**
1872 * r_abook_find_cards_by_rate
1873 * @abook: a #RAbook
1874 * @rate: an #RRate
1875 *
1876 * Find all cards that have the given rate
1877 * Found cards's ID has inserted in a GList. Caller must free returned GList
1878 *
1879 * returns: a GList* or %NULL if no cards have the requested rate
1880 */
1881 GList*
r_abook_find_cards_by_rate(RAbook * abook,RRate rate)1882 r_abook_find_cards_by_rate (RAbook* abook, RRate rate)
1883 {
1884 gpointer data;
1885 GList* found = NULL;
1886
1887 g_return_val_if_fail(IS_R_ABOOK(abook), NULL);
1888
1889 r_abook_reset_book(abook);
1890 data = r_abook_get_card(abook);
1891 for (; data; data = r_abook_get_next_card(abook))
1892 {
1893 glong id, card_rate;
1894 gboolean deleted;
1895
1896 g_object_get(R_CARD(data), "card-id", &id,
1897 "card-deleted", &deleted,
1898 "card-rate", &card_rate, NULL);
1899
1900 if (!deleted && (card_rate == rate))
1901 found = g_list_append(found, GINT_TO_POINTER(id));
1902 }
1903
1904 return found;
1905 }
1906
1907
1908 /**
1909 * r_abook_find_cards_by_genre
1910 * @abook: a #RAbook
1911 * @genre: a string
1912 *
1913 * Find all cards with the given genre ("male" or "female")
1914 * Found cards's ID has inserted in a GList. Caller must free returned GList
1915 *
1916 * returns: a GList* or %NULL if no cards have the requested genre
1917 */
1918 GList*
r_abook_find_cards_by_genre(RAbook * abook,const gchar * genre)1919 r_abook_find_cards_by_genre (RAbook* abook, const gchar* genre)
1920 {
1921 gpointer data;
1922 GList* found = NULL;
1923
1924 g_return_val_if_fail(IS_R_ABOOK(abook), NULL);
1925 g_return_val_if_fail(genre != NULL, NULL);
1926
1927 r_abook_reset_book(abook);
1928 data = r_abook_get_card(abook);
1929 for (; data; data = r_abook_get_next_card(abook))
1930 {
1931 gchar* type = NULL;
1932 gboolean deleted;
1933 glong id;
1934
1935 g_object_get(R_CARD(data), "card-id", &id, "card-deleted", &deleted,
1936 "card-type", &type, NULL);
1937
1938 if (!deleted && (g_ascii_strcasecmp(type, "personal") == 0))
1939 {
1940 if (r_personal_card_belongs_to_genre(R_PERSONAL_CARD(data), genre))
1941 found = g_list_append(found, GINT_TO_POINTER(id));
1942 }
1943 }
1944
1945 return found;
1946 }
1947
1948
1949 /**
1950 * r_abook_search
1951 * @abook: a #RAbook
1952 * @str: an string
1953 *
1954 * Search the given string in all cards's fields
1955 *
1956 * returns: a GList* of cards's id or %NULL if no cards
1957 * have the requested string
1958 */
1959 GList*
r_abook_search(RAbook * abook,const gchar * str)1960 r_abook_search (RAbook* abook, const gchar* str)
1961 {
1962 gpointer data;
1963 GList* found = NULL;
1964
1965 g_return_val_if_fail(IS_R_ABOOK(abook), NULL);
1966 g_return_val_if_fail(str != NULL, NULL);
1967
1968 r_abook_reset_book(abook);
1969 data = r_abook_get_card(abook);
1970 for (; data; data = r_abook_get_next_card(abook))
1971 {
1972 glong id;
1973
1974 g_object_get(R_CARD(data), "card-id", &id, NULL);
1975
1976 if (r_card_search(R_CARD(data), str))
1977 found = g_list_append(found, GINT_TO_POINTER(id));
1978 }
1979
1980 return found;
1981 }
1982
1983
1984 /**
1985 * r_abook_search_date
1986 * @abook: a #RAbook
1987 * @search_date: a time_t date
1988 * type: a #SearchType
1989 *
1990 * Search the given date
1991 *
1992 * returns: a GList* of cards's id or %NULL if no cards have the date
1993 */
1994 GList*
r_abook_search_date(RAbook * abook,gint search_date,SearchType type)1995 r_abook_search_date (RAbook* abook, gint search_date, SearchType type)
1996 {
1997 gpointer data;
1998 GList* found = NULL;
1999
2000 g_return_val_if_fail(IS_R_ABOOK(abook), NULL);
2001 g_return_val_if_fail(search_date > 0, NULL);
2002
2003 r_abook_reset_book(abook);
2004 data = r_abook_get_card(abook);
2005 for (; data; data = r_abook_get_next_card(abook))
2006 {
2007 glong id;
2008 gint creation, changed;
2009 GDate *date1, *date2;
2010 gboolean find = FALSE;
2011
2012 g_object_get(R_CARD(data), "card-id", &id,
2013 "card-created", &creation, "card-changed", &changed, NULL);
2014
2015 switch(type)
2016 {
2017 case SEARCH_ON_CREATION:
2018 date1 = g_date_new();
2019 date2 = g_date_new();
2020
2021 g_date_set_time_t(date1, creation);
2022 g_date_set_time_t(date2, search_date);
2023
2024 find = ((g_date_get_day(date1) == g_date_get_day(date2)) &&
2025 (g_date_get_month(date1) == g_date_get_month(date2)) &&
2026 (g_date_get_year(date1) == g_date_get_year(date2)));
2027
2028 g_date_free (date1);
2029 g_date_free (date2);
2030 break;
2031
2032 case SEARCH_ON_CHANGE:
2033 date1 = g_date_new();
2034 date2 = g_date_new();
2035
2036 g_date_set_time_t(date1, changed);
2037 g_date_set_time_t(date2, search_date);
2038
2039 find = ((g_date_get_day(date1) == g_date_get_day(date2)) &&
2040 (g_date_get_month(date1) == g_date_get_month(date2)) &&
2041 (g_date_get_year(date1) == g_date_get_year(date2)));
2042
2043 g_date_free (date1);
2044 g_date_free (date2);
2045 break;
2046
2047 case SEARCH_CREATION_BEFORE:
2048 find = (creation < search_date);
2049 break;
2050
2051 case SEARCH_CREATION_AFTER:
2052 find = (creation > search_date);
2053 break;
2054
2055 case SEARCH_CHANGE_BEFORE:
2056 find = (changed < search_date);
2057 break;
2058
2059 case SEARCH_CHANGE_AFTER:
2060 find = (changed > search_date);
2061 break;
2062
2063 default:
2064 break;
2065 }
2066
2067 if (find)
2068 found = g_list_append(found, GINT_TO_POINTER(id));
2069 }
2070
2071 return found;
2072 }
2073
2074
2075 /**
2076 * r_abook_search_between
2077 * @abook: a #RAbook
2078 * @first: a time_t date
2079 * @second: a time_t date
2080 * type: a #SearchType
2081 *
2082 * Search the for a date between the first and the second date
2083 *
2084 * returns: a GList* of cards's id or %NULL if no cards have the date
2085 */
2086 GList*
r_abook_search_between(RAbook * abook,gint first,gint second,SearchType type)2087 r_abook_search_between (RAbook* abook, gint first, gint second,
2088 SearchType type)
2089 {
2090 gpointer data;
2091 GList* found = NULL;
2092
2093 g_return_val_if_fail(IS_R_ABOOK(abook), NULL);
2094 g_return_val_if_fail(first > 0, NULL);
2095 g_return_val_if_fail(second > 0, NULL);
2096
2097 r_abook_reset_book(abook);
2098 data = r_abook_get_card(abook);
2099 for (; data; data = r_abook_get_next_card(abook))
2100 {
2101 glong id;
2102 gint creation, changed;
2103 gboolean find = FALSE;
2104
2105 g_object_get(R_CARD(data), "card-id", &id,
2106 "card-created", &creation, "card-changed", &changed, NULL);
2107
2108 switch(type)
2109 {
2110 case SEARCH_CREATION_BETWEEN:
2111 find = ((creation >= first) && (creation <= second));
2112 break;
2113
2114 case SEARCH_CHANGE_BETWEEN:
2115 find = ((changed >= first) && (changed <= second));
2116 break;
2117
2118 default:
2119 break;
2120 }
2121
2122 if (find)
2123 found = g_list_append(found, GINT_TO_POINTER(id));
2124 }
2125
2126 return found;
2127 }
2128
2129