From 79efc40b19f513570d800d2b3fa6293ea794a28d Mon Sep 17 00:00:00 2001 From: Chenthill Palanisamy Date: Mon, 14 Nov 2005 18:19:13 +0000 Subject: UI changes for the event editor. svn path=/trunk/; revision=30613 --- calendar/gui/dialogs/Makefile.am | 2 + calendar/gui/dialogs/comp-editor.c | 277 ++++-- calendar/gui/dialogs/comp-editor.h | 11 +- calendar/gui/dialogs/event-editor.c | 547 +++++++++-- calendar/gui/dialogs/event-page.c | 1613 +++++++++++++++++++++++++-------- calendar/gui/dialogs/event-page.glade | 1060 +++++++++++++--------- calendar/gui/dialogs/event-page.h | 28 +- calendar/gui/dialogs/memo-editor.c | 2 +- calendar/gui/dialogs/schedule-page.c | 1 + calendar/gui/dialogs/task-editor.c | 10 +- 10 files changed, 2535 insertions(+), 1016 deletions(-) (limited to 'calendar/gui/dialogs') diff --git a/calendar/gui/dialogs/Makefile.am b/calendar/gui/dialogs/Makefile.am index b38b6223a2..f26320e597 100644 --- a/calendar/gui/dialogs/Makefile.am +++ b/calendar/gui/dialogs/Makefile.am @@ -8,6 +8,8 @@ INCLUDES = \ -I$(top_srcdir)/shell \ -I$(top_srcdir)/widgets/misc \ -DEVOLUTION_GLADEDIR=\""$(gladedir)"\" \ + -DEVOLUTION_UIDIR=\""$(evolutionuidir)"\" \ + -DPREFIX=\""$(prefix)"\" \ $(EVOLUTION_CALENDAR_CFLAGS) noinst_LTLIBRARIES = libcal-dialogs.la diff --git a/calendar/gui/dialogs/comp-editor.c b/calendar/gui/dialogs/comp-editor.c index e205bd5c68..b1e9f69f84 100644 --- a/calendar/gui/dialogs/comp-editor.c +++ b/calendar/gui/dialogs/comp-editor.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include #include @@ -143,7 +145,7 @@ static void obj_modified_cb (ECal *client, GList *objs, gpointer data); static void obj_removed_cb (ECal *client, GList *uids, gpointer data); static gboolean open_attachment (EAttachmentBar *bar, CompEditor *editor); -G_DEFINE_TYPE (CompEditor, comp_editor, GTK_TYPE_DIALOG); +G_DEFINE_TYPE (CompEditor, comp_editor, BONOBO_TYPE_WINDOW); enum { DND_TYPE_MESSAGE_RFC822, @@ -882,73 +884,6 @@ prompt_to_save_changes (CompEditor *editor, gboolean send) } } -static void -response_cb (GtkWidget *widget, int response, gpointer data) -{ - CompEditor *editor = COMP_EDITOR (data); - CompEditorPrivate *priv; - ECalComponentText text; - gboolean delegated; - ECalComponent *comp; - - priv = editor->priv; - delegated = (priv->flags & COMP_EDITOR_DELEGATE); - - switch (response) { - case GTK_RESPONSE_OK: - /* Check whether the downloads are completed */ - if (e_attachment_bar_get_download_count (E_ATTACHMENT_BAR (editor->priv->attachment_bar)) ){ - gboolean response = 1; -#warning "FIXME: Cannot use mail functions from calendar!!!!" -#if 0 - ECalComponentVType vtype = e_cal_component_get_vtype(editor->priv->comp); - - if (vtype == E_CAL_COMPONENT_EVENT) - response = em_utils_prompt_user((GtkWindow *)widget, - NULL, - "calendar:ask-send-event-pending-download", - NULL); - else - response = em_utils_prompt_user((GtkWindow *)widget, - NULL, - "calendar:ask-send-task-pending-download", - NULL); -#endif - if (!response) - return; - } - commit_all_fields (editor); - if (e_cal_component_is_instance (priv->comp)) - if (!recur_component_dialog (priv->client, priv->comp, &priv->mod, GTK_WINDOW (editor), delegated)) - return; - - comp = comp_editor_get_current_comp (editor); - e_cal_component_get_summary (comp, &text); - g_object_unref (comp); - - if (!text.value) - if (!send_component_prompt_subject ((GtkWindow *) editor, priv->client, priv->comp)) - return; - if (save_comp_with_send (editor)) - close_dialog (editor); - break; - - case GTK_RESPONSE_HELP: - comp_editor_show_help (editor); - - break; - case GTK_RESPONSE_CANCEL: - commit_all_fields (editor); - - if (prompt_to_save_changes (editor, TRUE)) - close_dialog (editor); - break; - default: - /* We handle delete event below */ - break; - } -} - static int delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer data) { @@ -1233,6 +1168,152 @@ key_press_event(GtkWidget *widget, GdkEventKey *event) return FALSE; } +/* Menu callbacks */ +static void +menu_file_save_cb (BonoboUIComponent *uic, + void *data, + const char *path) +{ + CompEditor *editor = (CompEditor *) data; + CompEditorPrivate *priv = editor->priv; + ECalComponentText text; + gboolean delegated; + ECalComponent *comp; + + if (e_attachment_bar_get_download_count (E_ATTACHMENT_BAR (editor->priv->attachment_bar)) ){ + gboolean response = 1; + /*FIXME: Cannot use mail functions from calendar!!!! */ +#if 0 + ECalComponentVType vtype = e_cal_component_get_vtype(editor->priv->comp); + + if (vtype == E_CAL_COMPONENT_EVENT) + response = em_utils_prompt_user((GtkWindow *)widget, + NULL, + "calendar:ask-send-event-pending-download", + NULL); + else + response = em_utils_prompt_user((GtkWindow *)widget, + NULL, + "calendar:ask-send-task-pending-download", + NULL); +#endif + if (!response) + return; + } + commit_all_fields (editor); + if (e_cal_component_is_instance (priv->comp)) + if (!recur_component_dialog (priv->client, priv->comp, &priv->mod, GTK_WINDOW (editor), delegated)) + return; + + comp = comp_editor_get_current_comp (editor); + e_cal_component_get_summary (comp, &text); + g_object_unref (comp); + + if (!text.value) + if (!send_component_prompt_subject ((GtkWindow *) editor, priv->client, priv->comp)) + return; + if (save_comp_with_send (editor)) + close_dialog (editor); + +} + +static void +menu_file_close_cb (BonoboUIComponent *uic, + void *data, + const char *path) +{ + CompEditor *editor = (CompEditor *) data; + commit_all_fields (editor); + + if (prompt_to_save_changes (editor, TRUE)) + close_dialog (editor); +} + +static void +menu_edit_copy_cb (BonoboUIComponent *uic, + void *data, + const char *path) +{ + /*TODO Implement the function + CompEditor *editor = (CompEditor *) data; */ + +} + +static void +menu_edit_paste_cb (BonoboUIComponent *uic, + void *data, + const char *path) +{ + /*TODO Implement the function + CompEditor *editor = (CompEditor *) data; */ + +} + +static void +menu_edit_cut_cb (BonoboUIComponent *uic, + void *data, + const char *path) +{ + /*TODO Implement the function + CompEditor *editor = (CompEditor *) data; */ + +} + +static void +menu_insert_attachment_cb (BonoboUIComponent *uic, + void *data, + const char *path) +{ + CompEditor *editor = (CompEditor *) data; + EAttachmentBar *bar = (EAttachmentBar *)editor->priv->attachment_bar; + GPtrArray *file_list; + gboolean is_inline = FALSE; + int i; + + file_list = comp_editor_select_file_attachments (editor, &is_inline); + /*TODO add a good implementation here */ + if (!file_list) + return; + for (i = 0; i < file_list->len; i++) { + e_attachment_bar_attach (bar, file_list->pdata[i], is_inline ? "inline" : "attachment"); + g_free (file_list->pdata[i]); + } + + g_ptr_array_free (file_list, TRUE); +} + +static void +menu_help_cb (BonoboUIComponent *uic, + void *data, + const char *path) +{ + CompEditor *editor = (CompEditor *) data; + + comp_editor_show_help (editor); +} + +static BonoboUIVerb verbs [] = { + + BONOBO_UI_VERB ("FileSave", menu_file_save_cb), + BONOBO_UI_VERB ("FileClose", menu_file_close_cb), + + BONOBO_UI_VERB ("EditCopy", menu_edit_copy_cb), + BONOBO_UI_VERB ("EditPaste", menu_edit_paste_cb), + BONOBO_UI_VERB ("EditCut", menu_edit_cut_cb), + + BONOBO_UI_VERB ("InsertAttachments", menu_insert_attachment_cb), + + BONOBO_UI_VERB ("Help", menu_help_cb), + + BONOBO_UI_VERB_END +}; + +static EPixmap pixmaps[] = { + E_PIXMAP ("/Toolbar/InsertAttachments", "stock_attach", E_ICON_SIZE_LARGE_TOOLBAR), + + E_PIXMAP_END +}; + /* Creates the basic in the editor */ static void setup_widgets (CompEditor *editor) @@ -1244,9 +1325,8 @@ setup_widgets (CompEditor *editor) priv = editor->priv; /* Useful vbox */ - vbox = gtk_vbox_new (FALSE, 12); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 12); - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (editor)->vbox), vbox, TRUE, TRUE, 0); + vbox = gtk_vbox_new (FALSE, 0); + bonobo_window_set_contents (BONOBO_WINDOW (editor), vbox); gtk_widget_show (vbox); /* Notebook */ @@ -1254,14 +1334,8 @@ setup_widgets (CompEditor *editor) gtk_widget_show (GTK_WIDGET (priv->notebook)); gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (priv->notebook), TRUE, TRUE, 0); + gtk_notebook_set_show_tabs (priv->notebook, FALSE); - /* Buttons */ - gtk_dialog_add_button (GTK_DIALOG (editor), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); - gtk_dialog_add_button (GTK_DIALOG (editor), GTK_STOCK_OK, GTK_RESPONSE_OK); - gtk_dialog_add_button (GTK_DIALOG (editor), GTK_STOCK_HELP, GTK_RESPONSE_HELP); - gtk_dialog_set_response_sensitive (GTK_DIALOG (editor), GTK_RESPONSE_OK, FALSE); - - g_signal_connect (editor, "response", G_CALLBACK (response_cb), editor); g_signal_connect (editor, "delete_event", G_CALLBACK (delete_event_cb), editor); /*Attachments */ @@ -1325,6 +1399,7 @@ static void comp_editor_init (CompEditor *editor) { CompEditorPrivate *priv; + BonoboUIContainer *container; priv = g_new0 (CompEditorPrivate, 1); editor->priv = priv; @@ -1341,17 +1416,29 @@ comp_editor_init (CompEditor *editor) priv->is_group_item = FALSE; priv->help_section = g_strdup ("usage-calendar"); + container = bonobo_window_get_ui_container (BONOBO_WINDOW (editor)); + editor->uic = bonobo_ui_component_new_default (); + /* FIXME: handle bonobo exceptions */ + bonobo_ui_component_set_container (editor->uic, bonobo_object_corba_objref (BONOBO_OBJECT (container)), NULL); + + bonobo_ui_component_add_verb_list_with_data (editor->uic, verbs, editor); + + bonobo_ui_component_freeze (editor->uic, NULL); + + bonobo_ui_util_set_ui (editor->uic, PREFIX, + EVOLUTION_UIDIR "/evolution-editor.xml", + "evolution-editor", NULL); + e_pixmaps_update (editor->uic, pixmaps); + bonobo_ui_component_thaw (editor->uic, NULL); + + bonobo_ui_component_set_prop (editor->uic, "/commands/FileSave", "sensitive", "0", NULL); + /* DND support */ gtk_drag_dest_set (GTK_WIDGET (editor), GTK_DEST_DEFAULT_ALL, drop_types, num_drop_types, GDK_ACTION_COPY|GDK_ACTION_ASK|GDK_ACTION_MOVE); g_signal_connect(editor, "drag_data_received", G_CALLBACK (drag_data_received), NULL); g_signal_connect(editor, "drag-motion", G_CALLBACK(drag_motion), editor); gtk_window_set_type_hint (GTK_WINDOW (editor), GDK_WINDOW_TYPE_HINT_NORMAL); - gtk_dialog_set_has_separator (GTK_DIALOG (editor), FALSE); - - gtk_widget_ensure_style (GTK_WIDGET (editor)); - gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (editor)->vbox), 0); - gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (editor)->action_area), 12); } @@ -1572,8 +1659,8 @@ comp_editor_set_changed (CompEditor *editor, gboolean changed) priv->changed = changed; - gtk_dialog_set_response_sensitive (GTK_DIALOG (editor), GTK_RESPONSE_OK, changed); - gtk_dialog_set_default_response (GTK_DIALOG (editor), GTK_RESPONSE_OK); + bonobo_ui_component_set_prop (editor->uic, "/commands/FileSave", "sensitive", changed ? "1" : "0" + , NULL); } /** @@ -1694,14 +1781,17 @@ static void page_unmapped_cb (GtkWidget *page_widget, * comp_editor_append_page: * @editor: A component editor * @page: A component editor page - * @label: Label of the page + * @label: Label of the page. Should be NULL if add is FALSE. + * @add: Add's the page into the notebook if TRUE * - * Appends a page to the editor notebook with the given label + * Appends a page to the notebook if add is TRUE else + * just adds it to the list of pages. **/ void comp_editor_append_page (CompEditor *editor, CompEditorPage *page, - const char *label) + const char *label, + gboolean add) { CompEditorPrivate *priv; GtkWidget *page_widget; @@ -1712,7 +1802,6 @@ comp_editor_append_page (CompEditor *editor, g_return_if_fail (IS_COMP_EDITOR (editor)); g_return_if_fail (page != NULL); g_return_if_fail (IS_COMP_EDITOR_PAGE (page)); - g_return_if_fail (label != NULL); priv = editor->priv; @@ -1733,12 +1822,15 @@ comp_editor_append_page (CompEditor *editor, page_widget = comp_editor_page_get_widget (page); g_assert (page_widget != NULL); - label_widget = gtk_label_new_with_mnemonic (label); + if (label) + label_widget = gtk_label_new_with_mnemonic (label); is_first_page = (priv->pages == NULL); priv->pages = g_list_append (priv->pages, page); - gtk_notebook_append_page (priv->notebook, page_widget, label_widget); + + if (add) + gtk_notebook_append_page (priv->notebook, page_widget, label_widget); /* Listen for things happening on the page */ g_signal_connect(page, "changed", @@ -2557,7 +2649,8 @@ comp_editor_notify_client_changed (CompEditor *editor, ECal *client) if (!e_cal_is_read_only (client, &read_only, NULL)) read_only = TRUE; - gtk_dialog_set_response_sensitive (GTK_DIALOG (editor), GTK_RESPONSE_OK, !read_only); + + /* FIXME: SRINI: Disable widgets */ } static void diff --git a/calendar/gui/dialogs/comp-editor.h b/calendar/gui/dialogs/comp-editor.h index 31f977e3ff..3affcb22b6 100644 --- a/calendar/gui/dialogs/comp-editor.h +++ b/calendar/gui/dialogs/comp-editor.h @@ -22,6 +22,9 @@ #define COMP_EDITOR_H #include +#include +#include +#include #include #include "../itip-utils.h" #include "comp-editor-page.h" @@ -39,14 +42,15 @@ G_BEGIN_DECLS typedef struct _CompEditorPrivate CompEditorPrivate; typedef struct { - GtkDialog object; + BonoboWindow object; /* Private data */ CompEditorPrivate *priv; + BonoboUIComponent *uic; } CompEditor; typedef struct { - GtkDialogClass parent_class; + BonoboWindowClass parent_class; /* Virtual functions */ void (* set_e_cal) (CompEditor *page, ECal *client); @@ -80,7 +84,8 @@ void comp_editor_set_group_item (CompEditor *editor, gboolean comp_editor_get_group_item (CompEditor *editor); void comp_editor_append_page (CompEditor *editor, CompEditorPage *page, - const char *label); + const char *label, + gboolean add); void comp_editor_remove_page (CompEditor *editor, CompEditorPage *page); void comp_editor_show_page (CompEditor *editor, diff --git a/calendar/gui/dialogs/event-editor.c b/calendar/gui/dialogs/event-editor.c index 0eefcd065a..b1f1c123d7 100644 --- a/calendar/gui/dialogs/event-editor.c +++ b/calendar/gui/dialogs/event-editor.c @@ -32,19 +32,21 @@ #include #include #include - +#include #include "event-page.h" #include "recurrence-page.h" #include "meeting-page.h" #include "schedule-page.h" #include "cancel-comp.h" #include "event-editor.h" +#include "../calendar-config.h" struct _EventEditorPrivate { EventPage *event_page; RecurrencePage *recur_page; - MeetingPage *meet_page; + GtkWidget *recur_window; SchedulePage *sched_page; + GtkWidget *sched_window; EMeetingStore *model; gboolean is_meeting; @@ -59,11 +61,6 @@ static void event_editor_edit_comp (CompEditor *editor, ECalComponent *comp); static gboolean event_editor_send_comp (CompEditor *editor, ECalComponentItipMethod method); static void event_editor_finalize (GObject *object); -static void schedule_meeting_cmd (GtkWidget *widget, gpointer data); -static void refresh_meeting_cmd (GtkWidget *widget, gpointer data); -static void cancel_meeting_cmd (GtkWidget *widget, gpointer data); -static void forward_cmd (GtkWidget *widget, gpointer data); - static void model_row_change_insert_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data); static void model_row_delete_cb (GtkTreeModel *model, GtkTreePath *path, gpointer data); @@ -108,12 +105,311 @@ client_changed_cb (CompEditorPage *page, ECal *client, gpointer user_data) //set_menu_sens (EVENT_EDITOR (user_data)); } +static void +menu_view_attendee_cb (BonoboUIComponent *component, + const char *path, + Bonobo_UIComponent_EventType type, + const char *state, + gpointer user_data) +{ + EventEditor *ee = (EventEditor *) user_data; + if (type != Bonobo_UIComponent_STATE_CHANGED) + return; + event_page_set_view_attendee (ee->priv->event_page, atoi(state)); + calendar_config_set_show_attendee (atoi(state)); +} + +static void +menu_view_role_cb (BonoboUIComponent *component, + const char *path, + Bonobo_UIComponent_EventType type, + const char *state, + gpointer user_data) +{ + EventEditor *ee = (EventEditor *) user_data; + + if (type != Bonobo_UIComponent_STATE_CHANGED) + return; + event_page_set_view_role (ee->priv->event_page, atoi(state)); + calendar_config_set_show_role (atoi(state)); +} + +static void +menu_view_status_cb (BonoboUIComponent *component, + const char *path, + Bonobo_UIComponent_EventType type, + const char *state, + gpointer user_data) +{ + EventEditor *ee = (EventEditor *) user_data; + + if (type != Bonobo_UIComponent_STATE_CHANGED) + return; + + event_page_set_view_status (ee->priv->event_page, atoi(state)); + calendar_config_set_show_status (atoi(state)); +} + +static void +menu_view_type_cb (BonoboUIComponent *component, + const char *path, + Bonobo_UIComponent_EventType type, + const char *state, + gpointer user_data) +{ + EventEditor *ee = (EventEditor *) user_data; + + if (type != Bonobo_UIComponent_STATE_CHANGED) + return; + event_page_set_view_type (ee->priv->event_page, atoi(state)); + calendar_config_set_show_type (atoi(state)); +} + +static void +menu_view_rsvp_cb (BonoboUIComponent *component, + const char *path, + Bonobo_UIComponent_EventType type, + const char *state, + gpointer user_data) +{ + EventEditor *ee = (EventEditor *) user_data; + + if (type != Bonobo_UIComponent_STATE_CHANGED) + return; + event_page_set_view_rsvp (ee->priv->event_page, atoi(state)); + calendar_config_set_show_rsvp (atoi(state)); +} + +static void +menu_action_alarm_cb (BonoboUIComponent *component, + const char *path, + Bonobo_UIComponent_EventType type, + const char *state, + gpointer user_data) +{ + EventEditor *ee = (EventEditor *) user_data; + + event_page_show_alarm (ee->priv->event_page); +} + +static void +menu_show_time_busy_cb (BonoboUIComponent *component, + const char *path, + Bonobo_UIComponent_EventType type, + const char *state, + gpointer user_data) +{ + EventEditor *ee = (EventEditor *) user_data; + + if (type != Bonobo_UIComponent_STATE_CHANGED) + return; + + event_page_set_show_time_busy (ee->priv->event_page, atoi(state)); +} + +static void +menu_all_day_event_cb (BonoboUIComponent *component, + const char *path, + Bonobo_UIComponent_EventType type, + const char *state, + gpointer user_data) +{ + EventEditor *ee = (EventEditor *) user_data; + + if (type != Bonobo_UIComponent_STATE_CHANGED) + return; + event_page_set_all_day_event (ee->priv->event_page, atoi(state)); +} + +static void +menu_show_time_zone_cb (BonoboUIComponent *component, + const char *path, + Bonobo_UIComponent_EventType type, + const char *state, + gpointer user_data) +{ + EventEditor *ee = (EventEditor *) user_data; + + if (type != Bonobo_UIComponent_STATE_CHANGED) + return; + event_page_set_show_timezone (ee->priv->event_page, atoi(state)); + calendar_config_set_show_timezone (atoi(state)); +} + +static void +menu_show_categories_cb (BonoboUIComponent *component, + const char *path, + Bonobo_UIComponent_EventType type, + const char *state, + gpointer user_data) +{ + EventEditor *ee = (EventEditor *) user_data; + + if (type != Bonobo_UIComponent_STATE_CHANGED) + return; + + event_page_set_show_categories (ee->priv->event_page, atoi(state)); + calendar_config_set_show_categories (atoi(state)); +} + +static void +menu_class_public_cb (BonoboUIComponent *ui_component, + const char *path, + Bonobo_UIComponent_EventType type, + const char *state, + gpointer user_data) +{ + EventEditor *ee = (EventEditor *) user_data; + + if (state[0] == '0') + return; + event_page_set_classification (ee->priv->event_page, E_CAL_COMPONENT_CLASS_PUBLIC); +} + +static void +menu_class_private_cb (BonoboUIComponent *ui_component, + const char *path, + Bonobo_UIComponent_EventType type, + const char *state, + gpointer user_data) +{ + EventEditor *ee = (EventEditor *) user_data; + if (state[0] == '0') + return; + + event_page_set_classification (ee->priv->event_page, E_CAL_COMPONENT_CLASS_PRIVATE); +} + +static void +menu_class_confidential_cb (BonoboUIComponent *ui_component, + const char *path, + Bonobo_UIComponent_EventType type, + const char *state, + gpointer user_data) +{ + EventEditor *ee = (EventEditor *) user_data; + if (state[0] == '0') + return; + + event_page_set_classification (ee->priv->event_page, E_CAL_COMPONENT_CLASS_CONFIDENTIAL); +} + +static void +menu_action_recurrance_cb (BonoboUIComponent *ui_component, + const char *path, + Bonobo_UIComponent_EventType type, + const char *state, + gpointer user_data) +{ + EventEditor *ee = (EventEditor *) user_data; + + gtk_widget_show (ee->priv->recur_window); +} + +static void +menu_action_freebusy_cb (BonoboUIComponent *ui_component, + const char *path, + Bonobo_UIComponent_EventType type, + const char *state, + gpointer user_data) +{ + EventEditor *ee = (EventEditor *) user_data; + + gtk_widget_show (ee->priv->sched_window); +} + +static void +menu_action_alarm_cmd (BonoboUIComponent *uic, + void *data, + const char *path) +{ + EventEditor *ee = (EventEditor *) data; + + event_page_show_alarm (ee->priv->event_page); +} + +static void +menu_all_day_event_cmd (BonoboUIComponent *uic, + void *data, + const char *path) +{ + /* TODO + EventEditor *ee = (EventEditor *) data; + + event_page_set_all_day_event (ee->priv->event_page, atoi(state));*/ +} + +static void +menu_show_time_zone_cmd (BonoboUIComponent *uic, + void *data, + const char *path) +{ + /* TODO + EventEditor *ee = (EventEditor *) data; + + event_page_set_show_timezone (ee->priv->event_page, atoi(state)); + calendar_config_set_show_timezone (atoi(state)); */ +} + +static void +menu_action_recurrance_cmd (BonoboUIComponent *uic, + void *data, + const char *path) +{ + EventEditor *ee = (EventEditor *) data; + + gtk_widget_show (ee->priv->recur_window); +} + +static void +menu_action_freebusy_cmd (BonoboUIComponent *uic, + void *data, + const char *path) +{ + EventEditor *ee = (EventEditor *) data; + + gtk_widget_show (ee->priv->sched_window); +} + +static void +menu_insert_send_options_cmd (BonoboUIComponent *uic, + void *data, + const char *path) +{ + EventEditor *ee = (EventEditor *) data; + + event_page_sendoptions_clicked_cb (ee->priv->event_page); +} + +static BonoboUIVerb verbs [] = { + BONOBO_UI_VERB ("ActionAlarm", menu_action_alarm_cmd), + BONOBO_UI_VERB ("ActionAllDayEvent", menu_all_day_event_cmd), + BONOBO_UI_VERB ("ViewTimeZone", menu_show_time_zone_cmd), + BONOBO_UI_VERB ("ActionRecurrance", menu_action_recurrance_cmd), + BONOBO_UI_VERB ("ActionFreeBusy", menu_action_freebusy_cmd), + BONOBO_UI_VERB ("InsertSendOptions", menu_insert_send_options_cmd), + + BONOBO_UI_VERB_END +}; + +static EPixmap pixmaps[] = { + E_PIXMAP ("/Toolbar/ActionAlarm", "stock_alarm", E_ICON_SIZE_LARGE_TOOLBAR), + E_PIXMAP ("/Toolbar/ActionAllDayEvent", "stock_new-24h-appointment", E_ICON_SIZE_LARGE_TOOLBAR), + E_PIXMAP ("/Toolbar/ViewTimeZone", "stock_timezone", E_ICON_SIZE_LARGE_TOOLBAR), + E_PIXMAP ("/Toolbar/ActionRecurrance", "stock_task-recurring", E_ICON_SIZE_LARGE_TOOLBAR), + E_PIXMAP ("/commands/ActionRecurrance", "stock_task-recurring", E_ICON_SIZE_LARGE_TOOLBAR), + E_PIXMAP ("/Toolbar/ActionFreeBusy", "stock_task-recurring", E_ICON_SIZE_LARGE_TOOLBAR), + E_PIXMAP_END +}; + /* Object initialization function for the event editor */ static void event_editor_init (EventEditor *ee) { EventEditorPrivate *priv; - + CompEditor *editor = COMP_EDITOR(ee); + gboolean status; + priv = g_new0 (EventEditorPrivate, 1); ee->priv = priv; @@ -122,6 +418,116 @@ event_editor_init (EventEditor *ee) priv->updating = FALSE; priv->is_meeting = FALSE; + bonobo_ui_component_freeze (editor->uic, NULL); + + bonobo_ui_component_add_verb_list_with_data (editor->uic, verbs, ee); + + bonobo_ui_util_set_ui (editor->uic, PREFIX, + EVOLUTION_UIDIR "/evolution-event-editor.xml", + "evolution-event-editor", NULL); + + /* Show hide the attendee fields */ + status = calendar_config_get_show_attendee (); + bonobo_ui_component_set_prop ( + editor->uic, "/commands/ViewAttendee", + "state", status ? "1" : "0", NULL); + bonobo_ui_component_add_listener ( + editor->uic, "ViewAttendee", + menu_view_attendee_cb, editor); + + /* Hide send options */ + bonobo_ui_component_set_prop ( + editor->uic, "/commands/InsertSendOptions", + "hidden", "1", NULL); + + /* Show hide the status fields */ + status = calendar_config_get_show_status (); + bonobo_ui_component_set_prop ( + editor->uic, "/commands/ViewStatus", + "state", status ? "1" : "0", NULL); + bonobo_ui_component_add_listener ( + editor->uic, "ViewStatus", + menu_view_status_cb, editor); + + /* Show hide the type fields */ + status = calendar_config_get_show_type (); + bonobo_ui_component_set_prop ( + editor->uic, "/commands/ViewType", + "state", status ? "1" : "0", NULL); + bonobo_ui_component_add_listener ( + editor->uic, "ViewType", + menu_view_type_cb, editor); + + /* Show hide the role fields */ + status = calendar_config_get_show_role (); + bonobo_ui_component_set_prop ( + editor->uic, "/commands/ViewRole", + "state", status ? "1" : "0", NULL); + bonobo_ui_component_add_listener ( + editor->uic, "ViewRole", + menu_view_role_cb, editor); + + /* Show hide the rsvp fields */ + status = calendar_config_get_show_rsvp (); + bonobo_ui_component_set_prop ( + editor->uic, "/commands/ViewRSVP", + "state", status ? "1" : "0", NULL); + bonobo_ui_component_add_listener ( + editor->uic, "ViewRSVP", + menu_view_rsvp_cb, editor); + + bonobo_ui_component_add_listener ( + editor->uic, "ActionAlarm", + menu_action_alarm_cb, editor); + + bonobo_ui_component_add_listener ( + editor->uic, "ActionAllDayEvent", + menu_all_day_event_cb, editor); + + bonobo_ui_component_add_listener ( + editor->uic, "ActionShowTimeBusy", + menu_show_time_busy_cb, editor); + + status = calendar_config_get_show_timezone (); + bonobo_ui_component_set_prop ( + editor->uic, "/commands/ViewTimeZone", + "state", status ? "1" : "0", NULL); + bonobo_ui_component_add_listener ( + editor->uic, "ViewTimeZone", + menu_show_time_zone_cb, editor); + + status = calendar_config_get_show_categories (); + bonobo_ui_component_set_prop ( + editor->uic, "/commands/ViewCategories", + "state", status ? "1" : "0", NULL); + bonobo_ui_component_add_listener ( + editor->uic, "ViewCategories", + menu_show_categories_cb, editor); + + bonobo_ui_component_set_prop ( + editor->uic, "/commands/ActionClassPublic", + "state", "1", NULL); + bonobo_ui_component_add_listener ( + editor->uic, "ActionClassPublic", + menu_class_public_cb, editor); + bonobo_ui_component_add_listener ( + editor->uic, "ActionClassPrivate", + menu_class_private_cb, editor); + bonobo_ui_component_add_listener ( + editor->uic, "ActionClassConfidential", + menu_class_confidential_cb, editor); + + bonobo_ui_component_add_listener ( + editor->uic, "ActionRecurrance", + menu_action_recurrance_cb, editor); + bonobo_ui_component_add_listener ( + editor->uic, "ActionFreeBusy", + menu_action_freebusy_cb, editor); + + e_pixmaps_update (editor->uic, pixmaps); + + bonobo_ui_component_thaw (editor->uic, NULL); + comp_editor_set_help_section (COMP_EDITOR (ee), "usage-calendar-apts"); } @@ -129,26 +535,33 @@ EventEditor * event_editor_construct (EventEditor *ee, ECal *client) { EventEditorPrivate *priv; - guint32 flags = comp_editor_get_flags (COMP_EDITOR (ee)); + CompEditor *editor = COMP_EDITOR (ee); + guint32 flags = comp_editor_get_flags (editor); priv = ee->priv; - priv->event_page = event_page_new (); + priv->event_page = event_page_new (priv->model, client, COMP_EDITOR(ee)->uic); g_object_ref (priv->event_page); gtk_object_sink (GTK_OBJECT (priv->event_page)); comp_editor_append_page (COMP_EDITOR (ee), COMP_EDITOR_PAGE (priv->event_page), - _("Appoint_ment")); + _("Appoint_ment"), TRUE); g_signal_connect (G_OBJECT (priv->event_page), "client_changed", G_CALLBACK (client_changed_cb), ee); + priv->recur_window = gtk_dialog_new_with_buttons (_("Recurrance"), + (GtkWindow *) ee, GTK_DIALOG_MODAL, + "gtk-close", GTK_RESPONSE_CLOSE, + NULL); + g_signal_connect (priv->recur_window, "response", G_CALLBACK (gtk_widget_hide), NULL); priv->recur_page = recurrence_page_new (); g_object_ref (priv->recur_page); gtk_object_sink (GTK_OBJECT (priv->recur_page)); - comp_editor_append_page (COMP_EDITOR (ee), - COMP_EDITOR_PAGE (priv->recur_page), - _("_Recurrence")); - + gtk_container_add ((GtkContainer *) (GTK_DIALOG (priv->recur_window)->vbox), + comp_editor_page_get_widget (COMP_EDITOR_PAGE (priv->recur_page))); + gtk_widget_show_all (priv->recur_window); + gtk_widget_hide (priv->recur_window); + comp_editor_append_page (COMP_EDITOR (ee), COMP_EDITOR_PAGE (priv->recur_page), NULL, FALSE); if (priv->is_meeting) { if (e_cal_get_static_capability (client, CAL_STATIC_CAPABILITY_REQ_SEND_OPTIONS)) @@ -156,28 +569,33 @@ event_editor_construct (EventEditor *ee, ECal *client) comp_editor_set_group_item (COMP_EDITOR (ee), TRUE); if ((flags & COMP_EDITOR_USER_ORG) || (flags & COMP_EDITOR_DELEGATE)|| (flags & COMP_EDITOR_NEW_ITEM)) { + priv->sched_window = gtk_dialog_new_with_buttons (_("Free/Busy"), + (GtkWindow *) ee, GTK_DIALOG_MODAL, + "gtk-close", GTK_RESPONSE_CLOSE, + NULL); priv->sched_page = schedule_page_new (priv->model); g_object_ref (priv->sched_page); gtk_object_sink (GTK_OBJECT (priv->sched_page)); - comp_editor_append_page (COMP_EDITOR (ee), - COMP_EDITOR_PAGE (priv->sched_page), - _("Schedulin_g")); - } + gtk_container_add (GTK_CONTAINER (GTK_DIALOG(priv->sched_window)->vbox), comp_editor_page_get_widget (COMP_EDITOR_PAGE (priv->sched_page))); + gtk_widget_show_all (priv->sched_window); + gtk_widget_hide (priv->sched_window); + + g_signal_connect (priv->sched_window, "response", G_CALLBACK(gtk_widget_hide), NULL); + comp_editor_append_page (COMP_EDITOR (ee), COMP_EDITOR_PAGE (priv->sched_page), NULL, FALSE); + } else + bonobo_ui_component_set_prop (editor->uic, "/commands/ActionFreeBusy", "hidden", "1", NULL); - priv->meet_page = meeting_page_new (priv->model, client); - g_object_ref (priv->meet_page); - gtk_object_sink (GTK_OBJECT (priv->meet_page)); - - if (comp_editor_get_flags (COMP_EDITOR (ee)) & COMP_EDITOR_DELEGATE) { - comp_editor_append_page (COMP_EDITOR (ee), - COMP_EDITOR_PAGE (priv->meet_page), - _("_Delegatees")); - } else - comp_editor_append_page (COMP_EDITOR (ee), - COMP_EDITOR_PAGE (priv->meet_page), - _("_Attendees")); + event_page_set_meeting (priv->event_page, TRUE); priv->meeting_shown=TRUE; + } else { + bonobo_ui_component_set_prop (editor->uic, "/commands/ActionFreeBusy", "hidden", "1", NULL); + bonobo_ui_component_set_prop (editor->uic, "/commands/ViewAttendee", "hidden", "1", NULL); + bonobo_ui_component_set_prop (editor->uic, "/commands/ViewRole", "hidden", "1", NULL); + bonobo_ui_component_set_prop (editor->uic, "/commands/ViewRSVP", "hidden", "1", NULL); + bonobo_ui_component_set_prop (editor->uic, "/commands/ViewType", "hidden", "1", NULL); + bonobo_ui_component_set_prop (editor->uic, "/commands/ViewStatus", "hidden", "1", NULL); } + comp_editor_set_e_cal (COMP_EDITOR (ee), client); init_widgets (ee); @@ -231,15 +649,10 @@ event_editor_edit_comp (CompEditor *editor, ECalComponent *comp) GSList *l; int row; char *user_email; - user_email = itip_get_comp_attendee (comp, client); + if (!priv->meeting_shown) { - comp_editor_append_page (COMP_EDITOR (ee), - COMP_EDITOR_PAGE (priv->sched_page), - _("Schedulin_g")); - comp_editor_append_page (COMP_EDITOR (ee), - COMP_EDITOR_PAGE (priv->meet_page), - _("In_vitations")); + bonobo_ui_component_set_prop (editor->uic, "/commands/ActionFreeBusy", "hidden", "0", NULL); } if (!(delegate && e_cal_get_static_capability (client, CAL_STATIC_CAPABILITY_DELEGATE_TO_MANY))) { @@ -287,6 +700,8 @@ event_editor_edit_comp (CompEditor *editor, ECalComponent *comp) e_meeting_attendee_set_edit_level (ia, E_MEETING_ATTENDEE_EDIT_NONE); } } + + event_page_set_meeting (priv->event_page, TRUE); priv->meeting_shown = TRUE; } e_cal_component_free_attendee_list (attendees); @@ -310,7 +725,7 @@ event_editor_send_comp (CompEditor *editor, ECalComponentItipMethod method) method == E_CAL_COMPONENT_METHOD_CANCEL) goto parent; - comp = meeting_page_get_cancel_comp (priv->meet_page); + comp = event_page_get_cancel_comp (priv->event_page); if (comp != NULL) { ECal *client; gboolean result; @@ -356,11 +771,6 @@ event_editor_finalize (GObject *object) priv->recur_page = NULL; } - if (priv->meet_page) { - g_object_unref (priv->meet_page); - priv->meet_page = NULL; - } - if (priv->sched_page) { g_object_unref (priv->sched_page); priv->sched_page = NULL; @@ -408,19 +818,13 @@ show_meeting (EventEditor *ee) event_page_set_meeting (priv->event_page, TRUE); if (!priv->meeting_shown) { - comp_editor_append_page (COMP_EDITOR (ee), - COMP_EDITOR_PAGE (priv->sched_page), - _("Schedulin_g")); - comp_editor_append_page (COMP_EDITOR (ee), - COMP_EDITOR_PAGE (priv->meet_page), - _("In_vitations")); + bonobo_ui_component_set_prop (editor->uic, "/commands/ActionFreeBusy", "hidden", "0", NULL); + priv->meeting_shown = TRUE; comp_editor_set_changed (COMP_EDITOR (ee), FALSE); comp_editor_set_needs_send (COMP_EDITOR (ee), priv->meeting_shown); } - if (comp_editor_get_flags (COMP_EDITOR (ee)) & COMP_EDITOR_DELEGATE) - comp_editor_show_page (COMP_EDITOR (ee), COMP_EDITOR_PAGE (priv->meet_page)); if (!(flags & COMP_EDITOR_NEW_ITEM) && !(flags & COMP_EDITOR_USER_ORG)) gtk_drag_dest_unset (GTK_WIDGET (editor)); @@ -435,45 +839,6 @@ event_editor_show_meeting (EventEditor *ee) show_meeting (ee); } -static void -schedule_meeting_cmd (GtkWidget *widget, gpointer data) -{ - EventEditor *ee = EVENT_EDITOR (data); - - show_meeting (ee); -} - -static void -refresh_meeting_cmd (GtkWidget *widget, gpointer data) -{ - EventEditor *ee = EVENT_EDITOR (data); - - comp_editor_send_comp (COMP_EDITOR (ee), E_CAL_COMPONENT_METHOD_REFRESH); -} - -static void -cancel_meeting_cmd (GtkWidget *widget, gpointer data) -{ - EventEditor *ee = EVENT_EDITOR (data); - ECalComponent *comp; - - comp = comp_editor_get_current_comp (COMP_EDITOR (ee)); - if (cancel_component_dialog ((GtkWindow *) ee, - comp_editor_get_e_cal (COMP_EDITOR (ee)), comp, FALSE)) { - comp_editor_send_comp (COMP_EDITOR (ee), E_CAL_COMPONENT_METHOD_CANCEL); - comp_editor_delete_comp (COMP_EDITOR (ee)); - } -} - -static void -forward_cmd (GtkWidget *widget, gpointer data) -{ - EventEditor *ee = EVENT_EDITOR (data); - - if (comp_editor_save_comp (COMP_EDITOR (ee), TRUE)) - comp_editor_send_comp (COMP_EDITOR (ee), E_CAL_COMPONENT_METHOD_PUBLISH); -} - static void model_changed (EventEditor *ee) { diff --git a/calendar/gui/dialogs/event-page.c b/calendar/gui/dialogs/event-page.c index 5609259cbe..7414bab596 100644 --- a/calendar/gui/dialogs/event-page.c +++ b/calendar/gui/dialogs/event-page.c @@ -30,17 +30,26 @@ #include #include #include +#include #include #include #include #include "common/authentication.h" #include "e-util/e-categories-config.h" #include "e-util/e-dialog-widgets.h" +#include "e-util/e-popup.h" #include "misc/e-dateedit.h" #include "misc/e-send-options.h" #include #include "../calendar-config.h" #include "../e-timezone-entry.h" +#include +#include + +#include "../e-meeting-attendee.h" +#include "../e-meeting-store.h" +#include "../e-meeting-list-view.h" +#include "../e-cal-popup.h" #include "comp-editor.h" #include "comp-editor-util.h" #include "../e-alarm-list.h" @@ -58,24 +67,44 @@ struct _EventPagePrivate { /* Widgets from the Glade file */ GtkWidget *main; + BonoboUIComponent *uic; GtkWidget *summary; GtkWidget *summary_label; GtkWidget *location; GtkWidget *location_label; + EAccountList *accounts; + EMeetingAttendee *ia; + char *default_address; + char *user_add; + ECalComponent *comp; + + /* For meeting/event */ + GtkWidget *calendar_label; + GtkWidget *org_cal_label; + GtkWidget *attendee_box; + + /* Lists of attendees */ + GPtrArray *deleted_attendees; + GtkWidget *start_time; GtkWidget *end_time; + GtkWidget *end_time_selector; + GtkWidget *time_hour; + GtkWidget *hour_selector; GtkWidget *start_timezone; GtkWidget *end_timezone; - GtkWidget *all_day_event; + GtkWidget *timezone_label; + gboolean all_day_event; GtkWidget *description; - GtkWidget *classification; + ECalComponentClassification classification; - GtkWidget *show_time_as_busy; + gboolean show_time_as_busy; + GtkWidget *alarm_dialog; GtkWidget *alarm; GtkWidget *alarm_time; GtkWidget *alarm_warning; @@ -86,12 +115,29 @@ struct _EventPagePrivate { GtkWidget *source_selector; - GtkWidget *sendoptions_frame; - GtkWidget *sendoptions_button; + /* Meeting related items */ + GtkWidget *list_box; + GtkWidget *organizer_table; + GtkWidget *organizer; + GtkWidget *add; + GtkWidget *remove; + GtkWidget *edit; + GtkWidget *invite; + GtkWidget *attendees_label; + + /* ListView stuff */ + EMeetingStore *model; + ECal *client; + EMeetingListView *list_view; + gint row; + + /* For handling who the organizer is */ + gboolean user_org; + gboolean existing; + gboolean updating; EAlarmList *alarm_list_store; - gboolean updating; gboolean sendoptions_shown; ESendOptionsDialog *sod; @@ -117,7 +163,10 @@ static gboolean event_page_fill_component (CompEditorPage *page, ECalComponent * static gboolean event_page_fill_timezones (CompEditorPage *page, GHashTable *timezones); static void event_page_set_summary (CompEditorPage *page, const char *summary); static void event_page_set_dates (CompEditorPage *page, CompEditorPageDates *dates); - +static void notify_dates_changed (EventPage *epage, struct icaltimetype *start_tt, struct icaltimetype *end_tt); +static gboolean check_start_before_end (struct icaltimetype *start_tt, icaltimezone *start_zone, + struct icaltimetype *end_tt, icaltimezone *end_zone, gboolean adjust_end_time); +static void set_attendees (ECalComponent *comp, const GPtrArray *attendees); G_DEFINE_TYPE (EventPage, event_page, TYPE_COMP_EDITOR_PAGE); /* Class initialization function for the event page */ @@ -151,6 +200,7 @@ event_page_init (EventPage *epage) epage->priv = priv; priv->xml = NULL; + priv->uic = NULL; priv->main = NULL; priv->summary = NULL; @@ -161,26 +211,49 @@ event_page_init (EventPage *epage) priv->end_time = NULL; priv->start_timezone = NULL; priv->end_timezone = NULL; - priv->all_day_event = NULL; + priv->timezone_label = NULL; + priv->all_day_event = FALSE; priv->description = NULL; - priv->classification = NULL; - priv->show_time_as_busy = NULL; + priv->classification = E_CAL_COMPONENT_CLASS_NONE; + priv->show_time_as_busy = FALSE; + priv->alarm_dialog = NULL; priv->alarm = NULL; priv->alarm_time = NULL; priv->alarm_custom = NULL; priv->categories_btn = NULL; priv->categories = NULL; - priv->sendoptions_frame = NULL; - priv->sendoptions_button = NULL; priv->sod = NULL; - priv->alarm_interval = -1; + priv->deleted_attendees = g_ptr_array_new (); + + priv->comp = NULL; + + priv->accounts = NULL; + priv->ia = NULL; + priv->default_address = NULL; + priv->invite = NULL; + + priv->model = NULL; + priv->list_view = NULL; priv->updating = FALSE; + + priv->alarm_interval = -1; + priv->sendoptions_shown = FALSE; priv->is_meeting = FALSE; priv->sync_timezones = FALSE; + priv->default_address = NULL; +} + +static void +cleanup_attendees (GPtrArray *attendees) +{ + int i; + + for (i = 0; i < attendees->len; i++) + g_object_unref (g_ptr_array_index (attendees, i)); } /* Destroy handler for the event page */ @@ -195,7 +268,13 @@ event_page_finalize (GObject *object) epage = EVENT_PAGE (object); priv = epage->priv; + + if (priv->comp != NULL) + g_object_unref (priv->comp); + cleanup_attendees (priv->deleted_attendees); + g_ptr_array_free (priv->deleted_attendees, TRUE); + if (priv->main) gtk_widget_unref (priv->main); @@ -246,6 +325,57 @@ static const int alarm_map[] = { -1 }; +static void +set_classification_menu (EventPage *epage, gint class) +{ + bonobo_ui_component_freeze (epage->priv->uic, NULL); + switch (class) { + case E_CAL_COMPONENT_CLASS_PUBLIC: + printf("to pub\n"); + bonobo_ui_component_set_prop ( + epage->priv->uic, "/commands/ActionClassPublic", + "state", "1", NULL); + break; + case E_CAL_COMPONENT_CLASS_CONFIDENTIAL: + printf("to conf\n"); + bonobo_ui_component_set_prop ( + epage->priv->uic, "/commands/ActionClassConfidential", + "state", "1", NULL); + break; + case E_CAL_COMPONENT_CLASS_PRIVATE: + printf("to priv\n"); + bonobo_ui_component_set_prop ( + epage->priv->uic, "/commands/ActionClassPrivate", + "state", "1", NULL); + break; + } + bonobo_ui_component_thaw (epage->priv->uic, NULL); +} + +static void +set_busy_time_menu (EventPage *epage, gboolean status) +{ + bonobo_ui_component_set_prop ( + epage->priv->uic, "/commands/ActionShowTimeBusy", + "state", status ? "1" : "0", NULL); +} + +static void +enable_busy_time_menu (EventPage *epage, gboolean state) +{ + bonobo_ui_component_set_prop ( + epage->priv->uic, "/commands/ActionShowTimeBusy", + "sensitive", state ? "1" : "0", NULL); +} + +static void +set_all_day_event_menu (EventPage *epage, gboolean status) +{ + bonobo_ui_component_set_prop ( + epage->priv->uic, "/commands/ActionAllDayEvent", + "state", status ? "1" : "0", NULL); +} + /* get_widget handler for the event page */ static GtkWidget * event_page_get_widget (CompEditorPage *page) @@ -281,23 +411,16 @@ set_all_day (EventPage *epage, gboolean all_day) priv = epage->priv; - gtk_signal_handler_block_by_data (GTK_OBJECT (priv->all_day_event), - epage); - e_dialog_toggle_set (priv->all_day_event, all_day); - gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->all_day_event), - epage); + set_all_day_event_menu (epage, all_day); + + if (all_day) + gtk_option_menu_set_history ((GtkOptionMenu *) priv->end_time_selector, 1); + /* TODO implement for in end time selector */ + gtk_widget_set_sensitive (priv->end_time_selector, FALSE); e_date_edit_set_show_time (E_DATE_EDIT (priv->start_time), !all_day); e_date_edit_set_show_time (E_DATE_EDIT (priv->end_time), !all_day); - /* DATE values do not have timezones, so we hide the fields. */ - if (all_day) { - gtk_widget_hide (priv->start_timezone); - gtk_widget_hide (priv->end_timezone); - } else { - gtk_widget_show (priv->start_timezone); - gtk_widget_show (priv->end_timezone); - } } static void @@ -305,7 +428,7 @@ update_time (EventPage *epage, ECalComponentDateTime *start_date, ECalComponentD { EventPagePrivate *priv; struct icaltimetype *start_tt, *end_tt, implied_tt; - icaltimezone *start_zone = NULL, *end_zone = NULL; + icaltimezone *start_zone = NULL; gboolean all_day_event; priv = epage->priv; @@ -323,16 +446,6 @@ update_time (EventPage *epage, ECalComponentDateTime *start_date, ECalComponentD } } - end_zone = icaltimezone_get_builtin_timezone_from_tzid (end_date->tzid); - if (!end_zone) { - if (!e_cal_get_timezone (COMP_EDITOR_PAGE (epage)->client, - end_date->tzid, &end_zone, NULL)) { - /* FIXME: Handle error better. */ - g_warning ("Couldn't get timezone from server: %s", - end_date->tzid ? end_date->tzid : ""); - } - } - /* If both times are DATE values, we set the 'All Day Event' checkbox. Also, if DTEND is after DTSTART, we subtract 1 day from it. */ all_day_event = FALSE; @@ -351,13 +464,14 @@ update_time (EventPage *epage, ECalComponentDateTime *start_date, ECalComponentD } } + epage->priv->all_day_event = all_day_event; set_all_day (epage, all_day_event); /* If it is an all day event, we set both timezones to the current timezone, so that if the user toggles the 'All Day Event' checkbox the event uses the current timezone rather than none at all. */ if (all_day_event) - start_zone = end_zone = calendar_config_get_icaltimezone (); + start_zone = calendar_config_get_icaltimezone (); gtk_signal_handler_block_by_data (GTK_OBJECT (priv->start_time), epage); @@ -386,16 +500,12 @@ update_time (EventPage *epage, ECalComponentDateTime *start_date, ECalComponentD e_timezone_entry_set_timezone (E_TIMEZONE_ENTRY (priv->start_timezone), start_zone); - e_timezone_entry_set_timezone (E_TIMEZONE_ENTRY (priv->end_timezone), - end_zone); + event_page_set_show_timezone (epage, calendar_config_get_show_timezone() & !all_day_event); gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_timezone), epage); - gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_timezone), - epage); - - priv->sync_timezones = (start_zone == end_zone) ? TRUE : FALSE; + priv->sync_timezones = TRUE; } /* Fills the widgets with default values */ @@ -424,13 +534,16 @@ clear_widgets (EventPage *epage) gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time), epage); + epage->priv->all_day_event = FALSE; set_all_day (epage, FALSE); /* Classification */ - e_dialog_option_menu_set (priv->classification, E_CAL_COMPONENT_CLASS_PRIVATE, classification_map); + priv->classification = E_CAL_COMPONENT_CLASS_PRIVATE; + set_classification_menu (epage, priv->classification); /* Show Time As (Transparency) */ - e_dialog_toggle_set (priv->show_time_as_busy, TRUE); + priv->show_time_as_busy = TRUE; + set_busy_time_menu (epage, TRUE); /* Alarm */ e_dialog_toggle_set (priv->alarm, FALSE); @@ -438,6 +551,9 @@ clear_widgets (EventPage *epage) /* Categories */ e_dialog_editable_set (priv->categories, NULL); + + gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (priv->organizer)->entry), priv->default_address); + } static gboolean @@ -600,11 +716,59 @@ is_custom_alarm_store (EAlarmList *alarm_list_store, char *old_summary, CalUnit return FALSE; } +void +event_page_set_view_attendee (EventPage *epage, gboolean state) +{ + EventPagePrivate *priv = epage->priv; + + e_meeting_list_view_column_set_visible (priv->list_view, "Attendee ", state); +} + +void +event_page_set_view_role (EventPage *epage, gboolean state) +{ + EventPagePrivate *priv = epage->priv; + + e_meeting_list_view_column_set_visible (priv->list_view, "Role", state); +} + +void +event_page_set_view_status (EventPage *epage, gboolean state) +{ + EventPagePrivate *priv = epage->priv; + + e_meeting_list_view_column_set_visible (priv->list_view, "Status", state); +} + +void +event_page_set_view_type (EventPage *epage, gboolean state) +{ + EventPagePrivate *priv = epage->priv; + + e_meeting_list_view_column_set_visible (priv->list_view, "Type", state); +} + +void +event_page_set_view_rsvp (EventPage *epage, gboolean state) +{ + EventPagePrivate *priv = epage->priv; + + e_meeting_list_view_column_set_visible (priv->list_view, "RSVP", state); +} + +void +event_page_set_classification (EventPage *epage, ECalComponentClassification class) +{ + printf("Setting to %d\n", class); + epage->priv->classification = class; +} + static void sensitize_widgets (EventPage *epage) { gboolean read_only, custom, alarm, sens = TRUE, sensitize; EventPagePrivate *priv; + gboolean delegate; priv = epage->priv; if (COMP_EDITOR_PAGE (epage)->flags & COMP_EDITOR_MEETING) @@ -613,6 +777,8 @@ sensitize_widgets (EventPage *epage) if (!e_cal_is_read_only (COMP_EDITOR_PAGE (epage)->client, &read_only, NULL)) read_only = TRUE; + delegate = COMP_EDITOR_PAGE (epage)->flags & COMP_EDITOR_PAGE_DELEGATE; + sensitize = !read_only && sens; custom = is_custom_alarm_store (priv->alarm_list_store, priv->old_summary, priv->alarm_units, priv->alarm_interval, NULL); @@ -626,25 +792,60 @@ sensitize_widgets (EventPage *epage) gtk_widget_set_sensitive (priv->start_timezone, sensitize); gtk_widget_set_sensitive (priv->end_time, sensitize); gtk_widget_set_sensitive (priv->end_timezone, sensitize); - gtk_widget_set_sensitive (priv->all_day_event, sensitize); gtk_widget_set_sensitive (priv->description, sensitize); - gtk_widget_set_sensitive (priv->classification, sensitize); - gtk_widget_set_sensitive (priv->show_time_as_busy, sensitize); gtk_widget_set_sensitive (priv->alarm, !read_only); gtk_widget_set_sensitive (priv->alarm_time, !read_only && !custom && alarm); gtk_widget_set_sensitive (priv->alarm_custom, alarm); - if (custom) - gtk_widget_show (priv->alarm_warning); - else - gtk_widget_hide (priv->alarm_warning); gtk_widget_set_sensitive (priv->categories_btn, sensitize); - gtk_widget_set_sensitive (priv->sendoptions_button, sensitize); + /*TODO implement the for portion of the end time selector */ + gtk_widget_set_sensitive (priv->end_time_selector, FALSE); gtk_entry_set_editable (GTK_ENTRY (priv->categories), sensitize); - if (COMP_EDITOR_PAGE (epage)->flags & COMP_EDITOR_PAGE_DELEGATE) { - gtk_widget_set_sensitive (priv->sendoptions_button, TRUE); + if (delegate) { gtk_widget_set_sensitive (priv->source_selector, FALSE); } + + gtk_widget_set_sensitive (priv->organizer, !read_only); + gtk_widget_set_sensitive (priv->add, (!read_only && sens) || delegate); + gtk_widget_set_sensitive (priv->remove, (!read_only && sens) || delegate); + gtk_widget_set_sensitive (priv->invite, (!read_only && sens) || delegate); + gtk_widget_set_sensitive (GTK_WIDGET (priv->list_view), !read_only); + + bonobo_ui_component_set_prop (priv->uic, "/commands/InsertAttachments", "sensitive", sensitize ? "1" : "0" + , NULL); + bonobo_ui_component_set_prop (priv->uic, "/commands/ViewTimeZone", "sensitive", sensitize ? "1" : "0" + , NULL); + bonobo_ui_component_set_prop (priv->uic, "/commands/ActionAllDayEvent", "sensitive", sensitize ? "1" : "0" + , NULL); + bonobo_ui_component_set_prop (priv->uic, "/commands/ActionRecurrance", "sensitive", sensitize ? "1" : "0" + , NULL); + bonobo_ui_component_set_prop (priv->uic, "/commands/ActionShowTimeBusy", "sensitive", sensitize ? "1" : "0" + , NULL); + bonobo_ui_component_set_prop (priv->uic, "/commands/ActionAlarm", "sensitive", sensitize ? "1" : "0" + , NULL); + bonobo_ui_component_set_prop (priv->uic, "/commands/ActionClassPublic", "sensitive", sensitize ? "1" : "0" + , NULL); + bonobo_ui_component_set_prop (priv->uic, "/commands/ActionClassPrivate", "sensitive", sensitize ? "1" : "0" + , NULL); + bonobo_ui_component_set_prop (priv->uic, "/commands/ActionClassConfidential", "sensitive", + sensitize ? "1" : "0", NULL); + bonobo_ui_component_set_prop (priv->uic, "/commands/ViewCategories", "sensitive", sensitize ? "1" : "0" + , NULL); + + if (!priv->is_meeting) { + gtk_widget_hide (priv->calendar_label); + gtk_widget_hide (priv->list_box); + gtk_widget_hide (priv->attendee_box); + gtk_widget_hide (priv->organizer); + gtk_label_set_text_with_mnemonic ((GtkLabel *) priv->org_cal_label, _("Cale_ndar")); + } else { + gtk_widget_show (priv->calendar_label); + gtk_widget_show (priv->list_box); + gtk_widget_show (priv->attendee_box); + gtk_widget_show (priv->organizer); + gtk_label_set_text_with_mnemonic ((GtkLabel *) priv->org_cal_label, _("Or_ganizer")); + } + } void @@ -652,8 +853,7 @@ event_page_hide_options (EventPage *page) { g_return_if_fail (IS_EVENT_PAGE (page)); - gtk_widget_hide (page->priv->sendoptions_frame); - + bonobo_ui_component_set_prop (page->priv->uic, "/commands/InsertSendOptions", "hidden", "1", NULL); page->priv->sendoptions_shown = FALSE; } @@ -662,7 +862,7 @@ event_page_show_options (EventPage *page) { g_return_if_fail (IS_EVENT_PAGE (page)); - gtk_widget_show (page->priv->sendoptions_frame); + bonobo_ui_component_set_prop (page->priv->uic, "/commands/InsertSendOptions", "hidden", "0", NULL); page->priv->sendoptions_shown = TRUE; } @@ -672,6 +872,49 @@ event_page_set_meeting (EventPage *page, gboolean set) g_return_if_fail (IS_EVENT_PAGE (page)); page->priv->is_meeting = set; + sensitize_widgets (page); +} + +void +event_page_set_delegate (EventPage *page, gboolean set) +{ + g_return_if_fail (IS_EVENT_PAGE (page)); + + if (set) + gtk_label_set_text_with_mnemonic ((GtkLabel *)page->priv->attendees_label, _("_Delegatees")); + else + gtk_label_set_text_with_mnemonic ((GtkLabel *)page->priv->attendees_label, _("Atte_ndees")); +} + +static EAccount * +get_current_account (EventPage *epage) +{ + EventPagePrivate *priv; + EIterator *it; + const char *str; + + priv = epage->priv; + + str = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (priv->organizer)->entry)); + if (!str) + return NULL; + + for (it = e_list_get_iterator((EList *)priv->accounts); e_iterator_is_valid(it); e_iterator_next(it)) { + EAccount *a = (EAccount *)e_iterator_get(it); + char *full = g_strdup_printf("%s <%s>", a->id->name, a->id->address); + + if (!strcmp (full, str)) { + g_free (full); + g_object_unref (it); + + return a; + } + + g_free (full); + } + g_object_unref (it); + + return NULL; } /* fill_widgets handler for the event page */ @@ -697,15 +940,29 @@ event_page_fill_widgets (CompEditorPage *page, ECalComponent *comp) if (!e_cal_component_has_organizer (comp)) page->flags |= COMP_EDITOR_PAGE_USER_ORG; - + /* Don't send off changes during this time */ priv->updating = TRUE; + + /* Clean out old data */ + if (priv->comp != NULL) + g_object_unref (priv->comp); + priv->comp = NULL; + + cleanup_attendees (priv->deleted_attendees); + g_ptr_array_set_size (priv->deleted_attendees, 0); + + /* Component for cancellation */ + priv->comp = e_cal_component_clone (comp); /* Clean the page */ clear_widgets (epage); /* Summary, location, description(s) */ + /* Component for cancellation */ + priv->comp = e_cal_component_clone (comp); + e_cal_component_get_summary (comp, &text); e_dialog_editable_set (priv->summary, text.value); priv->old_summary = g_strdup (text.value); @@ -723,8 +980,67 @@ event_page_fill_widgets (CompEditorPage *page, ECalComponent *comp) } e_cal_component_free_text_list (l); - /* Start and end times */ + if (priv->is_meeting) { + ECalComponentOrganizer organizer; + + priv->user_add = itip_get_comp_attendee (comp, COMP_EDITOR_PAGE (epage)->client); + + /* If there is an existing organizer show it properly */ + if (e_cal_component_has_organizer (comp)) { + e_cal_component_get_organizer (comp, &organizer); + if (organizer.value != NULL) { + const gchar *strip = itip_strip_mailto (organizer.value); + gchar *string; + // gtk_widget_hide (priv->organizer_table); + // gtk_widget_show (priv->existing_organizer_table); + if (itip_organizer_is_user (comp, page->client)) { + if (e_cal_get_static_capability ( + page->client, + CAL_STATIC_CAPABILITY_ORGANIZER_NOT_EMAIL_ADDRESS)) + // gtk_widget_hide (priv->existing_organizer_btn); + priv->user_org = TRUE; + } else { + if (e_cal_get_static_capability ( + page->client, + CAL_STATIC_CAPABILITY_ORGANIZER_NOT_EMAIL_ADDRESS)) + // gtk_widget_hide (priv->existing_organizer_btn); + gtk_widget_set_sensitive (priv->invite, FALSE); + gtk_widget_set_sensitive (priv->add, FALSE); + gtk_widget_set_sensitive (priv->remove, FALSE); + priv->user_org = FALSE; + } + + if (e_cal_get_static_capability (COMP_EDITOR_PAGE (epage)->client, CAL_STATIC_CAPABILITY_NO_ORGANIZER) && (COMP_EDITOR_PAGE (epage)->flags & COMP_EDITOR_PAGE_DELEGATE)) + string = g_strdup (priv->user_add); + else if ( organizer.cn != NULL) + string = g_strdup_printf ("%s <%s>", organizer.cn, strip); + else + string = g_strdup (strip); + + // gtk_label_set_text (GTK_LABEL (priv->existing_organizer), string); + g_free (string); + priv->existing = TRUE; + } + } else { + EAccount *a; + + a = get_current_account (epage); + if (a != NULL) { + CompEditorPage *page = (CompEditorPage *) epage; + priv->ia = e_meeting_store_add_attendee_with_defaults (priv->model); + g_object_ref (priv->ia); + + e_meeting_attendee_set_address (priv->ia, g_strdup_printf ("MAILTO:%s", a->id->address)); + e_meeting_attendee_set_cn (priv->ia, g_strdup (a->id->name)); + if (page->client && e_cal_get_organizer_must_accept (page->client)) + e_meeting_attendee_set_status (priv->ia, ICAL_PARTSTAT_NEEDSACTION); + else + e_meeting_attendee_set_status (priv->ia, ICAL_PARTSTAT_ACCEPTED); + } + } + } + /* Start and end times */ e_cal_component_get_dtstart (comp, &start_date); e_cal_component_get_dtend (comp, &end_date); if (!start_date.value) { @@ -741,7 +1057,6 @@ event_page_fill_widgets (CompEditorPage *page, ECalComponent *comp) /* Classification */ e_cal_component_get_classification (comp, &cl); - switch (cl) { case E_CAL_COMPONENT_CLASS_PUBLIC: case E_CAL_COMPONENT_CLASS_PRIVATE: @@ -751,23 +1066,24 @@ event_page_fill_widgets (CompEditorPage *page, ECalComponent *comp) cl = E_CAL_COMPONENT_CLASS_PUBLIC; break; } - e_dialog_option_menu_set (priv->classification, cl, classification_map); + set_classification_menu (epage, cl); /* Show Time As (Transparency) */ e_cal_component_get_transparency (comp, &transparency); switch (transparency) { case E_CAL_COMPONENT_TRANSP_TRANSPARENT: - e_dialog_toggle_set (priv->show_time_as_busy, FALSE); + set_busy_time_menu (epage, FALSE); break; default: - e_dialog_toggle_set (priv->show_time_as_busy, TRUE); + set_busy_time_menu (epage, TRUE); break; } + if (e_cal_get_static_capability (page->client, CAL_STATIC_CAPABILITY_NO_TRANSPARENCY)) - gtk_widget_hide (priv->show_time_as_busy); + enable_busy_time_menu (epage, FALSE); else - gtk_widget_show (priv->show_time_as_busy); + enable_busy_time_menu (epage, TRUE); /* Alarms */ g_signal_handlers_block_matched (priv->alarm, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, epage); @@ -795,11 +1111,11 @@ event_page_fill_widgets (CompEditorPage *page, ECalComponent *comp) e_dialog_option_menu_set (priv->alarm_time, priv->alarm_interval == -1 ? ALARM_15_MINUTES : ALARM_USER_TIME, alarm_map); } g_signal_handlers_unblock_matched (priv->alarm, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, epage); - + /* Categories */ 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); @@ -827,7 +1143,6 @@ event_page_fill_component (CompEditorPage *page, ECalComponent *comp) struct icaltimetype start_tt, end_tt; gboolean all_day_event, start_date_set, end_date_set, busy; char *cat, *str; - ECalComponentClassification classif; GtkTextBuffer *text_buffer; GtkTextIter text_iter_start, text_iter_end; @@ -918,7 +1233,7 @@ event_page_fill_component (CompEditorPage *page, ECalComponent *comp) /* If the all_day toggle is set, we use DATE values for DTSTART and DTEND. If not, we fetch the hour & minute from the widgets. */ - all_day_event = e_dialog_toggle_get (priv->all_day_event); + all_day_event = priv->all_day_event; if (all_day_event) { start_tt.is_date = TRUE; @@ -927,7 +1242,7 @@ event_page_fill_component (CompEditorPage *page, ECalComponent *comp) /* We have to add 1 day to DTEND, as it is not inclusive. */ icaltime_adjust (&end_tt, 1, 0, 0, 0); } else { - icaltimezone *start_zone, *end_zone; + icaltimezone *start_zone; if (!e_date_edit_time_is_valid (E_DATE_EDIT (priv->start_time))) { comp_editor_page_display_validation_error (page, _("Start time is wrong"), priv->start_time); @@ -945,8 +1260,7 @@ event_page_fill_component (CompEditorPage *page, ECalComponent *comp) &end_tt.minute); start_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->start_timezone)); start_date.tzid = icaltimezone_get_tzid (start_zone); - end_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->end_timezone)); - end_date.tzid = icaltimezone_get_tzid (end_zone); + end_date.tzid = icaltimezone_get_tzid (start_zone); } e_cal_component_set_dtstart (comp, &start_date); @@ -966,11 +1280,11 @@ event_page_fill_component (CompEditorPage *page, ECalComponent *comp) g_free (str); /* Classification */ - classif = e_dialog_option_menu_get (priv->classification, classification_map); - e_cal_component_set_classification (comp, classif); + e_cal_component_set_classification (comp, priv->classification); + printf("Storing %d\n", priv->classification); /* Show Time As (Transparency) */ - busy = e_dialog_toggle_get (priv->show_time_as_busy); + busy = priv->show_time_as_busy; e_cal_component_set_transparency (comp, busy ? E_CAL_COMPONENT_TRANSP_OPAQUE : E_CAL_COMPONENT_TRANSP_TRANSPARENT); /* send options */ @@ -1081,6 +1395,79 @@ event_page_fill_component (CompEditorPage *page, ECalComponent *comp) } } + if (priv->is_meeting) { + ECalComponentOrganizer organizer = {NULL, NULL, NULL, NULL}; + + if (!priv->existing) { + EAccount *a; + gchar *addr = NULL; + + /* Find the identity for the organizer or sentby field */ + a = get_current_account (epage); + + /* Sanity Check */ + if (a == NULL) { + e_notice (page, GTK_MESSAGE_ERROR, + _("The organizer selected no longer has an account.")); + return FALSE; + } + + if (a->id->address == NULL || strlen (a->id->address) == 0) { + e_notice (page, GTK_MESSAGE_ERROR, + _("An organizer is required.")); + return FALSE; + } + + addr = g_strdup_printf ("MAILTO:%s", a->id->address); + + organizer.value = addr; + organizer.cn = a->id->name; + e_cal_component_set_organizer (comp, &organizer); + + g_free (addr); + } + + if (e_meeting_store_count_actual_attendees (priv->model) < 1) { + e_notice (page, GTK_MESSAGE_ERROR, + _("At least one attendee is required.")); + return FALSE; + } + + + if (COMP_EDITOR_PAGE (epage)->flags & COMP_EDITOR_PAGE_DELEGATE ) { + GSList *attendee_list, *l; + int i; + const GPtrArray *attendees = e_meeting_store_get_attendees (priv->model); + + e_cal_component_get_attendee_list (priv->comp, &attendee_list); + + for (i = 0; i < attendees->len; i++) { + EMeetingAttendee *ia = g_ptr_array_index (attendees, i); + ECalComponentAttendee *ca; + + /* Remove the duplicate user from the component if present */ + if (e_meeting_attendee_is_set_delto (ia)) { + for (l = attendee_list; l; l = l->next) { + ECalComponentAttendee *a = l->data; + + if (g_str_equal (a->value, e_meeting_attendee_get_address (ia))) { + attendee_list = g_slist_remove (attendee_list, l->data); + break; + } + } + } + + ca = e_meeting_attendee_as_e_cal_component_attendee (ia); + + attendee_list = g_slist_append (attendee_list, ca); + } + e_cal_component_set_attendee_list (comp, attendee_list); + e_cal_component_free_attendee_list (attendee_list); + } else + set_attendees (comp, e_meeting_store_get_attendees (priv->model)); + } + + return TRUE; } @@ -1127,128 +1514,634 @@ event_page_set_dates (CompEditorPage *page, CompEditorPageDates *dates) -/* Gets the widgets from the XML file and returns if they are all available. */ -static gboolean -get_widgets (EventPage *epage) +static void +time_sel_changed (GtkOptionMenu *widget, EventPagePrivate *priv) { - CompEditorPage *page = COMP_EDITOR_PAGE (epage); - EventPagePrivate *priv; - GSList *accel_groups; - GtkWidget *toplevel; - - priv = epage->priv; - -#define GW(name) glade_xml_get_widget (priv->xml, name) - - priv->main = GW ("event-page"); - if (!priv->main) - return FALSE; - - /* Get the GtkAccelGroup from the toplevel window, so we can install - it when the notebook page is mapped. */ - toplevel = gtk_widget_get_toplevel (priv->main); - accel_groups = gtk_accel_groups_from_object (G_OBJECT (toplevel)); - if (accel_groups) { - page->accel_group = accel_groups->data; - gtk_accel_group_ref (page->accel_group); + int selection = gtk_option_menu_get_history (widget); + + if (selection == 1) { + gtk_widget_hide (priv->time_hour); + gtk_widget_show (priv->end_time); + } else if (!selection){ + gtk_widget_show (priv->time_hour); + gtk_widget_hide (priv->end_time); } + +} - gtk_widget_ref (priv->main); - gtk_container_remove (GTK_CONTAINER (priv->main->parent), priv->main); - - priv->summary = GW ("summary"); - priv->summary_label = GW ("summary-label"); - priv->location = GW ("location"); - priv->location_label = GW ("location-label"); - - /* Glade's visibility flag doesn't seem to work for custom widgets */ - priv->start_time = GW ("start-time"); - gtk_widget_show (priv->start_time); - priv->end_time = GW ("end-time"); - gtk_widget_show (priv->end_time); - - priv->start_timezone = GW ("start-timezone"); - priv->end_timezone = GW ("end-timezone"); - priv->all_day_event = GW ("all-day-event"); - - priv->description = GW ("description"); - - priv->classification = GW ("classification"); - - priv->show_time_as_busy = GW ("show-time-as-busy"); - - priv->alarm = GW ("alarm"); - priv->alarm_time = GW ("alarm-time"); - priv->alarm_warning = GW ("alarm-warning"); - priv->alarm_custom = GW ("alarm-custom"); - - priv->categories_btn = GW ("categories-button"); - priv->categories = GW ("categories"); - - priv->source_selector = GW ("source"); +static void +add_clicked_cb (GtkButton *btn, EventPage *epage) +{ + EMeetingAttendee *attendee; - priv->sendoptions_frame = GW ("send-options-frame"); - priv->sendoptions_button = GW ("send-options-button"); + attendee = e_meeting_store_add_attendee_with_defaults (epage->priv->model); -#undef GW + if (COMP_EDITOR_PAGE (epage)->flags & COMP_EDITOR_PAGE_DELEGATE) { + e_meeting_attendee_set_delfrom (attendee, g_strdup_printf ("MAILTO:%s", epage->priv->user_add)); + } - return (priv->summary - && priv->location - && priv->start_time - && priv->end_time - && priv->start_timezone - && priv->end_timezone - && priv->all_day_event - && priv->description - && priv->classification - && priv->show_time_as_busy - && priv->alarm - && priv->alarm_time - && priv->alarm_warning - && priv->alarm_custom - && priv->categories_btn - && priv->categories - && priv->sendoptions_frame - && priv->sendoptions_button); + e_meeting_list_view_edit (epage->priv->list_view, attendee); } -/* Callback used when the summary changes; we emit the notification signal. */ -static void -summary_changed_cb (GtkEditable *editable, gpointer data) +static gboolean +existing_attendee (EMeetingAttendee *ia, ECalComponent *comp) { - EventPage *epage; - EventPagePrivate *priv; - gchar *summary; + GSList *attendees, *l; + const gchar *ia_address; - epage = EVENT_PAGE (data); - priv = epage->priv; + ia_address = itip_strip_mailto (e_meeting_attendee_get_address (ia)); + if (!ia_address) + return FALSE; - if (priv->updating) - return; + e_cal_component_get_attendee_list (comp, &attendees); + + for (l = attendees; l; l = l->next) { + ECalComponentAttendee *attendee = l->data; + const char *address; + + address = itip_strip_mailto (attendee->value); + if (address && !g_strcasecmp (ia_address, address)) { + e_cal_component_free_attendee_list (attendees); + return TRUE; + } + } - summary = e_dialog_editable_get (GTK_WIDGET (editable)); - comp_editor_page_notify_summary_changed (COMP_EDITOR_PAGE (epage), - summary); - g_free (summary); + e_cal_component_free_attendee_list (attendees); + + return FALSE; } - -/* Note that this assumes that the start_tt and end_tt passed to it are the - dates visible to the user. For DATE values, we have to add 1 day to the - end_tt before emitting the signal. */ static void -notify_dates_changed (EventPage *epage, struct icaltimetype *start_tt, - struct icaltimetype *end_tt) +remove_attendee (EventPage *epage, EMeetingAttendee *ia) { EventPagePrivate *priv; - CompEditorPageDates dates; + int pos = 0; + gboolean delegate = (COMP_EDITOR_PAGE (epage)->flags & COMP_EDITOR_PAGE_DELEGATE); + + priv = epage->priv; + + /* If the user deletes the organizer attendee explicitly, + assume they no longer want the organizer showing up */ + if (ia == priv->ia) { + g_object_unref (priv->ia); + priv->ia = NULL; + } + + /* If this was a delegatee, no longer delegate */ + if (e_meeting_attendee_is_set_delfrom (ia)) { + EMeetingAttendee *ib; + + ib = e_meeting_store_find_attendee (priv->model, e_meeting_attendee_get_delfrom (ia), &pos); + if (ib != NULL) { + e_meeting_attendee_set_delto (ib, NULL); + + if (!delegate) + e_meeting_attendee_set_edit_level (ib, E_MEETING_ATTENDEE_EDIT_FULL); + } + } + + /* Handle deleting all attendees in the delegation chain */ + while (ia != NULL) { + EMeetingAttendee *ib = NULL; + + if (existing_attendee (ia, priv->comp)) { + g_object_ref (ia); + g_ptr_array_add (priv->deleted_attendees, ia); + } + + if (e_meeting_attendee_get_delto (ia) != NULL) + ib = e_meeting_store_find_attendee (priv->model, e_meeting_attendee_get_delto (ia), NULL); + e_meeting_store_remove_attendee (priv->model, ia); + + ia = ib; + } + + sensitize_widgets (epage); +} + +static void +remove_clicked_cb (GtkButton *btn, EventPage *epage) +{ + EventPagePrivate *priv; + EMeetingAttendee *ia; + GtkTreeSelection *selection; + GList *paths = NULL, *tmp; + GtkTreeIter iter; + GtkTreePath *path = NULL; + gboolean valid_iter; + char *address; + + priv = epage->priv; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->list_view)); + if (!(paths = gtk_tree_selection_get_selected_rows (selection, (GtkTreeModel **) &(priv->model)))) { + g_warning ("Could not get a selection to delete."); + return; + } + paths = g_list_reverse (paths); + + for (tmp = paths; tmp; tmp=tmp->next) { + path = tmp->data; + + gtk_tree_model_get_iter (GTK_TREE_MODEL(priv->model), &iter, path); + + gtk_tree_model_get (GTK_TREE_MODEL (priv->model), &iter, E_MEETING_STORE_ADDRESS_COL, &address, -1); + ia = e_meeting_store_find_attendee (priv->model, address, NULL); + g_free (address); + if (!ia) { + g_warning ("Cannot delete attendee\n"); + continue; + } else if (e_meeting_attendee_get_edit_level (ia) != E_MEETING_ATTENDEE_EDIT_FULL) { + g_warning("Not enough rights to delete attendee: %s\n", e_meeting_attendee_get_address(ia)); + continue; + } + + remove_attendee (epage, ia); + } + + /* Select closest item after removal */ + valid_iter = gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->model), &iter, path); + if (!valid_iter) { + gtk_tree_path_prev (path); + valid_iter = gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->model), &iter, path); + } + + if (valid_iter) { + gtk_tree_selection_unselect_all (selection); + gtk_tree_selection_select_iter (selection, &iter); + } + + g_list_foreach (paths, (GFunc) gtk_tree_path_free, NULL); + g_list_free (paths); +} + +static void +invite_cb (GtkWidget *widget, gpointer data) +{ + EventPage *page; + EventPagePrivate *priv; + + page = EVENT_PAGE (data); + priv = page->priv; + + e_meeting_list_view_invite_others_dialog (priv->list_view); +} + +static void +attendee_added_cb (EMeetingListView *emlv, EMeetingAttendee *ia, gpointer user_data) +{ + EventPage *epage = EVENT_PAGE (user_data); + EventPagePrivate *priv; + gboolean delegate = (COMP_EDITOR_PAGE (epage)->flags & COMP_EDITOR_PAGE_DELEGATE); + + priv = epage->priv; + + if (delegate) { + if (existing_attendee (ia, priv->comp)) + e_meeting_store_remove_attendee (priv->model, ia); + else { + if (!e_cal_get_static_capability (COMP_EDITOR_PAGE(epage)->client, + CAL_STATIC_CAPABILITY_DELEGATE_TO_MANY)) { + const char *delegator_id = e_meeting_attendee_get_delfrom (ia); + EMeetingAttendee *delegator; + + delegator = e_meeting_store_find_attendee (priv->model, delegator_id, NULL); + e_meeting_attendee_set_delto (delegator, + g_strdup (e_meeting_attendee_get_address (ia))); + + gtk_widget_set_sensitive (priv->invite, FALSE); + gtk_widget_set_sensitive (priv->add, FALSE); + } + } + } + +} + +/* Callbacks for list view*/ +static void +popup_add_cb (EPopup *ep, EPopupItem *pitem, void *data) +{ + EventPage *epage = data; + + add_clicked_cb (NULL, epage); +} + +static void +popup_delete_cb (EPopup *ep, EPopupItem *pitem, void *data) +{ + EventPage *epage = data; + EventPagePrivate *priv; + + priv = epage->priv; + + remove_clicked_cb (NULL, epage); +} + +enum { + ATTENDEE_CAN_DELEGATE = 1<<1, + ATTENDEE_CAN_DELETE = 1<<2, + ATTENDEE_CAN_ADD = 1<<3, + ATTENDEE_LAST = 1<<4, +}; + +static EPopupItem context_menu_items[] = { + { E_POPUP_ITEM, "10.delete", N_("_Remove"), popup_delete_cb, NULL, GTK_STOCK_REMOVE, ATTENDEE_CAN_DELETE }, + { E_POPUP_ITEM, "15.add", N_("_Add "), popup_add_cb, NULL, GTK_STOCK_ADD }, +}; + +static void +context_popup_free(EPopup *ep, GSList *items, void *data) +{ + g_slist_free(items); +} + +static gint +button_press_event (GtkWidget *widget, GdkEventButton *event, EventPage *epage) +{ + EventPagePrivate *priv; + GtkMenu *menu; + EMeetingAttendee *ia; + GtkTreePath *path; + GtkTreeIter iter; + char *address; + guint32 disable_mask = ~0; + GSList *menus = NULL; + ECalPopup *ep; + int i; + + priv = epage->priv; + + /* only process right-clicks */ + if (event->button != 3 || event->type != GDK_BUTTON_PRESS) + return FALSE; + + /* only if we right-click on an attendee */ + if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (priv->list_view), event->x, event->y, &path, NULL, NULL, NULL)) { + GtkTreeSelection *selection; + + if (gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->model), &iter, path)) { + + gtk_tree_model_get (GTK_TREE_MODEL (priv->model), &iter, E_MEETING_STORE_ADDRESS_COL, &address, -1); + ia = e_meeting_store_find_attendee (priv->model, address, &priv->row); + g_free (address); + + if (ia) { + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->list_view)); + gtk_tree_selection_unselect_all (selection); + gtk_tree_selection_select_path (selection, path); + + if (e_meeting_attendee_get_edit_level (ia) == E_MEETING_ATTENDEE_EDIT_FULL) + disable_mask &= ~ATTENDEE_CAN_DELETE; + } + } + } + + if (GTK_WIDGET_IS_SENSITIVE(priv->add)) + disable_mask &= ~ATTENDEE_CAN_ADD; + else if (COMP_EDITOR_PAGE (epage)->flags & COMP_EDITOR_PAGE_USER_ORG) + disable_mask &= ~ATTENDEE_CAN_ADD; + + ep = e_cal_popup_new("org.gnome.evolution.calendar.meeting.popup"); + + for (i=0;ibutton, event->time); + + return TRUE; +} + +static gboolean +list_view_event (EMeetingListView *list_view, GdkEvent *event, EventPage *epage) { + + EventPagePrivate *priv= epage->priv; + + if (event->type == GDK_2BUTTON_PRESS && COMP_EDITOR_PAGE (epage)->flags & COMP_EDITOR_PAGE_USER_ORG) { + EMeetingAttendee *attendee; + + attendee = e_meeting_store_add_attendee_with_defaults (priv->model); + + if (COMP_EDITOR_PAGE (epage)->flags & COMP_EDITOR_PAGE_DELEGATE) { + e_meeting_attendee_set_delfrom (attendee, g_strdup_printf ("MAILTO:%s", epage->priv->user_add)); + } + + e_meeting_list_view_edit (epage->priv->list_view, attendee); + return TRUE; + } + + return FALSE; +} + + +static gboolean +list_key_press (EMeetingListView *list_view, GdkEventKey *event, EventPage *epage) +{ + if (event->keyval == GDK_Delete) { + EventPagePrivate *priv; + + priv = epage->priv; + remove_clicked_cb (NULL, epage); + + return TRUE; + } else if (event->keyval == GDK_Insert) { + add_clicked_cb (NULL, epage); + + return TRUE; + } + + return FALSE; +} + +void +event_page_set_all_day_event (EventPage *epage, gboolean all_day) +{ + EventPagePrivate *priv = epage->priv; + struct icaltimetype start_tt = icaltime_null_time(); + struct icaltimetype end_tt = icaltime_null_time(); + gboolean date_set; + + epage->priv->all_day_event = all_day; + e_date_edit_set_show_time (E_DATE_EDIT (priv->start_time), !all_day); + e_date_edit_set_show_time (E_DATE_EDIT (priv->end_time), !all_day); + + date_set = e_date_edit_get_date (E_DATE_EDIT (priv->start_time), + &start_tt.year, + &start_tt.month, + &start_tt.day); + e_date_edit_get_time_of_day (E_DATE_EDIT (priv->start_time), + &start_tt.hour, + &start_tt.minute); + g_assert (date_set); + + date_set = e_date_edit_get_date (E_DATE_EDIT (priv->end_time), + &end_tt.year, + &end_tt.month, + &end_tt.day); + e_date_edit_get_time_of_day (E_DATE_EDIT (priv->end_time), + &end_tt.hour, + &end_tt.minute); + g_assert (date_set); + + if (all_day) { + /* FIXME the history set here is wrong */ + gtk_option_menu_set_history ((GtkOptionMenu *) priv->end_time_selector, 1); + } + /* TODO implement the for portion in end time selector */ + gtk_widget_set_sensitive (priv->end_time_selector, FALSE); + + if (all_day) { + bonobo_ui_component_set_prop (epage->priv->uic, "/commands/ViewTimeZone", "sensitive", "0", NULL); + + /* Round down to the start of the day. */ + start_tt.hour = 0; + start_tt.minute = 0; + start_tt.second = 0; + start_tt.is_date = TRUE; + + /* Round down to the start of the day, or the start of the + previous day if it is midnight. */ + icaltime_adjust (&end_tt, 0, 0, 0, -1); + end_tt.hour = 0; + end_tt.minute = 0; + end_tt.second = 0; + end_tt.is_date = TRUE; + } else { + icaltimezone *start_zone; + + bonobo_ui_component_set_prop (epage->priv->uic, "/commands/ViewTimeZone", "sensitive", "1", NULL); + + if (end_tt.year == start_tt.year + && end_tt.month == start_tt.month + && end_tt.day == start_tt.day) { + /* The event is within one day, so we set the event + start to the start of the working day, and the end + to one hour later. */ + start_tt.hour = calendar_config_get_day_start_hour (); + start_tt.minute = calendar_config_get_day_start_minute (); + start_tt.second = 0; + + end_tt = start_tt; + icaltime_adjust (&end_tt, 0, 1, 0, 0); + } else { + /* The event is longer than 1 day, so we keep exactly + the same times, just using DATE-TIME rather than + DATE. */ + icaltime_adjust (&end_tt, 1, 0, 0, 0); + } + + /* Make sure that end > start using the timezones. */ + start_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->start_timezone)); + check_start_before_end (&start_tt, start_zone, + &end_tt, start_zone, + TRUE); + } + + event_page_set_show_timezone (epage, calendar_config_get_show_timezone() & !all_day); + gtk_signal_handler_block_by_data (GTK_OBJECT (priv->start_time), + epage); + gtk_signal_handler_block_by_data (GTK_OBJECT (priv->end_time), + epage); + + e_date_edit_set_date (E_DATE_EDIT (priv->start_time), start_tt.year, + start_tt.month, start_tt.day); + e_date_edit_set_time_of_day (E_DATE_EDIT (priv->start_time), + start_tt.hour, start_tt.minute); + + e_date_edit_set_date (E_DATE_EDIT (priv->end_time), end_tt.year, + end_tt.month, end_tt.day); + e_date_edit_set_time_of_day (E_DATE_EDIT (priv->end_time), + end_tt.hour, end_tt.minute); + + gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time), + epage); + gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time), + epage); + + /* Notify upstream */ + notify_dates_changed (epage, &start_tt, &end_tt); + + if (!priv->updating) + comp_editor_page_notify_changed (COMP_EDITOR_PAGE (epage)); + +} + +void +event_page_set_show_time_busy (EventPage *epage, gboolean state) +{ + epage->priv->show_time_as_busy = state; + if (!epage->priv->updating) + comp_editor_page_notify_changed (COMP_EDITOR_PAGE (epage)); + +} + +void +event_page_show_alarm (EventPage *epage) +{ + gtk_widget_show (epage->priv->alarm_dialog); +} + +void +event_page_set_show_timezone (EventPage *epage, gboolean state) +{ + if (state) { + gtk_widget_show_all (epage->priv->start_timezone); + gtk_widget_show (epage->priv->timezone_label); + } else { + gtk_widget_hide (epage->priv->start_timezone); + gtk_widget_hide (epage->priv->timezone_label); + } + +} + +void +event_page_set_show_categories (EventPage *epage, gboolean state) +{ + if (state) { + gtk_widget_show (epage->priv->categories_btn); + gtk_widget_show (epage->priv->categories); + } else { + gtk_widget_hide (epage->priv->categories_btn); + gtk_widget_hide (epage->priv->categories); + } +} + +/* Gets the widgets from the XML file and returns if they are all available. */ +static gboolean +get_widgets (EventPage *epage) +{ + CompEditorPage *page = COMP_EDITOR_PAGE (epage); + EventPagePrivate *priv; + GSList *accel_groups; + GtkWidget *toplevel; + GtkWidget *sw; + + priv = epage->priv; + +#define GW(name) glade_xml_get_widget (priv->xml, name) + + priv->main = GW ("event-page"); + if (!priv->main) + return FALSE; + + /* Get the GtkAccelGroup from the toplevel window, so we can install + it when the notebook page is mapped. */ + toplevel = gtk_widget_get_toplevel (priv->main); + accel_groups = gtk_accel_groups_from_object (G_OBJECT (toplevel)); + if (accel_groups) { + page->accel_group = accel_groups->data; + gtk_accel_group_ref (page->accel_group); + } + priv->alarm_dialog = GW ("alarm-dialog"); + priv->alarm = GW ("alarm"); + priv->alarm_time = GW ("alarm-time"); + priv->alarm_custom = GW ("alarm-custom"); + + priv->timezone_label = GW ("timezone-label"); + priv->start_timezone = GW ("start-timezone"); + priv->end_timezone = priv->start_timezone; + + if (!calendar_config_get_show_timezone()) { + gtk_widget_hide (priv->timezone_label); + gtk_widget_hide (priv->start_timezone); + } else { + gtk_widget_show (priv->timezone_label); + gtk_widget_show_all (priv->start_timezone); + } + priv->attendees_label = GW ("attendees-label"); + + gtk_widget_ref (priv->main); + gtk_container_remove (GTK_CONTAINER (priv->main->parent), priv->main); + + priv->categories = GW ("categories"); + priv->categories_btn = GW ("categories-button"); + priv->organizer = GW ("organizer"); + priv->summary = GW ("summary"); + priv->summary_label = GW ("summary-label"); + priv->location = GW ("location"); + priv->location_label = GW ("location-label"); + + priv->invite = GW ("invite"); + priv->add = GW ("add-attendee"); + priv->remove = GW ("remove-attendee"); + priv->list_box = GW ("list-box"); + + priv->calendar_label = GW ("calendar-label"); + priv->attendee_box = GW ("attendee-box"); + priv->org_cal_label = GW ("org-cal-label"); + + priv->list_view = e_meeting_list_view_new (priv->model); + + sw = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN); + gtk_widget_show (sw); + gtk_container_add (GTK_CONTAINER (sw), GTK_WIDGET (priv->list_view)); + gtk_box_pack_start (GTK_BOX (priv->list_box), sw, TRUE, TRUE, 0); + + + /* Glade's visibility flag doesn't seem to work for custom widgets */ + priv->start_time = GW ("start-time"); + gtk_widget_show (priv->start_time); + + priv->time_hour = GW ("time-hour"); + priv->hour_selector = GW ("hour_selector"); + priv->end_time_selector = GW ("end-time-selector"); + + priv->end_time = GW ("end-time"); + gtk_widget_show_all (priv->time_hour); + gtk_widget_hide (priv->end_time); + + priv->description = GW ("description"); + + priv->source_selector = GW ("source"); + +#undef GW + + return (priv->summary + && priv->location + && priv->start_time + && priv->end_time + && priv->description ); +} + +/* Callback used when the summary changes; we emit the notification signal. */ +static void +summary_changed_cb (GtkEditable *editable, gpointer data) +{ + EventPage *epage; + EventPagePrivate *priv; + gchar *summary; + + epage = EVENT_PAGE (data); + priv = epage->priv; + + if (priv->updating) + return; + + summary = e_dialog_editable_get (GTK_WIDGET (editable)); + comp_editor_page_notify_summary_changed (COMP_EDITOR_PAGE (epage), + summary); + g_free (summary); +} + + +/* Note that this assumes that the start_tt and end_tt passed to it are the + dates visible to the user. For DATE values, we have to add 1 day to the + end_tt before emitting the signal. */ +static void +notify_dates_changed (EventPage *epage, struct icaltimetype *start_tt, + struct icaltimetype *end_tt) +{ + EventPagePrivate *priv; + CompEditorPageDates dates; ECalComponentDateTime start_dt, end_dt; gboolean all_day_event; - icaltimezone *start_zone = NULL, *end_zone = NULL; - + icaltimezone *start_zone = NULL; priv = epage->priv; - all_day_event = e_dialog_toggle_get (priv->all_day_event); + all_day_event = priv->all_day_event; start_dt.value = start_tt; end_dt.value = end_tt; @@ -1259,11 +2152,10 @@ notify_dates_changed (EventPage *epage, struct icaltimetype *start_tt, icaltime_adjust (end_tt, 1, 0, 0, 0); } else { start_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->start_timezone)); - end_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->end_timezone)); } start_dt.tzid = start_zone ? icaltimezone_get_tzid (start_zone) : NULL; - end_dt.tzid = end_zone ? icaltimezone_get_tzid (end_zone) : NULL; + end_dt.tzid = start_zone ? icaltimezone_get_tzid (start_zone) : NULL; dates.start = &start_dt; dates.end = &end_dt; @@ -1331,7 +2223,7 @@ times_updated (EventPage *epage, gboolean adjust_end_time) struct icaltimetype end_tt = icaltime_null_time(); gboolean date_set, all_day_event; gboolean set_start_date = FALSE, set_end_date = FALSE; - icaltimezone *start_zone, *end_zone; + icaltimezone *start_zone; priv = epage->priv; @@ -1339,7 +2231,7 @@ times_updated (EventPage *epage, gboolean adjust_end_time) return; /* Fetch the start and end times and timezones from the widgets. */ - all_day_event = e_dialog_toggle_get (priv->all_day_event); + all_day_event = priv->all_day_event; date_set = e_date_edit_get_date (E_DATE_EDIT (priv->start_time), &start_tt.year, @@ -1380,10 +2272,9 @@ times_updated (EventPage *epage, gboolean adjust_end_time) &end_tt.minute); start_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->start_timezone)); - end_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->end_timezone)); if (check_start_before_end (&start_tt, start_zone, - &end_tt, end_zone, + &end_tt, start_zone, adjust_end_time)) { if (adjust_end_time) set_end_date = TRUE; @@ -1448,159 +2339,13 @@ start_timezone_changed_cb (GtkWidget *widget, gpointer data) zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->start_timezone)); priv->updating = TRUE; e_timezone_entry_set_timezone (E_TIMEZONE_ENTRY (priv->end_timezone), zone); + gtk_widget_show_all (priv->end_timezone); priv->updating = FALSE; } times_updated (epage, TRUE); } - -/* Callback used when the end timezone is changed. It checks if the end - * timezone is the same as the start timezone and sets sync_timezones if so. - */ -static void -end_timezone_changed_cb (GtkWidget *widget, gpointer data) -{ - EventPage *epage; - EventPagePrivate *priv; - icaltimezone *start_zone, *end_zone; - - epage = EVENT_PAGE (data); - priv = epage->priv; - - start_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->start_timezone)); - end_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->end_timezone)); - - priv->sync_timezones = (start_zone == end_zone) ? TRUE : FALSE; - - times_updated (epage, TRUE); -} - -/* Callback: all day event button toggled. - * Note that this should only be called when the user explicitly toggles the - * button. Be sure to block this handler when the toggle button's state is set - * within the code. - */ -static void -all_day_event_toggled_cb (GtkWidget *toggle, gpointer data) -{ - EventPage *epage; - EventPagePrivate *priv; - gboolean all_day; - struct icaltimetype start_tt = icaltime_null_time(); - struct icaltimetype end_tt = icaltime_null_time(); - gboolean date_set; - - epage = EVENT_PAGE (data); - priv = epage->priv; - - /* When the all_day toggle is turned on, the start date is - * rounded down to the start of the day, and end date is - * rounded down to the start of the day on which the event - * ends. The event is then taken to be inclusive of the days - * between the start and end days. Note that if the event end - * is at midnight, we round it down to the previous day, so the - * event times stay the same. - * - * When the all_day_toggle is turned off, then if the event is within - * one day, we set the event start to the start of the working day, - * and set the event end to one hour after it. If the event is longer - * than one day, we set the event end to the end of the day it is on, - * so that the actual event times remain the same. - * - * This may need tweaking to work well with different timezones used - * in the event start & end. - */ - all_day = GTK_TOGGLE_BUTTON (toggle)->active; - - set_all_day (epage, all_day); - - date_set = e_date_edit_get_date (E_DATE_EDIT (priv->start_time), - &start_tt.year, - &start_tt.month, - &start_tt.day); - e_date_edit_get_time_of_day (E_DATE_EDIT (priv->start_time), - &start_tt.hour, - &start_tt.minute); - g_assert (date_set); - - date_set = e_date_edit_get_date (E_DATE_EDIT (priv->end_time), - &end_tt.year, - &end_tt.month, - &end_tt.day); - e_date_edit_get_time_of_day (E_DATE_EDIT (priv->end_time), - &end_tt.hour, - &end_tt.minute); - g_assert (date_set); - - if (all_day) { - /* Round down to the start of the day. */ - start_tt.hour = 0; - start_tt.minute = 0; - start_tt.second = 0; - start_tt.is_date = TRUE; - - /* Round down to the start of the day, or the start of the - previous day if it is midnight. */ - icaltime_adjust (&end_tt, 0, 0, 0, -1); - end_tt.hour = 0; - end_tt.minute = 0; - end_tt.second = 0; - end_tt.is_date = TRUE; - } else { - icaltimezone *start_zone, *end_zone; - - if (end_tt.year == start_tt.year - && end_tt.month == start_tt.month - && end_tt.day == start_tt.day) { - /* The event is within one day, so we set the event - start to the start of the working day, and the end - to one hour later. */ - start_tt.hour = calendar_config_get_day_start_hour (); - start_tt.minute = calendar_config_get_day_start_minute (); - start_tt.second = 0; - - end_tt = start_tt; - icaltime_adjust (&end_tt, 0, 1, 0, 0); - } else { - /* The event is longer than 1 day, so we keep exactly - the same times, just using DATE-TIME rather than - DATE. */ - icaltime_adjust (&end_tt, 1, 0, 0, 0); - } - - /* Make sure that end > start using the timezones. */ - start_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->start_timezone)); - end_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->end_timezone)); - check_start_before_end (&start_tt, start_zone, - &end_tt, end_zone, - TRUE); - } - - gtk_signal_handler_block_by_data (GTK_OBJECT (priv->start_time), - epage); - gtk_signal_handler_block_by_data (GTK_OBJECT (priv->end_time), - epage); - - e_date_edit_set_date (E_DATE_EDIT (priv->start_time), start_tt.year, - start_tt.month, start_tt.day); - e_date_edit_set_time_of_day (E_DATE_EDIT (priv->start_time), - start_tt.hour, start_tt.minute); - - e_date_edit_set_date (E_DATE_EDIT (priv->end_time), end_tt.year, - end_tt.month, end_tt.day); - e_date_edit_set_time_of_day (E_DATE_EDIT (priv->end_time), - end_tt.hour, end_tt.minute); - - gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time), - epage); - gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time), - epage); - - /* Notify upstream */ - notify_dates_changed (epage, &start_tt, &end_tt); -} - /* Callback used when the categories button is clicked; we must bring up the * category list dialog. */ @@ -1618,15 +2363,13 @@ categories_clicked_cb (GtkWidget *button, gpointer data) e_categories_config_open_dialog_for_entry (GTK_ENTRY (entry)); } -static void -e_sendoptions_clicked_cb (GtkWidget *button, gpointer data) +void +event_page_sendoptions_clicked_cb (EventPage *epage) { - EventPage *epage; EventPagePrivate *priv; GtkWidget *toplevel; ESource *source; - epage = EVENT_PAGE (data); priv = epage->priv; if (!priv->sod) { @@ -1834,6 +2577,7 @@ init_widgets (EventPage *epage) GtkTextBuffer *text_buffer; icaltimezone *zone; char *menu_label = NULL; + GtkTreeSelection *selection; priv = epage->priv; @@ -1861,29 +2605,66 @@ init_widgets (EventPage *epage) g_signal_connect((priv->end_time), "changed", G_CALLBACK (date_changed_cb), epage); - g_signal_connect((priv->start_timezone), "changed", - G_CALLBACK (start_timezone_changed_cb), epage); - g_signal_connect((priv->end_timezone), "changed", - G_CALLBACK (end_timezone_changed_cb), epage); - - g_signal_connect((priv->all_day_event), "toggled", - G_CALLBACK (all_day_event_toggled_cb), epage); - - /* Categories button */ + /* Categories */ g_signal_connect((priv->categories_btn), "clicked", G_CALLBACK (categories_clicked_cb), epage); - - /* send options button */ - g_signal_connect((priv->sendoptions_button), "clicked", - G_CALLBACK (e_sendoptions_clicked_cb), epage); - + /* Source selector */ g_signal_connect((priv->source_selector), "source_selected", G_CALLBACK (source_changed_cb), epage); - /* Alarms */ priv->alarm_list_store = e_alarm_list_new (); + /* Timezone changed */ + g_signal_connect((priv->start_timezone), "changed", + G_CALLBACK (start_timezone_changed_cb), epage); + + e_meeting_list_view_column_set_visible (priv->list_view, "Attendee ", calendar_config_get_show_attendee()); + e_meeting_list_view_column_set_visible (priv->list_view, "Role", calendar_config_get_show_role()); + e_meeting_list_view_column_set_visible (priv->list_view, "RSVP", calendar_config_get_show_rsvp()); + e_meeting_list_view_column_set_visible (priv->list_view, "Status", calendar_config_get_show_status()); + e_meeting_list_view_column_set_visible (priv->list_view, "Type", calendar_config_get_show_type()); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->list_view)); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE); + + g_signal_connect (G_OBJECT (priv->list_view), "button_press_event", G_CALLBACK (button_press_event), epage); + g_signal_connect (G_OBJECT (priv->list_view), "event", G_CALLBACK (list_view_event), epage); + g_signal_connect (priv->list_view, "key_press_event", G_CALLBACK (list_key_press), epage); + + /* Add attendee button */ + g_signal_connect (priv->add, "clicked", G_CALLBACK (add_clicked_cb), epage); + + /* Remove attendee button */ + g_signal_connect (priv->remove, "clicked", G_CALLBACK (remove_clicked_cb), epage); + + /* Contacts button */ + g_signal_connect(priv->invite, "clicked", G_CALLBACK (invite_cb), epage); + + /* Alarm dialog */ + g_signal_connect (GTK_DIALOG (priv->alarm_dialog), "response", G_CALLBACK (gtk_widget_hide), priv->alarm_dialog); + gtk_widget_hide (priv->alarm_dialog); + + /* Meeting List View */ + g_signal_connect (priv->list_view, "attendee_added", G_CALLBACK (attendee_added_cb), epage); + + gtk_widget_show (GTK_WIDGET (priv->list_view)); + + /* categories */ + if (!calendar_config_get_show_categories()) { + gtk_widget_hide (priv->categories_btn); + gtk_widget_hide (priv->categories); + } else { + gtk_widget_show (priv->categories_btn); + gtk_widget_show (priv->categories); + } + + /* End time selector */ + gtk_option_menu_set_history ((GtkOptionMenu *) priv->end_time_selector, 1); + gtk_widget_hide (priv->time_hour); + gtk_widget_show (priv->end_time); + g_signal_connect (priv->end_time_selector, "changed", G_CALLBACK (time_sel_changed), priv); + /* Add the user defined time if necessary */ priv->alarm_units = calendar_config_get_default_reminder_units (); priv->alarm_interval = calendar_config_get_default_reminder_interval (); @@ -1929,10 +2710,6 @@ init_widgets (EventPage *epage) g_signal_connect (priv->alarm_custom, "clicked", G_CALLBACK (alarm_custom_clicked_cb), epage); - /* Connect the default signal handler to use to make sure we notify - * upstream of changes to the widget values. - */ - /* Belongs to priv->description */ g_signal_connect((text_buffer), "changed", G_CALLBACK (field_changed_cb), epage); @@ -1945,32 +2722,22 @@ init_widgets (EventPage *epage) G_CALLBACK (field_changed_cb), epage); g_signal_connect((priv->end_time), "changed", G_CALLBACK (field_changed_cb), epage); - g_signal_connect((priv->start_timezone), "changed", - G_CALLBACK (field_changed_cb), epage); - g_signal_connect((priv->end_timezone), "changed", - G_CALLBACK (field_changed_cb), epage); - g_signal_connect((priv->all_day_event), "toggled", - G_CALLBACK (field_changed_cb), epage); - g_signal_connect((priv->classification), - "changed", G_CALLBACK (field_changed_cb), - epage); - g_signal_connect((priv->show_time_as_busy), - "toggled", G_CALLBACK (field_changed_cb), - epage); - g_signal_connect((priv->alarm), - "toggled", G_CALLBACK (field_changed_cb), - epage); - g_signal_connect((priv->alarm_time), - "changed", G_CALLBACK (field_changed_cb), - epage); g_signal_connect((priv->categories), "changed", G_CALLBACK (field_changed_cb), epage); + g_signal_connect (priv->alarm, + "toggled", G_CALLBACK (alarm_changed_cb), + epage); + g_signal_connect (priv->alarm_custom, "clicked", + G_CALLBACK (alarm_custom_clicked_cb), epage); + /* Set the default timezone, so the timezone entry may be hidden. */ zone = calendar_config_get_icaltimezone (); e_timezone_entry_set_default_timezone (E_TIMEZONE_ENTRY (priv->start_timezone), zone); e_timezone_entry_set_default_timezone (E_TIMEZONE_ENTRY (priv->end_timezone), zone); + event_page_set_show_timezone (epage, calendar_config_get_show_timezone()); + return TRUE; } @@ -1986,11 +2753,19 @@ init_widgets (EventPage *epage) * created. **/ EventPage * -event_page_construct (EventPage *epage) +event_page_construct (EventPage *epage, EMeetingStore *model, ECal *client) { EventPagePrivate *priv; + char *backend_address = NULL; + EIterator *it; + EAccount *def_account; + GList *address_strings = NULL, *l; + EAccount *a; priv = epage->priv; + g_object_ref (model); + priv->model = model; + priv->client = client; priv->xml = glade_xml_new (EVOLUTION_GLADEDIR "/event-page.glade", NULL, NULL); @@ -2006,6 +2781,50 @@ event_page_construct (EventPage *epage) return NULL; } + /* Address information */ + if (!e_cal_get_cal_address (client, &backend_address, NULL)) + return NULL; + + priv->accounts = itip_addresses_get (); + def_account = itip_addresses_get_default(); + for (it = e_list_get_iterator((EList *)priv->accounts); + e_iterator_is_valid(it); + e_iterator_next(it)) { + a = (EAccount *)e_iterator_get(it); + char *full; + + full = g_strdup_printf("%s <%s>", a->id->name, a->id->address); + + address_strings = g_list_append(address_strings, full); + + /* Note that the address specified by the backend gets + * precedence over the default mail address. + */ + if (backend_address && !strcmp (backend_address, a->id->address)) { + if (priv->default_address) + g_free (priv->default_address); + + priv->default_address = g_strdup (full); + } else if (a == def_account && !priv->default_address) { + priv->default_address = g_strdup (full); + } + } + + if (backend_address) + g_free (backend_address); + + g_object_unref(it); + + if (address_strings) + gtk_combo_set_popdown_strings (GTK_COMBO (priv->organizer), address_strings); + else + g_warning ("No potential organizers!"); + + for (l = address_strings; l != NULL; l = l->next) + g_free (l->data); + g_list_free (address_strings); + + if (!init_widgets (epage)) { g_message ("event_page_construct(): " "Could not initialize the widgets!"); @@ -2024,16 +2843,18 @@ event_page_construct (EventPage *epage) * not be created. **/ EventPage * -event_page_new (void) +event_page_new (EMeetingStore *model, ECal *client, BonoboUIComponent *uic) { EventPage *epage; epage = g_object_new (TYPE_EVENT_PAGE, NULL); - if (!event_page_construct (epage)) { + if (!event_page_construct (epage, model, client)) { g_object_unref (epage); return NULL; } + epage->priv->uic = uic; + return epage; } @@ -2075,3 +2896,45 @@ event_page_create_source_option_menu (void) gtk_widget_show (menu); return menu; } + +static void +set_attendees (ECalComponent *comp, const GPtrArray *attendees) +{ + GSList *comp_attendees = NULL, *l; + int i; + + for (i = 0; i < attendees->len; i++) { + EMeetingAttendee *ia = g_ptr_array_index (attendees, i); + ECalComponentAttendee *ca; + + ca = e_meeting_attendee_as_e_cal_component_attendee (ia); + + comp_attendees = g_slist_prepend (comp_attendees, ca); + + } + comp_attendees = g_slist_reverse (comp_attendees); + + e_cal_component_set_attendee_list (comp, comp_attendees); + + for (l = comp_attendees; l != NULL; l = l->next) + g_free (l->data); + g_slist_free (comp_attendees); +} + +ECalComponent * +event_page_get_cancel_comp (EventPage *page) +{ + EventPagePrivate *priv; + + g_return_val_if_fail (page != NULL, NULL); + g_return_val_if_fail (IS_EVENT_PAGE (page), NULL); + + priv = page->priv; + + if (priv->deleted_attendees->len == 0) + return NULL; + + set_attendees (priv->comp, priv->deleted_attendees); + + return e_cal_component_clone (priv->comp); +} diff --git a/calendar/gui/dialogs/event-page.glade b/calendar/gui/dialogs/event-page.glade index 34c5a3847f..4d9b124d0d 100644 --- a/calendar/gui/dialogs/event-page.glade +++ b/calendar/gui/dialogs/event-page.glade @@ -15,6 +15,7 @@ False GDK_WINDOW_TYPE_HINT_NORMAL GDK_GRAVITY_NORTH_WEST + True @@ -23,58 +24,16 @@ False 6 - - - True - <b>Basics</b> - False - True - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - - - 0 - False - False - - - True False 0 - - - True - - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 12 - 0 - - - 0 - False - False - - - True - 5 + 9 2 False 6 @@ -89,17 +48,21 @@ GTK_JUSTIFY_CENTER False False - 7.45058e-09 + 7.45058015283e-09 0.5 0 0 summary + PANGO_ELLIPSIZE_NONE + -1 + False + 0 0 1 - 0 - 1 + 2 + 3 fill @@ -114,14 +77,14 @@ 0 True - * + * False 1 2 - 0 - 1 + 2 + 3 @@ -135,17 +98,21 @@ GTK_JUSTIFY_CENTER False False - 7.45058e-09 + 7.45058015283e-09 0.5 0 0 location + PANGO_ELLIPSIZE_NONE + -1 + False + 0 0 1 - 1 - 2 + 3 + 4 fill @@ -160,14 +127,14 @@ 0 True - * + * False 1 2 - 1 - 2 + 3 + 4 @@ -206,115 +173,159 @@ 1 2 - 4 - 5 + 7 + 8 expand|shrink|fill expand|shrink|fill - + True - Classi_fication: + _Description: True False GTK_JUSTIFY_CENTER False False - 7.45058e-09 + 7.45058015283e-09 + 0 + 0 + 0 + description + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 7 + 8 + fill + fill + + + + + + True + Or_ganizer: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 0.5 0 0 - classification + PANGO_ELLIPSIZE_NONE + -1 + False + 0 0 1 - 2 - 3 + 0 + 1 fill - + True - False - 6 + True + 0 - + True - True - 0 - - - - - - - True - Public - True - - + False + True + False + True + False - - - True - Private - True - - + + + True + True + True + True + 0 + + True + * + False + + - - - True - Confidential - True - - + + + True + GTK_SELECTION_BROWSE - 0 + 2 True True - + True - Cale_ndar: - True - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - source - - - 0 - False - False - - + False + 0 - - - True - event_page_create_source_option_menu - 0 - 0 - Wed, 17 Dec 2003 18:20:26 GMT + + + True + Cale_ndar: + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + source + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + False + False + + + + + + True + event_page_create_source_option_menu + 0 + 0 + Wed, 17 Dec 2003 18:20:26 GMT + + + 0 + True + True + + 0 @@ -326,67 +337,199 @@ 1 2 - 2 - 3 + 0 + 1 fill fill - + True - True - Ca_tegories... - True - GTK_RELIEF_NORMAL - True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-jump-to + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Atte_ndees... + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + 0 1 - 3 - 4 + 1 + 2 fill - + fill - + + 150 True - True - True - True - 0 - - True - * - False + False + 10 + + + + + + + + True + GTK_BUTTONBOX_START + 0 + + + + True + True + True + gtk-add + True + GTK_RELIEF_NORMAL + True + + + + + + True + True + True + gtk-remove + True + GTK_RELIEF_NORMAL + True + + + + + + True + True + True + gtk-edit + True + GTK_RELIEF_NORMAL + True + + + + + 0 + False + True + GTK_PACK_END + + 1 2 - 3 - 4 - + 1 + 2 + fill + fill - + True - _Description: + _Time: True False GTK_JUSTIFY_CENTER False False - 7.45058e-09 - 0 + 0 + 0.5 0 0 - description + PANGO_ELLIPSIZE_NONE + -1 + False + 0 0 @@ -394,281 +537,380 @@ 4 5 fill - fill + - - - 0 - True - True - - - - - 0 - True - True - - - - - True - <b>Date and Time</b> - False - True - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - - - 0 - False - False - - + + + True + False + 0 - - - True - False - 0 + + + True + make_date_edit + 0 + 0 + Sun, 09 Oct 2005 05:53:12 GMT + + + 2 + False + False + + - - - True - - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 12 - 0 - - - 0 - False - False - - + + + True + False + 0 - - - 6 - True - 4 - 4 - False - 6 - 6 + + + True + True + 0 - - - True - True - make_date_edit - 0 - 0 - Tue, 16 May 2000 19:11:05 GMT - - - - - - 1 - 2 - 0 - 1 - - - + + - - - True - True - make_date_edit - 0 - 0 - Tue, 16 May 2000 19:11:10 GMT - - - + + + True + for + True + + + + + + + True + until + True + + + + + + + + 2 + False + False + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + 1 + 1 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 24 0.5 1 1 + + + 0 + False + False + + + + + + True + hours + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + False + False + + + + + 2 + False + False + + + + + + True + make_date_edit + 0 + 0 + Sun, 09 Oct 2005 06:12:10 GMT + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + False + False + + 1 2 - 1 - 2 - - - - - - - True - make_timezone_entry - 0 - 0 - Mon, 18 Jun 2001 23:51:40 GMT - - - 2 - 3 - 1 - 2 - + 4 + 5 + fill fill - + True - _Start time: + Time _zone: True False - GTK_JUSTIFY_CENTER + GTK_JUSTIFY_LEFT False False 0 0.5 0 0 - start-time + PANGO_ELLIPSIZE_NONE + -1 + False + 0 0 1 - 0 - 1 + 5 + 6 fill - + True - _End time: - True - False - GTK_JUSTIFY_CENTER - False - False - 0 - 0.5 - 0 - 0 - end-time + make_timezone_entry + 0 + 0 + Mon, 10 Oct 2005 11:05:54 GMT - 0 - 1 - 1 - 2 + 1 + 2 + 5 + 6 fill - + fill - + True True - A_ll day event + Ca_tegories... True GTK_RELIEF_NORMAL True - False - False - True - 3 - 4 - 0 - 1 + 0 + 1 + 6 + 7 fill - - True - make_timezone_entry - 0 - 0 - Mon, 18 Jun 2001 23:51:34 GMT - - - 2 - 3 - 0 - 1 - - fill - - - - - + True True - Show time as bus_y - True - GTK_RELIEF_NORMAL - True - False - False - True + True + True + 0 + + True + * + False - 3 - 4 - 1 - 2 - fill + 1 + 2 + 6 + 7 + + + 0 + True + True + + + + + 0 + True + True + + + + + + + + 4 + True + Alarms + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER_ON_PARENT + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + True + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-close + True + GTK_RELIEF_NORMAL + True + -7 + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + False + 0 + + + + True + False + 2 - + True - True - Ala_rm - True - GTK_RELIEF_NORMAL - True - False - False - True + False + 0 + + + + True + True + _Set alarm + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 4 + False + False + + + + + + - 0 - 1 - 2 - 3 - fill - + 4 + False + False - + True False - 6 + 0 @@ -677,13 +919,14 @@ 0 - + True 15 minutes before appointment True + @@ -692,21 +935,23 @@ True 1 hour before appointment True + - + True - 1 day before appointment + 1day before appointment True + - 0 + 4 False False @@ -720,7 +965,7 @@ True - + True 0.5 0.5 @@ -732,13 +977,13 @@ 0 - + True False 2 - + True gtk-preferences 4 @@ -755,9 +1000,9 @@ - + True - C_ustomize... + C_ustomize True False GTK_JUSTIFY_LEFT @@ -767,6 +1012,10 @@ 0.5 0 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 0 @@ -780,41 +1029,16 @@ - 0 + 4 False False - 1 - 4 - 2 - 3 - fill - fill - - - - - - This appointment has customized alarms - False - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - - - 1 - 2 - 3 - 4 - + 8 + True + True @@ -827,66 +1051,8 @@ 0 - False - False - - - - - - 0 - 0.5 - GTK_SHADOW_NONE - - - - 12 - True - 0.5 - 0.5 - 0.06 - 1 - 0 - 0 - 0 - 253 - - - - True - True - Ad_vanced send options - True - GTK_RELIEF_NORMAL - True - - - - - - - - True - <b>Send Options</b> - False - True - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - - - label_item - - - - - 0 - False - False + True + True diff --git a/calendar/gui/dialogs/event-page.h b/calendar/gui/dialogs/event-page.h index 30b84a1621..50bac28a65 100644 --- a/calendar/gui/dialogs/event-page.h +++ b/calendar/gui/dialogs/event-page.h @@ -24,7 +24,13 @@ #ifndef EVENT_PAGE_H #define EVENT_PAGE_H +#include +#include +#include #include "comp-editor-page.h" +#include "../e-meeting-attendee.h" +#include "../e-meeting-store.h" +#include "../e-meeting-list-view.h" G_BEGIN_DECLS @@ -51,11 +57,29 @@ typedef struct { GtkType event_page_get_type (void); -EventPage *event_page_construct (EventPage *epage); -EventPage *event_page_new (void); +EventPage *event_page_construct (EventPage *epage, EMeetingStore *model, ECal *client); +EventPage *event_page_new (EMeetingStore *model, ECal *client, BonoboUIComponent *uic); +ECalComponent *event_page_get_cancel_comp (EventPage *page); void event_page_show_options (EventPage *page); void event_page_hide_options (EventPage *page); +void event_page_sendoptions_clicked_cb (EventPage *epage); void event_page_set_meeting (EventPage *page, gboolean set); +void event_page_set_show_timezone (EventPage *epage, gboolean state); +void event_page_set_view_rsvp (EventPage *epage, gboolean state); +void event_page_set_classification (EventPage *epage, ECalComponentClassification class); +void event_page_set_delegate (EventPage *page, gboolean set); +void event_page_set_all_day_event (EventPage *epage, gboolean all_day); +void event_page_set_show_categories (EventPage *epage, gboolean state); +void event_page_set_show_time_busy (EventPage *epage, gboolean state); +void event_page_show_alarm (EventPage *epage); + +void event_page_set_view_attendee (EventPage *epage, gboolean state); +void event_page_set_view_role (EventPage *epage, gboolean state); +void event_page_set_view_status (EventPage *epage, gboolean state); +void event_page_set_view_type (EventPage *epage, gboolean state); +void event_page_set_view_rvsp (EventPage *epage, gboolean state); + + G_END_DECLS diff --git a/calendar/gui/dialogs/memo-editor.c b/calendar/gui/dialogs/memo-editor.c index 7946198e9b..f81d1fd9cd 100644 --- a/calendar/gui/dialogs/memo-editor.c +++ b/calendar/gui/dialogs/memo-editor.c @@ -127,7 +127,7 @@ memo_editor_construct (MemoEditor *me, ECal *client) gtk_object_sink (GTK_OBJECT (priv->memo_page)); comp_editor_append_page (COMP_EDITOR (me), COMP_EDITOR_PAGE (priv->memo_page), - _("Memo")); + _("Memo"), TRUE); g_signal_connect (G_OBJECT (priv->memo_page), "client_changed", G_CALLBACK (client_changed_cb), me); diff --git a/calendar/gui/dialogs/schedule-page.c b/calendar/gui/dialogs/schedule-page.c index cec71cb815..9b0e0a0ee9 100644 --- a/calendar/gui/dialogs/schedule-page.c +++ b/calendar/gui/dialogs/schedule-page.c @@ -431,6 +431,7 @@ schedule_page_construct (SchedulePage *spage, EMeetingStore *ems) /* Selector */ priv->sel = E_MEETING_TIME_SELECTOR (e_meeting_time_selector_new (ems)); + gtk_widget_set_size_request ((GtkWidget *) priv->sel, -1, 400); e_meeting_time_selector_set_working_hours (priv->sel, calendar_config_get_day_start_hour (), calendar_config_get_day_start_minute (), diff --git a/calendar/gui/dialogs/task-editor.c b/calendar/gui/dialogs/task-editor.c index 5cb865d5d2..b5fdc9bd24 100644 --- a/calendar/gui/dialogs/task-editor.c +++ b/calendar/gui/dialogs/task-editor.c @@ -134,7 +134,7 @@ task_editor_construct (TaskEditor *te, ECal *client) gtk_object_sink (GTK_OBJECT (priv->task_page)); comp_editor_append_page (COMP_EDITOR (te), COMP_EDITOR_PAGE (priv->task_page), - _("_Task")); + _("_Task"), TRUE); g_signal_connect (G_OBJECT (priv->task_page), "client_changed", G_CALLBACK (client_changed_cb), te); @@ -143,7 +143,7 @@ task_editor_construct (TaskEditor *te, ECal *client) gtk_object_sink (GTK_OBJECT (priv->task_details_page)); comp_editor_append_page (COMP_EDITOR (te), COMP_EDITOR_PAGE (priv->task_details_page), - _("_Status")); + _("_Status"), TRUE); if (!e_cal_is_read_only (client, &read_only, NULL)) read_only = TRUE; @@ -158,7 +158,7 @@ task_editor_construct (TaskEditor *te, ECal *client) gtk_object_sink (GTK_OBJECT (priv->meet_page)); comp_editor_append_page (COMP_EDITOR (te), COMP_EDITOR_PAGE (priv->meet_page), - _("Assig_nment")); + _("Assig_nment"), TRUE); } comp_editor_set_e_cal (COMP_EDITOR (te), client); @@ -220,7 +220,7 @@ task_editor_edit_comp (CompEditor *editor, ECalComponent *comp) if (!priv->assignment_shown) comp_editor_append_page (COMP_EDITOR (te), COMP_EDITOR_PAGE (priv->meet_page), - _("Assig_nment")); + _("Assig_nment"), TRUE); for (l = attendees; l != NULL; l = l->next) { ECalComponentAttendee *ca = l->data; @@ -377,7 +377,7 @@ show_assignment (TaskEditor *te) if (!priv->assignment_shown) { comp_editor_append_page (COMP_EDITOR (te), COMP_EDITOR_PAGE (priv->meet_page), - _("Assig_nment")); + _("Assig_nment"), TRUE); priv->assignment_shown = TRUE; comp_editor_set_needs_send (COMP_EDITOR (te), priv->assignment_shown); -- cgit v1.2.3