[evolution-patches] Free/Busy Bounty rev 2



I have attached a new revision of the patch to the bug: 

http://bugzilla.gnome.org/show_bug.cgi?id=127539

My ISP's ftp server is down, so I didn't post any screenshots. Hopefully
this is the final revision. It will now check to see if it needs to
publish, and do so if it has been more than a day or week depending on
what the user has set. It will also publish after the the settings have
been changed. Additionaly you can arbitrarily publish with the Actions
menu or the pop-up menu.

Automatic publishing is set up in calendar-component.c: createControls.
It occured to me that it may be good to only check to publish on the
initial creation of the component and then remove the callback with
g_idle_remove rather than have it continue to try, the code to do this
is there, but commented out. This would especially be good if the server
to which the user is publishing is down. Thoughts?

I also HIG-ified the dialogs, as requested. Attached are the patch  for
evolution/calendar and the configure.in patch. The new source files are
in the tarball attached to the bug.

Cheers!

-Gary
Index: configure.in
===================================================================
RCS file: /cvs/gnome/evolution/configure.in,v
retrieving revision 1.645
diff -u -r1.645 configure.in
--- configure.in	8 Jan 2004 19:56:47 -0000	1.645
+++ configure.in	12 Jan 2004 04:07:05 -0000
@@ -1069,7 +1069,7 @@
 
 dnl --- evolution-calendar flags
 
-EVO_SET_COMPILE_FLAGS(EVOLUTION_CALENDAR, libgnome-2.0 libgnomeui-2.0 libbonoboui-2.0 >= $BONOBOUI_REQUIRED gal-2.2 >= $GAL_REQUIRED libglade-2.0 gnome-vfs-2.0 libgnomeprint-2.2 libgnomeprintui-2.2 libgtkhtml-3.1 >= $GTKHTML_REQUIRED libebook-1.0 >= $EDS_REQUIRED libecal-1.0 >= $EDS_REQUIRED)
+EVO_SET_COMPILE_FLAGS(EVOLUTION_CALENDAR, libgnome-2.0 libgnomeui-2.0 libbonoboui-2.0 gal-2.2 >= $GAL_REQUIRED libglade-2.0 gnome-vfs-2.0 libgnomeprint-2.2 libgnomeprintui-2.2 libgtkhtml-3.1 >= $GTKHTML_REQUIRED libsoup-2.2 >= 2.1.3 libebook-1.0 >= $EDS_REQUIRED libecal-1.0 >= $EDS_REQUIRED)
 AC_SUBST(EVOLUTION_CALENDAR_CFLAGS)
 AC_SUBST(EVOLUTION_CALENDAR_LIBS)
 
? free-busy.diff
? free-busy2.diff
? name
? common/Makefile
? common/Makefile.in
? gui/apps_evolution_calendar-1.5.schemas
? gui/e-pub-utils.c
? gui/e-pub-utils.h
? gui/fb-utils.c
? gui/fb-utils.h
? gui/dialogs/cal-prefs-dialog.gladep
? gui/dialogs/fb-editor.glade
? gui/dialogs/fb-editor.gladep
? gui/dialogs/url-editor-dialog.c
? gui/dialogs/url-editor-dialog.glade
? gui/dialogs/url-editor-dialog.gladep
? gui/dialogs/url-editor-dialog.h
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/calendar/ChangeLog,v
retrieving revision 1.2058
diff -u -r1.2058 ChangeLog
--- ChangeLog	9 Jan 2004 20:49:37 -0000	1.2058
+++ ChangeLog	12 Jan 2004 03:59:25 -0000
@@ -1,3 +1,66 @@
+2004-01-11 Gary Ekker <gekker novell com>
+
+	* gui/Makefile.am: add SOUP_CFLAGS, SOUP_LIBS, and fb-utils.[ch]
+	for Free/Busy publishing
+	
+	* gui/apps_evolution_calendar.schemas.in.in: add schema for
+	/apps/evo/calendar/free_busy key
+	
+	* gui/calendar-commands.c (publish_freebusy_cmd): change to
+	publish component rather than attach as email
+	
+	* gui/calendar-config-keys.h: add free_busy/urls key definition
+	
+	* gui/calendar-config.[ch] (calendar_config_get_free_busy): new
+  	method for retrieving FB gconf key
+	(calendar_config_set_free_busy): new method for saving FB
+	gconf key
+	
+	* gui/e-cal-view.c (on_publish): change to publish component
+	rather than attach as email
+	
+	* gui/itip-utils.[ch] (itip_publish_begin): new method to process 
+	e_cal_components and aggregate the data if we are publishing
+	for multiple calendars
+	(itip_publish_comp): new method to publish the ical data to an
+	http server via libsoup
+	(comp_fb_normalize): new static method to ensure rfc 2446 compliant 
+	data before publishing icalcomponent_get_uid
+	(fb_sort): new static method to sort FB properties in ascending order
+	
+	* gui/dialogs/Makefile.am: add url-editor-dialog.[ch] and 
+	url-editor-dialog.glade for configure FB publishing
+	
+	* gui/dialogs/cal-prefs-dialog.[ch] (cal_prefs_dialog_url_add_clicked):
+	(cal_prefs_dialog_url_edit_clicked):new method for events in FB tab 
+	of cal-prefs-dialog
+	(cal_prefs_dialog_url_remove_clicked): ditto
+	(cal_prefs_dialog_url_enable_clicked): ditto
+	(cal_prefs_dialog_url_url_list_change): ditto
+	(cal_prefs_dialog_url_url_list_enable_toggled): ditto
+	(cal_prefs_dialog_url_url_list_double_click): ditto
+	(show_fb_config): new method for updating dialog with FB specific
+	data in gconf
+	(update_fb_config): new method for updating gconf with FB specific
+	data from dialogs
+	(setup_changes): detect changes in url_list gtk_tree_view
+	(get_widgets): include new dialog widgets for FB config
+	(init_widgets): connect signals for new FB config widgets
+	
+	* gui/dialogs/cal-prefs-dialog.glade: add new widgets for FB config
+	
+	* gui/dialogs/url-editor-dialog.[ch]: add files for FB url-editor dialog
+	
+	* gui/dialogs/url-editor-dialog.glade: ditto
+	
+	* gui/e-pub-utils.[ch]: add files with FB publishing utilities
+
+	* gui/calendar-component.c (init_calendar_publishing): sets up
+	listeners to publish calendar, g_idle_add, and on gconf change
+	(init_calendar_publishing_cb): ditto
+	(conf_changed_callback): ditto
+	(impl_createControls): ditto
+	
 2004-01-09  Hans Petter Jansson  <hpj ximian com>
 
 	* gui/calendar-component.c (new_calendar_cb): calendar_config ->
Index: gui/Makefile.am
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/Makefile.am,v
retrieving revision 1.290
diff -u -r1.290 Makefile.am
--- gui/Makefile.am	22 Dec 2003 15:57:20 -0000	1.290
+++ gui/Makefile.am	12 Jan 2004 03:59:25 -0000
@@ -166,6 +166,8 @@
 	e-meeting-utils.h			\
 	e-mini-calendar-config.c		\
 	e-mini-calendar-config.h		\
+	e-pub-utils.c				\
+	e-pub-utils.h				\
 	e-select-names-editable.c		\
 	e-select-names-editable.h		\
 	e-select-names-renderer.c		\
Index: gui/apps_evolution_calendar.schemas.in.in
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/apps_evolution_calendar.schemas.in.in,v
retrieving revision 1.1
diff -u -r1.1 apps_evolution_calendar.schemas.in.in
--- gui/apps_evolution_calendar.schemas.in.in	2 Dec 2003 15:55:45 -0000	1.1
+++ gui/apps_evolution_calendar.schemas.in.in	12 Jan 2004 03:59:26 -0000
@@ -355,5 +355,17 @@
         <short>Programs that can run as part of alarms</short>
       </locale>
     </schema>
+    
+    <schema>
+      <key>/schemas/apps/evolution/calendar/publish/uris</key>
+      <applyto>/apps/evolution/calendar/publish/uris</applyto>
+      <owner>evolution-calendar</owner>
+      <type>list</type>
+      <list_type>string</list_type>
+      <default>[]</default>
+      <locale name="C">
+        <short>List of urls for free/busy publishing</short>
+      </locale>
+    </schema>    
   </schemalist>
 </gconfschemafile>
