Statistics
| Revision:

root / src / addressbook.c @ 1577

History | View | Annotate | Download (106.1 kB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2007 Hiroyuki Yamamoto
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 */
19
20
#ifdef HAVE_CONFIG_H
21
#  include "config.h"
22
#endif
23
24
#include "defs.h"
25
26
#include <glib.h>
27
#include <glib/gi18n.h>
28
#include <gdk/gdkkeysyms.h>
29
#include <gtk/gtkwindow.h>
30
#include <gtk/gtksignal.h>
31
#include <gtk/gtkvbox.h>
32
#include <gtk/gtkscrolledwindow.h>
33
#include <gtk/gtkhpaned.h>
34
#include <gtk/gtkhbox.h>
35
#include <gtk/gtklabel.h>
36
#include <gtk/gtkentry.h>
37
#include <gtk/gtkctree.h>
38
#include <gtk/gtkclist.h>
39
#include <gtk/gtktable.h>
40
#include <gtk/gtkhbbox.h>
41
#include <gtk/gtkbutton.h>
42
#include <gtk/gtkmenu.h>
43
#include <gtk/gtkmenuitem.h>
44
#include <gtk/gtkitemfactory.h>
45
#include <gtk/gtkstatusbar.h>
46
#include <gtk/gtkstock.h>
47
#include <string.h>
48
#include <setjmp.h>
49
50
#include "main.h"
51
#include "addressbook.h"
52
#include "manage_window.h"
53
#include "prefs_common.h"
54
#include "alertpanel.h"
55
#include "inputdialog.h"
56
#include "menu.h"
57
#include "stock_pixmap.h"
58
#include "xml.h"
59
#include "prefs.h"
60
#include "procmime.h"
61
#include "utils.h"
62
#include "gtkutils.h"
63
#include "codeconv.h"
64
#include "about.h"
65
#include "addr_compl.h"
66
67
#include "mgutils.h"
68
#include "addressitem.h"
69
#include "addritem.h"
70
#include "addrcache.h"
71
#include "addrbook.h"
72
#include "addrindex.h"
73
#include "addressadd.h"
74
#include "vcard.h"
75
#include "editvcard.h"
76
#include "editgroup.h"
77
#include "editaddress.h"
78
#include "editbook.h"
79
#include "ldif.h"
80
#include "importldif.h"
81
82
#ifdef USE_JPILOT
83
#include "jpilot.h"
84
#include "editjpilot.h"
85
#endif
86
87
#ifdef USE_LDAP
88
#include <pthread.h>
89
#include "syldap.h"
90
#include "editldap.h"
91
92
#define ADDRESSBOOK_LDAP_BUSYMSG "Busy"
93
#endif
94
95
typedef enum
96
{
97
        COL_NAME        = 0,
98
        COL_ADDRESS        = 1,
99
        COL_REMARKS        = 2
100
} AddressBookColumnPos;
101
102
#define N_COLS        3
103
#define COL_NAME_WIDTH                164
104
#define COL_ADDRESS_WIDTH        156
105
106
#define COL_FOLDER_WIDTH        170
107
108
#define ADDRESSBOOK_MSGBUF_SIZE 2048
109
110
static GdkPixmap *folderxpm;
111
static GdkBitmap *folderxpmmask;
112
static GdkPixmap *folderopenxpm;
113
static GdkBitmap *folderopenxpmmask;
114
static GdkPixmap *groupxpm;
115
static GdkBitmap *groupxpmmask;
116
static GdkPixmap *interfacexpm;
117
static GdkBitmap *interfacexpmmask;
118
static GdkPixmap *bookxpm;
119
static GdkBitmap *bookxpmmask;
120
static GdkPixmap *addressxpm;
121
static GdkBitmap *addressxpmmask;
122
static GdkPixmap *vcardxpm;
123
static GdkBitmap *vcardxpmmask;
124
static GdkPixmap *jpilotxpm;
125
static GdkBitmap *jpilotxpmmask;
126
static GdkPixmap *categoryxpm;
127
static GdkBitmap *categoryxpmmask;
128
static GdkPixmap *ldapxpm;
129
static GdkBitmap *ldapxpmmask;
130
131
/* Message buffer */
132
static gchar addressbook_msgbuf[ ADDRESSBOOK_MSGBUF_SIZE ];
133
134
/* Address list selection */
135
static GList *_addressListSelection_ = NULL;
136
137
/* Address index file and interfaces */
138
static AddressIndex *_addressIndex_ = NULL;
139
static GList *_addressInterfaceList_ = NULL;
140
static GList *_addressIFaceSelection_ = NULL;
141
#define ADDRESSBOOK_IFACE_SELECTION "1/y,3/y,4/y,2/n"
142
143
/* Address clipboard */
144
static GList *_clipObjectList_ = NULL;
145
146
static AddressBook_win addrbook;
147
148
static GHashTable *_addressBookTypeHash_ = NULL;
149
static GList *_addressBookTypeList_ = NULL;
150
151
static void addressbook_create                        (void);
152
static gint addressbook_close                        (void);
153
154
static void addressbook_menuitem_set_sensitive        (void);
155
156
/* callback functions */
157
static void addressbook_del_clicked                (GtkButton        *button,
158
                                                 gpointer         data);
159
static void addressbook_reg_clicked                (GtkButton        *button,
160
                                                 gpointer         data);
161
static void addressbook_to_clicked                (GtkButton        *button,
162
                                                 gpointer         data);
163
static void addressbook_lup_clicked                (GtkButton        *button,
164
                                                 gpointer        data);
165
static void addressbook_close_clicked                (GtkButton        *button,
166
                                                 gpointer        data);
167
168
static void addressbook_tree_selected                (GtkCTree        *ctree,
169
                                                 GtkCTreeNode        *node,
170
                                                 gint                 column,
171
                                                 gpointer         data);
172
static void addressbook_list_selected                (GtkCList        *clist,
173
                                                 gint                 row,
174
                                                 gint                 column,
175
                                                 GdkEvent        *event,
176
                                                 gpointer         data);
177
static void addressbook_list_row_selected        (GtkCTree        *clist,
178
                                                 GtkCTreeNode        *node,
179
                                                 gint                 column,
180
                                                 gpointer         data);
181
static void addressbook_list_row_unselected        (GtkCTree        *clist,
182
                                                 GtkCTreeNode        *node,
183
                                                 gint                 column,
184
                                                 gpointer         data);
185
static void addressbook_person_expand_node        (GtkCTree        *ctree,
186
                                                 GList                *node,
187
                                                 gpointer        *data );
188
static void addressbook_person_collapse_node        (GtkCTree        *ctree,
189
                                                 GList                *node,
190
                                                 gpointer        *data );
191
192
#if 0
193
static void addressbook_entry_changed                (GtkWidget        *widget);
194
#endif
195
196
static gboolean addressbook_list_button_pressed        (GtkWidget        *widget,
197
                                                 GdkEventButton        *event,
198
                                                 gpointer         data);
199
static gboolean addressbook_list_button_released(GtkWidget        *widget,
200
                                                 GdkEventButton        *event,
201
                                                 gpointer         data);
202
static gboolean addressbook_tree_button_pressed        (GtkWidget        *ctree,
203
                                                 GdkEventButton        *event,
204
                                                 gpointer         data);
205
static gboolean addressbook_tree_button_released(GtkWidget        *ctree,
206
                                                 GdkEventButton        *event,
207
                                                 gpointer         data);
208
static void addressbook_popup_close                (GtkMenuShell        *menu_shell,
209
                                                 gpointer         data);
210
211
static void addressbook_new_folder_cb                (gpointer         data,
212
                                                 guint                 action,
213
                                                 GtkWidget        *widget);
214
static void addressbook_new_group_cb                (gpointer         data,
215
                                                 guint                 action,
216
                                                 GtkWidget        *widget);
217
static void addressbook_treenode_edit_cb        (gpointer         data,
218
                                                 guint                 action,
219
                                                 GtkWidget        *widget);
220
static void addressbook_treenode_delete_cb        (gpointer         data,
221
                                                 guint                 action,
222
                                                 GtkWidget        *widget);
223
224
static void addressbook_change_node_name        (GtkCTreeNode        *node,
225
                                                 const gchar        *name);
226
227
static void addressbook_new_address_cb                (gpointer         data,
228
                                                 guint                 action,
229
                                                 GtkWidget        *widget);
230
static void addressbook_edit_address_cb                (gpointer         data,
231
                                                 guint                 action,
232
                                                 GtkWidget        *widget);
233
static void addressbook_delete_address_cb        (gpointer         data,
234
                                                 guint                 action,
235
                                                 GtkWidget        *widget);
236
static void addressbook_copy_address_cb                (gpointer         data,
237
                                                 guint                 action,
238
                                                 GtkWidget        *widget);
239
static void addressbook_paste_address_cb        (gpointer         data,
240
                                                 guint                 action,
241
                                                 GtkWidget        *widget);
242
243
static void close_cb                                (gpointer         data,
244
                                                 guint                 action,
245
                                                 GtkWidget        *widget);
246
static void addressbook_file_save_cb                (gpointer         data,
247
                                                 guint                 action,
248
                                                 GtkWidget        *widget);
249
250
/* Data source edit stuff */
251
static void addressbook_new_book_cb                (gpointer         data,
252
                                                        guint                 action,
253
                                                 GtkWidget        *widget);
254
static void addressbook_new_vcard_cb                (gpointer         data,
255
                                                        guint                 action,
256
                                                 GtkWidget        *widget);
257
258
#ifdef USE_JPILOT
259
static void addressbook_new_jpilot_cb                (gpointer         data,
260
                                                        guint                 action,
261
                                                 GtkWidget        *widget);
262
#endif
263
264
#ifdef USE_LDAP
265
static void addressbook_new_ldap_cb                (gpointer         data,
266
                                                        guint                 action,
267
                                                 GtkWidget        *widget);
268
#endif
269
270
static void addressbook_set_clist                (AddressObject        *obj);
271
272
static void addressbook_load_tree                (void);
273
void addressbook_read_file                        (void);
274
275
static GtkCTreeNode *addressbook_add_object        (GtkCTreeNode        *node,
276
                                                 AddressObject        *obj);
277
static AddressDataSource *addressbook_find_datasource
278
                                                (GtkCTreeNode        *node );
279
280
static AddressBookFile *addressbook_get_book_file();
281
282
static GtkCTreeNode *addressbook_node_add_folder
283
                                                (GtkCTreeNode        *node,
284
                                                AddressDataSource *ds,
285
                                                ItemFolder        *itemFolder,
286
                                                AddressObjectType otype);
287
static GtkCTreeNode *addressbook_node_add_group (GtkCTreeNode        *node,
288
                                                AddressDataSource *ds,
289
                                                ItemGroup        *itemGroup);
290
/* static GtkCTreeNode *addressbook_node_add_category */
291
/*                                                (GtkCTreeNode        *node, */
292
/*                                                 AddressDataSource *ds, */
293
/*                                                 ItemFolder        *itemFolder); */
294
static void addressbook_tree_remove_children        (GtkCTree        *ctree,
295
                                                GtkCTreeNode        *parent);
296
static void addressbook_move_nodes_up                (GtkCTree        *ctree,
297
                                                GtkCTreeNode        *node);
298
static GtkCTreeNode *addressbook_find_group_node (GtkCTreeNode        *parent,
299
                                                ItemGroup        *group);
300
301
/* static void addressbook_delete_object        (AddressObject        *obj); */
302
303
static gboolean key_pressed                        (GtkWidget        *widget,
304
                                                 GdkEventKey        *event,
305
                                                 gpointer         data);
306
static void size_allocated                        (GtkWidget        *widget,
307
                                                 GtkAllocation        *allocation,
308
                                                 gpointer         data);
309
310
static gint addressbook_list_compare_func        (GtkCList        *clist,
311
                                                 gconstpointer         ptr1,
312
                                                 gconstpointer         ptr2);
313
/* static gint addressbook_obj_name_compare        (gconstpointer         a, */
314
/*                                                 gconstpointer         b); */
315
316
/* static void addressbook_book_show_message        (AddressBookFile *book); */
317
/* static void addressbook_vcard_show_message        (VCardFile *vcf); */
318
#ifdef USE_JPILOT
319
/* static void addressbook_jpilot_show_message        (JPilotFile *jpf); */
320
#endif
321
#ifdef USE_LDAP
322
static void addressbook_ldap_show_message        (SyldapServer *server);
323
#endif
324
325
/* LUT's and IF stuff */
326
static void addressbook_free_adapter                (GtkCTreeNode        *node);
327
static void addressbook_free_child_adapters        (GtkCTreeNode        *node);
328
AddressTypeControlItem *addrbookctl_lookup        (gint                 ot);
329
AddressTypeControlItem *addrbookctl_lookup_iface(AddressIfType         ifType);
330
331
void addrbookctl_build_map                        (GtkWidget        *window);
332
void addrbookctl_build_iflist                        (void);
333
AdapterInterface *addrbookctl_find_interface        (AddressIfType         ifType);
334
void addrbookctl_build_ifselect                        (void);
335
336
static void addrbookctl_free_interface                (AdapterInterface *adapter);
337
static void addrbookctl_free_datasource                (AdapterDSource          *adapter);
338
static void addrbookctl_free_folder                (AdapterFolder          *adapter);
339
static void addrbookctl_free_group                (AdapterGroup          *adapter);
340
341
static void addressbook_list_select_clear        (void);
342
static void addressbook_list_select_add                (AddressObject *obj);
343
static void addressbook_list_select_remove        (AddressObject *obj);
344
345
static void addressbook_import_ldif_cb                (void);
346
347
static GtkItemFactoryEntry addressbook_entries[] =
348
{
349
        {N_("/_File"),                        NULL,        NULL, 0, "<Branch>"},
350
        {N_("/_File/New _Book"),        NULL,        addressbook_new_book_cb,        0, NULL},
351
        {N_("/_File/New _vCard"),        NULL,        addressbook_new_vcard_cb,       0, NULL},
352
#ifdef USE_JPILOT
353
        {N_("/_File/New _JPilot"),        NULL,        addressbook_new_jpilot_cb,      0, NULL},
354
#endif
355
#ifdef USE_LDAP
356
        {N_("/_File/New _LDAP Server"),        NULL,        addressbook_new_ldap_cb,        0, NULL},
357
#endif
358
        {N_("/_File/---"),                NULL,                NULL, 0, "<Separator>"},
359
        {N_("/_File/_Edit"),                NULL,                addressbook_treenode_edit_cb,   0, NULL},
360
        {N_("/_File/_Delete"),                NULL,                addressbook_treenode_delete_cb, 0, NULL},
361
        {N_("/_File/---"),                NULL,                NULL, 0, "<Separator>"},
362
        {N_("/_File/_Save"),                "<control>S",        addressbook_file_save_cb,       0, NULL},
363
        {N_("/_File/_Close"),                "<control>W",        close_cb, 0, NULL},
364
365
        {N_("/_Edit"),                        NULL,                NULL, 0, "<Branch>"},
366
        {N_("/_Edit/_Copy"),                "<control>C",        addressbook_copy_address_cb,    0, NULL},
367
        {N_("/_Edit/_Paste"),                "<control>V",        addressbook_paste_address_cb,    0, NULL},
368
369
        {N_("/_Address"),                NULL,                NULL, 0, "<Branch>"},
370
        {N_("/_Address/New _Address"),        "<control>N",        addressbook_new_address_cb,     0, NULL},
371
        {N_("/_Address/New _Group"),        "<control>G",        addressbook_new_group_cb,       0, NULL},
372
        {N_("/_Address/New _Folder"),        "<control>F",        addressbook_new_folder_cb,      0, NULL},
373
        {N_("/_Address/---"),                NULL,                NULL, 0, "<Separator>"},
374
        {N_("/_Address/_Edit"),                "<control>Return",        addressbook_edit_address_cb,    0, NULL},
375
        {N_("/_Address/_Delete"),        "Delete",        addressbook_delete_address_cb,  0, NULL},
376
377
        {N_("/_Tools"),                        NULL,                NULL, 0, "<Branch>"},
378
        {N_("/_Tools/Import _LDIF file"), NULL,                addressbook_import_ldif_cb,        0, NULL},
379
380
        {N_("/_Help"),                        NULL,                NULL, 0, "<Branch>"},
381
        {N_("/_Help/_About"),                NULL,                about_show, 0, NULL}
382
};
383
384
/* New options to be added. */
385
/*
386
        {N_("/_Edit"),                        NULL,                NULL, 0, "<Branch>"},
387
        {N_("/_Edit/C_ut"),                "<control>X",        NULL,                                0, NULL},
388
        {N_("/_Edit/_Copy"),                "<control>C",        NULL,                           0, NULL},
389
        {N_("/_Edit/_Paste"),                "<control>V",        NULL,                           0, NULL},
390
        {N_("/_Tools"),                        NULL,                NULL, 0, "<Branch>"},
391
        {N_("/_Tools/Import _Mozilla"),        NULL,           NULL,                                0, NULL},
392
        {N_("/_Tools/Import _vCard"),        NULL,           NULL,                                0, NULL},
393
        {N_("/_Tools/---"),                NULL,                NULL, 0, "<Separator>"},
394
        {N_("/_Tools/Export _LDIF file"), NULL,                NULL,                                0, NULL},
395
        {N_("/_Tools/Export v_Card"),        NULL,           NULL,                                0, NULL},
396
*/
397
398
static GtkItemFactoryEntry addressbook_tree_popup_entries[] =
399
{
400
        {N_("/New _Address"),        NULL, addressbook_new_address_cb, 0, NULL},
401
        {N_("/New _Group"),        NULL, addressbook_new_group_cb,   0, NULL},
402
        {N_("/New _Folder"),        NULL, addressbook_new_folder_cb,  0, NULL},
403
        {N_("/---"),                NULL, NULL, 0, "<Separator>"},
404
        {N_("/_Edit"),                NULL, addressbook_treenode_edit_cb,   0, NULL},
405
        {N_("/_Delete"),        NULL, addressbook_treenode_delete_cb, 0, NULL}
406
};
407
408
static GtkItemFactoryEntry addressbook_list_popup_entries[] =
409
{
410
        {N_("/New _Address"),        NULL, addressbook_new_address_cb,  0, NULL},
411
        {N_("/New _Group"),        NULL, addressbook_new_group_cb,    0, NULL},
412
        {N_("/New _Folder"),        NULL, addressbook_new_folder_cb,   0, NULL},
413
        {N_("/---"),                NULL, NULL, 0, "<Separator>"},
414
        {N_("/_Edit"),                NULL, addressbook_edit_address_cb,   0, NULL},
415
        {N_("/_Delete"),        NULL, addressbook_delete_address_cb, 0, NULL},
416
        {N_("/---"),                NULL, NULL, 0, "<Separator>"},
417
        {N_("/_Copy"),                NULL, addressbook_copy_address_cb,  0, NULL},
418
        {N_("/_Paste"),                NULL, addressbook_paste_address_cb, 0, NULL}
419
};
420
421
void addressbook_open(Compose *target)
422
{
423
        if (!addrbook.window) {
424
                addressbook_read_file();
425
                addressbook_create();
426
                addressbook_load_tree();
427
                gtk_ctree_select(GTK_CTREE(addrbook.ctree),
428
                                 GTK_CTREE_NODE(GTK_CLIST(addrbook.ctree)->row_list));
429
                addressbook_menuitem_set_sensitive();
430
                gtk_widget_show_all(addrbook.window);
431
        } 
432
433
        gtk_window_present(GTK_WINDOW(addrbook.window));
434
435
        addressbook_set_target_compose(target);
436
}
437
438
void addressbook_set_target_compose(Compose *target)
439
{
440
        addrbook.target_compose = target;
441
}
442
443
Compose *addressbook_get_target_compose(void)
444
{
445
        return addrbook.target_compose;
446
}
447
448
void addressbook_refresh(void)
449
{
450
        if (addrbook.window) {
451
                if (addrbook.treeSelected) {
452
                        addrbook.treeSelected = NULL;
453
                        gtk_ctree_select(GTK_CTREE(addrbook.ctree),
454
                                         addrbook.treeSelected);
455
                }
456
        }
457
        addressbook_export_to_file();
458
}
459
460
/*
461
* Create the address book widgets. The address book contains two CTree widgets: the
462
* address index tree on the left and the address list on the right.
463
*
464
* The address index tree displays a hierarchy of interfaces and groups. Each node in
465
* this tree is linked to an address Adapter. Adapters have been created for interfaces,
466
* data sources and folder objects.
467
*
468
* The address list displays group, person and email objects. These items are linked
469
* directly to ItemGroup, ItemPerson and ItemEMail objects inside the address book data
470
* sources.
471
*
472
* In the tradition of MVC architecture, the data stores have been separated from the
473
* GUI components. The addrindex.c file provides the interface to all data stores.
474
*/
475
static void addressbook_create(void)
476
{
477
        GtkWidget *window;
478
        GtkWidget *vbox;
479
        GtkWidget *menubar;
480
        GtkWidget *spc_hbox;
481
        GtkWidget *vbox2;
482
        GtkWidget *ctree_swin;
483
        GtkWidget *ctree;
484
        GtkWidget *clist_vbox;
485
        GtkWidget *clist_swin;
486
        GtkWidget *clist;
487
        GtkWidget *paned;
488
        GtkWidget *hbox;
489
        GtkWidget *label;
490
        GtkWidget *entry;
491
        GtkWidget *statusbar;
492
        GtkWidget *hbbox;
493
        GtkWidget *hbbox1;
494
        GtkWidget *hbbox2;
495
        GtkWidget *hsbox;
496
        GtkWidget *to_btn;
497
        GtkWidget *cc_btn;
498
        GtkWidget *bcc_btn;
499
        GtkWidget *del_btn;
500
        GtkWidget *reg_btn;
501
        GtkWidget *lup_btn;
502
        GtkWidget *close_btn;
503
        GtkWidget *tree_popup;
504
        GtkWidget *list_popup;
505
        GtkItemFactory *tree_factory;
506
        GtkItemFactory *list_factory;
507
        GtkItemFactory *menu_factory;
508
        gint n_entries;
509
        GList *nodeIf;
510
511
        gchar *titles[N_COLS];
512
        gchar *text;
513
        gint i;
514
515
        debug_print("Creating addressbook window...\n");
516
517
        titles[COL_NAME]    = _("Name");
518
        titles[COL_ADDRESS] = _("E-Mail address");
519
        titles[COL_REMARKS] = _("Remarks");
520
521
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
522
        gtk_window_set_title(GTK_WINDOW(window), _("Address book"));
523
        gtk_window_set_wmclass(GTK_WINDOW(window), "addressbook", "Sylpheed");
524
        gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, TRUE);
525
        gtk_widget_set_size_request(window, 620, 360);
526
        gtk_window_set_default_size(GTK_WINDOW(window),
527
                                    prefs_common.addressbook_width,
528
                                    prefs_common.addressbook_height);
529
        gtk_window_move(GTK_WINDOW(window), prefs_common.addressbook_x,
530
                        prefs_common.addressbook_y);
531
        gtk_widget_realize(window);
532
533
        g_signal_connect(G_OBJECT(window), "delete_event",
534
                         G_CALLBACK(addressbook_close), NULL);
535
        g_signal_connect(G_OBJECT(window), "key_press_event",
536
                         G_CALLBACK(key_pressed), NULL);
537
        g_signal_connect(G_OBJECT(window), "size_allocate",
538
                         G_CALLBACK(size_allocated), NULL);
539
        MANAGE_WINDOW_SIGNALS_CONNECT(window);
540
541
        vbox = gtk_vbox_new(FALSE, 0);
542
        gtk_container_add(GTK_CONTAINER(window), vbox);
543
544
        n_entries = sizeof(addressbook_entries) /
545
                sizeof(addressbook_entries[0]);
546
        menubar = menubar_create(window, addressbook_entries, n_entries,
547
                                 "<AddressBook>", NULL);
548
        gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, TRUE, 0);
