[Commits] callbacks.c 1.6 1.7 callbacks.h 1.1 1.2 contactwindow.c 1.4 1.5 mainwindow.h 1.1 1.2 plugin-loader.c 1.7 1.8 plugin-loader.h 1.5 1.6 plugin.h 1.6 1.7 utils.c 1.5 1.6 utils.h 1.5 1.6

miras at claws-mail.org miras at claws-mail.org
Sun Nov 20 22:24:22 CET 2011


Update of /home/claws-mail/contacts/src
In directory claws-mail:/tmp/cvs-serv324/src

Modified Files:
	callbacks.c callbacks.h contactwindow.c mainwindow.h 
	plugin-loader.c plugin-loader.h plugin.h utils.c utils.h 
Log Message:
2011-11-20 [mir]	0.6.0cvs22

	* plugins/example/example-plugin.c
	* plugins/ldap/ldap-plugin.c
	* plugins/xml/xml-plugin.c
	* src/callbacks.c
	* src/callbacks.h
	* src/contactwindow.c
	* src/mainwindow.h
	* src/plugin-loader.c
	* src/plugin-loader.h
	* src/plugin.h
	* src/utils.c
	* src/utils.h
	    Lots of bug fixes, some feature enhancements and complete
	    read-only support for LDAP with advanced search
	    capabilities. 

Index: contactwindow.c
===================================================================
RCS file: /home/claws-mail/contacts/src/contactwindow.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- contactwindow.c	14 Nov 2011 22:06:43 -0000	1.4
+++ contactwindow.c	20 Nov 2011 21:24:20 -0000	1.5
@@ -1017,6 +1017,7 @@
 static void contact_search_get(ContactEntryData** data, Contact* contact) {
 	gint i;
 	const gchar* value;
+	const gchar* term;
 	Email* email = NULL;
 	
 	for (i = 0; i < contact_entry_data_size; i++) {
@@ -1035,8 +1036,13 @@
 					else
 						email->remarks = g_strdup(value);
 				}
-				else
-					swap_data(contact->data, data[i]->key, value);
+				else {
+					if (strcmp("Display name", data[i]->key) == 0)
+						term = "cn";
+					else
+						term = data[i]->key;
+					swap_data(contact->data, term, value);
+				}
 			}
 		}
 	}

Index: mainwindow.h
===================================================================
RCS file: /home/claws-mail/contacts/src/mainwindow.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- mainwindow.h	7 Sep 2011 17:35:29 -0000	1.1
+++ mainwindow.h	20 Nov 2011 21:24:20 -0000	1.2
@@ -75,6 +75,8 @@
     GtkWidget*          statusbar;
     GtkWidget*          progress_dialog;
     GtkWidget*          progress_bar;
+    gpointer            selected_abook;
+    gpointer            selected_contact;
     guint               source_id;
     gchar*              default_book;
     gboolean            compose_mode;

Index: plugin-loader.h
===================================================================
RCS file: /home/claws-mail/contacts/src/plugin-loader.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- plugin-loader.h	14 Nov 2011 22:06:43 -0000	1.5
+++ plugin-loader.h	20 Nov 2011 21:24:20 -0000	1.6
@@ -64,6 +64,7 @@
 	void (*attribs_set) (GHashTable* attributes);
 	GSList* (*addrbook_all_get) (void);
 	GList* (*closed_books_get) (void);
+	GSList* (*addrbook_names_all) (void);
 	gboolean (*abook_open) (AddressBook* abook, gchar** error);
 	gboolean (*abook_close) (AddressBook* abook, gchar** error);
 	gboolean (*abook_delete) (AddressBook* abook, gchar** error);

Index: plugin.h
===================================================================
RCS file: /home/claws-mail/contacts/src/plugin.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- plugin.h	14 Nov 2011 22:06:43 -0000	1.6
+++ plugin.h	20 Nov 2011 21:24:20 -0000	1.7
@@ -62,12 +62,12 @@
 		gchar*		entry;
 		gboolean	check_btn;
 		gint		spin_btn;
-	} value;
+	} current_value;
 	union {
 		gchar*		entry;
 		gboolean	check_btn;
 		gint		spin_btn;
-	} default_value;
+	} preset_value;
 } ExtraConfig;
 
 typedef enum {
@@ -200,10 +200,12 @@
 GSList* plugin_attrib_list(void);
 void plugin_attribs_set(GHashTable* attributes);
 
-/* Return a list of address book names */
+/* Return a list of open address books */
 GSList* plugin_addrbook_all_get(void);
 /* Return a list of closed address books */
 GList* plugin_closed_books_get(void);
+/* Return a list of all address book names */
+GSList* plugin_addrbook_names_all(void);
 
 /* Commit all changes */
 gboolean plugin_commit_all(gchar** error);

Index: utils.h
===================================================================
RCS file: /home/claws-mail/contacts/src/utils.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- utils.h	14 Nov 2011 22:06:44 -0000	1.5
+++ utils.h	20 Nov 2011 21:24:20 -0000	1.6
@@ -62,6 +62,12 @@
 	} attr;
 } AttrList;
 
