addressbook_foldersel.c (11369B)
1 /* 2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client 3 * Copyright (C) 2001-2024 the Claws Mail team and Match Grun 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 3 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, see <http://www.gnu.org/licenses/>. 17 */ 18 19 /* 20 * Add address to address book dialog. 21 */ 22 23 #include "defs.h" 24 25 #include <glib.h> 26 #include <glib/gi18n.h> 27 #include <gdk/gdkkeysyms.h> 28 #include <gtk/gtk.h> 29 30 #include "gtkutils.h" 31 #include "stock_pixmap.h" 32 #include "prefs_common.h" 33 #include "addressadd.h" 34 #include "addritem.h" 35 #include "addrbook.h" 36 #include "addrindex.h" 37 #include "manage_window.h" 38 39 enum { 40 COL_ICON, 41 COL_NAME, 42 COL_PTR, 43 N_COLS 44 }; 45 46 typedef struct { 47 AddressBookFile *book; 48 ItemFolder *folder; 49 } FolderInfo; 50 51 static struct _AddressBookFolderSel_dlg { 52 GtkWidget *window; 53 GtkWidget *view_folder; 54 GtkWidget *ok_btn; 55 GtkWidget *cancel_btn; 56 gint status_cid; 57 FolderInfo *fiSelected; 58 } addressbook_foldersel_dlg; 59 60 static GdkPixbuf *folderXpm; 61 static GdkPixbuf *bookXpm; 62 63 static gboolean addressbook_foldersel_cancelled; 64 65 static FolderInfo *addressbook_foldersel_create_folderinfo( AddressBookFile *abf, ItemFolder *folder ) 66 { 67 FolderInfo *fi = g_new0( FolderInfo, 1 ); 68 fi->book = abf; 69 fi->folder = folder; 70 return fi; 71 } 72 73 static void addressbook_foldersel_free_folderinfo( FolderInfo *fi ) { 74 fi->book = NULL; 75 fi->folder = NULL; 76 g_free( fi ); 77 } 78 79 static gint addressbook_foldersel_delete_event( GtkWidget *widget, GdkEventAny *event, gboolean *cancelled ) 80 { 81 addressbook_foldersel_cancelled = TRUE; 82 gtk_main_quit(); 83 return TRUE; 84 } 85 86 static void set_selected_ptr() 87 { 88 GtkWidget *view = addressbook_foldersel_dlg.view_folder; 89 90 addressbook_foldersel_dlg.fiSelected = 91 gtkut_tree_view_get_selected_pointer(GTK_TREE_VIEW(view), COL_PTR, 92 NULL, NULL, NULL); 93 } 94 95 static void addressbook_foldersel_ok( GtkWidget *widget, gboolean *cancelled ) 96 { 97 set_selected_ptr(); 98 addressbook_foldersel_cancelled = FALSE; 99 gtk_main_quit(); 100 } 101 102 static void addressbook_foldersel_cancel( GtkWidget *widget, gboolean *cancelled ) 103 { 104 set_selected_ptr(); 105 addressbook_foldersel_cancelled = TRUE; 106 gtk_main_quit(); 107 } 108 109 static void addressbook_foldersel_row_activated(GtkTreeView *view, 110 GtkTreePath *path, GtkTreeViewColumn *col, 111 gpointer user_data) 112 { 113 addressbook_foldersel_ok(NULL, NULL); 114 } 115 116 static void addressbook_foldersel_size_allocate_cb(GtkWidget *widget, 117 GtkAllocation *allocation) 118 { 119 cm_return_if_fail(allocation != NULL); 120 121 gtk_window_get_size(GTK_WINDOW(widget), 122 &prefs_common.addressbook_folderselwin_width, &prefs_common.addressbook_folderselwin_height); 123 } 124 125 static void addressbook_foldersel_create( void ) 126 { 127 GtkWidget *window; 128 GtkWidget *vbox; 129 GtkWidget *view; 130 GtkWidget *vlbox; 131 GtkWidget *tree_win; 132 GtkWidget *hbbox; 133 GtkWidget *ok_btn; 134 GtkWidget *cancel_btn; 135 static GdkGeometry geometry; 136 GtkTreeStore *store; 137 GtkTreeSelection *sel; 138 GtkCellRenderer *rdr; 139 GtkTreeViewColumn *col; 140 141 window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "addressbook_foldersel" ); 142 gtk_container_set_border_width( GTK_CONTAINER(window), 0 ); 143 gtk_window_set_title( GTK_WINDOW(window), _("Select Address Book Folder") ); 144 gtk_window_set_position( GTK_WINDOW(window), GTK_WIN_POS_MOUSE ); 145 gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); 146 g_signal_connect( G_OBJECT(window), "delete_event", 147 G_CALLBACK(addressbook_foldersel_delete_event), NULL ); 148 g_signal_connect(G_OBJECT(window), "size_allocate", 149 G_CALLBACK(addressbook_foldersel_size_allocate_cb), NULL); 150 151 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); 152 gtk_container_add(GTK_CONTAINER(window), vbox); 153 gtk_container_set_border_width( GTK_CONTAINER(vbox), 8 ); 154 155 /* Address book/folder tree */ 156 vlbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); 157 gtk_box_pack_start(GTK_BOX(vbox), vlbox, TRUE, TRUE, 0); 158 gtk_container_set_border_width( GTK_CONTAINER(vlbox), 8 ); 159 160 tree_win = gtk_scrolled_window_new( NULL, NULL ); 161 gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(tree_win), 162 GTK_POLICY_AUTOMATIC, 163 GTK_POLICY_AUTOMATIC ); 164 gtk_box_pack_start( GTK_BOX(vlbox), tree_win, TRUE, TRUE, 0 ); 165 166 store = gtk_tree_store_new(N_COLS, 167 GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER); 168 169 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); 170 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), COL_NAME, GTK_SORT_ASCENDING); 171 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), TRUE); 172 gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(view), FALSE); 173 gtk_tree_view_set_search_column(GTK_TREE_VIEW(view), COL_NAME); 174 175 col = gtk_tree_view_column_new(); 176 rdr = gtk_cell_renderer_pixbuf_new(); 177 gtk_cell_renderer_set_padding(rdr, 0, 0); 178 gtk_tree_view_column_pack_start(col, rdr, FALSE); 179 gtk_tree_view_column_set_attributes(col, rdr, 180 "pixbuf", COL_ICON, NULL); 181 rdr = gtk_cell_renderer_text_new(); 182 gtk_tree_view_column_pack_start(col, rdr, TRUE); 183 gtk_tree_view_column_set_attributes(col, rdr, 184 "markup", COL_NAME, NULL); 185 gtk_tree_view_column_set_title(col, _("Address Book")); 186 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col); 187 188 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); 189 gtk_tree_selection_set_mode(sel, GTK_SELECTION_BROWSE); 190 191 gtk_container_add( GTK_CONTAINER(tree_win), view ); 192 193 /* Button panel */ 194 gtkut_stock_button_set_create( &hbbox, &cancel_btn, NULL, _("_Cancel"), 195 &ok_btn, NULL, _("_OK"), 196 NULL, NULL, NULL ); 197 gtk_box_pack_end( GTK_BOX(vbox), hbbox, FALSE, FALSE, 0 ); 198 gtk_container_set_border_width( GTK_CONTAINER(hbbox), 0 ); 199 gtk_widget_grab_default( ok_btn ); 200 201 g_signal_connect( G_OBJECT(view), "row-activated", 202 G_CALLBACK(addressbook_foldersel_row_activated), NULL); 203 g_signal_connect( G_OBJECT(ok_btn), "clicked", 204 G_CALLBACK(addressbook_foldersel_ok), NULL ); 205 g_signal_connect( G_OBJECT(cancel_btn), "clicked", 206 G_CALLBACK(addressbook_foldersel_cancel), NULL ); 207 208 if ( !geometry.min_height ) { 209 geometry.min_width = 300; 210 geometry.min_height = 350; 211 } 212 213 gtk_window_set_geometry_hints( GTK_WINDOW(window), NULL, &geometry, 214 GDK_HINT_MIN_SIZE ); 215 gtk_window_set_default_size( GTK_WINDOW(window), 216 prefs_common.addressbook_folderselwin_width, 217 prefs_common.addressbook_folderselwin_height ); 218 219 gtk_widget_show_all( vbox ); 220 221 addressbook_foldersel_dlg.window = window; 222 addressbook_foldersel_dlg.view_folder = view; 223 addressbook_foldersel_dlg.ok_btn = ok_btn; 224 addressbook_foldersel_dlg.cancel_btn = cancel_btn; 225 226 gtk_widget_show_all( window ); 227 228 stock_pixbuf_gdk(STOCK_PIXMAP_BOOK, &bookXpm); 229 stock_pixbuf_gdk(STOCK_PIXMAP_DIR_OPEN, &folderXpm); 230 } 231 232 static gboolean tree_clear_foreach_func(GtkTreeModel *model, 233 GtkTreePath *path, GtkTreeIter *iter, 234 gpointer user_data) 235 { 236 FolderInfo *fi; 237 238 gtk_tree_model_get(model, iter, COL_PTR, &fi, -1); 239 if (fi != NULL) { 240 addressbook_foldersel_free_folderinfo(fi); 241 } 242 gtk_tree_store_set(GTK_TREE_STORE(model), iter, COL_PTR, NULL, -1); 243 return FALSE; 244 } 245 246 static void addressbook_foldersel_tree_clear() 247 { 248 GtkWidget *view = addressbook_foldersel_dlg.view_folder; 249 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); 250 251 gtk_tree_model_foreach(model, tree_clear_foreach_func, NULL); 252 gtk_tree_store_clear(GTK_TREE_STORE(model)); 253 } 254 255 static void addressbook_foldersel_load_folder( GtkTreeIter *parent_iter, 256 ItemFolder *parentFolder, FolderInfo *fiParent) 257 { 258 GtkWidget *view = addressbook_foldersel_dlg.view_folder; 259 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); 260 GtkTreeIter iter; 261 GList *list; 262 ItemFolder *folder; 263 gchar *name; 264 FolderInfo *fi; 265 266 list = parentFolder->listFolder; 267 while ( list ) { 268 folder = list->data; 269 name = g_strdup( ADDRITEM_NAME(folder) ); 270 271 fi = addressbook_foldersel_create_folderinfo( fiParent->book, folder ); 272 273 debug_print("adding folder '%s'\n", name); 274 gtk_tree_store_append(GTK_TREE_STORE(model), &iter, parent_iter); 275 gtk_tree_store_set(GTK_TREE_STORE(model), &iter, 276 COL_ICON, folderXpm, 277 COL_NAME, name, 278 COL_PTR, fi, 279 -1); 280 g_free(name); 281 282 addressbook_foldersel_load_folder( parent_iter, folder, fi ); 283 list = g_list_next( list ); 284 } 285 } 286 287 static void addressbook_foldersel_load_data( AddressIndex *addrIndex ) 288 { 289 AddressDataSource *ds; 290 GList *list, *nodeDS; 291 gchar *name; 292 ItemFolder *rootFolder; 293 AddressBookFile *abf; 294 FolderInfo *fi; 295 GtkWidget *view = addressbook_foldersel_dlg.view_folder; 296 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); 297 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); 298 GtkTreeIter iter; 299 300 addressbook_foldersel_tree_clear(); 301 302 list = addrindex_get_interface_list( addrIndex ); 303 while ( list ) { 304 AddressInterface *interface = list->data; 305 if ( interface->type == ADDR_IF_BOOK ) { 306 nodeDS = interface->listSource; 307 while ( nodeDS ) { 308 ds = nodeDS->data; 309 name = g_strdup( addrindex_ds_get_name( ds ) ); 310 311 /* Read address book */ 312 if( ! addrindex_ds_get_read_flag( ds ) ) { 313 addrindex_ds_read_data( ds ); 314 } 315 316 /* Add node for address book */ 317 abf = ds->rawDataSource; 318 fi = addressbook_foldersel_create_folderinfo( abf, NULL ); 319 320 debug_print("adding AB '%s'\n", name); 321 gtk_tree_store_append(GTK_TREE_STORE(model), &iter, NULL); 322 gtk_tree_store_set(GTK_TREE_STORE(model), &iter, 323 COL_ICON, bookXpm, 324 COL_NAME, name, 325 COL_PTR, fi, 326 -1); 327 g_free(name); 328 329 rootFolder = addrindex_ds_get_root_folder( ds ); 330 addressbook_foldersel_load_folder( &iter, rootFolder, fi ); 331 332 nodeDS = g_list_next( nodeDS ); 333 } 334 } 335 list = g_list_next( list ); 336 } 337 338 if (gtk_tree_model_get_iter_first(model, &iter)) 339 gtk_tree_selection_select_iter(sel, &iter); 340 } 341 342 gboolean addressbook_foldersel_selection( AddressIndex *addrIndex, 343 AddressBookFile **book, ItemFolder **folder, 344 const gchar* path) 345 { 346 gboolean retVal = FALSE; 347 addressbook_foldersel_cancelled = FALSE; 348 349 if ( ! addressbook_foldersel_dlg.window ) 350 addressbook_foldersel_create(); 351 gtk_widget_grab_focus(addressbook_foldersel_dlg.ok_btn); 352 gtk_widget_show(addressbook_foldersel_dlg.window); 353 manage_window_set_transient(GTK_WINDOW(addressbook_foldersel_dlg.window)); 354 gtk_window_set_modal(GTK_WINDOW(addressbook_foldersel_dlg.window), TRUE); 355 356 addressbook_foldersel_dlg.fiSelected = NULL; 357 358 addressbook_foldersel_load_data( addrIndex ); 359 360 gtk_widget_show(addressbook_foldersel_dlg.window); 361 362 gtk_main(); 363 gtk_widget_hide( addressbook_foldersel_dlg.window ); 364 gtk_window_set_modal(GTK_WINDOW(addressbook_foldersel_dlg.window), FALSE); 365 if ( ! addressbook_foldersel_cancelled ) { 366 367 *book = NULL; 368 *folder = NULL; 369 370 if ( addressbook_foldersel_dlg.fiSelected ) { 371 *book = addressbook_foldersel_dlg.fiSelected->book; 372 *folder = addressbook_foldersel_dlg.fiSelected->folder; 373 retVal = TRUE; 374 } 375 } 376 377 addressbook_foldersel_tree_clear(); 378 379 return retVal; 380 }