Index: gui/calendar-commands.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/calendar-commands.c,v
retrieving revision 1.141
diff -u -r1.141 calendar-commands.c
--- gui/calendar-commands.c	9 Jan 2004 19:50:08 -0000	1.141
+++ gui/calendar-commands.c	12 Jan 2004 03:59:26 -0000
@@ -60,6 +60,7 @@
 #include "print.h"
 #include "dialogs/cal-prefs-dialog.h"
 #include "itip-utils.h"
+#include "e-pub-utils.h"
 #include "evolution-shell-component-utils.h"
 
 /* Focusing information for the calendar view.  We have to keep track of this
@@ -319,36 +320,7 @@
 static void
 publish_freebusy_cmd (BonoboUIComponent *uic, gpointer data, const gchar *path)
 {
-	GnomeCalendar *gcal;
-	GList *client_list, *cl;
-	GList *comp_list = NULL;
-	icaltimezone *utc;
-	time_t start = time (NULL), end;
-
-	gcal = GNOME_CALENDAR (data);
-
-	utc = icaltimezone_get_utc_timezone ();
-	start = time_day_begin_with_zone (start, utc);
-	end = time_add_week_with_zone (start, 6, utc);
-
-	/* FIXME Should we aggregate the data? */
-	client_list = e_cal_model_get_client_list (gnome_calendar_get_calendar_model (gcal));
-	for (cl = client_list; cl != NULL; cl = cl->next) {
-		if (e_cal_get_free_busy ((ECal *) cl->data, NULL, start, end, &comp_list, NULL)) {
-			GList *l;
-
-			for (l = comp_list; l; l = l->next) {
-				ECalComponent *comp = E_CAL_COMPONENT (l->data);
-				itip_send_comp (E_CAL_COMPONENT_METHOD_PUBLISH, comp, (ECal *) cl->data, NULL);
-
-				g_object_unref (comp);
-			}
-
-			g_list_free (comp_list);
-		}
-	}
-
-	g_list_free (client_list);
+	e_pub_publish (TRUE);
 }
 
 static void
Index: gui/calendar-component.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/calendar-component.c,v
retrieving revision 1.130
diff -u -r1.130 calendar-component.c
--- gui/calendar-component.c	9 Jan 2004 20:49:38 -0000	1.130
+++ gui/calendar-component.c	12 Jan 2004 03:59:26 -0000
@@ -30,6 +30,8 @@
 #include <bonobo/bonobo-control.h>
 #include <bonobo/bonobo-i18n.h>
 #include <bonobo/bonobo-exception.h>
+#include "e-pub-utils.h"
+#include "calendar-config-keys.h"
 #include "calendar-config.h"
 #include "calendar-component.h"
 #include "calendar-commands.h"
@@ -59,6 +61,7 @@
 	char *config_directory;
 
 	GConfClient *gconf_client;
+	int gconf_notify_id;
 	ESourceList *source_list;
 	GSList *source_selection;
 	
@@ -436,6 +439,34 @@
 	update_primary_selection (data);
 }
 
+static gboolean
+init_calendar_publishing_cb (gpointer data)
+{
+#if 0
+	guint *idle_id = (guint *) data;
+
+	/* remove the idle function--We could do this so that it runs once 
+	on each startup */
+	g_source_remove (*idle_id);
+	g_free (idle_id);
+#endif
+	
+	/* Publish if it is time to publish again */
+	e_pub_publish (FALSE);
+
+	return FALSE;
+}
+
+static void
+conf_changed_callback (GConfClient *client,
+		       unsigned int connection_id,
+		       GConfEntry *entry,
+		       void *user_data)
+{
+	/* publish config changed, so publish */
+	e_pub_publish (TRUE);
+}
+
 /* GObject methods.  */
 
 static void
@@ -589,6 +620,25 @@
 }
 
 static void