549
        menu_factory = gtk_item_factory_from_widget(menubar);
550
551
        spc_hbox = gtk_hbox_new(FALSE, 0);
552
        gtk_widget_set_size_request(spc_hbox, -1, BORDER_WIDTH);
553
        gtk_box_pack_start(GTK_BOX(vbox), spc_hbox, FALSE, FALSE, 0);
554
555
        vbox2 = gtk_vbox_new(FALSE, 4);
556
        gtk_box_pack_start(GTK_BOX(vbox), vbox2, TRUE, TRUE, 0);
557
558
        ctree_swin = gtk_scrolled_window_new(NULL, NULL);
559
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ctree_swin),
560
                                       GTK_POLICY_AUTOMATIC,
561
                                       GTK_POLICY_ALWAYS);
562
        gtk_widget_set_size_request(ctree_swin, COL_FOLDER_WIDTH + 40, -1);
563
564
        /* Address index */
565
        ctree = gtk_ctree_new(1, 0);
566
        gtk_container_add(GTK_CONTAINER(ctree_swin), ctree);
567
        gtk_clist_set_selection_mode(GTK_CLIST(ctree), GTK_SELECTION_BROWSE);
568
        gtk_clist_set_column_width(GTK_CLIST(ctree), 0, COL_FOLDER_WIDTH);
569
        gtk_ctree_set_line_style(GTK_CTREE(ctree), GTK_CTREE_LINES_DOTTED);
570
        gtk_ctree_set_expander_style(GTK_CTREE(ctree),
571
                                     GTK_CTREE_EXPANDER_SQUARE);
572
        gtk_ctree_set_indent(GTK_CTREE(ctree), CTREE_INDENT);
573
        gtk_clist_set_compare_func(GTK_CLIST(ctree),
574
                                   addressbook_list_compare_func);
575
        gtkut_clist_set_redraw(GTK_CLIST(ctree));
576
577
        g_signal_connect(G_OBJECT(ctree), "tree_select_row",
578
                         G_CALLBACK(addressbook_tree_selected), NULL);
579
        g_signal_connect(G_OBJECT(ctree), "button_press_event",
580
                         G_CALLBACK(addressbook_tree_button_pressed),
581
                         NULL);
582
        g_signal_connect(G_OBJECT(ctree), "button_release_event",
583
                         G_CALLBACK(addressbook_tree_button_released),
584
                         NULL);
585
586
        clist_vbox = gtk_vbox_new(FALSE, 4);
587
588
        clist_swin = gtk_scrolled_window_new(NULL, NULL);
589
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(clist_swin),
590
                                       GTK_POLICY_AUTOMATIC,
591
                                       GTK_POLICY_ALWAYS);
592
        gtk_box_pack_start(GTK_BOX(clist_vbox), clist_swin, TRUE, TRUE, 0);
593
594
        /* Address list */
595
        clist = gtk_ctree_new_with_titles(N_COLS, 0, titles);
596
        gtk_container_add(GTK_CONTAINER(clist_swin), clist);
597
        gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_EXTENDED);
598
        gtk_ctree_set_line_style(GTK_CTREE(clist), GTK_CTREE_LINES_NONE);
599
        gtk_ctree_set_expander_style(GTK_CTREE(clist), GTK_CTREE_EXPANDER_SQUARE);
600
        gtk_ctree_set_indent(GTK_CTREE(clist), CTREE_INDENT);
601
        gtk_clist_set_column_width(GTK_CLIST(clist), COL_NAME,
602
                                   COL_NAME_WIDTH);
603
        gtk_clist_set_column_width(GTK_CLIST(clist), COL_ADDRESS,
604
                                   COL_ADDRESS_WIDTH);
605
        gtk_clist_set_compare_func(GTK_CLIST(clist),
606
                                   addressbook_list_compare_func);
607
        gtkut_clist_set_redraw(GTK_CLIST(clist));
608
609
        for (i = 0; i < N_COLS; i++)
610
                GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist)->column[i].button,
611
                                       GTK_CAN_FOCUS);
612
613
        g_signal_connect(G_OBJECT(clist), "tree_select_row",
614
                         G_CALLBACK(addressbook_list_row_selected), NULL);
615
        g_signal_connect(G_OBJECT(clist), "tree_unselect_row",
616
                         G_CALLBACK(addressbook_list_row_unselected), NULL);
617
        g_signal_connect(G_OBJECT(clist), "button_press_event",
618
                         G_CALLBACK(addressbook_list_button_pressed),
619
                         NULL);
620
        g_signal_connect(G_OBJECT(clist), "button_release_event",
621
                         G_CALLBACK(addressbook_list_button_released),
622
                         NULL);
623
        g_signal_connect(G_OBJECT(clist), "select_row",
624
                         G_CALLBACK(addressbook_list_selected), NULL);
625
        g_signal_connect(G_OBJECT(clist), "tree_expand",
626
                         G_CALLBACK(addressbook_person_expand_node), NULL);
627
        g_signal_connect(G_OBJECT(clist), "tree_collapse",
628
                         G_CALLBACK(addressbook_person_collapse_node), NULL);
629
630
        hbox = gtk_hbox_new(FALSE, 4);
631
        gtk_box_pack_start(GTK_BOX(clist_vbox), hbox, FALSE, FALSE, 0);
632
633
#if 0
634
        label = gtk_label_new(_("Name:"));
635
        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
636
#endif
637
638
        entry = gtk_entry_new();
639
        gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
640
641
        address_completion_register_entry(GTK_ENTRY(entry));
642
643
#if 0
644
        g_signal_connect(G_OBJECT(entry), "changed",
645
                         G_CALLBACK(addressbook_entry_changed), NULL);
646
#endif
647
648
        paned = gtk_hpaned_new();
649
        gtk_box_pack_start(GTK_BOX(vbox2), paned, TRUE, TRUE, 0);
650
        gtk_paned_add1(GTK_PANED(paned), ctree_swin);
651
        gtk_paned_add2(GTK_PANED(paned), clist_vbox);
652
653
        /* Status bar */
654
        hsbox = gtk_hbox_new(FALSE, 0);
655
        gtk_box_pack_end(GTK_BOX(vbox), hsbox, FALSE, FALSE, 0);
656
        statusbar = gtk_statusbar_new();
657
        gtk_box_pack_start(GTK_BOX(hsbox), statusbar, TRUE, TRUE, 0);
658
659
        hbbox = gtk_hbox_new(FALSE, 4);
660
        gtk_box_pack_end(GTK_BOX(vbox), hbbox, FALSE, FALSE, 0);
661
662
        /* Button panel */
663
        hbbox1 = gtk_hbutton_box_new();
664
        gtk_button_box_set_layout(GTK_BUTTON_BOX(hbbox1), GTK_BUTTONBOX_END);
665
        gtk_box_set_spacing(GTK_BOX(hbbox1), 4);
666
        gtk_container_set_border_width(GTK_CONTAINER(hbbox1), 4);
667
        gtk_button_box_set_child_size(GTK_BUTTON_BOX(hbbox1), 64, -1);
668
        gtk_box_pack_end(GTK_BOX(hbbox), hbbox1, FALSE, FALSE, 0);
669
670
        to_btn = gtk_button_new_with_label
671
                (prefs_common.trans_hdr ? _("To:") : "To:");
672
        GTK_WIDGET_SET_FLAGS(to_btn, GTK_CAN_DEFAULT);
673
        gtk_box_pack_start(GTK_BOX(hbbox1), to_btn, TRUE, TRUE, 0);
674
        cc_btn = gtk_button_new_with_label
675
                (prefs_common.trans_hdr ? _("Cc:") : "Cc:");
676
        GTK_WIDGET_SET_FLAGS(cc_btn, GTK_CAN_DEFAULT);
677
        gtk_box_pack_start(GTK_BOX(hbbox1), cc_btn, TRUE, TRUE, 0);
678
        bcc_btn = gtk_button_new_with_label
679
                (prefs_common.trans_hdr ? _("Bcc:") : "Bcc:");
680
        GTK_WIDGET_SET_FLAGS(bcc_btn, GTK_CAN_DEFAULT);
681
        gtk_box_pack_start(GTK_BOX(hbbox1), bcc_btn, TRUE, TRUE, 0);
682
683
        g_signal_connect(G_OBJECT(to_btn), "clicked",
684
                         G_CALLBACK(addressbook_to_clicked),
685
                         GINT_TO_POINTER(COMPOSE_ENTRY_TO));
686
        g_signal_connect(G_OBJECT(cc_btn), "clicked",
687
                         G_CALLBACK(addressbook_to_clicked),
688
                         GINT_TO_POINTER(COMPOSE_ENTRY_CC));
689
        g_signal_connect(G_OBJECT(bcc_btn), "clicked",
690
                         G_CALLBACK(addressbook_to_clicked),
691
                         GINT_TO_POINTER(COMPOSE_ENTRY_BCC));
692
693
        hbbox2 = gtk_hbutton_box_new();
694
        gtk_button_box_set_layout(GTK_BUTTON_BOX(hbbox2), GTK_BUTTONBOX_END);
695
        gtk_box_set_spacing(GTK_BOX(hbbox2), 4);
696
        gtk_container_set_border_width(GTK_CONTAINER(hbbox2), 4);
697
        gtk_button_box_set_child_size(GTK_BUTTON_BOX(hbbox2), 64, -1);
698
        gtk_box_pack_end(GTK_BOX(hbbox), hbbox2, TRUE, TRUE, 0);
699
700
        del_btn = gtk_button_new_with_label(_("Delete"));
701
        GTK_WIDGET_SET_FLAGS(del_btn, GTK_CAN_DEFAULT);
702
        gtk_box_pack_start(GTK_BOX(hbbox2), del_btn, TRUE, TRUE, 0);
703
        reg_btn = gtk_button_new_with_label(_("Add"));
704
        GTK_WIDGET_SET_FLAGS(reg_btn, GTK_CAN_DEFAULT);
705
        gtk_box_pack_start(GTK_BOX(hbbox2), reg_btn, TRUE, TRUE, 0);
706
        lup_btn = gtk_button_new_with_label(_("Lookup"));
707
        GTK_WIDGET_SET_FLAGS(lup_btn, GTK_CAN_DEFAULT);
708
        gtk_box_pack_start(GTK_BOX(hbbox2), lup_btn, TRUE, TRUE, 0);
709
        close_btn = gtk_button_new_with_mnemonic(_("_Close"));
710
        GTK_WIDGET_SET_FLAGS(close_btn, GTK_CAN_DEFAULT);
711
        gtk_box_pack_start(GTK_BOX(hbbox2), close_btn, TRUE, TRUE, 0);
712
        gtk_button_box_set_child_secondary(GTK_BUTTON_BOX(hbbox2), close_btn,
713
                                           TRUE);
714
715
        g_signal_connect(G_OBJECT(del_btn), "clicked",
716
                         G_CALLBACK(addressbook_del_clicked), NULL);
717
        g_signal_connect(G_OBJECT(reg_btn), "clicked",
718
                         G_CALLBACK(addressbook_reg_clicked), NULL);
719
        g_signal_connect(G_OBJECT(lup_btn), "clicked",
720
                         G_CALLBACK(addressbook_lup_clicked), NULL);
721
        g_signal_connect(G_OBJECT(close_btn), "clicked",
722
                         G_CALLBACK(addressbook_close_clicked), NULL);
723
724
        /* Build icons for interface */
725
        stock_pixmap_gdk( window, STOCK_PIXMAP_INTERFACE,
726
                          &interfacexpm, &interfacexpmmask );
727
728
        /* Build control tables */
729
        addrbookctl_build_map(window);
730
        addrbookctl_build_iflist();
731
        addrbookctl_build_ifselect();
732
733
        /* Add each interface into the tree as a root level folder */
734
        nodeIf = _addressInterfaceList_;
735
        while( nodeIf ) {
736
                AdapterInterface *adapter = nodeIf->data;
737
                AddressInterface *iface = adapter->interface;
738
                nodeIf = g_list_next(nodeIf);
739
740
                if(iface->useInterface) {
741
                        AddressTypeControlItem *atci = adapter->atci;
742
                        text = atci->displayName;
743
                        adapter->treeNode =
744
                                gtk_ctree_insert_node( GTK_CTREE(ctree),
745
                                        NULL, NULL, &text, FOLDER_SPACING,
746
                                        interfacexpm, interfacexpmmask,
747
                                        interfacexpm, interfacexpmmask,
748
                                        FALSE, FALSE );
749
                        gtk_ctree_node_set_row_data( GTK_CTREE(ctree), adapter->treeNode, adapter );
750
                }
751
        }
752
753
        /* Popup menu */
754
        n_entries = sizeof(addressbook_tree_popup_entries) /
755
                sizeof(addressbook_tree_popup_entries[0]);
756
        tree_popup = menu_create_items(addressbook_tree_popup_entries,
757
                                       n_entries,
758
                                       "<AddressBookTree>", &tree_factory,
759
                                       NULL);
760
        g_signal_connect(G_OBJECT(tree_popup), "selection_done",
761
                         G_CALLBACK(addressbook_popup_close), NULL);
762
        n_entries = sizeof(addressbook_list_popup_entries) /
763
                sizeof(addressbook_list_popup_entries[0]);
764
        list_popup = menu_create_items(addressbook_list_popup_entries,
765
                                       n_entries,
766
                                       "<AddressBookList>", &list_factory,
767
                                       NULL);
768
769
        addrbook.window  = window;
770
        addrbook.menubar = menubar;
771
        addrbook.ctree   = ctree;
772
        addrbook.clist   = clist;
773
        addrbook.entry   = entry;
774
        addrbook.statusbar = statusbar;
775
        addrbook.status_cid = gtk_statusbar_get_context_id( GTK_STATUSBAR(statusbar), "Addressbook Window" );
776
777
        addrbook.to_btn  = to_btn;
778
        addrbook.cc_btn  = cc_btn;
779
        addrbook.bcc_btn = bcc_btn;
780
        addrbook.del_btn = del_btn;
781
        addrbook.reg_btn = reg_btn;
782
        addrbook.lup_btn = lup_btn;
783
        addrbook.close_btn = close_btn;
784
785
        addrbook.tree_popup   = tree_popup;
786
        addrbook.list_popup   = list_popup;
787
        addrbook.tree_factory = tree_factory;
788
        addrbook.list_factory = list_factory;
789
        addrbook.menu_factory = menu_factory;
790
791
        addrbook.listSelected = NULL;
792
        address_completion_start(window);
793
        gtk_widget_show_all(window);
