[Commits] Makefile.am 1.2 1.3 vcard-utils.c 1.1 1.2 vcard-utils.h 1.1 1.2

miras at claws-mail.org miras at claws-mail.org
Mon Mar 26 00:55:15 CEST 2012


Update of /home/claws-mail/contacts/libversit
In directory srv:/tmp/cvs-serv12090/libversit

Modified Files:
	Makefile.am vcard-utils.c vcard-utils.h 
Log Message:
2012-03-25 [mir]	0.6.0cvs80

	* extensions/vcard/src/vcard-extension.c
	* libversit/Makefile.am
	* libversit/vcard-utils.c
	* libversit/vcard-utils.h
	* src/utils.c
	* src/utils.h
	* src/dbus/Makefile.am
	* src/dbus/claws-contacts.xml
	* src/dbus/server-object.c
	* src/dbus/server-object.h
	* xmllib/parser.c
	A bunch of changes and enhancements. Also added feature
	to allow users to create a vCard for each account which
	is to be used for optionally added a vCard to every
	send email. 

Index: Makefile.am
===================================================================
RCS file: /home/claws-mail/contacts/libversit/Makefile.am,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Makefile.am	5 Jan 2012 01:45:06 -0000	1.2
+++ Makefile.am	25 Mar 2012 22:55:13 -0000	1.3
@@ -7,6 +7,7 @@
 		$(includedir)/claws-contacts
 
 libvcardinclude_HEADERS = \
+		    port.h \
 		    vcard-utils.h \
 			vobject.h
 
@@ -23,7 +24,6 @@
 	    -d
 
 libversit_la_SOURCES = \
-		    port.h \
 		    vobject.c \
 		    vcc.c \
 			vcc.h \

Index: vcard-utils.c
===================================================================
RCS file: /home/claws-mail/contacts/libversit/vcard-utils.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- vcard-utils.c	5 Jan 2012 01:45:06 -0000	1.1
+++ vcard-utils.c	25 Mar 2012 22:55:13 -0000	1.2
@@ -33,15 +33,16 @@
 #       include <config.h>
 #endif
 
+#include <errno.h>
 #include <glib.h>
 #include <glib/gi18n.h>
+#include <glib/gstdio.h>
 #include <glib/gprintf.h>
 #include <string.h>
 #include "plugin.h"
 #include "plugin-loader.h"
-//#include "extension.h"
 #include "utils.h"
-//#include "gtk-utils.h"
+#include "gtk-utils.h"
 #include "vobject.h"
 #include "vcard-utils.h"
 
@@ -58,6 +59,43 @@
 	NUMPHONES,
 };
 