+init_calendar_publishing (CalendarComponent *calendar_component)
+{
+	guint *idle_id;
+	CalendarComponentPrivate *priv;
+	
+	priv = calendar_component->priv;
+	
+	gconf_client_add_dir (priv->gconf_client, CALENDAR_CONFIG_PUBLISH, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+
+	priv->gconf_notify_id
+		= gconf_client_notify_add (priv->gconf_client, CALENDAR_CONFIG_PUBLISH,
+					   (GConfClientNotifyFunc) conf_changed_callback, NULL,
+					   NULL, NULL);
+	
+	idle_id = g_new0 (guint, 1);
+	*idle_id = g_idle_add ((GSourceFunc) init_calendar_publishing_cb, idle_id);
+}
+
+static void
 impl_createControls (PortableServer_Servant servant,
 		     Bonobo_Control *corba_sidebar_control,
 		     Bonobo_Control *corba_view_control,
@@ -636,6 +686,9 @@
 	e_activity_handler_attach_task_bar (priv->activity_handler, E_TASK_BAR (statusbar_widget));
 	statusbar_control = bonobo_control_new (statusbar_widget);
 
+	/* Initialize Calendar Publishing */
+	init_calendar_publishing(calendar_component);
+	
 	/* connect after setting the initial selections, or we'll get unwanted calls
 	   to calendar_control_sensitize_calendar_commands */
 	g_signal_connect_object (priv->source_selector, "selection_changed",
Index: gui/calendar-config-keys.h
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/calendar-config-keys.h,v
retrieving revision 1.4
diff -u -r1.4 calendar-config-keys.h
--- gui/calendar-config-keys.h	3 Dec 2003 16:37:22 -0000	1.4
+++ gui/calendar-config-keys.h	12 Jan 2004 03:59:26 -0000
@@ -70,6 +70,9 @@
 #define CALENDAR_CONFIG_DEFAULT_REMINDER_INTERVAL CALENDAR_CONFIG_PREFIX "/other/default_reminder_interval"
 #define CALENDAR_CONFIG_DEFAULT_REMINDER_UNITS CALENDAR_CONFIG_PREFIX "/other/default_reminder_units"
 
+/* Free/Busy settings */
+#define CALENDAR_CONFIG_PUBLISH CALENDAR_CONFIG_PREFIX"/publish/uris"
+
 G_END_DECLS
 
 #endif
Index: gui/calendar-config.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/calendar-config.c,v
retrieving revision 1.65
diff -u -r1.65 calendar-config.c
--- gui/calendar-config.c	14 Dec 2003 23:57:08 -0000	1.65
+++ gui/calendar-config.c	12 Jan 2004 03:59:27 -0000
@@ -1025,3 +1025,16 @@
 	return sexp;
 }
 
+GSList *
+calendar_config_get_free_busy(void)
+{	
+	return gconf_client_get_list (config, CALENDAR_CONFIG_PUBLISH, 
+				      GCONF_VALUE_STRING, NULL);
+}
+
+void
+calendar_config_set_free_busy (GSList *url_list)
+{
+	gconf_client_set_list (config, CALENDAR_CONFIG_PUBLISH, 
+			       GCONF_VALUE_STRING, url_list, NULL);
+}
Index: gui/calendar-config.h
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/calendar-config.h,v
retrieving revision 1.30
diff -u -r1.30 calendar-config.h
--- gui/calendar-config.h	19 Nov 2003 03:55:31 -0000	1.30
+++ gui/calendar-config.h	12 Jan 2004 03:59:27 -0000
@@ -202,6 +202,9 @@
 CalUnits calendar_config_get_default_reminder_units (void);
 void     calendar_config_set_default_reminder_units (CalUnits units);
 
+/* Free/Busy Settings */
+GSList * calendar_config_get_free_busy(void);
+void calendar_config_set_free_busy(GSList * url_list);
 
 /* Convenience functions to configure common properties of ECalendar,
    EDateEdit & ECalendarTable widgets, and the ECellDateEdit ETable cell. */
Index: gui/e-cal-view.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-cal-view.c,v
retrieving revision 1.29
diff -u -r1.29 e-cal-view.c
--- gui/e-cal-view.c	9 Jan 2004 07:48:29 -0000	1.29
+++ gui/e-cal-view.c	12 Jan 2004 03:59:27 -0000
@@ -41,6 +41,7 @@
 #include "e-cal-view.h"
 #include "e-comp-editor-registry.h"
 #include "itip-utils.h"
+#include "e-pub-utils.h"
 #include "dialogs/delete-comp.h"
 #include "dialogs/delete-error.h"
 #include "dialogs/event-editor.h"
@@ -1127,34 +1128,7 @@
 static void
 on_publish (GtkWidget *widget, gpointer user_data)
 {
-	ECalendarView *cal_view;
-	icaltimezone *utc;
-	time_t start = time (NULL), end;
-	GList *comp_list = NULL, *client_list, *cl;
-
-	cal_view = E_CALENDAR_VIEW (user_data);
-
-	utc = icaltimezone_get_utc_timezone ();
-	start = time_day_begin_with_zone (start, utc);
-	end = time_add_week_with_zone (start, 6, utc);
-
-	client_list = e_cal_model_get_client_list (cal_view->priv->model);
-	for (cl = client_list; cl != NULL; cl = cl->next) {
-		if (e_cal_get_free_busy ((ECal *) cl->data, NULL, start, end, &comp_list, NULL)) {
-			GList *l;
-
-			for (l = comp_list; l; l = l->next) {
-				ECalComponent *comp = E_CAL_COMPONENT (l->data);
-				itip_send_comp (E_CAL_COMPONENT_METHOD_PUBLISH, comp, (ECal *) cl->data, NULL);
-
-				g_object_unref (comp);
-			}
-
-			g_list_free (comp_list);
-		}
-	}
-
-	g_list_free (client_list);
+	e_pub_publish (TRUE);
 }
 
 static void
Index: gui/itip-utils.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/itip-utils.c,v
retrieving revision 1.84
diff -u -r1.84 itip-utils.c
--- gui/itip-utils.c	1 Dec 2003 22:14:20 -0000	1.84
+++ gui/itip-utils.c	12 Jan 2004 03:59:28 -0000
@@ -37,6 +37,10 @@
 #include <e-util/e-time-utils.h>
 #include <libecal/e-cal-time-util.h>
 #include <libecal/e-cal-util.h>
+#include <libsoup/soup-session-async.h>
+#include <libsoup/soup-message.h>
+#include <libsoup/soup-uri.h>
+#include "e-util/e-passwords.h"
 #include "calendar-config.h"
 #include "itip-utils.h"
 
@@ -977,3 +981,217 @@
 	return retval;
 }
 
+gboolean
+itip_publish_begin (ECalComponent *pub_comp, ECal *client, 
+		    gboolean cloned, ECalComponent **clone)
+{
+	icalcomponent *icomp =NULL, *icomp_clone = NULL;
+	icalproperty *prop;
+		
+	if (e_cal_component_get_vtype (pub_comp) == E_CAL_COMPONENT_FREEBUSY) {
+				
+		if (!cloned) {
+			*clone = e_cal_component_clone(pub_comp);
+			cloned = TRUE;
+		} else {
+			
+			icomp = e_cal_component_get_icalcomponent (pub_comp);
+			icomp_clone = e_cal_component_get_icalcomponent (*clone);
+			for (prop = icalcomponent_get_first_property (icomp,
+						      ICAL_FREEBUSY_PROPERTY);
+	     			prop != NULL;
+	     			prop = icalcomponent_get_next_property (icomp, 
+						       ICAL_FREEBUSY_PROPERTY))
+			{
+				icalproperty *p;
+		
+				p = icalproperty_new_clone (prop);
+				icalcomponent_add_property (icomp_clone, p);
+			}
+		}		
+	}
+
+	return TRUE;
+}
+
+static void
+fb_sort (struct icalperiodtype *ipt, int fb_count)
+{
+	int i,j;
+	
+	if (ipt == NULL || fb_count == 0)
+		return;
+	
+	for (i = 0; i < fb_count-1; i++) {
+		for (j = i+1; j < fb_count; j++) {
+			struct icalperiodtype temp;
+				
+			if (icaltime_compare(ipt[i].start, ipt[j].start) < 0)
+				continue;
+			
+			if (icaltime_compare(ipt[i].start, ipt[j].start) == 0){
+				if (icaltime_compare(ipt[i].end, 
+						     ipt[j].start) < 0)
+					continue;
+			}
+			temp = ipt[i];
+			ipt[i] = ipt[j];
+			ipt[j] = temp;
+		}
+	}
+}
+
+static icalcomponent *
+comp_fb_normalize (icalcomponent *icomp)
+{
+	icalcomponent *iclone;
+	icalproperty *prop, *p;
+	const char *uid,  *comment;
+	struct icaltimetype itt;
+	int fb_count, i = 0, j;
+	struct icalperiodtype *ipt;
+	
+	iclone = icalcomponent_new (ICAL_VFREEBUSY_COMPONENT);
+	
+	prop = icalcomponent_get_first_property (icomp, 
+						 ICAL_ORGANIZER_PROPERTY);
+	p = icalproperty_new_clone (prop);
+	icalcomponent_add_property (iclone, p);
+	
+	itt = icalcomponent_get_dtstart (icomp);
+	icalcomponent_set_dtstart(iclone, itt);
+	
+	itt = icalcomponent_get_dtend (icomp);
+	icalcomponent_set_dtend (iclone, itt);
+	
+	fb_count =  icalcomponent_count_properties (icomp, 
+						    ICAL_FREEBUSY_PROPERTY);
+	ipt = g_new0(struct icalperiodtype, fb_count+1);
+	
+	for (prop = icalcomponent_get_first_property (icomp, 
+						      ICAL_FREEBUSY_PROPERTY);
+		prop != NULL;
+		prop = icalcomponent_get_next_property (icomp, 
+							ICAL_FREEBUSY_PROPERTY))
+	{
+		ipt[i] = icalproperty_get_freebusy(prop);
+		i++;
+	}
+	
+	fb_sort (ipt, fb_count);
+	
+	for (j = 0; j <= fb_count-1; j++) {
+		icalparameter *param;
+		
+		prop = icalproperty_new_freebusy (ipt[j]);
+		param = icalparameter_new_fbtype (ICAL_FBTYPE_BUSY);
+		icalproperty_add_parameter (prop, param);
+		icalcomponent_add_property (iclone, prop);
+	}
+	g_free (ipt);
+	
+	/* Should I strip this RFC 2446 says there must not be a UID
+		if the METHOD is PUBLISH?? */
+	uid = icalcomponent_get_uid(icomp);
+	if (uid)
+		icalcomponent_set_uid (iclone, uid);
+
+	itt = icaltime_from_timet_with_zone (time (NULL), FALSE,
+					     icaltimezone_get_utc_timezone ());
+	icalcomponent_set_dtstamp (iclone, itt);	
+	
+	prop = icalcomponent_get_first_property (icomp, ICAL_URL_PROPERTY);
+	p = icalproperty_new_clone (prop);
+	icalcomponent_add_property (iclone, p);
+	
+	comment =  icalcomponent_get_comment(icomp);
+	if (comment)
+		icalcomponent_set_comment(iclone, comment);
+
+	for (prop = icalcomponent_get_first_property (icomp, ICAL_X_PROPERTY);
+	     prop != NULL;
+	     prop = icalcomponent_get_next_property (icomp, ICAL_X_PROPERTY))
+	{		
+		p = icalproperty_new_clone (prop);
+		icalcomponent_add_property (iclone, p);
+	}
+	
+	return iclone;
+
+	g_object_unref (iclone);
+	return NULL;
+}
+
+gboolean
+itip_publish_comp (ECal *client, gchar *uri, gchar *username, 
+		   gchar *password, ECalComponent **pub_comp)
+{
+	icalcomponent *toplevel = NULL, *icalcomp = NULL;
+	icalcomponent *icomp = NULL;
+	SoupSession *session;
+	SoupMessage *msg;
+	SoupUri *real_uri;
+	char *ical_string;
+	char *prompt;
+	gboolean remember = FALSE;
+	
+	toplevel = e_cal_util_new_top_level ();
+	icalcomponent_set_method(toplevel, ICAL_METHOD_PUBLISH);
+	
+	e_cal_component_set_url (*pub_comp, uri);
+	
+	icalcomp = e_cal_component_get_icalcomponent (*pub_comp);
+	
+	icomp = comp_fb_normalize (icalcomp);	
+
+	icalcomponent_add_component (toplevel, icomp);
+	ical_string = icalcomponent_as_ical_string (toplevel);
+
+	/* Publish the component */
+	session = soup_session_async_new ();
+
+	/* add username and password to the uri */	
+	if (strlen(password) == 0) {
+		prompt = g_strdup_printf (_("Enter the password for %s"), uri);
+		password = e_passwords_ask_password (_("Enter password"), 
+						     "Calendar", NULL, 
+						     prompt, TRUE, 
+						   E_PASSWORDS_DO_NOT_REMEMBER,
+						     &remember, NULL);
+
+		g_free (prompt);
+	}
+
+	real_uri = soup_uri_new(uri);
+	if (!real_uri) {
+		g_warning (G_STRLOC ": Invalid URL: %s", uri);
+		return FALSE;
+	}
+	
+	real_uri->user = g_strdup(username);
+	real_uri->passwd = g_strdup(password);
+		
+	
+	/* build the SOAP message */
+	msg = soup_message_new_from_uri (SOUP_METHOD_PUT, real_uri);
+	if (!msg) {
+		g_warning (G_STRLOC ": Could not build SOAP message");
+		return FALSE;
+	}
+	soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT);	
+	soup_message_set_request (msg, "text/calendar", SOUP_BUFFER_USER_OWNED,
+				  ical_string, strlen (ical_string));
+	
+	/* send message to server */
+	soup_session_send_message (session, msg);
+	if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
+		g_warning(G_STRLOC ": Could not publish Free/Busy: %d: %s", 
+			  msg->status_code, 
+			  soup_status_get_phrase(msg->status_code));
+		return FALSE;
+	}
+	
+	soup_uri_free(real_uri);
+	
+	return TRUE;
+}
Index: gui/itip-utils.h
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/itip-utils.h,v
retrieving revision 1.15
diff -u -r1.15 itip-utils.h
--- gui/itip-utils.h	7 Nov 2003 05:52:00 -0000	1.15
+++ gui/itip-utils.h	12 Jan 2004 03:59:28 -0000
@@ -31,5 +31,10 @@
 gboolean itip_send_comp (ECalComponentItipMethod method, ECalComponent *comp,
 			 ECal *client, icalcomponent *zones);
 
