[evolution-patches] #57287, 58748



Should fix the two bugs above, there is one bit remaining to fix and
this is to handle the case when a new task is added via the calendar
when the task list isn't displayed.

-JP
-- 
JP Rosevear <jpr novell com>
Novell, Inc.
? primary-uncheck.patch
? gui/primary-uncheck.patch
? gui/scroll.patch
? gui/select-auto.patch
? gui/select.patch
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/calendar/ChangeLog,v
retrieving revision 1.2443
diff -u -r1.2443 ChangeLog
--- ChangeLog	12 Jul 2004 17:29:46 -0000	1.2443
+++ ChangeLog	13 Jul 2004 02:10:18 -0000
@@ -1,3 +1,79 @@
+2004-07-12  JP Rosevear  <jpr novell com>
+
+	Fixes #57287, 58748
+	
+	* gui/tasks-component.c (source_added_cb): if the source was
+	added in the main calendar, select it because the user caused this
+	to happen by creating a task
+	(create_component_view): listen for source_added signal on the
+	tasks
+
+	* gui/gnome-cal.c (view_selection_changed_cb): if the user created
+	a task, make sure we are displaying the relevant event list
+	(set_timezone): set the default zone of the default client
+	(setup_widgets): listen for the user_created signal
+	(gnome_calendar_destroy): clean up default client
+	(client_cal_opened_cb): disconnect from the open signal
+	(default_client_cal_opened_cb): set the default client on the
+	models
+	(open_ecal): make the callback function a param
+	(gnome_calendar_add_source): include the default client when
+	searching for an existing client
+	(gnome_calendar_set_default_source): make the default client
+	independent of the rest of the clients
+
+	* gui/e-week-view.c (e_week_view_on_editing_stopped): emit
+	user_created signal
+
+	* gui/e-tasks.c (user_created_cb): if the user created a task,
+	make sure we are displaying the relevant task list
+	(set_timezone): set the timezone on the client
+	(setup_widgets): listen for user_created signal
+	(e_tasks_destroy): unref default client
+	(default_client_cal_opened_cb): set the default on the model when
+	it opens
+	(open_ecal): open a task list
+	(e_tasks_add_todo_source): include the default client when
+	searching for an existing client
+	(e_tasks_set_default_source): make the default client independent
+	of the rest of the clients
+
+	* gui/e-day-view.c (e_day_view_on_editing_stopped): emit
+	user_created signal
+
+	* gui/e-calendar-view.h: add signal proto
+
+	* gui/e-calendar-view.c (e_calendar_view_class_init): add
+	user_created signal
+
+	* gui/e-calendar-table.h: add signal proto
+
+	* gui/e-calendar-table.c (e_calendar_table_class_init): add
+	user_created signal
+	(row_appended_cb): if row is appended, emit user_created signal
+	(e_calendar_table_init): listen for row_appended signal
+
+	* gui/e-cal-model.h: add signal proto
+
+	* gui/e-cal-model.c (e_cal_model_class_init): add row_appended
+	signal
+	(ecm_append_row): don't leak, emit row appended signal
+	(e_cal_model_set_default_client): remove the existing default if
+	it was only used as the default
+	(update_e_cal_view_for_client): short circuit query create
+	(add_new_client): look for an existing client and update its
+	record if found, handle opening things here
+	(e_cal_model_add_client): just call add_new_client
+	(remove_client_objects): just remove a client's objects
+	(remove_client): use above, handle removal of client if its
+	default
+
+	* gui/calendar-component.c (source_added_cb): if the source was
+	added in the main calendar, select it because the user caused this
+	to happen by creating an appointment
+	(create_component_view): listen for source_added signal on the
+	calendar
+
 2004-07-12  Rodney Dawes  <dobey#novell.com>
 
 	* gui/e-tasks.c (pane_realized): Add this callback so we can set the
Index: gui/calendar-component.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/calendar-component.c,v
retrieving revision 1.176
diff -u -r1.176 calendar-component.c
--- gui/calendar-component.c	28 Jun 2004 08:47:08 -0000	1.176
+++ gui/calendar-component.c	13 Jul 2004 02:10:18 -0000
@@ -444,6 +444,18 @@
 }
 
 static void