+typedef struct {
+	GHashTable* hash;
+	gboolean	is_and;
+	gint		equal;
+} Compare;
+
 void debug_print_real(const gchar *format, ...);
 const char* debug_srcname(const char *file);
 gboolean debug_get_mode();
@@ -112,6 +118,7 @@
 AddressBook* address_book_new();
 AddressBook* address_book_get(Plugin* plugin, const gchar* name);
 AddressBook* address_book_copy(AddressBook* a, gboolean deep);
+gboolean address_book_name_exists(Plugin* plugin, AddressBook* book);
 void address_book_contacts_free(AddressBook* address_book);
 void address_book_free(AddressBook** address_book);
 gint address_book_compare(gconstpointer a, gconstpointer b);
@@ -132,6 +139,10 @@
 gpointer extra_config_copy(gpointer data);
 ExtraConfig* get_extra_config(GSList* list, const gchar* name);
 GSList* find_name(GtkContainer* container, const gchar* name);
+GSList* get_basic_attributes(Contact* contact);
+gboolean match_string_pattern(const gchar* pattern, const gchar* haystack, gboolean case_aware);
+void contact_compare_values(gpointer ckey, gpointer value, gpointer data);
+gboolean email_compare_values(GSList* a, GSList* b, gboolean is_and);
 
 G_END_DECLS
 

Index: plugin-loader.c
===================================================================
RCS file: /home/claws-mail/contacts/src/plugin-loader.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- plugin-loader.c	14 Nov 2011 22:06:43 -0000	1.7
+++ plugin-loader.c	20 Nov 2011 21:24:20 -0000	1.8
@@ -605,7 +605,7 @@
 			 plugin_abook_open, plugin_abook_close, plugin_abook_delete,
 			 plugin_addrbook_all_get, plugin_abook_set_config, plugin_type,
 			 plugin_file_filter, plugin_url, plugin_attribs_set, plugin_commit_all,
-			 plugin_remaining_attribs, plugin_inactive_attribs,
+			 plugin_remaining_attribs, plugin_inactive_attribs, plugin_addrbook_names_all,
 			 plugin_closed_books_get, plugin_need_credentials, plugin_extra_config;
 
 	plugin = g_new0(Plugin, 1);
@@ -633,6 +633,7 @@
 		!g_module_symbol(plugin->module, "plugin_attrib_list", &plugin_attrib_list) ||
 		!g_module_symbol(plugin->module, "plugin_attribs_set", &plugin_attribs_set) ||
 		!g_module_symbol(plugin->module, "plugin_addrbook_all_get", &plugin_addrbook_all_get) ||
+		!g_module_symbol(plugin->module, "plugin_addrbook_names_all", &plugin_addrbook_names_all) ||
 		!g_module_symbol(plugin->module, "plugin_reset", &plugin_reset) ||
 		!g_module_symbol(plugin->module, "plugin_abook_open", &plugin_abook_open) ||
 		!g_module_symbol(plugin->module, "plugin_abook_close", &plugin_abook_close) ||
@@ -715,6 +716,7 @@
 	plugin->attrib_list = plugin_attrib_list;
 	plugin->attribs_set = plugin_attribs_set;
 	plugin->addrbook_all_get = plugin_addrbook_all_get;
+	plugin->addrbook_names_all = plugin_addrbook_names_all;
 	plugin->get_contact = get_contact;
 	plugin->set_contact = set_contact;
 	plugin->delete_contact = delete_contact;

Index: utils.c
===================================================================
RCS file: /home/claws-mail/contacts/src/utils.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- utils.c	14 Nov 2011 22:06:44 -0000	1.5
+++ utils.c	20 Nov 2011 21:24:20 -0000	1.6
@@ -45,6 +45,7 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <gcrypt.h>
+#include <stdlib.h>
 
 #include "utils.h"
 #include "gtk-utils.h"
@@ -1407,8 +1408,10 @@
 
 	if (base64_enc)
 		cipher = g_base64_decode(cipher_text, &size);
-	else
+	else {
 		cipher = (guchar *) g_strdup(cipher_text);
+		size = strlen(cipher_text) + 1;
+	}
 
 	if (aes_init(&digest)) {
 		plain = g_new0(guchar, size + 1);
@@ -1480,8 +1483,8 @@
     g_free(ec->label);
     g_free(ec->tooltip);
 	if (ec->type == PLUGIN_CONFIG_EXTRA_ENTRY) {
-		g_free(ec->value.entry);
-		g_free(ec->default_value.entry);
+		g_free(ec->current_value.entry);
+		g_free(ec->preset_value.entry);
 	}
     g_free(ec);
     ec = NULL;
@@ -1500,12 +1503,12 @@
 	b->tooltip = g_strdup(a->tooltip);
 	b->type = a->type;
 	if (a->type == PLUGIN_CONFIG_EXTRA_ENTRY) {
-		b->value.entry = g_strdup(a->value.entry);
-		b->default_value.entry = g_strdup(a->default_value.entry);
+		b->current_value.entry = g_strdup(a->current_value.entry);
+		b->preset_value.entry = g_strdup(a->preset_value.entry);
 	}
 	else {
-		b->value = a->value;
-		b->default_value = a->default_value;
+		b->current_value = a->current_value;
+		b->preset_value = a->preset_value;
 	}
 	
 	return b; 
@@ -1561,4 +1564,225 @@
 	}
 	
 	return extra_config_copy(conf);
