Statistics
| Revision:

root / src / addressbook.c @ 3043

History | View | Annotate | Download (136.6 kB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2012 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/gtk.h>
30
#include <string.h>
31
#include <setjmp.h>
32
33
#include "main.h"
34
#include "addressbook.h"
35
#include "manage_window.h"
36
#include "prefs_common.h"
37
#include "alertpanel.h"
38
#include "inputdialog.h"
39
#include "menu.h"
40
#include "stock_pixmap.h"
41
#include "xml.h"
42
#include "prefs.h"
43
#include "procmime.h"
44
#include "utils.h"
45
#include "gtkutils.h"
46
#include "codeconv.h"
47
#include "about.h"
48
#include "addr_compl.h"
49
50
#include "mgutils.h"
51
#include "addressitem.h"
52
#include "addritem.h"
53
#include "addrcache.h"
54
#include "addrbook.h"
55
#include "addrindex.h"
56
#include "addressadd.h"
57
#include "vcard.h"
58
#include "editvcard.h"
59
#include "editgroup.h"
60
#include "editaddress.h"
61
#include "editbook.h"
62
#include "ldif.h"
63
#include "importldif.h"
64
#include "importcsv.h"
65
66
#ifdef USE_JPILOT
67
#include "jpilot.h"
68
#include "editjpilot.h"
69
#endif
70
71
#ifdef USE_LDAP
72
#include <pthread.h>
73
#include "syldap.h"
74
#include "editldap.h"
75
76
#define ADDRESSBOOK_LDAP_BUSYMSG "Busy"
77
#endif
78
79
typedef enum
80
{
81
        COL_FOLDER_NAME,
82
        COL_OBJ,
83
        COL_PIXBUF,
84
        COL_PIXBUF_OPEN,
85
86
        N_TREE_COLS
87
} AddressBookTreeColumnPos;
88
89
typedef enum
90
{
91
        COL_NAME,
92
        COL_ADDRESS,
93
        COL_REMARKS,
94
        COL_L_OBJ,
95
        COL_L_PIXBUF,
96
97
        N_LIST_COLS
98
} AddressBookListColumnPos;
99
100
enum
101
{
102
        DRAG_TYPE_OBJ,
103
104
        N_DRAG_TYPES
105
};
106
107
#define COL_NAME_WIDTH                164
108
#define COL_ADDRESS_WIDTH        156
109
110
#define COL_FOLDER_WIDTH        170
111
112
#define ADDRESSBOOK_MSGBUF_SIZE 2048
113
114
static GdkPixbuf *folderpix;
115
static GdkPixbuf *folderopenpix;
116
static GdkPixbuf *grouppix;
117
static GdkPixbuf *interfacepix;
118
static GdkPixbuf *bookpix;
119
static GdkPixbuf *personpix;
120
static GdkPixbuf *addresspix;
121
static GdkPixbuf *vcardpix;
122
static GdkPixbuf *jpilotpix;
123
static GdkPixbuf *categorypix;
124
static GdkPixbuf *ldappix;
125
126
/* Address list selection */
127
static GList *_addressListSelection_ = NULL;
128
129
static gboolean can_toggle_list_selection = TRUE;
130
static gboolean list_on_drag = FALSE;
131
132
/* Address index file and interfaces */
133
static AddressIndex *_addressIndex_ = NULL;
134
static GList *_addressInterfaceList_ = NULL;
135
static GList *_addressIFaceSelection_ = NULL;
136
#define ADDRESSBOOK_IFACE_SELECTION "1/y,3/y,4/y,2/n"
137
138
/* Address clipboard */
139
static GList *_clipObjectList_ = NULL;
140
141
static AddressBook_win addrbook;
142
143
static GHashTable *_addressBookTypeHash_ = NULL;
144
static GList *_addressBookTypeList_ = NULL;
145
146
static void addressbook_refresh                        (void);
147
static void addressbook_reopen                        (void);
148
149
static void addressbook_create                        (void);
150
static gint addressbook_close                        (void);
151
152
static void addressbook_menuitem_set_sensitive        (void);
153
154
/* callback functions */
155
static void addressbook_del_clicked                (GtkButton        *button,
156
                                                 gpointer         data);
157
static void addressbook_reg_clicked                (GtkButton        *button,
158
                                                 gpointer         data);
159
static void addressbook_to_clicked                (GtkButton        *button,
160
                                                 gpointer         data);
161
static void addressbook_lup_clicked                (GtkButton        *button,
162
                                                 gpointer        data);
163
static void addressbook_close_clicked                (GtkButton        *button,
164
                                                 gpointer        data);
165
166
static void addressbook_tree_selection_changed        (GtkTreeSelection *selection,
167
                                                 gpointer         data);
168
static void addressbook_list_selection_changed        (GtkTreeSelection *selection,
169
                                                 gpointer         data);
170
static void addressbook_person_expand_node        (GtkTreeView        *treeview,
171
                                                 GtkTreeIter        *iter,
172
                                                 GtkTreePath        *path,
173
                                                 gpointer        *data);
174
static void addressbook_person_collapse_node        (GtkTreeView        *treeview,
175
                                                 GtkTreeIter        *iter,
176
                                                 GtkTreePath        *path,
177
                                                 gpointer        *data);
178
179
static void addressbook_drag_begin                (GtkWidget        *widget,
180
                                                 GdkDragContext        *drag_context,
181
                                                 gpointer         data);
182
static void addressbook_drag_end                (GtkWidget        *widget,
183
                                                 GdkDragContext        *drag_context,
184
                                                 gpointer         data);
185
static void addressbook_drag_data_get                (GtkWidget        *widget,
186
                                                 GdkDragContext        *drag_context,
187
                                                 GtkSelectionData *selection_data,
188
                                                 guint                 info,
189
                                                 guint                 time,
190
                                                 gpointer         data);
191
192
#if 0
193
static void addressbook_entry_changed                (GtkWidget        *widget);
194
#endif
195
static void addressbook_entry_activated                (GtkWidget        *widget,
196
                                                 gpointer         data);
197
198
static gboolean addressbook_list_button_pressed        (GtkWidget        *widget,
199
                                                 GdkEventButton        *event,
200
                                                 gpointer         data);
201
static gboolean addressbook_list_button_released(GtkWidget        *widget,
202
                                                 GdkEventButton        *event,
203
                                                 gpointer         data);
204
static gboolean addressbook_tree_button_pressed        (GtkWidget        *ctree,
205
                                                 GdkEventButton        *event,
206
                                                 gpointer         data);
207
static gboolean addressbook_tree_button_released(GtkWidget        *ctree,
208
                                                 GdkEventButton        *event,
209
                                                 gpointer         data);
210
211
static gboolean addressbook_drag_motion                (GtkWidget        *widget,
212
                                                 GdkDragContext        *context,
213
                                                 gint                 x,
214
                                                 gint                 y,
215
                                                 guint                 time,
216
                                                 gpointer         data);
217
static void addressbook_drag_leave                (GtkWidget        *widget,
218
                                                 GdkDragContext        *context,
219
                                                 guint                 time,
220
                                                 gpointer         data);
221
static void addressbook_drag_received                (GtkWidget        *widget,
222
                                                 GdkDragContext        *context,
223
                                                 gint                 x,
224
                                                 gint                 y,
225
                                                 GtkSelectionData *data,
226
                                                 guint                 info,
227
                                                 guint                 time,
228
                                                 gpointer         user_data);
229
230
static void addressbook_folder_resized                (GtkWidget        *widget,
231
                                                 GtkAllocation        *allocation,
232
                                                 gpointer         data);
233
static void addressbook_col_resized                (GtkWidget        *widget,
234
                                                 GtkAllocation        *allocation,
235
                                                 gpointer         data);
236
237
static void addressbook_popup_close                (GtkMenuShell        *menu_shell,
238
                                                 gpointer         data);
239
240
static void addressbook_new_folder_cb                (gpointer         data,
241
                                                 guint                 action,
242
                                                 GtkWidget        *widget);
243
static void addressbook_new_group_cb                (gpointer         data,
244
                                                 guint                 action,
245
                                                 GtkWidget        *widget);
246
static void addressbook_treenode_edit_cb        (gpointer         data,
247
                                                 guint                 action,
248
                                                 GtkWidget        *widget);
249
static void addressbook_treenode_delete_cb        (gpointer         data,
250
                                                 guint                 action,
251
                                                 GtkWidget        *widget);
252
253
static void addressbook_change_node_name        (GtkTreeIter        *iter,
254
                                                 const gchar        *name);
255
256
static void addressbook_new_address_cb                (gpointer         data,
257
                                                 guint                 action,
258
                                                 GtkWidget        *widget);
259
static void addressbook_compose_to_cb                (gpointer         data,
260
                                                 guint                 action,
261
                                                 GtkWidget        *widget);
262
static void addressbook_edit_address_cb                (gpointer         data,
263
                                                 guint                 action,
264
                                                 GtkWidget        *widget);
265
static void addressbook_delete_address_cb        (gpointer         data,
266
                                                 guint                 action,
267
                                                 GtkWidget        *widget);
268
static void addressbook_copy_address_cb                (gpointer         data,
269
                                                 guint                 action,
270
                                                 GtkWidget        *widget);
271
static void addressbook_paste_address_cb        (gpointer         data,
272
                                                 guint                 action,
273
                                                 GtkWidget        *widget);
274
275
static void close_cb                                (gpointer         data,
276
                                                 guint                 action,
277
                                                 GtkWidget        *widget);
278
static void addressbook_file_save_cb                (gpointer         data,
279
                                                 guint                 action,
280
                                                 GtkWidget        *widget);
281
282
/* Data source edit stuff */
283
static void addressbook_new_book_cb                (gpointer         data,
284
                                                        guint                 action,
285
                                                 GtkWidget        *widget);
286
static void addressbook_new_vcard_cb                (gpointer         data,
287
                                                        guint                 action,
288
                                                 GtkWidget        *widget);
289
290
#ifdef USE_JPILOT
291
static void addressbook_new_jpilot_cb                (gpointer         data,
292
                                                        guint                 action,
293
                                                 GtkWidget        *widget);
294
#endif
295
296
#ifdef USE_LDAP
297
static void addressbook_new_ldap_cb                (gpointer         data,
298
                                                        guint                 action,
299
                                                 GtkWidget        *widget);
300
#endif
301
302
static void addressbook_set_list                (AddressObject        *obj);
303
304
static void addressbook_load_tree                (void);
305
void addressbook_read_file                        (void);
306
307
static gboolean addressbook_add_object                (GtkTreeIter        *iter,
308
                                                 GtkTreeIter        *new_iter,
309
                                                 AddressObject        *obj);
310
static AddressDataSource *addressbook_find_datasource
311
                                                (GtkTreeIter        *iter);
312
313
static AddressBookFile *addressbook_get_book_file();
314
315
static gboolean addressbook_node_add_folder        (GtkTreeIter        *iter,
316
                                                 AddressDataSource *ds,
317
                                                 ItemFolder        *itemFolder,
318
                                                 AddressObjectType otype,
319
                                                 GtkTreeIter        *new_iter);
320
static gboolean addressbook_node_add_group        (GtkTreeIter        *iter,
321
                                                 AddressDataSource *ds,
322
                                                 ItemGroup        *itemGroup,
323
                                                 GtkTreeIter        *new_iter);
324
static void addressbook_tree_remove_children        (GtkTreeModel        *model,
325
                                                 GtkTreeIter        *parent);
326
static void addressbook_move_nodes_up                (GtkTreeIter        *iter);
327
static gboolean addressbook_find_group_node        (GtkTreeIter        *parent,
328
                                                 GtkTreeIter        *iter,
329
                                                 ItemGroup        *group);
330
331
/* static void addressbook_delete_object        (AddressObject        *obj); */
332
333
static gboolean key_pressed                        (GtkWidget        *widget,
334
                                                 GdkEventKey        *event,
335
                                                 gpointer         data);
336
static void size_allocated                        (GtkWidget        *widget,
337
                                                 GtkAllocation        *allocation,
338
                                                 gpointer         data);
339
340
static gint addressbook_tree_compare                (GtkTreeModel        *model,
341
                                                 GtkTreeIter        *a,
342
                                                 GtkTreeIter        *b,
343
                                                 gpointer         data);
344
static gint addressbook_list_name_compare        (GtkTreeModel        *model,
345
                                                 GtkTreeIter        *a,
346
                                                 GtkTreeIter        *b,
347
                                                 gpointer         data);
348
static gint addressbook_list_address_compare        (GtkTreeModel        *model,
349
                                                 GtkTreeIter        *a,
350
                                                 GtkTreeIter        *b,
351
                                                 gpointer         data);
352
static gint addressbook_list_remarks_compare        (GtkTreeModel        *model,
353
                                                 GtkTreeIter        *a,
354
                                                 GtkTreeIter        *b,
355
                                                 gpointer         data);
356
 
357
static gboolean addressbook_list_select_func        (GtkTreeSelection *selection,
358
                                                 GtkTreeModel *model,
359
                                                 GtkTreePath *path,
360
                                                 gboolean cur_selected,
361
                                                 gpointer data);
362
363
/* static void addressbook_book_show_message        (AddressBookFile *book); */
364
/* static void addressbook_vcard_show_message        (VCardFile *vcf); */
365
#ifdef USE_JPILOT
366
/* static void addressbook_jpilot_show_message        (JPilotFile *jpf); */
367
#endif
368
#ifdef USE_LDAP
369
static void addressbook_ldap_show_message        (SyldapServer *server);
370
#endif
371
372
/* LUT's and IF stuff */
373
static void addressbook_free_adapter                (GtkTreeIter        *iter);
374
static void addressbook_free_child_adapters        (GtkTreeIter        *iter);
375
AddressTypeControlItem *addrbookctl_lookup        (gint                 ot);
376
AddressTypeControlItem *addrbookctl_lookup_iface(AddressIfType         ifType);
377
378
void addrbookctl_build_map                        (GtkWidget        *window);
379
void addrbookctl_build_iflist                        (void);
380
AdapterInterface *addrbookctl_find_interface        (AddressIfType         ifType);
381
void addrbookctl_build_ifselect                        (void);
382
383
static void addrbookctl_free_interface                (AdapterInterface *adapter);
384
static void addrbookctl_free_datasource                (AdapterDSource          *adapter);
385
static void addrbookctl_free_folder                (AdapterFolder          *adapter);
386
static void addrbookctl_free_group                (AdapterGroup          *adapter);
387
388
static void addressbook_list_select_clear        (void);
389
static void addressbook_list_select_remove        (AddressObject        *obj);
390
static void addressbook_list_select_set                (GList                *row_list);
391
392
static void addressbook_import_ldif_cb                (void);
393
static void addressbook_import_csv_cb                (void);
394
395
static void addressbook_modified                (void);
396
397
398
static GtkTargetEntry addressbook_drag_types[] =
399
{
400
        {"application/octet-stream", GTK_TARGET_SAME_APP, DRAG_TYPE_OBJ}
401
};
402
403
static GtkItemFactoryEntry addressbook_entries[] =
404
{
405
        {N_("/_File"),                        NULL,        NULL, 0, "<Branch>"},
406
        {N_("/_File/New _Book"),        NULL,        addressbook_new_book_cb,        0, NULL},
407
        {N_("/_File/New _vCard"),        NULL,        addressbook_new_vcard_cb,       0, NULL},
408
#ifdef USE_JPILOT
409
        {N_("/_File/New _JPilot"),        NULL,        addressbook_new_jpilot_cb,      0, NULL},
410
#endif
411
#ifdef USE_LDAP
412
        {N_("/_File/New _LDAP Server"),        NULL,        addressbook_new_ldap_cb,        0, NULL},
413
#endif
414
        {N_("/_File/---"),                NULL,                NULL, 0, "<Separator>"},
415
        {N_("/_File/_Edit"),                NULL,                addressbook_treenode_edit_cb,   0, NULL},
416
        {N_("/_File/_Delete"),                NULL,                addressbook_treenode_delete_cb, 0, NULL},
417
        {N_("/_File/---"),                NULL,                NULL, 0, "<Separator>"},
418
        {N_("/_File/_Save"),                "<control>S",        addressbook_file_save_cb,       0, NULL},
419
        {N_("/_File/_Close"),                "<control>W",        close_cb, 0, NULL},
420
421
        {N_("/_Edit"),                        NULL,                NULL, 0, "<Branch>"},
422
        {N_("/_Edit/_Copy"),                "<control>C",        addressbook_copy_address_cb,    0, NULL},
423
        {N_("/_Edit/_Paste"),                "<control>V",        addressbook_paste_address_cb,    0, NULL},
424
425
        {N_("/_Address"),                NULL,                NULL, 0, "<Branch>"},
426
        {N_("/_Address/New _Address"),        "<control>N",        addressbook_new_address_cb,     0, NULL},
427
        {N_("/_Address/New _Group"),        "<control>G",        addressbook_new_group_cb,       0, NULL},
428
        {N_("/_Address/New _Folder"),        "<control>F",        addressbook_new_folder_cb,      0, NULL},
429
        {N_("/_Address/---"),                NULL,                NULL, 0, "<Separator>"},
430
        {N_("/_Address/Add _to recipient"),
431
                                        "<control>M",        addressbook_compose_to_cb, COMPOSE_ENTRY_TO, NULL},
432
        {N_("/_Address/Add to _Cc"),
433
                                        NULL,                addressbook_compose_to_cb, COMPOSE_ENTRY_CC, NULL},
434
        {N_("/_Address/Add to _Bcc"),
435
                                        NULL,                addressbook_compose_to_cb, COMPOSE_ENTRY_BCC, NULL},
436
        {N_("/_Address/---"),                NULL,                NULL, 0, "<Separator>"},
437
        {N_("/_Address/_Edit"),                "<control>Return",        addressbook_edit_address_cb,    0, NULL},
438
        {N_("/_Address/_Delete"),        "Delete",        addressbook_delete_address_cb,  0, NULL},
439
440
        {N_("/_Tools"),                        NULL,                NULL, 0, "<Branch>"},
441
        {N_("/_Tools/Import _LDIF file"), NULL,                addressbook_import_ldif_cb,        0, NULL},
442
        {N_("/_Tools/Import _CSV file"), NULL,                addressbook_import_csv_cb,        0, NULL},
443
444
        {N_("/_Help"),                        NULL,                NULL, 0, "<Branch>"},
445
        {N_("/_Help/_About"),                NULL,                about_show, 0, NULL}
446
};
447
448
/* New options to be added. */
449
/*
450
        {N_("/_Edit"),                        NULL,                NULL, 0, "<Branch>"},
451
        {N_("/_Edit/C_ut"),                "<control>X",        NULL,                                0, NULL},
452
        {N_("/_Edit/_Copy"),                "<control>C",        NULL,                           0, NULL},
453
        {N_("/_Edit/_Paste"),                "<control>V",        NULL,                           0, NULL},
454
        {N_("/_Tools"),                        NULL,                NULL, 0, "<Branch>"},
455
        {N_("/_Tools/Import _Mozilla"),        NULL,           NULL,                                0, NULL},
456
        {N_("/_Tools/Import _vCard"),        NULL,           NULL,                                0, NULL},
457
        {N_("/_Tools/---"),                NULL,                NULL, 0, "<Separator>"},
458
        {N_("/_Tools/Export _LDIF file"), NULL,                NULL,                                0, NULL},
459
        {N_("/_Tools/Export v_Card"),        NULL,           NULL,                                0, NULL},
460
*/
461
462
static GtkItemFactoryEntry addressbook_tree_popup_entries[] =
463
{
464
        {N_("/New _Address"),        NULL, addressbook_new_address_cb, 0, NULL},
465
        {N_("/New _Group"),        NULL, addressbook_new_group_cb,   0, NULL},
466
        {N_("/New _Folder"),        NULL, addressbook_new_folder_cb,  0, NULL},
467
        {N_("/---"),                NULL, NULL, 0, "<Separator>"},
468
        {N_("/_Edit"),                NULL, addressbook_treenode_edit_cb,   0, NULL},
469
        {N_("/_Delete"),        NULL, addressbook_treenode_delete_cb, 0, NULL}
470
};
471
472
static GtkItemFactoryEntry addressbook_list_popup_entries[] =
473
{
474
        {N_("/New _Address"),        NULL, addressbook_new_address_cb,  0, NULL},
475
        {N_("/New _Group"),        NULL, addressbook_new_group_cb,    0, NULL},
476
        {N_("/New _Folder"),        NULL, addressbook_new_folder_cb,   0, NULL},
477
        {N_("/---"),                NULL, NULL, 0, "<Separator>"},
478
        {N_("/Add _to recipient"),
479
                                NULL, addressbook_compose_to_cb, COMPOSE_ENTRY_TO, NULL},
480
        {N_("/Add t_o Cc"),
481
                                NULL, addressbook_compose_to_cb, COMPOSE_ENTRY_CC, NULL},
482
        {N_("/Add to _Bcc"),
483
                                NULL, addressbook_compose_to_cb, COMPOSE_ENTRY_BCC, NULL},
484
        {N_("/---"),                NULL, NULL, 0, "<Separator>"},
485
        {N_("/_Edit"),                NULL, addressbook_edit_address_cb,   0, NULL},
486
        {N_("/_Delete"),        NULL, addressbook_delete_address_cb, 0, NULL},
487
        {N_("/---"),                NULL, NULL, 0, "<Separator>"},
488
        {N_("/_Copy"),                NULL, addressbook_copy_address_cb,  0, NULL},
489
        {N_("/_Paste"),                NULL, addressbook_paste_address_cb, 0, NULL}
490
};
491
492
493
void addressbook_open(Compose *target)
494
{
495
        if (!addrbook.window) {
496
                GtkTreeView *treeview;
497
                GtkTreeModel *model;
498
                GtkTreeIter iter;
499
                GtkTreePath *path;
500
501
                addressbook_read_file();
502
                addressbook_create();
503
                addressbook_load_tree();
504
                treeview = GTK_TREE_VIEW(addrbook.treeview);
505
                model = gtk_tree_view_get_model(treeview);
506
                if (gtk_tree_model_get_iter_first(model, &iter)) {
507
                        path = gtk_tree_model_get_path(model, &iter);
508
                        gtk_tree_view_set_cursor(treeview, path, NULL, FALSE);
509
                        gtk_tree_path_free(path);
510
                }
511
                addressbook_menuitem_set_sensitive();
512
                gtk_widget_show_all(addrbook.window);
513
        } 
514
515
        gtk_window_present(GTK_WINDOW(addrbook.window));
516
517
        addressbook_set_target_compose(target);
518
}
519
520
void addressbook_set_target_compose(Compose *target)
521
{
522
        addrbook.target_compose = target;
523
}
524
525
Compose *addressbook_get_target_compose(void)
526
{
527
        return addrbook.target_compose;
528
}
529
530
static void addressbook_refresh(void)
531
{
532
        if (addrbook.window) {
533
                if (addrbook.tree_opened) {
534
                        addressbook_reopen();
535
                }
536
        }
537
        addressbook_export_to_file();
538
}
539
540
static void addressbook_reopen(void)
541
{
542
        GtkTreePath *path;
543
544
        if (addrbook.tree_selected) {
545
                gtk_tree_row_reference_free(addrbook.tree_selected);
546
                addrbook.tree_selected = NULL;
547
        }
548
        if (addrbook.tree_opened) {
549
                path = gtk_tree_row_reference_get_path(addrbook.tree_opened);
550
                gtk_tree_view_set_cursor(GTK_TREE_VIEW(addrbook.treeview), path, NULL, FALSE);
551
                gtk_tree_path_free(path);
552
        }
553
}
554
555
/*
556
* Create the address book widgets. The address book contains two CTree widgets: the
557
* address index tree on the left and the address list on the right.
558
*
559
* The address index tree displays a hierarchy of interfaces and groups. Each node in
560
* this tree is linked to an address Adapter. Adapters have been created for interfaces,
561
* data sources and folder objects.
562
*
563
* The address list displays group, person and email objects. These items are linked
564
* directly to ItemGroup, ItemPerson and ItemEMail objects inside the address book data
565
* sources.
566
*
567
* In the tradition of MVC architecture, the data stores have been separated from the
568
* GUI components. The addrindex.c file provides the interface to all data stores.
569
*/
570
static void addressbook_create(void)
571
{
572
        GtkWidget *window;
573
        GtkWidget *vbox;
574
        GtkWidget *menubar;
575
        GtkWidget *spc_hbox;
576
        GtkWidget *vbox2;
577
        GtkWidget *tree_swin;
578
        GtkWidget *treeview;
579
        GtkTreeStore *tree_store;
580
        GtkTreeSelection *selection;
581
        GtkTreeViewColumn *column;
582
        GtkCellRenderer *renderer;
583
        GtkWidget *list_vbox;
584
        GtkWidget *list_swin;
585
        GtkWidget *listview;
586
        GtkTreeStore *list_store;
587
        GtkWidget *paned;
588
        GtkWidget *hbox;
589
        GtkWidget *label;
590
        GtkWidget *entry;
591
        GtkWidget *statusbar;
592
        GtkWidget *hbbox;
593
        GtkWidget *hbbox1;
594
        GtkWidget *hbbox2;
595
        GtkWidget *hsbox;
596
        GtkWidget *to_btn;
597
        GtkWidget *cc_btn;
598
        GtkWidget *bcc_btn;
599
        GtkWidget *del_btn;
600
        GtkWidget *reg_btn;
601
        GtkWidget *lup_btn;
602
        GtkWidget *close_btn;
603
        GtkWidget *tree_popup;
604
        GtkWidget *list_popup;
605
        GtkItemFactory *tree_factory;
606
        GtkItemFactory *list_factory;
607
        GtkItemFactory *menu_factory;
608
        gint n_entries;
609
        GList *nodeIf;
610
611
        debug_print("Creating addressbook window...\n");
612
613
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
614
        gtk_window_set_title(GTK_WINDOW(window), _("Address book"));
615
        gtk_window_set_wmclass(GTK_WINDOW(window), "addressbook", "Sylpheed");
616
        gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, TRUE);
617
        gtk_widget_set_size_request(window, 620, 360);
618
        gtk_window_set_default_size(GTK_WINDOW(window),
619
                                    prefs_common.addressbook_width,
620
                                    prefs_common.addressbook_height);
621
        gtkut_window_move(GTK_WINDOW(window), prefs_common.addressbook_x,
622
                          prefs_common.addressbook_y);
623
        gtk_widget_realize(window);
624
625
        g_signal_connect(G_OBJECT(window), "delete_event",
626
                         G_CALLBACK(addressbook_close), NULL);
627
        g_signal_connect(G_OBJECT(window), "key_press_event",
628
                         G_CALLBACK(key_pressed), NULL);
629
        g_signal_connect(G_OBJECT(window), "size_allocate",
630
                         G_CALLBACK(size_allocated), NULL);
631
        MANAGE_WINDOW_SIGNALS_CONNECT(window);
632
633
        vbox = gtk_vbox_new(FALSE, 0);
634
        gtk_container_add(GTK_CONTAINER(window), vbox);
635
636
        n_entries = sizeof(addressbook_entries) /
637
                sizeof(addressbook_entries[0]);
638
        menubar = menubar_create(window, addressbook_entries, n_entries,
639
                                 "<AddressBook>", NULL);
640
        gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, TRUE, 0);
