From ee804aafe11507b85a3626480aa406b16b8104da Mon Sep 17 00:00:00 2001 From: Chenthill Palanisamy Date: Wed, 16 Nov 2005 13:53:47 +0000 Subject: UI changes for task editor. svn path=/trunk/; revision=30626 --- calendar/ChangeLog | 49 + calendar/gui/apps_evolution_calendar.schemas.in.in | 14 +- calendar/gui/calendar-config.c | 17 - calendar/gui/calendar-config.h | 11 +- calendar/gui/dialogs/event-page.c | 30 +- calendar/gui/dialogs/event-page.h | 1 - calendar/gui/dialogs/task-editor.c | 395 ++++++-- calendar/gui/dialogs/task-page.c | 1008 ++++++++++++++++++-- calendar/gui/dialogs/task-page.glade | 783 +++++++-------- calendar/gui/dialogs/task-page.h | 21 +- 10 files changed, 1720 insertions(+), 609 deletions(-) (limited to 'calendar') diff --git a/calendar/ChangeLog b/calendar/ChangeLog index 090ab33535..51fbd16f17 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,52 @@ +2005-11-16 Chenthill Palanisamy + + Reviewed/Edited the patch from Srinivasa Ragavan + + * gui/apps_evolution_calendar.schemas.in.in: + * gui/calendar-config.c: + * gui/calendar-config.h: Removed the view_attendee function and its + gconf keys. + * gui/dialogs/event-editor.c: (menu_action_recurrence_cb), + (menu_action_recurrence_cmd), (event_editor_init), + (event_editor_construct): + * gui/dialogs/event-page.c: (sensitize_widgets): Do not sensitize + labels. + (set_classification_menu), (event_page_set_classification), + (event_page_fill_widgets), (event_page_fill_component), + (init_widgets): + * gui/dialogs/event-page.h:Corrected the spelling of recurrence and + removed the printf's. + * gui/dialogs/task-editor.c: (menu_view_role_cb), + (menu_view_status_cb), (menu_view_type_cb), (menu_view_rsvp_cb), + (menu_show_time_zone_cb), (menu_show_categories_cb), + (menu_class_public_cb), (menu_class_private_cb), + (menu_class_confidential_cb), (menu_option_status_cb), + (menu_insert_send_options_cmd), (menu_show_time_zone_cmd), + (menu_option_status_cmd), (task_editor_init), + (task_editor_construct), (task_editor_edit_comp), + (task_editor_send_comp), (task_editor_finalize), (show_assignment), + (task_editor_show_assignment): + * gui/dialogs/task-page.c: (task_page_init), (cleanup_attendees), + (task_page_finalize), (set_classification_menu), (clear_widgets), + (task_page_set_view_role), (task_page_set_view_status), + (task_page_set_view_type), (task_page_set_view_rsvp), + (task_page_set_classification), (sensitize_widgets), + (task_page_hide_options), (task_page_show_options), + (task_page_set_assignment), (get_current_account), + (task_page_fill_widgets), (set_attendees), + (task_page_fill_component), (add_clicked_cb), (existing_attendee), + (remove_attendee), (remove_clicked_cb), (invite_cb), + (attendee_added_cb), (popup_add_cb), (popup_delete_cb), + (context_popup_free), (button_press_event), (list_view_event), + (list_key_press), (task_page_set_show_timezone), + (task_page_set_show_categories), (task_page_fill_timezones), + (get_widgets), (date_changed_cb), (timezone_changed_cb), + (task_page_sendoptions_clicked_cb), (init_widgets), + (task_page_construct), (task_page_new), + (task_page_get_cancel_comp): + * gui/dialogs/task-page.glade: + * gui/dialogs/task-page.h: UI changes for task editor. + 2005-11-16 Irene Huang * gui/e-cal-model-memos.c: struct _ECalModelMemosPrivate diff --git a/calendar/gui/apps_evolution_calendar.schemas.in.in b/calendar/gui/apps_evolution_calendar.schemas.in.in index 7352fc4fd7..8ae9adadc0 100644 --- a/calendar/gui/apps_evolution_calendar.schemas.in.in +++ b/calendar/gui/apps_evolution_calendar.schemas.in.in @@ -27,19 +27,7 @@ - - /schemas/apps/evolution/calendar/display/show_attendee - /apps/evolution/calendar/display/show_attendee - evolution-calendar - bool - true - - Show Attendee field in the event/task/meeting editor - Whether to show attendee field in the event/task/meeting editor - - - - + /schemas/apps/evolution/calendar/display/show_role /apps/evolution/calendar/display/show_role evolution-calendar diff --git a/calendar/gui/calendar-config.c b/calendar/gui/calendar-config.c index fa992d7885..5fcde9d5b9 100644 --- a/calendar/gui/calendar-config.c +++ b/calendar/gui/calendar-config.c @@ -268,23 +268,6 @@ calendar_config_add_notification_24_hour_format (GConfClientNotifyFunc func, gpo return id; } -/* Show Attendee */ -gboolean -calendar_config_get_show_attendee (void) -{ - calendar_config_init (); - - return gconf_client_get_bool (config, CALENDAR_CONFIG_SHOW_ATTENDEE, NULL); -} - -void -calendar_config_set_show_attendee (gboolean state) -{ - calendar_config_init (); - - gconf_client_set_bool (config, CALENDAR_CONFIG_SHOW_ATTENDEE, state, NULL); -} - /* Show RSVP*/ gboolean calendar_config_get_show_rsvp (void) diff --git a/calendar/gui/calendar-config.h b/calendar/gui/calendar-config.h index e1dcf70544..b111dbe04c 100644 --- a/calendar/gui/calendar-config.h +++ b/calendar/gui/calendar-config.h @@ -112,13 +112,6 @@ gboolean calendar_config_get_24_hour_format (void); void calendar_config_set_24_hour_format (gboolean use_24_hour); guint calendar_config_add_notification_24_hour_format (GConfClientNotifyFunc func, gpointer data); -/* Fields to show/hide */ -gboolean calendar_config_get_show_attendee (void); -void calendar_config_set_show_attendee (gboolean status); - -gboolean calendar_config_get_show_role (void); -void calendar_config_set_show_role (gboolean status); - gboolean calendar_config_get_show_status (void); void calendar_config_set_show_status (gboolean status); @@ -134,6 +127,10 @@ void calendar_config_set_show_timezone (gboolean status); gboolean calendar_config_get_show_categories (void); void calendar_config_set_show_categories (gboolean status); +gboolean calendar_config_get_show_role (void); +void calendar_config_set_show_role (gboolean state); + + /* The time divisions in the Day/Work-Week view in minutes (5/10/15/30/60). */ gint calendar_config_get_time_divisions (void); void calendar_config_set_time_divisions (gint divisions); diff --git a/calendar/gui/dialogs/event-page.c b/calendar/gui/dialogs/event-page.c index 7414bab596..a00c3fa801 100644 --- a/calendar/gui/dialogs/event-page.c +++ b/calendar/gui/dialogs/event-page.c @@ -331,19 +331,16 @@ 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); @@ -716,14 +713,6 @@ 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) { @@ -759,7 +748,6 @@ event_page_set_view_rsvp (EventPage *epage, gboolean state) void event_page_set_classification (EventPage *epage, ECalComponentClassification class) { - printf("Setting to %d\n", class); epage->priv->classification = class; } @@ -784,9 +772,7 @@ sensitize_widgets (EventPage *epage) custom = is_custom_alarm_store (priv->alarm_list_store, priv->old_summary, priv->alarm_units, priv->alarm_interval, NULL); alarm = e_dialog_toggle_get (priv->alarm); - gtk_widget_set_sensitive (priv->summary_label, sensitize); gtk_entry_set_editable (GTK_ENTRY (priv->summary), sensitize); - gtk_widget_set_sensitive (priv->location_label, sensitize); gtk_entry_set_editable (GTK_ENTRY (priv->location), sensitize); gtk_widget_set_sensitive (priv->start_time, sensitize); gtk_widget_set_sensitive (priv->start_timezone, sensitize); @@ -817,11 +803,11 @@ sensitize_widgets (EventPage *epage) , 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" + bonobo_ui_component_set_prop (priv->uic, "/commands/ActionRecurrence", "sensitive", sensitize ? "1" : "0" , NULL); - bonobo_ui_component_set_prop (priv->uic, "/commands/ActionShowTimeBusy", "sensitive", sensitize ? "1" : "0" + bonobo_ui_component_set_prop (priv->uic, "/commands/ActionShowTimeBusy", "sensitive", !read_only ? "1" : "0" , NULL); - bonobo_ui_component_set_prop (priv->uic, "/commands/ActionAlarm", "sensitive", sensitize ? "1" : "0" + bonobo_ui_component_set_prop (priv->uic, "/commands/ActionAlarm", "sensitive", !read_only ? "1" : "0" , NULL); bonobo_ui_component_set_prop (priv->uic, "/commands/ActionClassPublic", "sensitive", sensitize ? "1" : "0" , NULL); @@ -831,6 +817,8 @@ sensitize_widgets (EventPage *epage) sensitize ? "1" : "0", NULL); bonobo_ui_component_set_prop (priv->uic, "/commands/ViewCategories", "sensitive", sensitize ? "1" : "0" , NULL); + bonobo_ui_component_set_prop (priv->uic, "/commands/InsertSendOptions", "sensitive", sensitize ? "1" : "0" + , NULL); if (!priv->is_meeting) { gtk_widget_hide (priv->calendar_label); @@ -1003,8 +991,7 @@ event_page_fill_widgets (CompEditorPage *page, ECalComponent *comp) 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->invite, FALSE); gtk_widget_set_sensitive (priv->add, FALSE); gtk_widget_set_sensitive (priv->remove, FALSE); priv->user_org = FALSE; @@ -1017,7 +1004,6 @@ event_page_fill_widgets (CompEditorPage *page, ECalComponent *comp) else string = g_strdup (strip); - // gtk_label_set_text (GTK_LABEL (priv->existing_organizer), string); g_free (string); priv->existing = TRUE; } @@ -1281,7 +1267,6 @@ event_page_fill_component (CompEditorPage *page, ECalComponent *comp) /* Classification */ e_cal_component_set_classification (comp, priv->classification); - printf("Storing %d\n", priv->classification); /* Show Time As (Transparency) */ busy = priv->show_time_as_busy; @@ -2619,7 +2604,8 @@ init_widgets (EventPage *epage) 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, "Attendee ", + TRUE); 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()); diff --git a/calendar/gui/dialogs/event-page.h b/calendar/gui/dialogs/event-page.h index 50bac28a65..3585b15b0a 100644 --- a/calendar/gui/dialogs/event-page.h +++ b/calendar/gui/dialogs/event-page.h @@ -73,7 +73,6 @@ 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); diff --git a/calendar/gui/dialogs/task-editor.c b/calendar/gui/dialogs/task-editor.c index b5fdc9bd24..e61c527c78 100644 --- a/calendar/gui/dialogs/task-editor.c +++ b/calendar/gui/dialogs/task-editor.c @@ -31,17 +31,21 @@ #include #include +#include +#include + #include "task-page.h" #include "task-details-page.h" #include "meeting-page.h" #include "cancel-comp.h" +#include "../calendar-config.h" #include "task-editor.h" struct _TaskEditorPrivate { TaskPage *task_page; TaskDetailsPage *task_details_page; - MeetingPage *meet_page; - + + GtkWidget *task_details_window; EMeetingStore *model; gboolean assignment_shown; @@ -56,11 +60,6 @@ static void task_editor_edit_comp (CompEditor *editor, ECalComponent *comp); static gboolean task_editor_send_comp (CompEditor *editor, ECalComponentItipMethod method); static void task_editor_finalize (GObject *object); -static void assign_task_cmd (GtkWidget *widget, gpointer data); -static void refresh_task_cmd (GtkWidget *widget, gpointer data); -static void cancel_task_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); @@ -104,11 +103,213 @@ client_changed_cb (CompEditorPage *page, ECal *client, gpointer user_data) // set_menu_sens (TASK_EDITOR (user_data)); } +static void +menu_view_role_cb (BonoboUIComponent *component, + const char *path, + Bonobo_UIComponent_EventType type, + const char *state, + gpointer user_data) +{ + TaskEditor *te = (TaskEditor *) user_data; + + if (type != Bonobo_UIComponent_STATE_CHANGED) + return; + task_page_set_view_role (te->priv->task_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) +{ + TaskEditor *te = (TaskEditor *) user_data; + + if (type != Bonobo_UIComponent_STATE_CHANGED) + return; + + task_page_set_view_status (te->priv->task_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) +{ + TaskEditor *te = (TaskEditor *) user_data; + + if (type != Bonobo_UIComponent_STATE_CHANGED) + return; + task_page_set_view_type (te->priv->task_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) +{ + TaskEditor *te = (TaskEditor *) user_data; + + if (type != Bonobo_UIComponent_STATE_CHANGED) + return; + task_page_set_view_rsvp (te->priv->task_page, atoi(state)); + calendar_config_set_show_rsvp (atoi(state)); +} + +static void +menu_show_time_zone_cb (BonoboUIComponent *component, + const char *path, + Bonobo_UIComponent_EventType type, + const char *state, + gpointer user_data) +{ + TaskEditor *te = (TaskEditor *) user_data; + + if (type != Bonobo_UIComponent_STATE_CHANGED) + return; + task_page_set_show_timezone (te->priv->task_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) +{ + TaskEditor *te = (TaskEditor *) user_data; + + if (type != Bonobo_UIComponent_STATE_CHANGED) + return; + + task_page_set_show_categories (te->priv->task_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) +{ + TaskEditor *te = (TaskEditor *) user_data; + + if (state[0] == '0') + return; + printf("Setting to public\n"); + task_page_set_classification (te->priv->task_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) +{ + TaskEditor *te = (TaskEditor *) user_data; + if (state[0] == '0') + return; + + printf("Setting to private\n"); + task_page_set_classification (te->priv->task_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) +{ + TaskEditor *te = (TaskEditor *) user_data; + if (state[0] == '0') + return; + + printf("Setting to confidential\n"); + task_page_set_classification (te->priv->task_page, E_CAL_COMPONENT_CLASS_CONFIDENTIAL); +} + + +static void +menu_option_status_cb (BonoboUIComponent *ui_component, + const char *path, + Bonobo_UIComponent_EventType type, + const char *state, + gpointer user_data) +{ + TaskEditor *te = (TaskEditor *) user_data; + + gtk_widget_show (te->priv->task_details_window); +} + +static void +menu_insert_send_options_cmd (BonoboUIComponent *uic, + void *data, + const char *path) +{ + TaskEditor *te = (TaskEditor *) data; + + task_page_sendoptions_clicked_cb (te->priv->task_page); +} + +static void +menu_show_time_zone_cmd (BonoboUIComponent *uic, + void *data, + const char *path) +{ /* TODO implement it + TaskEditor *te = (TaskEditor *) data; + + task_page_set_show_timezone (te->priv->task_page, atoi(state)); + calendar_config_set_show_timezone (atoi(state)); */ +} + +static void +menu_option_status_cmd (BonoboUIComponent *uic, + void *data, + const char *path) +{ + /* TODO implement it + TaskEditor *te = (TaskEditor *) data; + + task_page_set_view_status (te->priv->task_page, atoi(state)); + calendar_config_set_show_status (atoi(state)); */ +} + +static BonoboUIVerb verbs [] = { + + BONOBO_UI_VERB ("ViewTimeZone", menu_show_time_zone_cmd), + BONOBO_UI_VERB ("OptionStatus", menu_option_status_cmd), + BONOBO_UI_VERB ("InsertSendOptions", menu_insert_send_options_cmd), + BONOBO_UI_VERB_END +}; + +static EPixmap pixmaps[] = { + E_PIXMAP ("/Toolbar/ViewTimeZone", "stock_timezone", E_ICON_SIZE_LARGE_TOOLBAR), + E_PIXMAP ("/Toolbar/OptionStatus", "stock_view-details", E_ICON_SIZE_LARGE_TOOLBAR), + E_PIXMAP ("/commands/OptionStatus", "stock_view-details", E_ICON_SIZE_LARGE_TOOLBAR), + + E_PIXMAP_END +}; + + /* Object initialization function for the task editor */ static void task_editor_init (TaskEditor *te) { TaskEditorPrivate *priv; + CompEditor *editor = COMP_EDITOR(te); + gboolean status; priv = g_new0 (TaskEditorPrivate, 1); te->priv = priv; @@ -118,6 +319,88 @@ task_editor_init (TaskEditor *te) priv->updating = FALSE; priv->is_assigned = FALSE; + bonobo_ui_component_freeze (editor->uic, NULL); + + bonobo_ui_component_add_verb_list_with_data (editor->uic, verbs, te); + + bonobo_ui_util_set_ui (editor->uic, PREFIX, + EVOLUTION_UIDIR "/evolution-task-editor.xml", + "evolution-task-editor", 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); + + 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, "OptionStatus", + menu_option_status_cb, editor); + + e_pixmaps_update (editor->uic, pixmaps); + + bonobo_ui_component_thaw (editor->uic, NULL); + + comp_editor_set_help_section (COMP_EDITOR (te), "usage-calendar-todo"); } @@ -126,10 +409,11 @@ task_editor_construct (TaskEditor *te, ECal *client) { TaskEditorPrivate *priv; gboolean read_only = FALSE; + CompEditor *editor = COMP_EDITOR (te); priv = te->priv; - priv->task_page = task_page_new (); + priv->task_page = task_page_new (priv->model, client, editor->uic); g_object_ref (priv->task_page); gtk_object_sink (GTK_OBJECT (priv->task_page)); comp_editor_append_page (COMP_EDITOR (te), @@ -138,12 +422,20 @@ task_editor_construct (TaskEditor *te, ECal *client) g_signal_connect (G_OBJECT (priv->task_page), "client_changed", G_CALLBACK (client_changed_cb), te); + priv->task_details_window = gtk_dialog_new_with_buttons (_("Task Details"), + (GtkWindow *) te, GTK_DIALOG_MODAL, + "gtk-close", GTK_RESPONSE_CLOSE, + NULL); + g_signal_connect (priv->task_details_window, "response", G_CALLBACK(gtk_widget_hide), NULL); + priv->task_details_page = task_details_page_new (); g_object_ref (priv->task_details_page); gtk_object_sink (GTK_OBJECT (priv->task_details_page)); - comp_editor_append_page (COMP_EDITOR (te), - COMP_EDITOR_PAGE (priv->task_details_page), - _("_Status"), TRUE); + gtk_container_add ((GtkContainer *) GTK_DIALOG(priv->task_details_window)->vbox, + comp_editor_page_get_widget ((CompEditorPage *)priv->task_details_page)); + gtk_widget_show_all (priv->task_details_window); + gtk_widget_hide (priv->task_details_window); + comp_editor_append_page (editor, COMP_EDITOR_PAGE (priv->task_details_page), NULL, FALSE); if (!e_cal_is_read_only (client, &read_only, NULL)) read_only = TRUE; @@ -151,14 +443,17 @@ task_editor_construct (TaskEditor *te, ECal *client) if (priv->is_assigned) { if (e_cal_get_static_capability (client, CAL_STATIC_CAPABILITY_REQ_SEND_OPTIONS)) task_page_show_options (priv->task_page); - + + task_page_set_assignment (priv->task_page, TRUE); comp_editor_set_group_item (COMP_EDITOR (te), TRUE); - priv->meet_page = meeting_page_new (priv->model, client); - g_object_ref (priv->meet_page); - gtk_object_sink (GTK_OBJECT (priv->meet_page)); - comp_editor_append_page (COMP_EDITOR (te), - COMP_EDITOR_PAGE (priv->meet_page), - _("Assig_nment"), TRUE); + } else { + task_page_set_assignment (priv->task_page, FALSE); + + bonobo_ui_component_set_prop (editor->uic, "/commands/InsertSendOptions", "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 (te), client); @@ -206,21 +501,12 @@ task_editor_edit_comp (CompEditor *editor, ECalComponent *comp) e_cal_component_get_organizer (comp, &organizer); e_cal_component_get_attendee_list (comp, &attendees); - /* Clear things up */ - e_meeting_store_remove_all_attendees (priv->model); - - if (attendees == NULL) { - comp_editor_remove_page (editor, COMP_EDITOR_PAGE (priv->meet_page)); - priv->assignment_shown = FALSE; - } else { + if (attendees != NULL) { GSList *l; int row; - task_page_hide_options (priv->task_page); - if (!priv->assignment_shown) - comp_editor_append_page (COMP_EDITOR (te), - COMP_EDITOR_PAGE (priv->meet_page), - _("Assig_nment"), TRUE); + task_page_hide_options (priv->task_page); + task_page_set_assignment (priv->task_page, TRUE); for (l = attendees; l != NULL; l = l->next) { ECalComponentAttendee *ca = l->data; @@ -285,7 +571,7 @@ task_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 = task_page_get_cancel_comp (priv->task_page); if (comp != NULL) { ECal *client; gboolean result; @@ -329,11 +615,6 @@ task_editor_finalize (GObject *object) priv->task_details_page = NULL; } - if (priv->meet_page) { - g_object_unref (priv->meet_page); - priv->meet_page = NULL; - } - if (priv->model) { g_object_unref (priv->model); priv->model = NULL; @@ -375,9 +656,6 @@ show_assignment (TaskEditor *te) task_page_set_assignment (priv->task_page, TRUE); if (!priv->assignment_shown) { - comp_editor_append_page (COMP_EDITOR (te), - COMP_EDITOR_PAGE (priv->meet_page), - _("Assig_nment"), TRUE); priv->assignment_shown = TRUE; comp_editor_set_needs_send (COMP_EDITOR (te), priv->assignment_shown); @@ -395,45 +673,6 @@ task_editor_show_assignment (TaskEditor *te) show_assignment (te); } -static void -assign_task_cmd (GtkWidget *widget, gpointer data) -{ - TaskEditor *te = TASK_EDITOR (data); - - show_assignment (te); -} - -static void -refresh_task_cmd (GtkWidget *widget, gpointer data) -{ - TaskEditor *te = TASK_EDITOR (data); - - comp_editor_send_comp (COMP_EDITOR (te), E_CAL_COMPONENT_METHOD_REFRESH); -} - -static void -cancel_task_cmd (GtkWidget *widget, gpointer data) -{ - TaskEditor *te = TASK_EDITOR (data); - ECalComponent *comp; - - comp = comp_editor_get_current_comp (COMP_EDITOR (te)); - if (cancel_component_dialog ((GtkWindow *) te, - comp_editor_get_e_cal (COMP_EDITOR (te)), comp, FALSE)) { - comp_editor_send_comp (COMP_EDITOR (te), E_CAL_COMPONENT_METHOD_CANCEL); - comp_editor_delete_comp (COMP_EDITOR (te)); - } -} - -static void -forward_cmd (GtkWidget *widget, gpointer data) -{ - TaskEditor *te = TASK_EDITOR (data); - - if (comp_editor_save_comp (COMP_EDITOR (te), TRUE)) - comp_editor_send_comp (COMP_EDITOR (te), E_CAL_COMPONENT_METHOD_PUBLISH); -} - static void model_changed (TaskEditor *te) { diff --git a/calendar/gui/dialogs/task-page.c b/calendar/gui/dialogs/task-page.c index af3e207192..3d4cb500b6 100644 --- a/calendar/gui/dialogs/task-page.c +++ b/calendar/gui/dialogs/task-page.c @@ -26,6 +26,7 @@ #endif #include +#include #include #include #include @@ -36,7 +37,9 @@ #include #include #include +#include #include "common/authentication.h" +#include "e-util/e-popup.h" #include "e-util/e-dialog-widgets.h" #include "e-util/e-categories-config.h" #include "../e-timezone-entry.h" @@ -46,6 +49,10 @@ #include "e-send-options-utils.h" #include "task-page.h" +#include "../e-meeting-attendee.h" +#include "../e-meeting-store.h" +#include "../e-meeting-list-view.h" +#include "../e-cal-popup.h" /* Private part of the TaskPage structure */ @@ -53,20 +60,37 @@ struct _TaskPagePrivate { /* Glade XML data */ GladeXML *xml; + /* Bonobo Controller for the menu/toolbar */ + BonoboUIComponent *uic; + /* Widgets from the Glade file */ GtkWidget *main; + 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 *summary; GtkWidget *summary_label; GtkWidget *due_date; GtkWidget *start_date; - GtkWidget *due_timezone; - GtkWidget *start_timezone; - + GtkWidget *timezone; + GtkWidget *timezone_label; + GtkWidget *description; - GtkWidget *classification; + ECalComponentClassification classification; GtkWidget *categories_btn; GtkWidget *categories; @@ -75,6 +99,26 @@ struct _TaskPagePrivate { 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; gboolean sendoptions_shown; gboolean is_assignment; @@ -134,16 +178,16 @@ task_page_init (TaskPage *tpage) tpage->priv = priv; priv->xml = NULL; + priv->uic = NULL; priv->main = NULL; priv->summary = NULL; priv->summary_label = NULL; priv->due_date = NULL; priv->start_date = NULL; - priv->due_timezone = NULL; - priv->start_timezone = NULL; + priv->timezone = NULL; priv->description = NULL; - priv->classification = NULL; + priv->classification = E_CAL_COMPONENT_CLASS_NONE; priv->categories_btn = NULL; priv->categories = NULL; priv->sendoptions_frame = NULL; @@ -154,6 +198,28 @@ task_page_init (TaskPage *tpage) priv->updating = FALSE; priv->sendoptions_shown = FALSE; priv->is_assignment = FALSE; + + 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->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 task page */ @@ -181,7 +247,13 @@ task_page_finalize (GObject *object) g_object_unref (priv->sod); priv->sod = NULL; } - + + if (priv->comp != NULL) + g_object_unref (priv->comp); + + cleanup_attendees (priv->deleted_attendees); + g_ptr_array_free (priv->deleted_attendees, TRUE); + g_free (priv); tpage->priv = NULL; @@ -189,6 +261,30 @@ task_page_finalize (GObject *object) (* G_OBJECT_CLASS (task_page_parent_class)->finalize) (object); } +static void +set_classification_menu (TaskPage *page, gint class) +{ + bonobo_ui_component_freeze (page->priv->uic, NULL); + switch (class) { + case E_CAL_COMPONENT_CLASS_PUBLIC: + bonobo_ui_component_set_prop ( + page->priv->uic, "/commands/ActionClassPublic", + "state", "1", NULL); + break; + case E_CAL_COMPONENT_CLASS_CONFIDENTIAL: + bonobo_ui_component_set_prop ( + page->priv->uic, "/commands/ActionClassConfidential", + "state", "1", NULL); + break; + case E_CAL_COMPONENT_CLASS_PRIVATE: + bonobo_ui_component_set_prop ( + page->priv->uic, "/commands/ActionClassPrivate", + "state", "1", NULL); + break; + } + bonobo_ui_component_thaw (page->priv->uic, NULL); +} + /* get_widget handler for the task page */ @@ -234,23 +330,58 @@ clear_widgets (TaskPage *tpage) e_date_edit_set_time (E_DATE_EDIT (priv->due_date), 0); /* 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 (tpage, priv->classification); /* Categories */ e_dialog_editable_set (priv->categories, NULL); + + gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (priv->organizer)->entry), priv->default_address); + +} + +void +task_page_set_view_role (TaskPage *page, gboolean state) +{ + TaskPagePrivate *priv = page->priv; + + e_meeting_list_view_column_set_visible (priv->list_view, "Role", state); } -/* Decode the radio button group for classifications */ -static ECalComponentClassification -classification_get (GtkWidget *widget) +void +task_page_set_view_status (TaskPage *page, gboolean state) +{ + TaskPagePrivate *priv = page->priv; + + e_meeting_list_view_column_set_visible (priv->list_view, "Status", state); +} + +void +task_page_set_view_type (TaskPage *page, gboolean state) { - return e_dialog_option_menu_get (widget, classification_map); + TaskPagePrivate *priv = page->priv; + + e_meeting_list_view_column_set_visible (priv->list_view, "Type", state); +} + +void +task_page_set_view_rsvp (TaskPage *page, gboolean state) +{ + TaskPagePrivate *priv = page->priv; + + e_meeting_list_view_column_set_visible (priv->list_view, "RSVP", state); +} + +void +task_page_set_classification (TaskPage *page, ECalComponentClassification class) +{ + page->priv->classification = class; } static void sensitize_widgets (TaskPage *tpage) { - gboolean read_only; + gboolean read_only, sens, sensitize; TaskPagePrivate *priv; priv = tpage->priv; @@ -258,25 +389,67 @@ sensitize_widgets (TaskPage *tpage) if (!e_cal_is_read_only (COMP_EDITOR_PAGE (tpage)->client, &read_only, NULL)) read_only = TRUE; - gtk_widget_set_sensitive (priv->summary_label, !read_only); + if (COMP_EDITOR_PAGE (tpage)->flags & COMP_EDITOR_IS_ASSIGNED) + sens = COMP_EDITOR_PAGE (tpage)->flags & COMP_EDITOR_PAGE_USER_ORG; + + sensitize = (!read_only && sens); + gtk_entry_set_editable (GTK_ENTRY (priv->summary), !read_only); gtk_widget_set_sensitive (priv->due_date, !read_only); gtk_widget_set_sensitive (priv->start_date, !read_only); - gtk_widget_set_sensitive (priv->due_timezone, !read_only); - gtk_widget_set_sensitive (priv->start_timezone, !read_only); + gtk_widget_set_sensitive (priv->timezone, !read_only); gtk_widget_set_sensitive (priv->description, !read_only); - gtk_widget_set_sensitive (priv->classification, !read_only); gtk_widget_set_sensitive (priv->categories_btn, !read_only); gtk_widget_set_sensitive (priv->sendoptions_button, !read_only); gtk_entry_set_editable (GTK_ENTRY (priv->categories), !read_only); + + gtk_widget_set_sensitive (priv->organizer, !read_only); + gtk_widget_set_sensitive (priv->add, (!read_only && sens)); + gtk_widget_set_sensitive (priv->remove, (!read_only && sens)); + gtk_widget_set_sensitive (priv->invite, (!read_only && sens)); + 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/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); + bonobo_ui_component_set_prop (priv->uic, "/commands/InsertSendOptions", "sensitive", sensitize ? "1" : "0" + , NULL); + bonobo_ui_component_set_prop (priv->uic, "/commands/OptionStatus", "sensitive", sensitize ? "1" : "0" + , NULL); + + + if (!priv->is_assignment) { + gtk_widget_hide (priv->calendar_label); + gtk_widget_hide (priv->list_box); + gtk_widget_hide (priv->attendee_box); + gtk_widget_hide (priv->organizer); + gtk_widget_hide (priv->invite); + gtk_label_set_text_with_mnemonic ((GtkLabel *) priv->org_cal_label, _("_Group")); + } else { + gtk_widget_show (priv->invite); + 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 task_page_hide_options (TaskPage *page) { g_return_if_fail (IS_TASK_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; } @@ -285,7 +458,7 @@ task_page_show_options (TaskPage *page) { g_return_if_fail (IS_TASK_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; } @@ -295,6 +468,38 @@ task_page_set_assignment (TaskPage *page, gboolean set) g_return_if_fail (IS_TASK_PAGE (page)); page->priv->is_assignment = set; + sensitize_widgets (page); +} + +static EAccount * +get_current_account (TaskPage *page) +{ + TaskPagePrivate *priv; + EIterator *it; + const char *str; + + priv = page->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 task page */ @@ -316,10 +521,23 @@ task_page_fill_widgets (CompEditorPage *page, ECalComponent *comp) priv = tpage->priv; 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 screen */ clear_widgets (tpage); + priv->user_add = itip_get_comp_attendee (comp, page->client); + /* Summary, description(s) */ e_cal_component_get_summary (comp, &text); e_dialog_editable_set (priv->summary, text.value); @@ -350,7 +568,6 @@ task_page_fill_widgets (CompEditorPage *page, ECalComponent *comp) if (due_tt->is_date) { e_date_edit_set_time_of_day (E_DATE_EDIT (priv->due_date), -1, -1); - zone = default_zone; } else { e_date_edit_set_time_of_day (E_DATE_EDIT (priv->due_date), due_tt->hour, @@ -362,26 +579,31 @@ task_page_fill_widgets (CompEditorPage *page, ECalComponent *comp) /* If no time is set, we use the default timezone, so the user usually doesn't have to set this when they set the date. */ - zone = default_zone; + zone = NULL; } /* Note that if we are creating a new task, the timezones may not be on the server, so we try to get the builtin timezone with the TZID first. */ - if (!zone) - zone = icaltimezone_get_builtin_timezone_from_tzid (d.tzid); - if (!zone) { + if (!zone && d.tzid) { if (!e_cal_get_timezone (page->client, d.tzid, &zone, NULL)) /* FIXME: Handle error better. */ g_warning ("Couldn't get timezone from server: %s", d.tzid ? d.tzid : ""); } - e_timezone_entry_set_timezone (E_TIMEZONE_ENTRY (priv->due_timezone), - zone); + + e_timezone_entry_set_timezone (E_TIMEZONE_ENTRY (priv->timezone), + zone ? zone : default_zone); + gtk_widget_show_all (priv->timezone); + + if (!(COMP_EDITOR_PAGE (tpage)->flags & COMP_EDITOR_PAGE_NEW_ITEM) && !zone) { + task_page_set_show_timezone (tpage, FALSE); + bonobo_ui_component_set_prop (priv->uic, "/commands/ViewTimeZone", + "state", "0", NULL); + } e_cal_component_free_datetime (&d); - /* Start Date. */ e_cal_component_get_dtstart (comp, &d); zone = NULL; @@ -408,17 +630,6 @@ task_page_fill_widgets (CompEditorPage *page, ECalComponent *comp) zone = default_zone; } - if (!zone) - zone = icaltimezone_get_builtin_timezone_from_tzid (d.tzid); - if (!zone) { - if (!e_cal_get_timezone (page->client, d.tzid, &zone, NULL)) - /* FIXME: Handle error better. */ - g_warning ("Couldn't get timezone from server: %s", - d.tzid ? d.tzid : ""); - } - e_timezone_entry_set_timezone (E_TIMEZONE_ENTRY (priv->start_timezone), - zone); - e_cal_component_free_datetime (&d); /* Classification. */ @@ -434,7 +645,7 @@ task_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 (tpage, cl); e_cal_component_get_uid (comp, &uid); if (e_cal_get_object (COMP_EDITOR_PAGE (tpage)->client, uid, NULL, &icalcomp, NULL)) { @@ -450,6 +661,62 @@ task_page_fill_widgets (CompEditorPage *page, ECalComponent *comp) source = e_cal_get_source (page->client); e_source_option_menu_select (E_SOURCE_OPTION_MENU (priv->source_selector), source); + if (priv->is_assignment) { + ECalComponentOrganizer organizer; + + priv->user_add = itip_get_comp_attendee (comp, COMP_EDITOR_PAGE (tpage)->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; + if (itip_organizer_is_user (comp, page->client)) { + if (e_cal_get_static_capability ( + page->client, + CAL_STATIC_CAPABILITY_ORGANIZER_NOT_EMAIL_ADDRESS)) + priv->user_org = TRUE; + } else { + if (e_cal_get_static_capability ( + page->client, + CAL_STATIC_CAPABILITY_ORGANIZER_NOT_EMAIL_ADDRESS)) + 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 (tpage)->client, CAL_STATIC_CAPABILITY_NO_ORGANIZER) && (COMP_EDITOR_PAGE (tpage)->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); + + g_free (string); + priv->existing = TRUE; + } + } else { + EAccount *a; + + a = get_current_account (tpage); + if (a != NULL) { + CompEditorPage *page = (CompEditorPage *) tpage; + 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); + } + } + } + + priv->updating = FALSE; sensitize_widgets (tpage); @@ -457,6 +724,30 @@ task_page_fill_widgets (CompEditorPage *page, ECalComponent *comp) return TRUE; } +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); +} + /* fill_component handler for the task page */ static gboolean task_page_fill_component (CompEditorPage *page, ECalComponent *comp) @@ -539,7 +830,7 @@ task_page_fill_component (CompEditorPage *page, ECalComponent *comp) &due_tt.minute); if (due_date_set) { if (time_set) { - due_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->due_timezone)); + due_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->timezone)); date.tzid = icaltimezone_get_tzid (due_zone); } else { due_tt.is_date = TRUE; @@ -568,7 +859,7 @@ task_page_fill_component (CompEditorPage *page, ECalComponent *comp) &start_tt.minute); if (start_date_set) { if (time_set) { - start_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->start_timezone)); + start_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->timezone)); date.tzid = icaltimezone_get_tzid (start_zone); } else { start_tt.is_date = TRUE; @@ -580,7 +871,7 @@ task_page_fill_component (CompEditorPage *page, ECalComponent *comp) } /* Classification. */ - e_cal_component_set_classification (comp, classification_get (priv->classification)); + e_cal_component_set_classification (comp, priv->classification); /* send options */ if (priv->sendoptions_shown && priv->sod) @@ -597,9 +888,431 @@ task_page_fill_component (CompEditorPage *page, ECalComponent *comp) if (str) g_free (str); + if (priv->is_assignment) { + 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 (tpage); + + /* 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 (tpage)->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; +} + +static void +add_clicked_cb (GtkButton *btn, TaskPage *page) +{ + EMeetingAttendee *attendee; + + attendee = e_meeting_store_add_attendee_with_defaults (page->priv->model); + + if (COMP_EDITOR_PAGE (page)->flags & COMP_EDITOR_PAGE_DELEGATE) { + e_meeting_attendee_set_delfrom (attendee, g_strdup_printf ("MAILTO:%s", page->priv->user_add)); + } + + e_meeting_list_view_edit (page->priv->list_view, attendee); +} + +static gboolean +existing_attendee (EMeetingAttendee *ia, ECalComponent *comp) +{ + GSList *attendees, *l; + const gchar *ia_address; + + ia_address = itip_strip_mailto (e_meeting_attendee_get_address (ia)); + if (!ia_address) + return FALSE; + + 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; + } + } + + e_cal_component_free_attendee_list (attendees); + + return FALSE; +} + +static void +remove_attendee (TaskPage *page, EMeetingAttendee *ia) +{ + TaskPagePrivate *priv; + int pos = 0; + gboolean delegate = (COMP_EDITOR_PAGE (page)->flags & COMP_EDITOR_PAGE_DELEGATE); + + priv = page->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 (page); +} + +static void +remove_clicked_cb (GtkButton *btn, TaskPage *page) +{ + TaskPagePrivate *priv; + EMeetingAttendee *ia; + GtkTreeSelection *selection; + GList *paths = NULL, *tmp; + GtkTreeIter iter; + GtkTreePath *path = NULL; + gboolean valid_iter; + char *address; + + priv = page->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 (page, 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) +{ + TaskPage *page; + TaskPagePrivate *priv; + + page = TASK_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) +{ + TaskPage *page = TASK_PAGE (user_data); + TaskPagePrivate *priv; + gboolean delegate = (COMP_EDITOR_PAGE (page)->flags & COMP_EDITOR_PAGE_DELEGATE); + + priv = page->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(page)->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) +{ + TaskPage *page = data; + + add_clicked_cb (NULL, page); +} + +static void +popup_delete_cb (EPopup *ep, EPopupItem *pitem, void *data) +{ + TaskPage *page = data; + TaskPagePrivate *priv; + + priv = page->priv; + + remove_clicked_cb (NULL, page); +} + +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, TaskPage *page) +{ + TaskPagePrivate *priv; + GtkMenu *menu; + EMeetingAttendee *ia; + GtkTreePath *path; + GtkTreeIter iter; + char *address; + guint32 disable_mask = ~0; + GSList *menus = NULL; + ECalPopup *ep; + int i; + + priv = page->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 ((GtkTreeView *) 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 (page)->flags & COMP_EDITOR_PAGE_USER_ORG) + disable_mask &= ~ATTENDEE_CAN_ADD; + + ep = e_cal_popup_new("org.gnome.evolution.calendar.task.popup"); + + for (i=0;ibutton, event->time); + return TRUE; } +static gboolean +list_view_event (EMeetingListView *list_view, GdkEvent *event, TaskPage *page) { + + TaskPagePrivate *priv= page->priv; + + if (event->type == GDK_2BUTTON_PRESS && COMP_EDITOR_PAGE (page)->flags & COMP_EDITOR_PAGE_USER_ORG) { + EMeetingAttendee *attendee; + + attendee = e_meeting_store_add_attendee_with_defaults (priv->model); + + if (COMP_EDITOR_PAGE (page)->flags & COMP_EDITOR_PAGE_DELEGATE) { + e_meeting_attendee_set_delfrom (attendee, g_strdup_printf ("MAILTO:%s", page->priv->user_add)); + } + + e_meeting_list_view_edit (page->priv->list_view, attendee); + return TRUE; + } + + return FALSE; +} + + +static gboolean +list_key_press (EMeetingListView *list_view, GdkEventKey *event, TaskPage *page) +{ + if (event->keyval == GDK_Delete) { + TaskPagePrivate *priv; + + priv = page->priv; + remove_clicked_cb (NULL, page); + + return TRUE; + } else if (event->keyval == GDK_Insert) { + add_clicked_cb (NULL, page); + + return TRUE; + } + + return FALSE; +} + +void +task_page_set_show_timezone (TaskPage *page, gboolean state) +{ + if (state) { + gtk_widget_show_all (page->priv->timezone); + gtk_widget_show (page->priv->timezone_label); + } else { + gtk_widget_hide (page->priv->timezone); + gtk_widget_hide (page->priv->timezone_label); + } + +} + +void +task_page_set_show_categories (TaskPage *page, gboolean state) +{ + if (state) { + gtk_widget_show (page->priv->categories_btn); + gtk_widget_show (page->priv->categories); + } else { + gtk_widget_hide (page->priv->categories_btn); + gtk_widget_hide (page->priv->categories); + } +} + /* fill_timezones handler for the event page */ static gboolean task_page_fill_timezones (CompEditorPage *page, GHashTable *timezones) @@ -611,15 +1324,8 @@ task_page_fill_timezones (CompEditorPage *page, GHashTable *timezones) tpage = TASK_PAGE (page); priv = tpage->priv; - /* add due date timezone */ - zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->due_timezone)); - if (zone) { - if (!g_hash_table_lookup (timezones, icaltimezone_get_tzid (zone))) - g_hash_table_insert (timezones, icaltimezone_get_tzid (zone), zone); - } - /* add start date timezone */ - zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->start_timezone)); + zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->timezone)); if (zone) { if (!g_hash_table_lookup (timezones, icaltimezone_get_tzid (zone))) g_hash_table_insert (timezones, icaltimezone_get_tzid (zone), zone); @@ -662,6 +1368,8 @@ get_widgets (TaskPage *tpage) TaskPagePrivate *priv; GSList *accel_groups; GtkWidget *toplevel; + GtkWidget *sw; + GtkTreeSelection *selection; priv = tpage->priv; @@ -692,35 +1400,47 @@ get_widgets (TaskPage *tpage) priv->start_date = GW ("start-date"); gtk_widget_show (priv->start_date); - priv->due_timezone = GW ("due-timezone"); - priv->start_timezone = GW ("start-timezone"); - + priv->timezone = GW ("timezone"); + priv->timezone_label = GW ("timezone-label"); + priv->attendees_label = GW ("attendees-label"); priv->description = GW ("description"); - - priv->classification = GW ("classification"); - priv->categories_btn = GW ("categories-button"); priv->categories = GW ("categories"); + priv->organizer = GW ("organizer"); + priv->invite = GW ("invite"); + priv->add = GW ("add-attendee"); + priv->remove = GW ("remove-attendee"); + priv->list_box = GW ("list-box"); + priv->calendar_label = GW ("group-label"); + priv->attendee_box = GW ("attendee-box"); + priv->org_cal_label = GW ("org-task-label"); + + priv->list_view = e_meeting_list_view_new (priv->model); + + selection = gtk_tree_view_get_selection ((GtkTreeView *) priv->list_view); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE); + gtk_widget_show (GTK_WIDGET (priv->list_view)); + + 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); priv->source_selector = GW ("source"); - priv->sendoptions_frame = GW ("send-options-frame"); - priv->sendoptions_button = GW ("send-options-button"); - #undef GW return (priv->summary && priv->summary_label && priv->due_date && priv->start_date - && priv->due_timezone - && priv->start_timezone - && priv->classification + && priv->timezone && priv->description && priv->categories_btn && priv->categories - && priv->sendoptions_frame - && priv->sendoptions_button); + ); } /* Callback used when the summary changes; we emit the notification signal. */ @@ -772,7 +1492,7 @@ date_changed_cb (EDateEdit *dedit, gpointer data) &start_tt.minute); if (date_set) { if (time_set) { - icaltimezone *zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->start_timezone)); + icaltimezone *zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->timezone)); start_dt.tzid = icaltimezone_get_tzid (zone); } else { start_tt.is_date = TRUE; @@ -792,7 +1512,7 @@ date_changed_cb (EDateEdit *dedit, gpointer data) &due_tt.minute); if (date_set) { if (time_set) { - icaltimezone *zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->due_timezone)); + icaltimezone *zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->timezone)); due_dt.tzid = icaltimezone_get_tzid (zone); } else { due_tt.is_date = TRUE; @@ -815,6 +1535,19 @@ date_changed_cb (EDateEdit *dedit, gpointer data) &dates); } +static void +timezone_changed_cb (EDateEdit *dedit, gpointer data) +{ + TaskPage *tpage; + TaskPagePrivate *priv; + + tpage = TASK_PAGE (data); + priv = tpage->priv; + + date_changed_cb ((EDateEdit *) priv->start_date, tpage); + date_changed_cb ((EDateEdit *) priv->due_date, tpage); +} + /* Callback used when the categories button is clicked; we must bring up the * category list dialog. */ @@ -896,15 +1629,13 @@ source_changed_cb (GtkWidget *widget, ESource *source, gpointer data) } } -static void -e_sendoptions_clicked_cb (GtkWidget *button, gpointer data) +void +task_page_sendoptions_clicked_cb (TaskPage *tpage) { - TaskPage *tpage; TaskPagePrivate *priv; GtkWidget *toplevel; ESource *source; - tpage = TASK_PAGE (data); priv = tpage->priv; if (!priv->sod) { @@ -957,14 +1688,13 @@ init_widgets (TaskPage *tpage) g_signal_connect((priv->due_date), "changed", G_CALLBACK (date_changed_cb), tpage); + /* time zone changed */ + g_signal_connect (priv->timezone, "changed", G_CALLBACK(timezone_changed_cb), tpage); + /* Categories button */ g_signal_connect((priv->categories_btn), "clicked", G_CALLBACK (categories_clicked_cb), tpage); - /* send options button */ - g_signal_connect((priv->sendoptions_button), "clicked", - G_CALLBACK (e_sendoptions_clicked_cb), tpage); - /* Source selector */ g_signal_connect((priv->source_selector), "source_selected", G_CALLBACK (source_changed_cb), tpage); @@ -982,19 +1712,54 @@ init_widgets (TaskPage *tpage) G_CALLBACK (field_changed_cb), tpage); g_signal_connect (priv->due_date, "changed", G_CALLBACK (field_changed_cb), tpage); - g_signal_connect((priv->due_timezone), "changed", - G_CALLBACK (field_changed_cb), tpage); - g_signal_connect((priv->start_timezone), "changed", - G_CALLBACK (field_changed_cb), tpage); - g_signal_connect((priv->classification), "changed", + g_signal_connect((priv->timezone), "changed", G_CALLBACK (field_changed_cb), tpage); g_signal_connect((priv->categories), "changed", G_CALLBACK (field_changed_cb), tpage); + g_signal_connect (G_OBJECT (priv->list_view), "button_press_event", G_CALLBACK (button_press_event), tpage); + g_signal_connect (G_OBJECT (priv->list_view), "event", G_CALLBACK (list_view_event), tpage); + g_signal_connect (priv->list_view, "key_press_event", G_CALLBACK (list_key_press), tpage); + + /* Add attendee button */ + g_signal_connect (priv->add, "clicked", G_CALLBACK (add_clicked_cb), tpage); + /* Remove attendee button */ + g_signal_connect (priv->remove, "clicked", G_CALLBACK (remove_clicked_cb), tpage); + + /* Contacts button */ + g_signal_connect(priv->invite, "clicked", G_CALLBACK (invite_cb), tpage); + + /* Meeting List View */ + g_signal_connect (priv->list_view, "attendee_added", G_CALLBACK (attendee_added_cb), tpage); + /* 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->due_timezone), zone); + e_timezone_entry_set_default_timezone (E_TIMEZONE_ENTRY (priv->timezone), zone); + + task_page_set_show_timezone (tpage, calendar_config_get_show_timezone()); + + e_meeting_list_view_column_set_visible (priv->list_view, "Attendee ", + TRUE); + 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()); + + if (!calendar_config_get_show_timezone()) { + gtk_widget_hide (priv->timezone_label); + gtk_widget_hide (priv->timezone); + } else { + gtk_widget_show (priv->timezone_label); + gtk_widget_show_all (priv->timezone); + } + + 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); + } return TRUE; } @@ -1011,11 +1776,19 @@ init_widgets (TaskPage *tpage) * created. **/ TaskPage * -task_page_construct (TaskPage *tpage) +task_page_construct (TaskPage *tpage, EMeetingStore *model, ECal *client) { TaskPagePrivate *priv; - + char *backend_address = NULL; + EIterator *it; + EAccount *def_account; + GList *address_strings = NULL, *l; + EAccount *a; + priv = tpage->priv; + g_object_ref (model); + priv->model = model; + priv->client = client; priv->xml = glade_xml_new (EVOLUTION_GLADEDIR "/task-page.glade", NULL, NULL); @@ -1030,6 +1803,49 @@ task_page_construct (TaskPage *tpage) "Could not find all widgets in the XML file!"); 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 (tpage)) { g_message ("task_page_construct(): " @@ -1049,19 +1865,39 @@ task_page_construct (TaskPage *tpage) * not be created. **/ TaskPage * -task_page_new (void) +task_page_new (EMeetingStore *model, ECal *client, BonoboUIComponent *uic) { TaskPage *tpage; tpage = gtk_type_new (TYPE_TASK_PAGE); - if (!task_page_construct (tpage)) { + if (!task_page_construct (tpage, model, client)) { g_object_unref (tpage); return NULL; } + + tpage->priv->uic = uic; return tpage; } +ECalComponent * +task_page_get_cancel_comp (TaskPage *page) +{ + TaskPagePrivate *priv; + + g_return_val_if_fail (page != NULL, NULL); + g_return_val_if_fail (IS_TASK_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); +} + GtkWidget *task_page_create_date_edit (void); GtkWidget * diff --git a/calendar/gui/dialogs/task-page.glade b/calendar/gui/dialogs/task-page.glade index 76156a3a1a..adf9dc4b17 100644 --- a/calendar/gui/dialogs/task-page.glade +++ b/calendar/gui/dialogs/task-page.glade @@ -15,6 +15,7 @@ False GDK_WINDOW_TYPE_HINT_NORMAL GDK_GRAVITY_NORTH_WEST + True @@ -23,81 +24,101 @@ 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 - 4 + 8 2 False 6 12 - + True - True - True - True - 0 - - True - * - False + False + 0 + + + + True + 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 + + + + + 0 + True + True + + 1 2 - 0 - 1 - + 1 + 2 + fill + fill @@ -115,119 +136,158 @@ 0 0 summary + PANGO_ELLIPSIZE_NONE + -1 + False + 0 0 1 - 0 - 1 + 2 + 3 fill - + True - Classi_fication: + True + True + True + 0 + + True + * + False + + + 1 + 2 + 2 + 3 + + + + + + + True + Or_ganiser: True False GTK_JUSTIFY_LEFT False False - 0.5 + 0 0.5 0 0 - classification + PANGO_ELLIPSIZE_NONE + -1 + False + 0 0 1 - 1 - 2 + 0 + 1 fill - + True - False + True 0 - + True - True - 0 - - - - - - - True - Public - True - - - - - - True - Private - True - - + False + True + False + True + False + + + + True + True + True + True + 0 + + True + * + False + + - - - True - Confidential - True - - + + + True + GTK_SELECTION_BROWSE - 0 + 2 True True - + True - _Group: - True - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 12 - 0 - source - - - 0 - False - False - - + False + 0 - - - True - task_page_create_source_option_menu - 0 - 0 - Thu, 18 Dec 2003 01:58:48 GMT + + + True + _Group: + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + False + False + + + + + + True + task_page_create_source_option_menu + 0 + 0 + Thu, 18 Dec 2003 01:58:48 GMT + + + 0 + True + True + + 0 @@ -239,52 +299,136 @@ 1 2 - 1 - 2 + 0 + 1 fill fill - + True - True - Categor_ies... - 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 - 2 - 3 + 1 + 2 fill - + fill - + True - True - True - True - 0 - - True - * - False - - Categories - + D_escription: + True + False + GTK_JUSTIFY_CENTER + False + False + 0 + 0 + 0 + 0 + description + PANGO_ELLIPSIZE_NONE + -1 + False + 0 - 1 - 2 - 2 - 3 + 0 + 1 + 7 + 8 + fill @@ -314,117 +458,18 @@ 0 0 - - Task Description - 1 2 - 3 - 4 - expand|shrink|fill - expand|shrink|fill - - - - - - True - D_escription: - True - False - GTK_JUSTIFY_CENTER - False - False - 0 - 0 - 0 - 0 - description - - - 0 - 1 - 3 - 4 + 7 + 8 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 - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 12 - 0 - - - 0 - False - False - - - - - - True - 2 - 2 - False - 6 - 12 @@ -440,12 +485,16 @@ 0 0 due-date + PANGO_ELLIPSIZE_NONE + -1 + False + 0 0 1 - 0 - 1 + 4 + 5 fill @@ -465,177 +514,147 @@ 0 0 start-date + PANGO_ELLIPSIZE_NONE + -1 + False + 0 0 1 - 1 - 2 + 3 + 4 fill - + True - False - 0 - - - - True - task_page_create_date_edit - 0 - 0 - Mon, 14 Jun 2004 18:16:07 GMT - - - - - - 0 - True - True - - - - - - True - make_timezone_entry - 0 - 0 - Tue, 19 Jun 2001 04:43:54 GMT - - - 0 - True - True - - + task_page_create_date_edit + 0 + 0 + Mon, 14 Jun 2004 18:16:13 GMT 1 2 - 0 - 1 - fill - fill + 3 + 4 + shrink|fill + shrink|fill - + True - False - 0 - - - - True - task_page_create_date_edit - 0 - 0 - Mon, 14 Jun 2004 18:16:13 GMT - - - - - - 0 - True - True - - - - - - True - make_timezone_entry - 0 - 0 - Tue, 19 Jun 2001 04:43:46 GMT - - - 0 - True - True - - + task_page_create_date_edit + 0 + 0 + Mon, 14 Jun 2004 18:16:07 GMT 1 2 - 1 - 2 + 4 + 5 fill fill - - - 0 - True - True - - - - - 0 - False - False - - - - - - 0 - 0.5 - GTK_SHADOW_NONE - - - - 12 - True - 0.5 - 0.5 - 0.11 - 1 - 0 - 0 - 12 - 0 - + True True - Ad_vanced send options + Categor_ies... True GTK_RELIEF_NORMAL True + + 0 + 1 + 6 + 7 + fill + + - - - - - True - <b>Send Options</b> - False - True - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 + + + True + True + True + True + 0 + + True + * + False + + + 1 + 2 + 6 + 7 + + + + + + + True + Time zone: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 5 + 6 + fill + + + + + + + True + make_timezone_entry + 0 + 0 + Tue, 19 Jun 2001 04:43:54 GMT + + + 1 + 2 + 5 + 6 + fill + fill + + - label_item + 0 + True + True diff --git a/calendar/gui/dialogs/task-page.h b/calendar/gui/dialogs/task-page.h index 9a061a141b..64fa67591b 100644 --- a/calendar/gui/dialogs/task-page.h +++ b/calendar/gui/dialogs/task-page.h @@ -24,7 +24,13 @@ #ifndef TASK_PAGE_H #define TASK_PAGE_H -#include "comp-editor-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 @@ -50,11 +56,20 @@ typedef struct { } TaskPageClass; GtkType task_page_get_type (void); -TaskPage *task_page_construct (TaskPage *epage); -TaskPage *task_page_new (void); +TaskPage *task_page_construct (TaskPage *epage, EMeetingStore *model, ECal *client); +TaskPage *task_page_new (EMeetingStore *model, ECal *client, BonoboUIComponent *uic); +ECalComponent * task_page_get_cancel_comp (TaskPage *page); void task_page_show_options (TaskPage *page); void task_page_hide_options (TaskPage *page); void task_page_set_assignment (TaskPage *page, gboolean set); +void task_page_sendoptions_clicked_cb (TaskPage *tpage); +void task_page_set_view_role (TaskPage *page, gboolean state); +void task_page_set_view_status (TaskPage *page, gboolean state); +void task_page_set_view_type (TaskPage *page, gboolean state); +void task_page_set_view_rsvp (TaskPage *page, gboolean state); +void task_page_set_classification (TaskPage *page, ECalComponentClassification class); +void task_page_set_show_timezone (TaskPage *page, gboolean state); +void task_page_set_show_categories (TaskPage *page, gboolean state); -- cgit v1.2.3