-}
\ No newline at end of file
+}
+
+gboolean address_book_name_exists(Plugin* plugin, AddressBook* book) {
+	gboolean found = FALSE;
+	GSList *list, *cur;
+	
+	if (! plugin || ! book)
+		return found;
+	
+	list = plugin->addrbook_names_all();
+	cur = list;
+	
+	while(cur && ! found) {
+		gchar* name = (gchar *) cur->data;
+		if (utf8_collate(name, book->abook_name) == 0)
+			found = TRUE;
+		cur = cur->next;
+	}
+	gslist_free(&list, g_free);
+	
+	return found;
+}
+
+GSList* get_basic_attributes(Contact* contact) {
+	GSList *list = NULL, *cur;
+	gchar* value = NULL;
+	
+	extract_data(contact->data, "nick-name", (void **) &value);
+	if (value) {
+		list = g_slist_prepend(list, g_strdup(value));
+		g_free(value);
+		value = NULL;
+	}
+	extract_data(contact->data, "first-name", (void **) &value);
+	if (value) {
+		list = g_slist_prepend(list, g_strdup(value));
+		g_free(value);
+		value = NULL;
+	}
+	extract_data(contact->data, "last-name", (void **) &value);
+	if (value) {
+		list = g_slist_prepend(list, g_strdup(value));
+		g_free(value);
+		value = NULL;
+	}
+	extract_data(contact->data, "cn", (void **) &value);
+	if (value) {
+		list = g_slist_prepend(list, g_strdup(value));
+		g_free(value);
+		value = NULL;
+	}
+	
+	for (cur = contact->emails; cur; cur = g_slist_next(cur)) {
+		Email* e = (Email *) cur->data;
+		list = g_slist_prepend(list, g_strdup(e->alias));		
+		list = g_slist_prepend(list, g_strdup(e->email));		
+	}
+	
+	return list;
+}
+
+gboolean match_string_pattern(const gchar* pattern,
+							  const gchar* haystack,
+							  gboolean case_aware) {
+	const gchar *txt, *source;
+	gunichar ch = 0, cp;
+	gboolean in_str = FALSE, error = FALSE, has_source;
+	
+	if (! pattern || ! haystack)
+		return FALSE;
+	
+	if (!*pattern && !*haystack)
+		return TRUE;
+	
+	if (g_utf8_validate(pattern, -1, NULL) &&
+			g_utf8_validate(haystack, -1, NULL)) {
+
+		if (g_utf8_strlen(pattern, -1) == 1 && (
+			*pattern == '*' || (*pattern == '?' &&
+			g_utf8_strlen(haystack, -1) < 2)))
+			return TRUE;
+		
+		if (*pattern && g_utf8_strlen(haystack, -1) < 1)
+			return FALSE;
+		
+		txt = pattern;
+		source = haystack;
+
+		while (*txt && *source && !error) {
+			ch = g_utf8_get_char(txt);
+			cp = g_utf8_get_char(source);
+			switch (ch) {
+				case '*':
+					in_str = TRUE;
+					break;
+				case '?':
+					break;
+				default:
+					if (! case_aware) {
+						cp = g_unichar_toupper(cp);
+						ch = g_unichar_toupper(ch);
+					}
+					if (in_str) {
+						while (ch != cp && *source) {
+							source = g_utf8_find_next_char(source, NULL);
+							cp = g_utf8_get_char(source);
+							if (! case_aware)
+								cp = g_unichar_toupper(cp);
+						}
+						in_str = FALSE;
+					}
+					else
+						error = (cp == ch) ? FALSE : TRUE;
+					break;
+			}
+			if (!error) {
+				has_source = FALSE;
+				if (*source && !in_str) {
+					has_source = TRUE;
+					source = g_utf8_find_next_char(source, NULL);
+				}
+				if (*source || has_source)
+					txt = g_utf8_find_next_char(txt, NULL);
+			}
+		}
+		if (!*source && (ch = g_utf8_get_char(txt)) != 0) {
+			if (ch != '*') {
+				if (ch == '?' && g_utf8_strlen(txt, -1) == 1) {
+					/* keep value of error */
+				}
+				else {
+					if (g_utf8_strlen(txt, -1) > 1)
+						error = TRUE;
+				}
+			}
+		}
+		else if (*source && !g_utf8_get_char(txt)) {
+			if (ch != '*') {
+				if (ch == '?' && g_utf8_strlen(source, -1) < 1) {
+					/* keep value of error */
+				}
+				else
+					error = TRUE;
+			}
+		}
+		else {
+			/* Keep value of error */
+		}
+	}
+	
+	return (!error);
+}
+
+gboolean email_compare_values(GSList* a, GSList* b, gboolean is_and) {
+	GSList *cur1, *cur2;
+	gint equal = -1;
+	
+	for (cur1 = a; cur1; cur1 = g_slist_next(cur1)) {
+		Email* e1 = (Email *) cur1->data;
+		for (cur2 = b; cur2; cur2 = g_slist_next(cur2)) {
+			Email* e2 = (Email *) cur2->data;
+			if (e1->alias) {
+				equal = match_string_pattern(e1->alias, e2->alias, TRUE);
+				if ((!equal && is_and) || (equal && !is_and))
+					break;
+			}
+			if (e1->email) { 
+				equal = match_string_pattern(e1->email, e2->email, TRUE);
+				if ((!equal && is_and) || (equal && !is_and))
+					break;
+			}
+			if (e1->remarks) 
+				equal = match_string_pattern(e1->remarks, e2->remarks, TRUE);
+		}
+		if (equal && !is_and)
+			break;
+	}
+	
+	return equal;
+}
+
+void contact_compare_values(gpointer k, gpointer v, gpointer data) {
+	Compare* comp = (Compare *) data;
+	AttribDef *attr;
+	const gchar* term;
+	
+	term = ((AttribDef *) v)->value.string;
+	
+	if (debug_get_mode()) {
+		Contact* c = g_new0(Contact, 1);
+		c->data = comp->hash;
+		contact_dump(c, stderr);
+		fprintf(stderr, "Key: %s - Value: %s\n", (gchar *) k, term);
+		g_free(c);
+	}
+	if ((comp->is_and && comp->equal) ||
+		(!comp->is_and && (comp->equal < 0 || comp->equal == 0))) {
+		attr = g_hash_table_lookup(comp->hash, k);
+		if (attr) {
+			if (attr->type == ATTRIB_TYPE_STRING) {
+				comp->equal = match_string_pattern(
+					term, attr->value.string, TRUE);
+			}
+			else if (attr->type == ATTRIB_TYPE_CHAR) {
+				gchar* ch = g_strdup_printf("%c", attr->value.character);
+				comp->equal = match_string_pattern(term, ch, TRUE);
+				g_free(ch);
+			}
+			else if (attr->type == ATTRIB_TYPE_BOOLEAN) {
+				comp->equal = attr->value.boolean = atoi(term);
+			}
+			else if (attr->type == ATTRIB_TYPE_INT) {
+				comp->equal = attr->value.number = atoi(term);
+			}
+			else {
+				comp->equal = FALSE;
+			}
+		}
+	}
+	else
+		comp->equal = FALSE;
+}