641
        menu_factory = gtk_item_factory_from_widget(menubar);
642
643
        spc_hbox = gtk_hbox_new(FALSE, 0);
644
        gtk_widget_set_size_request(spc_hbox, -1, BORDER_WIDTH);
645
        gtk_box_pack_start(GTK_BOX(vbox), spc_hbox, FALSE, FALSE, 0);
646
647
        vbox2 = gtk_vbox_new(FALSE, 4);
648
        gtk_box_pack_start(GTK_BOX(vbox), vbox2, TRUE, TRUE, 0);
649
650
        tree_swin = gtk_scrolled_window_new(NULL, NULL);
651
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(tree_swin),
652
                                       GTK_POLICY_AUTOMATIC,
653
                                       GTK_POLICY_AUTOMATIC);
654
        gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(tree_swin),
655
                                            GTK_SHADOW_IN);
656
        gtk_widget_set_size_request(tree_swin, prefs_common.addressbook_folder_width, -1);
657
658
        /* Address index */
659
        tree_store = gtk_tree_store_new(N_TREE_COLS, G_TYPE_STRING,
660
                                        G_TYPE_POINTER, GDK_TYPE_PIXBUF,
661
                                        GDK_TYPE_PIXBUF);
662
        gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(tree_store),
663
                                        COL_FOLDER_NAME,
664
                                        addressbook_tree_compare,
665
                                        NULL, NULL);
666
667
        treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(tree_store));
668
        g_object_unref(G_OBJECT(tree_store));
669
        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
670
        gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
671
        gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE);
672
        gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), FALSE);
673
        gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeview),
674
                                        COL_FOLDER_NAME);
675
        gtk_tree_view_set_reorderable(GTK_TREE_VIEW(treeview), FALSE);
676
677
        gtk_container_add(GTK_CONTAINER(tree_swin), treeview);
678
679
        column = gtk_tree_view_column_new();
680
        gtk_tree_view_column_set_spacing(column, 1);
681
        gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
682
        gtk_tree_view_column_set_resizable(column, TRUE);
683
684
        renderer = gtk_cell_renderer_pixbuf_new();
685
        g_object_set(renderer, "ypad", 0, NULL);
686
        gtk_tree_view_column_pack_start(column, renderer, FALSE);
687
        gtk_tree_view_column_set_title(column, _("Folder"));
688
        gtk_tree_view_column_set_attributes
689
                (column, renderer, "pixbuf", COL_PIXBUF,
690
                 "pixbuf-expander-open", COL_PIXBUF_OPEN,
691
                 "pixbuf-expander-closed", COL_PIXBUF, NULL);
692
693
        renderer = gtk_cell_renderer_text_new();
694
        g_object_set(renderer,
695
#if GTK_CHECK_VERSION(2, 6, 0)
696
                     "ellipsize", PANGO_ELLIPSIZE_END,
697
#endif
698
                     "ypad", 0, NULL);
699
        gtk_tree_view_column_pack_start(column, renderer, TRUE);
700
        gtk_tree_view_column_set_attributes(column, renderer,
701
                                            "text", COL_FOLDER_NAME, NULL);
702
703
        gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
704
        gtk_tree_view_set_expander_column(GTK_TREE_VIEW(treeview), column);
705
706
        gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(tree_store),
707
                                             COL_FOLDER_NAME,
708
                                             GTK_SORT_ASCENDING);
709
710
        g_signal_connect(G_OBJECT(tree_swin), "size-allocate",
711
                         G_CALLBACK(addressbook_folder_resized), NULL);
712
713
        g_signal_connect(G_OBJECT(selection), "changed",
714
                         G_CALLBACK(addressbook_tree_selection_changed), NULL);
715
        g_signal_connect(G_OBJECT(treeview), "button_press_event",
716
                         G_CALLBACK(addressbook_tree_button_pressed),
717
                         NULL);
718
        g_signal_connect(G_OBJECT(treeview), "button_release_event",
719
                         G_CALLBACK(addressbook_tree_button_released),
720
                         NULL);
721
722
        gtk_drag_dest_set(treeview, GTK_DEST_DEFAULT_ALL,
723
                          addressbook_drag_types, N_DRAG_TYPES,
724
                          GDK_ACTION_MOVE | GDK_ACTION_COPY);
725
        g_signal_connect(G_OBJECT(treeview), "drag-motion",
726
                         G_CALLBACK(addressbook_drag_motion), NULL);
727
        g_signal_connect(G_OBJECT(treeview), "drag-leave",
728
                         G_CALLBACK(addressbook_drag_leave), NULL);
729
        g_signal_connect(G_OBJECT(treeview), "drag-data-received",
730
                         G_CALLBACK(addressbook_drag_received), NULL);
731
732
        list_vbox = gtk_vbox_new(FALSE, 4);
733
734
        list_swin = gtk_scrolled_window_new(NULL, NULL);
735
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(list_swin),
736
                                       GTK_POLICY_AUTOMATIC,
737
                                       GTK_POLICY_AUTOMATIC);
738
        gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(list_swin),
739
                                            GTK_SHADOW_IN);
740
        gtk_box_pack_start(GTK_BOX(list_vbox), list_swin, TRUE, TRUE, 0);
741
742
        /* Address list */
743
        list_store = gtk_tree_store_new(N_LIST_COLS, G_TYPE_STRING,
744
                                        G_TYPE_STRING, G_TYPE_STRING,
745
                                        G_TYPE_POINTER, GDK_TYPE_PIXBUF);
746
        gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(list_store),
747
                                        COL_NAME,
748
                                        addressbook_list_name_compare,
749
                                        NULL, NULL);
750
        gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(list_store),
751
                                        COL_ADDRESS,
752
                                        addressbook_list_address_compare,
753
                                        NULL, NULL);
754
        gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(list_store),
755
                                        COL_REMARKS,
756
                                        addressbook_list_remarks_compare,
757
                                        NULL, NULL);
758
759
        listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store));
760
        g_object_unref(G_OBJECT(list_store));
761
        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(listview));
762
        gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
763
        gtk_tree_selection_set_select_function
764
                (selection, addressbook_list_select_func, NULL, NULL);
765
        gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(listview), TRUE);
766
        gtk_tree_view_set_search_column(GTK_TREE_VIEW(listview), COL_NAME);
767
        gtk_tree_view_set_reorderable(GTK_TREE_VIEW(listview), FALSE);
768
        gtk_container_add(GTK_CONTAINER(list_swin), listview);
769
770
        column = gtk_tree_view_column_new();
771
        gtk_tree_view_column_set_spacing(column, 1);
772
        gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
773
        gtk_tree_view_column_set_fixed_width
774
                (column, prefs_common.addressbook_col_name);
775
        gtk_tree_view_column_set_resizable(column, TRUE);
776
        gtk_tree_view_column_set_title(column, _("Name"));
777
778
        renderer = gtk_cell_renderer_pixbuf_new();
779
        g_object_set(renderer, "ypad", 0, NULL);
780
        gtk_tree_view_column_pack_start(column, renderer, FALSE);
781
        gtk_tree_view_column_set_attributes(column, renderer,
782
                                            "pixbuf", COL_L_PIXBUF, NULL);
783
784
        renderer = gtk_cell_renderer_text_new();
785
        g_object_set(renderer,
786
#if GTK_CHECK_VERSION(2, 6, 0)
787
                     "ellipsize", PANGO_ELLIPSIZE_END,
788
#endif
789
                     "ypad", 0, NULL);
790
        gtk_tree_view_column_pack_start(column, renderer, TRUE);
791
        gtk_tree_view_column_set_attributes(column, renderer,
792
                                            "text", COL_NAME, NULL);
793
794
        gtk_tree_view_column_set_sort_column_id(column, COL_NAME);
795
        gtk_tree_view_append_column(GTK_TREE_VIEW(listview), column);
796
        gtk_tree_view_set_expander_column(GTK_TREE_VIEW(listview), column);
797
        g_signal_connect(G_OBJECT(column->button), "size-allocate",
798
                         G_CALLBACK(addressbook_col_resized),
799
                         GINT_TO_POINTER(COL_NAME));
800
801
        renderer = gtk_cell_renderer_text_new();
802
        g_object_set(renderer,
803
#if GTK_CHECK_VERSION(2, 6, 0)
804
                     "ellipsize", PANGO_ELLIPSIZE_END,
805
#endif
806
                     "ypad", 0, NULL);
807
        column = gtk_tree_view_column_new_with_attributes
808
                (_("E-Mail address"), renderer, "text", COL_ADDRESS, NULL);
809
        gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
810
        gtk_tree_view_column_set_fixed_width
811
                (column, prefs_common.addressbook_col_addr);
812
        gtk_tree_view_column_set_resizable(column, TRUE);
813
        gtk_tree_view_column_set_sort_column_id(column, COL_ADDRESS);
814
        gtk_tree_view_append_column(GTK_TREE_VIEW(listview), column);
815
        g_signal_connect(G_OBJECT(column->button), "size-allocate",
816
                         G_CALLBACK(addressbook_col_resized),
817
                         GINT_TO_POINTER(COL_ADDRESS));
818
819
        renderer = gtk_cell_renderer_text_new();
820
        g_object_set(renderer,
821
#if GTK_CHECK_VERSION(2, 6, 0)
822
                     "ellipsize", PANGO_ELLIPSIZE_END,
823
#endif
824
                     "ypad", 0, NULL);
825
        column = gtk_tree_view_column_new_with_attributes
826
                (_("Remarks"), renderer, "text", COL_REMARKS, NULL);
827
        gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
828
        gtk_tree_view_column_set_resizable(column, TRUE);
829
        gtk_tree_view_column_set_sort_column_id(column, COL_REMARKS);
830
        gtk_tree_view_append_column(GTK_TREE_VIEW(listview), column);
831
        g_signal_connect(G_OBJECT(column->button), "size-allocate",
832
                         G_CALLBACK(addressbook_col_resized),
833
                         GINT_TO_POINTER(COL_REMARKS));
834
835
        gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(list_store),
836
                                             COL_NAME, GTK_SORT_ASCENDING);
837
838
        g_signal_connect(G_OBJECT(selection), "changed",
839
                         G_CALLBACK(addressbook_list_selection_changed), NULL);
840
        g_signal_connect(G_OBJECT(listview), "button_press_event",
841
                         G_CALLBACK(addressbook_list_button_pressed),
842
                         NULL);
843
        g_signal_connect(G_OBJECT(listview), "button_release_event",
844
                         G_CALLBACK(addressbook_list_button_released),
845
                         NULL);
846
        g_signal_connect(G_OBJECT(listview), "row_expanded",
847
                         G_CALLBACK(addressbook_person_expand_node), NULL);
848
        g_signal_connect(G_OBJECT(listview), "row_collapsed",
849
                         G_CALLBACK(addressbook_person_collapse_node), NULL);
850
851
        gtk_tree_view_enable_model_drag_source
852
                (GTK_TREE_VIEW(listview), GDK_BUTTON1_MASK,
853
                 addressbook_drag_types, N_DRAG_TYPES,
854
                 GDK_ACTION_MOVE | GDK_ACTION_COPY);
855
856
        g_signal_connect_after(G_OBJECT(listview), "drag-begin",
857
                               G_CALLBACK(addressbook_drag_begin), NULL);
858
        g_signal_connect_after(G_OBJECT(listview), "drag-end",
859
                               G_CALLBACK(addressbook_drag_end), NULL);
860
        g_signal_connect(G_OBJECT(listview), "drag-data-get",
861
                         G_CALLBACK(addressbook_drag_data_get), NULL);
862
863
        hbox = gtk_hbox_new(FALSE, 4);
864
        gtk_box_pack_start(GTK_BOX(list_vbox), hbox, FALSE, FALSE, 0);
865
866
        label = gtk_label_new(_("Search:"));
867
        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
868
869
        entry = gtk_entry_new();
870
        gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
871
872
        address_completion_register_entry(GTK_ENTRY(entry));
873
874
#if 0
875
        g_signal_connect(G_OBJECT(entry), "changed",
876
                         G_CALLBACK(addressbook_entry_changed), NULL);
877
#endif
878
        g_signal_connect(G_OBJECT(entry), "activate",
879
                         G_CALLBACK(addressbook_entry_activated), NULL);
880
881
        paned = gtk_hpaned_new();
882
        gtk_box_pack_start(GTK_BOX(vbox2), paned, TRUE, TRUE, 0);
883
        gtk_paned_add1(GTK_PANED(paned), tree_swin);
884
        gtk_paned_add2(GTK_PANED(paned), list_vbox);
885
886
        /* Status bar */
887
        hsbox = gtk_hbox_new(FALSE, 0);
888
        gtk_box_pack_end(GTK_BOX(vbox), hsbox, FALSE, FALSE, 0);
889
        statusbar = gtk_statusbar_new();
890
        gtk_box_pack_start(GTK_BOX(hsbox), statusbar, TRUE, TRUE, 0);
891
892
        hbbox = gtk_hbox_new(FALSE, 4);
893
        gtk_box_pack_end(GTK_BOX(vbox), hbbox, FALSE, FALSE, 0);
894
895
        /* Button panel */
896
        hbbox1 = gtk_hbutton_box_new();
897
        gtk_button_box_set_layout(GTK_BUTTON_BOX(hbbox1), GTK_BUTTONBOX_END);
898
        gtk_box_set_spacing(GTK_BOX(hbbox1), 4);
899
        gtk_container_set_border_width(GTK_CONTAINER(hbbox1), 4);
900
        gtk_button_box_set_child_size(GTK_BUTTON_BOX(hbbox1), 64, -1);
901
        gtk_box_pack_end(GTK_BOX(hbbox), hbbox1, FALSE, FALSE, 0);
902
903
        to_btn = gtk_button_new_with_label
904
                (prefs_common.trans_hdr ? _("To:") : "To:");
905
        GTK_WIDGET_SET_FLAGS(to_btn, GTK_CAN_DEFAULT);
906
        gtk_box_pack_start(GTK_BOX(hbbox1), to_btn, TRUE, TRUE, 0);
907
        cc_btn = gtk_button_new_with_label
908
                (prefs_common.trans_hdr ? _("Cc:") : "Cc:");
909
        GTK_WIDGET_SET_FLAGS(cc_btn, GTK_CAN_DEFAULT);
910
        gtk_box_pack_start(GTK_BOX(hbbox1), cc_btn, TRUE, TRUE, 0);
911
        bcc_btn = gtk_button_new_with_label
912
                (prefs_common.trans_hdr ? _("Bcc:") : "Bcc:");
913
        GTK_WIDGET_SET_FLAGS(bcc_btn, GTK_CAN_DEFAULT);
914
        gtk_box_pack_start(GTK_BOX(hbbox1), bcc_btn, TRUE, TRUE, 0);
915
916
        g_signal_connect(G_OBJECT(to_btn), "clicked",
917
                         G_CALLBACK(addressbook_to_clicked),
918
                         GINT_TO_POINTER(COMPOSE_ENTRY_TO));
919
        g_signal_connect(G_OBJECT(cc_btn), "clicked",
920
                         G_CALLBACK(addressbook_to_clicked),
921
                         GINT_TO_POINTER(COMPOSE_ENTRY_CC));
922
        g_signal_connect(G_OBJECT(bcc_btn), "clicked",
923
                         G_CALLBACK(addressbook_to_clicked),
924
                         GINT_TO_POINTER(COMPOSE_ENTRY_BCC));
925
926
        hbbox2 = gtk_hbutton_box_new();
927
        gtk_button_box_set_layout(GTK_BUTTON_BOX(hbbox2), GTK_BUTTONBOX_END);
928
        gtk_box_set_spacing(GTK_BOX(hbbox2), 4);
929
        gtk_container_set_border_width(GTK_CONTAINER(hbbox2), 4);
930
        gtk_button_box_set_child_size(GTK_BUTTON_BOX(hbbox2), 64, -1);
931
        gtk_box_pack_end(GTK_BOX(hbbox), hbbox2, TRUE, TRUE, 0);
932
933
        del_btn = gtk_button_new_with_label(_("Delete"));
934
        GTK_WIDGET_SET_FLAGS(del_btn, GTK_CAN_DEFAULT);
935
        gtk_box_pack_start(GTK_BOX(hbbox2), del_btn, TRUE, TRUE, 0);
936
        reg_btn = gtk_button_new_with_label(_("Add"));
937
        GTK_WIDGET_SET_FLAGS(reg_btn, GTK_CAN_DEFAULT);
938
        gtk_box_pack_start(GTK_BOX(hbbox2), reg_btn, TRUE, TRUE, 0);
939
        lup_btn = gtk_button_new_with_label(_("Search"));
940
        GTK_WIDGET_SET_FLAGS(lup_btn, GTK_CAN_DEFAULT);
941
        gtk_box_pack_start(GTK_BOX(hbbox2), lup_btn, TRUE, TRUE, 0);
942
        close_btn = gtk_button_new_with_mnemonic(_("_Close"));
943
        GTK_WIDGET_SET_FLAGS(close_btn, GTK_CAN_DEFAULT);
944
        gtk_box_pack_start(GTK_BOX(hbbox2), close_btn, TRUE, TRUE, 0);
945
        gtk_button_box_set_child_secondary(GTK_BUTTON_BOX(hbbox2), close_btn,
946
                                           TRUE);
947
948
        g_signal_connect(G_OBJECT(del_btn), "clicked",
949
                         G_CALLBACK(addressbook_del_clicked), NULL);
950
        g_signal_connect(G_OBJECT(reg_btn), "clicked",
951
                         G_CALLBACK(addressbook_reg_clicked), NULL);
952
        g_signal_connect(G_OBJECT(lup_btn), "clicked",
953
                         G_CALLBACK(addressbook_lup_clicked), NULL);
954
        g_signal_connect(G_OBJECT(close_btn), "clicked",
955
                         G_CALLBACK(addressbook_close_clicked), NULL);
956
957
        /* Build icons for interface */
958
        stock_pixbuf_gdk(window, STOCK_PIXMAP_INTERFACE, &interfacepix);
959
        /* Build control tables */
960
        addrbookctl_build_map(window);
961
        addrbookctl_build_iflist();
962
        addrbookctl_build_ifselect();
963
964
        /* Add each interface into the tree as a root level folder */
965
        nodeIf = _addressInterfaceList_;
966
        while( nodeIf ) {
967
                AdapterInterface *adapter = nodeIf->data;
968
                AddressInterface *iface = adapter->iface;
969
970
                nodeIf = g_list_next(nodeIf);
971
972
                if(iface->useInterface) {
973
                        AddressTypeControlItem *atci = adapter->atci;
974
                        gchar *text = atci->displayName;
975
                        GtkTreeIter iter;
976
                        GtkTreePath *path;
977
978
                        debug_print("addressbook_create: adapter: %s\n", text);
979
                        gtk_tree_store_append(tree_store, &iter, NULL);
980
                        gtk_tree_store_set(tree_store, &iter,
981
                                           COL_FOLDER_NAME, text,
982
                                           COL_OBJ, adapter,
983
                                           COL_PIXBUF, interfacepix,
984
                                           COL_PIXBUF_OPEN, interfacepix, -1);
985
                        path = gtk_tree_model_get_path(GTK_TREE_MODEL(tree_store), &iter);
986
                        adapter->tree_row = gtk_tree_row_reference_new(GTK_TREE_MODEL(tree_store), path);
987
                        gtk_tree_path_free(path);
988
                }
989
        }
990
991
        /* Popup menu */
992
        n_entries = sizeof(addressbook_tree_popup_entries) /
993
                sizeof(addressbook_tree_popup_entries[0]);
994
        tree_popup = menu_create_items(addressbook_tree_popup_entries,
995
                                       n_entries,
996
                                       "<AddressBookTree>", &tree_factory,
997
                                       NULL);
998
        g_signal_connect(G_OBJECT(tree_popup), "selection_done",
999
                         G_CALLBACK(addressbook_popup_close), NULL);
1000
        n_entries = sizeof(addressbook_list_popup_entries) /
1001
                sizeof(addressbook_list_popup_entries[0]);
1002
        list_popup = menu_create_items(addressbook_list_popup_entries,
1003
                                       n_entries,
1004
                                       "<AddressBookList>", &list_factory,
1005
                                       NULL);
1006
1007
        addrbook.window     = window;
1008
        addrbook.menubar    = menubar;
1009
        addrbook.treeview   = treeview;
1010
        addrbook.listview   = listview;
1011
        addrbook.entry      = entry;
1012
        addrbook.statusbar  = statusbar;
1013
        addrbook.status_cid = gtk_statusbar_get_context_id(GTK_STATUSBAR(statusbar), "Address Book Window");
1014
1015
        addrbook.to_btn  = to_btn;
1016
        addrbook.cc_btn  = cc_btn;
1017
        addrbook.bcc_btn = bcc_btn;
1018
        addrbook.del_btn = del_btn;
1019
        addrbook.reg_btn = reg_btn;
1020
        addrbook.lup_btn = lup_btn;
1021
        addrbook.close_btn = close_btn;
1022
1023
        addrbook.tree_popup   = tree_popup;
1024
        addrbook.list_popup   = list_popup;
1025
        addrbook.tree_factory = tree_factory;
1026
        addrbook.list_factory = list_factory;
1027
        addrbook.menu_factory = menu_factory;
1028
1029
        addrbook.tree_selected = NULL;
1030
        addrbook.list_selected = NULL;
1031
        address_completion_start(window);
1032
        gtk_widget_show_all(window);