+source_added_cb (GnomeCalendar *calendar, ECalSourceType source_type, ESource *source, CalendarComponentView *component_view)
+{
+	switch (source_type) {
+	case E_CAL_SOURCE_TYPE_EVENT:
+		e_source_selector_select_source (E_SOURCE_SELECTOR (component_view->source_selector), source);
+		break;
+	default:
+		break;
+	}
+}
+
+static void
 source_removed_cb (GnomeCalendar *calendar, ECalSourceType source_type, ESource *source, CalendarComponentView *component_view)
 {
 	switch (source_type) {
@@ -1078,6 +1090,8 @@
 	component_view->calendar = (GnomeCalendar *) bonobo_control_get_widget (component_view->view_control);
 
 	/* This signal is thrown if backends die - we update the selector */
+	g_signal_connect (component_view->calendar, "source_added", 
+			  G_CALLBACK (source_added_cb), component_view);
 	g_signal_connect (component_view->calendar, "source_removed", 
 			  G_CALLBACK (source_removed_cb), component_view);
 
Index: gui/e-cal-model.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-cal-model.c,v
retrieving revision 1.36
diff -u -r1.36 e-cal-model.c
--- gui/e-cal-model.c	11 Jun 2004 15:55:14 -0000	1.36
+++ gui/e-cal-model.c	13 Jul 2004 02:10:19 -0000
@@ -34,6 +34,8 @@
 typedef struct {
 	ECal *client;
 	ECalView *query;
+
+	gboolean do_query;
 } ECalModelClient;
 
 struct _ECalModelPrivate {
@@ -88,9 +90,15 @@
 
 static const char *ecm_get_color_for_component (ECalModel *model, ECalModelComponent *comp_data);
 
+static ECalModelClient *add_new_client (ECalModel *model, ECal *client, gboolean do_query);
+static ECalModelClient *find_client_data (ECalModel *model, ECal *client);
+static void remove_client_objects (ECalModel *model, ECalModelClient *client_data);
+static void remove_client (ECalModel *model, ECalModelClient *client_data);
+
 /* Signal IDs */
 enum {
 	TIME_RANGE_CHANGED,
+	ROW_APPENDED,
 	LAST_SIGNAL
 };
 
@@ -135,6 +143,15 @@
 			      NULL, NULL,
 			      e_calendar_marshal_VOID__LONG_LONG,
 			      G_TYPE_NONE, 2, G_TYPE_LONG, G_TYPE_LONG);	
+
+	signals[ROW_APPENDED] =
+		g_signal_new ("row_appended",
+			      G_TYPE_FROM_CLASS (klass),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (ECalModelClass, row_appended),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE, 0);
 }
 
 static void
@@ -758,9 +775,13 @@
 		g_warning (G_STRLOC ": Could not create the object!");
 
 		/* FIXME: show error dialog */
+		icalcomponent_free (comp_data.icalcomp);
+		return;
 	}
 
 	icalcomponent_free (comp_data.icalcomp);
+
+	g_signal_emit (G_OBJECT (model), signals[ROW_APPENDED], 0);	
 }
 
 static void *
@@ -1097,6 +1118,8 @@
 	
 	priv = model->priv;
 
+	/* FIXME Should we force the client to be open? */
+
 	/* we always return a valid ECal, since we rely on it in many places */
 	if (priv->default_client)
 		return priv->default_client;
@@ -1113,6 +1136,7 @@
 e_cal_model_set_default_client (ECalModel *model, ECal *client)
 {
 	ECalModelPrivate *priv;
+	ECalModelClient *client_data;
 	
 	g_return_if_fail (model != NULL);
 	g_return_if_fail (E_IS_CAL_MODEL (model));
@@ -1121,11 +1145,21 @@
 
 	priv = model->priv;
 
+	if (priv->default_client) {
+		ECalModelClient *client_data;
+		
+		client_data = find_client_data (model, priv->default_client);
+		g_assert (client_data);
+
+		if (!client_data->do_query)
+			remove_client (model, client_data);
+	}
+	
 	/* Make sure its in the model */
-	e_cal_model_add_client (model, client);
+	client_data = add_new_client (model, client, FALSE);
 
 	/* Store the default client */	
-	priv->default_client = e_cal_model_get_client_for_uri (model, e_cal_get_uri (client));
+	priv->default_client = client_data->client;	
 }
 
 /**
@@ -1366,6 +1400,10 @@
 	/* prepare the query */
 	g_assert (priv->full_sexp != NULL);
 
+	/* Don't create the new query if we won't use it */
+	if (!client_data->do_query)
+		return;
+	
 	if (!e_cal_get_query (client_data->client, priv->full_sexp, &client_data->query, NULL)) {
 		g_warning (G_STRLOC ": Unable to get query");
 
@@ -1412,24 +1450,46 @@
 	update_e_cal_view_for_client (model, client_data);
 }
 
+
 static ECalModelClient *
-add_new_client (ECalModel *model, ECal *client)
+add_new_client (ECalModel *model, ECal *client, gboolean do_query)
 {
 	ECalModelPrivate *priv;
 	ECalModelClient *client_data;
-
+	ECal *existing_client;
+	
 	priv = model->priv;
 
+	/* Look for an existing client with the same URI */
+	existing_client = e_cal_model_get_client_for_uri (model, e_cal_get_uri (client));
+	if (existing_client) {
+		client_data = find_client_data (model, client);
+		g_assert (client_data);
+
+		if (!client_data->do_query)
+			client_data->do_query = do_query;
+		
+		goto load;
+	}
+	
 	client_data = g_new0 (ECalModelClient, 1);
-	client_data->client = client;
+	client_data->client = g_object_ref (client);
 	client_data->query = NULL;
-	g_object_ref (client_data->client);
+	client_data->do_query = do_query;
 
 	priv->clients = g_list_append (priv->clients, client_data);
 
 	g_signal_connect (G_OBJECT (client_data->client), "backend_died",
 			  G_CALLBACK (backend_died_cb), model);
 
+ load:
+	if (e_cal_get_load_state (client) == E_CAL_LOAD_LOADED) {
+		update_e_cal_view_for_client (model, client_data);
+	} else {
+		g_signal_connect (client, "cal_opened", G_CALLBACK (cal_opened_cb), model);
+		e_cal_open_async (client, TRUE);
+	}
+
 	return client_data;
 }
 
@@ -1447,29 +1507,14 @@
 
 	priv = model->priv;
 
