From e4a68478f7fed9fdf32feae4cca56fb1f4b71411 Mon Sep 17 00:00:00 2001 From: Hans Petter Jansson Date: Thu, 18 Dec 2003 02:41:53 +0000 Subject: Add the concept of a source client, where the object lives currently. The 2003-12-17 Hans Petter Jansson * gui/dialogs/comp-editor.c: Add the concept of a source client, where the object lives currently. The plain client is where it will be stored. (comp_editor_finalize): If we have a source client, disconnect from and unref it. (save_comp): Check if the object is being moved, and if so, remove it from the source client, and make the target client the new source. (comp_editor_append_page): Connect to client_changed signal. (real_set_e_cal): Change an old gtk_signal_disconnect_by_data() to the GLib equivalent, and don't cast ECal to GtkObject. If the source client is not set, make it equivalent to the target client. (page_client_changed_cb): Implement. Handles a client change. * gui/dialogs/comp-editor-page.c (comp_editor_page_class_init): Add a new signal, "client_changed", that notifies that the ECal client was changed from one of the editor pages. (comp_editor_page_set_e_cal): Fix two bugs in this function; if the same client is set twice, its ref count could drop to 0. Additionally, it was unreffing the new client instead of the old one. (comp_editor_page_notify_client_changed): Implement. * gui/dialogs/event-page.c (event_page_fill_widgets): Fill in the source menu. (get_widgets): Get the source menu. (source_changed_cb): Implement. Try to open a client for the new source, and if successful, notify of the change. Show a dialog on failure, and revert to last selected source. (init_widgets): Connect to source menu. (event_page_create_source_option_menu): Implement Glade helper. * gui/dialogs/task-page.c (task_page_fill_widgets): Fill in the source menu. (get_widgets): Get the source menu. (source_changed_cb): Implement, similar to the event page, but for tasks. (init_widgets): Connect to source menu. (task_page_construct): Fix a message booboo. (task_page_create_source_option_menu): Implement Glade helper. * gui/dialogs/event-page.glade: Add source menu widget. * gui/dialogs/task-page.glade: Add source menu widget. svn path=/trunk/; revision=23974 --- calendar/ChangeLog | 45 ++++++++++++++++++++++ calendar/gui/dialogs/comp-editor-page.c | 34 ++++++++++++++++- calendar/gui/dialogs/comp-editor-page.h | 6 ++- calendar/gui/dialogs/comp-editor.c | 55 +++++++++++++++++++++++++- calendar/gui/dialogs/event-page.c | 66 ++++++++++++++++++++++++++++++++ calendar/gui/dialogs/event-page.glade | 36 +++++++++++++++++ calendar/gui/dialogs/task-page.c | 68 ++++++++++++++++++++++++++++++++- calendar/gui/dialogs/task-page.glade | 36 +++++++++++++++++ 8 files changed, 341 insertions(+), 5 deletions(-) diff --git a/calendar/ChangeLog b/calendar/ChangeLog index f1fffca864..a6ad38d047 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,48 @@ +2003-12-17 Hans Petter Jansson + + * gui/dialogs/comp-editor.c: Add the concept of a source client, where + the object lives currently. The plain client is where it will be + stored. + (comp_editor_finalize): If we have a source client, disconnect from + and unref it. + (save_comp): Check if the object is being moved, and if so, remove it + from the source client, and make the target client the new source. + (comp_editor_append_page): Connect to client_changed signal. + (real_set_e_cal): Change an old gtk_signal_disconnect_by_data() to + the GLib equivalent, and don't cast ECal to GtkObject. If the source + client is not set, make it equivalent to the target client. + (page_client_changed_cb): Implement. Handles a client change. + + * gui/dialogs/comp-editor-page.c (comp_editor_page_class_init): Add + a new signal, "client_changed", that notifies that the ECal client + was changed from one of the editor pages. + (comp_editor_page_set_e_cal): Fix two bugs in this function; if the + same client is set twice, its ref count could drop to 0. Additionally, + it was unreffing the new client instead of the old one. + (comp_editor_page_notify_client_changed): Implement. + + * gui/dialogs/event-page.c (event_page_fill_widgets): Fill in the + source menu. + (get_widgets): Get the source menu. + (source_changed_cb): Implement. Try to open a client for the new + source, and if successful, notify of the change. Show a dialog on + failure, and revert to last selected source. + (init_widgets): Connect to source menu. + (event_page_create_source_option_menu): Implement Glade helper. + + * gui/dialogs/task-page.c (task_page_fill_widgets): Fill in the source + menu. + (get_widgets): Get the source menu. + (source_changed_cb): Implement, similar to the event page, but for + tasks. + (init_widgets): Connect to source menu. + (task_page_construct): Fix a message booboo. + (task_page_create_source_option_menu): Implement Glade helper. + + * gui/dialogs/event-page.glade: Add source menu widget. + + * gui/dialogs/task-page.glade: Add source menu widget. + 2003-12-17 Rodrigo Moya * gui/tasks-component.c (add_popup_menu_item): diff --git a/calendar/gui/dialogs/comp-editor-page.c b/calendar/gui/dialogs/comp-editor-page.c index 64771bebed..db51481f62 100644 --- a/calendar/gui/dialogs/comp-editor-page.c +++ b/calendar/gui/dialogs/comp-editor-page.c @@ -43,6 +43,7 @@ enum { NEEDS_SEND, SUMMARY_CHANGED, DATES_CHANGED, + CLIENT_CHANGED, LAST_SIGNAL }; @@ -131,6 +132,15 @@ comp_editor_page_class_init (CompEditorPageClass *class) g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); + comp_editor_page_signals[CLIENT_CHANGED] = + g_signal_new ("client_changed", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CompEditorPageClass, client_changed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, G_TYPE_OBJECT); + class->changed = NULL; class->summary_changed = NULL; class->dates_changed = NULL; @@ -272,8 +282,11 @@ comp_editor_page_set_e_cal (CompEditorPage *page, ECal *client) g_return_if_fail (page != NULL); g_return_if_fail (IS_COMP_EDITOR_PAGE (page)); + if (client == page->client) + return; + if (page->client) - g_object_unref (client); + g_object_unref (page->client); page->client = client; if (page->client) @@ -384,6 +397,25 @@ comp_editor_page_notify_dates_changed (CompEditorPage *page, dates); } +/** + * comp_editor_page_notify_client_changed: + * @page: An editor page. + * + * Makes an editor page emit the "client_changed" signal. This is meant to be + * used only by page implementations. + **/ +void +comp_editor_page_notify_client_changed (CompEditorPage *page, + ECal *client) +{ + g_return_if_fail (page != NULL); + g_return_if_fail (IS_COMP_EDITOR_PAGE (page)); + + gtk_signal_emit (GTK_OBJECT (page), + comp_editor_page_signals[CLIENT_CHANGED], + client); +} + /** * comp_editor_page_display_validation_error: * @page: An editor page. diff --git a/calendar/gui/dialogs/comp-editor-page.h b/calendar/gui/dialogs/comp-editor-page.h index 6046a7c039..84d7d9d196 100644 --- a/calendar/gui/dialogs/comp-editor-page.h +++ b/calendar/gui/dialogs/comp-editor-page.h @@ -46,7 +46,8 @@ typedef struct { typedef struct { GtkObject object; - /* Some of the pages need the ECal to access timezone data. */ + /* Some of the pages need the ECal to access timezone data. Also, + * the event page needs to know it to fill the source option menu. */ ECal *client; /* The GtkAccelGroup for the page. We install this when the page is @@ -66,6 +67,7 @@ typedef struct { void (* summary_changed) (CompEditorPage *page, const char *summary); void (* dates_changed) (CompEditorPage *page, const char *dates); + void (* client_changed) (CompEditorPage *page, ECal *client); /* Virtual methods */ @@ -99,6 +101,8 @@ void comp_editor_page_notify_summary_changed (CompEditorPage *page, const char *summary); void comp_editor_page_notify_dates_changed (CompEditorPage *page, CompEditorPageDates *dates); +void comp_editor_page_notify_client_changed (CompEditorPage *page, + ECal *client); void comp_editor_page_display_validation_error (CompEditorPage *page, const char *msg, GtkWidget *field); diff --git a/calendar/gui/dialogs/comp-editor.c b/calendar/gui/dialogs/comp-editor.c index cd270eb423..4e4a9da7c2 100644 --- a/calendar/gui/dialogs/comp-editor.c +++ b/calendar/gui/dialogs/comp-editor.c @@ -56,6 +56,9 @@ struct _CompEditorPrivate { /* Client to use */ ECal *client; + /* Source client (where comp lives currently) */ + ECal *source_client; + /* Calendar object/uid we are editing; this is an internal copy */ ECalComponent *comp; @@ -100,6 +103,7 @@ static void close_dialog (CompEditor *editor); static void page_changed_cb (GtkObject *obj, gpointer data); static void page_summary_changed_cb (GtkObject *obj, const char *summary, gpointer data); static void page_dates_changed_cb (GtkObject *obj, CompEditorPageDates *dates, gpointer data); +static void page_client_changed_cb (GtkObject *obj, ECal *client, gpointer data); static void obj_updated_cb (ECal *client, const char *uid, gpointer data); static void obj_removed_cb (ECal *client, const char *uid, gpointer data); @@ -268,6 +272,12 @@ comp_editor_finalize (GObject *object) priv->client = NULL; } + if (priv->source_client) { + g_signal_handlers_disconnect_matched (priv->source_client, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, editor); + g_object_unref (priv->source_client); + priv->source_client = NULL; + } + /* We want to destroy the pages after the widgets get destroyed, since they have lots of signal handlers connected to the widgets with the pages as the data. */ @@ -296,6 +306,7 @@ save_comp (CompEditor *editor) GList *l; gboolean result; GError *error = NULL; + const char *orig_uid; priv = editor->priv; @@ -322,6 +333,8 @@ save_comp (CompEditor *editor) priv->updating = TRUE; + e_cal_component_get_uid (priv->comp, &orig_uid); + if (!cal_comp_is_on_server (priv->comp, priv->client)) { result = e_cal_create_object (priv->client, e_cal_component_get_icalcomponent (priv->comp), NULL, &error); } else { @@ -343,6 +356,23 @@ save_comp (CompEditor *editor) return FALSE; } else { + if (priv->source_client && + !e_source_equal (e_cal_get_source (priv->client), + e_cal_get_source (priv->source_client)) && + cal_comp_is_on_server (priv->comp, priv->source_client)) { + /* Comp found a new home. Remove it from old one. */ + e_cal_remove_object (priv->source_client, orig_uid, NULL); + + /* Let priv->source_client point to new home, so we can move it + * again this session. */ + g_signal_handlers_disconnect_matched (priv->source_client, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, editor); + g_object_unref (priv->source_client); + + priv->source_client = priv->client; + g_object_ref (priv->source_client); + } + priv->changed = FALSE; } @@ -654,6 +684,8 @@ comp_editor_append_page (CompEditor *editor, G_CALLBACK (page_summary_changed_cb), editor); g_signal_connect(page, "dates_changed", G_CALLBACK (page_dates_changed_cb), editor); + g_signal_connect(page, "client_changed", + G_CALLBACK (page_client_changed_cb), editor); /* Listen for when the page is mapped/unmapped so we can install/uninstall the appropriate GtkAccelGroup. */ @@ -938,13 +970,20 @@ real_set_e_cal (CompEditor *editor, ECal *client) } if (priv->client) { - gtk_signal_disconnect_by_data (GTK_OBJECT (priv->client), - editor); + g_signal_handlers_disconnect_matched (G_OBJECT (priv->client), + G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, + editor); g_object_unref (priv->client); } priv->client = client; + if (!priv->source_client) { + priv->source_client = client; + g_object_ref (client); + } + /* Pass the client to any pages that need it. */ for (elem = priv->pages; elem; elem = elem->next) comp_editor_page_set_e_cal (elem->data, client); @@ -1429,6 +1468,18 @@ page_dates_changed_cb (GtkObject *obj, } } +static void +page_client_changed_cb (GtkObject *obj, ECal *client, gpointer data) +{ + CompEditor *editor = COMP_EDITOR (data); + CompEditorPrivate *priv; + + priv = editor->priv; + + priv->changed = TRUE; + comp_editor_set_e_cal (editor, client); +} + static void obj_updated_cb (ECal *client, const char *uid, gpointer data) { diff --git a/calendar/gui/dialogs/event-page.c b/calendar/gui/dialogs/event-page.c index c943825c84..99a49f33a6 100644 --- a/calendar/gui/dialogs/event-page.c +++ b/calendar/gui/dialogs/event-page.c @@ -29,12 +29,14 @@ #include #include #include +#include #include #include #include #include "e-util/e-categories-config.h" #include "e-util/e-dialog-widgets.h" #include "widgets/misc/e-dateedit.h" +#include "widgets/misc/e-source-option-menu.h" #include #include "../calendar-config.h" #include "../e-timezone-entry.h" @@ -74,6 +76,8 @@ struct _EventPagePrivate { GtkWidget *categories_btn; GtkWidget *categories; + GtkWidget *source_selector; + gboolean updating; /* This is TRUE if both the start & end timezone are the same. If the @@ -417,6 +421,7 @@ event_page_fill_widgets (CompEditorPage *page, ECalComponent *comp) ECalComponentDateTime start_date, end_date; const char *location; const char *categories; + ESource *source; GSList *l; g_return_if_fail (page->client != NULL); @@ -512,6 +517,10 @@ event_page_fill_widgets (CompEditorPage *page, ECalComponent *comp) e_cal_component_get_categories (comp, &categories); e_dialog_editable_set (priv->categories, categories); + /* Source */ + source = e_cal_get_source (page->client); + e_source_option_menu_select (E_SOURCE_OPTION_MENU (priv->source_selector), source); + priv->updating = FALSE; } @@ -749,6 +758,8 @@ get_widgets (EventPage *epage) priv->categories_btn = GW ("categories-button"); priv->categories = GW ("categories"); + priv->source_selector = GW ("source"); + #undef GW return (priv->summary @@ -1189,6 +1200,40 @@ field_changed_cb (GtkWidget *widget, gpointer data) comp_editor_page_notify_changed (COMP_EDITOR_PAGE (epage)); } +static void +source_changed_cb (GtkWidget *widget, ESource *source, gpointer data) +{ + EventPage *epage; + EventPagePrivate *priv; + + epage = EVENT_PAGE (data); + priv = epage->priv; + + if (!priv->updating) { + ECal *client; + + client = e_cal_new (source, CALOBJ_TYPE_EVENT); + if (!client || !e_cal_open (client, FALSE, NULL)) { + GtkWidget *dialog; + + if (client) + g_object_unref (client); + + e_source_option_menu_select (E_SOURCE_OPTION_MENU (priv->source_selector), + e_cal_get_source (COMP_EDITOR_PAGE (epage)->client)); + + dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, + GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, + _("Unable to open the calendar '%s'."), + e_source_peek_name (source)); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + } else { + comp_editor_page_notify_client_changed (COMP_EDITOR_PAGE (epage), client); + } + } +} + /* Hooks the widget signals */ static gboolean init_widgets (EventPage *epage) @@ -1277,6 +1322,8 @@ init_widgets (EventPage *epage) epage); g_signal_connect((priv->categories), "changed", G_CALLBACK (field_changed_cb), epage); + g_signal_connect((priv->source_selector), "source_selected", + G_CALLBACK (source_changed_cb), epage); /* Set the default timezone, so the timezone entry may be hidden. */ location = calendar_config_get_timezone (); @@ -1369,3 +1416,22 @@ make_timezone_entry (void) gtk_widget_show (w); return w; } + +GtkWidget *event_page_create_source_option_menu (void); + +GtkWidget * +event_page_create_source_option_menu (void) +{ + GtkWidget *menu; + GConfClient *gconf_client; + ESourceList *source_list; + + gconf_client = gconf_client_get_default (); + source_list = e_source_list_new_for_gconf (gconf_client, "/apps/evolution/calendar/sources"); + + menu = e_source_option_menu_new (source_list); + g_object_unref (source_list); + + gtk_widget_show (menu); + return menu; +} diff --git a/calendar/gui/dialogs/event-page.glade b/calendar/gui/dialogs/event-page.glade index b59eb61e86..46e1cc0bb0 100644 --- a/calendar/gui/dialogs/event-page.glade +++ b/calendar/gui/dialogs/event-page.glade @@ -587,6 +587,42 @@ True + + + + True + Calendar: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + event_page_create_source_option_menu + 0 + 0 + Wed, 17 Dec 2003 18:20:26 GMT + + + 0 + False + True + + 0 diff --git a/calendar/gui/dialogs/task-page.c b/calendar/gui/dialogs/task-page.c index 830e5a0bef..1ff2cd608d 100644 --- a/calendar/gui/dialogs/task-page.c +++ b/calendar/gui/dialogs/task-page.c @@ -31,10 +31,12 @@ #include #include #include +#include #include #include #include #include +#include "widgets/misc/e-source-option-menu.h" #include "e-util/e-dialog-widgets.h" #include "e-util/e-categories-config.h" #include "../e-timezone-entry.h" @@ -68,6 +70,8 @@ struct _TaskPagePrivate { GtkWidget *categories_btn; GtkWidget *categories; + GtkWidget *source_selector; + gboolean updating; }; @@ -256,6 +260,7 @@ task_page_fill_widgets (CompEditorPage *page, ECalComponent *comp) const char *categories; icaltimezone *zone, *default_zone; char *location; + ESource *source; tpage = TASK_PAGE (page); priv = tpage->priv; @@ -399,6 +404,9 @@ task_page_fill_widgets (CompEditorPage *page, ECalComponent *comp) e_cal_component_get_categories (comp, &categories); e_dialog_editable_set (priv->categories, categories); + /* Source */ + source = e_cal_get_source (page->client); + e_source_option_menu_select (E_SOURCE_OPTION_MENU (priv->source_selector), source); priv->updating = FALSE; } @@ -634,6 +642,8 @@ get_widgets (TaskPage *tpage) priv->categories_btn = GW ("categories-button"); priv->categories = GW ("categories"); + priv->source_selector = GW ("source"); + #undef GW return (priv->summary @@ -772,6 +782,40 @@ field_changed_cb (GtkWidget *widget, gpointer data) comp_editor_page_notify_changed (COMP_EDITOR_PAGE (tpage)); } +static void +source_changed_cb (GtkWidget *widget, ESource *source, gpointer data) +{ + TaskPage *epage; + TaskPagePrivate *priv; + + epage = TASK_PAGE (data); + priv = epage->priv; + + if (!priv->updating) { + ECal *client; + + client = e_cal_new (source, CALOBJ_TYPE_TODO); + if (!client || !e_cal_open (client, FALSE, NULL)) { + GtkWidget *dialog; + + if (client) + g_object_unref (client); + + e_source_option_menu_select (E_SOURCE_OPTION_MENU (priv->source_selector), + e_cal_get_source (COMP_EDITOR_PAGE (epage)->client)); + + dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, + GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, + _("Unable to open tasks in '%s'."), + e_source_peek_name (source)); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + } else { + comp_editor_page_notify_client_changed (COMP_EDITOR_PAGE (epage), client); + } + } +} + /* Hooks the widget signals */ static gboolean init_widgets (TaskPage *tpage) @@ -839,6 +883,9 @@ init_widgets (TaskPage *tpage) g_signal_connect((priv->categories_btn), "clicked", G_CALLBACK (categories_clicked_cb), tpage); + /* Source selector */ + g_signal_connect((priv->source_selector), "source_selected", + G_CALLBACK (source_changed_cb), tpage); /* Set the default timezone, so the timezone entry may be hidden. */ location = calendar_config_get_timezone (); @@ -882,7 +929,7 @@ task_page_construct (TaskPage *tpage) } if (!init_widgets (tpage)) { - g_message ("event_page_construct(): " + g_message ("task_page_construct(): " "Could not initialize the widgets!"); return NULL; } @@ -924,3 +971,22 @@ task_page_create_date_edit (void) return dedit; } + +GtkWidget *task_page_create_source_option_menu (void); + +GtkWidget * +task_page_create_source_option_menu (void) +{ + GtkWidget *menu; + GConfClient *gconf_client; + ESourceList *source_list; + + gconf_client = gconf_client_get_default (); + source_list = e_source_list_new_for_gconf (gconf_client, "/apps/evolution/tasks/sources"); + + menu = e_source_option_menu_new (source_list); + g_object_unref (source_list); + + gtk_widget_show (menu); + return menu; +} diff --git a/calendar/gui/dialogs/task-page.glade b/calendar/gui/dialogs/task-page.glade index 02a8797b45..49f91b1c98 100644 --- a/calendar/gui/dialogs/task-page.glade +++ b/calendar/gui/dialogs/task-page.glade @@ -463,6 +463,42 @@ True + + + + True + Folder: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + task_page_create_source_option_menu + 0 + 0 + Thu, 18 Dec 2003 01:58:48 GMT + + + 0 + False + True + + 0 -- cgit v1.2.3