1033
}
1034
1035
static gint addressbook_close(void)
1036
{
1037
        gtkut_widget_get_uposition(addrbook.window,
1038
                                   &prefs_common.addressbook_x,
1039
                                   &prefs_common.addressbook_y);
1040
        gtk_widget_hide(addrbook.window);
1041
        addressbook_export_to_file();
1042
        return TRUE;
1043
}
1044
1045
static void addressbook_status_show(const gchar *msg)
1046
{
1047
        if (addrbook.statusbar != NULL) {
1048
                gtk_statusbar_pop(GTK_STATUSBAR(addrbook.statusbar), addrbook.status_cid);
1049
                if (msg) {
1050
                        gtk_statusbar_push(GTK_STATUSBAR(addrbook.statusbar), addrbook.status_cid, msg);
1051
                }
1052
        }
1053
}
1054
1055
static void addressbook_ds_show_message(AddressDataSource *ds)
1056
{
1057
        gint retVal;
1058
        gchar *name;
1059
        gchar msgbuf[ADDRESSBOOK_MSGBUF_SIZE] = "";
1060
1061
        if (ds) {
1062
                name = addrindex_ds_get_name(ds);
1063
                if (ds->type == ADDR_IF_BOOK && name &&
1064
                    !strcmp(name, ADDR_DS_AUTOREG))
1065
                        name = _("Auto-registered address");
1066
                retVal = addrindex_ds_get_status_code(ds);
1067
                if (retVal == MGU_SUCCESS) {
1068
                        g_snprintf(msgbuf, sizeof(msgbuf), "%s", name);
1069
                } else {
1070
                        g_snprintf(msgbuf, sizeof(msgbuf), "%s: %s",
1071
                                   name, mgu_error2string(retVal));
1072
                }
1073
        }
1074
1075
        addressbook_status_show(msgbuf);
1076
}
1077
1078
/*
1079
* Delete one or more objects from address list.
1080
*/
1081
static void addressbook_del_clicked(GtkButton *button, gpointer data)
1082
{
1083
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
1084
        GtkTreeSelection *selection;
1085
        GtkTreeModel *model;
1086
        GtkTreeIter iter;
1087
        GtkTreeView *listview = GTK_TREE_VIEW(addrbook.listview);
1088
        GtkTreeModel *lmodel;
1089
        GtkTreeIter list_sel;
1090
        AddressObject *pobj = NULL;
1091
        AddressObject *obj = NULL;
1092
        AdapterDSource *ads = NULL;
1093
        gboolean procFlag;
1094
        AlertValue aval;
1095
        AddressBookFile *abf = NULL;
1096
        AddressDataSource *ds = NULL;
1097
1098
        if (!addrbook.tree_opened)
1099
                return;
1100
1101
        model = gtk_tree_view_get_model(treeview);
1102
        lmodel = gtk_tree_view_get_model(listview);
1103
        selection = gtk_tree_view_get_selection(treeview);
1104
1105
        gtkut_tree_row_reference_get_iter(model, addrbook.tree_opened, &iter);
1106
        gtk_tree_model_get(model, &iter, COL_OBJ, &pobj, -1);
1107
        g_return_if_fail(pobj != NULL);
1108
1109
        gtkut_tree_row_reference_get_iter(lmodel, addrbook.list_selected,
1110
                                          &list_sel);
1111
        gtk_tree_model_get(lmodel, &list_sel, COL_L_OBJ, &obj, -1);
1112
        if (obj == NULL)
1113
                return;
1114
        if (!gtk_tree_selection_get_selected(selection, NULL, &iter))
1115
                return;
1116
        ds = addressbook_find_datasource(&iter);
1117
        if (ds == NULL)
1118
                return;
1119
1120
        procFlag = FALSE;
1121
        if (pobj->type == ADDR_DATASOURCE) {
1122
                ads = ADAPTER_DSOURCE(pobj);
1123
                if(ads->subType == ADDR_BOOK)
1124
                        procFlag = TRUE;
1125
        }
1126
        else if (pobj->type == ADDR_ITEM_FOLDER) {
1127
                procFlag = TRUE;
1128
        } else if (pobj->type == ADDR_ITEM_GROUP) {
1129
                procFlag = TRUE;
1130
        }
1131
        if (!procFlag)
1132
                return;
1133
        abf = ds->rawDataSource;
1134
        if (abf == NULL)
1135
                return;
1136
1137
        /* Confirm deletion */
1138
        aval = alertpanel(_("Delete address(es)"),
1139
                          _("Really delete the address(es)?"),
1140
                          GTK_STOCK_YES, GTK_STOCK_NO, NULL);
1141
        if (aval != G_ALERTDEFAULT)
1142
                return;
1143
1144
        /* Process deletions */
1145
        if (pobj->type == ADDR_DATASOURCE || pobj->type == ADDR_ITEM_FOLDER) {
1146
                /* Items inside folders */
1147
                GList *node;
1148
1149
                node = _addressListSelection_;
1150
                while (node) {
1151
                        AddrItemObject *aio = node->data;
1152
                        node = g_list_next(node);
1153
                        if (aio->type == ADDR_ITEM_GROUP) {
1154
                                ItemGroup *item = (ItemGroup *)aio;
1155
                                GtkTreeIter giter;
1156
1157
                                addressbook_find_group_node(&iter, &giter, item);
1158
                                item = addrbook_remove_group(abf, item);
1159
                                if (item) {
1160
                                        addritem_free_item_group(item);
1161
                                        item = NULL;
1162
                                }
1163
                                /* Remove group from parent node */
1164
                                gtk_tree_store_remove(GTK_TREE_STORE(model), &giter);
1165
                        } else if (aio->type == ADDR_ITEM_PERSON) {
1166
                                ItemPerson *item = (ItemPerson *)aio;
1167
1168
                                if (_clipObjectList_) {
1169
                                        _clipObjectList_ = g_list_remove(_clipObjectList_, item);
1170
                                }
1171
                                item = addrbook_remove_person(abf, item);
1172
                                if (item) {
1173
                                        addritem_free_item_person(item);
1174
                                        item = NULL;
1175
                                }
1176
                        } else if (aio->type == ADDR_ITEM_EMAIL) {
1177
                                ItemEMail *item = (ItemEMail *)aio;
1178
                                ItemPerson *person = (ItemPerson *)ADDRITEM_PARENT(item);
1179
1180
                                item = addrbook_person_remove_email(abf, person, item);
1181
                                if (item) {
1182
                                        addritem_free_item_email(item);
1183
                                        item = NULL;
1184
                                }
1185
                        }
1186
                }
1187
                addressbook_list_select_clear();
1188
                addressbook_reopen();
1189
                addressbook_modified();
1190
                return;
1191
        } else if (pobj->type == ADDR_ITEM_GROUP) {
1192
                /* Items inside groups */
1193
                GList *node;
1194
                ItemGroup *group = ADAPTER_GROUP(pobj)->itemGroup;
1195
1196
                node = _addressListSelection_;
1197
                while (node) {
1198
                        AddrItemObject *aio = node->data;
1199
                        node = g_list_next(node);
1200
                        if (aio->type == ADDR_ITEM_EMAIL) {
1201
                                ItemEMail *item = (ItemEMail *)aio;
1202
                                item = addrbook_group_remove_email(abf, group, item);
1203
                        }
1204
                }
1205
                addressbook_list_select_clear();
1206
                addressbook_reopen();
1207
                return;
1208
        }
1209
1210
        gtk_tree_store_remove(GTK_TREE_STORE(lmodel), &list_sel);
1211
        addressbook_list_select_remove(obj);
1212
}
1213
1214
static void addressbook_reg_clicked(GtkButton *button, gpointer data)
1215
{
1216
        addressbook_new_address_cb(NULL, 0, NULL);
1217
}
1218
1219
gchar *addressbook_format_address(AddressObject *obj)
1220
{
1221
        gchar *buf = NULL;
1222
        gchar *name = NULL;
1223
        gchar *address = NULL;
1224
1225
        if( obj->type == ADDR_ITEM_EMAIL ) {
1226
                ItemPerson *person = NULL;
1227
                ItemEMail *email = ( ItemEMail * ) obj;
1228
1229
                person = ( ItemPerson * ) ADDRITEM_PARENT(email);
1230
                if( email->address ) {
1231
                        if( ADDRITEM_NAME(email) ) {
1232
                                name = ADDRITEM_NAME(email);
1233
                                if( *name == '\0' ) {
1234
                                        name = ADDRITEM_NAME(person);
1235
                                }
1236
                        }
1237
                        else if( person && ADDRITEM_NAME(person) ) {
1238
                                name = ADDRITEM_NAME(person);
1239
                        }
1240
                        else {
1241
                                buf = g_strdup( email->address );
1242
                        }
1243
                        address = email->address;
1244
                }
1245
        }
1246
        else if( obj->type == ADDR_ITEM_PERSON ) {
1247
                ItemPerson *person = ( ItemPerson * ) obj;
1248
                GList *node = person->listEMail;
1249
1250
                name = ADDRITEM_NAME(person);
1251
                if( node ) {
1252
                        ItemEMail *email = ( ItemEMail * ) node->data;
1253
                        address = email->address;
1254
                }
1255
        }
1256
        if( address ) {
1257
                if( !prefs_common.always_add_address_only &&
1258
                    name && name[0] != '\0' ) {
1259
                        if( name[0] != '"' && strpbrk( name, ",.[]<>" ) != NULL )
1260
                                buf = g_strdup_printf( "\"%s\" <%s>", name, address );
1261
                        else
1262
                                buf = g_strdup_printf( "%s <%s>", name, address );
1263
                }
1264
                else {
1265
                        buf = g_strdup( address );
1266
                }
1267
        }
1268
1269
        return buf;
1270
}
1271
1272
static void addressbook_to_clicked(GtkButton *button, gpointer data)
1273
{
1274
        GList *node = _addressListSelection_;
1275
        gboolean new_compose = FALSE;
1276
1277
        if (!addrbook.target_compose) {
1278
                new_compose = TRUE;
1279
                addrbook.target_compose = compose_new(NULL, NULL, NULL, NULL);
1280
                if (!addrbook.target_compose)
1281
                        return;
1282
        }
1283
1284
        if (new_compose)
1285
                compose_block_modified(addrbook.target_compose);
1286
1287
        while( node ) {
1288
                AddressObject *obj = node->data;
1289
                Compose *compose = addrbook.target_compose;
1290
1291
                node = g_list_next( node );
1292
                if( obj->type == ADDR_ITEM_PERSON || obj->type == ADDR_ITEM_EMAIL ) {
1293
                        gchar *addr = addressbook_format_address( obj );
1294
                        compose_entry_append( compose, addr, (ComposeEntryType) data );
1295
                        g_free( addr );
1296
                        addr = NULL;
1297
                }
1298
                else if( obj->type == ADDR_ITEM_GROUP ) {
1299
                        ItemGroup *group = ( ItemGroup * ) obj;
1300
                        GList *nodeMail = group->listEMail;
1301
                        while( nodeMail ) {
1302
                                ItemEMail *email = nodeMail->data;
1303
                                gchar *addr = addressbook_format_address( ( AddressObject * ) email );
1304
                                compose_entry_append( compose, addr, (ComposeEntryType) data );
1305
                                g_free( addr );
1306
                                nodeMail = g_list_next( nodeMail );
1307
                        }
1308
                }
1309
        }
1310
1311
        if (new_compose)
1312
                compose_unblock_modified(addrbook.target_compose);
1313
}
1314
1315
static void addressbook_menuitem_set_sensitive(void)
1316
{
1317
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
1318
        GtkTreeView *listview = GTK_TREE_VIEW(addrbook.listview);
1319
        GtkTreeSelection *selection;
1320
        GtkTreeSelection *lselection;
1321
        GtkTreeModel *model;
1322
        GtkTreeModel *lmodel;
1323
        GtkTreeIter iter;
1324
        GtkTreeIter liter;
1325
        gboolean canAdd = FALSE;
1326
        gboolean canEditTree = TRUE;
1327
        gboolean canEditAddress = FALSE;
1328
        gboolean canDelete = FALSE;
1329
        gboolean canLookup = FALSE;
1330
        gboolean canCopy = FALSE;
1331
        gboolean canPaste = FALSE;
1332
        gboolean hasListSelection = _addressListSelection_ != NULL;
1333
        AddressTypeControlItem *atci = NULL;
1334
        AddressDataSource *ds = NULL;
1335
        AddressInterface *iface = NULL;
1336
        AddressObject *pobj = NULL;
1337
        AddressObject *obj = NULL;
1338
1339
        menu_set_sensitive(addrbook.menu_factory, "/File/New Book", FALSE);
1340
        menu_set_sensitive(addrbook.menu_factory, "/File/New vCard", FALSE);
1341
#ifdef USE_JPILOT
1342
        menu_set_sensitive(addrbook.menu_factory, "/File/New JPilot", FALSE);
1343
#endif
1344
#ifdef USE_LDAP
1345
        menu_set_sensitive(addrbook.menu_factory, "/File/New LDAP Server", FALSE);
1346
#endif
1347
        menu_set_insensitive_all(GTK_MENU_SHELL(addrbook.tree_popup));
1348
        menu_set_insensitive_all(GTK_MENU_SHELL(addrbook.list_popup));
1349
1350
        selection = gtk_tree_view_get_selection(treeview);
1351
        if (!gtk_tree_selection_get_selected(selection, &model, &iter))
1352
                return;
1353
1354
        gtk_tree_model_get(model, &iter, COL_OBJ, &pobj, -1);
1355
        if (pobj == NULL)
1356
                return;
1357
1358
        lmodel = gtk_tree_view_get_model(listview);
1359
        lselection = gtk_tree_view_get_selection(listview);
1360
1361
        if (addrbook.list_selected) {
1362
                if (gtkut_tree_row_reference_get_iter(lmodel, addrbook.list_selected, &liter))
1363
                        gtk_tree_model_get(lmodel, &liter, COL_L_OBJ, &obj, -1);
1364
        }
1365
1366
        if (pobj->type == ADDR_INTERFACE) {
1367
                AdapterInterface *adapter = ADAPTER_INTERFACE(pobj);
1368
1369
                iface = adapter->iface;
1370
                if (iface && iface->haveLibrary) {
1371
                        /* Enable appropriate File / New command */
1372
                        atci = adapter->atci;
1373
                        menu_set_sensitive(addrbook.menu_factory, atci->menuCommand, TRUE);
1374
                }
1375
                canEditTree = FALSE;
1376
        } else if (pobj->type == ADDR_DATASOURCE) {
1377
                AdapterDSource *ads = ADAPTER_DSOURCE(pobj);
1378
1379
                ds = ads->dataSource;
1380
                iface = ds->iface;
1381
                if (!iface->readOnly) {
1382
                        canAdd = canEditAddress = TRUE;
1383
                }
1384
                if (!iface->haveLibrary) {
1385
                        canAdd = canEditAddress = FALSE;
1386
                }
1387
#ifdef USE_LDAP
1388
                if (ads->subType == ADDR_LDAP) {
1389
                        if (iface->haveLibrary && ds->rawDataSource)
1390
                                canLookup = TRUE;
1391
                } else
1392
#endif
1393
                        canLookup = TRUE;
1394
                if (ads->subType == ADDR_BOOK && pobj->name &&
1395
                    !strcmp(pobj->name, ADDR_DS_AUTOREG))
1396
                        canEditTree = FALSE;
1397
        } else if (pobj->type == ADDR_ITEM_FOLDER) {
1398
                ds = addressbook_find_datasource(&iter);
1399
                if (ds) {
1400
                        iface = ds->iface;
1401
                        if (!iface->readOnly) {
1402
                                canAdd = canEditAddress = TRUE;
1403
                        }
1404
                        canLookup = TRUE;
1405
                }
1406
        } else if (pobj->type == ADDR_ITEM_GROUP) {
1407
                ds = addressbook_find_datasource(&iter);
1408
                if (ds) {
1409
                        iface = ds->iface;
1410
                        if (!iface->readOnly) {
1411
                                canEditAddress = TRUE;
1412
                        }
1413
                        canLookup = TRUE;
1414
                }
1415
        }
1416
1417
        if (obj == NULL)
1418
                canEditAddress = FALSE;
1419
        canDelete = canEditAddress;
1420
        if (gtk_tree_selection_count_selected_rows(lselection) > 1)
1421
                canEditAddress = FALSE;
1422
        if (_addressListSelection_) {
1423
                GList *cur;
1424
                AddressObject *item;
1425
1426
                for (cur = _addressListSelection_; cur != NULL; cur = cur->next) {
1427
                        item = cur->data;
1428
                        if (item->type == ADDR_ITEM_PERSON) {
1429
                                canCopy = TRUE;
1430
                                break;
1431
                        }
1432
                }
1433
        }
1434
        if (_clipObjectList_ && canAdd)
1435
                canPaste = TRUE;
1436
1437
        /* Enable add */
1438
        menu_set_sensitive(addrbook.menu_factory, "/Address/New Address", canAdd);
1439
        menu_set_sensitive(addrbook.menu_factory, "/Address/New Folder", canAdd);
1440
        menu_set_sensitive(addrbook.menu_factory, "/Address/New Group", canAdd);
1441
1442
        menu_set_sensitive(addrbook.menu_factory, "/Address/Add to recipient", hasListSelection);
1443
        menu_set_sensitive(addrbook.menu_factory, "/Address/Add to Cc", hasListSelection);
1444
        menu_set_sensitive(addrbook.menu_factory, "/Address/Add to Bcc", hasListSelection);
1445
1446
        /* Enable edit */
1447
        menu_set_sensitive(addrbook.menu_factory, "/Address/Edit", canEditAddress);
1448
        menu_set_sensitive(addrbook.menu_factory, "/Address/Delete", canDelete);
1449
1450
        menu_set_sensitive(addrbook.menu_factory, "/File/Edit", canEditTree);
1451
        menu_set_sensitive(addrbook.menu_factory, "/File/Delete", canEditTree);
1452
1453
        menu_set_sensitive(addrbook.menu_factory, "/Edit/Copy",   canCopy);
1454
        menu_set_sensitive(addrbook.menu_factory, "/Edit/Paste",  canPaste);
1455
1456
        /* Popup menu */
1457
        menu_set_sensitive(addrbook.tree_factory, "/New Address", canAdd);
1458
        menu_set_sensitive(addrbook.tree_factory, "/New Folder", canAdd);
1459
        menu_set_sensitive(addrbook.tree_factory, "/New Group", canAdd);
1460
        menu_set_sensitive(addrbook.tree_factory, "/Edit", canEditTree);
1461
        menu_set_sensitive(addrbook.tree_factory, "/Delete", canEditTree);
1462
1463
        menu_set_sensitive(addrbook.list_factory, "/New Address", canAdd);
1464
        menu_set_sensitive(addrbook.list_factory, "/New Folder", canAdd);
1465
        menu_set_sensitive(addrbook.list_factory, "/New Group", canAdd);
1466
        menu_set_sensitive(addrbook.list_factory, "/Add to recipient", hasListSelection);
1467
        menu_set_sensitive(addrbook.list_factory, "/Add to Cc", hasListSelection);
1468
        menu_set_sensitive(addrbook.list_factory, "/Add to Bcc", hasListSelection);
1469
        menu_set_sensitive(addrbook.list_factory, "/Edit", canEditAddress);
1470
        menu_set_sensitive(addrbook.list_factory, "/Delete", canDelete);
1471
        menu_set_sensitive(addrbook.list_factory, "/Copy", canCopy);
1472
        menu_set_sensitive(addrbook.list_factory, "/Paste", canPaste);
1473
1474
        /* Buttons */
1475
        gtk_widget_set_sensitive(addrbook.to_btn, hasListSelection);
1476
        gtk_widget_set_sensitive(addrbook.cc_btn, hasListSelection);
1477
        gtk_widget_set_sensitive(addrbook.bcc_btn, hasListSelection);
1478
        gtk_widget_set_sensitive(addrbook.reg_btn, canAdd);
1479
        gtk_widget_set_sensitive(addrbook.del_btn, canDelete);
1480
        gtk_widget_set_sensitive(addrbook.lup_btn, canLookup);
1481
}
1482
1483
static void addressbook_tree_selection_changed(GtkTreeSelection *selection,
1484
                                               gpointer data)
1485
{
1486
        GtkTreeModel *model;
1487
        GtkTreeModel *lmodel;
1488
        GtkTreeIter iter;
1489
        GtkTreePath *path;
1490
        AddressObject *obj = NULL;
1491
        AdapterDSource *ads = NULL;
1492
        AddressDataSource *ds = NULL;
1493
        ItemFolder *rootFolder = NULL;
1494
1495
        debug_print("addressbook_tree_selection_changed\n");
1496
1497
        if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
1498
                debug_print("addressbook_tree_selection_changed: no selection\n");
1499
                gtk_tree_row_reference_free(addrbook.tree_selected);
1500
                addrbook.tree_selected = NULL;
1501
                gtk_tree_row_reference_free(addrbook.tree_opened);
1502
                addrbook.tree_opened = NULL;
1503
                addressbook_status_show("");
1504
                if (addrbook.entry)
1505
                        gtk_entry_set_text(GTK_ENTRY(addrbook.entry), "");
1506
                if (addrbook.listview) {
1507
                        lmodel = gtk_tree_view_get_model(GTK_TREE_VIEW(addrbook.listview));
1508
                        gtk_tree_store_clear(GTK_TREE_STORE(lmodel));
1509
                }
1510
                return;
1511
        }
1512
1513
        path = gtk_tree_model_get_path(model, &iter);
1514
        gtk_tree_row_reference_free(addrbook.tree_selected);
1515
        addrbook.tree_selected = gtk_tree_row_reference_new(model, path);
1516
        gtk_tree_row_reference_free(addrbook.list_selected);
1517
        addrbook.list_selected = NULL;
1518
        addressbook_status_show("");
1519
        if (addrbook.entry)
1520
                gtk_entry_set_text(GTK_ENTRY(addrbook.entry), "");
1521
        if (addrbook.listview) {
1522
                lmodel = gtk_tree_view_get_model(GTK_TREE_VIEW(addrbook.listview));
1523
                gtk_tree_store_clear(GTK_TREE_STORE(lmodel));
1524
        }
1525
        gtk_tree_model_get(model, &iter, COL_OBJ, &obj, -1);
1526
        if (obj == NULL) {
1527
                gtk_tree_path_free(path);
1528
                return;
1529
        }
1530
1531
        gtk_tree_row_reference_free(addrbook.tree_opened);
1532
        addrbook.tree_opened = gtk_tree_row_reference_new(model, path);
1533
1534
        if (obj->type == ADDR_DATASOURCE) {
1535
                /* Read from file */
1536
                static gboolean tVal = TRUE;
1537
1538
                ads = ADAPTER_DSOURCE(obj);
1539
                if (ads == NULL) return;
1540
                ds = ads->dataSource;
1541
                if (ds == NULL) return;                
1542
1543
                if (addrindex_ds_get_modify_flag(ds)) {
1544
                        addrindex_ds_read_data(ds);
1545
                }
1546
1547
                if (!addrindex_ds_get_read_flag(ds)) {
1548
                        addrindex_ds_read_data(ds);
1549
                }
1550
                addressbook_ds_show_message(ds);
1551
1552
                if (!addrindex_ds_get_access_flag(ds)) {
1553
                        /* Remove existing folders and groups */
1554
                        addressbook_tree_remove_children(model, &iter);
1555
1556
                        /* Load folders into the tree */
1557
                        rootFolder = addrindex_ds_get_root_folder(ds);
1558
                        if (ds->type == ADDR_IF_JPILOT) {
1559
                                addressbook_node_add_folder(&iter, ds, rootFolder, ADDR_CATEGORY, NULL);
1560
                        } else {
1561
                                addressbook_node_add_folder(&iter, ds, rootFolder, ADDR_ITEM_FOLDER, NULL);
1562
                        }
1563
                        addrindex_ds_set_access_flag(ds, &tVal);
1564
                        gtk_tree_view_expand_row(GTK_TREE_VIEW(addrbook.treeview), path, TRUE);
1565
                }
1566
        }
1567
1568
        gtk_tree_path_free(path);
1569
1570
        /* Update address list */
1571
        addressbook_set_list(obj);
1572
        addressbook_menuitem_set_sensitive();
1573
        addressbook_list_select_clear();
1574
}
1575
1576
static void addressbook_list_selection_changed(GtkTreeSelection *selection,
1577
                                               gpointer data)
1578
{
1579
        GtkTreeModel *lmodel;
1580
        GtkTreePath *path;
1581
        GList *selected;
1582
1583
        debug_print("addressbook_list_selection_changed\n");
1584
1585
        selected = gtk_tree_selection_get_selected_rows(selection, &lmodel);
1586
        addressbook_list_select_set(selected);
1587
        gtk_tree_row_reference_free(addrbook.list_selected);
1588
        if (selected) {
1589
                path = (GtkTreePath *)selected->data;
1590
                addrbook.list_selected = gtk_tree_row_reference_new(lmodel, path);
1591
                g_list_foreach(selected, (GFunc)gtk_tree_path_free, NULL);
1592
                g_list_free(selected);
1593
        } else
1594
                addrbook.list_selected = NULL;
1595
1596
        addressbook_menuitem_set_sensitive();
1597
}
1598
1599
static void addressbook_list_select_clear(void)
1600
{
1601
        if (_addressListSelection_) {
1602
                g_list_free(_addressListSelection_);
1603
        }
1604
        _addressListSelection_ = NULL;
1605
}
1606
1607
static void addressbook_list_select_remove(AddressObject *obj)
1608
{
1609
        if (!obj)
1610
                return;
1611
        if (_addressListSelection_) {
1612
                _addressListSelection_ = g_list_remove(_addressListSelection_, obj);
1613
        }
1614
}
1615
1616
static void addressbook_list_select_set(GList *row_list)
1617
{
1618
        GtkTreeModel *model;
1619
        GtkTreeIter iter;
1620
        GList *cur;
1621
        AddressObject *obj;
1622
1623
        model = gtk_tree_view_get_model(GTK_TREE_VIEW(addrbook.listview));
1624
1625
        addressbook_list_select_clear();
1626
        for (cur = row_list; cur != NULL; cur = cur->next) {
1627
                obj = NULL;
1628
                gtk_tree_model_get_iter(model, &iter, (GtkTreePath *)cur->data);
1629
                gtk_tree_model_get(model, &iter, COL_L_OBJ, &obj, -1);
1630
                if (obj && (obj->type == ADDR_ITEM_PERSON ||
1631
                            obj->type == ADDR_ITEM_EMAIL ||
1632
                            obj->type == ADDR_ITEM_GROUP)) {
1633
                        _addressListSelection_ = g_list_prepend(_addressListSelection_, obj);
1634
                }
1635
        }
1636
        _addressListSelection_ = g_list_reverse(_addressListSelection_);
1637
}
1638
1639
static void addressbook_entry_activated(GtkWidget *widget, gpointer data)
1640
{
1641
        addressbook_lup_clicked(NULL, NULL);
1642
}
1643
1644
static gboolean addressbook_list_button_pressed(GtkWidget *widget,
1645
                                                GdkEventButton *event,
1646
                                                gpointer data)
1647
{
1648
        GtkTreePath *path = NULL;
1649
        GtkTreeSelection *selection;
1650
        gboolean is_selected = FALSE;
1651
        gboolean mod_pressed = FALSE;
1652
1653
        if (!event)
1654
                return FALSE;
1655
1656
        gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), event->x, event->y,
1657
                                      &path, NULL, NULL, NULL);
1658
        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
1659
        if (path)
1660
                is_selected = gtk_tree_selection_path_is_selected
1661
                        (selection, path);
1662
        mod_pressed = ((event->state &
1663
                        (GDK_SHIFT_MASK|GDK_MOD1_MASK|GDK_CONTROL_MASK)) != 0);