794
}
795
796
static gint addressbook_close(void)
797
{
798
        gtkut_widget_get_uposition(addrbook.window,
799
                                   &prefs_common.addressbook_x,
800
                                   &prefs_common.addressbook_y);
801
        gtk_widget_hide(addrbook.window);
802
        addressbook_export_to_file();
803
        return TRUE;
804
}
805
806
static void addressbook_status_show( gchar *msg ) {
807
        if( addrbook.statusbar != NULL ) {
808
                gtk_statusbar_pop( GTK_STATUSBAR(addrbook.statusbar), addrbook.status_cid );
809
                if( msg ) {
810
                        gtk_statusbar_push( GTK_STATUSBAR(addrbook.statusbar), addrbook.status_cid, msg );
811
                }
812
        }
813
}
814
815
static void addressbook_ds_show_message( AddressDataSource *ds ) {
816
        gint retVal;
817
        gchar *name;
818
        *addressbook_msgbuf = '\0';
819
        if( ds ) {
820
                name = addrindex_ds_get_name( ds );
821
                retVal = addrindex_ds_get_status_code( ds );
822
                if( retVal == MGU_SUCCESS ) {
823
                        if( ds ) {
824
                                sprintf( addressbook_msgbuf, "%s", name );
825
                        }
826
                }
827
                else {
828
                        if( ds == NULL ) {
829
                                sprintf( addressbook_msgbuf, "%s", mgu_error2string( retVal ) );
830
                        }
831
                        else {
832
                                sprintf( addressbook_msgbuf, "%s: %s", name, mgu_error2string( retVal ) );
833
                        }
834
                }
835
        }
836
        addressbook_status_show( addressbook_msgbuf );
837
}
838
839
/*
840
* Delete one or more objects from address list.
841
*/
842
static void addressbook_del_clicked(GtkButton *button, gpointer data)
843
{
844
        GtkCTree *clist = GTK_CTREE(addrbook.clist);
845
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
846
        AddressObject *pobj, *obj;
847
        AdapterDSource *ads = NULL;
848
        GtkCTreeNode *nodeList;
849
        gboolean procFlag;
850
        AlertValue aval;
851
        AddressBookFile *abf = NULL;
852
        AddressDataSource *ds = NULL;
853
854
        pobj = gtk_ctree_node_get_row_data(ctree, addrbook.opened );
855
        g_return_if_fail(pobj != NULL);
856
857
        nodeList = addrbook.listSelected;
858
        obj = gtk_ctree_node_get_row_data( clist, nodeList );
859
        if( obj == NULL) return;
860
        ds = addressbook_find_datasource( addrbook.treeSelected );
861
        if( ds == NULL ) return;
862
863
        procFlag = FALSE;
864
        if( pobj->type == ADDR_DATASOURCE ) {
865
                ads = ADAPTER_DSOURCE(pobj);
866
                if( ads->subType == ADDR_BOOK ) procFlag = TRUE;
867
        }
868
        else if( pobj->type == ADDR_ITEM_FOLDER ) {
869
                procFlag = TRUE;
870
        }
871
        else if( pobj->type == ADDR_ITEM_GROUP ) {
872
                procFlag = TRUE;
873
        }
874
        if( ! procFlag ) return;
875
        abf = ds->rawDataSource;
876
        if( abf == NULL ) return;
877
878
        /* Confirm deletion */
879
        aval = alertpanel( _("Delete address(es)"),
880
                        _("Really delete the address(es)?"),
881
                        GTK_STOCK_YES, GTK_STOCK_NO, NULL );
882
        if( aval != G_ALERTDEFAULT ) return;
883
884
        /* Process deletions */
885
        if( pobj->type == ADDR_DATASOURCE || pobj->type == ADDR_ITEM_FOLDER ) {
886
                /* Items inside folders */
887
                GList *node;
888
                node = _addressListSelection_;
889
                while( node ) {
890
                        AddrItemObject *aio = node->data;
891
                        node = g_list_next( node );
892
                        if( aio->type == ADDR_ITEM_GROUP ) {
893
                                ItemGroup *item = ( ItemGroup * ) aio;
894
                                GtkCTreeNode *nd = NULL;
895
896
                                nd = addressbook_find_group_node( addrbook.opened, item );
897
                                item = addrbook_remove_group( abf, item );
898
                                if( item ) {
899
                                        addritem_free_item_group( item );
900
                                        item = NULL;
901
                                }
902
                                /* Remove group from parent node */
903
                                gtk_ctree_remove_node( ctree, nd );
904
                        }
905
                        else if( aio->type == ADDR_ITEM_PERSON ) {
906
                                ItemPerson *item = ( ItemPerson * ) aio;
907
                                if( _clipObjectList_ ) {
908
                                        _clipObjectList_ = g_list_remove( _clipObjectList_, item );
909
                                }
910
                                item = addrbook_remove_person( abf, item );
911
                                if( item ) {
912
                                        addritem_free_item_person( item );
913
                                        item = NULL;
914
                                }
915
                        }
916
                        else if( aio->type == ADDR_ITEM_EMAIL ) {
917
                                ItemEMail *item = ( ItemEMail * ) aio;
918
                                ItemPerson *person = ( ItemPerson * ) ADDRITEM_PARENT(item);
919
                                item = addrbook_person_remove_email( abf, person, item );
920
                                if( item ) {
921
                                        addritem_free_item_email( item );
922
                                        item = NULL;
923
                                }
924
                        }
925
                }
926
                addressbook_list_select_clear();
927
                addrbook.treeSelected = NULL;
928
                gtk_ctree_select( ctree, addrbook.opened );
929
                return;
930
        }
931
        else if( pobj->type == ADDR_ITEM_GROUP ) {
932
                /* Items inside groups */
933
                GList *node;
934
                ItemGroup *group = ADAPTER_GROUP(pobj)->itemGroup;
935
                node = _addressListSelection_;
936
                while( node ) {
937
                        AddrItemObject *aio = node->data;
938
                        node = g_list_next( node );
939
                        if( aio->type == ADDR_ITEM_EMAIL ) {
940
                                ItemEMail *item = ( ItemEMail * ) aio;
941
                                item = addrbook_group_remove_email( abf, group, item );
942
                        }
943
                }
944
                addressbook_list_select_clear();
945
                addrbook.treeSelected = NULL;
946
                gtk_ctree_select( ctree, addrbook.opened );
947
                return;
948
        }
949
950
        gtk_ctree_node_set_row_data( clist, nodeList, NULL );
951
        gtk_ctree_remove_node( clist, nodeList );
952
        addressbook_list_select_remove( obj );
953
954
}
955
956
static void addressbook_reg_clicked(GtkButton *button, gpointer data)
957
{
958
        addressbook_new_address_cb( NULL, 0, NULL );
959
}
960
961
gchar *addressbook_format_address( AddressObject * obj ) {
962
        gchar *buf = NULL;
963
        gchar *name = NULL;
964
        gchar *address = NULL;
965
966
        if( obj->type == ADDR_ITEM_EMAIL ) {
967
                ItemPerson *person = NULL;
968
                ItemEMail *email = ( ItemEMail * ) obj;
969
970
                person = ( ItemPerson * ) ADDRITEM_PARENT(email);
971
                if( email->address ) {
972
                        if( ADDRITEM_NAME(email) ) {
973
                                name = ADDRITEM_NAME(email);
974
                                if( *name == '\0' ) {
975
                                        name = ADDRITEM_NAME(person);
976
                                }
977
                        }
978
                        else if( ADDRITEM_NAME(person) ) {
979
                                name = ADDRITEM_NAME(person);
980
                        }
981
                        else {
982
                                buf = g_strdup( email->address );
983
                        }
984
                        address = email->address;
985
                }
986
        }
987
        else if( obj->type == ADDR_ITEM_PERSON ) {
988
                ItemPerson *person = ( ItemPerson * ) obj;
989
                GList *node = person->listEMail;
990
991
                name = ADDRITEM_NAME(person);
992
                if( node ) {
993
                        ItemEMail *email = ( ItemEMail * ) node->data;
994
                        address = email->address;
995
                }
996
        }
997
        if( address ) {
998
                if( name && name[0] != '\0' ) {
999
                        if( name[0] != '"' && strpbrk( name, ",.[]<>" ) != NULL )
1000
                                buf = g_strdup_printf( "\"%s\" <%s>", name, address );
1001
                        else
1002
                                buf = g_strdup_printf( "%s <%s>", name, address );
1003
                }
1004
                else {
1005
                        buf = g_strdup( address );
1006
                }
1007
        }
1008
1009
        return buf;
1010
}
1011
1012
static void addressbook_to_clicked(GtkButton *button, gpointer data)
1013
{
1014
        GList *node = _addressListSelection_;
1015
1016
        if (!addrbook.target_compose) {
1017
                addrbook.target_compose = compose_new(NULL, NULL, NULL, NULL);
1018
                if (!addrbook.target_compose)
1019
                        return;
1020
        }
1021
1022
        while( node ) {
1023
                AddressObject *obj = node->data;
1024
                Compose *compose = addrbook.target_compose;
1025
1026
                node = g_list_next( node );
1027
                if( obj->type == ADDR_ITEM_PERSON || obj->type == ADDR_ITEM_EMAIL ) {
1028
                        gchar *addr = addressbook_format_address( obj );
1029
                        compose_entry_append( compose, addr, (ComposeEntryType) data );
1030
                        g_free( addr );
1031
                        addr = NULL;
1032
                }
1033
                else if( obj->type == ADDR_ITEM_GROUP ) {
1034
                        ItemGroup *group = ( ItemGroup * ) obj;
1035
                        GList *nodeMail = group->listEMail;
1036
                        while( nodeMail ) {
1037
                                ItemEMail *email = nodeMail->data;
1038
                                gchar *addr = addressbook_format_address( ( AddressObject * ) email );
1039
                                compose_entry_append( compose, addr, (ComposeEntryType) data );
1040
                                g_free( addr );
1041
                                nodeMail = g_list_next( nodeMail );
1042
                        }
1043
                }
1044
        }
1045
}
1046
1047
static void addressbook_menuitem_set_sensitive(void) {
1048
        gboolean canAdd = FALSE;
1049
        gboolean canEditTree = TRUE;
1050
        gboolean canEditAddress = FALSE;
1051
        gboolean canDelete = FALSE;
1052
        gboolean canLookup = FALSE;
1053
        gboolean canCopy = FALSE;
1054
        gboolean canPaste = FALSE;
1055
        AddressTypeControlItem *atci = NULL;
1056
        AddressDataSource *ds = NULL;
1057
        AddressInterface *iface = NULL;
1058
        AddressObject *pobj = NULL;
1059
        AddressObject *obj = NULL;
1060
1061
        menu_set_sensitive( addrbook.menu_factory, "/File/New Book", FALSE );
1062
        menu_set_sensitive( addrbook.menu_factory, "/File/New vCard", FALSE );
1063
#ifdef USE_JPILOT
1064
        menu_set_sensitive( addrbook.menu_factory, "/File/New JPilot", FALSE );
1065
#endif
1066
#ifdef USE_LDAP
1067
        menu_set_sensitive( addrbook.menu_factory, "/File/New LDAP Server", FALSE );
1068
#endif
1069
        menu_set_insensitive_all(GTK_MENU_SHELL(addrbook.tree_popup));
1070
        menu_set_insensitive_all( GTK_MENU_SHELL(addrbook.list_popup) );
1071
1072
        pobj = gtk_ctree_node_get_row_data( GTK_CTREE(addrbook.ctree), addrbook.treeSelected );
1073
        if( pobj == NULL ) return;
1074
1075
        if( addrbook.listSelected )
1076
                obj = gtk_ctree_node_get_row_data( GTK_CTREE(addrbook.clist), addrbook.listSelected );
1077
1078
        if( pobj->type == ADDR_INTERFACE ) {
1079
                AdapterInterface *adapter = ADAPTER_INTERFACE(pobj);
1080
                iface = adapter->interface;
1081
                if( iface ) {
1082
                        if( iface->haveLibrary ) {
1083
                                /* Enable appropriate File / New command */
1084
                                atci = adapter->atci;
1085
                                menu_set_sensitive( addrbook.menu_factory, atci->menuCommand, TRUE );
1086
                        }
1087
                }
1088
                canEditTree = FALSE;
1089
        }
1090
        else if( pobj->type == ADDR_DATASOURCE ) {
1091
                AdapterDSource *ads = ADAPTER_DSOURCE(pobj);
1092
                ds = ads->dataSource;
1093
                iface = ds->interface;
1094
                if( ! iface->readOnly ) {
1095
                        canAdd = canEditAddress = TRUE;
1096
                }
1097
                if( ! iface->haveLibrary ) {
1098
                        canAdd = canEditAddress = FALSE;
1099
                }
1100
#ifdef USE_LDAP
1101
                if( ads->subType == ADDR_LDAP &&
1102
                    iface->haveLibrary && ds->rawDataSource ) {
1103
                        canLookup = TRUE;
1104
                }
1105
#endif
1106
        }
1107
        else if( pobj->type == ADDR_ITEM_FOLDER ) {
1108
                ds = addressbook_find_datasource( addrbook.treeSelected );
1109
                if( ds ) {
1110
                        iface = ds->interface;
1111
                        if( ! iface->readOnly ) {
1112
                                canAdd = canEditAddress = TRUE;
1113
                        }
1114
                }
1115
        }
1116
        else if( pobj->type == ADDR_ITEM_GROUP ) {
1117
                ds = addressbook_find_datasource( addrbook.treeSelected );
1118
                if( ds ) {
1119
                        iface = ds->interface;
1120
                        if( ! iface->readOnly ) {
1121
                                canEditAddress = TRUE;
1122
                        }
1123
                }
1124
        }
1125
1126
        if( obj == NULL ) canEditAddress = FALSE;
1127
        canDelete = canEditAddress;
1128
        if( GTK_CLIST(addrbook.clist)->selection &&
1129
            GTK_CLIST(addrbook.clist)->selection->next ) canEditAddress = FALSE;
1130
        if( _addressListSelection_ ) {
1131
                GList *cur;
1132
                AddressObject *item;
1133
                for( cur = _addressListSelection_; cur != NULL; cur = cur->next ) {
1134
                        item = cur->data;
1135
                        if( item->type == ADDR_ITEM_PERSON ) {
1136
                                canCopy = TRUE;
1137
                                break;
1138
                        }
1139
                }
1140
        }
1141
        if( _clipObjectList_ && canAdd ) canPaste = TRUE;
1142
1143
        /* Enable add */
1144
        menu_set_sensitive( addrbook.menu_factory, "/Address/New Address", canAdd );
1145
        menu_set_sensitive( addrbook.menu_factory, "/Address/New Folder",  canAdd );
1146
        menu_set_sensitive( addrbook.menu_factory, "/Address/New Group",   canAdd );
1147
1148
        /* Enable edit */
1149
        menu_set_sensitive( addrbook.menu_factory, "/Address/Edit",   canEditAddress );
1150
        menu_set_sensitive( addrbook.menu_factory, "/Address/Delete", canDelete );
1151
1152
        menu_set_sensitive( addrbook.menu_factory, "/File/Edit",      canEditTree );
1153
        menu_set_sensitive( addrbook.menu_factory, "/File/Delete",    canEditTree );
1154
1155
        menu_set_sensitive( addrbook.menu_factory, "/Edit/Copy",   canCopy );
1156
        menu_set_sensitive( addrbook.menu_factory, "/Edit/Paste",  canPaste );
1157
1158
        /* Popup menu */
1159
        menu_set_sensitive( addrbook.tree_factory, "/New Address", canAdd );
1160
        menu_set_sensitive( addrbook.tree_factory, "/New Folder", canAdd );
1161
        menu_set_sensitive( addrbook.tree_factory, "/New Group", canAdd );
1162
        menu_set_sensitive( addrbook.tree_factory, "/Edit", canEditTree );
1163
        menu_set_sensitive( addrbook.tree_factory, "/Delete", canEditTree );
1164
1165
        menu_set_sensitive( addrbook.list_factory, "/New Address", canAdd );
1166
        menu_set_sensitive( addrbook.list_factory, "/New Folder", canAdd );
1167
        menu_set_sensitive( addrbook.list_factory, "/New Group", canAdd );
1168
        menu_set_sensitive( addrbook.list_factory, "/Edit", canEditAddress );
1169
        menu_set_sensitive( addrbook.list_factory, "/Delete", canDelete );
1170
        menu_set_sensitive( addrbook.list_factory, "/Copy", canCopy );
1171
        menu_set_sensitive( addrbook.list_factory, "/Paste", canPaste );
1172
1173
        /* Buttons */
1174
        gtk_widget_set_sensitive( addrbook.reg_btn, canAdd );
1175
        gtk_widget_set_sensitive( addrbook.del_btn, canDelete );
1176
        gtk_widget_set_sensitive( addrbook.lup_btn, canLookup );
1177
}
1178
1179
static void addressbook_tree_selected(GtkCTree *ctree, GtkCTreeNode *node,
1180
                                      gint column, gpointer data)
1181
{
1182
        AddressObject *obj = NULL;
1183
        AdapterDSource *ads = NULL;
1184
        AddressDataSource *ds = NULL;
1185
        ItemFolder *rootFolder = NULL;
1186
1187
        if( addrbook.treeSelected == node ) return;
1188
        addrbook.treeSelected = node;
1189
        addrbook.listSelected = NULL;
1190
        addressbook_status_show( "" );
1191
        if( addrbook.entry != NULL ) gtk_entry_set_text(GTK_ENTRY(addrbook.entry), "");
1192
1193
        if( addrbook.clist ) gtk_clist_clear( GTK_CLIST(addrbook.clist) );
1194
        if( node ) obj = gtk_ctree_node_get_row_data( ctree, node );
1195
        if( obj == NULL ) return;
1196
1197
        addrbook.opened = node;
1198
1199
        if( obj->type == ADDR_DATASOURCE ) {
1200
                /* Read from file */
1201
                static gboolean tVal = TRUE;
1202
1203
                ads = ADAPTER_DSOURCE(obj);
1204
                if( ads == NULL ) return;
1205
                ds = ads->dataSource;
1206
                if( ds == NULL ) return;                
1207
1208
                if( addrindex_ds_get_modify_flag( ds ) ) {
1209
                        addrindex_ds_read_data( ds );
1210
                }
1211
1212
                if( ! addrindex_ds_get_read_flag( ds ) ) {
1213
                        addrindex_ds_read_data( ds );
1214
                }
1215
                addressbook_ds_show_message( ds );
1216
1217
                if( ! addrindex_ds_get_access_flag( ds ) ) {
1218
                        /* Remove existing folders and groups */
1219
                        gtk_clist_freeze( GTK_CLIST(ctree) );
1220
                        addressbook_tree_remove_children( ctree, node );
1221
                        gtk_clist_thaw( GTK_CLIST(ctree) );
1222
1223
                        /* Load folders into the tree */
1224
                        rootFolder = addrindex_ds_get_root_folder( ds );
1225
                        if( ds->type == ADDR_IF_JPILOT ) {
1226
                                addressbook_node_add_folder( node, ds, rootFolder, ADDR_CATEGORY );
1227
                        }
1228
                        else {
1229
                                addressbook_node_add_folder( node, ds, rootFolder, ADDR_ITEM_FOLDER );
1230
                        }
1231
                        addrindex_ds_set_access_flag( ds, &tVal );
1232
                        gtk_ctree_expand( ctree, node );
1233
                }
1234
        }
1235
1236
        /* Update address list */
1237
        addressbook_set_clist( obj );
1238
1239
        addressbook_menuitem_set_sensitive();
1240
1241
        addressbook_list_select_clear();
1242
1243
}
1244
1245
static void addressbook_list_selected(GtkCList *clist, gint row, gint column,
1246
                                      GdkEvent *event, gpointer data)