+typedef struct {
+	const gchar* prop;
+	const gchar* label;
+	const gchar* tooltip;
+	GtkWidget*	 widget;
+} VcardItem;
+
+enum {
+	VI_GivenName,
+	VI_AdditionalNames,
+	VI_FamilyName,
+	VI_Adr,
+	VI_City,
+	VI_PostalCode,
+	VI_Location,
+	VI_Title,
+	VI_URL,
+	VI_X509,
+	VI_Telephone_Work,
+	VI_Telephone_Home,
+	VI_Telephone_Cellular,
+	VI_EmailAddress_Work,
+	VI_EmailAddress_Home,
+	VI_Fax,
+	VI_GeoLocation,
+	VI_Photo,
+	VI_TimeZone,
+	VI_Account,
+	VI_Items
+};
+
+#define VCTelephoneCellProp		VCTelephoneProp";"VCCellularProp
+#define VCTelephoneHomeProp		VCTelephoneProp";"VCHomeProp
+#define VCTelephoneWorkProp		VCTelephoneProp";"VCWorkProp
+#define VCEmailAddressWorkProp	VCEmailAddressProp";"VCWorkProp
+#define VCEmailAddressHomeProp	VCEmailAddressProp";"VCHomeProp
+
 static const gchar* phone[NUMTYPES][NUMPHONES] =
 	{ 
 		{"mobile", "homePhone", "telephoneNumber"}, /* LDAP */
@@ -67,10 +105,18 @@
 static const gchar* phone_prop[NUMPHONES] =
 	{ VCCellularProp, VCHomeProp, VCWorkProp };
 		
-struct _CBData {
+struct CBData {
 	VObject* o;
 	Plugin* p;
-} cb_data;
+};
+
+struct DData {
+	MainWindow*	mainwindow;
+	VcardItem**	items;
+	gchar*		account;
+	gboolean	has_pix;
+	gboolean	has_cert;
+};
 
 static void strip_whitespace(gchar** s) {
 	gchar *ptr, *token;
@@ -191,7 +237,7 @@
 			initPropIterator(&iter,v);
     		while (moreIteration(&iter) && !attr) {
 				VObject *prop = nextVObject(&iter);
-				gchar* value = vObjectName(prop);/*(gchar *) vcard_value(prop);*/
+				gchar* value = vObjectName(prop);
 				if (value) {
 					if (g_str_has_prefix(plugin_type, "LDAP")) {
 						if (g_strstr_len(value, strlen(value), "CELL"))
@@ -307,7 +353,7 @@
 			value = vcard_value(prop);
 			if (value) {
 				if (family) {
-					gchar* tmp = family;
+					gchar* tmp = g_strdup(family);
 					g_free(family);
 					family = g_strconcat(tmp, " ", value, NULL);
 					g_free(tmp);
@@ -321,7 +367,7 @@
 			value = vcard_value(prop);
 			if (value) {
 				if (family) {
-					gchar* tmp = family;
+					gchar* tmp = g_strdup(family);
 					g_free(family);
 					family = g_strconcat(value, " ", tmp, NULL);
 					g_free(tmp);
@@ -444,7 +490,7 @@
 static void hash_iter(gpointer k, gpointer v, gpointer u) {
 	gchar* key = (gchar *) k;
 	AttribDef* attr = (AttribDef *) v;
-	struct _CBData* cb_data = (struct _CBData *) u;
+	struct CBData* cb_data = (struct CBData *) u;
 	void* value;
 	
 	AttribType type = get_data(attr, &value);
@@ -462,6 +508,7 @@
 GSList* contacts2vcard(GList* contacts, Plugin* plugin, gchar** error) {
 	GSList* vcards = NULL;
 	GList* cur;
+	struct CBData cb_data;
 
 	cm_return_val_if_fail(plugin != NULL, NULL);
 	cm_return_val_if_fail(contacts != NULL, NULL);
@@ -501,10 +548,637 @@
 	return o;
 }
 
-VObject* personal_vcard(gchar** error) {
+static void mime_error_handler(char *s, void* user_data) {
+	MainWindow* win = (MainWindow *) user_data;
+	
+	gchar* msg = g_strdup_printf("vCard parser: %s", s);
+	debug_print("%s\n", msg);
+	show_message((win) ? win->window : NULL, GTK_UTIL_MESSAGE_WARNING, msg);
+	g_free(msg);
+}
+
+gchar* personal_vcard_get(const gchar* account, gchar** error) {
 	VObject* o = NULL;
+	gchar* vcard = NULL;
+	gchar* file;
+	gchar* home;
 	
-	return o;
+	home = get_self_home();
+	file = g_strconcat(home, G_DIR_SEPARATOR_S, account, ".vcf", NULL);
+	g_free(home);
+	if (g_file_test(file, G_FILE_TEST_EXISTS)) {
+		registerMimeErrorHandler(mime_error_handler, NULL);
+		o = Parse_MIME_FromFileName(file);
+		if (o) {
+			vcard = writeMemVObject(0, 0, o);
+			cleanVObject(o);
+		}
+	}
+	else {
+		if (*error)
+			*error = g_strconcat(file, ": ", N_("Does not exists"), NULL);
+	}
+	g_free(file);
+
+	return vcard;
+}
+
+static VcardItem** vcard_widget_new() {	
+	static VcardItem GivenName, AdditionalNames, FamilyName, Adr, City;
+	static VcardItem PostalCode, Location, Title, URL, X509, Telephone_Cellular;
+	static VcardItem Telephone_Home, Telephone_Work, EmailAddress_Home;
+	static VcardItem EmailAddress_Work, Fax, GeoLocation, Photo, TimeZone, Account;
+	VcardItem** items = g_new0(VcardItem *, VI_Items);
+
+	GivenName.label = N_("Firstname");
+	GivenName.prop = VCGivenNameProp;
+	GivenName.tooltip = N_("Your Given Name");
+	AdditionalNames.label = N_("Additional Names");
+	AdditionalNames.prop = VCAdditionalNamesProp;
+	AdditionalNames.tooltip = N_("Space separated list of additional names");
+	FamilyName.label = N_("Lastname");
+	FamilyName.prop = VCFamilyNameProp;
+	FamilyName.tooltip = N_("Your Family name");
+	Adr.label = N_("Address");
+	Adr.prop = VCStreetAddressProp;
+	Adr.tooltip = N_("Your Address");
+	City.label = N_("City");
+	City.prop = VCCityProp;
+	City.tooltip = N_("Your City");
+	PostalCode.label = N_("ZIP");
+	PostalCode.prop = VCPostalCodeProp;
+	PostalCode.tooltip = N_("Your ZIP code");
+	Location.label = N_("Country");
+	Location.prop = VCLocationProp;
+	Location.tooltip = N_("Your Country");
+	Title.label = N_("Title");
+	Title.prop = VCTitleProp;
+	Title.tooltip = N_("Your Title");
+	URL.label = N_("URL");
+	URL.prop = VCURLProp;
+	URL.tooltip = N_("URL to website");
+	X509.label = N_("X509 Certificate");
+	X509.prop = VCX509Prop";"VCEncodingProp"="VCBase64Prop;
+	X509.tooltip = N_("Your personal X509 Certificate");
+	Telephone_Cellular.label = N_("Mobile Phone");
+	Telephone_Cellular.prop = VCTelephoneCellProp;
+	Telephone_Cellular.tooltip = N_("Your Mobile Phone");
+	Telephone_Home.label = N_("Home Phone");
+	Telephone_Home.prop = VCTelephoneHomeProp;
+	Telephone_Home.tooltip = N_("Your Home Phone number");
+	Telephone_Work.label = N_("Work Phone");
+	Telephone_Work.prop = VCTelephoneWorkProp;
+	Telephone_Work.tooltip = N_("Your Work Phone number");
+	EmailAddress_Home.label = N_("Personal Email Address");
+	EmailAddress_Home.prop = VCEmailAddressHomeProp;
+	EmailAddress_Home.tooltip = N_("Your Personal Email Address");
+	EmailAddress_Work.label = N_("Work Email Address");
+	EmailAddress_Work.prop = VCEmailAddressWorkProp;
+	EmailAddress_Work.tooltip = N_("Your Work Email Address");
+	Fax.label = N_("FAX number");
+	Fax.prop = VCFaxProp;
+	Fax.tooltip = N_("Your FAX number");
+	GeoLocation.label = N_("Geographical Location");
+	GeoLocation.prop = VCGeoLocationProp;
+	GeoLocation.tooltip = N_("Latitude, Longitude");
+	Photo.label = N_("Photo");
+	Photo.prop = VCPhotoProp";"VCEncodingProp"="VCBase64Prop;
+	Photo.tooltip = N_("Picture in JPEG, GIF or PNG format");
+	TimeZone.label = N_("TimeZone"); 
+	TimeZone.prop = VCTimeZoneProp;
+	TimeZone.tooltip = N_("TimeZone specified in ISO-8601 format");
+	Account.tooltip = N_("Account this vCard relates to"); 
+
+	items[VI_GivenName] = &GivenName;
+	items[VI_AdditionalNames] = &AdditionalNames;
+	items[VI_FamilyName] = &FamilyName;
+	items[VI_Adr] = &Adr;
+	items[VI_City] = &City;
+	items[VI_PostalCode] = &PostalCode;
+	items[VI_Location] = &Location;
+	items[VI_Title] = &Title;
+	items[VI_URL] = &URL;
+	items[VI_X509] = &X509;
+	items[VI_Telephone_Cellular] = &Telephone_Cellular;
+	items[VI_Telephone_Home] = &Telephone_Home;
+	items[VI_Telephone_Work] = &Telephone_Work;
+	items[VI_EmailAddress_Home] = &EmailAddress_Home;
+	items[VI_EmailAddress_Work] = &EmailAddress_Work;
+	items[VI_Fax] = &Fax;
+	items[VI_GeoLocation] = &GeoLocation;
+	items[VI_Photo] = &Photo;
+	items[VI_TimeZone] = &TimeZone;
+	items[VI_Account] = &Account;
+	
+	return items;
+}
+
+static GtkWidget* label_and_input(const gchar* text,
+								  const gchar* tooltip,
+								  gboolean has_focus) {
+	GtkWidget *label, *entry, *hbox;
+	
+	hbox = gtk_hbox_new(FALSE, 5);
+	entry = gtk_entry_new();
+	if (has_focus)
+			gtk_widget_grab_focus(entry);
+	if (tooltip)
+		gtk_widget_set_tooltip_text(entry, tooltip);
+	label = gtk_label_new(text);
+	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+	gtk_widget_set_size_request(label, 150, -1);
+	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
+	gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 5);
+	gtk_widget_show_all(hbox);
+	
+	return hbox;
+}
+
+#define PHOTO_WIDTH 140
+#define PHOTO_HEIGHT 140
+static void image_change(gpointer data) {
+	struct DData* d_data = (struct DData *) data;
+	GtkWidget *dialog;
+	gchar* file = NULL;
+	GtkFileFilter* filter;
+	gchar* home;
+	GdkPixbuf* pixbuf;
+	GError* err = NULL;
+	
+	filter = gtk_file_filter_new();
+	gtk_file_filter_set_name(filter, "Image");
+	gtk_file_filter_add_pixbuf_formats(filter);
+	
+	dialog = gtk_file_chooser_dialog_new("Select File",
+					      GTK_WINDOW(d_data->mainwindow->window),
+					      GTK_FILE_CHOOSER_ACTION_OPEN,
+					      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+					      GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+					      NULL);
+	gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
+	gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE);
+	home = get_self_home();
+	gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), home);
+	g_free(home);
+	
+	if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
+		file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
+
+		pixbuf = gdk_pixbuf_new_from_file_at_scale(
+			file, PHOTO_WIDTH, PHOTO_HEIGHT, TRUE, &err);
+		g_clear_error(&err);
+		
+		if (pixbuf) {
+			gtk_image_clear(GTK_IMAGE(d_data->items[VI_Photo]->widget));
+			gtk_image_set_from_pixbuf(
+				GTK_IMAGE(d_data->items[VI_Photo]->widget),	pixbuf);
+			g_object_unref(pixbuf);
+			d_data->has_pix = TRUE;
+		}
+		
+		g_free(file);
+	}
+
+	gtk_widget_destroy(dialog);
+}
+
+static void cert_change(gpointer data) {
+	struct DData* d_data = (struct DData *) data;
+	GtkWidget *dialog;
+	gchar* file = NULL;
+	const gchar* home;
+	GError* err = NULL;
+	gchar* content;
+	GtkTextBuffer* buf;
+	gsize size;
+		
+	dialog = gtk_file_chooser_dialog_new("Select File",
+					      GTK_WINDOW(d_data->mainwindow->window),
+					      GTK_FILE_CHOOSER_ACTION_OPEN,
+					      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+					      GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+					      NULL);
+	gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE);
+	home = get_home();
+	gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), home);
+	
+	if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
+		file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
+		
+		if (g_file_get_contents(file, &content, &size, &err)) {
+			debug_print("File size: %d\n", size);
+			buf = gtk_text_view_get_buffer(
+					GTK_TEXT_VIEW(d_data->items[VI_X509]->widget));
+			gchar* text = g_base64_encode((guchar *) content, size);
+			gtk_text_buffer_set_text(buf, text, -1);
+			g_free(text);
+			g_free(content);
+			d_data->has_cert = TRUE;
+		}
+		
+		g_clear_error(&err);
+		g_free(file);
+	}
+
+	gtk_widget_destroy(dialog);
+}
+
+static gboolean image_button_pressed_cb(GtkWidget* widget,
+										GdkEventButton* event,
+										gpointer data) {
+    debug_print("Button pressed: %d\n", event->button);
+    if (event->button == 1 && event->type == GDK_BUTTON_PRESS) {
+		image_change(data);
+		return TRUE;
+    }
+    return FALSE;
+}
+
+static gboolean cert_button_pressed_cb(GtkWidget* widget,
+									   GdkEventButton* event,
+									   gpointer data) {
+    debug_print("Button pressed: %d\n", event->button);
+    if (event->button == 1 && event->type == GDK_BUTTON_PRESS) {
+		cert_change(data);
+		return TRUE;
+    }
+    return FALSE;
+}
+
+static const gchar* hbox_get_entry_text(GtkWidget* hbox) {
+	GList *children, *cur;
+	
+	children = gtk_container_get_children(GTK_CONTAINER(GTK_BOX(hbox)));
+	for (cur = children; cur; cur = g_list_next(cur)) {
+		GtkWidget* widget = (GtkWidget *) cur->data;
+		if (strcmp(G_OBJECT_TYPE_NAME(widget), "GtkEntry") == 0)
+			return gtk_entry_get_text(GTK_ENTRY(widget));
+	}
+	return "";
+}
+
+static void hbox_set_entry_text(GtkWidget* hbox, const gchar* text) {
+	GList *children, *cur;
+	
+	children = gtk_container_get_children(GTK_CONTAINER(GTK_BOX(hbox)));
+	for (cur = children; cur; cur = g_list_next(cur)) {
+		GtkWidget* widget = (GtkWidget *) cur->data;
+		if (strcmp(G_OBJECT_TYPE_NAME(widget), "GtkEntry") == 0)
+			gtk_entry_set_text(GTK_ENTRY(widget), text);
+	}
+}
+
+static gint get_vi_item(struct DData* d_data, VObject* prop) {
+	gint vi_item = -1;
+	guint i;
+	const gchar *name, *propname;
+	VObjectIterator iter;
+	
+	if (! prop)
+		return vi_item;
+		
+	name = vObjectName(prop);
+	if (! name)
+		return vi_item;
+		
+	for (i = VI_GivenName; i < VI_Items - 1 && vi_item < 0; i++) {
+		if (strcasecmp(d_data->items[i]->prop, name) == 0)
+			vi_item = i;
+	}
+	if (vi_item < 0) {
+		if (strcasecmp("X509", name) == 0)
+			vi_item = VI_X509;
+		else if (strcasecmp("PHOTO", name) == 0)
+			vi_item = VI_Photo;
+		else {
+			initPropIterator(&iter, prop);
+			while (moreIteration(&iter)) {
+				VObject* o = nextVObject(&iter);
+				propname = vObjectName(o);
+				if (propname && strcasecmp("TEL", name) == 0) {
+					if (strcasecmp(propname, "WORK") == 0)
+						vi_item = VI_Telephone_Work;
+					else if (strcasecmp(propname, "HOME") == 0)
+						vi_item = VI_Telephone_Home;
+					else if (strcasecmp(propname, "CELL") == 0)
+						vi_item = VI_Telephone_Cellular;
+					else {
+						/* we should never end here */
+					}
+				}
+				else if (propname && strcasecmp("EMAIL", name) == 0) {
+					if (strcasecmp(propname, "WORK") == 0)
+						vi_item = VI_EmailAddress_Work;
+					else if (strcasecmp(propname, "HOME") == 0)
+						vi_item = VI_EmailAddress_Home;
+					else {
+						/* we should never end here */
+					}
+				}
+				else {
+					/* we should never end here */
+				}
+			}
+		}
+	}
+	
+	return vi_item;
+}
+ 
+static void set_vcard_property(struct DData* d_data, VObject* prop) {
+	gint vi_item;
+	gchar* text;
+	GdkPixbuf* pixbuf;
+	GtkTextBuffer* buf;
+	
+	if (! prop)
+		return;
+
+	vi_item = get_vi_item(d_data, prop);
+	if (vi_item < 0)
+		return;
+
+	text = (gchar *) vcard_value(prop);
+	switch (vi_item) {
+		case VI_Photo:
+			pixbuf = contact_load_image(d_data->mainwindow->window, text);
+			if (pixbuf) {
+				gtk_image_clear(GTK_IMAGE(d_data->items[vi_item]->widget));
+				gtk_image_set_from_pixbuf(
+					GTK_IMAGE(d_data->items[vi_item]->widget),	pixbuf);
+				g_object_unref(pixbuf);
+				d_data->has_pix = TRUE;
+			}
+			g_free(text);
+			return;
+		case VI_X509:
+			buf = gtk_text_view_get_buffer(
+					GTK_TEXT_VIEW(d_data->items[vi_item]->widget));
+			gtk_text_buffer_set_text(buf, text, -1);
+			g_free(text);
+			d_data->has_cert = TRUE;
+			return;
+		default:
+			hbox_set_entry_text(d_data->items[vi_item]->widget, text);
+			g_free(text);
+			return;
+	}				
+}
+
+static void insert_existing_vcard(struct DData* d_data) {
+	gchar* home = get_self_home();
+	gchar* file;
+	VObject* o;
+	VObjectIterator iter;
+	
+	file = g_strconcat(home, G_DIR_SEPARATOR_S, d_data->account, ".vcf", NULL);
+	if (g_file_test(file, G_FILE_TEST_EXISTS)) {
+		registerMimeErrorHandler(mime_error_handler, d_data->mainwindow);
+		o = Parse_MIME_FromFileName(file);
+		if (o) {
+			if (debug_get_mode())
+				printVObject(stderr, o);
+			initPropIterator(&iter,o);
+			while (moreIteration(&iter)) {
+				VObject* prop = nextVObject(&iter);
+				set_vcard_property(d_data, prop);
+			}
+			cleanVObject(o);
+		}
+	}
+	g_free(file);
+	g_free(home);
+}
+static void set_default_image(struct DData* d_data, gboolean update) {
+    gchar* photo = NULL;
+    GError* err = NULL;
+    GdkPixbuf* pixbuf;
+
+	photo = g_strdup_printf("%s/%s", PIXDIR, "anonymous.xpm");
+	pixbuf = gdk_pixbuf_new_from_file_at_scale(
+		photo, PHOTO_WIDTH, PHOTO_HEIGHT, TRUE, &err);
+	g_free(photo);
+	if (err) {
+		show_message(d_data->mainwindow->window,
+				GTK_UTIL_MESSAGE_ERROR, "%s", err->message);
+		g_clear_error(&err);
+	}
+	if (update) {
+		gtk_image_clear(GTK_IMAGE(d_data->items[VI_Photo]->widget));
+		gtk_image_set_from_pixbuf(
+			GTK_IMAGE(d_data->items[VI_Photo]->widget),	pixbuf);
+	}
+	else
+		d_data->items[VI_Photo]->widget = gtk_image_new_from_pixbuf(pixbuf);
+	g_object_unref(pixbuf);
+}
+
+static void save_vcard(struct DData* d_data) {
+	VObject* o;
+	guint i;
+	GdkPixbuf* pixbuf;
+	gchar* buffer;
+	guchar* base64;
+	GError *err = NULL;
+	gsize len;
+	GtkTextBuffer* buf;
+	GtkTextIter start, end;
+	gchar *home, *file;
+	FILE* fp;
+	
+	o = newVObject(VCCardProp);
+	addPropValue(o, VCVersionProp, "2.1");
+	for (i = VI_GivenName; i < VI_Items - 1; i++) {
+		switch (i) {
+			case VI_Photo:
+				if (d_data->has_pix) {
+					pixbuf = gtk_image_get_pixbuf(
+						GTK_IMAGE(d_data->items[i]->widget));
+					if (gdk_pixbuf_save_to_buffer(
+							pixbuf, &buffer, &len, "png", &err, NULL)) {
+						VObject* vo = newVObject(d_data->items[i]->prop);
+						setValueWithSize(vo, buffer, len);
+						addVObjectProp(o, vo);
+						g_free(buffer);
+					}
+				}
+				break;
+			case VI_X509:
+				if (d_data->has_cert) {
+					buf = gtk_text_view_get_buffer(
+							GTK_TEXT_VIEW(d_data->items[i]->widget));
+					gtk_text_buffer_get_bounds(buf, &start, &end); 
+					buffer = gtk_text_buffer_get_text(buf, &start, &end, TRUE);
+					base64 = g_base64_decode(buffer, &len);
+					g_free(buffer);
+					VObject* vo = newVObject(d_data->items[i]->prop);
+					setValueWithSize(vo, base64, len);
+					addVObjectProp(o, vo);
+					g_free(base64);
+				}
+				break;
+			default:
+				buffer = hbox_get_entry_text(d_data->items[i]->widget);
+				if (buffer && strlen(buffer) > 0)
+					addPropValue(o, d_data->items[i]->prop, buffer);
+				break;
+		}				
+	}
+	if (debug_get_mode())
+		printVObject(stderr, o);
+	home = get_self_home();
+	file = g_strconcat(home, G_DIR_SEPARATOR_S, d_data->account, ".vcf", NULL);
+	g_free(home);
+	fp = g_fopen(file, "w");
+	if (fp) {
+		writeVObject(fp, o);
+		fclose(fp);
+	}
+	else
+		show_message(d_data->mainwindow->window, GTK_UTIL_MESSAGE_ERROR,
+			"%s", strerror(errno));
+	g_free(file);
+	cleanVObject(o);
+}
+
+static void special_attributes_page(GtkWidget* vbox, struct DData* d_data) {
+	GtkWidget *frame, *window, *hbox, *vbox1, *btn;
+	
+	hbox = gtk_hbox_new(FALSE, 5);
+
+	frame = gtk_frame_new(N_("Image"));
+	vbox1 = gtk_vbox_new(FALSE, 5);
+	gtk_container_add(GTK_CONTAINER(frame), vbox1);
+
+	set_default_image(d_data, FALSE);
+	gtk_box_pack_start(GTK_BOX(vbox1), d_data->items[VI_Photo]->widget, TRUE, TRUE, 5);
+
+	btn = gtk_button_new_with_mnemonic(_("New _Image"));
+	g_signal_connect(btn, "button-press-event",
+		G_CALLBACK(image_button_pressed_cb), d_data);
+	gtk_box_pack_start(GTK_BOX(vbox1), btn, TRUE, TRUE, 5);
+
+	gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, FALSE, 5);
+	
+	frame = gtk_frame_new(N_("Certificate"));
+	vbox1 = gtk_vbox_new(FALSE, 5);
+	gtk_container_add(GTK_CONTAINER(frame), vbox1);
+
+	window = gtk_scrolled_window_new(NULL, NULL);
+	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(window),
+		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+	gtk_box_pack_start(GTK_BOX(vbox1), window, TRUE, TRUE, 5);
+
+	btn = gtk_button_new_with_mnemonic(_("New _Certificate"));
+	g_signal_connect(btn, "button-press-event",
+		G_CALLBACK(cert_button_pressed_cb), d_data);
+	gtk_box_pack_start(GTK_BOX(vbox1), btn, FALSE, FALSE, 5);
+
+	d_data->items[VI_X509]->widget = gtk_text_view_new();
+	gtk_text_view_set_editable(GTK_TEXT_VIEW(d_data->items[VI_X509]->widget), FALSE);
+	gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(d_data->items[VI_X509]->widget), FALSE);
+	gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(d_data->items[VI_X509]->widget), GTK_WRAP_WORD_CHAR);
+	gtk_container_add(GTK_CONTAINER(window), d_data->items[VI_X509]->widget);
+	gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 5);
+	
+	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
+	
+	d_data->items[VI_GeoLocation]->widget = label_and_input(
+			d_data->items[VI_GeoLocation]->label, d_data->items[VI_GeoLocation]->tooltip, FALSE);
+	gtk_box_pack_start(GTK_BOX(vbox), d_data->items[VI_GeoLocation]->widget, FALSE, FALSE, 5);
+	
+	d_data->items[VI_TimeZone]->widget = label_and_input(
+			d_data->items[VI_TimeZone]->label, d_data->items[VI_TimeZone]->tooltip, FALSE);
+	gtk_box_pack_start(GTK_BOX(vbox), d_data->items[VI_TimeZone]->widget, FALSE, FALSE, 5);
+}
+
+void personal_vcard_make(MainWindow* mainwindow, gchar** error) {
+	GtkWidget *dialog, *notebook, *label;
+	GtkWidget* frame[3];
+	GtkWidget* vbox[3];
+	const gchar* tab_text[3] = {
+		"Personal Attributes", "Common Attributes", "Special Attributes" };
+	VcardItem** vcard;
+	guint items, i;
+	gchar* account;
+	struct DData d_data;
+	
+	if (! show_input(mainwindow->window, N_("Choose Account"), &account,
+		N_("\nName of account to connect this vCard to.\n"
+		   "If vCard already exists open in edit mode.\n"
+		   "A vCard file has this naming convention: account\".vcf\"\n")))
+		return;
+
+	if (! account) {
+		show_message(mainwindow->window, GTK_UTIL_MESSAGE_WARNING,
+			N_("Cannot create a vcard when account name is missing"));
+		return;
+	}
+	
+	dialog = gtk_dialog_new_with_buttons (N_("Create Personal vCard"),
+										  GTK_WINDOW(mainwindow->window),
+										  GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+										  GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+										  GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+										  NULL);
+	gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_REJECT);
+	vcard = vcard_widget_new();
+	notebook = gtk_notebook_new();
+	gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
+
+	gchar* text = g_markup_printf_escaped
+		("<span foreground=\"navy\" weight=\"bold\" size=\"large\">"
+		 "  Account: %s  </span>", account);
+	for (i = 0; i < 3; i++) {
+		label = gtk_label_new(NULL);
+		gtk_label_set_markup(GTK_LABEL(label), text);
+		gtk_widget_set_tooltip_text(label, vcard[VI_Account]->tooltip);
+		vbox[i] = gtk_vbox_new(FALSE, 5);
+		frame[i] = gtk_frame_new(NULL);
+		gtk_frame_set_label_widget(GTK_FRAME(frame[i]), label);
+		gtk_frame_set_label_align(GTK_FRAME(frame[i]), 0.5, 0.5);
+		gtk_container_add(GTK_CONTAINER(frame[i]), vbox[i]);
+		gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame[i], NULL);
+		gtk_notebook_set_tab_label_text(GTK_NOTEBOOK(notebook), frame[i], tab_text[i]);
+	}
+	g_free(text);
+
+	for (items = 0; items < VI_Items; items++) {
+		if (items == VI_Account || items == VI_Photo || items == VI_X509 ||
+			items == VI_GeoLocation || items == VI_TimeZone)
+			continue;
+		else if (items >= VI_GivenName && items < VI_URL) {
+			gboolean focus = (items == VI_GivenName);
+			vcard[items]->widget = label_and_input(
+				vcard[items]->label, vcard[items]->tooltip, focus);
+			gtk_box_pack_start(GTK_BOX(vbox[0]), vcard[items]->widget, FALSE, FALSE, 5);
+		}
+		else {
+			vcard[items]->widget = label_and_input(
+					vcard[items]->label, vcard[items]->tooltip, FALSE);
+			gtk_box_pack_start(GTK_BOX(vbox[1]), vcard[items]->widget, FALSE, FALSE, 5);
+		}
+	}
+	d_data.mainwindow = mainwindow;
+	d_data.items = vcard;
+	d_data.account = account;
+	d_data.has_cert = FALSE;
+	d_data.has_pix = FALSE;
+	special_attributes_page(vbox[2], &d_data);
+	
+	insert_existing_vcard(&d_data);
+	
+	GtkWidget* content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+	gtk_container_add(GTK_CONTAINER(content), notebook);
+	
+	gtk_widget_show_all(dialog);
+	gint res = gtk_dialog_run(GTK_DIALOG(dialog));
+	if (res == GTK_RESPONSE_ACCEPT) {
+		save_vcard(&d_data);
+	}
+	gtk_widget_destroy(dialog);
+	g_free(vcard);
+	g_free(account);
 }
 
 Contact* vcard_ptr2contact(Plugin* plugin, const gchar* vcard, gint len, gchar** error) {

Index: vcard-utils.h
===================================================================
RCS file: /home/claws-mail/contacts/libversit/vcard-utils.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- vcard-utils.h	5 Jan 2012 01:45:06 -0000	1.1
+++ vcard-utils.h	25 Mar 2012 22:55:13 -0000	1.2
@@ -44,7 +44,8 @@
 Contact* vcard2contact(VObject* vcard, Plugin* plugin, gchar** error);
 GSList* contacts2vcard(GList* contacts, Plugin* plugin, gchar** error);
 VObject* contact2vcard(Contact* contact, Plugin* plugin, gchar** error);
-VObject* personal_vcard(gchar** error);
+gchar* personal_vcard_get(const gchar* account, gchar** error);
+void personal_vcard_make(MainWindow* mainwindow, gchar** error);
 Contact* vcard_ptr2contact(Plugin* plugin, const gchar* vcard, gint len, gchar** error);
  
 G_END_DECLS



More information about the Commits mailing list