-	if (e_cal_model_get_client_for_uri (model, e_cal_get_uri (client)))
-		return;
-
-	client_data = add_new_client (model, client);	
-	if (e_cal_get_load_state (client) == E_CAL_LOAD_LOADED) {
-		update_e_cal_view_for_client (model, client_data);
-	} else {
-		g_signal_connect (client, "cal_opened", G_CALLBACK (cal_opened_cb), model);
-		e_cal_open_async (client, TRUE);
-	}
+	client_data = add_new_client (model, client, TRUE);	
 }
 
 static void
-remove_client (ECalModel *model, ECalModelClient *client_data)
+remove_client_objects (ECalModel *model, ECalModelClient *client_data)
 {
-	gint i;
-
-	g_signal_handlers_disconnect_matched (client_data->client, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, model);
-	if (client_data->query)
-		g_signal_handlers_disconnect_matched (client_data->query, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, model);
-
-	model->priv->clients = g_list_remove (model->priv->clients, client_data);
-
+	int i;
+	
 	/* remove all objects belonging to this client */
 	for (i = model->priv->objects->len; i > 0; i--) {
 		ECalModelComponent *comp_data = (ECalModelComponent *) g_ptr_array_index (model->priv->objects, i - 1);
@@ -1485,11 +1530,29 @@
 			e_table_model_row_deleted (E_TABLE_MODEL (model), i - 1);
 		}
 	}
+}
+
+static void
+remove_client (ECalModel *model, ECalModelClient *client_data)
+{
+	/* FIXME We might not want to disconnect the open signal for the default client */
+	g_signal_handlers_disconnect_matched (client_data->client, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, model);
+	if (client_data->query)
+		g_signal_handlers_disconnect_matched (client_data->query, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, model);
+
+	remove_client_objects (model, client_data);
+
+	/* If this is the default client and we were querying (so it
+	 * was also a source), keep it around but don't query it */
+	if (model->priv->default_client == client_data->client && client_data->do_query) {
+		client_data->do_query = FALSE;
+		
+		return;
+	}
+
+	/* Remove the client from the list */
+	model->priv->clients = g_list_remove (model->priv->clients, client_data);
 
-	/* If this was the default client, unset it */
-	if (model->priv->default_client == client_data->client)
-		model->priv->default_client = NULL;
-	
 	/* free all remaining memory */
 	g_object_unref (client_data->client);
 	if (client_data->query)
Index: gui/e-cal-model.h
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-cal-model.h,v
retrieving revision 1.11
diff -u -r1.11 e-cal-model.h
--- gui/e-cal-model.h	29 Apr 2004 21:21:56 -0000	1.11
+++ gui/e-cal-model.h	13 Jul 2004 02:10:19 -0000
@@ -84,6 +84,7 @@
 
 	/* Signals */
 	void (* time_range_changed) (ECalModel *model, time_t start, time_t end);
+	void (* row_appended) (ECalModel *model);
 } ECalModelClass;
 
 GType               e_cal_model_get_type                       (void);
Index: gui/e-calendar-table.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-calendar-table.c,v
retrieving revision 1.120
diff -u -r1.120 e-calendar-table.c
--- gui/e-calendar-table.c	10 Jun 2004 14:04:55 -0000	1.120
+++ gui/e-calendar-table.c	13 Jul 2004 02:10:19 -0000
@@ -104,6 +104,13 @@
 static ECalModelComponent *get_selected_comp (ECalendarTable *cal_table);
 static void open_task (ECalendarTable *cal_table, ECalModelComponent *comp_data, gboolean assign);
 
+/* Signal IDs */
+enum {
+	USER_CREATED,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
 
 /* The icons to represent the task. */
 #define E_CALENDAR_MODEL_NUM_ICONS	4
@@ -131,6 +138,15 @@
 	/* Method override */
 	object_class->destroy		= e_calendar_table_destroy;
 
+	signals[USER_CREATED] =
+		g_signal_new ("user_created",
+			      G_TYPE_FROM_CLASS (class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (ECalendarTableClass, user_created),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE, 0);
+
 	/* clipboard atom */
 	if (!clipboard_atom)
 		clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE);
@@ -279,6 +295,12 @@
 }
 
 static void
+row_appended_cb (ECalModel *model, ECalendarTable *cal_table) 
+{
+	g_signal_emit (cal_table, signals[USER_CREATED], 0);
+}
+
+static void
 e_calendar_table_init (ECalendarTable *cal_table)
 {
 	GtkWidget *table;
@@ -292,6 +314,7 @@
 	/* Create the model */
 
 	cal_table->model = (ECalModel *) e_cal_model_tasks_new ();
+	g_signal_connect (cal_table->model, "row_appended", G_CALLBACK (row_appended_cb), cal_table);
 
 	/* Create the header columns */
 
Index: gui/e-calendar-table.h
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-calendar-table.h,v
retrieving revision 1.22
diff -u -r1.22 e-calendar-table.h
--- gui/e-calendar-table.h	29 Apr 2004 19:36:53 -0000	1.22
+++ gui/e-calendar-table.h	13 Jul 2004 02:10:19 -0000
@@ -68,6 +68,9 @@
 
 struct _ECalendarTableClass {
 	GtkTableClass parent_class;
+
+	/* Notification signals */
+	void (* user_created) (ECalendarTable *cal_table);
 };
 
 
Index: gui/e-calendar-view.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-calendar-view.c,v
retrieving revision 1.59
diff -u -r1.59 e-calendar-view.c
--- gui/e-calendar-view.c	9 Jul 2004 16:13:43 -0000	1.59
+++ gui/e-calendar-view.c	13 Jul 2004 02:10:19 -0000
@@ -103,6 +103,7 @@
 	TIMEZONE_CHANGED,
 	EVENT_CHANGED,
 	EVENT_ADDED,
+	USER_CREATED,
 	OPEN_EVENT,
 	LAST_SIGNAL
 };