+gboolean itip_publish_comp (ECal *client, gchar* uri, gchar* username, 
+			    gchar* password, ECalComponent **pub_comp);
+
+gboolean itip_publish_begin (ECalComponent *pub_comp, ECal *client, 
+			     gboolean cloned, ECalComponent **clone);
 
 #endif
Index: gui/dialogs/Makefile.am
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/dialogs/Makefile.am,v
retrieving revision 1.58
diff -u -r1.58 Makefile.am
--- gui/dialogs/Makefile.am	9 Jan 2004 20:49:39 -0000	1.58
+++ gui/dialogs/Makefile.am	12 Jan 2004 03:59:28 -0000
@@ -78,7 +78,9 @@
 	task-details-page.c	\
 	task-details-page.h	\
 	task-page.c		\
-	task-page.h
+	task-page.h		\
+	url-editor-dialog.c	\
+	url-editor-dialog.h	
 
 glade_DATA =				\
 	alarm-options.glade		\
@@ -91,8 +93,8 @@
 	recurrence-page.glade		\
 	schedule-page.glade		\
 	task-details-page.glade		\
-	task-page.glade
-
+	task-page.glade			\
+	url-editor-dialog.glade
 
 CLEANFILES = $(BUILT_SOURCES)
 
Index: gui/dialogs/cal-prefs-dialog.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/dialogs/cal-prefs-dialog.c,v
retrieving revision 1.31
diff -u -r1.31 cal-prefs-dialog.c
--- gui/dialogs/cal-prefs-dialog.c	18 Nov 2003 04:24:25 -0000	1.31
+++ gui/dialogs/cal-prefs-dialog.c	12 Jan 2004 03:59:29 -0000
@@ -34,10 +34,16 @@
 #include "../e-timezone-entry.h"
 #include "cal-prefs-dialog.h"
 #include "../calendar-config.h"
+#include "url-editor-dialog.h"
 
+#include <gtk/gtk.h>
+#include <gtk/gtkmain.h>
 #include <gtk/gtksignal.h>
 #include <gtk/gtkoptionmenu.h>
 #include <gtk/gtktogglebutton.h>
+#include <libxml/tree.h>
+#include <string.h>
+#include <libgnome/gnome-i18n.h>
 #include <libgnomeui/gnome-color-picker.h>
 #include <glade/glade.h>
 #include <gal/util/e-util.h>
@@ -45,40 +51,6 @@
 #include <widgets/misc/e-dateedit.h>
 
 
-struct _DialogData {
-	/* Glade XML data */
-	GladeXML *xml;
-
-	GtkWidget *page;
-
-	GtkWidget *timezone;
-	GtkWidget *working_days[7];
-	GtkWidget *week_start_day;
-	GtkWidget *start_of_day;
-	GtkWidget *end_of_day;
-	GtkWidget *use_12_hour;
-	GtkWidget *use_24_hour;
-	GtkWidget *time_divisions;
-	GtkWidget *show_end_times;
-	GtkWidget *compress_weekend;
-	GtkWidget *dnav_show_week_no;
-
-	/* Widgets for the task list options */
-	GtkWidget *tasks_due_today_color;
-	GtkWidget *tasks_overdue_color;
-
-	GtkWidget *tasks_hide_completed_checkbutton;
-	GtkWidget *tasks_hide_completed_spinbutton;
-	GtkWidget *tasks_hide_completed_optionmenu;
-
-	/* Other page options */
-	GtkWidget *confirm_delete;
-	GtkWidget *default_reminder;
-	GtkWidget *default_reminder_interval;
-	GtkWidget *default_reminder_units;
-};
-typedef struct _DialogData DialogData;
-
 static const int week_start_day_map[] = {
 	1, 2, 3, 4, 5, 6, 0, -1
 };
@@ -96,7 +68,6 @@
 	CAL_MINUTES, CAL_HOURS, CAL_DAYS, -1
 };
 
-
 static gboolean get_widgets (DialogData *data);
 
 static void widget_changed_callback (GtkWidget *, void *data);
@@ -115,8 +86,23 @@
 static void cal_prefs_dialog_start_of_day_changed (GtkWidget *button, void *data);
 static void cal_prefs_dialog_hide_completed_tasks_toggled (GtkWidget *button, void *data);
 
+static void cal_prefs_dialog_url_add_clicked(GtkWidget *button, void *data);
+static void cal_prefs_dialog_url_edit_clicked(GtkWidget *button, void *data);
+static void cal_prefs_dialog_url_remove_clicked(GtkWidget *button, void *data);
+static void cal_prefs_dialog_url_enable_clicked(GtkWidget *button, void *data);
+static void cal_prefs_dialog_url_list_change (GtkTreeSelection *selection, 
+					      DialogData *dialog_data);
+static void cal_prefs_dialog_url_list_enable_toggled (GtkCellRendererToggle *renderer, const char *path_string, void *data);
+static void cal_prefs_dialog_url_list_double_click(GtkTreeView *treeview, 
+						   GtkTreePath *path, 
+						   GtkTreeViewColumn *column, 
+						   DialogData *dialog_data);
+static void show_fb_config (DialogData *dialog_data);
+static void update_fb_config (DialogData *dialog_data);
+
 GtkWidget *cal_prefs_dialog_create_time_edit (void);
 
+#define PREFS_WINDOW(dialog_data) GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (dialog_data), GTK_TYPE_WINDOW))
 
 /**
  * cal_prefs_dialog_new:
@@ -233,6 +219,8 @@
 	connect_changed (dialog_data->default_reminder_interval, "changed", config_control);
 	connect_changed (GTK_OPTION_MENU (dialog_data->default_reminder_units)->menu, "selection_done", config_control);
 
+	connect_changed ((GtkWidget *) gtk_tree_view_get_selection (dialog_data->url_list), "changed", config_control);
+	
 	/* These use GnomeColorPicker so we have to use a different signal.  */
 	g_signal_connect((dialog_data->tasks_due_today_color), "color_set",
 			    G_CALLBACK (color_set_callback), config_control);