1247
{
1248
        if (event && event->type == GDK_2BUTTON_PRESS) {
1249
                /* Handle double click */
1250
                if (prefs_common.add_address_by_click &&
1251
                    addrbook.target_compose)
1252
                        addressbook_to_clicked(NULL, GINT_TO_POINTER(COMPOSE_ENTRY_TO));
1253
                else
1254
                        addressbook_edit_address_cb(NULL, 0, NULL);
1255
        }
1256
}
1257
1258
#if 0
1259
static void addressbook_list_select_show() {
1260
        GList *node = _addressListSelection_;
1261
        gchar *addr = NULL;
1262
        printf( "show selection...>>>\n" );
1263
        while( node != NULL ) {
1264
                AddressObject *obj = ( AddressObject * ) node->data;
1265
                if( obj ) {
1266
                        printf( "- %d : '%s'\n", obj->type, obj->name );
1267
                        if( obj->type == ADDR_ITEM_GROUP ) {
1268
                                ItemGroup *group = ( ItemGroup * ) obj;
1269
                                GList *node = group->listEMail;
1270
                                while( node ) {
1271
                                        ItemEMail *email = node->data;
1272
                                        addr = addressbook_format_address( ( AddressObject * ) email );
1273
                                        if( addr ) {
1274
                                                printf( "\tgrp >%s<\n", addr );
1275
                                                g_free( addr );
1276
                                        }
1277
                                        node = g_list_next( node );
1278
                                }
1279
                        }
1280
                        else {
1281
                                addr = addressbook_format_address( obj );
1282
                                if( addr ) {
1283
                                        printf( "\t>%s<\n", addr );
1284
                                        g_free( addr );
1285
                                }
1286
                        }
1287
                }
1288
                else {
1289
                        printf( "- NULL" );
1290
                }
1291
                node = g_list_next( node );
1292
        }
1293
        printf( "show selection...<<<\n" );
1294
}
1295
#endif
1296
1297
static void addressbook_list_select_clear() {
1298
        if( _addressListSelection_ ) {
1299
                g_list_free( _addressListSelection_ );
1300
        }
1301
        _addressListSelection_ = NULL;
1302
}
1303
1304
static void addressbook_list_select_add( AddressObject *obj ) {
1305
        if( obj ) {
1306
                if(     obj->type == ADDR_ITEM_PERSON ||
1307
                        obj->type == ADDR_ITEM_EMAIL ||
1308
                        obj->type == ADDR_ITEM_GROUP ) {
1309
                        if( ! g_list_find( _addressListSelection_, obj ) ) {
1310
                                _addressListSelection_ = g_list_append( _addressListSelection_, obj );
1311
                        }
1312
                }
1313
        }
1314
        /* addressbook_list_select_show(); */
1315
}
1316
1317
static void addressbook_list_select_remove( AddressObject *obj ) {
1318
        if( obj == NULL ) return;
1319
        if( _addressListSelection_ ) {
1320
                _addressListSelection_ = g_list_remove(        _addressListSelection_, obj );
1321
        }
1322
        /* addressbook_list_select_show(); */
1323
}
1324
1325
static void addressbook_list_row_selected( GtkCTree *clist, GtkCTreeNode *node, gint column, gpointer data ) {
1326
        GtkEntry *entry = GTK_ENTRY(addrbook.entry);
1327
        AddressObject *obj = NULL;
1328
1329
        gtk_entry_set_text( entry, "" );
1330
        addrbook.listSelected = node;
1331
        obj = gtk_ctree_node_get_row_data( clist, node );
1332
        if( obj != NULL ) {
1333
                addressbook_list_select_add( obj );
1334
        }
1335
1336
        addressbook_menuitem_set_sensitive();
1337
}
1338
1339
static void addressbook_list_row_unselected( GtkCTree *ctree, GtkCTreeNode *node, gint column, gpointer data ) {
1340
        AddressObject *obj;
1341
1342
        obj = gtk_ctree_node_get_row_data( ctree, node );
1343
        if( obj != NULL ) {
1344
                addressbook_list_select_remove( obj );
1345
        }
1346
1347
        addressbook_menuitem_set_sensitive();
1348
}
1349
1350
static gboolean addressbook_list_button_pressed(GtkWidget *widget,
1351
                                                GdkEventButton *event,
1352
                                                gpointer data)
1353
{
1354
        if( ! event ) return FALSE;
1355
1356
        if( event->button == 3 ) {
1357
                gtk_menu_popup( GTK_MENU(addrbook.list_popup), NULL, NULL, NULL, NULL,
1358
                       event->button, event->time );
1359
        }
1360
        return FALSE;
1361
}
1362
1363
static gboolean addressbook_list_button_released(GtkWidget *widget,
1364
                                                 GdkEventButton *event,
1365
                                                 gpointer data)
1366
{
1367
        return FALSE;
1368
}
1369
1370
static gboolean addressbook_tree_button_pressed(GtkWidget *ctree,
1371
                                                GdkEventButton *event,
1372
                                                gpointer data)
1373
{
1374
        GtkCList *clist = GTK_CLIST(ctree);
1375
        gint row, column;
1376
        AddressObject *obj = NULL;
1377
        /* GtkCTreeNode *node; */
1378
        AdapterDSource *ads = NULL;
1379
        AddressInterface *iface = NULL;
1380
        AddressDataSource *ds = NULL;
1381
1382
        if( ! event ) return FALSE;
1383
/* */
1384
        if( gtk_clist_get_selection_info( clist, event->x, event->y, &row, &column ) ) {
1385
                gtk_clist_select_row( clist, row, column );
1386
                gtkut_clist_set_focus_row(clist, row);
1387
        }
1388
/* */
1389
1390
        addressbook_menuitem_set_sensitive();
1391
1392
        if( event->button == 3 ) {
1393
                gtk_menu_popup(GTK_MENU(addrbook.tree_popup), NULL, NULL, NULL, NULL,
1394
                               event->button, event->time);
1395
        }
1396
1397
        return FALSE;
1398
}
1399
1400
static gboolean addressbook_tree_button_released(GtkWidget *ctree,
1401
                                                 GdkEventButton *event,
1402
                                                 gpointer data)
1403
{
1404
#if 0
1405
        gtk_ctree_select(GTK_CTREE(addrbook.ctree), addrbook.opened);
1406
        gtkut_ctree_set_focus_row(GTK_CTREE(addrbook.ctree), addrbook.opened);
1407
#endif
1408
        return FALSE;
1409
}
1410
1411
static void addressbook_popup_close(GtkMenuShell *menu_shell, gpointer data)
1412
{
1413
        if (!addrbook.opened) return;
1414
1415
        gtk_ctree_select(GTK_CTREE(addrbook.ctree), addrbook.opened);
1416
        gtkut_ctree_set_focus_row(GTK_CTREE(addrbook.ctree),
1417
                                  addrbook.opened);
1418
}
1419
1420
static void addressbook_new_folder_cb(gpointer data, guint action,
1421
                                      GtkWidget *widget)
1422
{
1423
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
1424
        AddressObject *obj = NULL;
1425
        AddressDataSource *ds = NULL;
1426
        AddressBookFile *abf = NULL;
1427
        ItemFolder *parentFolder = NULL;
1428
        ItemFolder *folder = NULL;
1429
1430
        if( ! addrbook.treeSelected ) return;
1431
        obj = gtk_ctree_node_get_row_data( ctree, addrbook.treeSelected );
1432
        if( obj == NULL ) return;
1433
        ds = addressbook_find_datasource( addrbook.treeSelected );
1434
        if( ds == NULL ) return;
1435
1436
        if( obj->type == ADDR_DATASOURCE ) {
1437
                if( ADAPTER_DSOURCE(obj)->subType != ADDR_BOOK ) return;
1438
        }
1439
        else if( obj->type == ADDR_ITEM_FOLDER ) {
1440
                parentFolder = ADAPTER_FOLDER(obj)->itemFolder;
1441
        }
1442
        else {
1443
                return;
1444
        }
1445
1446
        abf = ds->rawDataSource;
1447
        if( abf == NULL ) return;
1448
        folder = addressbook_edit_folder( abf, parentFolder, NULL );
1449
        if( folder ) {
1450
                GtkCTreeNode *nn;
1451
                nn = addressbook_node_add_folder( addrbook.treeSelected, ds, folder, ADDR_ITEM_FOLDER );
1452
                gtk_ctree_expand( ctree, addrbook.treeSelected );
1453
                if( addrbook.treeSelected == addrbook.opened ) addressbook_set_clist(obj);
1454
        }
1455
1456
}
1457
1458
static void addressbook_new_group_cb(gpointer data, guint action,
1459
                                     GtkWidget *widget)
1460
{
1461
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
1462
        AddressObject *obj = NULL;
1463
        AddressDataSource *ds = NULL;
1464
        AddressBookFile *abf = NULL;
1465
        ItemFolder *parentFolder = NULL;
1466
        ItemGroup *group = NULL;
1467
1468
        if( ! addrbook.treeSelected ) return;
1469
        obj = gtk_ctree_node_get_row_data(ctree, addrbook.treeSelected);
1470
        if( obj == NULL ) return;
1471
        ds = addressbook_find_datasource( addrbook.treeSelected );
1472
        if( ds == NULL ) return;
1473
1474
        if( obj->type == ADDR_DATASOURCE ) {
1475
                if( ADAPTER_DSOURCE(obj)->subType != ADDR_BOOK ) return;
1476
        }
1477
        else if( obj->type == ADDR_ITEM_FOLDER ) {
1478
                parentFolder = ADAPTER_FOLDER(obj)->itemFolder;
1479
        }
1480
        else {
1481
                return;
1482
        }
1483
1484
        abf = ds->rawDataSource;
1485
        if( abf == NULL ) return;
1486
        group = addressbook_edit_group( abf, parentFolder, NULL );
1487
        if( group ) {
1488
                GtkCTreeNode *nn;
1489
                nn = addressbook_node_add_group( addrbook.treeSelected, ds, group );
1490
                gtk_ctree_expand( ctree, addrbook.treeSelected );
1491
                if( addrbook.treeSelected == addrbook.opened ) addressbook_set_clist(obj);
1492
        }
1493
1494
}
1495
1496
static void addressbook_change_node_name(GtkCTreeNode *node, const gchar *name)
1497
{
1498
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
1499
        gchar *text[1];
1500
        guint8 spacing;
1501
        GdkPixmap *pix_cl, *pix_op;
1502
        GdkBitmap *mask_cl, *mask_op;
1503
        gboolean is_leaf, expanded;
1504
1505
        gtk_ctree_get_node_info(ctree, node, text, &spacing,
1506
                                &pix_cl, &mask_cl, &pix_op, &mask_op,
1507
                                &is_leaf, &expanded);
1508
        gtk_ctree_set_node_info(ctree, node, name, spacing,
1509
                                pix_cl, mask_cl, pix_op, mask_op,
1510
                                is_leaf, expanded);
1511
}
1512
1513
/*
1514
* Edit data source.
1515
* Enter: obj   Address object to edit.
1516
*        node  Node in tree.
1517
* Return: New name of data source.
1518
*/
1519
static gchar *addressbook_edit_datasource( AddressObject *obj, GtkCTreeNode *node ) {
1520
        gchar *newName = NULL;
1521
        AddressDataSource *ds = NULL;
1522
        AddressInterface *iface = NULL;
1523
        AdapterDSource *ads = NULL;
1524
1525
        ds = addressbook_find_datasource( node );
1526
        if( ds == NULL ) return NULL;
1527
        iface = ds->interface;
1528
        if( ! iface->haveLibrary ) return NULL;
1529
1530
        /* Read data from data source */
1531
        if( ! addrindex_ds_get_read_flag( ds ) ) {
1532
                addrindex_ds_read_data( ds );
1533
        }
1534
1535
        /* Handle edit */
1536
        ads = ADAPTER_DSOURCE(obj);
1537
        if( ads->subType == ADDR_BOOK ) {
1538
                if( addressbook_edit_book( _addressIndex_, ads ) == NULL ) return NULL;
1539
        }
1540
        else if( ads->subType == ADDR_VCARD ) {
1541
                       if( addressbook_edit_vcard( _addressIndex_, ads ) == NULL ) return NULL;
1542
        }
1543
#ifdef USE_JPILOT
1544
        else if( ads->subType == ADDR_JPILOT ) {
1545
                if( addressbook_edit_jpilot( _addressIndex_, ads ) == NULL ) return NULL;
1546
        }
1547
#endif
1548
#ifdef USE_LDAP
1549
        else if( ads->subType == ADDR_LDAP ) {
1550
                if( addressbook_edit_ldap( _addressIndex_, ads ) == NULL ) return NULL;
1551
        }
1552
#endif
1553
        else {
1554
                return NULL;
1555
        }
1556
        newName = obj->name;
1557
        return newName;
1558
}
1559
1560
/*
1561
* Edit an object that is in the address tree area.
1562
*/
1563
static void addressbook_treenode_edit_cb(gpointer data, guint action,
1564
                                       GtkWidget *widget)
1565
{
1566
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
1567
        AddressObject *obj;
1568
        AddressDataSource *ds = NULL;
1569
        AddressBookFile *abf = NULL;
1570
        GtkCTreeNode *node = NULL, *parentNode = NULL;
1571
        gchar *name = NULL;
1572
1573
        if( ! addrbook.treeSelected ) return;
1574
        node = addrbook.treeSelected;
1575
        if( GTK_CTREE_ROW(node)->level == 1 ) return;
1576
        obj = gtk_ctree_node_get_row_data( ctree, node );
1577
        if( obj == NULL ) return;
1578
        parentNode = GTK_CTREE_ROW(node)->parent;
1579
1580
        ds = addressbook_find_datasource( node );
1581
        if( ds == NULL ) return;
1582
1583
        if( obj->type == ADDR_DATASOURCE ) {
1584
                name = addressbook_edit_datasource( obj, node );
1585
                if( name == NULL ) return;
1586
        }
1587
        else {
1588
                abf = ds->rawDataSource;
1589
                if( abf == NULL ) return;
1590
                if( obj->type == ADDR_ITEM_FOLDER ) {
1591
                        AdapterFolder *adapter = ADAPTER_FOLDER(obj);
1592
                        ItemFolder *item = adapter->itemFolder;
1593
                        ItemFolder *parentFolder = NULL;
1594
                        parentFolder = ( ItemFolder * ) ADDRITEM_PARENT(item);
1595
                        if( addressbook_edit_folder( abf, parentFolder, item ) == NULL ) return;
1596
                        name = ADDRITEM_NAME(item);
1597
                }
1598
                else if( obj->type == ADDR_ITEM_GROUP ) {
1599
                        AdapterGroup *adapter = ADAPTER_GROUP(obj);
1600
                        ItemGroup *item = adapter->itemGroup;
1601
                        ItemFolder *parentFolder = NULL;
1602
                        parentFolder = ( ItemFolder * ) ADDRITEM_PARENT(item);
1603
                        if( addressbook_edit_group( abf, parentFolder, item ) == NULL ) return;
1604
                        name = ADDRITEM_NAME(item);
1605
                }
1606
        }
1607
        if( name && parentNode ) {
1608
                /* Update node in tree view */
1609
                addressbook_change_node_name( node, name );
1610
                gtk_ctree_sort_node(ctree, parentNode);
1611
                gtk_ctree_expand( ctree, node );
1612
                addrbook.treeSelected = NULL;
1613
                gtk_ctree_select( ctree, node );
1614
        }
1615
}
1616
1617
/*
1618
* Delete an item from the tree widget.
1619
*/
1620
static void addressbook_treenode_delete_cb(gpointer data, guint action,
1621
                                         GtkWidget *widget)