@@ -166,6 +167,7 @@
  	klass->selected_time_changed = NULL;
 	klass->event_changed = NULL;
 	klass->event_added = NULL;
+	klass->user_created = NULL;
 
 	klass->get_selected_events = NULL;
 	klass->get_selected_time_range = NULL;
@@ -214,15 +216,6 @@
 			      G_TYPE_NONE, 1,
 			      G_TYPE_POINTER);
 
-	e_calendar_view_signals[OPEN_EVENT] =
-		g_signal_new ("open_event",
-			      G_TYPE_FROM_CLASS (klass),
-			      G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
-			      G_STRUCT_OFFSET (ECalendarViewClass, open_event),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__VOID,
-			      G_TYPE_NONE, 0);
-
 	e_calendar_view_signals[EVENT_ADDED] =
 		g_signal_new ("event_added",
 			      G_TYPE_FROM_CLASS (object_class),
@@ -232,6 +225,24 @@
 			      g_cclosure_marshal_VOID__POINTER,
 			      G_TYPE_NONE, 1,
 			      G_TYPE_POINTER);
+
+	e_calendar_view_signals[USER_CREATED] =
+		g_signal_new ("user_created",
+			      G_TYPE_FROM_CLASS (klass),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (ECalendarViewClass, user_created),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE, 0);
+
+	e_calendar_view_signals[OPEN_EVENT] =
+		g_signal_new ("open_event",
+			      G_TYPE_FROM_CLASS (klass),
+			      G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+			      G_STRUCT_OFFSET (ECalendarViewClass, open_event),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE, 0);
 
 	/* clipboard atom */
 	if (!clipboard_atom)
Index: gui/e-calendar-view.h
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-calendar-view.h,v
retrieving revision 1.25
diff -u -r1.25 e-calendar-view.h
--- gui/e-calendar-view.h	29 Apr 2004 19:36:53 -0000	1.25
+++ gui/e-calendar-view.h	13 Jul 2004 02:10:19 -0000
@@ -87,6 +87,7 @@
 	void (* timezone_changed) (ECalendarView *cal_view, icaltimezone *old_zone, icaltimezone *new_zone);
 	void (* event_changed) (ECalendarView *day_view, ECalendarViewEvent *event);
 	void (* event_added) (ECalendarView *day_view, ECalendarViewEvent *event);
+	void (* user_created) (ECalendarView *cal_view);
 
 	/* Virtual methods */
 	GList * (* get_selected_events) (ECalendarView *cal_view); /* a GList of ECalendarViewEvent's */
Index: gui/e-day-view.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-day-view.c,v
retrieving revision 1.248
diff -u -r1.248 e-day-view.c
--- gui/e-day-view.c	17 May 2004 20:41:46 -0000	1.248
+++ gui/e-day-view.c	13 Jul 2004 02:10:21 -0000
@@ -6049,6 +6049,8 @@
 		if (!on_server) {
 			if (!e_cal_create_object (client, icalcomp, NULL, NULL))
 				g_message (G_STRLOC ": Could not create the object!");
+			else
+				g_signal_emit_by_name (day_view, "user_created");
 		} else {
 			CalObjModType mod = CALOBJ_MOD_ALL;
 			GtkWindow *toplevel;
Index: gui/e-tasks.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-tasks.c,v
retrieving revision 1.99
diff -u -r1.99 e-tasks.c
--- gui/e-tasks.c	12 Jul 2004 17:29:46 -0000	1.99
+++ gui/e-tasks.c	13 Jul 2004 02:10:21 -0000
@@ -61,6 +61,7 @@
 	/* The task lists for display */
 	GHashTable *clients;
 	GList *clients_list;
+	ECal *default_client;
 
 	ECalView *query;
 	
@@ -88,7 +89,6 @@
 	GList *notifications;
 };
 
-
 static void e_tasks_class_init (ETasksClass *class);
 static void e_tasks_init (ETasks *tasks);
 static void setup_widgets (ETasks *tasks);
@@ -178,6 +178,21 @@
 			 n_selected);
 }
 
+static void
+user_created_cb (GtkWidget *view, ETasks *tasks)
+{
+	ETasksPrivate *priv;	
+	ECal *ecal;
+	ECalModel *model;
+	
+	priv = tasks->priv;
+
+	model = e_calendar_table_get_model (E_CALENDAR_TABLE (priv->tasks_view));
+	ecal = e_cal_model_get_default_client (model);
+
+	e_tasks_add_todo_source (tasks, e_cal_get_source (ecal));
+}
+
 /* Callback used when the sexp in the search bar changes */
 static void
 search_bar_sexp_changed_cb (CalSearchBar *cal_search, const char *sexp, gpointer data)