1664
1665
        if (event->button == 1) {
1666
                if (is_selected && !mod_pressed) {
1667
                        can_toggle_list_selection = FALSE;
1668
                }
1669
1670
                if (is_selected && event->type == GDK_2BUTTON_PRESS) {
1671
                        debug_print("addressbook_list_button_pressed: GDK_2BUTTON_PRESS\n");
1672
                        /* Handle double click */
1673
                        if (prefs_common.add_address_by_click &&
1674
                            addrbook.target_compose)
1675
                                addressbook_to_clicked
1676
                                        (NULL, GINT_TO_POINTER(COMPOSE_ENTRY_TO));
1677
                        else
1678
                                addressbook_edit_address_cb(NULL, 0, NULL);
1679
                }
1680
        } else if (event->button == 3) {
1681
                gtk_menu_popup(GTK_MENU(addrbook.list_popup), NULL, NULL,
1682
                               NULL, NULL, event->button, event->time);
1683
                gtk_tree_path_free(path);
1684
                if (is_selected)
1685
                        return TRUE;
1686
        }
1687
1688
        return FALSE;
1689
}
1690
1691
static gboolean addressbook_list_button_released(GtkWidget *widget,
1692
                                                 GdkEventButton *event,
1693
                                                 gpointer data)
1694
{
1695
        if (!can_toggle_list_selection && !list_on_drag) {
1696
                GtkTreePath *path;
1697
1698
                if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), event->x, event->y, &path, NULL, NULL, NULL)) {
1699
                        can_toggle_list_selection = TRUE;
1700
                        gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), path, NULL, FALSE);
1701
                        gtk_tree_path_free(path);
1702
                }
1703
        }
1704
        can_toggle_list_selection = TRUE;
1705
        list_on_drag = FALSE;
1706
        return FALSE;
1707
}
1708
1709
static gboolean addressbook_tree_button_pressed(GtkWidget *widget,
1710
                                                GdkEventButton *event,
1711
                                                gpointer data)
1712
{
1713
        GtkTreeView *treeview = GTK_TREE_VIEW(widget);
1714
        GtkTreeSelection *selection;
1715
        GtkTreePath *path;
1716
1717
        if (!event)
1718
                return FALSE;
1719
1720
        if (!gtk_tree_view_get_path_at_pos(treeview, event->x, event->y,
1721
                                           &path, NULL, NULL, NULL))
1722
                return TRUE;
1723
        selection = gtk_tree_view_get_selection(treeview);
1724
1725
        addressbook_menuitem_set_sensitive();
1726
1727
        if (event->button == 3) {
1728
                gtk_tree_selection_select_path(selection, path);
1729
                gtk_menu_popup(GTK_MENU(addrbook.tree_popup),
1730
                               NULL, NULL, NULL, NULL,
1731
                               event->button, event->time);
1732
        } else if (event->type == GDK_2BUTTON_PRESS) {
1733
                gtk_tree_view_expand_row(treeview, path, FALSE);
1734
        }
1735
1736
        gtk_tree_path_free(path);
1737
        return FALSE;
1738
}
1739
1740
static gboolean addressbook_tree_button_released(GtkWidget *widget,
1741
                                                 GdkEventButton *event,
1742
                                                 gpointer data)
1743
{
1744
        return FALSE;
1745
}
1746
1747
static gboolean addressbook_obj_is_droppable(GtkTreeModel *model,
1748
                                             AddressObject *obj)
1749
{
1750
        gboolean acceptable = FALSE;
1751
1752
        if (!model || !obj)
1753
                return FALSE;
1754
        if (!_addressListSelection_)
1755
                return FALSE;
1756
1757
        if (obj->type == ADDR_DATASOURCE) {
1758
                AdapterDSource *ads;
1759
                AddressDataSource *ds;
1760
                AddressInterface *iface;
1761
1762
                ads = ADAPTER_DSOURCE(obj);
1763
                ds = ads ? ads->dataSource : NULL;
1764
                iface = ds ? ds->iface : NULL;
1765
                if (ads && ads->subType == ADDR_BOOK &&
1766
                    iface && !iface->readOnly)
1767
                        acceptable = TRUE;
1768
        } else if (obj->type == ADDR_ITEM_FOLDER) {
1769
                acceptable = TRUE;
1770
        }
1771
1772
        if (acceptable && addrbook.tree_opened) {
1773
                AddressObject *open_obj;
1774
                GtkTreeIter opened;
1775
1776
                gtkut_tree_row_reference_get_iter(model, addrbook.tree_opened,
1777
                                                  &opened);
1778
                gtk_tree_model_get(model, &opened, COL_OBJ, &open_obj, -1);
1779
                if (open_obj == obj)
1780
                        acceptable = FALSE;
1781
        }
1782
1783
        if (acceptable) {
1784
                GList *node;
1785
                for (node = _addressListSelection_; node != NULL; node = node->next) {
1786
                        AddressObject *obj = node->data;
1787
                        if (obj && obj->type == ADDR_ITEM_PERSON)
1788
                                break;
1789
                }
1790
                if (!node)
1791
                        acceptable = FALSE;
1792
        }
1793
1794
        return acceptable;
1795
}
1796
1797
static gboolean addressbook_drag_motion(GtkWidget *widget,
1798
                                        GdkDragContext *context,
1799
                                        gint x, gint y,
1800
                                        guint time, gpointer data)
1801
{
1802
        GtkTreeModel *model;
1803
        GtkTreePath *path = NULL;
1804
        GtkTreeIter iter;
1805
        AddressObject *obj, *src_obj;
1806
        AddressDataSource *src_ds;
1807
        AddressBookFile *src_abf;
1808
        gboolean acceptable;
1809
1810
        if (!gtk_tree_view_get_dest_row_at_pos
1811
                (GTK_TREE_VIEW(widget), x, y, &path, NULL)) {
1812
                gtk_tree_view_set_drag_dest_row
1813
                        (GTK_TREE_VIEW(widget), NULL,
1814
                         GTK_TREE_VIEW_DROP_INTO_OR_AFTER);
1815
                gdk_drag_status(context, 0, time);
1816
                return FALSE;
1817
        }
1818
1819
        model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
1820
        gtk_tree_model_get_iter(model, &iter, path);
1821
        gtk_tree_model_get(model, &iter, COL_OBJ, &obj, -1);
1822
        g_return_val_if_fail(obj != NULL, FALSE);
1823
1824
        /* source */
1825
        gtkut_tree_row_reference_get_iter(model, addrbook.tree_opened, &iter);
1826
        gtk_tree_model_get(model, &iter, COL_OBJ, &src_obj, -1);
1827
        g_return_val_if_fail(src_obj != NULL, FALSE);
1828
        src_ds = addressbook_find_datasource(&iter);
1829
        g_return_val_if_fail(src_ds != NULL, FALSE);
1830
        src_abf = src_ds->rawDataSource;
1831
        g_return_val_if_fail(src_abf != NULL, FALSE);
1832
1833
#ifdef G_OS_WIN32
1834
        {
1835
                GdkModifierType state = 0;
1836
1837
                gdk_window_get_pointer(widget->window, NULL, NULL, &state);
1838
                if ((state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) == 0)
1839
                        context->actions = GDK_ACTION_MOVE | GDK_ACTION_COPY;
1840
        }
1841
#endif
1842
1843
        if (!src_ds->iface ||
1844
            (src_ds->iface->readOnly || !src_ds->iface->haveLibrary))
1845
                context->actions &= ~GDK_ACTION_MOVE;
1846
1847
        acceptable = addressbook_obj_is_droppable(model, obj);
1848
        if ((context->actions & (GDK_ACTION_MOVE | GDK_ACTION_COPY)) == 0)
1849
                acceptable = FALSE;
1850
1851
        if (!acceptable) {
1852
                gtk_tree_view_set_drag_dest_row
1853
                        (GTK_TREE_VIEW(widget), NULL,
1854
                         GTK_TREE_VIEW_DROP_INTO_OR_AFTER);
1855
                gdk_drag_status(context, 0, time);
1856
        } else {
1857
                GdkDragAction action = 0;
1858
1859
                if ((context->actions & GDK_ACTION_MOVE) != 0)
1860
                        action = GDK_ACTION_MOVE;
1861
                else if ((context->actions & GDK_ACTION_COPY) != 0)
1862
                        action = GDK_ACTION_COPY;
1863
                gtk_tree_view_set_drag_dest_row
1864
                        (GTK_TREE_VIEW(widget), path,
1865
                         GTK_TREE_VIEW_DROP_INTO_OR_AFTER);
1866
                gdk_drag_status(context, action, time);
1867
        }
1868
1869
        gtk_tree_path_free(path);
1870
1871
        return TRUE;
1872
}
1873
1874
static void addressbook_drag_leave(GtkWidget *widget, GdkDragContext *context,
1875
                                   guint time, gpointer data)
1876
{
1877
        gtk_tree_view_set_drag_dest_row(GTK_TREE_VIEW(widget), NULL,
1878
                                        GTK_TREE_VIEW_DROP_INTO_OR_AFTER);
1879
}
1880
1881
static void addressbook_drag_received(GtkWidget        *widget,
1882
                                      GdkDragContext *context,
1883
                                      gint x, gint y,
1884
                                      GtkSelectionData *data,
1885
                                      guint info, guint time,
1886
                                      gpointer user_data)
1887
{
1888
        GtkTreeModel *model;
1889
        GtkTreePath *path = NULL;
1890
        GtkTreeIter iter;
1891
        AddressObject *obj, *pobj, *src_obj;
1892
        AddressDataSource *ds, *src_ds;
1893
        AddressBookFile *abf, *src_abf;
1894
        gboolean acceptable;
1895
        gboolean is_move;
1896
        GList *node;
1897
        ItemFolder *folder = NULL;
1898
        ItemPerson *person, *new_person;
1899
1900
        if (!gtk_tree_view_get_dest_row_at_pos
1901
                (GTK_TREE_VIEW(widget), x, y, &path, NULL))
1902
                return;
1903
1904
        debug_print("addressbook_drag_received_cb: received data\n");
1905
1906
        /* dest */
1907
        model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
1908
        gtk_tree_model_get_iter(model, &iter, path);
1909
        gtk_tree_model_get(model, &iter, COL_OBJ, &pobj, -1);
1910
        g_return_if_fail(pobj != NULL);
1911
        ds = addressbook_find_datasource(&iter);
1912
        g_return_if_fail(ds != NULL);
1913
1914
        /* source */
1915
        gtkut_tree_row_reference_get_iter(model, addrbook.tree_opened, &iter);
1916
        gtk_tree_model_get(model, &iter, COL_OBJ, &src_obj, -1);
1917
        g_return_if_fail(src_obj != NULL);
1918
        src_ds = addressbook_find_datasource(&iter);
1919
        g_return_if_fail(src_ds != NULL);
1920
        src_abf = src_ds->rawDataSource;
1921
        g_return_if_fail(src_abf != NULL);
1922
1923
        acceptable = addressbook_obj_is_droppable(model, pobj);
1924
        abf = ds->rawDataSource;
1925
        if (!abf)
1926
                acceptable = FALSE;
1927
1928
        if ((context->actions & (GDK_ACTION_MOVE | GDK_ACTION_COPY)) == 0)
1929
                acceptable = FALSE;
1930
        is_move = (context->actions & GDK_ACTION_MOVE) != 0;
1931
1932
        if (!src_ds->iface ||
1933
            (src_ds->iface->readOnly || !src_ds->iface->haveLibrary))
1934
                is_move = FALSE;
1935
1936
        if (!_addressListSelection_ || !acceptable) {
1937
                context->action = 0;
1938
                gtk_drag_finish(context, FALSE, FALSE, time);
1939
                gtk_tree_path_free(path);
1940
                return;
1941
        }
1942
1943
        if (pobj->type == ADDR_ITEM_FOLDER)
1944
                folder = ADAPTER_FOLDER(pobj)->itemFolder;
1945
1946
        node = _addressListSelection_;
1947
        while (node) {
1948
                GList *cur;
1949
1950
                obj = node->data;
1951
                node = g_list_next(node);
1952
                if (obj->type != ADDR_ITEM_PERSON)
1953
                        continue;
1954
1955
                person = (ItemPerson *)obj;
1956
                new_person = addrbook_add_address_list(abf, folder, NULL);
1957
                ADDRITEM_NAME(new_person) = g_strdup(ADDRITEM_NAME(person));
1958
                new_person->firstName = g_strdup(person->firstName);
1959
                new_person->lastName = g_strdup(person->lastName);
1960
                new_person->nickName = g_strdup(person->nickName);
1961
                for (cur = person->listEMail; cur != NULL; cur = cur->next) {
1962
                        ItemEMail *email = cur->data;
1963
                        addritem_person_add_email(new_person, addritem_copy_item_email(email));
1964
                }
1965
                for (cur = person->listAttrib; cur != NULL; cur = cur->next) {
1966
                        UserAttribute *attr = cur->data;
1967
                        addritem_person_add_attribute(new_person, addritem_copy_attribute(attr));
1968
                }
1969
1970
                if (is_move) {
1971
                        if (_clipObjectList_)
1972
                                _clipObjectList_ = g_list_remove(_clipObjectList_, person);
1973
                        person = addrbook_remove_person(src_abf, person);
1974
                        if (person)
1975
                                addritem_free_item_person(person);
1976
                }
1977
        }
1978
1979
        if (is_move) {
1980
                addressbook_list_select_clear();
1981
                addressbook_reopen();
1982
        }
1983
1984
        context->action = 0;
1985
        gtk_drag_finish(context, TRUE, FALSE, time);
1986
1987
        gtk_tree_path_free(path);
1988
1989
        addressbook_modified();
1990
}
1991
1992
static void addressbook_folder_resized(GtkWidget *widget,
1993
                                       GtkAllocation *allocation,
1994
                                       gpointer data)
1995
{
1996
        gint width = allocation->width;
1997
1998
        if (width < 8)
1999
                return;
2000
2001
        prefs_common.addressbook_folder_width = width;
2002
}
2003
2004
static void addressbook_col_resized(GtkWidget *widget,
2005
                                    GtkAllocation *allocation, gpointer data)
2006
{
2007
        AddressBookListColumnPos type = (gint)data;
2008
        gint width = allocation->width;
2009
2010
        if (width < 8)
2011
                return;
2012
2013
        switch (type) {
2014
        case COL_NAME:
2015
                prefs_common.addressbook_col_name = width;
2016
                break;
2017
        case COL_ADDRESS:
2018
                prefs_common.addressbook_col_addr = width;
2019
                break;
2020
        case COL_REMARKS:
2021
                prefs_common.addressbook_col_rem = width;
2022
                break;
2023
        default:
2024
                break;
2025
        }
2026
}
2027
2028
static void addressbook_popup_close(GtkMenuShell *menu_shell, gpointer data)
2029
{
2030
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
2031
        GtkTreeSelection *selection;
2032
        GtkTreePath *path;
2033
2034
        if (!addrbook.tree_opened)
2035
                return;
2036
 
2037
        selection = gtk_tree_view_get_selection(treeview);
2038
        path = gtk_tree_row_reference_get_path(addrbook.tree_opened);
2039
        if (path) {
2040
                gtk_tree_selection_select_path(selection, path);
2041
                gtk_tree_path_free(path);
2042
        }
2043
}
2044
2045
static void addressbook_new_folder_cb(gpointer data, guint action,
2046
                                      GtkWidget *widget)
2047
{
2048
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
2049
        GtkTreeSelection *selection;
2050
        GtkTreeModel *model;
2051
        GtkTreeIter iter;
2052
        AddressObject *obj = NULL;
2053
        AddressDataSource *ds = NULL;
2054
        AddressBookFile *abf = NULL;
2055
        ItemFolder *parentFolder = NULL;
2056
        ItemFolder *folder = NULL;
2057
2058
        selection = gtk_tree_view_get_selection(treeview);
2059
        if (!gtk_tree_selection_get_selected(selection, &model, &iter))
2060
                return;
2061
2062
        gtk_tree_model_get(model, &iter, COL_OBJ, &obj, -1);
2063
        if (obj == NULL)
2064
                return;
2065
        ds = addressbook_find_datasource(&iter);
2066
        if (ds == NULL)
2067
                return;
2068
2069
        if (obj->type == ADDR_DATASOURCE) {
2070
                if (ADAPTER_DSOURCE(obj)->subType != ADDR_BOOK) return;
2071
        } else if (obj->type == ADDR_ITEM_FOLDER) {
2072
                parentFolder = ADAPTER_FOLDER(obj)->itemFolder;
2073
        } else {
2074
                return;
2075
        }
2076
2077
        abf = ds->rawDataSource;
2078
        if (abf == NULL) return;
2079
        folder = addressbook_edit_folder(abf, parentFolder, NULL);
2080
        if (folder) {
2081
                GtkTreeIter new_iter;
2082
                GtkTreePath *path;
2083
                addressbook_node_add_folder(&iter, ds, folder, ADDR_ITEM_FOLDER, &new_iter);
2084
                path = gtk_tree_model_get_path(model, &iter);
2085
                gtk_tree_view_expand_row(treeview, path, TRUE);
2086
                gtk_tree_path_free(path);
2087
                if (gtkut_tree_row_reference_equal(addrbook.tree_selected, addrbook.tree_opened))
2088
                        addressbook_set_list(obj);
2089
        }
2090
2091
}
2092
2093
static void addressbook_new_group_cb(gpointer data, guint action,
2094
                                     GtkWidget *widget)
2095
{
2096
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
2097
        GtkTreeSelection *selection;
2098
        GtkTreeModel *model;
2099
        GtkTreeIter iter;
2100
        AddressObject *obj = NULL;
2101
        AddressDataSource *ds = NULL;
2102
        AddressBookFile *abf = NULL;
2103
        ItemFolder *parentFolder = NULL;
2104
        ItemGroup *group = NULL;
2105
2106
        selection = gtk_tree_view_get_selection(treeview);
2107
        if (!gtk_tree_selection_get_selected(selection, &model, &iter))
2108
                return;
2109
2110
        gtk_tree_model_get(model, &iter, COL_OBJ, &obj, -1);
2111
        if (obj == NULL)
2112
                return;
2113
        ds = addressbook_find_datasource(&iter);
2114
        if (ds == NULL)
2115
                return;
2116
2117
        if (obj->type == ADDR_DATASOURCE) {
2118
                if (ADAPTER_DSOURCE(obj)->subType != ADDR_BOOK) return;
2119
        } else if (obj->type == ADDR_ITEM_FOLDER) {
2120
                parentFolder = ADAPTER_FOLDER(obj)->itemFolder;
2121
        } else {
2122
                return;
2123
        }
2124
2125
        abf = ds->rawDataSource;
2126
        if (abf == NULL) return;
2127
        group = addressbook_edit_group(abf, parentFolder, NULL);
2128
        if (group) {
2129
                GtkTreeIter new_iter;
2130
                GtkTreePath *path;
2131
                addressbook_node_add_group(&iter, ds, group, &new_iter);
2132
                path = gtk_tree_model_get_path(model, &iter);
2133
                gtk_tree_view_expand_row(treeview, path, TRUE);
2134
                gtk_tree_path_free(path);
2135
                if (gtkut_tree_row_reference_equal(addrbook.tree_selected, addrbook.tree_opened))
2136
                        addressbook_set_list(obj);
2137
        }
2138
2139
}
2140
2141
static void addressbook_change_node_name(GtkTreeIter *iter, const gchar *name)
2142
{
2143
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
2144
        GtkTreeStore *store;
2145
2146
        store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
2147
        gtk_tree_store_set(store, iter, COL_FOLDER_NAME, name, -1);
2148
}
2149
2150
/*
2151
* Edit data source.
2152
* Enter: obj   Address object to edit.
2153
*        node  Node in tree.
2154
* Return: New name of data source.
2155
*/
2156
static gchar *addressbook_edit_datasource(AddressObject *obj, GtkTreeIter *iter)
2157
{
2158
        gchar *newName = NULL;
2159
        AddressDataSource *ds = NULL;
2160
        AddressInterface *iface = NULL;
2161
        AdapterDSource *ads = NULL;
2162
2163
        ds = addressbook_find_datasource(iter);
2164
        if (ds == NULL)
2165
                return NULL;
2166
        iface = ds->iface;
2167
        if (!iface->haveLibrary)
2168
                return NULL;
2169
2170
        /* Read data from data source */
2171
        if (!addrindex_ds_get_read_flag(ds)) {
2172
                addrindex_ds_read_data(ds);
2173
        }
2174
2175
        /* Handle edit */
2176
        ads = ADAPTER_DSOURCE(obj);
2177
        if (ads->subType == ADDR_BOOK) {
2178
                if (addressbook_edit_book(_addressIndex_, ads) == NULL)
2179
                        return NULL;
2180
        } else if (ads->subType == ADDR_VCARD) {
2181
                       if (addressbook_edit_vcard(_addressIndex_, ads) == NULL)
2182
                        return NULL;
2183
#ifdef USE_JPILOT
2184
        } else if (ads->subType == ADDR_JPILOT) {
2185
                if (addressbook_edit_jpilot(_addressIndex_, ads) == NULL)
2186
                        return NULL;
2187
#endif
2188
#ifdef USE_LDAP
2189
        } else if (ads->subType == ADDR_LDAP) {
2190
                if (addressbook_edit_ldap(_addressIndex_, ads) == NULL)
2191
                        return NULL;
2192
#endif
2193
        } else {
2194
                return NULL;
2195
        }
2196
        newName = obj->name;
2197
        return newName;
2198
}
2199
2200
/*
2201
* Edit an object that is in the address tree area.
2202
*/
2203
static void addressbook_treenode_edit_cb(gpointer data, guint action,
2204
                                         GtkWidget *widget)
2205
{
2206
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
2207
        GtkTreeSelection *selection;
2208
        GtkTreeModel *model;
2209
        GtkTreeIter iter, parent;
2210
        AddressObject *obj = NULL;
2211
        AddressDataSource *ds = NULL;
2212
        AddressBookFile *abf = NULL;
2213
        gchar *name = NULL;
2214
2215
        selection = gtk_tree_view_get_selection(treeview);
2216
        if (!gtk_tree_selection_get_selected(selection, &model, &iter))
2217
                return;
2218
2219
        if (gtk_tree_store_iter_depth(GTK_TREE_STORE(model), &iter) == 0)
2220
                return;
2221
        gtk_tree_model_get(model, &iter, COL_OBJ, &obj, -1);
2222
        if (obj == NULL)
2223
                return;
2224
        if (!gtk_tree_model_iter_parent(model, &parent, &iter))
2225
                return;
2226
2227
        ds = addressbook_find_datasource(&iter);
2228
        if (ds == NULL)
2229
                return;
2230
2231
        if (obj->type == ADDR_DATASOURCE) {
2232
                name = addressbook_edit_datasource(obj, &iter);
2233
                if (name == NULL)
2234
                        return;
2235
        } else {
2236
                abf = ds->rawDataSource;
2237
                if (abf == NULL)
2238
                        return;
2239
                if (obj->type == ADDR_ITEM_FOLDER) {
2240
                        AdapterFolder *adapter = ADAPTER_FOLDER(obj);
2241
                        ItemFolder *item = adapter->itemFolder;
2242
                        ItemFolder *parentFolder = NULL;
2243
                        parentFolder = (ItemFolder *)ADDRITEM_PARENT(item);
2244
                        if (addressbook_edit_folder(abf, parentFolder, item) == NULL)
2245
                                return;
2246
                        name = ADDRITEM_NAME(item);
2247
                } else if (obj->type == ADDR_ITEM_GROUP) {
2248
                        AdapterGroup *adapter = ADAPTER_GROUP(obj);
2249
                        ItemGroup *item = adapter->itemGroup;
2250
                        ItemFolder *parentFolder = NULL;
2251
                        parentFolder = (ItemFolder *)ADDRITEM_PARENT(item);
2252
                        if (addressbook_edit_group(abf, parentFolder, item) == NULL)
2253
                                return;
2254
                        name = ADDRITEM_NAME(item);
2255
                }
2256
        }
2257
2258
        if (name) {
2259
                GtkTreePath *path;
2260
2261
                /* Update node in tree view */
2262
                addressbook_change_node_name(&iter, name);
2263
                path = gtk_tree_model_get_path(model, &iter);
2264
                gtk_tree_view_expand_row(treeview, path, TRUE);
2265
                gtk_tree_view_set_cursor(treeview, path, NULL, FALSE);
2266
                gtk_tree_path_free(path);
2267
        }
2268
}
2269
2270
/*
2271
* Delete an item from the tree widget.
2272
*/
2273
static void addressbook_treenode_delete_cb(gpointer data, guint action,
2274
                                         GtkWidget *widget)