1622
{
1623
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
1624
        GtkCTreeNode *node = NULL;
1625
        AddressObject *obj;
1626
        gchar *message;
1627
        AlertValue aval;
1628
        AddressBookFile *abf = NULL;
1629
        AdapterDSource *ads = NULL;
1630
        AddressInterface *iface = NULL;
1631
        AddressDataSource *ds = NULL;
1632
        gboolean remFlag = FALSE;
1633
1634
        if( ! addrbook.treeSelected ) return;
1635
        node = addrbook.treeSelected;
1636
        if( GTK_CTREE_ROW(node)->level == 1 ) return;
1637
1638
        obj = gtk_ctree_node_get_row_data( ctree, node );
1639
        g_return_if_fail(obj != NULL);
1640
1641
        if( obj->type == ADDR_DATASOURCE ) {
1642
                ads = ADAPTER_DSOURCE(obj);
1643
                if( ads == NULL ) return;
1644
                ds = ads->dataSource;
1645
                if( ds == NULL ) return;
1646
        }
1647
        else {
1648
                /* Must be folder or something else */
1649
                ds = addressbook_find_datasource( node );
1650
                if( ds == NULL ) return;
1651
1652
                /* Only allow deletion from non-readOnly data sources */
1653
                iface = ds->interface;
1654
                if( iface->readOnly ) return;
1655
        }
1656
1657
        /* Confirm deletion */
1658
        if( obj->type == ADDR_ITEM_FOLDER ) {
1659
                message = g_strdup_printf
1660
                        ( _( "Do you want to delete the folder AND all addresses in `%s' ?\n"
1661
                             "If deleting the folder only, addresses will be moved into parent folder." ),
1662
                         obj->name );
1663
                aval = alertpanel( _("Delete folder"), message, _("_Folder only"), _("Folder and _addresses"), GTK_STOCK_CANCEL );
1664
                g_free(message);
1665
                if( aval != G_ALERTDEFAULT && aval != G_ALERTALTERNATE ) return;
1666
        }
1667
        else {
1668
                message = g_strdup_printf(_("Really delete `%s' ?"), obj->name);
1669
                aval = alertpanel(_("Delete"), message, GTK_STOCK_YES, GTK_STOCK_NO, NULL);
1670
                g_free(message);
1671
                if (aval != G_ALERTDEFAULT) return;
1672
        }
1673
1674
        /* Proceed with deletion */
1675
        if( obj->type == ADDR_DATASOURCE ) {
1676
                /* Remove data source. */
1677
                if( addrindex_index_remove_datasource( _addressIndex_, ds ) ) {
1678
                        addressbook_free_child_adapters( node );
1679
                        remFlag = TRUE;
1680
                }
1681
        }
1682
        else {
1683
                abf = addressbook_get_book_file();
1684
                if( abf == NULL ) return;
1685
        }
1686
1687
        if( obj->type == ADDR_ITEM_FOLDER ) {
1688
                AdapterFolder *adapter = ADAPTER_FOLDER(obj);
1689
                ItemFolder *item = adapter->itemFolder;
1690
                if( aval == G_ALERTDEFAULT ) {
1691
                        /* Remove folder only */
1692
                        item = addrbook_remove_folder( abf, item );
1693
                        if( item ) {
1694
                                addritem_free_item_folder( item );
1695
                                addressbook_move_nodes_up( ctree, node );
1696
                                remFlag = TRUE;
1697
                        }
1698
                }
1699
                else if( aval == G_ALERTALTERNATE ) {
1700
                        /* Remove folder and addresses */
1701
                        item = addrbook_remove_folder_delete( abf, item );
1702
                        if( item ) {
1703
                                addritem_free_item_folder( item );
1704
                                addressbook_free_child_adapters( node );
1705
                                remFlag = TRUE;
1706
                        }
1707
                }
1708
        }
1709
        else if( obj->type == ADDR_ITEM_GROUP ) {
1710
                AdapterGroup *adapter = ADAPTER_GROUP(obj);
1711
                ItemGroup *item = adapter->itemGroup;
1712
1713
                item = addrbook_remove_group( abf, item );
1714
                if( item ) {
1715
                        addritem_free_item_group( item );
1716
                        remFlag = TRUE;
1717
                }
1718
        }
1719
1720
        if( remFlag ) {
1721
                /* Free up adapter and remove node. */
1722
                addressbook_free_adapter( node );
1723
                gtk_ctree_remove_node(ctree, node );
1724
        }
1725
}
1726
1727
static void addressbook_new_address_cb( gpointer data, guint action, GtkWidget *widget ) {
1728
        AddressObject *pobj = NULL;
1729
        AddressDataSource *ds = NULL;
1730
        AddressBookFile *abf = NULL;
1731
1732
        pobj = gtk_ctree_node_get_row_data(GTK_CTREE(addrbook.ctree), addrbook.treeSelected);
1733
        if( pobj == NULL ) return;
1734
        ds = addressbook_find_datasource( GTK_CTREE_NODE(addrbook.treeSelected) );
1735
        if( ds == NULL ) return;
1736
1737
        abf = ds->rawDataSource;
1738
        if( abf == NULL ) return;
1739
1740
        if( pobj->type == ADDR_DATASOURCE ) {
1741
                if( ADAPTER_DSOURCE(pobj)->subType == ADDR_BOOK ) {
1742
                        /* New address */
1743
                        ItemPerson *person = addressbook_edit_person( abf, NULL, NULL, FALSE );
1744
                        if( person ) {
1745
                                if( addrbook.treeSelected == addrbook.opened ) {
1746
                                        addrbook.treeSelected = NULL;
1747
                                        gtk_ctree_select( GTK_CTREE(addrbook.ctree), addrbook.opened );
1748
                                }
1749
                        }
1750
                }
1751
        }
1752
        else if( pobj->type == ADDR_ITEM_FOLDER ) {
1753
                /* New address */
1754
                ItemFolder *folder = ADAPTER_FOLDER(pobj)->itemFolder;
1755
                ItemPerson *person = addressbook_edit_person( abf, folder, NULL, FALSE );
1756
                if( person ) {
1757
                        if (addrbook.treeSelected == addrbook.opened) {
1758
                                addrbook.treeSelected = NULL;
1759
                                gtk_ctree_select( GTK_CTREE(addrbook.ctree), addrbook.opened );
1760
                        }
1761
                }
1762
        }
1763
        else if( pobj->type == ADDR_ITEM_GROUP ) {
1764
                /* New address in group */
1765
                ItemGroup *group = ADAPTER_GROUP(pobj)->itemGroup;
1766
                if( addressbook_edit_group( abf, NULL, group ) == NULL ) return;
1767
                if (addrbook.treeSelected == addrbook.opened) {
1768
                        /* Change node name in tree. */
1769
                        addressbook_change_node_name( addrbook.treeSelected, ADDRITEM_NAME(group) );
1770
                        addrbook.treeSelected = NULL;
1771
                        gtk_ctree_select( GTK_CTREE(addrbook.ctree), addrbook.opened );
1772
                }
1773
        }
1774
}
1775
1776
/*
1777
* Search for specified group in address index tree.
1778
*/
1779
static GtkCTreeNode *addressbook_find_group_node( GtkCTreeNode *parent, ItemGroup *group ) {
1780
        GtkCTreeNode *node = NULL;
1781
        GtkCTreeRow *currRow;
1782
1783
        currRow = GTK_CTREE_ROW( parent );
1784
        if( currRow ) {
1785
                node = currRow->children;
1786
                while( node ) {
1787
                        AddressObject *obj = gtk_ctree_node_get_row_data( GTK_CTREE(addrbook.ctree), node );
1788
                        if( obj->type == ADDR_ITEM_GROUP ) {
1789
                                ItemGroup *g = ADAPTER_GROUP(obj)->itemGroup;
1790
                                if( g == group ) return node;
1791
                        }
1792
                        currRow = GTK_CTREE_ROW(node);
1793
                        node = currRow->sibling;
1794
                }
1795
        }
1796
        return NULL;
1797
}
1798
1799
static AddressBookFile *addressbook_get_book_file() {
1800
        AddressBookFile *abf = NULL;
1801
        AddressDataSource *ds = NULL;
1802
1803
        ds = addressbook_find_datasource( addrbook.treeSelected );
1804
        if( ds == NULL ) return NULL;
1805
        if( ds->type == ADDR_IF_BOOK ) abf = ds->rawDataSource;
1806
        return abf;
1807
}
1808
1809
static void addressbook_tree_remove_children( GtkCTree *ctree, GtkCTreeNode *parent ) {
1810
        GtkCTreeNode *node;
1811
        GtkCTreeRow *row;
1812
1813
        /* Remove existing folders and groups */
1814
        row = GTK_CTREE_ROW( parent );
1815
        if( row ) {
1816
                while( (node = row->children) ) {
1817
                        gtk_ctree_remove_node( ctree, node );
1818
                }
1819
        }
1820
}
1821
1822
static void addressbook_move_nodes_up( GtkCTree *ctree, GtkCTreeNode *node ) {
1823
        GtkCTreeNode *parent, *child;
1824
        GtkCTreeRow *currRow;
1825
        currRow = GTK_CTREE_ROW( node );
1826
        if( currRow ) {
1827
                parent = currRow->parent;
1828
                while( (child = currRow->children) ) {
1829
                        gtk_ctree_move( ctree, child, parent, node );
1830
                }
1831
                gtk_ctree_sort_node( ctree, parent );
1832
        }
1833
}
1834
1835
static void addressbook_edit_address_cb( gpointer data, guint action, GtkWidget *widget ) {
1836
        GtkCTree *clist = GTK_CTREE(addrbook.clist);
1837
        GtkCTree *ctree;
1838
        AddressObject *obj = NULL, *pobj = NULL;
1839
        AddressDataSource *ds = NULL;
1840
        GtkCTreeNode *node = NULL, *parentNode = NULL;
1841
        gchar *name = NULL;
1842
        AddressBookFile *abf = NULL;
1843
1844
        if( addrbook.listSelected == NULL ) return;
1845
        obj = gtk_ctree_node_get_row_data( clist, addrbook.listSelected );
1846
        g_return_if_fail(obj != NULL);
1847
1848
               ctree = GTK_CTREE( addrbook.ctree );
1849
        pobj = gtk_ctree_node_get_row_data( ctree, addrbook.treeSelected );
1850
        node = gtk_ctree_find_by_row_data( ctree, addrbook.treeSelected, obj );
1851
1852
        ds = addressbook_find_datasource( GTK_CTREE_NODE(addrbook.treeSelected) );
1853
        if( ds == NULL ) return;
1854
1855
        abf = addressbook_get_book_file();
1856
        if( abf == NULL ) return;
1857
        if( obj->type == ADDR_ITEM_EMAIL ) {
1858
                ItemEMail *email = ( ItemEMail * ) obj;
1859
                ItemPerson *person;
1860
                if( email == NULL ) return;
1861
                if( pobj && pobj->type == ADDR_ITEM_GROUP ) {
1862
                        /* Edit parent group */
1863
                        AdapterGroup *adapter = ADAPTER_GROUP(pobj);
1864
                        ItemGroup *itemGrp = adapter->itemGroup;
1865
                        if( addressbook_edit_group( abf, NULL, itemGrp ) == NULL ) return;
1866
                        name = ADDRITEM_NAME(itemGrp);
1867
                        node = addrbook.treeSelected;
1868
                        parentNode = GTK_CTREE_ROW(node)->parent;
1869
                }
1870
                else {
1871
                        /* Edit person - email page */
1872
                        person = ( ItemPerson * ) ADDRITEM_PARENT(email);
1873
                        if( addressbook_edit_person( abf, NULL, person, TRUE ) == NULL ) return;
1874
                        addrbook.treeSelected = NULL;
1875
                        gtk_ctree_select( ctree, addrbook.opened );
1876
                        invalidate_address_completion();
1877
                        return;
1878
                }
1879
        }
1880
        else if( obj->type == ADDR_ITEM_PERSON ) {
1881
                /* Edit person - basic page */
1882
                ItemPerson *person = ( ItemPerson * ) obj;
1883
                if( addressbook_edit_person( abf, NULL, person, FALSE ) == NULL ) return;
1884
                addrbook.treeSelected = NULL;
1885
                gtk_ctree_select( ctree, addrbook.opened );
1886
                invalidate_address_completion();
1887
                return;
1888
        }
1889
        else if( obj->type == ADDR_ITEM_GROUP ) {
1890
                ItemGroup *itemGrp = ( ItemGroup * ) obj;
1891
                if( addressbook_edit_group( abf, NULL, itemGrp ) == NULL ) return;
1892
                parentNode = addrbook.treeSelected;
1893
                node = addressbook_find_group_node( parentNode, itemGrp );
1894
                name = ADDRITEM_NAME(itemGrp);
1895
        }
1896
        else {
1897
                return;
1898
        }
1899
1900
        /* Update tree node with node name */
1901
        if( node == NULL ) return;
1902
        addressbook_change_node_name( node, name );
1903
        gtk_ctree_sort_node( ctree, parentNode );
1904
        addrbook.treeSelected = NULL;
1905
        gtk_ctree_select( ctree, addrbook.opened );
1906
}
1907
1908
static void addressbook_delete_address_cb(gpointer data, guint action,
1909
                                          GtkWidget *widget)
1910
{
1911
        addressbook_del_clicked(NULL, NULL);
1912
}
1913
1914
static void addressbook_copy_address_cb(gpointer data, guint action,
1915
                                        GtkWidget *widget)
1916
{
1917
        GtkCTree *clist = GTK_CTREE( addrbook.clist );
1918
        AddressObject *obj;
1919
        GList *node;
1920
1921
        if ( _addressListSelection_ == NULL ) return;
1922
1923
        g_list_free( _clipObjectList_ );
1924
        _clipObjectList_ = NULL;
1925
1926
        node = _addressListSelection_;
1927
        while( node ) {
1928
                obj = node->data;
1929
                if( obj->type == ADDR_ITEM_PERSON ) {
1930
                        _clipObjectList_ = g_list_append( _clipObjectList_, obj );
1931
                }
1932
                node = g_list_next( node );
1933
        }
1934
1935
        addressbook_menuitem_set_sensitive();
1936
}
1937
1938
static void addressbook_paste_address_cb(gpointer data, guint action,
1939
                                         GtkWidget *widget)
1940
{
1941
        GtkCTree *clist = GTK_CTREE( addrbook.clist );
1942
        GtkCTree *ctree = GTK_CTREE( addrbook.ctree );
1943
        AddressObject *obj = NULL, *pobj = NULL;
1944
        AddressDataSource *ds = NULL;
1945
        AddressBookFile *abf = NULL;
1946
        ItemFolder *folder = NULL;
1947
        ItemPerson *clipPerson, *person;
1948
        GList *cur;
1949
        GList *node;
1950
1951
        if (!_clipObjectList_) return;
1952
1953
        pobj = gtk_ctree_node_get_row_data( ctree, addrbook.treeSelected );
1954
        if( pobj->type == ADDR_ITEM_FOLDER )
1955
                folder = ADAPTER_FOLDER(pobj)->itemFolder;
1956
        else if( pobj->type == ADDR_DATASOURCE )
1957
                folder = NULL;
1958
        else
1959
                return;
1960
1961
        ds = addressbook_find_datasource( GTK_CTREE_NODE(addrbook.treeSelected) );
1962
        if( ds == NULL ) return;
1963
1964
        abf = ds->rawDataSource;
1965
        if( abf == NULL ) return;
1966
1967
        node = _clipObjectList_;
1968
        while( node ) {
1969
                obj = node->data;
1970
                node = g_list_next( node );
1971
                if( obj->type != ADDR_ITEM_PERSON ) continue;
1972
                clipPerson = (ItemPerson *)obj;
1973
1974
                person = addrbook_add_address_list(abf, folder, NULL);
1975
                ADDRITEM_NAME(person) = g_strdup(ADDRITEM_NAME(clipPerson));
1976
                person->firstName = g_strdup(clipPerson->firstName);
1977
                person->lastName = g_strdup(clipPerson->lastName);
1978
                person->nickName = g_strdup(clipPerson->nickName);
1979
                for (cur = clipPerson->listEMail; cur != NULL; cur = cur->next) {
1980
                        ItemEMail *email = cur->data;
1981
                        addritem_person_add_email(person, addritem_copy_item_email(email));
1982
                }
1983
                for (cur = clipPerson->listAttrib; cur != NULL; cur = cur->next) {
1984
                        UserAttribute *attr = cur->data;
1985
                        addritem_person_add_attribute(person, addritem_copy_attribute(attr));
1986
                }
1987
        }
1988
1989
        if (addrbook.treeSelected == addrbook.opened) {
1990
                addrbook.treeSelected = NULL;
1991
                gtk_ctree_select( GTK_CTREE(addrbook.ctree), addrbook.opened );
1992
        }
1993
}
1994
1995
static void close_cb(gpointer data, guint action, GtkWidget *widget)
1996
{
1997
        addressbook_close();
1998
}
1999
2000
static void addressbook_file_save_cb( gpointer data, guint action, GtkWidget *widget ) {
2001
        addressbook_export_to_file();
2002
}
2003
2004
static void addressbook_person_expand_node( GtkCTree *ctree, GList *node, gpointer *data ) {
2005
        if( node ) {
2006
                ItemPerson *person = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
2007
                if( person ) addritem_person_set_opened( person, TRUE );
2008
        }
2009
}
2010
2011
static void addressbook_person_collapse_node( GtkCTree *ctree, GList *node, gpointer *data ) {
2012
        if( node ) {
2013
                ItemPerson *person = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
2014
                if( person ) addritem_person_set_opened( person, FALSE );
2015
        }
2016
}
2017
2018
static gchar *addressbook_format_item_clist( ItemPerson *person, ItemEMail *email ) {
2019
        gchar *str = NULL;
2020
        gchar *eMailAlias = ADDRITEM_NAME(email);
2021
        if( eMailAlias && *eMailAlias != '\0' ) {
2022
                if( person ) {
2023
                        str = g_strdup_printf( "%s - %s", ADDRITEM_NAME(person), eMailAlias );
2024
                }
2025
                else {
2026
                        str = g_strdup( eMailAlias );
2027
                }
2028
        }
2029
        return str;
2030
}
2031
2032
static void addressbook_load_group( GtkCTree *clist, ItemGroup *itemGroup ) {
2033
        GList *items = itemGroup->listEMail;
2034
        AddressTypeControlItem *atci = addrbookctl_lookup( ADDR_ITEM_EMAIL );
2035
        for( ; items != NULL; items = g_list_next( items ) ) {
2036
                GtkCTreeNode *nodeEMail = NULL;
2037
                gchar *text[N_COLS];
2038
                ItemEMail *email = items->data;
2039
                ItemPerson *person;
2040
                gchar *str = NULL;
2041
2042
                if( ! email ) continue;
2043
2044
                person = ( ItemPerson * ) ADDRITEM_PARENT(email);
2045
                str = addressbook_format_item_clist( person, email );
2046
                if( str ) {
2047
                        text[COL_NAME] = str;
2048
                }
2049
                else {
2050
                        text[COL_NAME] = ADDRITEM_NAME(person);
2051
                }
2052
                text[COL_ADDRESS] = email->address;
2053
                text[COL_REMARKS] = email->remarks;
2054
                nodeEMail = gtk_ctree_insert_node(
2055
                                clist, NULL, NULL,
2056
                                text, FOLDER_SPACING,
2057
                                atci->iconXpm, atci->maskXpm,
2058
                                atci->iconXpmOpen, atci->maskXpmOpen,
2059
                                FALSE, FALSE );
2060
                gtk_ctree_node_set_row_data( clist, nodeEMail, email );
2061
                g_free( str );
2062
                str = NULL;
2063
        }
2064
}
2065
2066
static void addressbook_folder_load_person( GtkCTree *clist, ItemFolder *itemFolder ) {
2067
        GList *items;
2068
        AddressTypeControlItem *atci = addrbookctl_lookup( ADDR_ITEM_PERSON );
2069
        AddressTypeControlItem *atciMail = addrbookctl_lookup( ADDR_ITEM_EMAIL );
2070
2071
        if( atci == NULL ) return;
2072
        if( atciMail == NULL ) return;
2073
2074
        /* Load email addresses */
2075
        items = addritem_folder_get_person_list( itemFolder );
2076
        for( ; items != NULL; items = g_list_next( items ) ) {
2077
                GtkCTreeNode *nodePerson = NULL;
2078
                GtkCTreeNode *nodeEMail = NULL;
2079
                gchar *text[N_COLS];
2080
                gboolean flgFirst = TRUE, haveAddr = FALSE;
2081
                /* gint row; */
2082
                ItemPerson *person;
2083
                GList *node;
2084
2085
                person = ( ItemPerson * ) items->data;
2086
                if( person == NULL ) continue;
2087
2088
                text[COL_NAME] = NULL;
2089
                node = person->listEMail;
2090
                while( node ) {
2091
                        ItemEMail *email = node->data;
2092
                        gchar *eMailAddr = NULL;
2093
                        node = g_list_next( node );
2094
2095
                        text[COL_ADDRESS] = email->address;
2096
                        text[COL_REMARKS] = email->remarks;
2097
                        eMailAddr = ADDRITEM_NAME(email);
2098
                        if( eMailAddr && *eMailAddr == '\0' ) eMailAddr = NULL;
2099
                        if( flgFirst ) {
2100
                                /* First email belongs with person */
2101
                                gchar *str = addressbook_format_item_clist( person, email );
2102
                                if( str ) {
2103
                                        text[COL_NAME] = str;
2104
                                }
2105
                                else {
2106
                                        text[COL_NAME] = ADDRITEM_NAME(person);
2107
                                }
2108
                                nodePerson = gtk_ctree_insert_node(
2109
                                                clist, NULL, NULL,
2110
                                                text, FOLDER_SPACING,
2111
                                                atci->iconXpm, atci->maskXpm,
2112
                                                atci->iconXpmOpen, atci->maskXpmOpen,
2113
                                                FALSE, person->isOpened );
2114
                                g_free( str );
2115
                                str = NULL;
2116
                                gtk_ctree_node_set_row_data(clist, nodePerson, person );
2117
                        }
2118
                        else {
2119
                                /* Subsequent email is a child node of person */
2120
                                text[COL_NAME] = ADDRITEM_NAME(email);
2121
                                nodeEMail = gtk_ctree_insert_node(
2122
                                                clist, nodePerson, NULL,
2123
                                                text, FOLDER_SPACING,
2124
                                                atciMail->iconXpm, atciMail->maskXpm,
2125
                                                atciMail->iconXpmOpen, atciMail->maskXpmOpen,
2126
                                                FALSE, TRUE );
2127
                                gtk_ctree_node_set_row_data(clist, nodeEMail, email );
2128
                        }
2129
                        flgFirst = FALSE;
2130
                        haveAddr = TRUE;
2131
                }
2132
                if( ! haveAddr ) {
2133
                        /* Have name without EMail */
2134
                        text[COL_NAME] = ADDRITEM_NAME(person);
2135
                        text[COL_ADDRESS] = NULL;
2136
                        text[COL_REMARKS] = NULL;
2137
                        nodePerson = gtk_ctree_insert_node(
2138
                                        clist, NULL, NULL,
2139
                                        text, FOLDER_SPACING,
2140
                                        atci->iconXpm, atci->maskXpm,
2141
                                        atci->iconXpmOpen, atci->maskXpmOpen,
2142
                                        FALSE, person->isOpened );
2143
                        gtk_ctree_node_set_row_data(clist, nodePerson, person );
2144
                }
2145
        }
2146
        gtk_ctree_sort_node(GTK_CTREE(clist), NULL);
2147
2148
        /* Free up the list */
2149
        mgu_clear_list( items );
2150
        g_list_free( items );
2151
}
2152
2153
static void addressbook_folder_load_group( GtkCTree *clist, ItemFolder *itemFolder ) {
2154
        GList *items;
2155
        AddressTypeControlItem *atci =  addrbookctl_lookup( ADDR_ITEM_GROUP );
2156
2157
        /* Load any groups */
2158
        if( ! atci ) return;
2159
        items = addritem_folder_get_group_list( itemFolder );
2160
        for( ; items != NULL; items = g_list_next( items ) ) {
2161
                GtkCTreeNode *nodeGroup = NULL;
2162
                gchar *text[N_COLS];
2163
                ItemGroup *group = items->data;
2164
                if( group == NULL ) continue;
2165
                text[COL_NAME] = ADDRITEM_NAME(group);
2166
                text[COL_ADDRESS] = NULL;
2167
                text[COL_REMARKS] = NULL;
2168
                nodeGroup = gtk_ctree_insert_node(clist, NULL, NULL,
2169
                                      text, FOLDER_SPACING,
2170
                                      atci->iconXpm, atci->maskXpm,
2171
                                      atci->iconXpmOpen, atci->maskXpmOpen,
2172
                                      FALSE, FALSE);
2173
                gtk_ctree_node_set_row_data(clist, nodeGroup, group );
2174
        }
2175
        gtk_ctree_sort_node(clist, NULL);
2176
2177
        /* Free up the list */
2178
        mgu_clear_list( items );
2179
        g_list_free( items );
2180
}
2181
2182
#if 0
2183
/*
2184
 * Load data sources into list.
2185
 */