@@ -282,6 +270,12 @@
 	data->default_reminder = GW ("default-reminder");
 	data->default_reminder_interval = GW ("default-reminder-interval");
 	data->default_reminder_units = GW ("default-reminder-units");
+	
+	data->url_add = GW ("url_add");
+	data->url_edit = GW ("url_edit");
+	data->url_remove = GW ("url_remove");
+	data->url_enable = GW ("url_enable");
+	data->url_list = GTK_TREE_VIEW (GW ("url_list"));
 
 #undef GW
 
@@ -311,7 +305,12 @@
 		&& data->confirm_delete
 		&& data->default_reminder
 		&& data->default_reminder_interval
-		&& data->default_reminder_units);
+		&& data->default_reminder_units
+		&& data->url_add
+		&& data->url_edit
+		&& data->url_remove
+		&& data->url_enable
+		&& data->url_list);
 }
 
 
@@ -361,6 +360,13 @@
 static void
 init_widgets (DialogData *dialog_data)
 {
+	GtkCellRenderer *renderer = NULL;
+	GtkTreeSelection *selection;
+	GtkListStore *model;
+	
+	dialog_data->url_editor = FALSE;
+	dialog_data->url_editor_dlg =NULL;
+	
 	g_signal_connect((dialog_data->use_24_hour), "toggled",
 			    G_CALLBACK (cal_prefs_dialog_use_24_hour_toggled),
 			    dialog_data);
@@ -377,8 +383,65 @@
 			    "toggled",
 			    G_CALLBACK (cal_prefs_dialog_hide_completed_tasks_toggled),
 			    dialog_data);
-}
+	
+	/* Free/Busy ... */
+	g_signal_connect((dialog_data->url_add), "clicked",
+			    G_CALLBACK (cal_prefs_dialog_url_add_clicked),
+			    dialog_data);
+
+	g_signal_connect((dialog_data->url_edit), "clicked",
+			    G_CALLBACK (cal_prefs_dialog_url_edit_clicked),
+			    dialog_data);
 
+	g_signal_connect((dialog_data->url_remove), "clicked",
+			    G_CALLBACK (cal_prefs_dialog_url_remove_clicked),
+			    dialog_data);
+
+	g_signal_connect((dialog_data->url_enable), "clicked",
+			    G_CALLBACK (cal_prefs_dialog_url_enable_clicked),
+			    dialog_data);
+
+	/* Free/Busy Listview */
+	renderer = gtk_cell_renderer_toggle_new();
+	g_object_set ((GObject *) renderer, "activatable", TRUE, NULL);
+	
+	model = gtk_list_store_new (URL_LIST_N_COLUMNS, G_TYPE_BOOLEAN,
+				    G_TYPE_STRING, G_TYPE_POINTER);
+	
+	gtk_tree_view_set_model (dialog_data->url_list, 
+				 (GtkTreeModel *) model);
+
+	gtk_tree_view_insert_column_with_attributes (dialog_data->url_list, -1,
+						    _("Enabled"), renderer,
+						    "active", 
+						     URL_LIST_ENABLED_COLUMN, 
+						    NULL);
+
+	g_signal_connect(renderer, "toggled", 
+			 G_CALLBACK (cal_prefs_dialog_url_list_enable_toggled),
+			 dialog_data);
+	
+	renderer = gtk_cell_renderer_text_new();
+	gtk_tree_view_insert_column_with_attributes(dialog_data->url_list, -1, 
+						    _("Location"), renderer,
+						    "text", 
+						    URL_LIST_LOCATION_COLUMN, 
+						    NULL);
+	
+	selection = gtk_tree_view_get_selection ((GtkTreeView *) dialog_data->url_list);
+	gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+	gtk_tree_view_set_headers_visible ((GtkTreeView *) dialog_data->url_list, TRUE);
+	
+	
+	g_signal_connect (gtk_tree_view_get_selection (dialog_data->url_list),
+			  "changed", 
+			  G_CALLBACK (cal_prefs_dialog_url_list_change), 
+			  dialog_data);
+	
+	g_signal_connect(dialog_data->url_list, "row-activated",
+			 G_CALLBACK (cal_prefs_dialog_url_list_double_click),
+			 dialog_data);
+}
 
 static void
 cal_prefs_dialog_use_24_hour_toggled (GtkWidget	*button,
@@ -479,6 +542,300 @@
 				    65535);
 }
 