2275
{
2276
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
2277
        GtkTreeSelection *selection;
2278
        GtkTreeModel *model;
2279
        GtkTreeIter iter, parent;
2280
        AddressObject *obj;
2281
        gchar *message;
2282
        AlertValue aval;
2283
        AddressBookFile *abf = NULL;
2284
        AdapterDSource *ads = NULL;
2285
        AddressInterface *iface = NULL;
2286
        AddressDataSource *ds = NULL;
2287
        gboolean remFlag = FALSE;
2288
2289
        selection = gtk_tree_view_get_selection(treeview);
2290
        if (!gtk_tree_selection_get_selected(selection, &model, &iter))
2291
                return;
2292
2293
        if (gtk_tree_store_iter_depth(GTK_TREE_STORE(model), &iter) == 0)
2294
                return;
2295
        gtk_tree_model_get(model, &iter, COL_OBJ, &obj, -1);
2296
        g_return_if_fail(obj != NULL);
2297
2298
        if (obj->type == ADDR_DATASOURCE) {
2299
                ads = ADAPTER_DSOURCE(obj);
2300
                if (ads == NULL)
2301
                        return;
2302
                ds = ads->dataSource;
2303
                if (ds == NULL)
2304
                        return;
2305
        } else {
2306
                /* Must be folder or something else */
2307
                ds = addressbook_find_datasource(&iter);
2308
                if (ds == NULL)
2309
                        return;
2310
2311
                /* Only allow deletion from non-readOnly data sources */
2312
                iface = ds->iface;
2313
                if (iface->readOnly)
2314
                        return;
2315
        }
2316
2317
        /* Confirm deletion */
2318
        if (obj->type == ADDR_ITEM_FOLDER) {
2319
                message = g_strdup_printf
2320
                        (_("Do you want to delete the folder AND all addresses in `%s' ?\n"
2321
                           "If deleting the folder only, addresses will be moved into parent folder."),
2322
                         obj->name);
2323
                aval = alertpanel(_("Delete folder"), message, _("_Folder only"), _("Folder and _addresses"), GTK_STOCK_CANCEL);
2324
                g_free(message);
2325
                if (aval != G_ALERTDEFAULT && aval != G_ALERTALTERNATE)
2326
                        return;
2327
        } else {
2328
                message = g_strdup_printf(_("Really delete `%s' ?"), obj->name);
2329
                aval = alertpanel(_("Delete"), message, GTK_STOCK_YES, GTK_STOCK_NO, NULL);
2330
                g_free(message);
2331
                if (aval != G_ALERTDEFAULT)
2332
                        return;
2333
        }
2334
2335
        /* Proceed with deletion */
2336
        if (obj->type == ADDR_DATASOURCE) {
2337
                /* Remove data source. */
2338
                if (addrindex_index_remove_datasource(_addressIndex_, ds)) {
2339
                        addressbook_free_child_adapters(&iter);
2340
                        abf = addressbook_get_book_file();
2341
                        if (abf) {
2342
                                gchar *bookFile;
2343
                                bookFile = g_strconcat(abf->path, G_DIR_SEPARATOR_S, abf->fileName, NULL);
2344
                                debug_print("removing %s\n", bookFile);
2345
                                g_unlink(bookFile);
2346
                                g_free(bookFile);
2347
                        }
2348
                        remFlag = TRUE;
2349
                }
2350
        } else {
2351
                abf = addressbook_get_book_file();
2352
                if (abf == NULL)
2353
                        return;
2354
        }
2355
2356
        if (obj->type == ADDR_ITEM_FOLDER) {
2357
                AdapterFolder *adapter = ADAPTER_FOLDER(obj);
2358
                ItemFolder *item = adapter->itemFolder;
2359
2360
                if (aval == G_ALERTDEFAULT) {
2361
                        /* Remove folder only */
2362
                        item = addrbook_remove_folder(abf, item);
2363
                        if (item) {
2364
                                addritem_free_item_folder(item);
2365
                                addressbook_move_nodes_up(&iter);
2366
                                remFlag = TRUE;
2367
                        }
2368
                } else if (aval == G_ALERTALTERNATE) {
2369
                        /* Remove folder and addresses */
2370
                        item = addrbook_remove_folder_delete(abf, item);
2371
                        if (item) {
2372
                                addritem_free_item_folder(item);
2373
                                addressbook_free_child_adapters(&iter);
2374
                                remFlag = TRUE;
2375
                        }
2376
                }
2377
        } else if (obj->type == ADDR_ITEM_GROUP) {
2378
                AdapterGroup *adapter = ADAPTER_GROUP(obj);
2379
                ItemGroup *item = adapter->itemGroup;
2380
2381
                item = addrbook_remove_group(abf, item);
2382
                if (item) {
2383
                        addritem_free_item_group(item);
2384
                        remFlag = TRUE;
2385
                }
2386
        }
2387
2388
        if (remFlag) {
2389
                /* Free up adapter and remove node. */
2390
                addressbook_free_adapter(&iter);
2391
                gtk_tree_model_iter_parent(model, &parent, &iter);
2392
                gtk_tree_store_remove(GTK_TREE_STORE(model), &iter);
2393
                gtk_tree_selection_select_iter(selection, &parent);
2394
        }
2395
}
2396
2397
static void addressbook_new_address_cb(gpointer data, guint action, GtkWidget *widget)
2398
{
2399
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
2400
        GtkTreeSelection *selection;
2401
        GtkTreeModel *model;
2402
        GtkTreeIter iter;
2403
        AddressObject *pobj = NULL;
2404
        AddressDataSource *ds = NULL;
2405
        AddressBookFile *abf = NULL;
2406
2407
        selection = gtk_tree_view_get_selection(treeview);
2408
        if (!gtk_tree_selection_get_selected(selection, &model, &iter))
2409
                return;
2410
2411
        gtk_tree_model_get(model, &iter, COL_OBJ, &pobj, -1);
2412
        if (pobj == NULL)
2413
                return;
2414
        ds = addressbook_find_datasource(&iter);
2415
        if (ds == NULL)
2416
                return;
2417
2418
        abf = ds->rawDataSource;
2419
        if (abf == NULL)
2420
                return;
2421
2422
        if (pobj->type == ADDR_DATASOURCE) {
2423
                if (ADAPTER_DSOURCE(pobj)->subType == ADDR_BOOK) {
2424
                        /* New address */
2425
                        ItemPerson *person = addressbook_edit_person(abf, NULL, NULL, FALSE);
2426
                        if (person) {
2427
                                if (gtkut_tree_row_reference_equal(addrbook.tree_selected, addrbook.tree_opened)) {
2428
                                        addressbook_reopen();
2429
                                }
2430
                                addressbook_modified();
2431
                        }
2432
                }
2433
        }
2434
        else if( pobj->type == ADDR_ITEM_FOLDER ) {
2435
                /* New address */
2436
                ItemFolder *folder = ADAPTER_FOLDER(pobj)->itemFolder;
2437
                ItemPerson *person = addressbook_edit_person(abf, folder, NULL, FALSE);
2438
                if (person) {
2439
                        if (gtkut_tree_row_reference_equal(addrbook.tree_selected, addrbook.tree_opened)) {
2440
                                addressbook_reopen();
2441
                        }
2442
                        addressbook_modified();
2443
                }
2444
        }
2445
        else if( pobj->type == ADDR_ITEM_GROUP ) {
2446
                /* New address in group */
2447
                ItemGroup *group = ADAPTER_GROUP(pobj)->itemGroup;
2448
2449
                if (addressbook_edit_group(abf, NULL, group) == NULL)
2450
                        return;
2451
                if (gtkut_tree_row_reference_equal
2452
                        (addrbook.tree_selected, addrbook.tree_opened)) {
2453
                        /* Change node name in tree. */
2454
                        addressbook_change_node_name(&iter, ADDRITEM_NAME(group));
2455
                        addressbook_reopen();
2456
                }
2457
        }
2458
}
2459
2460
static void addressbook_compose_to_cb(gpointer data, guint action, GtkWidget *widget)
2461
{
2462
        addressbook_to_clicked(NULL, GINT_TO_POINTER(action));
2463
}
2464
2465
/*
2466
* Search for specified group in address index tree.
2467
*/
2468
static gboolean addressbook_find_group_node(GtkTreeIter *parent, GtkTreeIter *iter, ItemGroup *group)
2469
{
2470
        GtkTreeModel *model;
2471
        GtkTreeIter iter_;
2472
        gboolean valid = TRUE;
2473
2474
        model = gtk_tree_view_get_model(GTK_TREE_VIEW(addrbook.treeview));
2475
        valid = gtk_tree_model_iter_children(model, &iter_, parent);
2476
        while (valid) {
2477
                AddressObject *obj = NULL;
2478
2479
                gtk_tree_model_get(model, &iter_, COL_OBJ, &obj, -1);
2480
                if (obj && obj->type == ADDR_ITEM_GROUP) {
2481
                        ItemGroup *g = ADAPTER_GROUP(obj)->itemGroup;
2482
                        if (g == group) {
2483
                                *iter = iter_;
2484
                                return TRUE;
2485
                        }
2486
                }
2487
                valid = gtk_tree_model_iter_next(model, &iter_);
2488
        }
2489
2490
        return FALSE;
2491
}
2492
2493
static AddressBookFile *addressbook_get_book_file(void)
2494
{
2495
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
2496
        GtkTreeSelection *selection;
2497
        GtkTreeIter iter;
2498
        AddressBookFile *abf = NULL;
2499
        AddressDataSource *ds = NULL;
2500
2501
        selection = gtk_tree_view_get_selection(treeview);
2502
        if (!gtk_tree_selection_get_selected(selection, NULL, &iter))
2503
                return NULL;
2504
        ds = addressbook_find_datasource(&iter);
2505
        if (ds == NULL)
2506
                return NULL;
2507
        if (ds->type == ADDR_IF_BOOK)
2508
                abf = ds->rawDataSource;
2509
        return abf;
2510
}
2511
2512
static void addressbook_tree_remove_children(GtkTreeModel *model,
2513
                                             GtkTreeIter *parent)
2514
{
2515
        GtkTreeIter iter;
2516
2517
        /* Remove existing folders and groups */
2518
        while (gtk_tree_model_iter_children(model, &iter, parent)) {
2519
                gtk_tree_store_remove(GTK_TREE_STORE(model), &iter);
2520
        }
2521
}
2522
2523
static void addressbook_move_nodes_recursive(GtkTreeIter *iter,
2524
                                             GtkTreeIter *parent)
2525
{
2526
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
2527
        GtkTreeModel *model;
2528
        GtkTreeIter child, new_iter;
2529
        gboolean valid;
2530
2531
        model = gtk_tree_view_get_model(treeview);
2532
2533
        valid = gtk_tree_model_iter_children(model, &child, iter);
2534
        while (valid) {
2535
                gchar *name = NULL;
2536
                AddressObject *obj = NULL;
2537
                GdkPixbuf *pixbuf = NULL;
2538
                GdkPixbuf *pixbuf_open = NULL;
2539
2540
                gtk_tree_model_get(model, &child, COL_FOLDER_NAME, &name,
2541
                                   COL_OBJ, &obj, COL_PIXBUF, &pixbuf,
2542
                                   COL_PIXBUF_OPEN, &pixbuf_open, -1);
2543
                gtk_tree_store_append(GTK_TREE_STORE(model), &new_iter, parent);
2544
                gtk_tree_store_set(GTK_TREE_STORE(model), &new_iter,
2545
                                   COL_FOLDER_NAME, name,
2546
                                   COL_OBJ, obj,
2547
                                   COL_PIXBUF, pixbuf,
2548
                                   COL_PIXBUF_OPEN, pixbuf_open, -1);
2549
                g_free(name);
2550
                addressbook_move_nodes_recursive(&child, &new_iter);
2551
                valid = gtk_tree_model_iter_next(model, &child);
2552
        }
2553
}
2554
2555
static void addressbook_move_nodes_up(GtkTreeIter *iter)
2556
{
2557
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
2558
        GtkTreeModel *model;
2559
        GtkTreeIter parent;
2560
2561
        model = gtk_tree_view_get_model(treeview);
2562
        if (!gtk_tree_model_iter_parent(model, &parent, iter))
2563
                return;
2564
2565
        addressbook_move_nodes_recursive(iter, &parent);
2566
}
2567
2568
static void addressbook_edit_address_cb(gpointer data, guint action, GtkWidget *widget)
2569
{
2570
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
2571
        GtkTreeSelection *selection;
2572
        GtkTreeModel *model;
2573
        GtkTreeIter liter, iter, node, parent;
2574
        gboolean node_found;
2575
        gboolean parent_found = FALSE;
2576
        GtkTreeView *listview = GTK_TREE_VIEW(addrbook.listview);
2577
        GtkTreeModel *lmodel;
2578
        AddressObject *obj = NULL, *pobj = NULL;
2579
        AddressDataSource *ds = NULL;
2580
        gchar *name = NULL;
2581
        AddressBookFile *abf = NULL;
2582
2583
        if (addrbook.list_selected == NULL)
2584
                return;
2585
2586
        lmodel = gtk_tree_view_get_model(listview);
2587
        if (!gtkut_tree_row_reference_get_iter(lmodel, addrbook.list_selected,
2588
                                               &liter))
2589
                return;
2590
        gtk_tree_model_get(lmodel, &liter, COL_L_OBJ, &obj, -1);
2591
        g_return_if_fail(obj != NULL);
2592
2593
        selection = gtk_tree_view_get_selection(treeview);
2594
        if (!gtk_tree_selection_get_selected(selection, &model, &iter))
2595
                return;
2596
        gtk_tree_model_get(model, &iter, COL_OBJ, &pobj, -1);
2597
        node_found = gtkut_tree_model_find_by_column_data
2598
                (model, &node, &iter, COL_OBJ, obj);
2599
2600
        ds = addressbook_find_datasource(&iter);
2601
        if (ds == NULL)
2602
                return;
2603
2604
        abf = addressbook_get_book_file();
2605
        if (abf == NULL)
2606
                return;
2607
2608
        if (obj->type == ADDR_ITEM_EMAIL) {
2609
                ItemEMail *email = (ItemEMail *)obj;
2610
                ItemPerson *person;
2611
2612
                if (email == NULL)
2613
                        return;
2614
                if (pobj && pobj->type == ADDR_ITEM_GROUP) {
2615
                        /* Edit parent group */
2616
                        AdapterGroup *adapter = ADAPTER_GROUP(pobj);
2617
                        ItemGroup *itemGrp = adapter->itemGroup;
2618
2619
                        if (addressbook_edit_group(abf, NULL, itemGrp) == NULL)
2620
                                return;
2621
                        name = ADDRITEM_NAME(itemGrp);
2622
                        node = iter;
2623
                        node_found = TRUE;
2624
                        parent_found = gtk_tree_model_iter_parent(model, &parent, &node);
2625
                } else {
2626
                        /* Edit person - email page */
2627
                        person = (ItemPerson *)ADDRITEM_PARENT(email);
2628
                        if (addressbook_edit_person(abf, NULL, person, TRUE) == NULL)
2629
                                return;
2630
                        addressbook_reopen();
2631
                        addressbook_modified();
2632
                        return;
2633
                }
2634
        } else if (obj->type == ADDR_ITEM_PERSON) {
2635
                /* Edit person - basic page */
2636
                ItemPerson *person = (ItemPerson *)obj;
2637
2638
                if (addressbook_edit_person(abf, NULL, person, FALSE) == NULL)
2639
                        return;
2640
                addressbook_reopen();
2641
                addressbook_modified();
2642
                return;
2643
        } else if (obj->type == ADDR_ITEM_GROUP) {
2644
                ItemGroup *itemGrp = (ItemGroup *)obj;
2645
2646
                if (addressbook_edit_group(abf, NULL, itemGrp) == NULL)
2647
                        return;
2648
                parent = iter;
2649
                parent_found = TRUE;
2650
                node_found = addressbook_find_group_node(&parent, &node, itemGrp);
2651
                name = ADDRITEM_NAME(itemGrp);
2652
        } else {
2653
                return;
2654
        }
2655
2656
        /* Update tree node with node name */
2657
        if (node_found) {
2658
                addressbook_change_node_name(&node, name);
2659
                addressbook_reopen();
2660
        }
2661
}
2662
2663
static void addressbook_delete_address_cb(gpointer data, guint action,
2664
                                          GtkWidget *widget)
2665
{
2666
        addressbook_del_clicked(NULL, NULL);
2667
}
2668
2669
static void addressbook_copy_address_cb(gpointer data, guint action,
2670
                                        GtkWidget *widget)
2671
{
2672
        AddressObject *obj;
2673
        GList *node;
2674
2675
        if (_addressListSelection_ == NULL)
2676
                return;
2677
2678
        g_list_free(_clipObjectList_);
2679
        _clipObjectList_ = NULL;
2680
2681
        node = _addressListSelection_;
2682
        while (node) {
2683
                obj = node->data;
2684
                if (obj->type == ADDR_ITEM_PERSON) {
2685
                        _clipObjectList_ = g_list_append(_clipObjectList_, obj);
2686
                }
2687
                node = g_list_next(node);
2688
        }
2689
2690
        addressbook_menuitem_set_sensitive();
2691
}
2692
2693
static void addressbook_paste_address_cb(gpointer data, guint action,
2694
                                         GtkWidget *widget)
2695
{
2696
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
2697
        GtkTreeSelection *selection;
2698
        GtkTreeModel *model;
2699
        GtkTreeIter iter;
2700
        AddressObject *obj = NULL, *pobj = NULL;
2701
        AddressDataSource *ds = NULL;
2702
        AddressBookFile *abf = NULL;
2703
        ItemFolder *folder = NULL;
2704
        ItemPerson *clipPerson, *person;
2705
        GList *cur;
2706
        GList *node;
2707
2708
        if (!_clipObjectList_)
2709
                return;
2710
2711
        selection = gtk_tree_view_get_selection(treeview);
2712
        if (!gtk_tree_selection_get_selected(selection, &model, &iter))
2713
                return;
2714
        gtk_tree_model_get(model, &iter, COL_OBJ, &pobj, -1);
2715
        if (pobj->type == ADDR_ITEM_FOLDER)
2716
                folder = ADAPTER_FOLDER(pobj)->itemFolder;
2717
        else if (pobj->type == ADDR_DATASOURCE)
2718
                folder = NULL;
2719
        else
2720
                return;
2721
2722
        ds = addressbook_find_datasource(&iter);
2723
        if (ds == NULL)
2724
                return;
2725
2726
        abf = ds->rawDataSource;
2727
        if (abf == NULL)
2728
                return;
2729
2730
        node = _clipObjectList_;
2731
        while (node) {
2732
                obj = node->data;
2733
                node = g_list_next(node);
2734
                if (obj->type != ADDR_ITEM_PERSON)
2735
                        continue;
2736
                clipPerson = (ItemPerson *)obj;
2737
2738
                person = addrbook_add_address_list(abf, folder, NULL);
2739
                ADDRITEM_NAME(person) = g_strdup(ADDRITEM_NAME(clipPerson));
2740
                person->firstName = g_strdup(clipPerson->firstName);
2741
                person->lastName = g_strdup(clipPerson->lastName);
2742
                person->nickName = g_strdup(clipPerson->nickName);
2743
                for (cur = clipPerson->listEMail; cur != NULL; cur = cur->next) {
2744
                        ItemEMail *email = cur->data;
2745
                        addritem_person_add_email(person, addritem_copy_item_email(email));
2746
                }
2747
                for (cur = clipPerson->listAttrib; cur != NULL; cur = cur->next) {
2748
                        UserAttribute *attr = cur->data;
2749
                        addritem_person_add_attribute(person, addritem_copy_attribute(attr));
2750
                }
2751
        }
2752
2753
        if (gtkut_tree_row_reference_equal(addrbook.tree_selected, addrbook.tree_opened))
2754
                addressbook_reopen();
2755
        addressbook_modified();
2756
}
2757
2758
static void close_cb(gpointer data, guint action, GtkWidget *widget)
2759
{
2760
        addressbook_close();
2761
}
2762
2763
static void addressbook_file_save_cb(gpointer data, guint action, GtkWidget *widget)
2764
{
2765
        addressbook_export_to_file();
2766
}
2767
2768
static void addressbook_person_expand_node(GtkTreeView *treeview,
2769
                                           GtkTreeIter *iter, GtkTreePath *path,
2770
                                           gpointer *data)
2771
{
2772
        GtkTreeModel *model;
2773
        ItemPerson *person = NULL;
2774
2775
        model = gtk_tree_view_get_model(treeview);
2776
        gtk_tree_model_get(model, iter, COL_L_OBJ, &person, -1);
2777
        if (person)
2778
                addritem_person_set_opened(person, TRUE);
2779
}
2780
2781
static void addressbook_person_collapse_node(GtkTreeView *treeview,
2782
                                             GtkTreeIter *iter,
2783
                                             GtkTreePath *path, gpointer *data)
2784
{
2785
        GtkTreeModel *model;
2786
        ItemPerson *person = NULL;
2787
2788
        model = gtk_tree_view_get_model(treeview);
2789
        gtk_tree_model_get(model, iter, COL_L_OBJ, &person, -1);
2790
        if (person)
2791
                addritem_person_set_opened(person, FALSE);
2792
}
2793
2794
static void addressbook_drag_begin(GtkWidget *widget,
2795
                                   GdkDragContext *drag_context, gpointer data)
2796
{
2797
        list_on_drag = TRUE;
2798
        /* gtk_drag_set_icon_default(drag_context); */
2799
}
2800
2801
static void addressbook_drag_end(GtkWidget *widget,
2802
                                 GdkDragContext *drag_context, gpointer data)
2803
{
2804
}
2805
2806
static void addressbook_drag_data_get(GtkWidget *widget,
2807
                                      GdkDragContext *drag_context,
2808
                                      GtkSelectionData *selection_data,
2809
                                      guint info, guint time, gpointer data)
2810
{
2811
        if (info == DRAG_TYPE_OBJ) {
2812
                gtk_selection_data_set(selection_data, selection_data->target,
2813
                                       8, (guchar *)"drag-from-list", 14);
2814
        }
2815
}
2816
2817
static gchar *addressbook_format_item_list(ItemPerson *person, ItemEMail *email)
2818
{
2819
        gchar *str = NULL;
2820
        gchar *eMailAlias = ADDRITEM_NAME(email);
2821
2822
        if (eMailAlias && *eMailAlias != '\0') {
2823
                if (person) {
2824
                        str = g_strdup_printf("%s - %s", ADDRITEM_NAME(person), eMailAlias);
2825
                } else {
2826
                        str = g_strdup(eMailAlias);
2827
                }
2828
        }
2829
        return str;
2830
}
2831
2832
static gboolean addressbook_match_item(const gchar *name,
2833
                                       const gchar *email_alias,
2834
                                       const gchar *addr,
2835
                                       const gchar *remarks,
2836
                                       const gchar *str)
2837
{
2838
        if (!name)
2839
                return FALSE;
2840
        if (!str || str[0] == '\0')
2841
                return TRUE;
2842
        if (strcasestr(name, str))
2843
                return TRUE;
2844
        else if (email_alias && strcasestr(email_alias, str))
2845
                return TRUE;
2846
        else if (addr && strcasestr(addr, str))
2847
                return TRUE;
2848
        else if (remarks && strcasestr(remarks, str))
2849
                return TRUE;
2850
2851
        return FALSE;
2852
}
2853
2854
static void addressbook_load_group(ItemGroup *itemGroup)
2855
{
2856
        GtkTreeView *listview = GTK_TREE_VIEW(addrbook.listview);
2857
        GtkTreeModel *model;
2858
        GtkTreeIter iter;
2859
        GList *items = itemGroup->listEMail;
2860
        AddressTypeControlItem *atci = addrbookctl_lookup(ADDR_ITEM_EMAIL);
2861
        const gchar *search_str;
2862
2863
        model = gtk_tree_view_get_model(listview);
2864
        search_str = gtk_entry_get_text(GTK_ENTRY(addrbook.entry));
2865
2866
        for (; items != NULL; items = g_list_next(items)) {
2867
                ItemEMail *email = items->data;
2868
                ItemPerson *person;
2869
                const gchar *name;
2870
                gchar *str;
2871
2872
                if (!email) continue;
2873
2874
                person = (ItemPerson *)ADDRITEM_PARENT(email);
2875
                if (!person) {
2876
                        g_warning("email %p (%s) don't have parent\n", email, email->address);
2877
                        continue;
2878
                }
2879
                if (!addressbook_match_item(ADDRITEM_NAME(person),
2880
                                            ADDRITEM_NAME(email),
2881
                                            email->address, email->remarks,
2882
                                            search_str))
2883
                        continue;
2884
2885
                str = addressbook_format_item_list(person, email);
2886
                if (str) {
2887
                        name = str;
2888
                } else {
2889
                        name = ADDRITEM_NAME(person);
2890
                }
2891
                gtk_tree_store_append(GTK_TREE_STORE(model), &iter, NULL);
2892
                gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
2893
                                   COL_NAME, name,
2894
                                   COL_ADDRESS, email->address ? email->address : "",
2895
                                   COL_REMARKS, email->remarks ? email->remarks : "",
2896
                                   COL_L_OBJ, email,
2897
                                   COL_L_PIXBUF, atci->icon_pixbuf,
2898
                                   -1);
2899
                g_free(str);
2900
        }