2186
static void addressbook_node_load_datasource( GtkCTree *clist, AddressObject *obj ) {
2187
        AdapterInterface *adapter;
2188
        AddressInterface *iface;
2189
        AddressTypeControlItem *atci = NULL;
2190
        /* AddressDataSource *ds; */
2191
        GtkCTreeNode *newNode, *node;
2192
        GtkCTreeRow *row;
2193
        GtkCell *cell = NULL;
2194
        gchar *text[N_COLS];
2195
2196
        adapter = ADAPTER_INTERFACE(obj);
2197
        if( adapter == NULL ) return;
2198
        iface = adapter->interface;
2199
        atci = adapter->atci;
2200
        if( atci == NULL ) return;
2201
2202
        /* Create nodes in list copying values for data sources in tree */
2203
        row = GTK_CTREE_ROW( adapter->treeNode );
2204
        if( row ) {
2205
                node = row->children;
2206
                while( node ) {
2207
                        gpointer data = gtk_ctree_node_get_row_data( clist, node );
2208
                        row = GTK_CTREE_ROW( node );
2209
                        cell = ( ( GtkCListRow * )row )->cell;
2210
                        text[COL_NAME] = cell->u.text;
2211
                        text[COL_ADDRESS] = NULL;
2212
                        text[COL_REMARKS] = NULL;
2213
                        newNode = gtk_ctree_insert_node( clist, NULL, NULL,
2214
                                      text, FOLDER_SPACING,
2215
                                      atci->iconXpm, atci->maskXpm,
2216
                                      atci->iconXpmOpen, atci->maskXpmOpen,
2217
                                      FALSE, FALSE);
2218
                        gtk_ctree_node_set_row_data( clist, newNode, data );
2219
                        node = row->sibling;
2220
2221
                }
2222
        }
2223
        gtk_ctree_sort_node( clist, NULL );
2224
}
2225
#endif
2226
2227
static AddressDataSource *addressbook_find_datasource( GtkCTreeNode *node ) {
2228
        AddressDataSource *ds = NULL;
2229
        AddressObject *ao;
2230
2231
        g_return_val_if_fail(addrbook.ctree != NULL, NULL);
2232
2233
        while( node ) {
2234
                if( GTK_CTREE_ROW(node)->level < 2 ) return NULL;
2235
                ao = gtk_ctree_node_get_row_data( GTK_CTREE(addrbook.ctree), node );
2236
                if( ao ) {
2237
/*                        printf( "ao->type = %d\n", ao->type ); */
2238
                        if( ao->type == ADDR_DATASOURCE ) {
2239
                                AdapterDSource *ads = ADAPTER_DSOURCE(ao);
2240
/*                                printf( "found it\n" ); */
2241
                                ds = ads->dataSource;
2242
                                break;
2243
                        }
2244
                }
2245
                node = GTK_CTREE_ROW(node)->parent;
2246
        }
2247
        return ds;
2248
}
2249
2250
/*
2251
* Load address list widget with children of specified object.
2252
* Enter: obj        Parent object to be loaded.
2253
*/
2254
static void addressbook_set_clist( AddressObject *obj ) {
2255
        GtkCTree *ctreelist = GTK_CTREE(addrbook.clist);
2256
        GtkCList *clist = GTK_CLIST(addrbook.clist);
2257
        AddressDataSource *ds = NULL;
2258
        AdapterDSource *ads = NULL;
2259
2260
        if( obj == NULL ) {
2261
                gtk_clist_clear(clist);
2262
                return;
2263
        }
2264
2265
        if( obj->type == ADDR_INTERFACE ) {
2266
                /* printf( "set_clist: loading datasource...\n" ); */
2267
                /* addressbook_node_load_datasource( clist, obj ); */
2268
                return;
2269
        }
2270
2271
        gtk_clist_freeze(clist);
2272
        gtk_clist_clear(clist);
2273
2274
        if( obj->type == ADDR_DATASOURCE ) {
2275
                ads = ADAPTER_DSOURCE(obj);
2276
                ds = ADAPTER_DSOURCE(obj)->dataSource;
2277
                if( ds ) {
2278
                        /* Load root folder */
2279
                        ItemFolder *rootFolder = NULL;
2280
                        rootFolder = addrindex_ds_get_root_folder( ds );
2281
                        addressbook_folder_load_person( ctreelist, addrindex_ds_get_root_folder( ds ) );
2282
                        addressbook_folder_load_group( ctreelist, addrindex_ds_get_root_folder( ds ) );
2283
                }
2284
        }
2285
        else {
2286
                if( obj->type == ADDR_ITEM_GROUP ) {
2287
                        /* Load groups */
2288
                        ItemGroup *itemGroup = ADAPTER_GROUP(obj)->itemGroup;
2289
                        addressbook_load_group( ctreelist, itemGroup );
2290
                }
2291
                else if( obj->type == ADDR_ITEM_FOLDER ) {
2292
                        /* Load folders */
2293
                        ItemFolder *itemFolder = ADAPTER_FOLDER(obj)->itemFolder;
2294
                        addressbook_folder_load_person( ctreelist, itemFolder );
2295
                        addressbook_folder_load_group( ctreelist, itemFolder );
2296
                }
2297
        }
2298
2299
        gtk_clist_sort(clist);
2300
        gtk_clist_thaw(clist);
2301
}
2302
2303
/*
2304
* Free adaptor for specified node.
2305
*/
2306
static void addressbook_free_adapter( GtkCTreeNode *node ) {
2307
        AddressObject *ao;
2308
2309
        g_return_if_fail(addrbook.ctree != NULL);
2310
2311
        if( node ) {
2312
                if( GTK_CTREE_ROW(node)->level < 2 ) return;
2313
                ao = gtk_ctree_node_get_row_data( GTK_CTREE(addrbook.ctree), node );
2314
                if( ao == NULL ) return;
2315
                if( ao->type == ADDR_INTERFACE ) {
2316
                        AdapterInterface *ai = ADAPTER_INTERFACE(ao);
2317
                        addrbookctl_free_interface( ai );
2318
                }
2319
                else if( ao->type == ADDR_DATASOURCE ) {
2320
                        AdapterDSource *ads = ADAPTER_DSOURCE(ao);
2321
                        addrbookctl_free_datasource( ads );
2322
                }
2323
                else if( ao->type == ADDR_ITEM_FOLDER ) {
2324
                        AdapterFolder *af = ADAPTER_FOLDER(ao);
2325
                        addrbookctl_free_folder( af );
2326
                }
2327
                else if( ao->type == ADDR_ITEM_GROUP ) {
2328
                        AdapterGroup *ag = ADAPTER_GROUP(ao);
2329
                        addrbookctl_free_group( ag );
2330
                }
2331
                gtk_ctree_node_set_row_data( GTK_CTREE(addrbook.ctree), node, NULL );
2332
        }
2333
}
2334
2335
/*
2336
* Free all children adapters.
2337
*/
2338
static void addressbook_free_child_adapters( GtkCTreeNode *node ) {
2339
        GtkCTreeNode *parent, *child;
2340
        GtkCTreeRow *currRow;
2341
2342
        if( node == NULL ) return;
2343
        currRow = GTK_CTREE_ROW( node );
2344
        if( currRow ) {
2345
                parent = currRow->parent;
2346
                child = currRow->children;
2347
                while( child ) {
2348
                        addressbook_free_child_adapters( child );
2349
                        addressbook_free_adapter( child );
2350
                        currRow = GTK_CTREE_ROW( child );
2351
                        child = currRow->sibling;
2352
                }
2353
        }
2354
}
2355
2356
AdapterDSource *addressbook_create_ds_adapter( AddressDataSource *ds,
2357
                                AddressObjectType otype, gchar *name )
2358
{
2359
        AdapterDSource *adapter = g_new0( AdapterDSource, 1 );
2360
        ADDRESS_OBJECT(adapter)->type = ADDR_DATASOURCE;
2361
        ADDRESS_OBJECT_NAME(adapter) = g_strdup( name );
2362
        adapter->dataSource = ds;
2363
        adapter->subType = otype;
2364
        return adapter;
2365
}
2366
2367
void addressbook_ads_set_name( AdapterDSource *adapter, gchar *value ) {
2368
        ADDRESS_OBJECT_NAME(adapter) = mgu_replace_string( ADDRESS_OBJECT_NAME(adapter), value );
2369
}
2370
2371
/*
2372
 * Load tree from address index with the initial data.
2373
 */
2374
static void addressbook_load_tree( void ) {
2375
        GtkCTree *ctree = GTK_CTREE( addrbook.ctree );
2376
        GList *nodeIf, *nodeDS;
2377
        AdapterInterface *adapter;
2378
        AddressInterface *iface;
2379
        AddressTypeControlItem *atci;
2380
        AddressDataSource *ds;
2381
        AdapterDSource *ads;
2382
        GtkCTreeNode *node, *newNode;
2383
        gchar *name;
2384
2385
        nodeIf = _addressInterfaceList_;
2386
        while( nodeIf ) {
2387
                adapter = nodeIf->data;
2388
                node = adapter->treeNode;
2389
                iface = adapter->interface;
2390
                atci = adapter->atci;
2391
                if( iface ) {
2392
                        if( iface->useInterface ) {
2393
                                /* Load data sources below interface node */
2394
                                nodeDS = iface->listSource;
2395
                                while( nodeDS ) {
2396
                                        ds = nodeDS->data;
2397
                                        newNode = NULL;
2398
                                        name = addrindex_ds_get_name( ds );
2399
                                        ads = addressbook_create_ds_adapter( ds, atci->objectType, name );
2400
                                        newNode = addressbook_add_object( node, ADDRESS_OBJECT(ads) );
2401
                                        nodeDS = g_list_next( nodeDS );
2402
                                }
2403
                                gtk_ctree_expand( ctree, node );
2404
                        }
2405
                }
2406
                nodeIf = g_list_next( nodeIf );
2407
        }
2408
}
2409
2410
/*
2411
 * Convert the old address book to new format.
2412
 */
2413
static gboolean addressbook_convert( AddressIndex *addrIndex ) {
2414
        gboolean retVal = FALSE;
2415
        gboolean errFlag = TRUE;
2416
        gchar *msg = NULL;
2417
2418
        /* Read old address book, performing conversion */
2419
        debug_print( "Reading and converting old address book...\n" );
2420
        addrindex_set_file_name( addrIndex, ADDRESSBOOK_OLD_FILE );
2421
        addrindex_read_data( addrIndex );
2422
        if( addrIndex->retVal == MGU_NO_FILE ) {
2423
                /* We do not have a file - new user */
2424
                debug_print( "New user... create new books...\n" );
2425
                addrindex_create_new_books( addrIndex );
2426
                if( addrIndex->retVal == MGU_SUCCESS ) {
2427
                        /* Save index file */
2428
                        addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2429
                        addrindex_save_data( addrIndex );
2430
                        if( addrIndex->retVal == MGU_SUCCESS ) {
2431
                                retVal = TRUE;
2432
                                errFlag = FALSE;
2433
                        }
2434
                        else {
2435
                                msg = _( "New user, could not save index file." );
2436
                        }
2437
                }
2438
                else {
2439
                        msg = _( "New user, could not save address book files." );
2440
                }
2441
        }
2442
        else {
2443
                /* We have an old file */
2444
                if( addrIndex->wasConverted ) {
2445
                        /* Converted successfully - save address index */
2446
                        addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2447
                        addrindex_save_data( addrIndex );
2448
                        if( addrIndex->retVal == MGU_SUCCESS ) {
2449
                                msg = _( "Old address book converted successfully." );
2450
                                retVal = TRUE;
2451
                                errFlag = FALSE;
2452
                        }
2453
                        else {
2454
                                msg = _("Old address book converted,\n"
2455
                                        "could not save new address index file" );
2456
                        }
2457
                }
2458
                else {
2459
                        /* File conversion failed - just create new books */
2460
                        debug_print( "File conversion failed... just create new books...\n" );
2461
                        addrindex_create_new_books( addrIndex );
2462
                        if( addrIndex->retVal == MGU_SUCCESS ) {
2463
                                /* Save index */
2464
                                addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2465
                                addrindex_save_data( addrIndex );
2466
                                if( addrIndex->retVal == MGU_SUCCESS ) {
2467
                                        msg = _("Could not convert address book,\n"
2468
                                                "but created empty new address book files." );
2469
                                        retVal = TRUE;
2470
                                        errFlag = FALSE;
2471
                                }
2472
                                else {
2473
                                        msg = _("Could not convert address book,\n"
2474
                                                "could not create new address book files." );
2475
                                }
2476
                        }
2477
                        else {
2478
                                msg = _("Could not convert address book\n"
2479
                                        "and could not create new address book files." );
2480
                        }
2481
                }
2482
        }
2483
        if( errFlag ) {
2484
                debug_print( "Error\n%s\n", msg );
2485
                alertpanel( _( "Addressbook conversion error" ), msg, GTK_STOCK_CLOSE, NULL, NULL );
2486
        }
2487
        else if( msg ) {
2488
                debug_print( "Warning\n%s\n", msg );
2489
                alertpanel( _( "Addressbook conversion" ), msg, GTK_STOCK_CLOSE, NULL, NULL );
2490
        }
2491
2492
        return retVal;
2493
}
2494
2495
void addressbook_read_file( void ) {
2496
        AddressIndex *addrIndex = NULL;
2497
2498
        debug_print( "Reading address index...\n" );
2499
        if( _addressIndex_ ) {
2500
                debug_print( "address book already read!!!\n" );
2501
                return;
2502
        }
2503
2504
        addrIndex = addrindex_create_index();
2505
2506
        /* Use new address book index. */
2507
        addrindex_set_file_path( addrIndex, get_rc_dir() );
2508
        addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2509
        addrindex_read_data( addrIndex );
2510
        if( addrIndex->retVal == MGU_NO_FILE ) {
2511
                /* Conversion required */
2512
                debug_print( "Converting...\n" );
2513
                if( addressbook_convert( addrIndex ) ) {
2514
                        _addressIndex_ = addrIndex;
2515
                }
2516
        }
2517
        else if( addrIndex->retVal == MGU_SUCCESS ) {
2518
                _addressIndex_ = addrIndex;
2519
        }
2520
        else {
2521
                /* Error reading address book */
2522
                debug_print( "Could not read address index.\n" );
2523
                addrindex_print_index( addrIndex, stdout );
2524
                alertpanel( _( "Addressbook Error" ),
2525
                            _( "Could not read address index" ),
2526
                            GTK_STOCK_CLOSE, NULL, NULL );
2527
        }
2528
        debug_print( "done.\n" );
2529
}
2530
2531
#if 0
2532
void addressbook_read_file_old( void ) {
2533
        AddressIndex *addrIndex = NULL;
2534
        gboolean errFlag = TRUE;
2535
        gchar *msg = NULL;
2536
2537
        if( _addressIndex_ ) {
2538
                debug_print( "address book already read!!!\n" );
2539
                return;
2540
        }
2541
2542
        addrIndex = addrindex_create_index();
2543
2544
        /* Use use new address book. */
2545
        /* addrindex_set_file_path( addrIndex, "/home/match/tmp/empty-dir" ); */
2546
        addrindex_set_file_path( addrIndex, get_rc_dir() );
2547
        addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2548
2549
        debug_print( "Reading address index...\n" );
2550
        addrindex_read_data( addrIndex );
2551
        if( addrIndex->retVal == MGU_NO_FILE ) {
2552
                /* Read old address book, performing conversion */
2553
                debug_print( "Reading and converting old address book...\n" );
2554
                addrindex_set_file_name( addrIndex, ADDRESSBOOK_OLD_FILE );
2555
                addrindex_read_data( addrIndex );
2556
                if( addrIndex->retVal == MGU_NO_FILE ) {
2557
                        /* We do not have a file - new user */
2558
                        debug_print( "New user... create new books...\n" );
2559
                        addrindex_create_new_books( addrIndex );
2560
                        if( addrIndex->retVal == MGU_SUCCESS ) {
2561
                                /* Save index file */
2562
                                addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2563
                                addrindex_save_data( addrIndex );
2564
                                if( addrIndex->retVal == MGU_SUCCESS ) {
2565
                                        errFlag = FALSE;
2566
                                }
2567
                                else {
2568
                                        msg = g_strdup( _( "New user, could not save index file." ) );
2569
                                }
2570
                        }
2571
                        else {
2572
                                msg = g_strdup( _( "New user, could not save address book files." ) );
2573
                        }
2574
                }
2575
                else {
2576
                        /* We have an old file */
2577
                        if( addrIndex->wasConverted ) {
2578
                                /* Converted successfully - save address index */
2579
                                addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2580
                                addrindex_save_data( addrIndex );
2581
                                if( addrIndex->retVal == MGU_SUCCESS ) {
2582
                                        msg = g_strdup( _( "Old address book converted successfully." ) );
2583
                                        errFlag = FALSE;
2584
                                }
2585
                                else {
2586
                                        msg = g_strdup( _(
2587
                                                "Old address book converted, " \
2588
                                                "could not save new address index file" ) );
2589
                                }
2590
                        }
2591
                        else {
2592
                                /* File conversion failed - just create new books */
2593
                                debug_print( "File conversion failed... just create new books...\n" );
2594
                                addrindex_create_new_books( addrIndex );
2595
                                if( addrIndex->retVal == MGU_SUCCESS ) {
2596
                                        /* Save index */
2597
                                        addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2598
                                        addrindex_save_data( addrIndex );
2599
                                        if( addrIndex->retVal == MGU_SUCCESS ) {
2600
                                                msg = g_strdup( _(
2601
                                                        "Could not convert address book, " \
2602
                                                        "but created empty new address book files." ) );
2603
                                                errFlag = FALSE;
2604
                                        }
2605
                                        else {
2606
                                                msg = g_strdup( _(
2607
                                                        "Could not convert address book, " \
2608
                                                        "could not create new address book files." ) );
2609
                                        }
2610
                                }
2611
                                else {
2612
                                        msg = g_strdup( _(
2613
                                                "Could not convert address book " \
2614
                                                "and could not create new address book files." ) );
2615
                                }
2616
                        }
2617
                }
2618
        }
2619
        else if( addrIndex->retVal == MGU_SUCCESS ) {
2620
                errFlag = FALSE;
2621
        }
2622
        else {
2623
                debug_print( "Could not read address index.\n" );
2624
                addrindex_print_index( addrIndex, stdout );
2625
                msg = g_strdup( _( "Could not read address index" ) );
2626
        }
2627
        _addressIndex_ = addrIndex;
2628
2629
        if( errFlag ) {
2630
                debug_print( "Error\n%s\n", msg );
2631
                alertpanel( _( "Addressbook Conversion Error" ), msg,
2632
                            GTK_STOCK_CLOSE, NULL, NULL );
2633
        }
2634
        else {
2635
                if( msg ) {
2636
                        debug_print( "Warning\n%s\n", msg );
2637
                        alertpanel( _( "Addressbook Conversion" ), msg,
2638
                                    GTK_STOCK_CLOSE, NULL, NULL );
2639
                }
2640
        }
2641
        if( msg ) g_free( msg );
2642
        debug_print( "done.\n" );
2643
}
2644
#endif
2645
2646
/*
2647
* Add object into the address index tree widget.
2648
* Enter: node        Parent node.
2649
*        obj        Object to add.
2650
* Return: Node that was added, or NULL if object not added.
2651
*/
2652
static GtkCTreeNode *addressbook_add_object(GtkCTreeNode *node,
2653
                                            AddressObject *obj)