+static void
+cal_prefs_dialog_url_add_clicked  (GtkWidget *button, void *data)
+{
+	DialogData *dialog_data = (DialogData *) data;
+	EPublishUri *url = NULL;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	GtkTreeSelection *selection;
+	
+	model = gtk_tree_view_get_model (dialog_data->url_list);
+	url = g_new0 (EPublishUri, 1);
+	url->enabled = TRUE;
+	url->location = "";
+	
+	if (!dialog_data->url_editor) {
+			
+		dialog_data->url_editor = url_editor_dialog_new (dialog_data, 
+								 url);
+	
+		if (url->location != "") {
+			gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+			gtk_list_store_set(GTK_LIST_STORE(model), &iter, 
+					   URL_LIST_ENABLED_COLUMN, 
+					   url->enabled,
+					   URL_LIST_LOCATION_COLUMN, 
+					   g_strdup (url->location),
+					   URL_LIST_FREE_BUSY_URL_COLUMN, url,
+					   -1);
+		
+			if (!GTK_WIDGET_SENSITIVE((GtkWidget *) dialog_data->url_remove)) {
+				selection = gtk_tree_view_get_selection ((GtkTreeView *) dialog_data->url_list);
+				gtk_tree_model_get_iter_first ((GtkTreeModel *) model, &iter);
+				gtk_widget_set_sensitive ((GtkWidget*) dialog_data->url_remove, TRUE);
+				gtk_tree_selection_select_iter (selection, &iter);
+			}	
+		}
+		dialog_data->url_editor = FALSE;
+		dialog_data->url_editor_dlg = NULL;
+	} else {
+		gdk_window_raise (dialog_data->url_editor_dlg->window);
+	}	
+}
+
+static void
+cal_prefs_dialog_url_edit_clicked  (GtkWidget *button, void *data)
+{
+	DialogData *dialog_data = (DialogData *) data;
+	
+	if (!dialog_data->url_editor) {
+		GtkTreeSelection *selection;
+		EPublishUri *url = NULL;
+		GtkTreeModel *model;
+		GtkTreeIter iter;
+		
+		selection = gtk_tree_view_get_selection ((GtkTreeView *) dialog_data->url_list);
+		if (gtk_tree_selection_get_selected (selection, &model, &iter)){
+			gtk_tree_model_get (model, &iter, 
+					    URL_LIST_FREE_BUSY_URL_COLUMN, 
+					    &url, 
+					    -1);
+
+		}
+
+		if (url) {
+			
+			dialog_data->url_editor = url_editor_dialog_new (dialog_data, url);
+	
+			gtk_list_store_set((GtkListStore *) model, &iter, 
+					   URL_LIST_LOCATION_COLUMN, 
+					   g_strdup (url->location), 
+					   URL_LIST_ENABLED_COLUMN, 
+					   url->enabled, 
+					   URL_LIST_FREE_BUSY_URL_COLUMN, url,
+					   -1);
+
+			if (!GTK_WIDGET_SENSITIVE((GtkWidget *) dialog_data->url_remove)) {
+				selection = gtk_tree_view_get_selection ((GtkTreeView *) dialog_data->url_list);
+				gtk_tree_model_get_iter_first ((GtkTreeModel *) model, &iter);
+				gtk_widget_set_sensitive ((GtkWidget*) dialog_data->url_remove, TRUE);
+				gtk_tree_selection_select_iter (selection, &iter);
+			}
+			dialog_data->url_editor = FALSE;
+			dialog_data->url_editor_dlg = NULL;
+		}
+	} else {
+		gdk_window_raise (dialog_data->url_editor_dlg->window);
+	}	
+}
+
+static void
+cal_prefs_dialog_url_remove_clicked  (GtkWidget *button, void *data)
+{
+	DialogData *dialog_data = (DialogData *) data;
+	EPublishUri *url = NULL;
+	GtkTreeSelection * selection;
+	GtkTreeModel *model;
+	GtkWidget *confirm;
+	GtkTreeIter iter;
+	int ans;
+	
+	selection = gtk_tree_view_get_selection (dialog_data->url_list);
+	if (gtk_tree_selection_get_selected (selection, &model, &iter))
+		gtk_tree_model_get (model, &iter, 
+				    URL_LIST_FREE_BUSY_URL_COLUMN, &url, 
+				    -1);
+	
+	/* make sure we have a valid account selected and that 
+	   we aren't editing anything... */
+	if (url == NULL || dialog_data->url_editor)
+		return;
+	
+	confirm = gtk_message_dialog_new (PREFS_WINDOW (dialog_data),
+					  GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
+					  GTK_MESSAGE_QUESTION, 
+					  GTK_BUTTONS_NONE,
+					  _("Are you sure you want to remove this URL?"));
+	
+	(GtkButton *) button = gtk_button_new_from_stock (GTK_STOCK_YES);
+	gtk_button_set_label ((GtkButton *) button, _("Remove"));
+	gtk_dialog_add_action_widget ((GtkDialog *) confirm, (GtkWidget *) button, GTK_RESPONSE_YES);
+	gtk_widget_show ((GtkWidget *) button);
+	
+	(GtkButton *) button = gtk_button_new_from_stock (GTK_STOCK_NO);
+	gtk_button_set_label ((GtkButton *) button, _("Don't Remove"));
+	gtk_dialog_add_action_widget ((GtkDialog *) confirm, 
+				      (GtkWidget *) button, GTK_RESPONSE_NO);
+
+	gtk_widget_show ((GtkWidget *) button);
+	
+	ans = gtk_dialog_run ((GtkDialog *) confirm);
+	gtk_widget_destroy (confirm);
+	
+	if (ans == GTK_RESPONSE_YES) {
+		int len;
+		
+		gtk_list_store_remove ((GtkListStore *) model, &iter);
+		
+		len = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (model), NULL);
+		if (len > 0) {
+			gtk_tree_selection_select_iter (selection, &iter);
+		} else {
+			gtk_widget_set_sensitive (GTK_WIDGET (dialog_data->url_edit), FALSE);
+			gtk_widget_set_sensitive (GTK_WIDGET (dialog_data->url_remove), FALSE);
+			gtk_widget_set_sensitive (GTK_WIDGET (dialog_data->url_enable), FALSE);
+		}
+		g_free(url);
+	}
+}
+
+static void
+cal_prefs_dialog_url_enable_clicked  (GtkWidget *button, void *data)
+{
+	DialogData *dialog_data = (DialogData *) data;
+	EPublishUri *url = NULL;
+	GtkTreeSelection * selection;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	
+	selection = gtk_tree_view_get_selection (dialog_data->url_list);
+	if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+		gtk_tree_model_get (model, &iter, 
+				    URL_LIST_FREE_BUSY_URL_COLUMN, &url, 
+				    -1);
+		url->enabled = !url->enabled;
+		gtk_list_store_set ((GtkListStore *) model, &iter, 
+				    URL_LIST_ENABLED_COLUMN, url->enabled, 
+				    -1);
+		
+		gtk_button_set_label ((GtkButton *) dialog_data->url_enable, 
+				      url->enabled ? _("Disable") : _("Enable"));
+	}
+}
+ 
+static void
+cal_prefs_dialog_url_list_enable_toggled (GtkCellRendererToggle *renderer, 
+					   const char *path_string, 
+					   void *data)
+{
+	DialogData *dialog_data = (DialogData *) data;
+	GtkTreeSelection * selection;
+	EPublishUri *url = NULL;
+	GtkTreeModel *model;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	
+	path = gtk_tree_path_new_from_string (path_string);
+	model = gtk_tree_view_get_model (dialog_data->url_list);
+	selection = gtk_tree_view_get_selection (dialog_data->url_list);
+
+	if (gtk_tree_model_get_iter (model, &iter, path)) {
+		gtk_tree_model_get (model, &iter, 
+				    URL_LIST_FREE_BUSY_URL_COLUMN, &url, 
+				    -1);
+
+		url->enabled = !url->enabled;
+		gtk_list_store_set((GtkListStore *) model, &iter, 
+				   URL_LIST_ENABLED_COLUMN,
+				   url->enabled, -1);
+
+		if (gtk_tree_selection_iter_is_selected (selection, &iter))
+			gtk_button_set_label ((GtkButton *) dialog_data->url_enable, 
+					      url->enabled ? _("Disable") : _("Enable"));
+	}
+
+	gtk_tree_path_free(path);
+}
+
+static void
+cal_prefs_dialog_url_list_double_click (GtkTreeView *treeview, 
+					GtkTreePath *path, 
+					GtkTreeViewColumn *column, 
+					DialogData *dialog_data)
+{
+	cal_prefs_dialog_url_edit_clicked  (NULL, dialog_data);
+}				
+
+static void
+cal_prefs_dialog_url_list_change (GtkTreeSelection *selection, 
+				  DialogData *dialog_data)
+{
+	EPublishUri *url = NULL;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	int state;
+	
+	state = gtk_tree_selection_get_selected (selection, &model, &iter);
+	if (state) {
+		gtk_tree_model_get (model, &iter, 
+				    URL_LIST_FREE_BUSY_URL_COLUMN, &url, 
+				    -1);
+
+		if (url->location && url->enabled)
+			gtk_button_set_label ((GtkButton *) dialog_data->url_enable, _("Disable"));
+		else
+			gtk_button_set_label ((GtkButton *) dialog_data->url_enable, _("Enable"));
+	} else {
+		gtk_widget_grab_focus (GTK_WIDGET (dialog_data->url_add));
+	}
+	
+	gtk_widget_set_sensitive (GTK_WIDGET (dialog_data->url_edit), state);
+	gtk_widget_set_sensitive (GTK_WIDGET (dialog_data->url_remove), state);
+	gtk_widget_set_sensitive (GTK_WIDGET (dialog_data->url_enable), state);
+}
+
+/* Shows the current Free/Busy settings in the dialog */
+static void
+show_fb_config (DialogData *dialog_data)
+{
+	GSList *url_config_list;
+	GtkListStore *model;
+	GtkTreeIter iter;
+	
+	model = (GtkListStore *) gtk_tree_view_get_model (dialog_data->url_list);
+	gtk_list_store_clear (model);
+	
+	/* restore urls from gconf */
+	url_config_list = calendar_config_get_free_busy();
+	
+	while (url_config_list) {
+		gchar *xml = (gchar *)url_config_list->data;
+		EPublishUri *url;
+		url = g_new0 (EPublishUri, 1);
+		
+		e_pub_uri_from_xml (url, xml);
+		if (url->location) {
+			gtk_list_store_append(model, &iter);
+			gtk_list_store_set(model, &iter, 
+					   URL_LIST_ENABLED_COLUMN, 
+					   url->enabled,
+					   URL_LIST_LOCATION_COLUMN, 
+					   url->location,
+					   URL_LIST_FREE_BUSY_URL_COLUMN, url,
+					   -1);
+		}
+
+		url_config_list = g_slist_next(url_config_list);
+		g_free (xml);
+	}
+
+	g_slist_foreach (url_config_list, (GFunc) g_free, NULL);
+	g_slist_free(url_config_list);
+	if (!gtk_tree_model_get_iter_first((GtkTreeModel *) model, &iter)) {
+		/* list is empty-disable edit, remove, and enable buttons */
+		gtk_widget_set_sensitive(GTK_WIDGET(dialog_data->url_edit), 
+					 FALSE);
+
+		gtk_widget_set_sensitive(GTK_WIDGET(dialog_data->url_remove), 
+					 FALSE);
+
+		gtk_widget_set_sensitive(GTK_WIDGET(dialog_data->url_enable), 
+					 FALSE);
+	}
+}
+
 /* Shows the current task list settings in the dialog */
 static void
 show_task_list_config (DialogData *dialog_data)