@@ -237,6 +252,10 @@
 			e_cal_set_default_timezone (client, zone, NULL);
 	}
 
+	if (priv->default_client && e_cal_get_load_state (priv->default_client) == E_CAL_LOAD_LOADED)
+		/* FIXME Error checking */
+		e_cal_set_default_timezone (priv->default_client, zone, NULL);
+
 	if (priv->preview)
 		e_cal_component_preview_set_default_timezone (E_CAL_COMPONENT_PREVIEW (priv->preview), zone);
 }
@@ -477,6 +496,8 @@
 	priv->tasks_view = e_calendar_table_new ();
 	priv->tasks_view_config = e_calendar_table_config_new (E_CALENDAR_TABLE (priv->tasks_view));
 	
+	g_signal_connect (priv->tasks_view, "user_created", G_CALLBACK (user_created_cb), tasks);
+
 	etable = e_table_scrolled_get_table (
 		E_TABLE_SCROLLED (E_CALENDAR_TABLE (priv->tasks_view)->etable));
 	e_table_set_state (etable, E_TASKS_TABLE_DEFAULT_STATE);
@@ -492,6 +513,7 @@
 			  G_CALLBACK(table_drag_data_get), tasks);
 	g_signal_connect (etable, "table_drag_data_delete",
 			  G_CALLBACK(table_drag_data_delete), tasks);
