2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001-2007 Match Grun and the Claws Mail team
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 3 of the License, or
8 * (at your option) any later version.
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 * Add address to address book dialog.
31 #include <glib/gi18n.h>
32 #include <gdk/gdkkeysyms.h>
33 #include <gtk/gtkwindow.h>
34 #include <gtk/gtksignal.h>
35 #include <gtk/gtkhbox.h>
36 #include <gtk/gtklabel.h>
37 #include <gtk/gtkentry.h>
38 #include <gtk/gtkhbbox.h>
39 #include <gtk/gtkbutton.h>
42 #include "stock_pixmap.h"
43 #include "prefs_common.h"
44 #include "addressadd.h"
47 #include "addrindex.h"
48 #include "manage_window.h"
49 #include "ldapserver.h"
50 #include "ldapupdate.h"
51 #include "alertpanel.h"
54 AddressBookFile
*book
;
58 static struct _AddressAdd_dlg
{
60 GtkWidget
*entry_name
;
61 GtkWidget
*label_address
;
62 GtkWidget
*entry_remarks
;
63 GtkWidget
*tree_folder
;
65 GtkWidget
*cancel_btn
;
68 FolderInfo
*fiSelected
;
71 static GdkPixmap
*folderXpm
;
72 static GdkBitmap
*folderXpmMask
;
73 static GdkPixmap
*bookXpm
;
74 static GdkBitmap
*bookXpmMask
;
76 static gboolean addressadd_cancelled
;
78 static FolderInfo
*addressadd_create_folderinfo( AddressBookFile
*abf
, ItemFolder
*folder
)
80 FolderInfo
*fi
= g_new0( FolderInfo
, 1 );
86 static void addressadd_free_folderinfo( FolderInfo
*fi
) {
95 static void addressadd_status_show( gchar
*msg
) {
96 if( addressadd_dlg
.statusbar
!= NULL
) {
97 gtk_statusbar_pop( GTK_STATUSBAR(addressadd_dlg
.statusbar
), addressadd_dlg
.status_cid
);
99 gtk_statusbar_push( GTK_STATUSBAR(addressadd_dlg
.statusbar
), addressadd_dlg
.status_cid
, msg
);
104 static gint
addressadd_delete_event( GtkWidget
*widget
, GdkEventAny
*event
, gboolean
*cancelled
) {
105 addressadd_cancelled
= TRUE
;
110 static gboolean
addressadd_key_pressed( GtkWidget
*widget
, GdkEventKey
*event
, gboolean
*cancelled
) {
111 if (event
&& event
->keyval
== GDK_Escape
) {
112 addressadd_cancelled
= TRUE
;
118 static void addressadd_ok( GtkWidget
*widget
, gboolean
*cancelled
) {
119 addressadd_cancelled
= FALSE
;
123 static void addressadd_cancel( GtkWidget
*widget
, gboolean
*cancelled
) {
124 addressadd_cancelled
= TRUE
;
128 static void addressadd_folder_select( GtkCTree
*ctree
, gint row
, gint column
,
129 GdkEvent
*event
, gpointer data
)
131 addressadd_dlg
.fiSelected
= gtk_clist_get_row_data( GTK_CLIST(ctree
), row
);
134 static gboolean
addressadd_tree_button( GtkCTree
*ctree
, GdkEventButton
*event
, gpointer data
) {
135 if( ! event
) return FALSE
;
136 if( event
->button
== 1 ) {
137 /* Handle double click */
138 if( event
->type
== GDK_2BUTTON_PRESS
) {
139 addressadd_cancelled
= FALSE
;
147 static void addressadd_size_allocate_cb(GtkWidget
*widget
,
148 GtkAllocation
*allocation
)
150 g_return_if_fail(allocation
!= NULL
);
152 prefs_common
.addressaddwin_width
= allocation
->width
;
153 prefs_common
.addressaddwin_height
= allocation
->height
;
156 static void addressadd_create( void ) {
161 GtkWidget
*entry_name
;
162 GtkWidget
*label_addr
;
163 GtkWidget
*entry_rems
;
164 GtkWidget
*tree_folder
;
169 GtkWidget
*cancel_btn
;
171 GtkWidget
*statusbar
;
173 static GdkGeometry geometry
;
175 window
= gtkut_window_new(GTK_WINDOW_TOPLEVEL
, "addressadd");
176 gtk_container_set_border_width( GTK_CONTAINER(window
), 0 );
177 gtk_window_set_title( GTK_WINDOW(window
), _("Add to address book") );
178 gtk_window_set_position( GTK_WINDOW(window
), GTK_WIN_POS_MOUSE
);
179 gtk_window_set_modal( GTK_WINDOW(window
), TRUE
);
180 g_signal_connect( G_OBJECT(window
), "delete_event",
181 G_CALLBACK(addressadd_delete_event
), NULL
);
182 g_signal_connect( G_OBJECT(window
), "key_press_event",
183 G_CALLBACK(addressadd_key_pressed
), NULL
);
184 g_signal_connect(G_OBJECT(window
), "size_allocate",
185 G_CALLBACK(addressadd_size_allocate_cb
), NULL
);
187 vbox
= gtk_vbox_new(FALSE
, 8);
188 gtk_container_add(GTK_CONTAINER(window
), vbox
);
189 gtk_container_set_border_width( GTK_CONTAINER(vbox
), 8 );
191 table
= gtk_table_new(3, 2, FALSE
);
192 gtk_box_pack_start(GTK_BOX(vbox
), table
, FALSE
, FALSE
, 0);
193 gtk_container_set_border_width( GTK_CONTAINER(table
), 8 );
194 gtk_table_set_row_spacings(GTK_TABLE(table
), 8);
195 gtk_table_set_col_spacings(GTK_TABLE(table
), 8);
199 label
= gtk_label_new(_("Name"));
200 gtk_table_attach(GTK_TABLE(table
), label
, 0, 1, top
, (top
+ 1), GTK_FILL
, 0, 0, 0);
201 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0.5);
203 entry_name
= gtk_entry_new();
204 /* gtk_entry_set_max_length(); */
205 gtk_entry_set_text (GTK_ENTRY(entry_name
),"");
207 gtk_table_attach(GTK_TABLE(table
), entry_name
, 1, 2, top
, (top
+ 1), GTK_FILL
| GTK_EXPAND
, 0, 0, 0);
211 label
= gtk_label_new(_("Address"));
212 gtk_table_attach(GTK_TABLE(table
), label
, 0, 1, top
, (top
+ 1), GTK_FILL
, 0, 0, 0);
213 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
215 label_addr
= gtk_label_new("");
216 gtk_table_attach(GTK_TABLE(table
), label_addr
, 1, 2, top
, (top
+ 1), GTK_FILL
, 0, 0, 0);
217 gtk_misc_set_alignment(GTK_MISC(label_addr
), 0, 0.5);
221 label
= gtk_label_new(_("Remarks"));
222 gtk_table_attach(GTK_TABLE(table
), label
, 0, 1, top
, (top
+ 1), GTK_FILL
, 0, 0, 0);
223 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0.5);
225 entry_rems
= gtk_entry_new();
226 /* gtk_entry_set_max_length(); */
227 gtk_table_attach(GTK_TABLE(table
), entry_rems
, 1, 2, top
, (top
+ 1), GTK_FILL
| GTK_EXPAND
, 0, 0, 0);
229 /* Address book/folder tree */
230 vlbox
= gtk_vbox_new(FALSE
, 8);
231 gtk_box_pack_start(GTK_BOX(vbox
), vlbox
, TRUE
, TRUE
, 0);
232 gtk_container_set_border_width( GTK_CONTAINER(vlbox
), 8 );
234 tree_win
= gtk_scrolled_window_new( NULL
, NULL
);
235 gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(tree_win
),
236 GTK_POLICY_AUTOMATIC
,
237 GTK_POLICY_AUTOMATIC
);
238 gtk_box_pack_start( GTK_BOX(vlbox
), tree_win
, TRUE
, TRUE
, 0 );
240 tree_folder
= gtk_ctree_new( 1, 0 );
241 gtk_container_add( GTK_CONTAINER(tree_win
), tree_folder
);
242 gtk_clist_column_titles_show( GTK_CLIST(tree_folder
) );
243 gtk_clist_set_column_title( GTK_CLIST(tree_folder
), 0, _( "Select Address Book Folder" ) );
244 gtk_ctree_set_line_style( GTK_CTREE(tree_folder
), GTK_CTREE_LINES_DOTTED
);
245 gtk_clist_set_selection_mode( GTK_CLIST(tree_folder
), GTK_SELECTION_BROWSE
);
246 gtk_ctree_set_expander_style( GTK_CTREE(tree_folder
), GTK_CTREE_EXPANDER_SQUARE
);
247 gtk_ctree_set_indent( GTK_CTREE(tree_folder
), CTREE_INDENT
);
248 gtk_clist_set_auto_sort( GTK_CLIST(tree_folder
), TRUE
);
251 hsbox
= gtk_hbox_new(FALSE
, 0);
252 gtk_box_pack_end(GTK_BOX(vbox
), hsbox
, FALSE
, FALSE
, BORDER_WIDTH
);
253 statusbar
= gtk_statusbar_new();
254 gtk_box_pack_start(GTK_BOX(hsbox
), statusbar
, TRUE
, TRUE
, BORDER_WIDTH
);
257 gtkut_stock_button_set_create(&hbbox
, &cancel_btn
, GTK_STOCK_CANCEL
,
258 &ok_btn
, GTK_STOCK_OK
,
260 gtk_box_pack_end(GTK_BOX(vbox
), hbbox
, FALSE
, FALSE
, 0);
261 gtk_container_set_border_width( GTK_CONTAINER(hbbox
), 0 );
262 gtk_widget_grab_default(ok_btn
);
264 g_signal_connect(G_OBJECT(ok_btn
), "clicked",
265 G_CALLBACK(addressadd_ok
), NULL
);
266 g_signal_connect(G_OBJECT(cancel_btn
), "clicked",
267 G_CALLBACK(addressadd_cancel
), NULL
);
268 g_signal_connect(G_OBJECT(tree_folder
), "select_row",
269 G_CALLBACK(addressadd_folder_select
), NULL
);
270 g_signal_connect(G_OBJECT(tree_folder
), "button_press_event",
271 G_CALLBACK(addressadd_tree_button
), NULL
);
273 if (!geometry
.min_height
) {
274 geometry
.min_width
= 300;
275 geometry
.min_height
= 400;
278 gtk_window_set_geometry_hints(GTK_WINDOW(window
), NULL
, &geometry
,
280 gtk_widget_set_size_request(window
, prefs_common
.addressaddwin_width
,
281 prefs_common
.addressaddwin_height
);
283 gtk_widget_show_all(vbox
);
285 addressadd_dlg
.window
= window
;
286 addressadd_dlg
.entry_name
= entry_name
;
287 addressadd_dlg
.label_address
= label_addr
;
288 addressadd_dlg
.entry_remarks
= entry_rems
;
289 addressadd_dlg
.tree_folder
= tree_folder
;
290 addressadd_dlg
.ok_btn
= ok_btn
;
291 addressadd_dlg
.cancel_btn
= cancel_btn
;
292 addressadd_dlg
.statusbar
= statusbar
;
293 addressadd_dlg
.status_cid
= gtk_statusbar_get_context_id( GTK_STATUSBAR(statusbar
), "Address Add" );
295 gtk_widget_show_all( window
);
297 stock_pixmap_gdk( window
, STOCK_PIXMAP_BOOK
, &bookXpm
, &bookXpmMask
);
298 stock_pixmap_gdk( window
, STOCK_PIXMAP_DIR_OPEN
,
299 &folderXpm
, &folderXpmMask
);
302 static void addressadd_load_folder( GtkCTreeNode
*parentNode
, ItemFolder
*parentFolder
,
303 FolderInfo
*fiParent
)
305 GtkCTree
*tree
= GTK_CTREE( addressadd_dlg
.tree_folder
);
313 list
= parentFolder
->listFolder
;
316 fName
= g_strdup( ADDRITEM_NAME(folder
) );
318 node
= gtk_sctree_insert_node( tree
, parentNode
, NULL
, name
, FOLDER_SPACING
,
319 folderXpm
, folderXpmMask
, folderXpm
, folderXpmMask
,
322 fi
= addressadd_create_folderinfo( fiParent
->book
, folder
);
323 gtk_ctree_node_set_row_data_full( tree
, node
, fi
,
324 ( GtkDestroyNotify
) addressadd_free_folderinfo
);
325 addressadd_load_folder( node
, folder
, fi
);
326 list
= g_list_next( list
);
330 static void addressadd_load_data( AddressIndex
*addrIndex
) {
331 AddressDataSource
*ds
;
332 GList
*list
, *nodeDS
;
335 ItemFolder
*rootFolder
;
336 AddressBookFile
*abf
;
338 GtkCTree
*tree
= GTK_CTREE( addressadd_dlg
.tree_folder
);
341 gtk_clist_clear( GTK_CLIST( tree
) );
342 list
= addrindex_get_interface_list( addrIndex
);
344 AddressInterface
*interface
= list
->data
;
345 if( interface
->type
== ADDR_IF_BOOK
||
346 interface
->type
== ADDR_IF_LDAP
) {
347 nodeDS
= interface
->listSource
;
350 dsName
= g_strdup( addrindex_ds_get_name( ds
) );
352 /* Read address book */
353 if( ! addrindex_ds_get_read_flag( ds
) ) {
354 addrindex_ds_read_data( ds
);
357 /* Add node for address book */
358 abf
= ds
->rawDataSource
;
360 node
= gtk_ctree_insert_node( tree
, NULL
, NULL
,
361 name
, FOLDER_SPACING
, bookXpm
,
362 bookXpmMask
, bookXpm
, bookXpmMask
,
366 fi
= addressadd_create_folderinfo( abf
, NULL
);
367 gtk_ctree_node_set_row_data_full( tree
, node
, fi
,
368 ( GtkDestroyNotify
) addressadd_free_folderinfo
);
370 rootFolder
= addrindex_ds_get_root_folder( ds
);
371 addressadd_load_folder( node
, rootFolder
, fi
);
373 nodeDS
= g_list_next( nodeDS
);
376 list
= g_list_next( list
);
380 gboolean
addressadd_selection( AddressIndex
*addrIndex
, const gchar
*name
, const gchar
*address
, const gchar
*remarks
) {
381 gboolean retVal
= FALSE
;
382 ItemPerson
*person
= NULL
;
383 FolderInfo
*fi
= NULL
;
384 addressadd_cancelled
= FALSE
;
386 if( ! addressadd_dlg
.window
) addressadd_create();
387 gtk_widget_grab_focus(addressadd_dlg
.ok_btn
);
388 gtk_widget_show(addressadd_dlg
.window
);
389 manage_window_set_transient(GTK_WINDOW(addressadd_dlg
.window
));
391 addressadd_dlg
.fiSelected
= NULL
;
392 addressadd_status_show( "" );
393 addressadd_load_data( addrIndex
);
394 gtk_clist_select_row( GTK_CLIST( addressadd_dlg
.tree_folder
), 0, 0 );
395 gtk_widget_show(addressadd_dlg
.window
);
397 gtk_entry_set_text( GTK_ENTRY(addressadd_dlg
.entry_name
), "" );
398 gtk_label_set_text( GTK_LABEL(addressadd_dlg
.label_address
), "" );
399 gtk_entry_set_text( GTK_ENTRY(addressadd_dlg
.entry_remarks
), "" );
401 gtk_entry_set_text( GTK_ENTRY(addressadd_dlg
.entry_name
), name
);
403 gtk_label_set_text( GTK_LABEL(addressadd_dlg
.label_address
), address
);
405 gtk_entry_set_text( GTK_ENTRY(addressadd_dlg
.entry_remarks
), remarks
);
408 gtk_widget_hide( addressadd_dlg
.window
);
410 if( ! addressadd_cancelled
) {
411 if( addressadd_dlg
.fiSelected
) {
412 gchar
*returned_name
;
413 gchar
*returned_remarks
;
414 returned_name
= gtk_editable_get_chars( GTK_EDITABLE(addressadd_dlg
.entry_name
), 0, -1 );
415 returned_remarks
= gtk_editable_get_chars( GTK_EDITABLE(addressadd_dlg
.entry_remarks
), 0, -1 );
417 fi
= addressadd_dlg
.fiSelected
;
419 person
= addrbook_add_contact( fi
->book
, fi
->folder
,
423 person
->status
= ADD_ENTRY
;
425 if (fi
->book
->type
== ADBOOKTYPE_LDAP
) {
426 LdapServer
*server
= (LdapServer
*) fi
->book
;
427 ldapsvr_set_modified(server
, TRUE
);
428 ldapsvr_update_book(server
, person
);
429 if (server
->retVal
!= LDAPRC_SUCCESS
) {
430 alertpanel( _("Add address(es)"),
431 _("Can't add the specified address"),
432 GTK_STOCK_CLOSE
, NULL
, NULL
);
433 return server
->retVal
;
437 g_free(returned_name
);
438 g_free(returned_remarks
);
439 if( person
) retVal
= TRUE
;
443 gtk_clist_clear( GTK_CLIST( addressadd_dlg
.tree_folder
) );