@@ -576,6 +933,9 @@
 	/* Task list */
 
 	show_task_list_config (dialog_data);
+	
+	/* Free/Busy */
+	show_fb_config (dialog_data);
 
 	/* Other page */
 
@@ -605,6 +965,41 @@
 	return spec;
 }
 
+/* Updates the Free/Busy config values from the settings in the dialog*/
+static void
+update_fb_config (DialogData *dialog_data)
+{
+	GtkTreeIter iter;
+	GtkListStore *model = NULL;
+	gboolean valid;
+	GSList *url_list;
+ 	
+	url_list = NULL;
+	
+	model = (GtkListStore *) gtk_tree_view_get_model (dialog_data->url_list);
+	
+	valid = gtk_tree_model_get_iter_first ((GtkTreeModel *) model, &iter);
+	while (valid) {
+		EPublishUri *url;
+		gchar *xml;
+		
+		gtk_tree_model_get ((GtkTreeModel *) model, &iter, 
+					URL_LIST_FREE_BUSY_URL_COLUMN, &url, 
+					-1);
+
+		xml = e_pub_uri_to_xml (url);
+		if (xml != NULL) {
+			url_list = g_slist_append(url_list, xml);
+		}
+		g_free (url);
+		
+		valid = gtk_tree_model_iter_next((GtkTreeModel *) model, &iter);
+	}
+	calendar_config_set_free_busy(url_list);
+
+	g_slist_free (url_list);
+}
+
 /* Updates the task list config values from the settings in the dialog */
 static void
 update_task_list_config (DialogData *dialog_data)
@@ -671,6 +1066,9 @@
 
 	/* Task list */
 	update_task_list_config (dialog_data);
+	
+	/* Free/Busy */
+	update_fb_config (dialog_data);
 
 	/* Other page */
 
Index: gui/dialogs/cal-prefs-dialog.glade
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/dialogs/cal-prefs-dialog.glade,v
retrieving revision 1.24
diff -u -r1.24 cal-prefs-dialog.glade
--- gui/dialogs/cal-prefs-dialog.glade	19 Dec 2003 17:49:01 -0000	1.24
+++ gui/dialogs/cal-prefs-dialog.glade	12 Jan 2004 03:59:29 -0000
@@ -1005,7 +1005,6 @@
 
 	  <child>
 	    <widget class="GtkVBox" id="vbox8">
-	      <property name="border_width">6</property>
 	      <property name="visible">True</property>
 	      <property name="homogeneous">False</property>
 	      <property name="spacing">6</property>
@@ -1444,6 +1443,369 @@
 	    <widget class="GtkLabel" id="label7">
 	      <property name="visible">True</property>
 	      <property name="label" translatable="yes">_Display</property>