2901
}
2902
2903
static void addressbook_folder_load_person(ItemFolder *itemFolder)
2904
{
2905
        GtkTreeView *listview = GTK_TREE_VIEW(addrbook.listview);
2906
        GtkTreeModel *model;
2907
        GList *items;
2908
        AddressTypeControlItem *atci = addrbookctl_lookup(ADDR_ITEM_PERSON);
2909
        AddressTypeControlItem *atciMail = addrbookctl_lookup(ADDR_ITEM_EMAIL);
2910
        const gchar *search_str;
2911
2912
        if (atci == NULL)
2913
                return;
2914
        if (atciMail == NULL)
2915
                return;
2916
2917
        model = gtk_tree_view_get_model(listview);
2918
        search_str = gtk_entry_get_text(GTK_ENTRY(addrbook.entry));
2919
2920
        /* Load email addresses */
2921
        items = addritem_folder_get_person_list(itemFolder);
2922
        for (; items != NULL; items = g_list_next(items)) {
2923
                GtkTreeIter iperson, iemail;
2924
                gboolean flgFirst = TRUE, haveAddr = FALSE;
2925
                ItemPerson *person;
2926
                ItemEMail *email;
2927
                GList *node;
2928
2929
                person = (ItemPerson *)items->data;
2930
                if (!person)
2931
                        continue;
2932
2933
                node = person->listEMail;
2934
                if (node && node->data) {
2935
                        email = node->data;
2936
                        if (!addressbook_match_item(ADDRITEM_NAME(person), ADDRITEM_NAME(email), email->address, email->remarks, search_str))
2937
                                continue;
2938
                } else {
2939
                        if (!addressbook_match_item(ADDRITEM_NAME(person), NULL, NULL, NULL, search_str))
2940
                                continue;
2941
                }
2942
2943
                while (node) {
2944
                        const gchar *name;
2945
2946
                        email = node->data;
2947
                        node = g_list_next(node);
2948
2949
                        if (flgFirst) {
2950
                                /* First email belongs with person */
2951
                                gchar *str = addressbook_format_item_list(person, email);
2952
                                if (str) {
2953
                                        name = str;
2954
                                } else {
2955
                                        name = ADDRITEM_NAME(person);
2956
                                }
2957
2958
                                gtk_tree_store_append(GTK_TREE_STORE(model),
2959
                                                      &iperson, NULL);
2960
                                gtk_tree_store_set(GTK_TREE_STORE(model),
2961
                                                   &iperson,
2962
                                                   COL_NAME, name,
2963
                                                   COL_ADDRESS, email->address ? email->address : "",
2964
                                                   COL_REMARKS, email->remarks ? email->remarks : "",
2965
                                                   COL_L_OBJ, person,
2966
                                                   COL_L_PIXBUF, atci->icon_pixbuf,
2967
                                                   -1);
2968
                                g_free(str);
2969
                        } else {
2970
                                /* Subsequent email is a child node of person */
2971
                                name = ADDRITEM_NAME(email);
2972
                                gtk_tree_store_append(GTK_TREE_STORE(model),
2973
                                                      &iemail, &iperson);
2974
                                gtk_tree_store_set(GTK_TREE_STORE(model),
2975
                                                   &iemail,
2976
                                                   COL_NAME, name,
2977
                                                   COL_ADDRESS, email->address ? email->address : "",
2978
                                                   COL_REMARKS, email->remarks ? email->remarks : "",
2979
                                                   COL_L_OBJ, email,
2980
                                                   COL_L_PIXBUF, atciMail->icon_pixbuf,
2981
                                                   -1);
2982
                        }
2983
                        flgFirst = FALSE;
2984
                        haveAddr = TRUE;
2985
                }
2986
                if (!haveAddr) {
2987
                        /* Have name without EMail */
2988
                        gtk_tree_store_append(GTK_TREE_STORE(model),
2989
                                              &iperson, NULL);
2990
                        gtk_tree_store_set(GTK_TREE_STORE(model),
2991
                                           &iperson,
2992
                                           COL_NAME, ADDRITEM_NAME(person),
2993
                                           COL_ADDRESS, "",
2994
                                           COL_REMARKS, "",
2995
                                           COL_L_OBJ, person,
2996
                                           COL_L_PIXBUF, atci->icon_pixbuf,
2997
                                           -1);
2998
                }
2999
                if (person->isOpened) {
3000
                        GtkTreePath *path;
3001
                        path = gtk_tree_model_get_path(model, &iperson);
3002
                        gtk_tree_view_expand_row(listview, path, TRUE);
3003
                        gtk_tree_path_free(path);
3004
                }
3005
        }
3006
3007
        /* Free up the list */
3008
        mgu_clear_list(items);
3009
        g_list_free(items);
3010
}
3011
3012
static void addressbook_folder_load_group(ItemFolder *itemFolder)
3013
{
3014
        GtkTreeView *listview = GTK_TREE_VIEW(addrbook.listview);
3015
        GtkTreeModel *model;
3016
        GList *items;
3017
        AddressTypeControlItem *atci = addrbookctl_lookup(ADDR_ITEM_GROUP);
3018
        const gchar *search_str;
3019
3020
        if (!atci)
3021
                return;
3022
3023
        model = gtk_tree_view_get_model(listview);
3024
        search_str = gtk_entry_get_text(GTK_ENTRY(addrbook.entry));
3025
3026
        /* Load any groups */
3027
        items = addritem_folder_get_group_list(itemFolder);
3028
        for (; items != NULL; items = g_list_next(items)) {
3029
                GtkTreeIter iter;
3030
                ItemGroup *group = items->data;
3031
3032
                if (!group)
3033
                        continue;
3034
                if (!addressbook_match_item(ADDRITEM_NAME(group),
3035
                                            NULL, NULL, NULL, search_str))
3036
                        continue;
3037
3038
                gtk_tree_store_append(GTK_TREE_STORE(model), &iter, NULL);
3039
                gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
3040
                                   COL_NAME, ADDRITEM_NAME(group),
3041
                                   COL_ADDRESS, "",
3042
                                   COL_REMARKS, "",
3043
                                   COL_L_OBJ, group,
3044
                                   COL_L_PIXBUF, atci->icon_pixbuf,
3045
                                   -1);
3046
        }
3047
3048
        /* Free up the list */
3049
        mgu_clear_list(items);
3050
        g_list_free(items);
3051
}
3052
3053
static AddressDataSource *addressbook_find_datasource(GtkTreeIter *iter)
3054
{
3055
        GtkTreeModel *model;
3056
        GtkTreeIter iter_, parent;
3057
        AddressDataSource *ds = NULL;
3058
        AddressObject *ao;
3059
3060
        g_return_val_if_fail(addrbook.treeview != NULL, NULL);
3061
3062
        model = gtk_tree_view_get_model(GTK_TREE_VIEW(addrbook.treeview));
3063
        parent = *iter;
3064
3065
        do {
3066
                iter_ = parent;
3067
                if (gtk_tree_store_iter_depth(GTK_TREE_STORE(model), &iter_) < 1)
3068
                        return NULL;
3069
                ao = NULL;
3070
                gtk_tree_model_get(model, &iter_, COL_OBJ, &ao, -1);
3071
                if (ao) {
3072
                        /* g_print("ao->type = %d\n", ao->type); */
3073
                        if (ao->type == ADDR_DATASOURCE) {
3074
                                AdapterDSource *ads = ADAPTER_DSOURCE(ao);
3075
                                /* g_print("found it\n"); */
3076
                                ds = ads->dataSource;
3077
                                break;
3078
                        }
3079
                }
3080
        } while (gtk_tree_model_iter_parent(model, &parent, &iter_));
3081
3082
        return ds;
3083
}
3084
3085
/*
3086
* Load address list widget with children of specified object.
3087
* Enter: obj        Parent object to be loaded.
3088
*/
3089
static void addressbook_set_list(AddressObject *obj)
3090
{
3091
        GtkTreeView *listview = GTK_TREE_VIEW(addrbook.listview);
3092
        GtkTreeModel *model;
3093
        AddressDataSource *ds = NULL;
3094
        AdapterDSource *ads = NULL;
3095
        gboolean sorted;
3096
        gint address_list_sort_id = COL_NAME;
3097
        GtkSortType order = GTK_SORT_ASCENDING;
3098
3099
        debug_print("addressbook_set_list\n");
3100
3101
        model = gtk_tree_view_get_model(listview);
3102
3103
        if (obj == NULL) {
3104
                gtk_tree_store_clear(GTK_TREE_STORE(model));
3105
                return;
3106
        }
3107
3108
        if (obj->type == ADDR_INTERFACE) {
3109
                return;
3110
        }
3111
3112
        gtk_tree_store_clear(GTK_TREE_STORE(model));
3113
        sorted = gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(model),
3114
                                                      &address_list_sort_id,
3115
                                                      &order);
3116
        if (!sorted) {
3117
                address_list_sort_id = COL_NAME;
3118
                order = GTK_SORT_ASCENDING;
3119
        }
3120
        gtkut_tree_sortable_unset_sort_column_id(GTK_TREE_SORTABLE(model));
3121
3122
        if (obj->type == ADDR_DATASOURCE) {
3123
                ads = ADAPTER_DSOURCE(obj);
3124
                ds = ADAPTER_DSOURCE(obj)->dataSource;
3125
                if (ds) {
3126
                        /* Load root folder */
3127
                        ItemFolder *rootFolder = NULL;
3128
                        rootFolder = addrindex_ds_get_root_folder(ds);
3129
                        addressbook_folder_load_person(addrindex_ds_get_root_folder(ds));
3130
                        addressbook_folder_load_group(addrindex_ds_get_root_folder(ds));
3131
                }
3132
        } else if (obj->type == ADDR_ITEM_GROUP) {
3133
                /* Load groups */
3134
                ItemGroup *itemGroup = ADAPTER_GROUP(obj)->itemGroup;
3135
                addressbook_load_group(itemGroup);
3136
        } else if (obj->type == ADDR_ITEM_FOLDER) {
3137
                /* Load folders */
3138
                ItemFolder *itemFolder = ADAPTER_FOLDER(obj)->itemFolder;
3139
                addressbook_folder_load_person(itemFolder);
3140
                addressbook_folder_load_group(itemFolder);
3141
        }
3142
3143
        gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model),
3144
                                             address_list_sort_id, order);
3145
}
3146
3147
/*
3148
* Free adaptor for specified node.
3149
*/
3150
static void addressbook_free_adapter(GtkTreeIter *iter)
3151
{
3152
        GtkTreeModel *model;
3153
        AddressObject *ao = NULL;
3154
3155
        g_return_if_fail(addrbook.treeview != NULL);
3156
        g_return_if_fail(iter != NULL);
3157
3158
        model = gtk_tree_view_get_model(GTK_TREE_VIEW(addrbook.treeview));
3159
        if (gtk_tree_store_iter_depth(GTK_TREE_STORE(model), iter) < 1)
3160
                return;
3161
        gtk_tree_model_get(model, iter, COL_OBJ, &ao, -1);
3162
        if (ao == NULL)
3163
                return;
3164
3165
        if (ao->type == ADDR_INTERFACE) {
3166
                AdapterInterface *ai = ADAPTER_INTERFACE(ao);
3167
                addrbookctl_free_interface(ai);
3168
        } else if (ao->type == ADDR_DATASOURCE) {
3169
                AdapterDSource *ads = ADAPTER_DSOURCE(ao);
3170
                addrbookctl_free_datasource(ads);
3171
        } else if (ao->type == ADDR_ITEM_FOLDER) {
3172
                AdapterFolder *af = ADAPTER_FOLDER(ao);
3173
                addrbookctl_free_folder(af);
3174
        } else if (ao->type == ADDR_ITEM_GROUP) {
3175
                AdapterGroup *ag = ADAPTER_GROUP(ao);
3176
                addrbookctl_free_group(ag);
3177
        }
3178
3179
        gtk_tree_store_set(GTK_TREE_STORE(model), iter, COL_OBJ, NULL, -1);
3180
}
3181
3182
/*
3183
* Free all children adapters.
3184
*/
3185
static void addressbook_free_child_adapters(GtkTreeIter *iter)
3186
{
3187
        GtkTreeModel *model;
3188
        GtkTreeIter child;
3189
        gboolean valid;
3190
3191
        g_return_if_fail(iter != NULL);
3192
3193
        model = gtk_tree_view_get_model(GTK_TREE_VIEW(addrbook.treeview));
3194
        valid = gtk_tree_model_iter_children(model, &child, iter);
3195
        while (valid) {
3196
                addressbook_free_child_adapters(&child);
3197
                addressbook_free_adapter(&child);
3198
                valid = gtk_tree_model_iter_next(model, &child);
3199
        }
3200
}
3201
3202
AdapterDSource *addressbook_create_ds_adapter(AddressDataSource *ds,
3203
                                              AddressObjectType otype,
3204
                                              gchar *name)
3205
{
3206
        AdapterDSource *adapter = g_new0(AdapterDSource, 1);
3207
        ADDRESS_OBJECT(adapter)->type = ADDR_DATASOURCE;
3208
        ADDRESS_OBJECT_NAME(adapter) = g_strdup(name);
3209
        adapter->dataSource = ds;
3210
        adapter->subType = otype;
3211
        return adapter;
3212
}
3213
3214
void addressbook_ads_set_name(AdapterDSource *adapter, gchar *value)
3215
{
3216
        ADDRESS_OBJECT_NAME(adapter) =
3217
                mgu_replace_string(ADDRESS_OBJECT_NAME(adapter), value);
3218
}
3219
3220
/*
3221
 * Load tree from address index with the initial data.
3222
 */
3223
static void addressbook_load_tree(void)
3224
{
3225
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
3226
        GtkTreeModel *model;
3227
        GtkTreeIter iter, new_iter;
3228
        GtkTreePath *path;
3229
        GList *nodeIf, *nodeDS;
3230
        AdapterInterface *adapter;
3231
        AddressInterface *iface;
3232
        AddressTypeControlItem *atci;
3233
        AddressDataSource *ds;
3234
        AdapterDSource *ads;
3235
        gchar *name;
3236
3237
        model = gtk_tree_view_get_model(treeview);
3238
3239
        nodeIf = _addressInterfaceList_;
3240
        while (nodeIf) {
3241
                adapter = nodeIf->data;
3242
                gtkut_tree_row_reference_get_iter(model, adapter->tree_row, &iter);
3243
                iface = adapter->iface;
3244
                atci = adapter->atci;
3245
                if (iface) {
3246
                        if (iface->useInterface) {
3247
                                /* Load data sources below interface node */
3248
                                nodeDS = iface->listSource;
3249
                                while (nodeDS) {
3250
                                        ds = nodeDS->data;
3251
                                        name = addrindex_ds_get_name(ds);
3252
                                        ads = addressbook_create_ds_adapter(ds, atci->objectType, name);
3253
                                        addressbook_add_object(&iter, &new_iter, ADDRESS_OBJECT(ads));
3254
                                        nodeDS = g_list_next( nodeDS );
3255
                                }
3256
                                path = gtk_tree_model_get_path(model, &iter);
3257
                                gtk_tree_view_expand_row(treeview, path, TRUE);
3258
                                gtk_tree_path_free(path);
3259
                        }
3260
                }
3261
                nodeIf = g_list_next(nodeIf);
3262
        }
3263
}
3264
3265
/*
3266
 * Convert the old address book to new format.
3267
 */
3268
static gboolean addressbook_convert(AddressIndex *addrIndex)
3269
{
3270
        gboolean retVal = FALSE;
3271
        gboolean errFlag = TRUE;
3272
        gchar *msg = NULL;
3273
3274
        /* Read old address book, performing conversion */
3275
        debug_print( "Reading and converting old address book...\n" );
3276
        addrindex_set_file_name( addrIndex, ADDRESSBOOK_OLD_FILE );
3277
        addrindex_read_data( addrIndex );
3278
        if( addrIndex->retVal == MGU_NO_FILE ) {
3279
                /* We do not have a file - new user */
3280
                debug_print( "New user... create new books...\n" );
3281
                addrindex_create_new_books( addrIndex );
3282
                if( addrIndex->retVal == MGU_SUCCESS ) {
3283
                        /* Save index file */
3284
                        addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
3285
                        addrindex_save_data( addrIndex );
3286
                        if( addrIndex->retVal == MGU_SUCCESS ) {
3287
                                retVal = TRUE;
3288
                                errFlag = FALSE;
3289
                        }
3290
                        else {
3291
                                msg = _( "New user, could not save index file." );
3292
                        }
3293
                }
3294
                else {
3295
                        msg = _( "New user, could not save address book files." );
3296
                }
3297
        }
3298
        else {
3299
                /* We have an old file */
3300
                if( addrIndex->wasConverted ) {
3301
                        /* Converted successfully - save address index */
3302
                        addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
3303
                        addrindex_save_data( addrIndex );
3304
                        if( addrIndex->retVal == MGU_SUCCESS ) {
3305
                                msg = _( "Old address book converted successfully." );
3306
                                retVal = TRUE;
3307
                                errFlag = FALSE;
3308
                        }
3309
                        else {
3310
                                msg = _("Old address book converted,\n"
3311
                                        "could not save new address index file" );
3312
                        }
3313
                }
3314
                else {
3315
                        /* File conversion failed - just create new books */
3316
                        debug_print( "File conversion failed... just create new books...\n" );
3317
                        addrindex_create_new_books( addrIndex );
3318
                        if( addrIndex->retVal == MGU_SUCCESS ) {
3319
                                /* Save index */
3320
                                addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
3321
                                addrindex_save_data( addrIndex );
3322
                                if( addrIndex->retVal == MGU_SUCCESS ) {
3323
                                        msg = _("Could not convert address book,\n"
3324
                                                "but created empty new address book files." );
3325
                                        retVal = TRUE;
3326
                                        errFlag = FALSE;
3327
                                }
3328
                                else {
3329
                                        msg = _("Could not convert address book,\n"
3330
                                                "could not create new address book files." );
3331
                                }
3332
                        }
3333
                        else {
3334
                                msg = _("Could not convert address book\n"
3335
                                        "and could not create new address book files." );
3336
                        }
3337
                }
3338
        }
3339
        if( errFlag ) {
3340
                debug_print( "Error\n%s\n", msg );
3341
                alertpanel( _( "Address book conversion error" ), msg, GTK_STOCK_CLOSE, NULL, NULL );
3342
        }
3343
        else if( msg ) {
3344
                debug_print( "Warning\n%s\n", msg );
3345
                alertpanel( _( "Address book conversion" ), msg, GTK_STOCK_CLOSE, NULL, NULL );
3346
        }
3347
3348
        return retVal;
3349
}
3350
3351
void addressbook_read_file(void)
3352
{
3353
        AddressIndex *addrIndex = NULL;
3354
3355
        debug_print( "Reading address index...\n" );
3356
        if (_addressIndex_) {
3357
                debug_print("address book already read!\n");
3358
                return;
3359
        }
3360
3361
        addrIndex = addrindex_create_index();
3362
3363
        /* Use new address book index. */
3364
        addrindex_set_file_path(addrIndex, get_rc_dir());
3365
        addrindex_set_file_name(addrIndex, ADDRESSBOOK_INDEX_FILE);
3366
        addrindex_read_data(addrIndex);
3367
        if (addrIndex->retVal == MGU_NO_FILE) {
3368
                /* Conversion required */
3369
                debug_print("Converting...\n");
3370
                if (addressbook_convert(addrIndex)) {
3371
                        addrindex_create_extra_books(addrIndex);
3372
                        _addressIndex_ = addrIndex;
3373
                }
3374
        } else if (addrIndex->retVal == MGU_SUCCESS) {
3375
                addrindex_create_extra_books(addrIndex);
3376
                _addressIndex_ = addrIndex;
3377
        } else {
3378
                gchar msg[1024];
3379
3380
                /* Error reading address book */
3381
                debug_print("Could not read address index.\n");
3382
                addrindex_print_index(addrIndex, stdout);
3383
                g_snprintf(msg, sizeof(msg),
3384
                           _("Could not read address index:\n\n%s%c%s"),
3385
                           addrIndex->filePath, G_DIR_SEPARATOR,
3386
                           addrIndex->fileName);
3387
                alertpanel_message(_("Address Book Error"), msg, ALERT_ERROR);
3388
        }
3389
        debug_print( "done.\n" );
3390
}
3391
3392
#if 0
3393
void addressbook_read_file_old( void ) {
3394
        AddressIndex *addrIndex = NULL;
3395
        gboolean errFlag = TRUE;
3396
        gchar *msg = NULL;
3397
3398
        if( _addressIndex_ ) {
3399
                debug_print( "address book already read!!!\n" );
3400
                return;
3401
        }
3402
3403
        addrIndex = addrindex_create_index();
3404
3405
        /* Use use new address book. */
3406
        /* addrindex_set_file_path( addrIndex, "/home/match/tmp/empty-dir" ); */
3407
        addrindex_set_file_path( addrIndex, get_rc_dir() );
3408
        addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
3409
3410
        debug_print( "Reading address index...\n" );
3411
        addrindex_read_data( addrIndex );
3412
        if( addrIndex->retVal == MGU_NO_FILE ) {
3413
                /* Read old address book, performing conversion */
3414
                debug_print( "Reading and converting old address book...\n" );
3415
                addrindex_set_file_name( addrIndex, ADDRESSBOOK_OLD_FILE );
3416
                addrindex_read_data( addrIndex );
3417
                if( addrIndex->retVal == MGU_NO_FILE ) {
3418
                        /* We do not have a file - new user */
3419
                        debug_print( "New user... create new books...\n" );
3420
                        addrindex_create_new_books( addrIndex );
3421
                        if( addrIndex->retVal == MGU_SUCCESS ) {
3422
                                /* Save index file */
3423
                                addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
3424
                                addrindex_save_data( addrIndex );
3425
                                if( addrIndex->retVal == MGU_SUCCESS ) {
3426
                                        errFlag = FALSE;
3427
                                }
3428
                                else {
3429
                                        msg = g_strdup( _( "New user, could not save index file." ) );
3430
                                }
3431
                        }
3432
                        else {
3433
                                msg = g_strdup( _( "New user, could not save address book files." ) );
3434
                        }
3435
                }
3436
                else {
3437
                        /* We have an old file */
3438
                        if( addrIndex->wasConverted ) {
3439
                                /* Converted successfully - save address index */
3440
                                addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
3441
                                addrindex_save_data( addrIndex );
3442
                                if( addrIndex->retVal == MGU_SUCCESS ) {
3443
                                        msg = g_strdup( _( "Old address book converted successfully." ) );
3444
                                        errFlag = FALSE;
3445
                                }
3446
                                else {
3447
                                        msg = g_strdup( _(
3448
                                                "Old address book converted, " \
3449
                                                "could not save new address index file" ) );
3450
                                }
3451
                        }
3452
                        else {
3453
                                /* File conversion failed - just create new books */
3454
                                debug_print( "File conversion failed... just create new books...\n" );
3455
                                addrindex_create_new_books( addrIndex );
3456
                                if( addrIndex->retVal == MGU_SUCCESS ) {
3457
                                        /* Save index */
3458
                                        addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
3459
                                        addrindex_save_data( addrIndex );
3460
                                        if( addrIndex->retVal == MGU_SUCCESS ) {
3461
                                                msg = g_strdup( _(
3462
                                                        "Could not convert address book, " \
3463
                                                        "but created empty new address book files." ) );
3464
                                                errFlag = FALSE;
3465
                                        }
3466
                                        else {
3467
                                                msg = g_strdup( _(
3468
                                                        "Could not convert address book, " \
3469
                                                        "could not create new address book files." ) );
3470
                                        }
3471
                                }
3472
                                else {
3473
                                        msg = g_strdup( _(
3474
                                                "Could not convert address book " \
3475
                                                "and could not create new address book files." ) );
3476
                                }
3477
                        }
3478
                }
3479
        }
3480
        else if( addrIndex->retVal == MGU_SUCCESS ) {
3481
                errFlag = FALSE;
3482
        }
3483
        else {
3484
                debug_print( "Could not read address index.\n" );
3485
                addrindex_print_index( addrIndex, stdout );
3486
                msg = g_strdup( _( "Could not read address index" ) );
3487
        }
3488
        _addressIndex_ = addrIndex;
3489
3490
        if( errFlag ) {
3491
                debug_print( "Error\n%s\n", msg );
3492
                alertpanel( _( "Address Book Conversion Error" ), msg,
3493
                            GTK_STOCK_CLOSE, NULL, NULL );
3494
        }
3495
        else {
3496
                if( msg ) {
3497
                        debug_print( "Warning\n%s\n", msg );
3498
                        alertpanel( _( "Address Book Conversion" ), msg,
3499
                                    GTK_STOCK_CLOSE, NULL, NULL );
3500
                }
3501
        }
3502
        if( msg ) g_free( msg );
3503
        debug_print( "done.\n" );
3504
}
3505
#endif
3506
3507
/*
3508
* Add object into the address index tree widget.
3509
* Enter: node        Parent node.
3510
*        obj        Object to add.
3511
* Return: Node that was added, or NULL if object not added.
3512
*/
3513
static gboolean addressbook_add_object(GtkTreeIter *iter, GtkTreeIter *new_iter,
3514
                                       AddressObject *obj)