Index: callbacks.h
===================================================================
RCS file: /home/claws-mail/contacts/src/callbacks.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- callbacks.h	7 Sep 2011 17:35:29 -0000	1.1
+++ callbacks.h	20 Nov 2011 21:24:20 -0000	1.2
@@ -43,6 +43,7 @@
 #include "plugin-loader.h"
 
 AddressBook* get_selected_address_book(GtkTreeView* view);
+void set_selected_address_book(GtkTreeView* view, AddressBook* book);
 Plugin* get_selected_plugin(GtkTreeView* view);
 Contact* get_selected_contact(GtkTreeView* view);
 gint delete_event(GtkWidget* widget, GdkEvent* event, gpointer data);

Index: callbacks.c
===================================================================
RCS file: /home/claws-mail/contacts/src/callbacks.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- callbacks.c	14 Nov 2011 22:06:43 -0000	1.6
+++ callbacks.c	20 Nov 2011 21:24:20 -0000	1.7
@@ -223,6 +223,7 @@
 static void show_popup_menu(GtkWidget* widget, GdkEventButton* event,
         gpointer data, gboolean new_row) {
     MainWindow* win = (MainWindow *) data;
+    GtkTreeView* view;
     int button, event_time;
     GtkWidget *menu,
               *abook_new, *abook_open, 
@@ -272,6 +273,14 @@
             gtk_menu_shell_append(GTK_MENU_SHELL(menu), abook_open);
 		}
         else {
+			view = GTK_TREE_VIEW(win->abook_list);
+			win->selected_abook = get_selected_address_book(view);
+			if (win->selected_abook == NULL) {
+				g_object_unref(accel);
+				gtk_widget_destroy(menu);
+				return;
+			}
+
     		abook_edit = gtk_image_menu_item_new_from_stock(
 					GTK_STOCK_EDIT, accel);
     		gtk_widget_add_accelerator(abook_edit, "activate", accel,
@@ -280,15 +289,6 @@
                 G_CALLBACK(abook_edit_cb), win);
             gtk_menu_shell_append(GTK_MENU_SHELL(menu), abook_edit);
 
-            abook_open = gtk_image_menu_item_new_with_mnemonic("_Open");
-    		gtk_image_menu_item_set_accel_group(
-					GTK_IMAGE_MENU_ITEM(abook_open), accel);
-    		gtk_widget_add_accelerator(abook_open, "activate", accel,
-            		GDK_O, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
-           	g_signal_connect(abook_open, "activate",
-                G_CALLBACK(abook_open_cb), win);
-            gtk_menu_shell_append(GTK_MENU_SHELL(menu), abook_open);
-
             abook_close = gtk_image_menu_item_new_with_mnemonic("_Close");
     		gtk_image_menu_item_set_accel_group(
 					GTK_IMAGE_MENU_ITEM(abook_close), accel);
@@ -319,6 +319,14 @@
 			gtk_menu_shell_append(GTK_MENU_SHELL(menu), contact_new);
 		}
 		else {
+			view = GTK_TREE_VIEW(win->contact_list);
+			win->selected_contact = get_selected_contact(view);
+			if (win->selected_contact == NULL) {
+				g_object_unref(accel);
+				gtk_widget_destroy(menu);
+				return;
+			}
+
             contact_edit = gtk_image_menu_item_new_from_stock(
                 GTK_STOCK_EDIT, accel);
     		gtk_widget_add_accelerator(contact_edit, "activate", accel,
@@ -528,6 +536,13 @@
 	return abook;
 }
 
+void set_selected_address_book(GtkTreeView* view, AddressBook* book) {
+	if (! view || ! book)
+		return;
+		
+	
+}
+
 Plugin* get_selected_plugin(GtkTreeView* view) {
     GtkTreeIter   iter;
     GtkTreeModel* model;
@@ -621,31 +636,114 @@
 
 void abook_edit_cb(GtkWidget* widget, gpointer data) {
     MainWindow* win = (MainWindow *) data;
-	AddressBook *abook, *new;
-	Plugin* plugin;
+	AddressBook *abook = NULL, *new;
+	Plugin* plugin = NULL;
 	gchar *error = NULL;
+	GSList *plugins;
+	GList *closed = NULL, *cur_closed;
+	GSList *open = NULL, *cur_open; 
+	gboolean use_closed = FALSE;
+	GSList* names = NULL;
+	gchar* plugin_name = NULL;
 	GtkTreeView* view;
 	GtkTreeIter* iter;
 
-	view = GTK_TREE_VIEW(win->abook_list);
-	abook = get_selected_address_book(view);
-	if (abook == NULL) {
-		iter = set_selection_combobox(win->window,
-						"[Edit book] Choose address book",
-						gtk_tree_view_get_model(view),
-						BOOK_NAME_COLUMN);
-		if (! iter)
-			return;
-		GtkTreeSelection* row = gtk_tree_view_get_selection(view);
-		gtk_tree_selection_select_iter(row, iter);
-		g_free(iter);
-		abook = get_selected_address_book(view);
+	if (win->selected_abook) {
+		abook = (AddressBook *) win->selected_abook;
+		win->selected_abook = NULL;
+		view = GTK_TREE_VIEW(win->abook_list);
+		plugin = get_selected_plugin(view);
+	}
+	else {
+		plugins = plugin_get_name_all();
+		gboolean response = show_choice_list(win->window,
+			"[Open book] Select plugin to use",
+			plugins, &plugin_name);
+		gslist_free(&plugins, NULL);
+
+		if (response) {
+			plugin = plugin_get_plugin(plugin_name);
+			if (plugin) {
+				closed = plugin->closed_books_get();
+				if (closed) {
+					use_closed = show_question(win->window,
+						"Choose from list of previously closed books?");
+				}
+				if (use_closed) {
+					for (cur_closed = closed; cur_closed; cur_closed = g_list_next(cur_closed)) {
+						AddressBook* abook = (AddressBook *) cur_closed->data;
+						names = g_slist_append(names, g_strdup(abook->abook_name));
+					}
+					if (names) {
+						g_free(plugin_name);
+						plugin_name = NULL;
+						if (show_choice_list(win->window, "Choose address book",
+								names, &plugin_name)) {
+							gint index = gslist_get_index(
+								names, plugin_name, gslist_compare_gchar);
+							abook = address_book_copy(g_list_nth_data(closed, index), TRUE);
+						}
+						gslist_free(&names, g_free);
+					}
+					g_free(plugin_name);
+				}
+				else {
+					open = plugin->addrbook_all_get();
+					if (open) {
+						for (cur_open = open; cur_open; cur_open = g_slist_next(cur_open)) {
+							AddressBook* abook = (AddressBook *) cur_open->data;
+							names = g_slist_append(names, g_strdup(abook->abook_name));
+						}
+						if (names) {
+							g_free(plugin_name);
+							plugin_name = NULL;
+							if (show_choice_list(win->window, "Choose address book",
+									names, &plugin_name)) {
+								gint index = gslist_get_index(
+									names, plugin_name, gslist_compare_gchar);
+								abook = address_book_copy(g_slist_nth_data(open, index), TRUE);
+							}
+							gslist_free(&names, g_free);
+						}
+						g_free(plugin_name);
+						gslist_free(&open, NULL);
+					}
+					else {
+						show_message(win->window, GTK_UTIL_MESSAGE_INFO,
+							_("No address book to edit"));
+					}
+				}
+				if (closed) {
+					for (cur_closed = closed; cur_closed; cur_closed = g_list_next(cur_closed)) {
+						AddressBook* a = (AddressBook *) cur_closed->data;
+						address_book_free(&a);
+					}
+					glist_free(&closed, NULL);
+				}
+			}
+		}
+		else {
+			view = GTK_TREE_VIEW(win->abook_list);
+			plugin = get_selected_plugin(view);
+			/*	abook = get_selected_address_book(view);
+				if (abook == NULL) {*/
+			iter = set_selection_combobox(win->window,
+							"[Edit book] Choose address book",
+							gtk_tree_view_get_model(view),
+							BOOK_NAME_COLUMN);
+			if (! iter)
+				return;
+			GtkTreeSelection* row = gtk_tree_view_get_selection(view);
+			gtk_tree_selection_select_iter(row, iter);
+			g_free(iter);
+			abook = get_selected_address_book(view);
+		}
 	}
-	new = address_book_copy(abook, TRUE);
-	plugin = get_selected_plugin(GTK_TREE_VIEW(win->abook_list));
 	if (abook && plugin) {
+		new = address_book_copy(abook, TRUE);
 		if (address_book_edit(win->window, plugin, &new)) {
-			plugin->abook_close(abook, &error);
+			if (! use_closed)
+				plugin->abook_close(abook, &error);
 			if (error) {
 				show_message(win->window, GTK_UTIL_MESSAGE_ERROR, "%s", error);
 				g_free(error);
@@ -659,14 +757,19 @@
 				address_book_free(&new);
 				return;
 			}
-			address_book_free(&abook);
 			plugin->abook_open(new, &error);
 			if (error) {
 				show_message(win->window, GTK_UTIL_MESSAGE_ERROR, "%s", error);
 				g_free(error);
 				address_book_free(&new);
 			}
+			win->selected_abook = abook;
 			update_abook_list(win);
+			win->selected_abook = NULL;
+			address_book_free(&abook);
+		}
+		else {
+			address_book_free(&new);
 		}
 	}
 	else {
@@ -683,9 +786,15 @@
 	GtkTreeView* view;
 	GtkTreeIter* iter;
 
-	view = GTK_TREE_VIEW(win->abook_list);
-	abook = get_selected_address_book(view);
-	if (abook == NULL) {
+	/* TODO: be able to also delete closed books */
+	if (win->selected_abook) {
+		abook = (AddressBook *) win->selected_abook;
+		win->selected_abook = NULL;
+	}
+	else {
+		view = GTK_TREE_VIEW(win->abook_list);
+/*	abook = get_selected_address_book(view);
+	if (abook == NULL) {*/
 		iter = set_selection_combobox(win->window,
 						"[Delete book] Choose address book",
 						gtk_tree_view_get_model(view),
@@ -726,6 +835,7 @@
 	gboolean use_closed = FALSE;
 	GList* cur;
 	GSList* names = NULL;
+	GList* closed = NULL;
 
     debug_print("Creating address book window\n");
 	
@@ -738,7 +848,7 @@
 	if (response) {
 		plugin = plugin_get_plugin(plugin_name);
 		if (plugin) {
-			GList* closed = plugin->closed_books_get();
+			closed = plugin->closed_books_get();
 			if (closed) {
 				use_closed = show_question(win->window,
 					"Choose from list of previously closed books?");
@@ -805,9 +915,14 @@
 	GtkTreeView* view;
 	GtkTreeIter* iter;
 
-	view = GTK_TREE_VIEW(win->abook_list);
-	abook = get_selected_address_book(view);
-	if (abook == NULL) {
+	if (win->selected_abook) {
+		abook = (AddressBook *) win->selected_abook;
+		win->selected_abook = NULL;
+	}
+	else {
+		view = GTK_TREE_VIEW(win->abook_list);
+/*	abook = get_selected_address_book(view);
+	if (abook == NULL) {*/
 		iter = set_selection_combobox(win->window,
 						"[Close book] Choose address book",
 						gtk_tree_view_get_model(view),
@@ -853,6 +968,12 @@
 		plugin = plugin_get_plugin(plugin_name);
 		if (plugin) {
 			if (address_book_edit(win->window, plugin, &book)) {
+				if (address_book_name_exists(plugin, book)) {
+					error = g_strdup_printf("%s: Name is in use!",
+						(book->abook_name) ? book->abook_name : "Missing name");
+					address_book_free(&book);
+					goto error;
+				}
 				if (plugin->file_filter() && strcmp("xml", plugin->file_filter()) == 0 &&
 						g_file_test(book->URL, G_FILE_TEST_EXISTS)) {
 					AddressBook* abook =
@@ -882,6 +1003,9 @@
 					if (plugin->abook_open(book, &error)) 
 						update_abook_list(win);
 				}
+				else
+					address_book_free(&book);
+	error:
 				if (error) {
 					show_message(win->window, GTK_UTIL_MESSAGE_WARNING, "%s", error);
 					g_free(error);
@@ -938,15 +1062,17 @@
 }
 
 void update_abook_list(MainWindow* mainwindow) {
-    GtkTreeIter   iter;
+    GtkTreeIter   iter, *selected = NULL;
     GtkListStore* store;
     GtkTreeModel* model;
+    GtkTreeSelection* row;
     GSList *list, *ref, *cur;
 
-	list_view_clear(GTK_TREE_VIEW(mainwindow->abook_list), mainwindow);
-	list_view_clear(GTK_TREE_VIEW(mainwindow->contact_list), mainwindow);
     model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainwindow->abook_list));
     store = GTK_LIST_STORE(model);
+
+	list_view_clear(GTK_TREE_VIEW(mainwindow->abook_list), mainwindow);
+	list_view_clear(GTK_TREE_VIEW(mainwindow->contact_list), mainwindow);
 	ref = address_books_get();
 	for (list = ref; list; list = g_slist_next(list)) {
 		Reference* reference = (Reference *) list->data;
@@ -957,6 +1083,11 @@
 					BOOK_NAME_COLUMN, book->abook_name,
 					BOOK_DATA_COLUMN, book,
 					BOOK_PLUGIN_COLUMN, reference->plugin, -1);
+			if (mainwindow->selected_abook) {
+				if (address_book_compare(book, mainwindow->selected_abook) == 0) {
+					selected = gtk_tree_iter_copy(&iter);
+				}
+			}
 		}
 		gslist_free(&reference->abooks, NULL);
 	}
@@ -965,6 +1096,12 @@
 		gtk_widget_set_sensitive(mainwindow->adv_search_btn, FALSE);
 		gtk_widget_set_sensitive(mainwindow->new_btn, FALSE);
 	}
+	if (selected) {
+		row = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainwindow->abook_list));
+		gtk_tree_selection_select_iter(row, selected);
+		abook_list_cursor_changed_cb(GTK_TREE_VIEW(mainwindow->abook_list), mainwindow);
+		gtk_tree_iter_free(selected);
+	}
 	gslist_free(&ref, NULL);
 }
 
@@ -994,6 +1131,52 @@
 	}
 }
 
+static void compare_extra_config_value(ExtraConfig* ec) {
+	if (ec) {
+		switch (ec->type) {
+			case PLUGIN_CONFIG_EXTRA_CHECKBOX:
+			case PLUGIN_CONFIG_EXTRA_SPINBUTTON:
+				break;
+			case PLUGIN_CONFIG_EXTRA_ENTRY:
+				if (! ec->current_value.entry)
+					ec->current_value.entry = g_strdup(ec->preset_value.entry);
+				break;
+		}
+	}
+}
+
+static GSList* make_extra_config(GSList* preset, GSList* current) {
+	GSList* merged = NULL;
+	GSList *head, *p_list, *c_list;
+	
+	head = g_slist_copy(preset);
+	c_list = current;
+	while (c_list) {
+		p_list = preset;
+		while(p_list) {
+			ExtraConfig* c = (ExtraConfig *) c_list->data;
+			ExtraConfig* p = (ExtraConfig *) p_list->data;
+			if (c && p && c->type == p->type &&
+					utf8_collate(c->label, p->label) == 0) {
+				compare_extra_config_value(c);
+				merged = g_slist_prepend(merged, c);
+				head = g_slist_remove(head, p);
+				break;
+			}
+			p_list = p_list->next;
+		}
+		c_list = c_list->next;
+	}
+	p_list = head;
+	while (p_list) {
+		merged = g_slist_prepend(merged, extra_config_copy(p_list->data));
+		p_list = p_list->next;
+	}
+	g_slist_free(head);
+	
+	return merged;
+}
+
 static void add_advanced_page(GtkNotebook* notebook,
 							  Plugin* plugin,
 							  AddressBook* address_book) {
@@ -1002,7 +1185,9 @@
 	gboolean new;
 	
 	if (address_book->extra_config) {
-		extra = address_book->extra_config;
+		GSList* preset = plugin->extra_config();
+		extra = make_extra_config(preset, address_book->extra_config);
+		gslist_free(&preset, extra_config_free);
 		new = FALSE;
 	}
 	else {
@@ -1024,10 +1209,10 @@
 						gtk_widget_set_tooltip_text(widget, ec->tooltip);
 					if (new)
 						gtk_toggle_button_set_active(
-							GTK_TOGGLE_BUTTON(widget), ec->default_value.check_btn);
+							GTK_TOGGLE_BUTTON(widget), ec->preset_value.check_btn);
 					else
 						gtk_toggle_button_set_active(
-							GTK_TOGGLE_BUTTON(widget), ec->value.check_btn);
+							GTK_TOGGLE_BUTTON(widget), ec->current_value.check_btn);
 					label = gtk_label_new("");
 					break;
 				case PLUGIN_CONFIG_EXTRA_ENTRY:
@@ -1038,10 +1223,10 @@
 						label = gtk_label_new("");
 					if (ec->tooltip)
 						gtk_widget_set_tooltip_text(widget, ec->tooltip);
-					if (ec->value.entry)
-						gtk_entry_set_text(GTK_ENTRY(widget), ec->value.entry);
-					else if (ec->default_value.entry)
-						gtk_entry_set_text(GTK_ENTRY(widget), ec->default_value.entry);
+					if (ec->current_value.entry)
+						gtk_entry_set_text(GTK_ENTRY(widget), ec->current_value.entry);
+					else if (ec->preset_value.entry)
+						gtk_entry_set_text(GTK_ENTRY(widget), ec->preset_value.entry);
 					break;
 				case PLUGIN_CONFIG_EXTRA_SPINBUTTON:
 					widget = gtk_spin_button_new_with_range(0.0, 100.0, 1.0);
@@ -1053,10 +1238,10 @@
 						gtk_widget_set_tooltip_text(widget, ec->tooltip);
 					if (new)
 						gtk_spin_button_set_value(
-							GTK_SPIN_BUTTON(widget), ec->default_value.spin_btn);
+							GTK_SPIN_BUTTON(widget), ec->preset_value.spin_btn);
 					else		
 						gtk_spin_button_set_value(
-							GTK_SPIN_BUTTON(widget), ec->value.spin_btn);		
+							GTK_SPIN_BUTTON(widget), ec->current_value.spin_btn);		
 					break;
 			}
 			gtk_widget_set_name(widget, ec->label);
@@ -1071,8 +1256,10 @@
 		}
 		label = gtk_label_new(_("Advanced settings"));
 		gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label);
-		if (! address_book->extra_config)
+		if (new)
 			gslist_free(&extra, extra_config_free);
+		else
+			gslist_free(&extra, NULL);
 	}
 }
 
@@ -1110,7 +1297,7 @@
 							widget = NULL;
 					}
 					if (widget) {
-						ec->value.check_btn = 
+						ec->current_value.check_btn = 
 							gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
 					}
 					break;