+	      <property name="use_underline">True</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_CENTER</property>
+	      <property name="wrap">False</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0.5</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	    </widget>
+	    <packing>
+	      <property name="type">tab</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkVBox" id="vbox14">
+	      <property name="border_width">12</property>
+	      <property name="visible">True</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">0</property>
+
+	      <child>
+		<widget class="GtkVBox" id="vbox18">
+		  <property name="visible">True</property>
+		  <property name="homogeneous">False</property>
+		  <property name="spacing">6</property>
+
+		  <child>
+		    <widget class="GtkLabel" id="label49">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">&lt;span weight=&quot;bold&quot;&gt;Free/Busy URLs&lt;/span&gt;</property>
+		      <property name="use_underline">False</property>
+		      <property name="use_markup">True</property>
+		      <property name="justify">GTK_JUSTIFY_LEFT</property>
+		      <property name="wrap">False</property>
+		      <property name="selectable">False</property>
+		      <property name="xalign">0</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xpad">0</property>
+		      <property name="ypad">0</property>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">False</property>
+		      <property name="fill">False</property>
+		    </packing>
+		  </child>
+
+		  <child>
+		    <widget class="GtkHBox" id="hbox24">
+		      <property name="visible">True</property>
+		      <property name="homogeneous">False</property>
+		      <property name="spacing">0</property>
+
+		      <child>
+			<widget class="GtkLabel" id="label50">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">    </property>
+			  <property name="use_underline">False</property>
+			  <property name="use_markup">False</property>
+			  <property name="justify">GTK_JUSTIFY_LEFT</property>
+			  <property name="wrap">False</property>
+			  <property name="selectable">False</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">False</property>
+			  <property name="fill">False</property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkVBox" id="vbox19">
+			  <property name="visible">True</property>
+			  <property name="homogeneous">False</property>
+			  <property name="spacing">0</property>
+
+			  <child>
+			    <widget class="GtkHBox" id="hbox20">
+			      <property name="visible">True</property>
+			      <property name="homogeneous">False</property>
+			      <property name="spacing">6</property>
+
+			      <child>
+				<widget class="GtkScrolledWindow" id="scrolledwindow1">
+				  <property name="visible">True</property>
+				  <property name="can_focus">True</property>
+				  <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+				  <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+				  <property name="shadow_type">GTK_SHADOW_IN</property>
+				  <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+				  <child>
+				    <widget class="GtkTreeView" id="url_list">
+				      <property name="visible">True</property>
+				      <property name="can_focus">True</property>
+				      <property name="headers_visible">True</property>
+				      <property name="rules_hint">False</property>
+				      <property name="reorderable">False</property>
+				      <property name="enable_search">True</property>
+				    </widget>
+				  </child>
+				</widget>
+				<packing>
+				  <property name="padding">0</property>
+				  <property name="expand">True</property>
+				  <property name="fill">True</property>
+				</packing>
+			      </child>
+
+			      <child>
+				<widget class="GtkVBox" id="vbox15">
+				  <property name="visible">True</property>
+				  <property name="homogeneous">False</property>
+				  <property name="spacing">0</property>
+
+				  <child>
+				    <widget class="GtkLabel" id="label44">
+				      <property name="height_request">34</property>
+				      <property name="visible">True</property>
+				      <property name="label" translatable="yes"></property>
+				      <property name="use_underline">False</property>
+				      <property name="use_markup">False</property>
+				      <property name="justify">GTK_JUSTIFY_CENTER</property>
+				      <property name="wrap">False</property>
+				      <property name="selectable">False</property>
+				      <property name="xalign">0.5</property>
+				      <property name="yalign">0.5</property>
+				      <property name="xpad">0</property>
+				      <property name="ypad">0</property>
+				    </widget>
+				    <packing>
+				      <property name="padding">0</property>
+				      <property name="expand">False</property>
+				      <property name="fill">False</property>
+				    </packing>
+				  </child>
+
+				  <child>
+				    <widget class="GtkVButtonBox" id="vbuttonbox3">
+				      <property name="visible">True</property>
+				      <property name="layout_style">GTK_BUTTONBOX_START</property>
+				      <property name="spacing">3</property>
+
+				      <child>
+					<widget class="GtkButton" id="url_add">
+					  <property name="visible">True</property>
+					  <property name="can_default">True</property>
+					  <property name="can_focus">True</property>
+					  <property name="relief">GTK_RELIEF_NORMAL</property>
+
+					  <child>
+					    <widget class="GtkAlignment" id="alignment5">
+					      <property name="visible">True</property>
+					      <property name="can_default">True</property>
+					      <property name="can_focus">True</property>
+					      <property name="xalign">0.5</property>
+					      <property name="yalign">0.5</property>
+					      <property name="xscale">0</property>
+					      <property name="yscale">0</property>
+
+					      <child>
+						<widget class="GtkHBox" id="hbox22">
+						  <property name="visible">True</property>
+						  <property name="homogeneous">False</property>
+						  <property name="spacing">2</property>
+
+						  <child>
+						    <widget class="GtkImage" id="image1">
+						      <property name="visible">True</property>
+						      <property name="stock">gtk-add</property>
+						      <property name="icon_size">4</property>
+						      <property name="xalign">0.5</property>
+						      <property name="yalign">0.5</property>
+						      <property name="xpad">0</property>
+						      <property name="ypad">0</property>
+						    </widget>
+						    <packing>
+						      <property name="padding">0</property>
+						      <property name="expand">False</property>
+						      <property name="fill">False</property>
+						    </packing>
+						  </child>
+
+						  <child>
+						    <widget class="GtkLabel" id="labeladd">
+						      <property name="visible">True</property>
+						      <property name="can_default">True</property>
+						      <property name="can_focus">True</property>
+						      <property name="label" translatable="yes">_Add URL</property>
+						      <property name="use_underline">True</property>
+						      <property name="use_markup">False</property>
+						      <property name="justify">GTK_JUSTIFY_LEFT</property>
+						      <property name="wrap">False</property>
+						      <property name="selectable">False</property>
+						      <property name="xalign">0.5</property>
+						      <property name="yalign">0.5</property>
+						      <property name="xpad">0</property>
+						      <property name="ypad">0</property>
+						    </widget>
+						    <packing>
+						      <property name="padding">0</property>
+						      <property name="expand">False</property>
+						      <property name="fill">False</property>
+						    </packing>
+						  </child>
+						</widget>
+					      </child>
+					    </widget>
+					  </child>
+					</widget>
+				      </child>
+
+				      <child>
+					<widget class="GtkButton" id="url_edit">
+					  <property name="visible">True</property>
+					  <property name="sensitive">False</property>
+					  <property name="can_default">True</property>
+					  <property name="can_focus">True</property>
+					  <property name="label" translatable="yes">_Edit</property>
+					  <property name="use_underline">True</property>
+					  <property name="relief">GTK_RELIEF_NORMAL</property>
+					</widget>
+				      </child>
+
+				      <child>
+					<widget class="GtkButton" id="url_remove">
+					  <property name="visible">True</property>
+					  <property name="sensitive">False</property>
+					  <property name="can_default">True</property>
+					  <property name="can_focus">True</property>
+					  <property name="label">gtk-remove</property>
+					  <property name="use_stock">True</property>
+					  <property name="relief">GTK_RELIEF_NORMAL</property>
+					</widget>
+				      </child>
+				    </widget>
+				    <packing>
+				      <property name="padding">0</property>
+				      <property name="expand">False</property>
+				      <property name="fill">False</property>
+				    </packing>
+				  </child>
+
+				  <child>
+				    <widget class="GtkLabel" id="label45">
+				      <property name="height_request">34</property>
+				      <property name="visible">True</property>
+				      <property name="label" translatable="yes"></property>
+				      <property name="use_underline">False</property>
+				      <property name="use_markup">False</property>
+				      <property name="justify">GTK_JUSTIFY_LEFT</property>
+				      <property name="wrap">False</property>
+				      <property name="selectable">False</property>
+				      <property name="xalign">0.5</property>
+				      <property name="yalign">0.5</property>
+				      <property name="xpad">0</property>
+				      <property name="ypad">0</property>
+				    </widget>
+				    <packing>
+				      <property name="padding">0</property>
+				      <property name="expand">False</property>
+				      <property name="fill">False</property>
+				    </packing>
+				  </child>
+
+				  <child>
+				    <widget class="GtkVButtonBox" id="vbuttonbox4">
+				      <property name="visible">True</property>
+				      <property name="layout_style">GTK_BUTTONBOX_START</property>
+				      <property name="spacing">3</property>
+
+				      <child>
+					<widget class="GtkButton" id="url_enable">
+					  <property name="width_request">91</property>
+					  <property name="visible">True</property>
+					  <property name="sensitive">False</property>
+					  <property name="can_default">True</property>
+					  <property name="can_focus">True</property>
+					  <property name="label" translatable="yes">E_nable</property>
+					  <property name="use_underline">True</property>
+					  <property name="relief">GTK_RELIEF_NORMAL</property>
+					</widget>
+				      </child>
+				    </widget>
+				    <packing>
+				      <property name="padding">0</property>
+				      <property name="expand">False</property>
+				      <property name="fill">False</property>
+				    </packing>
+				  </child>
+
+				  <child>
+				    <widget class="GtkLabel" id="label46">
+				      <property name="visible">True</property>
+				      <property name="label" translatable="yes"></property>
+				      <property name="use_underline">False</property>
+				      <property name="use_markup">False</property>
+				      <property name="justify">GTK_JUSTIFY_LEFT</property>
+				      <property name="wrap">False</property>
+				      <property name="selectable">False</property>
+				      <property name="xalign">0.5</property>
+				      <property name="yalign">0.5</property>
+				      <property name="xpad">0</property>
+				      <property name="ypad">0</property>
+				    </widget>
+				    <packing>
+				      <property name="padding">0</property>
+				      <property name="expand">False</property>
+				      <property name="fill">False</property>
+				    </packing>
+				  </child>
+				</widget>
+				<packing>
+				  <property name="padding">0</property>
+				  <property name="expand">False</property>
+				  <property name="fill">False</property>
+				</packing>
+			      </child>
+			    </widget>
+			    <packing>
+			      <property name="padding">0</property>
+			      <property name="expand">True</property>
+			      <property name="fill">True</property>
+			    </packing>
+			  </child>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">True</property>
+			  <property name="fill">True</property>
+			</packing>
+		      </child>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">True</property>
+		      <property name="fill">True</property>
+		    </packing>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">True</property>
+		  <property name="fill">True</property>
+		</packing>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="tab_expand">False</property>
+	      <property name="tab_fill">True</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="label42">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">_Free/Busy</property>
 	      <property name="use_underline">True</property>
 	      <property name="use_markup">False</property>
 	      <property name="justify">GTK_JUSTIFY_CENTER</property>
Index: gui/dialogs/cal-prefs-dialog.h
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/dialogs/cal-prefs-dialog.h,v
retrieving revision 1.9
diff -u -r1.9 cal-prefs-dialog.h
--- gui/dialogs/cal-prefs-dialog.h	7 Nov 2002 02:00:56 -0000	1.9
+++ gui/dialogs/cal-prefs-dialog.h	12 Jan 2004 03:59:29 -0000
@@ -30,9 +30,68 @@
 #ifndef _CAL_PREFS_DIALOG_H_
 #define _CAL_PREFS_DIALOG_H_
 
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include <gconf/gconf.h>
+#include <gconf/gconf-client.h>
+#include "../e-pub-utils.h"
 #include "evolution-config-control.h"
 
 G_BEGIN_DECLS
+
+enum {
+	URL_LIST_ENABLED_COLUMN,
+	URL_LIST_LOCATION_COLUMN,
+	URL_LIST_FREE_BUSY_URL_COLUMN,
+	URL_LIST_N_COLUMNS
+};
+
+struct _DialogData {
+	/* Glade XML data */
+	GladeXML *xml;
+	
+	GConfClient *gconf;
+
+	GtkWidget *page;
+
+	GtkWidget *timezone;
+	GtkWidget *working_days[7];
+	GtkWidget *week_start_day;
+	GtkWidget *start_of_day;
+	GtkWidget *end_of_day;
+	GtkWidget *use_12_hour;
+	GtkWidget *use_24_hour;
+	GtkWidget *time_divisions;
+	GtkWidget *show_end_times;
+	GtkWidget *compress_weekend;
+	GtkWidget *dnav_show_week_no;
+
+	/* Widgets for the task list options */
+	GtkWidget *tasks_due_today_color;
+	GtkWidget *tasks_overdue_color;
+
+	GtkWidget *tasks_hide_completed_checkbutton;
+	GtkWidget *tasks_hide_completed_spinbutton;
+	GtkWidget *tasks_hide_completed_optionmenu;
+	
+	/* Widgets for the Free/Busy options */
+	GtkWidget *url_add;
+	GtkWidget *url_edit;
+	GtkWidget *url_remove;
+	GtkWidget *url_enable;
+	GtkTreeView *url_list;
+	gboolean url_editor;
+	GtkWidget* url_editor_dlg;
+	guint destroyed : 1;
+	
+		
+	/* Other page options */
+	GtkWidget *confirm_delete;
+	GtkWidget *default_reminder;
+	GtkWidget *default_reminder_interval;
+	GtkWidget *default_reminder_units;
+};
+typedef struct _DialogData DialogData;
 
 EvolutionConfigControl *cal_prefs_dialog_new (void);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]