3515
{
3516
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
3517
        GtkTreeModel *model;
3518
        GtkTreeIter added;
3519
        AddressObject *pobj;
3520
        AddressObjectType otype;
3521
        AddressTypeControlItem *atci = NULL;
3522
        const gchar *name;
3523
3524
        g_return_val_if_fail(iter != NULL, FALSE);
3525
        g_return_val_if_fail(obj  != NULL, FALSE);
3526
3527
        model = gtk_tree_view_get_model(treeview);
3528
        gtk_tree_model_get(model, iter, COL_OBJ, &pobj, -1);
3529
        g_return_val_if_fail(pobj != NULL, FALSE);
3530
3531
        /* Determine object type to be displayed */
3532
        if (obj->type == ADDR_DATASOURCE) {
3533
                otype = ADAPTER_DSOURCE(obj)->subType;
3534
        } else {
3535
                otype = obj->type;
3536
        }
3537
3538
        /* Handle any special conditions. */
3539
        atci = addrbookctl_lookup(otype);
3540
        if (atci && atci->showInTree) {
3541
                /* Add object to tree */
3542
                debug_print("addressbook_add_object: obj: %s\n", obj->name);
3543
                if (otype == ADDR_BOOK && obj->name &&
3544
                    !strcmp(obj->name, ADDR_DS_AUTOREG))
3545
                        name = _("Auto-registered address");
3546
                else
3547
                        name = obj->name;
3548
                gtk_tree_store_append(GTK_TREE_STORE(model), &added, iter);
3549
                gtk_tree_store_set(GTK_TREE_STORE(model), &added,
3550
                                   COL_FOLDER_NAME, name,
3551
                                   COL_OBJ, obj,
3552
                                   COL_PIXBUF, atci->icon_pixbuf,
3553
                                   COL_PIXBUF_OPEN, atci->icon_open_pixbuf,
3554
                                   -1);
3555
                if (new_iter)
3556
                        *new_iter = added;
3557
                return TRUE;
3558
        }
3559
3560
        return FALSE;
3561
}
3562
3563
/*
3564
* Add group into the address index tree.
3565
* Enter: node           Parent node.
3566
*        ds        Data source.
3567
*        itemGroup Group to add.
3568
* Return: Inserted node.
3569
*/
3570
static gboolean addressbook_node_add_group(GtkTreeIter *iter, AddressDataSource *ds, ItemGroup *itemGroup, GtkTreeIter *new_iter)
3571
{
3572
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
3573
        GtkTreeStore *store;
3574
        GtkTreeIter new_iter_;
3575
        AdapterGroup *adapter;
3576
        AddressTypeControlItem *atci = NULL;
3577
        gchar *name;
3578
3579
        if(ds == NULL) return FALSE;
3580
        if(iter == NULL || itemGroup == NULL) return FALSE;
3581
3582
        name = itemGroup->obj.name;
3583
3584
        atci = addrbookctl_lookup(ADDR_ITEM_GROUP);
3585
3586
        adapter = g_new0(AdapterGroup, 1);
3587
        ADDRESS_OBJECT_TYPE(adapter) = ADDR_ITEM_GROUP;
3588
        ADDRESS_OBJECT_NAME(adapter) = g_strdup(ADDRITEM_NAME(itemGroup));
3589
        adapter->itemGroup = itemGroup;
3590
3591
        debug_print("addressbook_node_add_group: name: %s\n", name);
3592
        store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
3593
        gtk_tree_store_append(store, &new_iter_, iter);
3594
        gtk_tree_store_set(store, &new_iter_,
3595
                           COL_FOLDER_NAME, name,
3596
                           COL_OBJ, adapter,
3597
                           COL_PIXBUF, atci->icon_pixbuf,
3598
                           COL_PIXBUF_OPEN, atci->icon_open_pixbuf,
3599
                           -1);
3600
        if (new_iter)
3601
                *new_iter = new_iter_;
3602
        return TRUE;
3603
}
3604
3605
/*
3606
* Add folder into the address index tree.
3607
* Enter: iter            Parent node.
3608
*        ds         Data source.
3609
*        itemFolder Folder to add.
3610
*        otype      Object type to display.
3611
*        new_iter   Inserted node.
3612
* Return: TRUE if inserted.
3613
*/
3614
static gboolean addressbook_node_add_folder(GtkTreeIter *iter, AddressDataSource *ds, ItemFolder *itemFolder, AddressObjectType otype, GtkTreeIter *new_iter)
3615
{
3616
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
3617
        GtkTreeStore *store;
3618
        GtkTreeIter new_iter_;
3619
        AdapterFolder *adapter;
3620
        AddressTypeControlItem *atci = NULL;
3621
        GList *listItems = NULL;
3622
        gchar *name;
3623
        ItemFolder *rootFolder;
3624
3625
        if (ds == NULL)
3626
                return FALSE;
3627
        if (iter == NULL || itemFolder == NULL)
3628
                return FALSE;
3629
3630
        /* Determine object type */
3631
        atci = addrbookctl_lookup(otype);
3632
        if (atci == NULL)
3633
                return FALSE;
3634
3635
        store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
3636
3637
        rootFolder = addrindex_ds_get_root_folder(ds);
3638
        if (itemFolder == rootFolder) {
3639
                new_iter_ = *iter;
3640
        } else {
3641
                name = itemFolder->obj.name;
3642
3643
                adapter = g_new0(AdapterFolder, 1);
3644
                ADDRESS_OBJECT_TYPE(adapter) = ADDR_ITEM_FOLDER;
3645
                ADDRESS_OBJECT_NAME(adapter) = g_strdup(ADDRITEM_NAME(itemFolder));
3646
                adapter->itemFolder = itemFolder;
3647
3648
                debug_print("addressbook_node_add_folder: name: %s\n", name);
3649
                gtk_tree_store_append(store, &new_iter_, iter);
3650
                gtk_tree_store_set(store, &new_iter_,
3651
                                   COL_FOLDER_NAME, name,
3652
                                   COL_OBJ, adapter,
3653
                                   COL_PIXBUF, atci->icon_pixbuf,
3654
                                   COL_PIXBUF_OPEN, atci->icon_open_pixbuf,
3655
                                   -1);
3656
        }
3657
3658
        listItems = itemFolder->listFolder;
3659
        while (listItems) {
3660
                ItemFolder *item = listItems->data;
3661
                addressbook_node_add_folder(&new_iter_, ds, item, otype, NULL);
3662
                listItems = g_list_next(listItems);
3663
        }
3664
        listItems = itemFolder->listGroup;
3665
        while (listItems) {
3666
                ItemGroup *item = listItems->data;
3667
                addressbook_node_add_group(&new_iter_, ds, item, NULL);
3668
                listItems = g_list_next(listItems);
3669
        }
3670
        if (new_iter)
3671
                *new_iter = new_iter_;
3672
        return TRUE;
3673
}
3674
3675
#if 0
3676
static void addressbook_delete_object(AddressObject *obj) {
3677
        AdapterDSource *ads = NULL;
3678
        AddressDataSource *ds = NULL;
3679
        if (!obj) return;
3680
3681
        /* Remove data source. */
3682
        /* printf( "Delete obj type : %d\n", obj->type ); */
3683
3684
        ads = ADAPTER_DSOURCE(obj);
3685
        if( ads == NULL ) return;
3686
        ds = ads->dataSource;
3687
        if( ds == NULL ) return;
3688
3689
        /* Remove data source */
3690
        if( addrindex_index_remove_datasource( _addressIndex_, ds ) ) {
3691
                addrindex_free_datasource( _addressIndex_, ds );
3692
        }
3693
        /* Free up Adapter object */
3694
        g_free( ADAPTER_DSOURCE(obj) );
3695
}
3696
#endif
3697
3698
void addressbook_export_to_file( void ) {
3699
        if( _addressIndex_ ) {
3700
                /* Save all new address book data */
3701
                debug_print( "Saving address books...\n" );
3702
                addrindex_save_all_books( _addressIndex_ );
3703
3704
                debug_print( "Exporting addressbook to file...\n" );
3705
                addrindex_save_data( _addressIndex_ );
3706
                if( _addressIndex_->retVal != MGU_SUCCESS ) {
3707
                        addrindex_print_index( _addressIndex_, stdout );
3708
                }
3709
3710
                /* Notify address completion of new data */
3711
                addressbook_modified();
3712
        }
3713
}
3714
3715
static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event,
3716
                            gpointer data)
3717
{
3718
        if (event && event->keyval == GDK_Escape)
3719
                addressbook_close();
3720
        return FALSE;
3721
}
3722
3723
static void size_allocated(GtkWidget *widget, GtkAllocation *allocation,
3724
                           gpointer data)
3725
{
3726
        if (allocation->width <= 1 || allocation->height <= 1)
3727
                return;
3728
3729
        prefs_common.addressbook_width = allocation->width;
3730
        prefs_common.addressbook_height = allocation->height;
3731
}
3732
3733
/*
3734
* Comparison using cell contents (text in first column).
3735
*/
3736
static gint addressbook_tree_compare(GtkTreeModel *model, GtkTreeIter *a,
3737
                                     GtkTreeIter *b, gpointer data)
3738
{
3739
        gchar *name1 = NULL, *name2 = NULL;
3740
        AddressObject *obj1 = NULL, *obj2 = NULL;
3741
        gint ret;
3742
3743
        gtk_tree_model_get(model, a, COL_FOLDER_NAME, &name1, COL_OBJ, &obj1,
3744
                           -1);
3745
        gtk_tree_model_get(model, b, COL_FOLDER_NAME, &name2, COL_OBJ, &obj2,
3746
                           -1);
3747
3748
        /* Do not sort toplevel row */
3749
        if (obj1 && obj1->type == ADDR_INTERFACE)
3750
                return 0;
3751
3752
        if (!name1 || !name2) {
3753
                if (!name1)
3754
                        ret = (name2 != NULL);
3755
                else
3756
                        ret = -1;
3757
                g_free(name2);
3758
                g_free(name1);
3759
                return ret;
3760
        }
3761
        ret = g_ascii_strcasecmp(name1, name2);
3762
        g_free(name2);
3763
        g_free(name1);
3764
        return ret;
3765
}
3766
3767
static gint addressbook_list_col_compare(GtkTreeModel *model, GtkTreeIter *a,
3768
                                         GtkTreeIter *b, gint col)
3769
{
3770
        gchar *name1 = NULL, *name2 = NULL;
3771
        gint ret;
3772
3773
        gtk_tree_model_get(model, a, col, &name1, -1);
3774
        gtk_tree_model_get(model, b, col, &name2, -1);
3775
3776
        if (!name1)
3777
                name1 = g_strdup("");
3778
        if (!name2)
3779
                name2 = g_strdup("");
3780
        ret = g_ascii_strcasecmp(name1, name2);
3781
        g_free(name2);
3782
        g_free(name1);
3783
        return ret;
3784
}
3785
3786
static gint addressbook_list_name_compare(GtkTreeModel *model, GtkTreeIter *a,
3787
                                          GtkTreeIter *b, gpointer data)
3788
{
3789
        gint ret;
3790
3791
        ret = addressbook_list_col_compare(model, a, b, COL_NAME);
3792
        if (ret == 0)
3793
                ret = addressbook_list_col_compare(model, a, b, COL_ADDRESS);
3794
        if (ret == 0)
3795
                ret = addressbook_list_col_compare(model, a, b, COL_REMARKS);
3796
3797
        return ret;
3798
}
3799
3800
static gint addressbook_list_address_compare(GtkTreeModel *model,
3801
                                             GtkTreeIter *a, GtkTreeIter *b,
3802
                                             gpointer data)
3803
{
3804
        gint ret;
3805
3806
        ret = addressbook_list_col_compare(model, a, b, COL_ADDRESS);
3807
        if (ret == 0)
3808
                ret = addressbook_list_col_compare(model, a, b, COL_NAME);
3809
        if (ret == 0)
3810
                ret = addressbook_list_col_compare(model, a, b, COL_REMARKS);
3811
3812
        return ret;
3813
}
3814
3815
static gint addressbook_list_remarks_compare(GtkTreeModel *model,
3816
                                             GtkTreeIter *a, GtkTreeIter *b,
3817
                                             gpointer data)
3818
{
3819
        gint ret;
3820
3821
        ret = addressbook_list_col_compare(model, a, b, COL_REMARKS);
3822
        if (ret == 0)
3823
                ret = addressbook_list_col_compare(model, a, b, COL_NAME);
3824
        if (ret == 0)
3825
                ret = addressbook_list_col_compare(model, a, b, COL_ADDRESS);
3826
3827
        return ret;
3828
}
3829
3830
static gboolean addressbook_list_select_func(GtkTreeSelection *selection,
3831
                                             GtkTreeModel *model,
3832
                                             GtkTreePath *path,
3833
                                             gboolean cur_selected,
3834
                                             gpointer data)
3835
{
3836
        return can_toggle_list_selection;
3837
}
3838
3839
/* static */ 
3840
gint addressbook_obj_name_compare(gconstpointer a, gconstpointer b)
3841
{
3842
        const AddressObject *obj = a;
3843
        const gchar *name = b;
3844
        AddressTypeControlItem *atci = NULL;
3845
3846
        if (!obj || !name) return -1;
3847
3848
        atci = addrbookctl_lookup( obj->type );
3849
        if( ! atci ) return -1;
3850
        if( ! obj->name ) return -1;
3851
        return g_ascii_strcasecmp(obj->name, name);
3852
}
3853
3854
#if 0
3855
static void addressbook_book_show_message( AddressBookFile *abf ) {
3856
        gchar msgbuf[ADDRESSBOOK_MSGBUF_SIZE] = "";
3857
3858
        if (abf) {
3859
                if (abf->retVal == MGU_SUCCESS) {
3860
                        g_snprintf(msgbuf, sizeof(msgbuf), "%s", abf->name);
3861
                } else {
3862
                        g_snprintf(msgbuf, sizeof(msgbuf), "%s: %s", abf->name, mgu_error2string(abf->retVal));
3863
                }
3864
        }
3865
        addressbook_status_show(msgbuf);
3866
}
3867
#endif
3868
3869
static void addressbook_new_book_cb(gpointer data, guint action, GtkWidget *widget)
3870
{
3871
        GtkTreeModel *model;
3872
        GtkTreeIter iter;
3873
        AdapterDSource *ads;
3874
        AdapterInterface *adapter;
3875
3876
        adapter = addrbookctl_find_interface(ADDR_IF_BOOK);
3877
        if (adapter == NULL)
3878
                return;
3879
        if (!gtkut_tree_row_reference_equal(addrbook.tree_selected, adapter->tree_row))
3880
                return;
3881
3882
        model = gtk_tree_view_get_model(GTK_TREE_VIEW(addrbook.treeview));
3883
        gtkut_tree_row_reference_get_iter(model, addrbook.tree_selected, &iter);
3884
3885
        ads = addressbook_edit_book(_addressIndex_, NULL);
3886
        if (ads) {
3887
                addressbook_add_object(&iter, NULL, ADDRESS_OBJECT(ads));
3888
                if (gtkut_tree_row_reference_equal(addrbook.tree_selected, addrbook.tree_opened)) {
3889
                        addressbook_reopen();
3890
                }
3891
        }
3892
}
3893
3894
static void addressbook_new_vcard_cb(gpointer data, guint action, GtkWidget *widget)
3895
{
3896
        GtkTreeModel *model;
3897
        GtkTreeIter iter;
3898
        AdapterDSource *ads;
3899
        AdapterInterface *adapter;
3900
3901
        adapter = addrbookctl_find_interface(ADDR_IF_VCARD);
3902
        if (adapter == NULL)
3903
                return;
3904
        if (!gtkut_tree_row_reference_equal(addrbook.tree_selected, adapter->tree_row))
3905
                return;
3906
3907
        model = gtk_tree_view_get_model(GTK_TREE_VIEW(addrbook.treeview));
3908
        gtkut_tree_row_reference_get_iter(model, addrbook.tree_selected, &iter);
3909
3910
        ads = addressbook_edit_vcard(_addressIndex_, NULL);
3911
        if (ads) {
3912
                addressbook_add_object(&iter, NULL, ADDRESS_OBJECT(ads));
3913
                if (gtkut_tree_row_reference_equal(addrbook.tree_selected, addrbook.tree_opened)) {
3914
                        addressbook_reopen();
3915
                }
3916
                addressbook_modified();
3917
        }
3918
}
3919
3920
#if 0
3921
static void addressbook_vcard_show_message( VCardFile *vcf ) {
3922
        gchar msgbuf[ADDRESSBOOK_MSGBUF_SIZE] = "";
3923
3924
        if (vcf) {
3925
                if (vcf->retVal == MGU_SUCCESS) {
3926
                        g_snprintf(msgbuf, sizeof(msgbuf), "%s", vcf->name);
3927
                } else {
3928
                        g_snprintf(msgbuf, sizeof(msgbuf), "%s: %s", vcf->name, mgu_error2string(vcf->retVal));
3929
                }
3930
        }
3931
        addressbook_status_show(msgbuf);
3932
}
3933
#endif
3934
3935
#ifdef USE_JPILOT
3936
static void addressbook_new_jpilot_cb(gpointer data, guint action, GtkWidget *widget)
3937
{
3938
        GtkTreeModel *model;
3939
        GtkTreeIter iter;
3940
        AdapterDSource *ads;
3941
        AdapterInterface *adapter;
3942
        AddressInterface *iface;
3943
3944
        adapter = addrbookctl_find_interface(ADDR_IF_JPILOT);
3945
        if (adapter == NULL)
3946
                return;
3947
        if (!gtkut_tree_row_reference_equal(addrbook.tree_selected, adapter->tree_row))
3948
                return;
3949
        iface = adapter->iface;
3950
        if (!iface->haveLibrary)
3951
                return;
3952
3953
        model = gtk_tree_view_get_model(GTK_TREE_VIEW(addrbook.treeview));
3954
        gtkut_tree_row_reference_get_iter(model, addrbook.tree_selected, &iter);
3955
3956
        ads = addressbook_edit_jpilot(_addressIndex_, NULL);
3957
        if (ads) {
3958
                addressbook_add_object(&iter, NULL, ADDRESS_OBJECT(ads));
3959
                if (gtkut_tree_row_reference_equal(addrbook.tree_selected, addrbook.tree_opened)) {
3960
                        addressbook_reopen();
3961
                }
3962
        }
3963
}
3964
3965
#if 0
3966
static void addressbook_jpilot_show_message( JPilotFile *jpf ) {
3967
        gchar msgbuf[ADDRESSBOOK_MSGBUF_SIZE] = "";
3968
3969
        if (jpf) {
3970
                if (jpf->retVal == MGU_SUCCESS) {
3971
                        g_snprintf(msgbuf, sizeof(msgbuf), "%s", jpf->name);
3972
                } else {
3973
                        g_snprintf(msgbuf, sizeof(msgbuf), "%s: %s", jpf->name, mgu_error2string(jpf->retVal));
3974
                }
3975
        }
3976
        addressbook_status_show(msgbuf);
3977
}
3978
#endif
3979
#endif /* USE_JPILOT */
3980
3981
#ifdef USE_LDAP
3982
static void addressbook_new_ldap_cb(gpointer data, guint action, GtkWidget *widget)
3983
{
3984
        GtkTreeModel *model;
3985
        GtkTreeIter iter;
3986
        AdapterDSource *ads;
3987
        AdapterInterface *adapter;
3988
        AddressInterface *iface;
3989
3990
        adapter = addrbookctl_find_interface(ADDR_IF_LDAP);
3991
        if (adapter == NULL)
3992
                return;
3993
        if (!gtkut_tree_row_reference_equal(addrbook.tree_selected, adapter->tree_row))
3994
                return;
3995
        iface = adapter->iface;
3996
        if (!iface->haveLibrary)
3997
                return;
3998
3999
        model = gtk_tree_view_get_model(GTK_TREE_VIEW(addrbook.treeview));
4000
        gtkut_tree_row_reference_get_iter(model, addrbook.tree_selected, &iter);
4001
4002
        ads = addressbook_edit_ldap(_addressIndex_, NULL);
4003
        if( ads ) {
4004
                addressbook_add_object(&iter, NULL, ADDRESS_OBJECT(ads));
4005
                if (gtkut_tree_row_reference_equal(addrbook.tree_selected, addrbook.tree_opened)) {
4006
                        addressbook_reopen();
4007
                }
4008
        }
4009
}
4010
4011
static void addressbook_ldap_show_message(SyldapServer *svr)
4012
{
4013
        gchar msgbuf[ADDRESSBOOK_MSGBUF_SIZE] = "";
4014
4015
        if (svr) {
4016
                if (svr->busyFlag) {
4017
                        g_snprintf(msgbuf, sizeof(msgbuf), "%s: %s", svr->name, ADDRESSBOOK_LDAP_BUSYMSG);
4018
                } else {
4019
                        if (svr->retVal == MGU_SUCCESS) {
4020
                                g_snprintf(msgbuf, sizeof(msgbuf), "%s", svr->name);
4021
                        } else {
4022
                                g_snprintf(msgbuf, sizeof(msgbuf), "%s: %s", svr->name, mgu_error2string(svr->retVal));
4023
                        }
4024
                }
4025
        }
4026
        addressbook_status_show(msgbuf);
4027
}
4028
4029
static void ldapsearch_callback(SyldapServer *sls)
4030
{
4031
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
4032
        GtkTreeSelection *selection;
4033
        GtkTreeModel *model;
4034
        GtkTreeIter iter;
4035
        AddressObject *obj;
4036
        AdapterDSource *ads = NULL;
4037
        AddressDataSource *ds = NULL;
4038
        AddressInterface *iface = NULL;
4039
4040
        if (sls == NULL)
4041
                return;
4042
4043
        selection = gtk_tree_view_get_selection(treeview);
4044
        if (!gtk_tree_selection_get_selected(selection, &model, &iter))
4045
                return;
4046
        if (gtk_tree_store_iter_depth(GTK_TREE_STORE(model), &iter) == 0)
4047
                return;
4048
4049
        gtk_tree_model_get(model, &iter, COL_OBJ, &obj, -1);
4050
        if (obj == NULL)
4051
                return;
4052
        if (obj->type == ADDR_DATASOURCE) {
4053
                ads = ADAPTER_DSOURCE(obj);
4054
                if (ads->subType == ADDR_LDAP) {
4055
                        SyldapServer *server;
4056
4057
                        ds = ads->dataSource;
4058
                        if (ds == NULL)
4059
                                return;
4060
                        iface = ds->iface;
4061
                        if (!iface->haveLibrary)
4062
                                return;
4063
                        server = ds->rawDataSource;
4064
                        if (server == sls) {
4065
                                /* Read from cache */
4066
                                gtk_widget_show_all(addrbook.window);
4067
                                addressbook_set_list(obj);
4068
                                addressbook_ldap_show_message(sls);
4069
                                gtk_widget_show_all(addrbook.window);
4070
                                gtk_entry_set_text(GTK_ENTRY(addrbook.entry), "");
4071
                        }
4072
                }
4073
        }
4074
}
4075
#endif
4076
4077
/*
4078
 * Lookup button handler.
4079
 */