+
 	/*
 	e_table_drag_dest_set (e_table_scrolled_get_table (E_TABLE_SCROLLED (editor->table)),
 			       0, list_drag_types, num_list_drag_types, GDK_ACTION_LINK);
@@ -651,6 +673,10 @@
 		g_hash_table_destroy (priv->clients);
 		g_list_free (priv->clients_list);
 
+		if (priv->default_client)
+			g_object_unref (priv->default_client);
+		priv->default_client = NULL;
+
 		if (priv->current_uid) {
 			g_free (priv->current_uid);
 			priv->current_uid = NULL;
@@ -761,6 +787,8 @@
 
 	switch (status) {
 	case E_CALENDAR_STATUS_OK :
+		g_signal_handlers_disconnect_matched (ecal, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, client_cal_opened_cb, NULL);
+
 		set_status_message (tasks, _("Loading tasks"));
 		model = e_calendar_table_get_model (E_CALENDAR_TABLE (priv->tasks_view));
 		e_cal_model_add_client (model, ecal);
@@ -789,6 +817,63 @@
 	}
 }
 
+static void
+default_client_cal_opened_cb (ECal *ecal, ECalendarStatus status, ETasks *tasks)
+{
+	ECalModel *model;
+	ESource *source;
+	ETasksPrivate *priv;
+
+	priv = tasks->priv;
+
+	source = e_cal_get_source (ecal);
+
+	switch (status) {
+	case E_CALENDAR_STATUS_OK :
+		g_signal_handlers_disconnect_matched (ecal, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, default_client_cal_opened_cb, NULL);
+		model = e_calendar_table_get_model (E_CALENDAR_TABLE (priv->tasks_view));
+		
+		set_timezone (tasks);
+		e_cal_model_set_default_client (model, ecal);
+		break;
+	default :
+		/* Make sure the source doesn't disappear on us */
+		g_object_ref (source);
+
+		priv->clients_list = g_list_remove (priv->clients_list, ecal);
+		g_signal_handlers_disconnect_matched (ecal, G_SIGNAL_MATCH_DATA,
+						      0, 0, NULL, NULL, tasks);
+
+		/* Do this last because it unrefs the client */
+		g_hash_table_remove (priv->clients, e_cal_get_uri (ecal));
+
+		gtk_signal_emit (GTK_OBJECT (tasks), e_tasks_signals[SOURCE_REMOVED], source);
+
+		set_status_message (tasks, NULL);
+		g_object_unref (ecal);
+		g_object_unref (source);
+
+		break;
+	}
+}
+
+typedef void (*open_func) (ECal *, ECalendarStatus, ETasks *);
+
+static gboolean
+open_ecal (ETasks *tasks, ECal *cal, gboolean only_if_exists, open_func of)
+{
+	ETasksPrivate *priv;
+
+	priv = tasks->priv;
+	
+	set_status_message (tasks, _("Opening tasks at %s"), e_cal_get_uri (cal));
+
+	g_signal_connect (G_OBJECT (cal), "cal_opened", G_CALLBACK (of), tasks);
+	e_cal_open_async (cal, only_if_exists);
+
+	return TRUE;
+}
+
 void
 e_tasks_open_task			(ETasks		*tasks)
 {
@@ -833,8 +918,6 @@
 {
 	ETasksPrivate *priv;
 	ECal *client;
-	char *str_uri;
-	GError *error = NULL;
 	const char *uid;
 
 	g_return_val_if_fail (tasks != NULL, FALSE);
@@ -845,32 +928,40 @@
 
 	uid = e_source_peek_uid (source);
 	client = g_hash_table_lookup (priv->clients, uid);
-	if (client) 
+	if (client) {
+		/* We already have it */
+
 		return TRUE;
-	
+	} else {
+		ESource *default_source;
+		
+		if (priv->default_client) {
+			default_source = e_cal_get_source (priv->default_client);
+		
+			/* We don't have it but the default client is it */
+			if (!strcmp (e_source_peek_uid (default_source), uid))
+				client = g_object_ref (priv->default_client);
+		}
 
-	/* FIXME Loading should be async */
-	/* FIXME With no event handling here the status message never actually changes */
-	str_uri = e_source_get_uri (source);
-	set_status_message (tasks, _("Opening tasks at %s"), str_uri);
-
-	client = auth_new_cal_from_source (source, E_CAL_SOURCE_TYPE_TODO);
-	if (!client) {
-		g_free (str_uri);
-		return FALSE;
+		/* Create a new one */
+		if (!client) {
+			client = auth_new_cal_from_source (source, E_CAL_SOURCE_TYPE_TODO);
+			if (!client)
+				return FALSE;
+		}
 	}
 
-	g_hash_table_insert (priv->clients, g_strdup (uid) , client);
-	priv->clients_list = g_list_prepend (priv->clients_list, client);
-	
 	g_signal_connect (G_OBJECT (client), "backend_error", G_CALLBACK (backend_error_cb), tasks);
 	g_signal_connect (G_OBJECT (client), "categories_changed", G_CALLBACK (client_categories_changed_cb), tasks);
 	g_signal_connect (G_OBJECT (client), "backend_died", G_CALLBACK (backend_died_cb), tasks);
-	g_signal_connect (G_OBJECT (client), "cal_opened", G_CALLBACK (client_cal_opened_cb), tasks);
+
+	/* add the client to internal structure */	
+	g_hash_table_insert (priv->clients, g_strdup (uid) , client);
+	priv->clients_list = g_list_prepend (priv->clients_list, client);
 
 	gtk_signal_emit (GTK_OBJECT (tasks), e_tasks_signals[SOURCE_ADDED], source);
 
-	e_cal_open_async (client, FALSE);
+	open_ecal (tasks, client, FALSE, client_cal_opened_cb);
 
 	return TRUE;
 }
@@ -915,8 +1006,6 @@
 {
 	ETasksPrivate *priv;
 	ECal *ecal;
-	ECalModel *model;
-	char *str_uri;
 	
 	g_return_val_if_fail (tasks != NULL, FALSE);
 	g_return_val_if_fail (E_IS_TASKS (tasks), FALSE);
@@ -924,14 +1013,20 @@
 
 	priv = tasks->priv;
 
-	str_uri = e_source_get_uri (source);
-	model = e_calendar_table_get_model (E_CALENDAR_TABLE (priv->tasks_view));
-	ecal = e_cal_model_get_client_for_uri (model, str_uri);
-	g_free (str_uri);
-	if (!ecal)
-		return FALSE;
+	ecal = g_hash_table_lookup (priv->clients, e_source_peek_uid (source));
+
+	if (priv->default_client)
+		g_object_unref (priv->default_client);
+
+	if (ecal) {
+		priv->default_client = g_object_ref (ecal);
+	} else {
+		priv->default_client = auth_new_cal_from_source (source, E_CAL_SOURCE_TYPE_TODO);
+		if (!priv->default_client)
+			return FALSE;
+	}
 
-	e_cal_model_set_default_client (model, ecal);
+	open_ecal (tasks, priv->default_client, FALSE, default_client_cal_opened_cb);
 
 	return TRUE;
 }
Index: gui/e-week-view.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-week-view.c,v
retrieving revision 1.216
diff -u -r1.216 e-week-view.c
--- gui/e-week-view.c	15 Jun 2004 19:17:15 -0000	1.216
+++ gui/e-week-view.c	13 Jul 2004 02:10:22 -0000
@@ -3333,6 +3333,8 @@
 		if (!on_server) {
 			if (!e_cal_create_object (client, icalcomp, NULL, NULL))
 				g_message (G_STRLOC ": Could not create the object!");
+			else
+				g_signal_emit_by_name (week_view, "user_created");				
 		} else {
 			CalObjModType mod = CALOBJ_MOD_ALL;
 			GtkWindow *toplevel;
Index: gui/gnome-cal.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/gnome-cal.c,v
retrieving revision 1.342
diff -u -r1.342 gnome-cal.c
--- gui/gnome-cal.c	9 Jul 2004 17:31:22 -0000	1.342
+++ gui/gnome-cal.c	13 Jul 2004 02:10:23 -0000
@@ -91,6 +91,7 @@
 	
 	GHashTable *clients[E_CAL_SOURCE_TYPE_LAST];
 	GList *clients_list[E_CAL_SOURCE_TYPE_LAST];
+	ECal *default_client;
 	
 	/* Categories from the calendar clients */
 	/* FIXME are we getting all the categories? */
@@ -845,6 +846,21 @@
 			 gnome_calendar_signals[CALENDAR_SELECTION_CHANGED]);
 }
 
+static void
+user_created_cb (GtkWidget *view, GnomeCalendar *gcal)
+{
+	GnomeCalendarPrivate *priv;	
+	ECal *ecal;
+	ECalModel *model;
+	
+	priv = gcal->priv;	
+
+	model = e_calendar_view_get_model (priv->views[priv->current_view_type]);
+	ecal = e_cal_model_get_default_client (model);
+
+	gnome_calendar_add_source (gcal, E_CAL_SOURCE_TYPE_EVENT, e_cal_get_source (ecal));
+}
+
 
 /* Callback used when the taskpad receives a focus event.  We emit the
  * corresponding signal so that parents can change the menus as appropriate.
@@ -967,6 +983,10 @@
 				e_cal_set_default_timezone (client, priv->zone, NULL);
 		}
 	}
+
+	if (priv->default_client && e_cal_get_load_state (priv->default_client) == E_CAL_LOAD_LOADED)
+		/* FIXME Error checking */
+		e_cal_set_default_timezone (priv->default_client, priv->zone, NULL);
 }
 
 static void
