aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--calendar/ChangeLog76
-rw-r--r--calendar/gui/calendar-component.c14
-rw-r--r--calendar/gui/e-cal-model.c121
-rw-r--r--calendar/gui/e-cal-model.h1
-rw-r--r--calendar/gui/e-calendar-table.c23
-rw-r--r--calendar/gui/e-calendar-table.h3
-rw-r--r--calendar/gui/e-calendar-view.c29
-rw-r--r--calendar/gui/e-calendar-view.h1
-rw-r--r--calendar/gui/e-day-view.c2
-rw-r--r--calendar/gui/e-tasks.c151
-rw-r--r--calendar/gui/e-week-view.c2
-rw-r--r--calendar/gui/gnome-cal.c168
-rw-r--r--calendar/gui/tasks-component.c8
13 files changed, 500 insertions, 99 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index cedee40fee..1fc42d2410 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -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-08 Radek Doulik <rodo@ximian.com>
* gui/e-cal-model.c (e_cal_model_date_value_to_string): as below
diff --git a/calendar/gui/calendar-component.c b/calendar/gui/calendar-component.c
index 6b84eac36f..51b6402eb4 100644
--- a/calendar/gui/calendar-component.c
+++ b/calendar/gui/calendar-component.c
@@ -444,6 +444,18 @@ primary_source_selection_changed_cb (ESourceSelector *selector, CalendarComponen
}
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 @@ create_component_view (CalendarComponent *calendar_component)
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);
diff --git a/calendar/gui/e-cal-model.c b/calendar/gui/e-cal-model.c
index c2d4fc57ad..ebba86d864 100644
--- a/calendar/gui/e-cal-model.c
+++ b/calendar/gui/e-cal-model.c
@@ -34,6 +34,8 @@
typedef struct {
ECal *client;
ECalView *query;
+
+ gboolean do_query;
} ECalModelClient;
struct _ECalModelPrivate {
@@ -88,9 +90,15 @@ static char *ecm_value_to_string (ETableModel *etm, int col, const void *value);
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 @@ e_cal_model_class_init (ECalModelClass *klass)
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 @@ ecm_append_row (ETableModel *etm, ETableModel *source, int row)
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 @@ e_cal_model_get_default_client (ECalModel *model)
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 @@ void
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 @@ e_cal_model_set_default_client (ECalModel *model, ECal *client)
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 @@ update_e_cal_view_for_client (ECalModel *model, ECalModelClient *client_data)
/* 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 @@ cal_opened_cb (ECal *client, ECalendarStatus status, gpointer user_data)
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 @@ e_cal_model_add_client (ECalModel *model, ECal *client)
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 @@ remove_client (ECalModel *model, ECalModelClient *client_data)
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)
diff --git a/calendar/gui/e-cal-model.h b/calendar/gui/e-cal-model.h
index aef2e3d539..846d7b4acd 100644
--- a/calendar/gui/e-cal-model.h
+++ b/calendar/gui/e-cal-model.h
@@ -84,6 +84,7 @@ typedef struct {
/* 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);
diff --git a/calendar/gui/e-calendar-table.c b/calendar/gui/e-calendar-table.c
index c3044195fe..a0688fa8b5 100644
--- a/calendar/gui/e-calendar-table.c
+++ b/calendar/gui/e-calendar-table.c
@@ -104,6 +104,13 @@ static void mark_row_complete_cb (int model_row, gpointer data);
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 @@ e_calendar_table_class_init (ECalendarTableClass *class)
/* 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 @@ priority_compare_cb (gconstpointer a, gconstpointer b)
}
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 @@ e_calendar_table_init (ECalendarTable *cal_table)
/* 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 */
diff --git a/calendar/gui/e-calendar-table.h b/calendar/gui/e-calendar-table.h
index c69c95d56e..fc7afe5d4c 100644
--- a/calendar/gui/e-calendar-table.h
+++ b/calendar/gui/e-calendar-table.h
@@ -68,6 +68,9 @@ struct _ECalendarTable {
struct _ECalendarTableClass {
GtkTableClass parent_class;
+
+ /* Notification signals */
+ void (* user_created) (ECalendarTable *cal_table);
};
diff --git a/calendar/gui/e-calendar-view.c b/calendar/gui/e-calendar-view.c
index 2150ca0993..00cce026b4 100644
--- a/calendar/gui/e-calendar-view.c
+++ b/calendar/gui/e-calendar-view.c
@@ -103,6 +103,7 @@ enum {
TIMEZONE_CHANGED,
EVENT_CHANGED,
EVENT_ADDED,
+ USER_CREATED,
OPEN_EVENT,
LAST_SIGNAL
};
@@ -166,6 +167,7 @@ e_calendar_view_class_init (ECalendarViewClass *klass)
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 @@ e_calendar_view_class_init (ECalendarViewClass *klass)
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),
@@ -233,6 +226,24 @@ e_calendar_view_class_init (ECalendarViewClass *klass)
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)
clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE);
diff --git a/calendar/gui/e-calendar-view.h b/calendar/gui/e-calendar-view.h
index 8ee125e1d2..724833c1a4 100644
--- a/calendar/gui/e-calendar-view.h
+++ b/calendar/gui/e-calendar-view.h
@@ -87,6 +87,7 @@ struct _ECalendarViewClass {
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 */
diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c
index 30232e7279..0be9d6f4ca 100644
--- a/calendar/gui/e-day-view.c
+++ b/calendar/gui/e-day-view.c
@@ -6049,6 +6049,8 @@ e_day_view_on_editing_stopped (EDayView *day_view,
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;
diff --git a/calendar/gui/e-tasks.c b/calendar/gui/e-tasks.c
index 9f83428228..a935f09863 100644
--- a/calendar/gui/e-tasks.c
+++ b/calendar/gui/e-tasks.c
@@ -61,6 +61,7 @@ struct _ETasksPrivate {
/* The task lists for display */
GHashTable *clients;
GList *clients_list;
+ ECal *default_client;
ECalView *query;
@@ -88,7 +89,6 @@ struct _ETasksPrivate {
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 @@ table_selection_change_cb (ETable *etable, gpointer data)
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 @@ set_timezone (ETasks *tasks)
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 @@ setup_widgets (ETasks *tasks)
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 @@ setup_widgets (ETasks *tasks)
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 @@ e_tasks_destroy (GtkObject *object)
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 @@ client_cal_opened_cb (ECal *ecal, ECalendarStatus status, ETasks *tasks)
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 @@ client_cal_opened_cb (ECal *ecal, ECalendarStatus status, ETasks *tasks)
}
}
+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 @@ e_tasks_add_todo_source (ETasks *tasks, ESource *source)
{
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 @@ e_tasks_add_todo_source (ETasks *tasks, ESource *source)
uid = e_source_peek_uid (source);
client = g_hash_table_lookup (priv->clients, uid);
- if (client)
- return TRUE;
-
+ if (client) {
+ /* We already have it */
- /* 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);
+ 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);
+ }
- 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 @@ e_tasks_set_default_source (ETasks *tasks, ESource *source)
{
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 @@ e_tasks_set_default_source (ETasks *tasks, ESource *source)
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;
}
diff --git a/calendar/gui/e-week-view.c b/calendar/gui/e-week-view.c
index 7affe611b6..6efaac9529 100644
--- a/calendar/gui/e-week-view.c
+++ b/calendar/gui/e-week-view.c
@@ -3333,6 +3333,8 @@ e_week_view_on_editing_stopped (EWeekView *week_view,
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;
diff --git a/calendar/gui/gnome-cal.c b/calendar/gui/gnome-cal.c
index 034c0be1bd..cbddfcbf4c 100644
--- a/calendar/gui/gnome-cal.c
+++ b/calendar/gui/gnome-cal.c
@@ -91,6 +91,7 @@ struct _GnomeCalendarPrivate {
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 @@ view_selection_changed_cb (GtkWidget *view, GnomeCalendar *gcal)
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 @@ set_timezone (GnomeCalendar *calendar)
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 @@ setup_widgets (GnomeCalendar *gcal)
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 @@ gnome_calendar_destroy (GtkObject *object)
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 @@ client_cal_opened_cb (ECal *ecal, ECalendarStatus status, GnomeCalendar *gcal)
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 @@ client_cal_opened_cb (ECal *ecal, ECalendarStatus status, GnomeCalendar *gcal)
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 @@ client_cal_opened_cb (ECal *ecal, ECalendarStatus status, GnomeCalendar *gcal)
}
}
+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 @@ open_ecal (GnomeCalendar *gcal, ECal *cal, gboolean only_if_exists)
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 @@ backend_died_cb (ECal *ecal, gpointer data)
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 @@ gnome_calendar_add_source (GnomeCalendar *gcal, ECalSourceType source_type, ESou
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 @@ gnome_calendar_add_source (GnomeCalendar *gcal, ECalSourceType source_type, ESou
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 @@ gnome_calendar_set_default_source (GnomeCalendar *gcal, ECalSourceType source_ty
{
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 @@ gnome_calendar_set_default_source (GnomeCalendar *gcal, ECalSourceType source_ty
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;
}
diff --git a/calendar/gui/tasks-component.c b/calendar/gui/tasks-component.c
index 1fa67ed6b7..dc87020592 100644
--- a/calendar/gui/tasks-component.c
+++ b/calendar/gui/tasks-component.c
@@ -391,6 +391,12 @@ primary_source_selection_changed_cb (ESourceSelector *selector, TasksComponentVi
}
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 @@ create_component_view (TasksComponent *tasks_component)
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);