4080
static void addressbook_lup_clicked(GtkButton *button, gpointer data)
4081
{
4082
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
4083
        GtkTreeSelection *selection;
4084
        GtkTreeModel *model;
4085
        GtkTreeIter iter;
4086
        AddressObject *obj;
4087
        AdapterDSource *ads = NULL;
4088
#ifdef USE_LDAP
4089
        AddressDataSource *ds = NULL;
4090
        AddressInterface *iface = NULL;
4091
#endif /* USE_LDAP */
4092
        gchar *sLookup;
4093
4094
        selection = gtk_tree_view_get_selection(treeview);
4095
        if (!gtk_tree_selection_get_selected(selection, &model, &iter))
4096
                return;
4097
        if (gtk_tree_store_iter_depth(GTK_TREE_STORE(model), &iter) == 0)
4098
                return;
4099
4100
        gtk_tree_model_get(model, &iter, COL_OBJ, &obj, -1);
4101
        if (obj == NULL)
4102
                return;
4103
4104
        sLookup = gtk_editable_get_chars(GTK_EDITABLE(addrbook.entry), 0, -1);
4105
        g_strstrip(sLookup);
4106
4107
        if (obj->type == ADDR_DATASOURCE) {
4108
                ads = ADAPTER_DSOURCE(obj);
4109
#ifdef USE_LDAP
4110
                if (ads->subType == ADDR_LDAP) {
4111
                        SyldapServer *server;
4112
4113
                        ds = ads->dataSource;
4114
                        if (ds == NULL)
4115
                                return;
4116
                        iface = ds->iface;
4117
                        if (!iface->haveLibrary)
4118
                                return;
4119
                        server = ds->rawDataSource;
4120
                        if (server) {
4121
                                syldap_cancel_read(server);
4122
                                if (*sLookup == '\0' || strlen(sLookup) < 1 )
4123
                                        return;
4124
                                syldap_set_search_value(server, sLookup);
4125
                                syldap_set_callback(server, ldapsearch_callback);
4126
                                syldap_read_data_th(server);
4127
                                addressbook_ldap_show_message(server);
4128
                        }
4129
                } else
4130
#endif /* USE_LDAP */
4131
                        addressbook_set_list(obj);
4132
        } else {
4133
                addressbook_set_list(obj);
4134
        }
4135
4136
        g_free(sLookup);
4137
}
4138
4139
static void addressbook_close_clicked(GtkButton        *button, gpointer data)
4140
{
4141
        addressbook_close();
4142
}
4143
4144
/* **********************************************************************
4145
* Build lookup tables.
4146
* ***********************************************************************
4147
*/
4148
4149
/*
4150
* Build table that controls the rendering of object types.
4151
*/
4152
void addrbookctl_build_map(GtkWidget *window)
4153
{
4154
        AddressTypeControlItem *atci;
4155
4156
        /* Build icons */
4157
        stock_pixbuf_gdk(window, STOCK_PIXMAP_FOLDER_CLOSE, &folderpix);
4158
        stock_pixbuf_gdk(window, STOCK_PIXMAP_FOLDER_OPEN, &folderopenpix);
4159
        stock_pixbuf_gdk(window, STOCK_PIXMAP_GROUP, &grouppix);
4160
        stock_pixbuf_gdk(window, STOCK_PIXMAP_VCARD, &vcardpix);
4161
        stock_pixbuf_gdk(window, STOCK_PIXMAP_BOOK, &bookpix);
4162
        stock_pixbuf_gdk(window, STOCK_PIXMAP_PERSON, &personpix);
4163
        stock_pixbuf_gdk(window, STOCK_PIXMAP_ADDRESS, &addresspix);
4164
        stock_pixbuf_gdk(window, STOCK_PIXMAP_JPILOT, &jpilotpix);
4165
        stock_pixbuf_gdk(window, STOCK_PIXMAP_CATEGORY, &categorypix);
4166
        stock_pixbuf_gdk(window, STOCK_PIXMAP_LDAP, &ldappix);
4167
4168
        _addressBookTypeHash_ = g_hash_table_new(g_int_hash, g_int_equal);
4169
        _addressBookTypeList_ = NULL;
4170
4171
        /* Interface */
4172
        atci = g_new0(AddressTypeControlItem, 1);
4173
        atci->objectType = ADDR_INTERFACE;
4174
        atci->interfaceType = ADDR_IF_NONE;
4175
        atci->showInTree = TRUE;
4176
        atci->treeExpand = TRUE;
4177
        atci->treeLeaf = FALSE;
4178
        atci->displayName = _("Interface");
4179
        atci->icon_pixbuf = folderpix;
4180
        atci->icon_open_pixbuf = folderopenpix;
4181
        atci->menuCommand = NULL;
4182
        g_hash_table_insert(_addressBookTypeHash_, &atci->objectType, atci);
4183
        _addressBookTypeList_ = g_list_append(_addressBookTypeList_, atci);
4184
4185
        /* Address book */
4186
        atci = g_new0(AddressTypeControlItem, 1);
4187
        atci->objectType = ADDR_BOOK;
4188
        atci->interfaceType = ADDR_IF_BOOK;
4189
        atci->showInTree = TRUE;
4190
        atci->treeExpand = TRUE;
4191
        atci->treeLeaf = FALSE;
4192
        atci->displayName = _("Address Book");
4193
        atci->icon_pixbuf = bookpix;
4194
        atci->icon_open_pixbuf = bookpix;
4195
        atci->menuCommand = "/File/New Book";
4196
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
4197
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
4198
4199
        /* Item person */
4200
        atci = g_new0(AddressTypeControlItem, 1);
4201
        atci->objectType = ADDR_ITEM_PERSON;
4202
        atci->interfaceType = ADDR_IF_NONE;
4203
        atci->showInTree = FALSE;
4204
        atci->treeExpand = FALSE;
4205
        atci->treeLeaf = FALSE;
4206
        atci->displayName = _("Person");
4207
        atci->icon_pixbuf = personpix;
4208
        atci->icon_open_pixbuf = personpix;
4209
        atci->menuCommand = NULL;
4210
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
4211
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
4212
4213
        /* Item email */
4214
        atci = g_new0(AddressTypeControlItem, 1);
4215
        atci->objectType = ADDR_ITEM_EMAIL;
4216
        atci->interfaceType = ADDR_IF_NONE;
4217
        atci->showInTree = FALSE;
4218
        atci->treeExpand = FALSE;
4219
        atci->treeLeaf = TRUE;
4220
        atci->displayName = _("EMail Address");
4221
        atci->icon_pixbuf = addresspix;
4222
        atci->icon_open_pixbuf = addresspix;
4223
        atci->menuCommand = NULL;
4224
        g_hash_table_insert(_addressBookTypeHash_, &atci->objectType, atci);
4225
        _addressBookTypeList_ = g_list_append(_addressBookTypeList_, atci);
4226
4227
        /* Item group */
4228
        atci = g_new0(AddressTypeControlItem, 1);
4229
        atci->objectType = ADDR_ITEM_GROUP;
4230
        atci->interfaceType = ADDR_IF_BOOK;
4231
        atci->showInTree = TRUE;
4232
        atci->treeExpand = FALSE;
4233
        atci->treeLeaf = FALSE;
4234
        atci->displayName = _("Group");
4235
        atci->icon_pixbuf = grouppix;
4236
        atci->icon_open_pixbuf = grouppix;
4237
        atci->menuCommand = NULL;
4238
        g_hash_table_insert(_addressBookTypeHash_, &atci->objectType, atci);
4239
        _addressBookTypeList_ = g_list_append(_addressBookTypeList_, atci);
4240
4241
        /* Item folder */
4242
        atci = g_new0(AddressTypeControlItem, 1);
4243
        atci->objectType = ADDR_ITEM_FOLDER;
4244
        atci->interfaceType = ADDR_IF_BOOK;
4245
        atci->showInTree = TRUE;
4246
        atci->treeExpand = FALSE;
4247
        atci->treeLeaf = FALSE;
4248
        atci->displayName = _("Folder");
4249
        atci->icon_pixbuf = folderpix;
4250
        atci->icon_open_pixbuf = folderopenpix;
4251
        atci->menuCommand = NULL;
4252
        g_hash_table_insert(_addressBookTypeHash_, &atci->objectType, atci);
4253
        _addressBookTypeList_ = g_list_append(_addressBookTypeList_, atci);
4254
4255
        /* vCard */
4256
        atci = g_new0(AddressTypeControlItem, 1);
4257
        atci->objectType = ADDR_VCARD;
4258
        atci->interfaceType = ADDR_IF_VCARD;
4259
        atci->showInTree = TRUE;
4260
        atci->treeExpand = TRUE;
4261
        atci->treeLeaf = TRUE;
4262
        atci->displayName = _("vCard");
4263
        atci->icon_pixbuf = vcardpix;
4264
        atci->icon_open_pixbuf = vcardpix;
4265
        atci->menuCommand = "/File/New vCard";
4266
        g_hash_table_insert(_addressBookTypeHash_, &atci->objectType, atci);
4267
        _addressBookTypeList_ = g_list_append(_addressBookTypeList_, atci);
4268
4269
        /* JPilot */
4270
        atci = g_new0(AddressTypeControlItem, 1);
4271
        atci->objectType = ADDR_JPILOT;
4272
        atci->interfaceType = ADDR_IF_JPILOT;
4273
        atci->showInTree = TRUE;
4274
        atci->treeExpand = TRUE;
4275
        atci->treeLeaf = FALSE;
4276
        atci->displayName = _("JPilot");
4277
        atci->icon_pixbuf = jpilotpix;
4278
        atci->icon_open_pixbuf = jpilotpix;
4279
        atci->menuCommand = "/File/New JPilot";
4280
        g_hash_table_insert(_addressBookTypeHash_, &atci->objectType, atci);
4281
        _addressBookTypeList_ = g_list_append(_addressBookTypeList_, atci);
4282
4283
        /* Category */
4284
        atci = g_new0(AddressTypeControlItem, 1);
4285
        atci->objectType = ADDR_CATEGORY;
4286
        atci->interfaceType = ADDR_IF_JPILOT;
4287
        atci->showInTree = TRUE;
4288
        atci->treeExpand = TRUE;
4289
        atci->treeLeaf = TRUE;
4290
        atci->displayName = _("JPilot");
4291
        atci->icon_pixbuf = categorypix;
4292
        atci->icon_open_pixbuf = categorypix;
4293
        atci->menuCommand = NULL;
4294
        g_hash_table_insert(_addressBookTypeHash_, &atci->objectType, atci);
4295
        _addressBookTypeList_ = g_list_append(_addressBookTypeList_, atci);
4296
4297
        /* LDAP Server */
4298
        atci = g_new0(AddressTypeControlItem, 1);
4299
        atci->objectType = ADDR_LDAP;
4300
        atci->interfaceType = ADDR_IF_LDAP;
4301
        atci->showInTree = TRUE;
4302
        atci->treeExpand = TRUE;
4303
        atci->treeLeaf = TRUE;
4304
        atci->displayName = _("LDAP Server");
4305
        atci->icon_pixbuf = ldappix;
4306
        atci->icon_open_pixbuf = ldappix;
4307
        atci->menuCommand = "/File/New LDAP Server";
4308
        g_hash_table_insert(_addressBookTypeHash_, &atci->objectType, atci);
4309
        _addressBookTypeList_ = g_list_append(_addressBookTypeList_, atci);
4310
}
4311
4312
/*
4313
* Search for specified object type.
4314
*/
4315
AddressTypeControlItem *addrbookctl_lookup(gint ot)
4316
{
4317
        gint objType = ot;
4318
        return (AddressTypeControlItem *)g_hash_table_lookup(_addressBookTypeHash_, &objType);
4319
}
4320
4321
/*
4322
* Search for specified interface type.
4323
*/
4324
AddressTypeControlItem *addrbookctl_lookup_iface( AddressIfType ifType ) {
4325
        GList *node = _addressBookTypeList_;
4326
        while( node ) {
4327
                AddressTypeControlItem *atci = node->data;
4328
                if( atci->interfaceType == ifType ) return atci;
4329
                node = g_list_next( node );
4330
        }
4331
        return NULL;
4332
}
4333
4334
static void addrbookctl_free_address( AddressObject *obj ) {
4335
        g_free( obj->name );
4336
        obj->type = ADDR_NONE;
4337
        obj->name = NULL;
4338
}
4339
4340
static void addrbookctl_free_interface(AdapterInterface *adapter)
4341
{
4342
        addrbookctl_free_address(ADDRESS_OBJECT(adapter));
4343
        adapter->iface = NULL;
4344
        adapter->interfaceType = ADDR_IF_NONE;
4345
        adapter->atci = NULL;
4346
        adapter->enabled = FALSE;
4347
        adapter->haveLibrary = FALSE;
4348
        if (adapter->tree_row) {
4349
                gtk_tree_row_reference_free(adapter->tree_row);
4350
                adapter->tree_row = NULL;
4351
        }
4352
        g_free(adapter);
4353
}
4354
4355
static void addrbookctl_free_datasource( AdapterDSource *adapter ) {
4356
        addrbookctl_free_address( ADDRESS_OBJECT(adapter) );
4357
        adapter->dataSource = NULL;
4358
        adapter->subType = ADDR_NONE;
4359
        g_free( adapter );
4360
}
4361
4362
static void addrbookctl_free_folder( AdapterFolder *adapter ) {
4363
        addrbookctl_free_address( ADDRESS_OBJECT(adapter) );
4364
        adapter->itemFolder = NULL;
4365
        g_free( adapter );
4366
}
4367
4368
static void addrbookctl_free_group( AdapterGroup *adapter ) {
4369
        addrbookctl_free_address( ADDRESS_OBJECT(adapter) );
4370
        adapter->itemGroup = NULL;
4371
        g_free( adapter );
4372
}
4373
4374
/*
4375
 * Build GUI interface list.
4376
 */
4377
void addrbookctl_build_iflist(void)
4378
{
4379
        AddressTypeControlItem *atci;
4380
        AdapterInterface *adapter;
4381
        GList *list = NULL;
4382
4383
        if(_addressIndex_ == NULL) {
4384
                _addressIndex_ = addrindex_create_index();
4385
        }
4386
        _addressInterfaceList_ = NULL;
4387
        list = addrindex_get_interface_list(_addressIndex_);
4388
        while (list) {
4389
                AddressInterface *iface = list->data;
4390
                atci = addrbookctl_lookup_iface(iface->type);
4391
                if (atci) {
4392
                        adapter = g_new0(AdapterInterface, 1);
4393
                        adapter->interfaceType = iface->type;
4394
                        adapter->atci = atci;
4395
                        adapter->iface = iface;
4396
                        adapter->tree_row = NULL;
4397
                        adapter->enabled = TRUE;
4398
                        adapter->haveLibrary = iface->haveLibrary;
4399
                        ADDRESS_OBJECT(adapter)->type = ADDR_INTERFACE;
4400
                        ADDRESS_OBJECT_NAME(adapter) = g_strdup(atci->displayName);
4401
                        _addressInterfaceList_ = g_list_append(_addressInterfaceList_, adapter);
4402
                }
4403
                list = g_list_next(list);
4404
        }
4405
}
4406
4407
void addrbookctl_free_selection( GList *list ) {
4408
        GList *node = list;
4409
        while( node ) {
4410
                AdapterInterface *adapter = node->data;
4411
                adapter = NULL;
4412
                node = g_list_next( node );
4413
        }
4414
        g_list_free( list );
4415
}
4416
4417
/*
4418
* Find GUI interface type specified interface type.
4419
* Return: Interface item, or NULL if not found.
4420
*/
4421
AdapterInterface *addrbookctl_find_interface( AddressIfType ifType ) {
4422
        GList *node = _addressInterfaceList_;
4423
        while( node ) {
4424
                AdapterInterface *adapter = node->data;
4425
                if( adapter->interfaceType == ifType ) return adapter;
4426
                node = g_list_next( node );
4427
        }
4428
        return NULL;
4429
}
4430
4431
/*
4432
* Build interface list selection.
4433
*/
4434
void addrbookctl_build_ifselect(void)
4435
{
4436
        GList *newList = NULL;
4437
        gchar *selectStr;
4438
        gchar **splitStr;
4439
        gint ifType;
4440
        gint i;
4441
        gchar *endptr = NULL;
4442
        gboolean enabled;
4443
        AdapterInterface *adapter;
4444
        /* GList *node; */
4445
4446
        selectStr = g_strdup( ADDRESSBOOK_IFACE_SELECTION );
4447
4448
        /* Parse string */
4449
        splitStr = g_strsplit( selectStr, ",", -1 );
4450
        for( i = 0; i < ADDRESSBOOK_MAX_IFACE; i++ ) {
4451
                if( splitStr[i] ) {
4452
                        /* printf( "%d : %s\n", i, splitStr[i] ); */
4453
                        ifType = strtol( splitStr[i], &endptr, 10 );
4454
                        enabled = TRUE;
4455
                        if( *endptr ) {
4456
                                if( strcmp( endptr, "/n" ) == 0 ) {
4457
                                        enabled = FALSE;
4458
                                }
4459
                        }
4460
                        /* printf( "\t%d : %s\n", ifType, enabled ? "yes" : "no" ); */
4461
                        adapter = addrbookctl_find_interface( ifType );
4462
                        if( adapter ) {
4463
                                newList = g_list_append( newList, adapter );
4464
                        }
4465
                }
4466
                else {
4467
                        break;
4468
                }
4469
        }
4470
        /* printf( "i=%d\n", i ); */
4471
        g_strfreev( splitStr );
4472
        g_free( selectStr );
4473
4474
        /* Replace existing list */
4475
        mgu_clear_list( _addressIFaceSelection_ );
4476
        g_list_free( _addressIFaceSelection_ );
4477
        _addressIFaceSelection_ = newList;
4478
        newList = NULL;
4479
4480
}
4481
4482
/* **********************************************************************
4483
* Add sender to address book.
4484
* ***********************************************************************
4485
*/
4486
4487
/*
4488
 * This function is used by the Add sender to address book function.
4489
 */
4490
gboolean addressbook_add_contact(const gchar *name, const gchar *address, const gchar *remarks)
4491
{
4492
        debug_print("addressbook_add_contact: name/address: %s <%s>\n", name ? name : "", address);
4493
        if (addressadd_selection(_addressIndex_, name, address, remarks)) {
4494
                debug_print("addressbook_add_contact - added\n");
4495
                addressbook_refresh();
4496
        }
4497
        return TRUE;
4498
}
4499
4500
/*
4501
 * This function is used by the automatic address registration.
4502
 */
4503
gboolean addressbook_add_contact_autoreg(const gchar *name, const gchar *address, const gchar *remarks)
4504
{
4505
        debug_print("addressbook_add_contact_autoreg: name/address: %s <%s>\n", name ? name : "", address);
4506
        if (addressadd_autoreg(_addressIndex_, name, address, remarks)) {
4507
                addressbook_refresh();
4508
        }
4509
        return TRUE;
4510
}
4511
4512
/* **********************************************************************
4513
* Address completion support.
4514
* ***********************************************************************
4515
*/
4516
4517
/*
4518
* This function is used by the address completion function to load
4519
* addresses.
4520
* Enter: callBackFunc Function to be called when an address is
4521
*                     to be loaded.
4522
* Return: TRUE if data loaded, FALSE if address index not loaded.
4523
*/
4524
gboolean addressbook_load_completion_full(AddressBookCompletionFunc func)
4525
{
4526
        /* AddressInterface *interface; */
4527
        AddressDataSource *ds;
4528
        GList *nodeIf, *nodeDS;
4529
        GList *listP, *nodeP;
4530
        GList *nodeM;
4531
        gchar *sName, *sAddress, *sAlias, *sNickName;
4532
        gchar *sFirstName, *sLastName;
4533
4534
        debug_print( "addressbook_load_completion\n" );
4535
4536
        if( _addressIndex_ == NULL ) return FALSE;
4537
4538
        nodeIf = addrindex_get_interface_list( _addressIndex_ );
4539
        while( nodeIf ) {
4540
                AddressInterface *iface = nodeIf->data;
4541
                nodeDS = iface->listSource;
4542
                while( nodeDS ) {
4543
                        ds = nodeDS->data;
4544
4545
                        /* Read address book */
4546
                        if( ! addrindex_ds_get_read_flag( ds ) ) {
4547
                                addrindex_ds_read_data( ds );
4548
                        }
4549
4550
                        /* Get all persons */
4551
                        listP = addrindex_ds_get_all_persons( ds );
4552
                        nodeP = listP;
4553
                        while( nodeP ) {
4554
                                ItemPerson *person = nodeP->data;
4555
                                nodeM = person->listEMail;
4556
4557
                                /* Figure out name to use */
4558
                                sName = ADDRITEM_NAME(person);
4559
                                sNickName = person->nickName;
4560
                                if( sName == NULL || *sName == '\0' ) {
4561
                                        if (sNickName)
4562
                                                sName = sNickName;
4563
                                }
4564
                                sFirstName = person->firstName;
4565
                                sLastName = person->lastName;
4566
4567
                                /* Process each E-Mail address */
4568
                                while( nodeM ) {
4569
                                        ItemEMail *email = nodeM->data;
4570
                                        /* Have mail */
4571
                                        sAddress = email->address;
4572
                                        if( sAddress && *sAddress != '\0' ) {
4573
                                                sAlias = ADDRITEM_NAME(email);
4574
                                                if( sAlias && *sAlias != '\0' ) {
4575
                                                        func( sName, sFirstName, sLastName, sAlias, sAddress );
4576
                                                } else {
4577
                                                        func( sName, sFirstName, sLastName, sNickName, sAddress );
4578
                                                }
4579
                                        }
4580
                                        nodeM = g_list_next( nodeM );
4581
                                }
4582
                                nodeP = g_list_next( nodeP );
4583
                        }
4584
                        /* Free up the list */
4585
                        g_list_free( listP );
4586
4587
                        nodeDS = g_list_next( nodeDS );
4588
                }
4589
                nodeIf = g_list_next( nodeIf );
4590
        }
4591
        debug_print( "addressbook_load_completion... done\n" );
4592
4593
        return TRUE;
4594
}
4595
4596
static gint (*real_func)(const gchar *, const gchar *, const gchar *);
4597
4598
static gint wrapper_func(const gchar *name, const gchar *firstname, const gchar *lastname, const gchar *nickname, const gchar *address)
4599
{
4600
        return real_func(name, address, nickname);
4601
}
4602
4603
gboolean addressbook_load_completion(gint (*callBackFunc)(const gchar *, const gchar *, const gchar *))
4604
{
4605
        gboolean ret;
4606
4607
        real_func = callBackFunc;
4608
        ret = addressbook_load_completion_full(wrapper_func);
4609
        real_func = NULL;
4610
4611
        return ret;
4612
}
4613
4614
/* **********************************************************************
4615
* Address Import.
4616
* ***********************************************************************
4617
*/
4618
4619
/*
4620
* Import LDIF file.
4621
*/
4622
static void addressbook_import_ldif_cb(void)
4623
{
4624
        AddressDataSource *ds = NULL;
4625
        AdapterDSource *ads = NULL;
4626
        AddressBookFile *abf = NULL;
4627
        AdapterInterface *adapter;
4628
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
4629
        GtkTreeModel *model;
4630
        GtkTreeIter iter, new_iter;
4631
        GtkTreePath *path;
4632
4633
        adapter = addrbookctl_find_interface(ADDR_IF_BOOK);
4634
        if (!adapter || !adapter->tree_row)
4635
                return;
4636
4637
        abf = addressbook_imp_ldif(_addressIndex_);
4638
        gtk_window_present(GTK_WINDOW(addrbook.window));
4639
        if (!abf)
4640
                return;
4641
4642
        ds = addrindex_index_add_datasource(_addressIndex_, ADDR_IF_BOOK, abf);
4643
        ads = addressbook_create_ds_adapter(ds, ADDR_BOOK, NULL);
4644
        addressbook_ads_set_name(ads, abf->name);
4645
4646
        model = gtk_tree_view_get_model(treeview);
4647
        gtkut_tree_row_reference_get_iter(model, adapter->tree_row, &iter);
4648
4649
        if (addressbook_add_object(&iter, &new_iter, ADDRESS_OBJECT(ads))) {
4650
                path = gtk_tree_model_get_path(model, &new_iter);
4651
                gtk_tree_view_set_cursor(treeview, path, NULL, FALSE);
4652
                gtk_tree_path_free(path);
4653
        }
4654
4655
        /* Notify address completion */
4656
        addressbook_modified();
4657
}
4658
4659
gboolean addressbook_import_ldif_file(const gchar *file, const gchar *book_name)
4660
{
4661
        AddressBookFile *abf;
4662
4663
        g_return_val_if_fail(file != NULL, FALSE);
4664
        g_return_val_if_fail(book_name != NULL, FALSE);
4665
4666
        abf = addressbook_imp_ldif_file(_addressIndex_, file, book_name);
4667
        if (!abf)
4668
                return FALSE;
4669
4670
        addrindex_index_add_datasource(_addressIndex_, ADDR_IF_BOOK, abf);
4671
        addrindex_save_data(_addressIndex_);
4672
        addressbook_modified();
4673
4674
        return TRUE;
4675
}
4676
4677
/*
4678
* Import CSV file.
4679
*/
4680
static void addressbook_import_csv_cb(void)
4681
{
4682
        AddressDataSource *ds = NULL;
4683
        AdapterDSource *ads = NULL;
4684
        AddressBookFile *abf = NULL;
4685
        AdapterInterface *adapter;
4686
        GtkTreeView *treeview = GTK_TREE_VIEW(addrbook.treeview);
4687
        GtkTreeModel *model;
4688
        GtkTreeIter iter, new_iter;
4689
        GtkTreePath *path;
4690
4691
        adapter = addrbookctl_find_interface(ADDR_IF_BOOK);
4692
        if (!adapter || !adapter->tree_row)
4693
                return;
4694
4695
        abf = addressbook_imp_csv(_addressIndex_);
4696
        gtk_window_present(GTK_WINDOW(addrbook.window));
4697
        if (!abf)
4698
                return;
4699
4700
        ds = addrindex_index_add_datasource(_addressIndex_, ADDR_IF_BOOK, abf);
4701
        ads = addressbook_create_ds_adapter(ds, ADDR_BOOK, NULL);
4702
        addressbook_ads_set_name(ads, abf->name);
4703
4704
        model = gtk_tree_view_get_model(treeview);
4705
        gtkut_tree_row_reference_get_iter(model, adapter->tree_row, &iter);
4706
4707
        if (addressbook_add_object(&iter, &new_iter, ADDRESS_OBJECT(ads))) {
4708
                path = gtk_tree_model_get_path(model, &new_iter);
4709
                gtk_tree_view_set_cursor(treeview, path, NULL, FALSE);
4710
                gtk_tree_path_free(path);
4711
        }
4712
4713
        /* Notify address completion */
4714
        addressbook_modified();
4715
}
4716
4717
/* **********************************************************************
4718
* Address Book Fast Search.
4719
* ***********************************************************************
4720
*/
4721
4722
static GHashTable *addr_table;
4723
4724
#if USE_THREADS
4725
G_LOCK_DEFINE_STATIC(addr_table);
4726
#define S_LOCK(name)        G_LOCK(name)
4727
#define S_UNLOCK(name)        G_UNLOCK(name)
4728
#else
4729
#define S_LOCK(name)
4730
#define S_UNLOCK(name)
4731
#endif
4732
4733
static gint load_address(const gchar *name, const gchar *address,
4734
                         const gchar *nickname)
4735
{
4736
        gchar *addr;
4737
4738
        if (!address)
4739
                return -1;
4740
4741
        addr = g_ascii_strdown(address, -1);
4742
4743
        if (g_hash_table_lookup(addr_table, addr) == NULL)
4744
                g_hash_table_insert(addr_table, addr, addr);
4745
        else
4746
                g_free(addr);
4747
4748
        return 0;
4749
}
4750
4751
static void addressbook_modified(void)
4752
{
4753
        S_LOCK(addr_table);
4754
4755
        if (addr_table) {
4756
                hash_free_strings(addr_table);
4757
                g_hash_table_destroy(addr_table);
4758
                addr_table = NULL;
4759
        }
4760
4761
        S_UNLOCK(addr_table);
4762
4763
        invalidate_address_completion();
4764
}
4765
4766
gboolean addressbook_has_address(const gchar *address)
4767
{
4768
        GSList *list, *cur;
4769
        gchar *addr;
4770
        gboolean found = FALSE;
4771
4772
        if (!address)
4773
                return FALSE;
4774
4775
        /* debug_print("addressbook_has_address: check if addressbook has address: %s\n", address); */
4776
4777
        list = address_list_append(NULL, address);
4778
        if (!list)
4779
                return FALSE;
4780
4781
        S_LOCK(addr_table);
4782
4783
        if (!addr_table) {
4784
                addr_table = g_hash_table_new(g_str_hash, g_str_equal);
4785
                addressbook_load_completion(load_address);
4786
        }
4787
4788
        for (cur = list; cur != NULL; cur = cur->next) {
4789
                addr = g_ascii_strdown((gchar *)cur->data, -1);
4790
4791
                if (g_hash_table_lookup(addr_table, addr)) {
4792
                        found = TRUE;
4793
                        /* debug_print("<%s> is in addressbook\n", addr); */
4794
                } else {
4795
                        found = FALSE;
4796
                        g_free(addr);
4797
                        break;
4798
                }
4799
                g_free(addr);
4800
        }
4801
4802
        S_UNLOCK(addr_table);
4803
4804
        slist_free_strings(list);
4805
4806
        return found;
4807
}
4808
4809
/*
4810
* End of Source.
4811
*/