@@ -1268,6 +1288,9 @@
 		gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook),
 					  GTK_WIDGET (priv->views[i]), gtk_label_new (""));
 
+		g_signal_connect (priv->views[i], "user_created",
+				  G_CALLBACK (user_created_cb), gcal);
+
 		gtk_widget_show (GTK_WIDGET (priv->views[i]));
 	}
 
@@ -1351,6 +1374,13 @@
 			priv->clients[i] = NULL;
 			priv->clients_list[i] = NULL;
 		}
+
+		if (priv->default_client) {
+			g_signal_handlers_disconnect_matched (priv->default_client, G_SIGNAL_MATCH_DATA,
+							      0, 0, NULL, NULL, gcal);
+			g_object_unref (priv->default_client);
+		}		
+		priv->default_client = NULL;
 		
 		for (i = 0; i < E_CAL_SOURCE_TYPE_LAST; i++) {
 			free_categories (priv->categories[i]);
@@ -1988,9 +2018,6 @@
 		g_object_ref (source);
 		
 		priv->clients_list[source_type] = g_list_remove (priv->clients_list[source_type], ecal);
-		g_signal_handlers_disconnect_matched (ecal, G_SIGNAL_MATCH_DATA,
-						      0, 0, NULL, NULL, gcal);
-
 		g_hash_table_remove (priv->clients[source_type], e_source_peek_uid (source));
 
 		gtk_signal_emit (GTK_OBJECT (gcal), gnome_calendar_signals[SOURCE_REMOVED], source_type, source);
@@ -2000,6 +2027,8 @@
 		return;
 	}
 
+	g_signal_handlers_disconnect_matched (ecal, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, client_cal_opened_cb, NULL);
+
 	e_cal_set_default_timezone (ecal, priv->zone, NULL);
 
 	switch (source_type) {
@@ -2038,8 +2067,69 @@
 	}
 }
 
+static void
+default_client_cal_opened_cb (ECal *ecal, ECalendarStatus status, GnomeCalendar *gcal)
+{
+	GnomeCalendarPrivate *priv;
+	ECalSourceType source_type;
+	ESource *source;
+	int i;
+
+	priv = gcal->priv;
+
+	source_type = e_cal_get_source_type (ecal);
+	source = e_cal_get_source (ecal);
+
+	if (source_type == E_CAL_SOURCE_TYPE_EVENT)
+		e_calendar_view_set_status_message (priv->views[priv->current_view_type], NULL);
+	else
+		e_calendar_table_set_status_message (E_CALENDAR_TABLE (priv->todo), NULL);
+
+	if (status != E_CALENDAR_STATUS_OK) {
+		/* Make sure the source doesn't disappear on us */
+		g_object_ref (source);
+		
+		/* FIXME should we do this to prevent multiple error dialogs? */
+		priv->clients_list[source_type] = g_list_remove (priv->clients_list[source_type], ecal);
+		g_hash_table_remove (priv->clients[source_type], e_source_peek_uid (source));
+
+		/* FIXME Is there a better way to handle this? */
+		g_object_unref (priv->default_client);
+		priv->default_client = NULL;
+		
+		gtk_signal_emit (GTK_OBJECT (gcal), gnome_calendar_signals[SOURCE_REMOVED], source_type, source);
+		
+		g_object_unref (source);
+		
+		return;
+	}
+
+	g_signal_handlers_disconnect_matched (ecal, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, default_client_cal_opened_cb, NULL);
+
+	e_cal_set_default_timezone (ecal, priv->zone, NULL);
+	
+	switch (source_type) {
+	case E_CAL_SOURCE_TYPE_EVENT:
+		for (i = 0; i < GNOME_CAL_LAST_VIEW; i++) {
+			e_cal_model_set_default_client (
+				e_calendar_view_get_model (E_CALENDAR_VIEW (priv->views[i])),
+				ecal);
+		}
+		break;
+
+	case E_CAL_SOURCE_TYPE_TODO:
+		e_cal_model_set_default_client (e_calendar_table_get_model (E_CALENDAR_TABLE (priv->todo)), ecal);
+		break;
+
+	default:
+		return;
+        }
+}
+
+typedef void (*open_func) (ECal *, ECalendarStatus, GnomeCalendar *);
+
 static gboolean