@@ -1129,8 +1316,8 @@
 							widget = NULL;
 					}
 					if (widget) {
-						g_free(ec->value.entry);
-						ec->value.entry = 
+						g_free(ec->current_value.entry);
+						ec->current_value.entry = 
 							gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1);
 					}
 					break;
@@ -1149,7 +1336,7 @@
 							widget = NULL;
 					}
 					if (widget) {
-						ec->value.spin_btn = 
+						ec->current_value.spin_btn = 
 							gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
 					}
 					break;
@@ -1612,10 +1799,10 @@
 	AddressBook* abook;
 	Plugin* plugin;
 	Contact* contact;
-	gchar* mail = NULL;
+	gchar *mail, *cn, *first, *last, *con_id;
 	gchar* error = NULL;
 
-
+	mail = cn = first = last = con_id = NULL;
 	view = GTK_TREE_VIEW(win->abook_list);
 	plugin = get_selected_plugin(view);
 
@@ -1640,8 +1827,14 @@
 	}
 
 	view = GTK_TREE_VIEW(win->contact_list);
+	if (win->selected_contact) {
+		contact = (Contact *) win->selected_contact;
+		win->selected_contact = NULL;
+	}
+	else {
+/*	view = GTK_TREE_VIEW(win->contact_list);
 	contact = get_selected_contact(view);
-	if (contact == NULL) {
+	if (contact == NULL) {*/
 		iter = set_selection_combobox(win->window,
 						_("[Delete Contact] Choose contact to delete"),
 						gtk_tree_view_get_model(view),
@@ -1665,10 +1858,25 @@
 			iter = g_new0(GtkTreeIter, 1);
 			if (gtk_tree_selection_get_selected(row, &model, iter)) {
 				gtk_tree_model_get(model, iter, CONTACT_EMAIL_COLUMN, &mail, -1);
+				gtk_tree_model_get(model, iter, CONTACT_DISPLAYNAME_COLUMN, &cn, -1);
+				gtk_tree_model_get(model, iter, CONTACT_FIRSTNAME_COLUMN, &first, -1);
+				gtk_tree_model_get(model, iter, CONTACT_LASTNAME_COLUMN, &last, -1);
+			}
+			if (mail)
+				con_id = g_strdup(mail);
+			else if (cn)
+				con_id = g_strdup(cn);
+			else if (first || last) {
+				if (first && last)
+					con_id = g_strconcat(first, " ", last, NULL);
+				else if (last)
+					con_id = g_strdup(last);					
+				else
+					con_id = g_strdup(first);					
 			}
 		}
 		if (show_question(win->window,
-			_("Should contact '%s' be deleted?"), mail ? mail : "Unknown")) {
+			_("Should contact '%s' be deleted?"), con_id ? con_id : "Unknown")) {
 			plugin->delete_contact(abook, contact, &error);
 			if (iter && !error) {
 				gtk_list_store_remove(GTK_LIST_STORE(model), iter);
@@ -1683,6 +1891,9 @@
 			g_free(error);
 		}
 		g_free(mail);
+		g_free(cn);
+		g_free(first);
+		g_free(last);
 	}
 }
 
@@ -1720,8 +1931,14 @@
 	}
 
 	view = GTK_TREE_VIEW(win->contact_list);
+	if (win->selected_contact) {
+		contact = (Contact *) win->selected_contact;
+		win->selected_contact = NULL;
+	}
+	else {
+/*	view = GTK_TREE_VIEW(win->contact_list);
 	contact = get_selected_contact(view);
-	if (contact == NULL) {
+	if (contact == NULL) {*/
 		iter = set_selection_combobox(win->window,
 						_("[Edit Contact] Choose contact to edit"),
 						gtk_tree_view_get_model(view),



More information about the Commits mailing list