2654
{
2655
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
2656
        GtkCTreeNode *added;
2657
        AddressObject *pobj;
2658
        AddressObjectType otype;
2659
        AddressTypeControlItem *atci = NULL;
2660
2661
        g_return_val_if_fail(node != NULL, NULL);
2662
        g_return_val_if_fail(obj  != NULL, NULL);
2663
2664
        pobj = gtk_ctree_node_get_row_data(ctree, node);
2665
        g_return_val_if_fail(pobj != NULL, NULL);
2666
2667
        /* Determine object type to be displayed */
2668
        if( obj->type == ADDR_DATASOURCE ) {
2669
                otype = ADAPTER_DSOURCE(obj)->subType;
2670
        }
2671
        else {
2672
                otype = obj->type;
2673
        }
2674
2675
        /* Handle any special conditions. */
2676
        added = node;
2677
        atci = addrbookctl_lookup( otype );
2678
        if( atci ) {
2679
                if( atci->showInTree ) {
2680
                        /* Add object to tree */
2681
                        gchar **name;
2682
                        name = &obj->name;
2683
                        added = gtk_ctree_insert_node( ctree, node, NULL, name, FOLDER_SPACING,
2684
                                atci->iconXpm, atci->maskXpm, atci->iconXpmOpen, atci->maskXpmOpen,
2685
                                atci->treeLeaf, atci->treeExpand );
2686
                        gtk_ctree_node_set_row_data(ctree, added, obj);
2687
                }
2688
        }
2689
2690
        gtk_ctree_sort_node(ctree, node);
2691
2692
        return added;
2693
}
2694
2695
/*
2696
* Add group into the address index tree.
2697
* Enter: node           Parent node.
2698
*        ds        Data source.
2699
*        itemGroup Group to add.
2700
* Return: Inserted node.
2701
*/
2702
static GtkCTreeNode *addressbook_node_add_group( GtkCTreeNode *node, AddressDataSource *ds, ItemGroup *itemGroup ) {
2703
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
2704
        GtkCTreeNode *newNode;
2705
        AdapterGroup *adapter;
2706
        AddressTypeControlItem *atci = NULL;
2707
        gchar **name;
2708
2709
        if( ds == NULL ) return NULL;
2710
        if( node == NULL || itemGroup == NULL ) return NULL;
2711
2712
        name = &itemGroup->obj.name;
2713
2714
        atci = addrbookctl_lookup( ADDR_ITEM_GROUP );
2715
2716
        adapter = g_new0( AdapterGroup, 1 );
2717
        ADDRESS_OBJECT_TYPE(adapter) = ADDR_ITEM_GROUP;
2718
        ADDRESS_OBJECT_NAME(adapter) = g_strdup( ADDRITEM_NAME(itemGroup) );
2719
        adapter->itemGroup = itemGroup;
2720
2721
        newNode = gtk_ctree_insert_node( ctree, node, NULL, name, FOLDER_SPACING,
2722
                        atci->iconXpm, atci->maskXpm, atci->iconXpm, atci->maskXpm,
2723
                        atci->treeLeaf, atci->treeExpand );
2724
        gtk_ctree_node_set_row_data( ctree, newNode, adapter );
2725
        gtk_ctree_sort_node( ctree, node );
2726
        return newNode;
2727
}
2728
2729
/*
2730
* Add folder into the address index tree.
2731
* Enter: node            Parent node.
2732
*        ds         Data source.
2733
*        itemFolder Folder to add.
2734
*        otype      Object type to display.
2735
* Return: Inserted node.
2736
*/
2737
static GtkCTreeNode *addressbook_node_add_folder(
2738
                GtkCTreeNode *node, AddressDataSource *ds, ItemFolder *itemFolder, AddressObjectType otype )
2739
{
2740
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
2741
        GtkCTreeNode *newNode = NULL;
2742
        AdapterFolder *adapter;
2743
        AddressTypeControlItem *atci = NULL;
2744
        GList *listItems = NULL;
2745
        gchar **name;
2746
        ItemFolder *rootFolder;
2747
2748
        if( ds == NULL ) return NULL;
2749
        if( node == NULL || itemFolder == NULL ) return NULL;
2750
2751
        /* Determine object type */
2752
        atci = addrbookctl_lookup( otype );
2753
        if( atci == NULL ) return NULL;
2754
2755
        rootFolder = addrindex_ds_get_root_folder( ds );
2756
        if( itemFolder == rootFolder ) {
2757
                newNode = node;
2758
        }
2759
        else {
2760
                name = &itemFolder->obj.name;
2761
2762
                adapter = g_new0( AdapterFolder, 1 );
2763
                ADDRESS_OBJECT_TYPE(adapter) = ADDR_ITEM_FOLDER;
2764
                ADDRESS_OBJECT_NAME(adapter) = g_strdup( ADDRITEM_NAME(itemFolder) );
2765
                adapter->itemFolder = itemFolder;
2766
2767
                newNode = gtk_ctree_insert_node( ctree, node, NULL, name, FOLDER_SPACING,
2768
                                atci->iconXpm, atci->maskXpm, atci->iconXpm, atci->maskXpm,
2769
                                atci->treeLeaf, atci->treeExpand );
2770
                gtk_ctree_node_set_row_data( ctree, newNode, adapter );
2771
        }
2772
2773
        listItems = itemFolder->listFolder;
2774
        while( listItems ) {
2775
                ItemFolder *item = listItems->data;
2776
                addressbook_node_add_folder( newNode, ds, item, otype );
2777
                listItems = g_list_next( listItems );
2778
        }
2779
        listItems = itemFolder->listGroup;
2780
        while( listItems ) {
2781
                ItemGroup *item = listItems->data;
2782
                addressbook_node_add_group( newNode, ds, item );
2783
                listItems = g_list_next( listItems );
2784
        }
2785
        gtk_ctree_sort_node( ctree, node );
2786
        return newNode;
2787
}
2788
2789
#if 0
2790
static void addressbook_delete_object(AddressObject *obj) {
2791
        AdapterDSource *ads = NULL;
2792
        AddressDataSource *ds = NULL;
2793
        if (!obj) return;
2794
2795
        /* Remove data source. */
2796
        /* printf( "Delete obj type : %d\n", obj->type ); */
2797
2798
        ads = ADAPTER_DSOURCE(obj);
2799
        if( ads == NULL ) return;
2800
        ds = ads->dataSource;
2801
        if( ds == NULL ) return;
2802
2803
        /* Remove data source */
2804
        if( addrindex_index_remove_datasource( _addressIndex_, ds ) ) {
2805
                addrindex_free_datasource( _addressIndex_, ds );
2806
        }
2807
        /* Free up Adapter object */
2808
        g_free( ADAPTER_DSOURCE(obj) );
2809
}
2810
#endif
2811
2812
void addressbook_export_to_file( void ) {
2813
        if( _addressIndex_ ) {
2814
                /* Save all new address book data */
2815
                debug_print( "Saving address books...\n" );
2816
                addrindex_save_all_books( _addressIndex_ );
2817
2818
                debug_print( "Exporting addressbook to file...\n" );
2819
                addrindex_save_data( _addressIndex_ );
2820
                if( _addressIndex_->retVal != MGU_SUCCESS ) {
2821
                        addrindex_print_index( _addressIndex_, stdout );
2822
                }
2823
2824
                /* Notify address completion of new data */
2825
                invalidate_address_completion();
2826
        }
2827
}
2828
2829
static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event,
2830
                            gpointer data)
2831
{
2832
        if (event && event->keyval == GDK_Escape)
2833
                addressbook_close();
2834
        return FALSE;
2835
}
2836
2837
static void size_allocated(GtkWidget *widget, GtkAllocation *allocation,
2838
                           gpointer data)
2839
{
2840
        if (allocation->width <= 1 || allocation->height <= 1)
2841
                return;
2842
2843
        prefs_common.addressbook_width = allocation->width;
2844
        prefs_common.addressbook_height = allocation->height;
2845
}
2846
2847
/*
2848
* Comparsion using names of AddressItem objects.
2849
*/
2850
/*
2851
static gint addressbook_list_compare_func(GtkCList *clist,
2852
                                          gconstpointer ptr1,
2853
                                          gconstpointer ptr2)
2854
{
2855
        AddressObject *obj1 = ((GtkCListRow *)ptr1)->data;
2856
        AddressObject *obj2 = ((GtkCListRow *)ptr2)->data;
2857
        gchar *name1 = NULL, *name2 = NULL;
2858
        if( obj1 ) name1 = obj1->name;
2859
        if( obj2 ) name2 = obj2->name;
2860
        if( ! name1 ) return ( name2 != NULL );
2861
        if( ! name2 ) return -1;
2862
        return g_ascii_strcasecmp(name1, name2);
2863
}
2864
*/
2865
2866
/*
2867
* Comparison using cell contents (text in first column).
2868
*/
2869
static gint addressbook_list_compare_func( GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2 ) {
2870
        GtkCell *cell1 = ((GtkCListRow *)ptr1)->cell;
2871
        GtkCell *cell2 = ((GtkCListRow *)ptr2)->cell;
2872
        gchar *name1 = NULL, *name2 = NULL;
2873
        if( cell1 ) name1 = cell1->u.text;
2874
        if( cell2 ) name2 = cell2->u.text;
2875
        if( ! name1 ) return ( name2 != NULL );
2876
        if( ! name2 ) return -1;
2877
        return g_ascii_strcasecmp( name1, name2 );
2878
}
2879
2880
/* static */ 
2881
gint addressbook_obj_name_compare(gconstpointer a, gconstpointer b)
2882
{
2883
        const AddressObject *obj = a;
2884
        const gchar *name = b;
2885
        AddressTypeControlItem *atci = NULL;
2886
2887
        if (!obj || !name) return -1;
2888
2889
        atci = addrbookctl_lookup( obj->type );
2890
        if( ! atci ) return -1;
2891
        if( ! obj->name ) return -1;
2892
        return g_ascii_strcasecmp(obj->name, name);
2893
}
2894
2895
#if 0
2896
static void addressbook_book_show_message( AddressBookFile *abf ) {
2897
        *addressbook_msgbuf = '\0';
2898
        if( abf ) {
2899
                if( abf->retVal == MGU_SUCCESS ) {
2900
                        sprintf( addressbook_msgbuf, "%s", abf->name );
2901
                }
2902
                else {
2903
                        sprintf( addressbook_msgbuf, "%s: %s", abf->name, mgu_error2string( abf->retVal ) );
2904
                }
2905
        }
2906
        addressbook_status_show( addressbook_msgbuf );
2907
}
2908
#endif
2909
2910
static void addressbook_new_book_cb( gpointer data, guint action, GtkWidget *widget ) {
2911
        AdapterDSource *ads;
2912
        AdapterInterface *adapter;
2913
2914
        adapter = addrbookctl_find_interface( ADDR_IF_BOOK );
2915
        if( adapter == NULL ) return;
2916
        if( addrbook.treeSelected == NULL ) return;
2917
        if( addrbook.treeSelected != adapter->treeNode ) return;
2918
        ads = addressbook_edit_book( _addressIndex_, NULL );
2919
        if( ads ) {
2920
                addressbook_add_object( addrbook.treeSelected, ADDRESS_OBJECT(ads) );
2921
                if( addrbook.treeSelected == addrbook.opened ) {
2922
                        addrbook.treeSelected = NULL;
2923
                        gtk_ctree_select( GTK_CTREE(addrbook.ctree), addrbook.opened );
2924
                }
2925
        }
2926
}
2927
2928
static void addressbook_new_vcard_cb( gpointer data, guint action, GtkWidget *widget ) {
2929
        AdapterDSource *ads;
2930
        AdapterInterface *adapter;
2931
2932
        adapter = addrbookctl_find_interface( ADDR_IF_VCARD );
2933
        if( adapter == NULL ) return;
2934
        if( addrbook.treeSelected != adapter->treeNode ) return;
2935
        ads = addressbook_edit_vcard( _addressIndex_, NULL );
2936
        if( ads ) {
2937
                addressbook_add_object( addrbook.treeSelected, ADDRESS_OBJECT(ads) );
2938
                if( addrbook.treeSelected == addrbook.opened ) {
2939
                        addrbook.treeSelected = NULL;
2940
                        gtk_ctree_select( GTK_CTREE(addrbook.ctree), addrbook.opened );
2941
                }
2942
        }
2943
}
2944
2945
#if 0
2946
static void addressbook_vcard_show_message( VCardFile *vcf ) {
2947
        *addressbook_msgbuf = '\0';
2948
        if( vcf ) {
2949
                if( vcf->retVal == MGU_SUCCESS ) {
2950
                        sprintf( addressbook_msgbuf, "%s", vcf->name );
2951
                }
2952
                else {
2953
                        sprintf( addressbook_msgbuf, "%s: %s", vcf->name, mgu_error2string( vcf->retVal ) );
2954
                }
2955
        }
2956
        addressbook_status_show( addressbook_msgbuf );
2957
}
2958
#endif
2959
2960
#ifdef USE_JPILOT
2961
static void addressbook_new_jpilot_cb( gpointer data, guint action, GtkWidget *widget ) {
2962
        AdapterDSource *ads;
2963
        AdapterInterface *adapter;
2964
        AddressInterface *iface;
2965
2966
        adapter = addrbookctl_find_interface( ADDR_IF_JPILOT );
2967
        if( adapter == NULL ) return;
2968
        if( addrbook.treeSelected != adapter->treeNode ) return;
2969
        iface = adapter->interface;
2970
        if( ! iface->haveLibrary ) return;
2971
        ads = addressbook_edit_jpilot( _addressIndex_, NULL );
2972
        if( ads ) {
2973
                addressbook_add_object( addrbook.treeSelected, ADDRESS_OBJECT(ads) );
2974
                if( addrbook.treeSelected == addrbook.opened ) {
2975
                        addrbook.treeSelected = NULL;
2976
                        gtk_ctree_select( GTK_CTREE(addrbook.ctree), addrbook.opened );
2977
                }
2978
        }
2979
}
2980
2981
#if 0
2982
static void addressbook_jpilot_show_message( JPilotFile *jpf ) {
2983
        *addressbook_msgbuf = '\0';
2984
        if( jpf ) {
2985
                if( jpf->retVal == MGU_SUCCESS ) {
2986
                        sprintf( addressbook_msgbuf, "%s", jpf->name );
2987
                }
2988
                else {
2989
                        sprintf( addressbook_msgbuf, "%s: %s", jpf->name, mgu_error2string( jpf->retVal ) );
2990
                }
2991
        }
2992
        addressbook_status_show( addressbook_msgbuf );
2993
}
2994
#endif
2995
#endif /* USE_JPILOT */
2996
2997
#ifdef USE_LDAP
2998
static void addressbook_new_ldap_cb( gpointer data, guint action, GtkWidget *widget ) {
2999
        AdapterDSource *ads;
3000
        AdapterInterface *adapter;
3001
        AddressInterface *iface;
3002
3003
        adapter = addrbookctl_find_interface( ADDR_IF_LDAP );
3004
        if( adapter == NULL ) return;
3005
        if( addrbook.treeSelected != adapter->treeNode ) return;
3006
        iface = adapter->interface;
3007
        if( ! iface->haveLibrary ) return;
3008
        ads = addressbook_edit_ldap( _addressIndex_, NULL );
3009
        if( ads ) {
3010
                addressbook_add_object( addrbook.treeSelected, ADDRESS_OBJECT(ads) );
3011
                if( addrbook.treeSelected == addrbook.opened ) {
3012
                        addrbook.treeSelected = NULL;
3013
                        gtk_ctree_select( GTK_CTREE(addrbook.ctree), addrbook.opened );
3014
                }
3015
        }
3016
}
3017
3018
static void addressbook_ldap_show_message( SyldapServer *svr ) {
3019
        *addressbook_msgbuf = '\0';
3020
        if( svr ) {
3021
                if( svr->busyFlag ) {
3022
                        sprintf( addressbook_msgbuf, "%s: %s", svr->name, ADDRESSBOOK_LDAP_BUSYMSG );
3023
                }
3024
                else {
3025
                        if( svr->retVal == MGU_SUCCESS ) {
3026
                                sprintf( addressbook_msgbuf, "%s", svr->name );
3027
                        }
3028
                        else {
3029
                                sprintf( addressbook_msgbuf, "%s: %s", svr->name, mgu_error2string( svr->retVal ) );
3030
                        }
3031
                }
3032
        }
3033
        addressbook_status_show( addressbook_msgbuf );
3034
}
3035
3036
static void ldapsearch_callback( SyldapServer *sls ) {
3037
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
3038
        AddressObject *obj;
3039
        AdapterDSource *ads = NULL;
3040
        AddressDataSource *ds = NULL;
3041
        AddressInterface *iface = NULL;
3042
3043
        if( sls == NULL ) return;
3044
        if( ! addrbook.treeSelected ) return;
3045
        if( GTK_CTREE_ROW( addrbook.treeSelected )->level == 1 ) return;
3046
3047
        obj = gtk_ctree_node_get_row_data( ctree, addrbook.treeSelected );
3048
        if( obj == NULL ) return;
3049
        if( obj->type == ADDR_DATASOURCE ) {
3050
                ads = ADAPTER_DSOURCE(obj);
3051
                if( ads->subType == ADDR_LDAP ) {
3052
                        SyldapServer *server;
3053
3054
                        ds = ads->dataSource;
3055
                        if( ds == NULL ) return;
3056
                        iface = ds->interface;
3057
                        if( ! iface->haveLibrary ) return;
3058
                        server = ds->rawDataSource;
3059
                        if( server == sls ) {
3060
                                /* Read from cache */
3061
                                gtk_widget_show_all(addrbook.window);
3062
                                addressbook_set_clist( obj );
3063
                                addressbook_ldap_show_message( sls );
3064
                                gtk_widget_show_all(addrbook.window);
3065
                                gtk_entry_set_text( GTK_ENTRY(addrbook.entry), "" );
3066
                        }
3067
                }
3068
        }
3069
}
3070
#endif
3071
3072
/*
3073
 * Lookup button handler.
3074
 */