-open_ecal (GnomeCalendar *gcal, ECal *cal, gboolean only_if_exists)
+open_ecal (GnomeCalendar *gcal, ECal *cal, gboolean only_if_exists, open_func of)
 {
 	GnomeCalendarPrivate *priv;
 	char *msg;
@@ -2061,7 +2151,7 @@
 
 	g_free (msg);
 
-	g_signal_connect (G_OBJECT (cal), "cal_opened", G_CALLBACK (client_cal_opened_cb), gcal);
+	g_signal_connect (G_OBJECT (cal), "cal_opened", G_CALLBACK (of), gcal);
 	e_cal_open_async (cal, only_if_exists);
 
 	return TRUE;
@@ -2177,10 +2267,12 @@
 	gcal = GNOME_CALENDAR (data);
 	priv = gcal->priv;
 
+	/* FIXME What about default sources? */
+
 	/* Make sure the source doesn't go away on us since we use it below */
 	source_type = e_cal_get_source_type (ecal);
-	source = g_object_ref (e_cal_get_source (ecal));
-	
+	source = g_object_ref (e_cal_get_source (ecal));	
+		
 	priv->clients_list[source_type] = g_list_remove (priv->clients_list[source_type], ecal);
 	g_hash_table_remove (priv->clients[source_type], e_source_peek_uid (source));
 
@@ -2329,12 +2421,29 @@
 	priv = gcal->priv;
 
 	client = g_hash_table_lookup (priv->clients[source_type], e_source_peek_uid (source));
-	if (client)
+	if (client) {
+		/* We already have it */
+
 		return TRUE;
-	
-	client = auth_new_cal_from_source (source, source_type);
-	if (!client)
-		return FALSE;
+	} else {
+		ESource *default_source;
+		
+		if (priv->default_client) {
+			default_source = e_cal_get_source (priv->default_client);
+
+			g_message ("Check if default client matches (%s %s)", e_source_peek_uid (default_source), e_source_peek_uid (source));
+			/* We don't have it but the default client is it */
+			if (!strcmp (e_source_peek_uid (default_source), e_source_peek_uid (source)))
+				client = g_object_ref (priv->default_client);
+		}
+
+		/* Create a new one */		
+		if (!client) {
+			client = auth_new_cal_from_source (source, source_type);
+			if (!client)
+				return FALSE;
+		}
+	}
 	
 	g_signal_connect (G_OBJECT (client), "backend_error", G_CALLBACK (backend_error_cb), gcal);
 	g_signal_connect (G_OBJECT (client), "categories_changed", G_CALLBACK (client_categories_changed_cb), gcal);
@@ -2346,7 +2455,7 @@
 
 	gtk_signal_emit (GTK_OBJECT (gcal), gnome_calendar_signals[SOURCE_ADDED], source_type, source);
 
-	open_ecal (gcal, client, FALSE);
+	open_ecal (gcal, client, FALSE, client_cal_opened_cb);
 
 	return TRUE;
 }
@@ -2456,8 +2565,7 @@
 {
 	GnomeCalendarPrivate *priv;
 	ECal *client;
-	int i;
-
+	
 	g_return_val_if_fail (gcal != NULL, FALSE);
 	g_return_val_if_fail (GNOME_IS_CALENDAR (gcal), FALSE);
 	g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
@@ -2465,26 +2573,20 @@
 	priv = gcal->priv;
 
 	client = g_hash_table_lookup (priv->clients[source_type], e_source_peek_uid (source));
-	if (!client) 
-		return FALSE;
-	
-	switch (source_type) {
-	case E_CAL_SOURCE_TYPE_EVENT:
-		for (i = 0; i < GNOME_CAL_LAST_VIEW; i++) {
-			e_cal_model_set_default_client (
-				e_calendar_view_get_model (E_CALENDAR_VIEW (priv->views[i])),
-				client);
-		}
-		break;
 
-	case E_CAL_SOURCE_TYPE_TODO:
-		e_cal_model_set_default_client (e_calendar_table_get_model (E_CALENDAR_TABLE (priv->todo)), client);
-		break;
-		
-	default:
-		return FALSE;
+	if (priv->default_client)
+		g_object_unref (priv->default_client);
+
+	if (client) {
+		priv->default_client = g_object_ref (client);
+	} else {
+		priv->default_client = auth_new_cal_from_source (source, source_type);
+		if (!priv->default_client)
+			return FALSE;
 	}
-	
+
+	open_ecal (gcal, priv->default_client, FALSE, default_client_cal_opened_cb);
+
 	return TRUE;
 }
 
Index: gui/tasks-component.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/tasks-component.c,v
retrieving revision 1.70
diff -u -r1.70 tasks-component.c
--- gui/tasks-component.c	28 Jun 2004 08:47:08 -0000	1.70
+++ gui/tasks-component.c	13 Jul 2004 02:10:23 -0000
@@ -391,6 +391,12 @@
 }
 
 static void
+source_added_cb (ETasks *tasks, ESource *source, TasksComponentView *component_view)
+{
+	e_source_selector_select_source (E_SOURCE_SELECTOR (component_view->source_selector), source);
+}
+
+static void
 source_removed_cb (ETasks *tasks, ESource *source, TasksComponentView *component_view)
 {
 	e_source_selector_unselect_source (E_SOURCE_SELECTOR (component_view->source_selector), source);
@@ -894,6 +900,8 @@
 	component_view->model = E_TABLE_MODEL (e_calendar_table_get_model (e_tasks_get_calendar_table (component_view->tasks)));
 
 	/* This signal is thrown if backends die - we update the selector */
+	g_signal_connect (component_view->tasks, "source_added", 
+			  G_CALLBACK (source_added_cb), component_view);
 	g_signal_connect (component_view->tasks, "source_removed", 
 			  G_CALLBACK (source_removed_cb), component_view);
 


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