3075
static void addressbook_lup_clicked( GtkButton *button, gpointer data ) {
3076
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
3077
        AddressObject *obj;
3078
        AdapterDSource *ads = NULL;
3079
#ifdef USE_LDAP
3080
        AddressDataSource *ds = NULL;
3081
        AddressInterface *iface = NULL;
3082
#endif /* USE_LDAP */
3083
        gchar *sLookup;
3084
3085
        if( ! addrbook.treeSelected ) return;
3086
        if( GTK_CTREE_ROW( addrbook.treeSelected )->level == 1 ) return;
3087
3088
        obj = gtk_ctree_node_get_row_data( ctree, addrbook.treeSelected );
3089
        if( obj == NULL ) return;
3090
3091
        sLookup = gtk_editable_get_chars( GTK_EDITABLE(addrbook.entry), 0, -1 );
3092
        g_strchomp( sLookup );
3093
3094
        if( obj->type == ADDR_DATASOURCE ) {
3095
                ads = ADAPTER_DSOURCE(obj);
3096
#ifdef USE_LDAP
3097
                if( ads->subType == ADDR_LDAP ) {
3098
                        SyldapServer *server;
3099
3100
                        ds = ads->dataSource;
3101
                        if( ds == NULL ) return;
3102
                        iface = ds->interface;
3103
                        if( ! iface->haveLibrary ) return;
3104
                        server = ds->rawDataSource;
3105
                        if( server ) {
3106
                                syldap_cancel_read( server );
3107
                                if( *sLookup == '\0' || strlen( sLookup ) < 1 ) return;
3108
                                syldap_set_search_value( server, sLookup );
3109
                                syldap_set_callback( server, ldapsearch_callback );
3110
                                syldap_read_data_th( server );
3111
                                addressbook_ldap_show_message( server );
3112
                        }
3113
                }
3114
#endif /* USE_LDAP */
3115
        }
3116
3117
        g_free( sLookup );
3118
}
3119
3120
static void addressbook_close_clicked(GtkButton        *button, gpointer data)
3121
{
3122
        addressbook_close();
3123
}
3124
3125
/* **********************************************************************
3126
* Build lookup tables.
3127
* ***********************************************************************
3128
*/
3129
3130
/*
3131
* Build table that controls the rendering of object types.
3132
*/
3133
void addrbookctl_build_map( GtkWidget *window ) {
3134
        AddressTypeControlItem *atci;
3135
3136
        /* Build icons */
3137
        stock_pixmap_gdk(window, STOCK_PIXMAP_DIR_CLOSE, &folderxpm, &folderxpmmask);
3138
        stock_pixmap_gdk(window, STOCK_PIXMAP_DIR_OPEN, &folderopenxpm, &folderopenxpmmask);
3139
        stock_pixmap_gdk(window, STOCK_PIXMAP_GROUP, &groupxpm, &groupxpmmask);
3140
        stock_pixmap_gdk(window, STOCK_PIXMAP_VCARD, &vcardxpm, &vcardxpmmask);
3141
        stock_pixmap_gdk(window, STOCK_PIXMAP_BOOK, &bookxpm, &bookxpmmask);
3142
        stock_pixmap_gdk(window, STOCK_PIXMAP_ADDRESS, &addressxpm, &addressxpmmask);
3143
        stock_pixmap_gdk(window, STOCK_PIXMAP_JPILOT, &jpilotxpm, &jpilotxpmmask);
3144
        stock_pixmap_gdk(window, STOCK_PIXMAP_CATEGORY, &categoryxpm, &categoryxpmmask);
3145
        stock_pixmap_gdk(window, STOCK_PIXMAP_LDAP, &ldapxpm, &ldapxpmmask);
3146
3147
        _addressBookTypeHash_ = g_hash_table_new( g_int_hash, g_int_equal );
3148
        _addressBookTypeList_ = NULL;
3149
3150
        /* Interface */
3151
        atci = g_new0( AddressTypeControlItem, 1 );
3152
        atci->objectType = ADDR_INTERFACE;
3153
        atci->interfaceType = ADDR_IF_NONE;
3154
        atci->showInTree = TRUE;
3155
        atci->treeExpand = TRUE;
3156
        atci->treeLeaf = FALSE;
3157
        atci->displayName = _( "Interface" );
3158
        atci->iconXpm = folderxpm;
3159
        atci->maskXpm = folderxpmmask;
3160
        atci->iconXpmOpen = folderopenxpm;
3161
        atci->maskXpmOpen = folderopenxpmmask;
3162
        atci->menuCommand = NULL;
3163
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3164
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3165
3166
        /* Address book */
3167
        atci = g_new0( AddressTypeControlItem, 1 );
3168
        atci->objectType = ADDR_BOOK;
3169
        atci->interfaceType = ADDR_IF_BOOK;
3170
        atci->showInTree = TRUE;
3171
        atci->treeExpand = TRUE;
3172
        atci->treeLeaf = FALSE;
3173
        atci->displayName = _( "Address Book" );
3174
        atci->iconXpm = bookxpm;
3175
        atci->maskXpm = bookxpmmask;
3176
        atci->iconXpmOpen = bookxpm;
3177
        atci->maskXpmOpen = bookxpmmask;
3178
        atci->menuCommand = "/File/New Book";
3179
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3180
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3181
3182
        /* Item person */
3183
        atci = g_new0( AddressTypeControlItem, 1 );
3184
        atci->objectType = ADDR_ITEM_PERSON;
3185
        atci->interfaceType = ADDR_IF_NONE;
3186
        atci->showInTree = FALSE;
3187
        atci->treeExpand = FALSE;
3188
        atci->treeLeaf = FALSE;
3189
        atci->displayName = _( "Person" );
3190
        atci->iconXpm = NULL;
3191
        atci->maskXpm = NULL;
3192
        atci->iconXpmOpen = NULL;
3193
        atci->maskXpmOpen = NULL;
3194
        atci->menuCommand = NULL;
3195
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3196
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3197
3198
        /* Item email */
3199
        atci = g_new0( AddressTypeControlItem, 1 );
3200
        atci->objectType = ADDR_ITEM_EMAIL;
3201
        atci->interfaceType = ADDR_IF_NONE;
3202
        atci->showInTree = FALSE;
3203
        atci->treeExpand = FALSE;
3204
        atci->treeLeaf = TRUE;
3205
        atci->displayName = _( "EMail Address" );
3206
        atci->iconXpm = addressxpm;
3207
        atci->maskXpm = addressxpmmask;
3208
        atci->iconXpmOpen = addressxpm;
3209
        atci->maskXpmOpen = addressxpmmask;
3210
        atci->menuCommand = NULL;
3211
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3212
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3213
3214
        /* Item group */
3215
        atci = g_new0( AddressTypeControlItem, 1 );
3216
        atci->objectType = ADDR_ITEM_GROUP;
3217
        atci->interfaceType = ADDR_IF_BOOK;
3218
        atci->showInTree = TRUE;
3219
        atci->treeExpand = FALSE;
3220
        atci->treeLeaf = FALSE;
3221
        atci->displayName = _( "Group" );
3222
        atci->iconXpm = groupxpm;
3223
        atci->maskXpm = groupxpmmask;
3224
        atci->iconXpmOpen = groupxpm;
3225
        atci->maskXpmOpen = groupxpmmask;
3226
        atci->menuCommand = NULL;
3227
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3228
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3229
3230
        /* Item folder */
3231
        atci = g_new0( AddressTypeControlItem, 1 );
3232
        atci->objectType = ADDR_ITEM_FOLDER;
3233
        atci->interfaceType = ADDR_IF_BOOK;
3234
        atci->showInTree = TRUE;
3235
        atci->treeExpand = FALSE;
3236
        atci->treeLeaf = FALSE;
3237
        atci->displayName = _( "Folder" );
3238
        atci->iconXpm = folderxpm;
3239
        atci->maskXpm = folderxpmmask;
3240
        atci->iconXpmOpen = folderopenxpm;
3241
        atci->maskXpmOpen = folderopenxpmmask;
3242
        atci->menuCommand = NULL;
3243
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3244
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3245
3246
        /* vCard */
3247
        atci = g_new0( AddressTypeControlItem, 1 );
3248
        atci->objectType = ADDR_VCARD;
3249
        atci->interfaceType = ADDR_IF_VCARD;
3250
        atci->showInTree = TRUE;
3251
        atci->treeExpand = TRUE;
3252
        atci->treeLeaf = TRUE;
3253
        atci->displayName = _( "vCard" );
3254
        atci->iconXpm = vcardxpm;
3255
        atci->maskXpm = vcardxpmmask;
3256
        atci->iconXpmOpen = vcardxpm;
3257
        atci->maskXpmOpen = vcardxpmmask;
3258
        atci->menuCommand = "/File/New vCard";
3259
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3260
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3261
3262
        /* JPilot */
3263
        atci = g_new0( AddressTypeControlItem, 1 );
3264
        atci->objectType = ADDR_JPILOT;
3265
        atci->interfaceType = ADDR_IF_JPILOT;
3266
        atci->showInTree = TRUE;
3267
        atci->treeExpand = TRUE;
3268
        atci->treeLeaf = FALSE;
3269
        atci->displayName = _( "JPilot" );
3270
        atci->iconXpm = jpilotxpm;
3271
        atci->maskXpm = jpilotxpmmask;
3272
        atci->iconXpmOpen = jpilotxpm;
3273
        atci->maskXpmOpen = jpilotxpmmask;
3274
        atci->menuCommand = "/File/New JPilot";
3275
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3276
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3277
3278
        /* Category */
3279
        atci = g_new0( AddressTypeControlItem, 1 );
3280
        atci->objectType = ADDR_CATEGORY;
3281
        atci->interfaceType = ADDR_IF_JPILOT;
3282
        atci->showInTree = TRUE;
3283
        atci->treeExpand = TRUE;
3284
        atci->treeLeaf = TRUE;
3285
        atci->displayName = _( "JPilot" );
3286
        atci->iconXpm = categoryxpm;
3287
        atci->maskXpm = categoryxpmmask;
3288
        atci->iconXpmOpen = categoryxpm;
3289
        atci->maskXpmOpen = categoryxpmmask;
3290
        atci->menuCommand = NULL;
3291
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3292
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3293
3294
        /* LDAP Server */
3295
        atci = g_new0( AddressTypeControlItem, 1 );
3296
        atci->objectType = ADDR_LDAP;
3297
        atci->interfaceType = ADDR_IF_LDAP;
3298
        atci->showInTree = TRUE;
3299
        atci->treeExpand = TRUE;
3300
        atci->treeLeaf = TRUE;
3301
        atci->displayName = _( "LDAP Server" );
3302
        atci->iconXpm = ldapxpm;
3303
        atci->maskXpm = ldapxpmmask;
3304
        atci->iconXpmOpen = ldapxpm;
3305
        atci->maskXpmOpen = ldapxpmmask;
3306
        atci->menuCommand = "/File/New LDAP Server";
3307
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3308
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3309
3310
}
3311
3312
/*
3313
* Search for specified object type.
3314
*/
3315
AddressTypeControlItem *addrbookctl_lookup( gint ot ) {
3316
        gint objType = ot;
3317
        return ( AddressTypeControlItem * ) g_hash_table_lookup( _addressBookTypeHash_, &objType );
3318
}
3319
3320
/*
3321
* Search for specified interface type.
3322
*/
3323
AddressTypeControlItem *addrbookctl_lookup_iface( AddressIfType ifType ) {
3324
        GList *node = _addressBookTypeList_;
3325
        while( node ) {
3326
                AddressTypeControlItem *atci = node->data;
3327
                if( atci->interfaceType == ifType ) return atci;
3328
                node = g_list_next( node );
3329
        }
3330
        return NULL;
3331
}
3332
3333
static void addrbookctl_free_address( AddressObject *obj ) {
3334
        g_free( obj->name );
3335
        obj->type = ADDR_NONE;
3336
        obj->name = NULL;
3337
}
3338
3339
static void addrbookctl_free_interface( AdapterInterface *adapter ) {
3340
        addrbookctl_free_address( ADDRESS_OBJECT(adapter) );
3341
        adapter->interface = NULL;
3342
        adapter->interfaceType = ADDR_IF_NONE;
3343
        adapter->atci = NULL;
3344
        adapter->enabled = FALSE;
3345
        adapter->haveLibrary = FALSE;
3346
        adapter->treeNode = NULL;
3347
        g_free( adapter );
3348
}
3349
3350
static void addrbookctl_free_datasource( AdapterDSource *adapter ) {
3351
        addrbookctl_free_address( ADDRESS_OBJECT(adapter) );
3352
        adapter->dataSource = NULL;
3353
        adapter->subType = ADDR_NONE;
3354
        g_free( adapter );
3355
}
3356
3357
static void addrbookctl_free_folder( AdapterFolder *adapter ) {
3358
        addrbookctl_free_address( ADDRESS_OBJECT(adapter) );
3359
        adapter->itemFolder = NULL;
3360
        g_free( adapter );
3361
}
3362
3363
static void addrbookctl_free_group( AdapterGroup *adapter ) {
3364
        addrbookctl_free_address( ADDRESS_OBJECT(adapter) );
3365
        adapter->itemGroup = NULL;
3366
        g_free( adapter );
3367
}
3368
3369
/*
3370
 * Build GUI interface list.
3371
 */
3372
void addrbookctl_build_iflist() {
3373
        AddressTypeControlItem *atci;
3374
        AdapterInterface *adapter;
3375
        GList *list = NULL;
3376
3377
        if( _addressIndex_ == NULL ) {
3378
                _addressIndex_ = addrindex_create_index();
3379
        }
3380
        _addressInterfaceList_ = NULL;
3381
        list = addrindex_get_interface_list( _addressIndex_ );
3382
        while( list ) {
3383
                AddressInterface *interface = list->data;
3384
                atci = addrbookctl_lookup_iface( interface->type );
3385
                if( atci ) {
3386
                        adapter = g_new0( AdapterInterface, 1 );
3387
                        adapter->interfaceType = interface->type;
3388
                        adapter->atci = atci;
3389
                        adapter->interface = interface;
3390
                        adapter->treeNode = NULL;
3391
                        adapter->enabled = TRUE;
3392
                        adapter->haveLibrary = interface->haveLibrary;
3393
                        ADDRESS_OBJECT(adapter)->type = ADDR_INTERFACE;
3394
                        ADDRESS_OBJECT_NAME(adapter) = g_strdup( atci->displayName );
3395
                        _addressInterfaceList_ = g_list_append( _addressInterfaceList_, adapter );
3396
                }
3397
                list = g_list_next( list );
3398
        }
3399
}
3400
3401
void addrbookctl_free_selection( GList *list ) {
3402
        GList *node = list;
3403
        while( node ) {
3404
                AdapterInterface *adapter = node->data;
3405
                adapter = NULL;
3406
                node = g_list_next( node );
3407
        }
3408
        g_list_free( list );
3409
}
3410
3411
/*
3412
* Find GUI interface type specified interface type.
3413
* Return: Interface item, or NULL if not found.
3414
*/
3415
AdapterInterface *addrbookctl_find_interface( AddressIfType ifType ) {
3416
        GList *node = _addressInterfaceList_;
3417
        while( node ) {
3418
                AdapterInterface *adapter = node->data;
3419
                if( adapter->interfaceType == ifType ) return adapter;
3420
                node = g_list_next( node );
3421
        }
3422
        return NULL;
3423
}
3424
3425
/*
3426
* Build interface list selection.
3427
*/
3428
void addrbookctl_build_ifselect() {
3429
        GList *newList = NULL;
3430
        gchar *selectStr;
3431
        gchar **splitStr;
3432
        gint ifType;
3433
        gint i;
3434
        gchar *endptr = NULL;
3435
        gboolean enabled;
3436
        AdapterInterface *adapter;
3437
        /* GList *node; */
3438
3439
        selectStr = g_strdup( ADDRESSBOOK_IFACE_SELECTION );
3440
3441
        /* Parse string */
3442
        splitStr = g_strsplit( selectStr, ",", -1 );
3443
        for( i = 0; i < ADDRESSBOOK_MAX_IFACE; i++ ) {
3444
                if( splitStr[i] ) {
3445
                        /* printf( "%d : %s\n", i, splitStr[i] ); */
3446
                        ifType = strtol( splitStr[i], &endptr, 10 );
3447
                        enabled = TRUE;
3448
                        if( *endptr ) {
3449
                                if( strcmp( endptr, "/n" ) == 0 ) {
3450
                                        enabled = FALSE;
3451
                                }
3452
                        }
3453
                        /* printf( "\t%d : %s\n", ifType, enabled ? "yes" : "no" ); */
3454
                        adapter = addrbookctl_find_interface( ifType );
3455
                        if( adapter ) {
3456
                                newList = g_list_append( newList, adapter );
3457
                        }
3458
                }
3459
                else {
3460
                        break;
3461
                }
3462
        }
3463
        /* printf( "i=%d\n", i ); */
3464
        g_strfreev( splitStr );
3465
        g_free( selectStr );
3466
3467
        /* Replace existing list */
3468
        mgu_clear_list( _addressIFaceSelection_ );
3469
        g_list_free( _addressIFaceSelection_ );
3470
        _addressIFaceSelection_ = newList;
3471
        newList = NULL;
3472
3473
}
3474
3475
/* **********************************************************************
3476
* Add sender to address book.
3477
* ***********************************************************************
3478
*/
3479
3480
/*
3481
 * This function is used by the Add sender to address book function.
3482
 */
3483
gboolean addressbook_add_contact( const gchar *name, const gchar *address, const gchar *remarks ) {
3484
        debug_print( "addressbook_add_contact: name/address: %s - %s\n", name, address );
3485
        if( addressadd_selection( _addressIndex_, name, address, remarks ) ) {
3486
                debug_print( "addressbook_add_contact - added\n" );
3487
                addressbook_refresh();
3488
        }
3489
        return TRUE;
3490
}
3491
3492
/* **********************************************************************
3493
* Address completion support.
3494
* ***********************************************************************
3495
*/
3496
3497
/*
3498
* This function is used by the address completion function to load
3499
* addresses.
3500
* Enter: callBackFunc Function to be called when an address is
3501
*                     to be loaded.
3502
* Return: TRUE if data loaded, FALSE if address index not loaded.
3503
*/
3504
gboolean addressbook_load_completion( gint (*callBackFunc) ( const gchar *, const gchar * ) ) {
3505
        /* AddressInterface *interface; */
3506
        AddressDataSource *ds;
3507
        GList *nodeIf, *nodeDS;
3508
        GList *listP, *nodeP;
3509
        GList *nodeM;
3510
        gchar *sName, *sAddress, *sAlias, *sFriendly;
3511
3512
        debug_print( "addressbook_load_completion\n" );
3513
3514
        if( _addressIndex_ == NULL ) return FALSE;
3515
3516
        nodeIf = addrindex_get_interface_list( _addressIndex_ );
3517
        while( nodeIf ) {
3518
                AddressInterface *interface = nodeIf->data;
3519
                nodeDS = interface->listSource;
3520
                while( nodeDS ) {
3521
                        ds = nodeDS->data;
3522
3523
                        /* Read address book */
3524
                        if( ! addrindex_ds_get_read_flag( ds ) ) {
3525
                                addrindex_ds_read_data( ds );
3526
                        }
3527
3528
                        /* Get all persons */
3529
                        listP = addrindex_ds_get_all_persons( ds );
3530
                        nodeP = listP;
3531
                        while( nodeP ) {
3532
                                ItemPerson *person = nodeP->data;
3533
                                nodeM = person->listEMail;
3534
3535
                                /* Figure out name to use */
3536
                                sName = person->nickName;
3537
                                if( sName == NULL || *sName == '\0' ) {
3538
                                        sName = ADDRITEM_NAME(person);
3539
                                }
3540
3541
                                /* Process each E-Mail address */
3542
                                while( nodeM ) {
3543
                                        ItemEMail *email = nodeM->data;
3544
                                        /* Have mail */
3545
                                        sFriendly = sName;
3546
                                        sAddress = email->address;
3547
                                        if( sAddress && *sAddress != '\0' ) {
3548
                                                sAlias = ADDRITEM_NAME(email);
3549
                                                if( sAlias && *sAlias != '\0' ) {
3550
                                                        sFriendly = sAlias;
3551
                                                }
3552
                                                ( callBackFunc ) ( sFriendly, sAddress );
3553
                                        }
3554
3555
                                        nodeM = g_list_next( nodeM );
3556
                                }
3557
                                nodeP = g_list_next( nodeP );
3558
                        }
3559
                        /* Free up the list */
3560
                        g_list_free( listP );
3561
3562
                        nodeDS = g_list_next( nodeDS );
3563
                }
3564
                nodeIf = g_list_next( nodeIf );
3565
        }
3566
        debug_print( "addressbook_load_completion... done\n" );
3567
3568
        return TRUE;
3569
}
3570
3571
/* **********************************************************************
3572
* Address Import.
3573
* ***********************************************************************
3574
*/
3575
3576
/*
3577
* Import LDIF file.
3578
*/
3579
static void addressbook_import_ldif_cb() {
3580
        AddressDataSource *ds = NULL;
3581
        AdapterDSource *ads = NULL;
3582
        AddressBookFile *abf = NULL;
3583
        AdapterInterface *adapter;
3584
        GtkCTreeNode *newNode;
3585
3586
        adapter = addrbookctl_find_interface( ADDR_IF_BOOK );
3587
        if ( !adapter || !adapter->treeNode ) return;
3588
3589
        abf = addressbook_imp_ldif( _addressIndex_ );
3590
        if ( !abf ) return;
3591
3592
        ds = addrindex_index_add_datasource( _addressIndex_, ADDR_IF_BOOK, abf );
3593
        ads = addressbook_create_ds_adapter( ds, ADDR_BOOK, NULL );
3594
        addressbook_ads_set_name( ads, abf->name );
3595
        newNode = addressbook_add_object( adapter->treeNode, ADDRESS_OBJECT(ads) );
3596
        if ( newNode ) {
3597
                addrbook.treeSelected = NULL;
3598
                gtk_ctree_select( GTK_CTREE(addrbook.ctree), newNode );
3599
                addrbook.treeSelected = newNode;
3600
        }
3601
3602
        /* Notify address completion */
3603
        invalidate_address_completion();
3604
}
3605
3606
/*
3607
* End of Source.
3608
*/