From f4e8698fdd4c48422f217f409e92ec7a2d26c443 Mon Sep 17 00:00:00 2001 From: JP Rosevear Date: Fri, 1 Jun 2001 23:54:43 +0000 Subject: renamed from editor-page for consistency, more complete implementation 2001-06-01 JP Rosevear * gui/dialogs/comp-editor-page.[hc]: renamed from editor-page for consistency, more complete implementation * gui/dialogs/comp-editor.[hc]: More complete implementation * gui/dialogs/*-page.*: The various pages needed to construct the event and task dialogs * gui/dialogs/comp-editor-util.[hc]: useful utility functions for the component editor pages to use * gui/dialogs/Makefile.am: Build and install new files * gui/event-editor*: Remove, obsoleted by the new comp-editor stuff * gui/dialogs/task-editor-dialog.glade: ditto * gui/e-calendar-table.c (open_task): update to use comp editor stuff * gui/e-tasks.c (e_tasks_new_task): ditto * gui/gnome-cal.c (gnome_calendar_edit_object): ditto * gui/Makefile.am: don't build non-existent files nor try to install them svn path=/trunk/; revision=10088 --- calendar/gui/dialogs/Makefile.am | 17 +- calendar/gui/dialogs/alarm-page.c | 175 ++-- calendar/gui/dialogs/alarm-page.glade | 87 +- calendar/gui/dialogs/alarm-page.h | 14 +- calendar/gui/dialogs/comp-editor-page.c | 277 ++++++ calendar/gui/dialogs/comp-editor-page.h | 93 ++ calendar/gui/dialogs/comp-editor-util.c | 129 +++ calendar/gui/dialogs/comp-editor-util.h | 31 + calendar/gui/dialogs/comp-editor.c | 385 +++++++- calendar/gui/dialogs/comp-editor.h | 23 +- calendar/gui/dialogs/editor-page.c | 260 ----- calendar/gui/dialogs/editor-page.h | 86 -- calendar/gui/dialogs/event-editor.c | 155 +++ calendar/gui/dialogs/event-editor.h | 62 ++ calendar/gui/dialogs/event-page.c | 281 +++--- calendar/gui/dialogs/event-page.glade | 3 +- calendar/gui/dialogs/event-page.h | 20 +- calendar/gui/dialogs/recurrence-page.c | 338 ++++--- calendar/gui/dialogs/recurrence-page.glade | 85 +- calendar/gui/dialogs/recurrence-page.h | 14 +- calendar/gui/dialogs/task-details-page.c | 461 +++++++++ calendar/gui/dialogs/task-details-page.glade | 318 ++++-- calendar/gui/dialogs/task-details-page.h | 62 ++ calendar/gui/dialogs/task-editor-dialog.glade | 695 ------------- calendar/gui/dialogs/task-editor.c | 1301 ++----------------------- calendar/gui/dialogs/task-editor.h | 83 +- calendar/gui/dialogs/task-page.c | 966 ++++++++++++++++++ calendar/gui/dialogs/task-page.glade | 15 +- calendar/gui/dialogs/task-page.h | 61 ++ 29 files changed, 3570 insertions(+), 2927 deletions(-) create mode 100644 calendar/gui/dialogs/comp-editor-page.c create mode 100644 calendar/gui/dialogs/comp-editor-page.h create mode 100644 calendar/gui/dialogs/comp-editor-util.c create mode 100644 calendar/gui/dialogs/comp-editor-util.h delete mode 100644 calendar/gui/dialogs/editor-page.c delete mode 100644 calendar/gui/dialogs/editor-page.h create mode 100644 calendar/gui/dialogs/event-editor.c create mode 100644 calendar/gui/dialogs/event-editor.h create mode 100644 calendar/gui/dialogs/task-details-page.c create mode 100644 calendar/gui/dialogs/task-details-page.h delete mode 100644 calendar/gui/dialogs/task-editor-dialog.glade create mode 100644 calendar/gui/dialogs/task-page.c create mode 100644 calendar/gui/dialogs/task-page.h (limited to 'calendar/gui/dialogs') diff --git a/calendar/gui/dialogs/Makefile.am b/calendar/gui/dialogs/Makefile.am index 034e4060fc..74c65d72ab 100644 --- a/calendar/gui/dialogs/Makefile.am +++ b/calendar/gui/dialogs/Makefile.am @@ -24,10 +24,16 @@ libcal_dialogs_a_SOURCES = \ alarm-page.h \ cal-prefs-dialog.c \ cal-prefs-dialog.h \ + comp-editor.c \ + comp-editor.h \ + comp-editor-page.c \ + comp-editor-page.h \ + comp-editor-util.c \ + comp-editor-util.h \ delete-comp.c \ delete-comp.h \ - editor-page.c \ - editor-page.h \ + event-editor.c \ + event-editor.h \ event-page.c \ event-page.h \ recurrence-page.c \ @@ -35,7 +41,11 @@ libcal_dialogs_a_SOURCES = \ save-comp.c \ save-comp.h \ task-editor.c \ - task-editor.h + task-editor.h \ + task-details-page.c \ + task-details-page.h \ + task-page.c \ + task-page.h glade_DATA = \ alarm-notify.glade \ @@ -44,7 +54,6 @@ glade_DATA = \ event-page.glade \ recurrence-page.glade \ task-details-page.glade \ - task-editor-dialog.glade \ task-page.glade EXTRA_DIST = \ diff --git a/calendar/gui/dialogs/alarm-page.c b/calendar/gui/dialogs/alarm-page.c index 85141e9c47..74e728ad4c 100644 --- a/calendar/gui/dialogs/alarm-page.c +++ b/calendar/gui/dialogs/alarm-page.c @@ -26,13 +26,15 @@ #include #endif +#include #include #include #include #include #include -#include "cal-util/cal-util.h" #include "e-util/e-dialog-widgets.h" +#include "cal-util/cal-util.h" +#include "comp-editor-util.h" #include "alarm-page.h" @@ -47,7 +49,7 @@ struct _AlarmPagePrivate { GtkWidget *main; GtkWidget *summary; - GtkWidget *starting_date; + GtkWidget *date_time; GtkWidget *list; GtkWidget *add; @@ -58,6 +60,8 @@ struct _AlarmPagePrivate { GtkWidget *value_units; GtkWidget *relative; GtkWidget *time; + + gboolean updating; }; @@ -66,14 +70,13 @@ static void alarm_page_class_init (AlarmPageClass *class); static void alarm_page_init (AlarmPage *apage); static void alarm_page_destroy (GtkObject *object); -static GtkWidget *alarm_page_get_widget (EditorPage *page); -static void alarm_page_fill_widgets (EditorPage *page, CalComponent *comp); -static void alarm_page_fill_component (EditorPage *page, CalComponent *comp); -static void alarm_page_set_summary (EditorPage *page, const char *summary); -static char *alarm_page_get_summary (EditorPage *page); -static void alarm_page_set_dates (EditorPage *page, time_t start, time_t end); +static GtkWidget *alarm_page_get_widget (CompEditorPage *page); +static void alarm_page_fill_widgets (CompEditorPage *page, CalComponent *comp); +static void alarm_page_fill_component (CompEditorPage *page, CalComponent *comp); +static void alarm_page_set_summary (CompEditorPage *page, const char *summary); +static void alarm_page_set_dates (CompEditorPage *page, CompEditorPageDates *dates); -static EditorPageClass *parent_class = NULL; +static CompEditorPageClass *parent_class = NULL; @@ -102,7 +105,8 @@ alarm_page_get_type (void) (GtkClassInitFunc) NULL }; - alarm_page_type = gtk_type_unique (TYPE_EDITOR_PAGE, &alarm_page_info); + alarm_page_type = gtk_type_unique (TYPE_COMP_EDITOR_PAGE, + &alarm_page_info); } return alarm_page_type; @@ -112,19 +116,18 @@ alarm_page_get_type (void) static void alarm_page_class_init (AlarmPageClass *class) { - EditorPageClass *editor_page_class; + CompEditorPageClass *editor_page_class; GtkObjectClass *object_class; - editor_page_class = (EditorPageClass *) class; + editor_page_class = (CompEditorPageClass *) class; object_class = (GtkObjectClass *) class; - parent_class = gtk_type_class (TYPE_EDITOR_PAGE); + parent_class = gtk_type_class (TYPE_COMP_EDITOR_PAGE); editor_page_class->get_widget = alarm_page_get_widget; editor_page_class->fill_widgets = alarm_page_fill_widgets; editor_page_class->fill_component = alarm_page_fill_component; editor_page_class->set_summary = alarm_page_set_summary; - editor_page_class->get_summary = alarm_page_get_summary; editor_page_class->set_dates = alarm_page_set_dates; object_class->destroy = alarm_page_destroy; @@ -143,7 +146,7 @@ alarm_page_init (AlarmPage *apage) priv->main = NULL; priv->summary = NULL; - priv->starting_date = NULL; + priv->date_time = NULL; priv->list = NULL; priv->add = NULL; priv->delete = NULL; @@ -152,6 +155,8 @@ alarm_page_init (AlarmPage *apage) priv->value_units = NULL; priv->relative = NULL; priv->time = NULL; + + priv->updating = FALSE; } /* Frees all the alarm data and empties the list */ @@ -159,24 +164,25 @@ static void free_alarms (AlarmPage *apage) { AlarmPagePrivate *priv; - GtkCList *clist; int i; priv = apage->priv; - clist = GTK_CLIST (priv->list); - - for (i = 0; i < clist->rows; i++) { - CalComponentAlarm *alarm; - - alarm = gtk_clist_get_row_data (clist, i); - g_assert (alarm != NULL); - cal_component_alarm_free (alarm); - - gtk_clist_set_row_data (clist, i, NULL); + if (priv->list != NULL) { + GtkCList *clist = GTK_CLIST (priv->list); + + for (i = 0; i < clist->rows; i++) { + CalComponentAlarm *alarm; + + alarm = gtk_clist_get_row_data (clist, i); + g_assert (alarm != NULL); + cal_component_alarm_free (alarm); + + gtk_clist_set_row_data (clist, i, NULL); + } + + gtk_clist_clear (clist); } - - gtk_clist_clear (clist); } /* Destroy handler for the alarm page */ @@ -210,7 +216,7 @@ alarm_page_destroy (GtkObject *object) /* get_widget handler for the alarm page */ static GtkWidget * -alarm_page_get_widget (EditorPage *page) +alarm_page_get_widget (CompEditorPage *page) { AlarmPage *apage; AlarmPagePrivate *priv; @@ -230,10 +236,10 @@ clear_widgets (AlarmPage *apage) priv = apage->priv; /* Summary */ - e_dialog_editable_set (priv->summary, NULL); + gtk_label_set_text (GTK_LABEL (priv->summary), ""); /* Start date */ - gtk_label_set_text (GTK_LABEL (priv->starting_date), ""); + gtk_label_set_text (GTK_LABEL (priv->date_time), ""); /* List data */ free_alarms (apage); @@ -310,6 +316,7 @@ get_alarm_string (CalComponentAlarm *alarm) case CAL_ALARM_NONE: case CAL_ALARM_UNKNOWN: + default: base = _("Unknown"); break; } @@ -344,6 +351,7 @@ get_alarm_string (CalComponentAlarm *alarm) break; case CAL_ALARM_TRIGGER_NONE: case CAL_ALARM_TRIGGER_ABSOLUTE: + default: str = g_strdup_printf ("%s %s", base, _("Unknown")); break; @@ -377,22 +385,31 @@ append_reminder (AlarmPage *apage, CalComponentAlarm *alarm) /* fill_widgets handler for the alarm page */ static void -alarm_page_fill_widgets (EditorPage *page, CalComponent *comp) +alarm_page_fill_widgets (CompEditorPage *page, CalComponent *comp) { AlarmPage *apage; AlarmPagePrivate *priv; CalComponentText text; GList *alarms, *l; GtkCList *clist; - + CompEditorPageDates dates; + apage = ALARM_PAGE (page); priv = apage->priv; + /* Don't send off changes during this time */ + priv->updating = TRUE; + + /* Clean the page */ clear_widgets (apage); /* Summary */ cal_component_get_summary (comp, &text); - e_dialog_editable_set (priv->summary, text.value); + alarm_page_set_summary (page, text.value); + + /* Dates */ + comp_editor_dates (&dates, comp); + alarm_page_set_dates (page, &dates); /* List */ if (!cal_component_has_alarms (comp)) @@ -415,11 +432,13 @@ alarm_page_fill_widgets (EditorPage *page, CalComponent *comp) append_reminder (apage, ca_copy); } cal_obj_uid_list_free (alarms); + + priv->updating = FALSE; } /* fill_component handler for the alarm page */ static void -alarm_page_fill_component (EditorPage *page, CalComponent *comp) +alarm_page_fill_component (CompEditorPage *page, CalComponent *comp) { AlarmPage *apage; AlarmPagePrivate *priv; @@ -462,48 +481,31 @@ alarm_page_fill_component (EditorPage *page, CalComponent *comp) /* set_summary handler for the alarm page */ static void -alarm_page_set_summary (EditorPage *page, const char *summary) +alarm_page_set_summary (CompEditorPage *page, const char *summary) { AlarmPage *apage; AlarmPagePrivate *priv; - + gchar *s; + apage = ALARM_PAGE (page); priv = apage->priv; - gtk_signal_handler_block_by_data (GTK_OBJECT (priv->summary), apage); - e_utf8_gtk_entry_set_text (GTK_ENTRY (priv->summary), summary); - gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->summary), apage); -} - -/* get_summary handler for the alarm page */ -static char * -alarm_page_get_summary (EditorPage *page) -{ - AlarmPage *apage; - AlarmPagePrivate *priv; - - apage = ALARM_PAGE (page); - priv = apage->priv; - - return e_utf8_gtk_entry_get_text (GTK_ENTRY (priv->summary)); + s = e_utf8_to_gtk_string (priv->summary, summary); + gtk_label_set_text (GTK_LABEL (priv->summary), s); + g_free (s); } /* set_dates handler for the alarm page */ static void -alarm_page_set_dates (EditorPage *page, time_t start, time_t end) +alarm_page_set_dates (CompEditorPage *page, CompEditorPageDates *dates) { AlarmPage *apage; AlarmPagePrivate *priv; - char str[128]; - struct tm tm; apage = ALARM_PAGE (page); priv = apage->priv; - tm = *localtime (&start); - strftime (str, sizeof (str), _("%A %b %d %Y %H:%M:%S"), &tm); - - gtk_label_set_text (GTK_LABEL (priv->starting_date), str); + comp_editor_date_label (dates, priv->date_time); } @@ -554,23 +556,18 @@ static gboolean get_widgets (AlarmPage *apage) { AlarmPagePrivate *priv; - GtkWidget *toplevel; priv = apage->priv; #define GW(name) glade_xml_get_widget (priv->xml, name) - toplevel = GW ("alarm-toplevel"); priv->main = GW ("alarm-page"); - if (!(toplevel && priv->main)) - return FALSE; - + g_assert (priv->main); gtk_widget_ref (priv->main); gtk_widget_unparent (priv->main); - gtk_widget_destroy (toplevel); - + priv->summary = GW ("summary"); - priv->starting_date = GW ("starting-date"); + priv->date_time = GW ("date-time"); priv->list = GW ("list"); priv->add = GW ("add"); @@ -585,7 +582,7 @@ get_widgets (AlarmPage *apage) #undef GW return (priv->summary - && priv->starting_date + && priv->date_time && priv->list && priv->add && priv->delete @@ -596,24 +593,18 @@ get_widgets (AlarmPage *apage) && priv->time); } -/* Callback used when the summary changes; we emit the notification signal. */ -static void -summary_changed_cb (GtkEditable *editable, gpointer data) -{ - AlarmPage *apage; - - apage = ALARM_PAGE (data); - editor_page_notify_summary_changed (EDITOR_PAGE (apage)); -} - /* This is called when any field is changed; it notifies upstream. */ static void field_changed_cb (GtkWidget *widget, gpointer data) { AlarmPage *apage; - + AlarmPagePrivate *priv; + apage = ALARM_PAGE (data); - editor_page_notify_changed (EDITOR_PAGE (apage)); + priv = apage->priv; + + if (!priv->updating) + comp_editor_page_notify_changed (COMP_EDITOR_PAGE (apage)); } /* Callback used for the "add reminder" button */ @@ -639,15 +630,18 @@ add_clicked_cb (GtkButton *button, gpointer data) switch (e_dialog_option_menu_get (priv->value_units, value_map)) { case MINUTES: - trigger.u.rel_duration.minutes = e_dialog_spin_get_int (priv->interval_value); + trigger.u.rel_duration.minutes = + e_dialog_spin_get_int (priv->interval_value); break; case HOURS: - trigger.u.rel_duration.hours = e_dialog_spin_get_int (priv->interval_value); + trigger.u.rel_duration.hours = + e_dialog_spin_get_int (priv->interval_value); break; case DAYS: - trigger.u.rel_duration.days = e_dialog_spin_get_int (priv->interval_value); + trigger.u.rel_duration.days = + e_dialog_spin_get_int (priv->interval_value); break; default: @@ -702,10 +696,6 @@ init_widgets (AlarmPage *apage) priv = apage->priv; - /* Summary */ - gtk_signal_connect (GTK_OBJECT (priv->summary), "changed", - GTK_SIGNAL_FUNC (summary_changed_cb), apage); - /* Reminder buttons */ gtk_signal_connect (GTK_OBJECT (priv->add), "clicked", GTK_SIGNAL_FUNC (add_clicked_cb), apage); @@ -739,14 +729,17 @@ alarm_page_construct (AlarmPage *apage) priv = apage->priv; - priv->xml = glade_xml_new (EVOLUTION_GLADEDIR "/alarm-page.glade", NULL); + priv->xml = glade_xml_new (EVOLUTION_GLADEDIR "/alarm-page.glade", + NULL); if (!priv->xml) { - g_message ("alarm_page_construct(): Could not load the Glade XML file!"); + g_message ("alarm_page_construct(): " + "Could not load the Glade XML file!"); return NULL; } if (!get_widgets (apage)) { - g_message ("alarm_page_construct(): Could not find all widgets in the XML file!"); + g_message ("alarm_page_construct(): " + "Could not find all widgets in the XML file!"); return NULL; } diff --git a/calendar/gui/dialogs/alarm-page.glade b/calendar/gui/dialogs/alarm-page.glade index 3a4a8d6765..183ec1b95b 100644 --- a/calendar/gui/dialogs/alarm-page.glade +++ b/calendar/gui/dialogs/alarm-page.glade @@ -18,6 +18,7 @@ GtkWindow alarm-toplevel + False window1 GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE @@ -36,7 +37,7 @@ GtkFrame frame33 - + 0 GTK_SHADOW_ETCHED_IN @@ -58,14 +59,13 @@ GtkLabel label62 - + GTK_JUSTIFY_CENTER False 0 0.5 0 0 - reminder-summary 0 1 @@ -83,42 +83,44 @@ - GtkEntry - reminder-summary - True - True - True - 0 - + GtkLabel + label63 + + GTK_JUSTIFY_CENTER + False + 0 + 0 + 0 + 0 - 1 - 2 - 0 - 1 + 0 + 1 + 1 + 2 0 0 - True + False False - True + False False True - False + True GtkLabel - label63 - - GTK_JUSTIFY_CENTER + date-time + + GTK_JUSTIFY_LEFT False - 0 - 0 - 0 + 0.5 + 0.5 + 4 0 - 0 - 1 + 1 + 2 1 2 0 @@ -134,19 +136,19 @@ GtkLabel - starting date - - GTK_JUSTIFY_CENTER + summary + + GTK_JUSTIFY_LEFT False 0 - 0 - 0 + 0.5 + 4 0 1 2 - 1 - 2 + 0 + 1 0 0 False @@ -154,7 +156,7 @@ False False True - True + False @@ -192,7 +194,7 @@ GtkOptionMenu - reminder-action + action True Show a dialog Play a sound @@ -209,7 +211,7 @@ Run a program GtkSpinButton - reminder-interval-value + interval-value True 1 0 @@ -232,7 +234,7 @@ Run a program GtkOptionMenu - reminder-value-units + value-units True minute(s) hour(s) @@ -248,7 +250,7 @@ day(s) GtkOptionMenu - reminder-relative + relative True before after @@ -263,7 +265,7 @@ after GtkOptionMenu - reminder-time + time True start of appointment end of appointment @@ -281,7 +283,6 @@ end of appointment button9 True - GTK_RELIEF_NORMAL 0 False @@ -316,7 +317,7 @@ end of appointment GtkCList - reminder-list + list True 1 80 @@ -356,20 +357,18 @@ end of appointment GtkButton - reminder-add + add True True - GTK_RELIEF_NORMAL GtkButton - reminder-delete + delete True True - GTK_RELIEF_NORMAL diff --git a/calendar/gui/dialogs/alarm-page.h b/calendar/gui/dialogs/alarm-page.h index 1cb0b301bd..97c1361f4d 100644 --- a/calendar/gui/dialogs/alarm-page.h +++ b/calendar/gui/dialogs/alarm-page.h @@ -25,7 +25,7 @@ #ifndef ALARM_PAGE_H #define ALARM_PAGE_H -#include "editor-page.h" +#include "comp-editor-page.h" BEGIN_GNOME_DECLS @@ -33,29 +33,27 @@ BEGIN_GNOME_DECLS #define TYPE_ALARM_PAGE (alarm_page_get_type ()) #define ALARM_PAGE(obj) (GTK_CHECK_CAST ((obj), TYPE_ALARM_PAGE, AlarmPage)) -#define ALARM_PAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_ALARM_PAGE, \ - AlarmPageClass)) +#define ALARM_PAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_ALARM_PAGE, AlarmPageClass)) #define IS_ALARM_PAGE(obj) (GTK_CHECK_TYPE ((obj), TYPE_ALARM_PAGE)) #define IS_ALARM_PAGE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), TYPE_ALARM_PAGE)) typedef struct _AlarmPagePrivate AlarmPagePrivate; typedef struct { - EditorPage page; + CompEditorPage page; /* Private data */ AlarmPagePrivate *priv; } AlarmPage; typedef struct { - EditorPageClass parent_class; + CompEditorPageClass parent_class; } AlarmPageClass; -GtkType alarm_page_get_type (void); +GtkType alarm_page_get_type (void); AlarmPage *alarm_page_construct (AlarmPage *apage); - -AlarmPage *alarm_page_new (void); +AlarmPage *alarm_page_new (void); diff --git a/calendar/gui/dialogs/comp-editor-page.c b/calendar/gui/dialogs/comp-editor-page.c new file mode 100644 index 0000000000..f390e86dd8 --- /dev/null +++ b/calendar/gui/dialogs/comp-editor-page.c @@ -0,0 +1,277 @@ +/* Evolution calendar - Base class for calendar component editor pages + * + * Copyright (C) 2001 Ximian, Inc. + * + * Authors: Federico Mena-Quintero + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include "comp-editor-page.h" + + + +static void comp_editor_page_class_init (CompEditorPageClass *class); + +/* Signal IDs */ + +enum { + CHANGED, + SUMMARY_CHANGED, + DATES_CHANGED, + LAST_SIGNAL +}; + +static guint comp_editor_page_signals[LAST_SIGNAL]; + +#define CLASS(page) (COMP_EDITOR_PAGE_CLASS (GTK_OBJECT (page)->klass)) + + + +/** + * comp_editor_page_get_type: + * + * Registers the #CompEditorPage class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the #CompEditorPage class. + **/ +GtkType +comp_editor_page_get_type (void) +{ + static GtkType comp_editor_page_type = 0; + + if (!comp_editor_page_type) { + static const GtkTypeInfo comp_editor_page_info = { + "CompEditorPage", + sizeof (CompEditorPage), + sizeof (CompEditorPageClass), + (GtkClassInitFunc) comp_editor_page_class_init, + (GtkObjectInitFunc) NULL, + NULL, /* reserved_1 */ + NULL, /* reserved_2 */ + (GtkClassInitFunc) NULL + }; + + comp_editor_page_type = + gtk_type_unique (GTK_TYPE_OBJECT, + &comp_editor_page_info); + } + + return comp_editor_page_type; +} + +/* Class initialization function for the abstract editor page */ +static void +comp_editor_page_class_init (CompEditorPageClass *class) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass *) class; + + comp_editor_page_signals[CHANGED] = + gtk_signal_new ("changed", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (CompEditorPageClass, + changed), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + comp_editor_page_signals[SUMMARY_CHANGED] = + gtk_signal_new ("summary_changed", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (CompEditorPageClass, + summary_changed), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); + + comp_editor_page_signals[DATES_CHANGED] = + gtk_signal_new ("dates_changed", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (CompEditorPageClass, + dates_changed), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); + + gtk_object_class_add_signals (object_class, + comp_editor_page_signals, + LAST_SIGNAL); + + class->changed = NULL; + class->summary_changed = NULL; + class->dates_changed = NULL; + + class->get_widget = NULL; + class->fill_widgets = NULL; + class->fill_component = NULL; + class->set_summary = NULL; + class->set_dates = NULL; +} + + + +/** + * comp_editor_page_get_widget: + * @page: An editor page. + * + * Queries the main widget of an editor page. + * + * Return value: The widget that is the page's upper container. It should + * normally be inserted in a notebook widget. + **/ +GtkWidget * +comp_editor_page_get_widget (CompEditorPage *page) +{ + g_return_val_if_fail (page != NULL, NULL); + g_return_val_if_fail (IS_COMP_EDITOR_PAGE (page), NULL); + + g_assert (CLASS (page)->get_widget != NULL); + return (* CLASS (page)->get_widget) (page); +} + +/** + * comp_editor_page_fill_widgets: + * @page: An editor page. + * @comp: A calendar component. + * + * Fills the widgets of an editor page with the data from a calendar component. + **/ +void +comp_editor_page_fill_widgets (CompEditorPage *page, CalComponent *comp) +{ + g_return_if_fail (page != NULL); + g_return_if_fail (IS_COMP_EDITOR_PAGE (page)); + g_return_if_fail (comp != NULL); + + g_assert (CLASS (page)->fill_widgets != NULL); + (* CLASS (page)->fill_widgets) (page, comp); +} + +/** + * comp_editor_page_fill_component: + * @page: An editor page. + * @comp: A calendar component. + * + * Takes the data from the widgets of an editor page and sets it on a calendar + * component, replacing the contents of the properties that the editor page + * knows how to manipulate. + **/ +void +comp_editor_page_fill_component (CompEditorPage *page, CalComponent *comp) +{ + g_return_if_fail (page != NULL); + g_return_if_fail (IS_COMP_EDITOR_PAGE (page)); + g_return_if_fail (comp != NULL); + + if (CLASS (page)->fill_component != NULL) + (* CLASS (page)->fill_component) (page, comp); +} + +/** + * comp_editor_page_set_summary: + * @page: An editor page + * @summary: The text of the new summary value + * + * Sets the summary value for this group of widgets + **/ +void +comp_editor_page_set_summary (CompEditorPage *page, const char *summary) +{ + g_return_if_fail (page != NULL); + g_return_if_fail (IS_COMP_EDITOR_PAGE (page)); + + if (CLASS (page)->set_summary != NULL) + (* CLASS (page)->set_summary) (page, summary); +} + +/** + * comp_editor_page_set_dates: + * @page: An editor page + * @dates: A collection of various dates in time_t format + * + * Sets the date values for this group of widgets + **/ +void +comp_editor_page_set_dates (CompEditorPage *page, CompEditorPageDates *dates) +{ + g_return_if_fail (page != NULL); + g_return_if_fail (IS_COMP_EDITOR_PAGE (page)); + + if (CLASS (page)->set_dates != NULL) + (* CLASS (page)->set_dates) (page, dates); +} + +/** + * comp_editor_page_notify_changed: + * @page: An editor page. + * + * Makes an editor page emit the "changed" signal. This is meant to be + * used only by page implementations. + **/ +void +comp_editor_page_notify_changed (CompEditorPage *page) +{ + g_return_if_fail (page != NULL); + g_return_if_fail (IS_COMP_EDITOR_PAGE (page)); + + gtk_signal_emit (GTK_OBJECT (page), comp_editor_page_signals[CHANGED]); +} + +/** + * comp_editor_page_notify_summary_changed: + * @page: An editor page. + * + * Makes an editor page emit the "summary_changed" signal. This is meant to be + * used only by page implementations. + **/ +void +comp_editor_page_notify_summary_changed (CompEditorPage *page, + const char *summary) +{ + g_return_if_fail (page != NULL); + g_return_if_fail (IS_COMP_EDITOR_PAGE (page)); + + + gtk_signal_emit (GTK_OBJECT (page), + comp_editor_page_signals[SUMMARY_CHANGED], + summary); +} + +/** + * comp_editor_page_notify_dates_changed: + * @page: An editor page. + * + * Makes an editor page emit the "dates_changed" signal. This is meant to be + * used only by page implementations. + **/ +void +comp_editor_page_notify_dates_changed (CompEditorPage *page, + CompEditorPageDates *dates) +{ + g_return_if_fail (page != NULL); + g_return_if_fail (IS_COMP_EDITOR_PAGE (page)); + + gtk_signal_emit (GTK_OBJECT (page), + comp_editor_page_signals[DATES_CHANGED], + dates); +} diff --git a/calendar/gui/dialogs/comp-editor-page.h b/calendar/gui/dialogs/comp-editor-page.h new file mode 100644 index 0000000000..ac088e7759 --- /dev/null +++ b/calendar/gui/dialogs/comp-editor-page.h @@ -0,0 +1,93 @@ +/* Evolution calendar - Base class for calendar component editor pages + * + * Copyright (C) 2001 Ximian, Inc. + * + * Authors: Federico Mena-Quintero + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef COMP_EDITOR_PAGE_H +#define COMP_EDITOR_PAGE_H + +#include +#include +#include +#include + +BEGIN_GNOME_DECLS + + + +#define TYPE_COMP_EDITOR_PAGE (comp_editor_page_get_type ()) +#define COMP_EDITOR_PAGE(obj) (GTK_CHECK_CAST ((obj), TYPE_COMP_EDITOR_PAGE, CompEditorPage)) +#define COMP_EDITOR_PAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_COMP_EDITOR_PAGE, CompEditorPageClass)) +#define IS_COMP_EDITOR_PAGE(obj) (GTK_CHECK_TYPE ((obj), TYPE_COMP_EDITOR_PAGE)) +#define IS_COMP_EDITOR_PAGE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), TYPE_COMP_EDITOR_PAGE)) + +typedef struct { + time_t start; + time_t end; + time_t due; + time_t complete; +} CompEditorPageDates; + +typedef struct { + GtkObject object; +} CompEditorPage; + +typedef struct { + GtkObjectClass parent_class; + + /* Notification signals */ + + void (* changed) (CompEditorPage *page); + void (* summary_changed) (CompEditorPage *page, const char *summary); + void (* dates_changed) (CompEditorPage *page, const char *dates); + + /* Virtual methods */ + + GtkWidget *(* get_widget) (CompEditorPage *page); + + void (* fill_widgets) (CompEditorPage *page, CalComponent *comp); + void (* fill_component) (CompEditorPage *page, CalComponent *comp); + + void (* set_summary) (CompEditorPage *page, const char *summary); + void (* set_dates) (CompEditorPage *page, CompEditorPageDates *dates); +} CompEditorPageClass; + + +GtkType comp_editor_page_get_type (void); +GtkWidget *comp_editor_page_get_widget (CompEditorPage *page); +void comp_editor_page_fill_widgets (CompEditorPage *page, + CalComponent *comp); +void comp_editor_page_fill_component (CompEditorPage *page, + CalComponent *comp); +void comp_editor_page_set_summary (CompEditorPage *page, + const char *summary); +void comp_editor_page_set_dates (CompEditorPage *page, + CompEditorPageDates *dates); +void comp_editor_page_notify_changed (CompEditorPage *page); +void comp_editor_page_notify_summary_changed (CompEditorPage *page, + const char *summary); +void comp_editor_page_notify_dates_changed (CompEditorPage *page, + CompEditorPageDates *dates); + + + + +END_GNOME_DECLS + +#endif diff --git a/calendar/gui/dialogs/comp-editor-util.c b/calendar/gui/dialogs/comp-editor-util.c new file mode 100644 index 0000000000..1110b5f18a --- /dev/null +++ b/calendar/gui/dialogs/comp-editor-util.c @@ -0,0 +1,129 @@ +/* Evolution calendar - Widget utilities + * + * Copyright (C) 2000 Helix Code, Inc. + * + * Author: Federico Mena-Quintero + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include "../calendar-config.h" +#include "comp-editor-util.h" + + + +/** + * comp_editor_dates: + * @dates: A structure to be filled out with dates of a component + * @comp: The component to extract the dates from + * + * Extracts the dates from the calendar component into the + * CompEditorPageDates structure + **/ +void +comp_editor_dates (CompEditorPageDates *dates, CalComponent *comp) +{ + CalComponentDateTime dt; + struct icaltimetype *completed; + + dates->start = 0; + dates->end = 0; + dates->due = 0; + dates->complete = 0; + + cal_component_get_dtstart (comp, &dt); + if (dt.value) + dates->start = icaltime_as_timet (*dt.value); + + cal_component_get_dtend (comp, &dt); + if (dt.value) + dates->end = icaltime_as_timet (*dt.value); + + cal_component_get_due (comp, &dt); + if (dt.value) + dates->due = icaltime_as_timet (*dt.value); + + cal_component_get_completed (comp, &completed); + if (completed) { + dates->complete = icaltime_as_timet (*completed); + cal_component_free_icaltimetype (completed); + } +} + +static void +write_label_piece (time_t t, char *buffer, int size, char *stext, char *etext) +{ + struct tm *tmp_tm; + int len; + + tmp_tm = localtime (&t); + if (stext != NULL) + strcat (buffer, stext); + + len = strlen (buffer); + e_time_format_date_and_time (tmp_tm, + calendar_config_get_24_hour_format (), + FALSE, FALSE, + &buffer[len], size - len); + if (etext != NULL) + strcat (buffer, etext); +} + +/** + * comp_editor_date_label: + * @dates: The dates to use in constructing a label + * @label: The label whose text is to be set + * + * Set the text of a label based on the dates available and the user's + * formatting preferences + **/ +void +comp_editor_date_label (CompEditorPageDates *dates, GtkWidget *label) +{ + static char buffer[1024]; + + buffer[0] = '\0'; + + if (dates->start > 0) + write_label_piece (dates->start, buffer, 1024, NULL, NULL); + + if (dates->end > 0 && dates->start > 0) + write_label_piece (dates->end, buffer, 1024, _(" to "), NULL); + + if (dates->complete > 0) { + if (dates->start > 0) + write_label_piece (dates->complete, buffer, 1024, _(" (Completed "), ")"); + else + write_label_piece (dates->complete, buffer, 1024, _(" Completed "), NULL); + } + + if (dates->due > 0 && dates->complete == 0) { + if (dates->start > 0) + write_label_piece (dates->due, buffer, 1024, _(" (Due "), ")"); + else + write_label_piece (dates->due, buffer, 1024, _("Due "), NULL); + } + + gtk_label_set_text (GTK_LABEL (label), buffer); +} diff --git a/calendar/gui/dialogs/comp-editor-util.h b/calendar/gui/dialogs/comp-editor-util.h new file mode 100644 index 0000000000..ad27ab06ca --- /dev/null +++ b/calendar/gui/dialogs/comp-editor-util.h @@ -0,0 +1,31 @@ +/* Evolution calendar - Widget utilities + * + * Copyright (C) 2000 Helix Code, Inc. + * + * Author: JP Rosevear + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _COMP_EDITOR_UTIL_H_ +#define _COMP_EDITOR_UTIL_H_ + +#include +#include "comp-editor-page.h" + +void comp_editor_dates (CompEditorPageDates *date, CalComponent *comp); +void comp_editor_date_label (CompEditorPageDates *dates, GtkWidget *label); + +#endif diff --git a/calendar/gui/dialogs/comp-editor.c b/calendar/gui/dialogs/comp-editor.c index f101bfa15a..ddf9f9a9ae 100644 --- a/calendar/gui/dialogs/comp-editor.c +++ b/calendar/gui/dialogs/comp-editor.c @@ -23,12 +23,21 @@ #include #endif +#include +#include +#include "save-comp.h" #include "comp-editor.h" /* Private part of the CompEditor structure */ struct _CompEditorPrivate { + /* Client to use */ + CalClient *client; + + /* Calendar object/uid we are editing; this is an internal copy */ + CalComponent *comp; + /* The pages we have */ GList *pages; @@ -37,6 +46,8 @@ struct _CompEditorPrivate { /* Notebook to hold the pages */ GtkNotebook *notebook; + + gboolean changed; }; @@ -45,6 +56,15 @@ static void comp_editor_class_init (CompEditorClass *class); static void comp_editor_init (CompEditor *editor); static void comp_editor_destroy (GtkObject *object); +static void page_summary_changed_cb (GtkWidget *widget, const char *summary, gpointer data); +static void page_dates_changed_cb (GtkWidget *widget, CompEditorPageDates *dates, gpointer data); +static void page_changed_cb (GtkWidget *widget, gpointer data); + +static void save_clicked_cb (GtkWidget *widget, gpointer data); +static void close_clicked_cb (GtkWidget *widget, gpointer data); +static void help_clicked_cb (GtkWidget *widget, gpointer data); +static gint delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer data); + static GtkObjectClass *parent_class; @@ -52,21 +72,22 @@ static GtkObjectClass *parent_class; GtkType comp_editor_get_type (void) { - static GtkType comp_editor_type; + static GtkType comp_editor_type = 0; if (!comp_editor_type) { - static const GtkTypeInfo comp_editor_info = { + GtkTypeInfo comp_editor_info = { "CompEditor", sizeof (CompEditor), sizeof (CompEditorClass), (GtkClassInitFunc) comp_editor_class_init, - (GtkObjectInitfunc) comp_editor_init, + (GtkObjectInitFunc) comp_editor_init, NULL, /* reserved_1 */ NULL, /* reserved_2 */ (GtkClassInitFunc) NULL - } + }; - comp_editor_type = gtk_type_unique (GTK_TYPE_OBJECT, &comp_editor_info); + comp_editor_type = gtk_type_unique (GTK_TYPE_OBJECT, + &comp_editor_info); } return comp_editor_type; @@ -110,23 +131,30 @@ setup_widgets (CompEditor *editor) /* Notebook */ priv->notebook = GTK_NOTEBOOK (gtk_notebook_new ()); - gtk_box_pack_start (GTK_BOX (vbox), priv->notebook, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (priv->notebook), + TRUE, TRUE, 0); /* Buttons */ bbox = gtk_hbutton_box_new (); - gtk_hbutton_box_set_layout_default (GTK_HBUTTON_BOX (bbox), GTK_BUTTONBOX_END); + gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END); gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0); pixmap = gnome_stock_pixmap_widget (NULL, GNOME_STOCK_PIXMAP_SAVE); button = gnome_pixmap_button (pixmap, _("Save")); gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0); - + gtk_signal_connect (GTK_OBJECT (button), "clicked", + GTK_SIGNAL_FUNC (save_clicked_cb), editor); + button = gnome_stock_button (GNOME_STOCK_BUTTON_CLOSE); gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0); + gtk_signal_connect (GTK_OBJECT (button), "clicked", + GTK_SIGNAL_FUNC (close_clicked_cb), editor); button = gnome_stock_button (GNOME_STOCK_BUTTON_HELP); gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0); + gtk_signal_connect (GTK_OBJECT (button), "clicked", + GTK_SIGNAL_FUNC (help_clicked_cb), editor); } /* Object initialization function for the calendar component editor */ @@ -141,6 +169,7 @@ comp_editor_init (CompEditor *editor) setup_widgets (editor); priv->pages = NULL; + priv->changed = FALSE; } /* Destroy handler for the calendar component editor */ @@ -167,8 +196,18 @@ comp_editor_destroy (GtkObject *object) +/** + * comp_editor_append_page: + * @editor: A component editor + * @page: Top level widget of the page + * @label: Label of the page + * + * Appends a page to the editor notebook with the given label + **/ void -comp_editor_append_page (CompEditor *editor, EditorPage *page, const char *label) +comp_editor_append_page (CompEditor *editor, + CompEditorPage *page, + const char *label) { CompEditorPrivate *priv; GtkWidget *page_widget; @@ -177,7 +216,7 @@ comp_editor_append_page (CompEditor *editor, EditorPage *page, const char *label g_return_if_fail (editor != NULL); g_return_if_fail (IS_COMP_EDITOR (editor)); g_return_if_fail (page != NULL); - g_return_if_fail (IS_EDITOR_PAGE (page)); + g_return_if_fail (IS_COMP_EDITOR_PAGE (page)); g_return_if_fail (label != NULL); priv = editor->priv; @@ -185,11 +224,333 @@ comp_editor_append_page (CompEditor *editor, EditorPage *page, const char *label /* Only allow adding the pages while a component has not been set */ g_return_if_fail (priv->comp == NULL); - page_widget = editor_page_get_widget (page); + page_widget = comp_editor_page_get_widget (page); g_assert (page_widget != NULL); - + label_widget = gtk_label_new (label); priv->pages = g_list_append (priv->pages, page); gtk_notebook_append_page (priv->notebook, page_widget, label_widget); + + /* Listen for things happening on the page */ + gtk_signal_connect (GTK_OBJECT (page), "summary_changed", + GTK_SIGNAL_FUNC (page_summary_changed_cb), editor); + gtk_signal_connect (GTK_OBJECT (page), "dates_changed", + GTK_SIGNAL_FUNC (page_dates_changed_cb), editor); + gtk_signal_connect (GTK_OBJECT (page), "changed", + GTK_SIGNAL_FUNC (page_changed_cb), editor); +} + +/** + * comp_editor_set_cal_client: + * @editor: A component editor + * @client: The calendar client to use + * + * Sets the calendar client used by the editor to update components + **/ +void +comp_editor_set_cal_client (CompEditor *editor, CalClient *client) +{ + CompEditorPrivate *priv; + + g_return_if_fail (editor != NULL); + g_return_if_fail (IS_COMP_EDITOR (editor)); + + priv = editor->priv; + + if (client == priv->client) + return; + + if (client) { + g_return_if_fail (IS_CAL_CLIENT (client)); + g_return_if_fail (cal_client_get_load_state (client) == + CAL_CLIENT_LOAD_LOADED); + gtk_object_ref (GTK_OBJECT (client)); + } + + if (priv->client) { + gtk_signal_disconnect_by_data (GTK_OBJECT (priv->client), + editor); + gtk_object_unref (GTK_OBJECT (priv->client)); + } + + priv->client = client; +} + +/** + * comp_editor_get_cal_client: + * @editor: A component editor + * + * Returns the calendar client of the editor + * + * Return value: The calendar client of the editor + **/ +CalClient * +comp_editor_get_cal_client (CompEditor *editor) +{ + CompEditorPrivate *priv; + + g_return_val_if_fail (editor != NULL, NULL); + g_return_val_if_fail (IS_COMP_EDITOR (editor), NULL); + + priv = editor->priv; + + return priv->client; +} + +/* Creates an appropriate title for the event editor dialog */ +static char * +make_title_from_comp (CalComponent *comp) +{ + char *title; + const char *type_string; + CalComponentVType type; + CalComponentText text; + + if (!comp) + return g_strdup (_("Edit Appointment")); + + type = cal_component_get_vtype (comp); + switch (type) { + case CAL_COMPONENT_EVENT: + type_string = _("Appointment - %s"); + break; + case CAL_COMPONENT_TODO: + type_string = _("Task - %s"); + break; + case CAL_COMPONENT_JOURNAL: + type_string = _("Journal entry - %s"); + break; + default: + g_message ("make_title_from_comp(): Cannot handle object of type %d", type); + return NULL; + } + + cal_component_get_summary (comp, &text); + if (text.value) { + char *summary; + summary = e_utf8_to_locale_string (text.value); + title = g_strdup_printf (type_string, summary); + g_free (summary); + } else + title = g_strdup_printf (type_string, _("No summary")); + + return title; +} + +/* Sets the event editor's window title from a calendar component */ +static void +set_title_from_comp (CompEditor *editor) +{ + CompEditorPrivate *priv; + char *title; + + priv = editor->priv; + title = make_title_from_comp (priv->comp); + gtk_window_set_title (GTK_WINDOW (priv->window), title); + g_free (title); +} + +static void +fill_widgets (CompEditor *editor) +{ + CompEditorPrivate *priv; + GList *l; + + priv = editor->priv; + + for (l = priv->pages; l != NULL; l = l->next) + comp_editor_page_fill_widgets (l->data, priv->comp); +} + +/** + * comp_editor_edit_comp: + * @editor: A component editor + * @comp: A calendar component + * + * Starts the editor editing the given component + **/ +void +comp_editor_edit_comp (CompEditor *editor, CalComponent *comp) +{ + CompEditorPrivate *priv; + + g_return_if_fail (editor != NULL); + g_return_if_fail (IS_COMP_EDITOR (editor)); + + priv = editor->priv; + + if (priv->comp) { + gtk_object_unref (GTK_OBJECT (priv->comp)); + priv->comp = NULL; + } + + if (comp) + priv->comp = cal_component_clone (comp); + + set_title_from_comp (editor); + fill_widgets (editor); +} + + +/* Brings attention to a window by raising it and giving it focus */ +static void +raise_and_focus (GtkWidget *widget) +{ + g_assert (GTK_WIDGET_REALIZED (widget)); + gdk_window_show (widget->window); + gtk_widget_grab_focus (widget); +} + +/** + * comp_editor_focus: + * @editor: A component editor + * + * Brings the editor window to the front and gives it focus + **/ +void +comp_editor_focus (CompEditor *editor) +{ + CompEditorPrivate *priv; + + g_return_if_fail (editor != NULL); + g_return_if_fail (IS_COMP_EDITOR (editor)); + + priv = editor->priv; + + gtk_widget_show_all (priv->window); + raise_and_focus (priv->window); +} + +static void +save_comp (CompEditor *editor) +{ + CompEditorPrivate *priv; + GList *l; + + priv = editor->priv; + + for (l = priv->pages; l != NULL; l = l->next) + comp_editor_page_fill_component (l->data, priv->comp); + + if (!cal_client_update_object (priv->client, priv->comp)) + g_message ("save_comp (): Could not update the object!"); + else + priv->changed = FALSE; +} + +static gboolean +prompt_to_save_changes (CompEditor *editor) +{ + CompEditorPrivate *priv; + + priv = editor->priv; + + if (!priv->changed) + return TRUE; + + switch (save_component_dialog (GTK_WINDOW (priv->window))) { + case 0: /* Save */ + /* FIXME: If an error occurs here, we should popup a dialog + and then return FALSE. */ + save_comp (editor); + return TRUE; + case 1: /* Discard */ + return TRUE; + case 2: /* Cancel */ + default: + return FALSE; + break; + } +} + +/* Closes the dialog box and emits the appropriate signals */ +static void +close_dialog (CompEditor *editor) +{ + CompEditorPrivate *priv; + + priv = editor->priv; + + g_assert (priv->window != NULL); + + gtk_object_destroy (GTK_OBJECT (editor)); +} + +static void +save_clicked_cb (GtkWidget *widget, gpointer data) +{ + CompEditor *editor = COMP_EDITOR (data); + + save_comp (editor); + close_dialog (editor); +} + +static void +close_clicked_cb (GtkWidget *widget, gpointer data) +{ + CompEditor *editor = COMP_EDITOR (data); + + if (prompt_to_save_changes (editor)) + close_dialog (editor); +} + +static void +help_clicked_cb (GtkWidget *widget, gpointer data) +{ +} + +static void +page_summary_changed_cb (GtkWidget *widget, const char *summary, gpointer data) +{ + CompEditor *editor = COMP_EDITOR (data); + CompEditorPrivate *priv; + GList *l; + + priv = editor->priv; + + for (l = priv->pages; l != NULL; l = l->next) + comp_editor_page_set_summary (l->data, summary); + + priv->changed = TRUE; +} + +static void +page_dates_changed_cb (GtkWidget *widget, + CompEditorPageDates *dates, + gpointer data) +{ + CompEditor *editor = COMP_EDITOR (data); + CompEditorPrivate *priv; + GList *l; + + priv = editor->priv; + + for (l = priv->pages; l != NULL; l = l->next) + comp_editor_page_set_dates (l->data, dates); + + priv->changed = TRUE; +} + + +static void +page_changed_cb (GtkWidget *widget, gpointer data) +{ + CompEditor *editor = COMP_EDITOR (data); + CompEditorPrivate *priv; + + priv = editor->priv; + + priv->changed = TRUE; +} + +static gint +delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer data) +{ + CompEditor *editor = COMP_EDITOR (data); + + if (prompt_to_save_changes (editor)) + close_dialog (editor); + + return TRUE; } diff --git a/calendar/gui/dialogs/comp-editor.h b/calendar/gui/dialogs/comp-editor.h index 2362c1d012..225abeac3c 100644 --- a/calendar/gui/dialogs/comp-editor.h +++ b/calendar/gui/dialogs/comp-editor.h @@ -22,7 +22,9 @@ #ifndef COMP_EDITOR_H #define COMP_EDITOR_H -#include "editor-page.h" +#include +#include "cal-client.h" +#include "comp-editor-page.h" BEGIN_GNOME_DECLS @@ -30,8 +32,7 @@ BEGIN_GNOME_DECLS #define TYPE_COMP_EDITOR (comp_editor_get_type ()) #define COMP_EDITOR(obj) (GTK_CHECK_CAST ((obj), TYPE_COMP_EDITOR, CompEditor)) -#define COMP_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_COMP_EDITOR, \ - CompEditorClass)) +#define COMP_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_COMP_EDITOR, CompEditorClass)) #define IS_COMP_EDITOR(obj) (GTK_CHECK_TYPE ((obj), TYPE_COMP_EDITOR)) #define IS_COMP_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), TYPE_COMP_EDITOR)) @@ -48,11 +49,17 @@ typedef struct { GtkObjectClass parent_class; } CompEditorClass; -GtkType comp_editor_get_type (void); - -CompEditor *comp_editor_new (void); - -void comp_editor_add_page (CompEditor *editor, EditorPage *page); +GtkType comp_editor_get_type (void); +CompEditor *comp_editor_new (void); +void comp_editor_append_page (CompEditor *editor, + CompEditorPage *page, + const char *label); +void comp_editor_set_cal_client (CompEditor *editor, + CalClient *client); +CalClient * comp_editor_get_cal_client (CompEditor *editor); +void comp_editor_edit_comp (CompEditor *ee, + CalComponent *comp); +void comp_editor_focus (CompEditor *editor); diff --git a/calendar/gui/dialogs/editor-page.c b/calendar/gui/dialogs/editor-page.c deleted file mode 100644 index 5aad3aa01e..0000000000 --- a/calendar/gui/dialogs/editor-page.c +++ /dev/null @@ -1,260 +0,0 @@ -/* Evolution calendar - Base class for calendar component editor pages - * - * Copyright (C) 2001 Ximian, Inc. - * - * Authors: Federico Mena-Quintero - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include "editor-page.h" - - - -static void editor_page_class_init (EditorPageClass *class); - -/* Signal IDs */ - -enum { - CHANGED, - SUMMARY_CHANGED, - LAST_SIGNAL -}; - -static guint editor_page_signals[LAST_SIGNAL]; - -#define CLASS(page) (EDITOR_PAGE_CLASS (GTK_OBJECT (page)->klass)) - - - -/** - * editor_page_get_type: - * - * Registers the #EditorPage class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the #EditorPage class. - **/ -GtkType -editor_page_get_type (void) -{ - static GtkType editor_page_type = 0; - - if (!editor_page_type) { - static const GtkTypeInfo editor_page_info = { - "EditorPage", - sizeof (EditorPage), - sizeof (EditorPageClass), - (GtkClassInitFunc) editor_page_class_init, - (GtkObjectInitFunc) NULL, - NULL, /* reserved_1 */ - NULL, /* reserved_2 */ - (GtkClassInitFunc) NULL - }; - - editor_page_type = gtk_type_unique (GTK_TYPE_OBJECT, &editor_page_info); - } - - return editor_page_type; -} - -/* Class initialization function for the abstract editor page */ -static void -editor_page_class_init (EditorPageClass *class) -{ - GtkObjectClass *object_class; - - object_class = (GtkObjectClass *) class; - - editor_page_signals[CHANGED] = - gtk_signal_new ("changed", - GTK_RUN_FIRST, - object_class->type, - GTK_SIGNAL_OFFSET (EditorPageClass, changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - editor_page_signals[SUMMARY_CHANGED] = - gtk_signal_new ("summary_changed", - GTK_RUN_FIRST, - object_class->type, - GTK_SIGNAL_OFFSET (EditorPageClass, summary_changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - gtk_object_class_add_signals (object_class, editor_page_signals, LAST_SIGNAL); - - class->changed = NULL; - class->summary_changed = NULL; - - class->get_widget = NULL; - class->fill_widgets = NULL; - class->fill_component = NULL; - class->set_summary = NULL; - class->get_summary = NULL; - class->set_dates = NULL; -} - - - -/** - * editor_page_get_widget: - * @page: An editor page. - * - * Queries the main widget of an editor page. - * - * Return value: The widget that is the page's upper container. It should - * normally be inserted in a notebook widget. - **/ -GtkWidget * -editor_page_get_widget (EditorPage *page) -{ - g_return_val_if_fail (page != NULL, NULL); - g_return_val_if_fail (IS_EDITOR_PAGE (page), NULL); - - g_assert (CLASS (page)->get_widget != NULL); - return (* CLASS (page)->get_widget) (page); -} - -/** - * editor_page_fill_widgets: - * @page: An editor page. - * @comp: A calendar component. - * - * Fills the widgets of an editor page with the data from a calendar component. - **/ -void -editor_page_fill_widgets (EditorPage *page, CalComponent *comp) -{ - g_return_if_fail (page != NULL); - g_return_if_fail (IS_EDITOR_PAGE (page)); - g_return_if_fail (comp != NULL); - - g_assert (CLASS (page)->fill_widgets != NULL); - (* CLASS (page)->fill_widgets) (page, comp); -} - -/** - * editor_page_fill_component: - * @page: An editor page. - * @comp: A calendar component. - * - * Takes the data from the widgets of an editor page and sets it on a calendar - * component, replacing the contents of the properties that the editor page - * knows how to manipulate. - **/ -void -editor_page_fill_component (EditorPage *page, CalComponent *comp) -{ - g_return_if_fail (page != NULL); - g_return_if_fail (IS_EDITOR_PAGE (page)); - g_return_if_fail (comp != NULL); - - g_assert (CLASS (page)->fill_component != NULL); - (* CLASS (page)->fill_component) (page, comp); -} - -/** - * editor_page_set_summary: - * @page: An editor page. - * @summary: Summary string to set in the page's widgets, which must be encoded - * in UTF8. - * - * Sets the calendar component summary string in an editor page. - **/ -void -editor_page_set_summary (EditorPage *page, const char *summary) -{ - g_return_if_fail (page != NULL); - g_return_if_fail (IS_EDITOR_PAGE (page)); - g_return_if_fail (summary != NULL); - - g_assert (CLASS (page)->set_summary != NULL); - (* CLASS (page)->set_summary) (page, summary); -} - -/** - * editor_page_get_summary: - * @page: An editor page. - * - * Queries the current summary string in an editor page. - * - * Return value: Summary string in UTF8; must be freed by the caller. - **/ -char * -editor_page_get_summary (EditorPage *page) -{ - g_return_val_if_fail (page != NULL, NULL); - g_return_val_if_fail (IS_EDITOR_PAGE (page), NULL); - - g_assert (CLASS (page)->get_summary != NULL); - return (* CLASS (page)->get_summary) (page); -} - -/** - * editor_page_set_dates: - * @page: An editor page. - * @start: Start date for calendar component. - * @end: End date for calendar component. - * - * Sets the calendar component DTSTART and DTEND in an editor page. - **/ -void -editor_page_set_dates (EditorPage *page, time_t start, time_t end) -{ - g_return_if_fail (page != NULL); - g_return_if_fail (IS_EDITOR_PAGE (page)); - g_return_if_fail (start != -1); - - g_assert (CLASS (page)->set_dates != NULL); - (* CLASS (page)->set_dates) (page, start, end); -} - -/** - * editor_page_notify_changed: - * @page: An editor page. - * - * Makes an editor page emit the "changed" signal. This is meant to be - * used only by page implementations. - **/ -void -editor_page_notify_changed (EditorPage *page) -{ - g_return_if_fail (page != NULL); - g_return_if_fail (IS_EDITOR_PAGE (page)); - - gtk_signal_emit (GTK_OBJECT (page), editor_page_signals[CHANGED]); -} - -/** - * editor_page_notify_summary_changed: - * @page: An editor page. - * - * Makes an editor page emit the "summary_changed" signal. This is meant to be - * used only by page implementations. - **/ -void -editor_page_notify_summary_changed (EditorPage *page) -{ - g_return_if_fail (page != NULL); - g_return_if_fail (IS_EDITOR_PAGE (page)); - - gtk_signal_emit (GTK_OBJECT (page), editor_page_signals[SUMMARY_CHANGED]); -} diff --git a/calendar/gui/dialogs/editor-page.h b/calendar/gui/dialogs/editor-page.h deleted file mode 100644 index 48e688ae16..0000000000 --- a/calendar/gui/dialogs/editor-page.h +++ /dev/null @@ -1,86 +0,0 @@ -/* Evolution calendar - Base class for calendar component editor pages - * - * Copyright (C) 2001 Ximian, Inc. - * - * Authors: Federico Mena-Quintero - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef EDITOR_PAGE_H -#define EDITOR_PAGE_H - -#include -#include -#include -#include - -BEGIN_GNOME_DECLS - - - -#define TYPE_EDITOR_PAGE (editor_page_get_type ()) -#define EDITOR_PAGE(obj) (GTK_CHECK_CAST ((obj), TYPE_EDITOR_PAGE, EditorPage)) -#define EDITOR_PAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_EDITOR_PAGE, \ - EditorPageClass)) -#define IS_EDITOR_PAGE(obj) (GTK_CHECK_TYPE ((obj), TYPE_EDITOR_PAGE)) -#define IS_EDITOR_PAGE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), TYPE_EDITOR_PAGE)) - -typedef struct { - GtkObject object; -} EditorPage; - -typedef struct { - GtkObjectClass parent_class; - - /* Notification signals */ - - void (* changed) (EditorPage *page); - void (* summary_changed) (EditorPage *page); - void (* dtstart_changed) (EditorPage *page); - - /* Virtual methods */ - - GtkWidget *(* get_widget) (EditorPage *page); - - void (* fill_widgets) (EditorPage *page, CalComponent *comp); - void (* fill_component) (EditorPage *page, CalComponent *comp); - - void (* set_summary) (EditorPage *page, const char *summary); - char *(* get_summary) (EditorPage *page); - - void (* set_dates) (EditorPage *page, time_t start, time_t end); -} EditorPageClass; - -GtkType editor_page_get_type (void); - -GtkWidget *editor_page_get_widget (EditorPage *page); - -void editor_page_fill_widgets (EditorPage *page, CalComponent *comp); -void editor_page_fill_component (EditorPage *page, CalComponent *comp); - -void editor_page_set_summary (EditorPage *page, const char *summary); -char *editor_page_get_summary (EditorPage *page); - -void editor_page_set_dates (EditorPage *page, time_t start, time_t end); - -void editor_page_notify_changed (EditorPage *page); -void editor_page_notify_summary_changed (EditorPage *page); - - - -END_GNOME_DECLS - -#endif diff --git a/calendar/gui/dialogs/event-editor.c b/calendar/gui/dialogs/event-editor.c new file mode 100644 index 0000000000..b53efe12aa --- /dev/null +++ b/calendar/gui/dialogs/event-editor.c @@ -0,0 +1,155 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* Evolution calendar - Event editor dialog + * + * Copyright (C) 2000 Helix Code, Inc. + * Copyright (C) 2001 Ximian, Inc. + * + * Authors: Miguel de Icaza + * Federico Mena-Quintero + * Seth Alves + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "event-page.h" +#include "alarm-page.h" +#include "recurrence-page.h" +#include "event-editor.h" + +struct _EventEditorPrivate { + EventPage *event_page; + AlarmPage *alarm_page; + RecurrencePage *recur_page; +}; + + + +static void event_editor_class_init (EventEditorClass *class); +static void event_editor_init (EventEditor *ee); +static void event_editor_destroy (GtkObject *object); + +static CompEditor *parent_class; + + + +/** + * event_editor_get_type: + * + * Registers the #EventEditor class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the #EventEditor class. + **/ +GtkType +event_editor_get_type (void) +{ + static GtkType event_editor_type = 0; + + if (!event_editor_type) { + static const GtkTypeInfo event_editor_info = { + "EventEditor", + sizeof (EventEditor), + sizeof (EventEditorClass), + (GtkClassInitFunc) event_editor_class_init, + (GtkObjectInitFunc) event_editor_init, + NULL, /* reserved_1 */ + NULL, /* reserved_2 */ + (GtkClassInitFunc) NULL + }; + + event_editor_type = gtk_type_unique (TYPE_COMP_EDITOR, + &event_editor_info); + } + + return event_editor_type; +} + +/* Class initialization function for the event editor */ +static void +event_editor_class_init (EventEditorClass *class) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass *) class; + + parent_class = gtk_type_class (TYPE_COMP_EDITOR); + + object_class->destroy = event_editor_destroy; +} + +/* Object initialization function for the event editor */ +static void +event_editor_init (EventEditor *ee) +{ + EventEditorPrivate *priv; + + priv = g_new0 (EventEditorPrivate, 1); + ee->priv = priv; + + priv->event_page = event_page_new (); + comp_editor_append_page (COMP_EDITOR (ee), + COMP_EDITOR_PAGE (priv->event_page), + _("Appointment")); + + priv->alarm_page = alarm_page_new (); + comp_editor_append_page (COMP_EDITOR (ee), + COMP_EDITOR_PAGE (priv->alarm_page), + _("Reminder")); + + priv->recur_page = recurrence_page_new (); + comp_editor_append_page (COMP_EDITOR (ee), + COMP_EDITOR_PAGE (priv->recur_page), + _("Recurrence")); + +} + +/* Destroy handler for the event editor */ +static void +event_editor_destroy (GtkObject *object) +{ + EventEditor *ee; + EventEditorPrivate *priv; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_EVENT_EDITOR (object)); + + ee = EVENT_EDITOR (object); + priv = ee->priv; + + if (GTK_OBJECT_CLASS (parent_class)->destroy) + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + +/** + * event_editor_new: + * + * Creates a new event editor dialog. + * + * Return value: A newly-created event editor dialog, or NULL if the event + * editor could not be created. + **/ +EventEditor * +event_editor_new (void) +{ + return EVENT_EDITOR (gtk_type_new (TYPE_EVENT_EDITOR)); +} diff --git a/calendar/gui/dialogs/event-editor.h b/calendar/gui/dialogs/event-editor.h new file mode 100644 index 0000000000..6f05b1cf46 --- /dev/null +++ b/calendar/gui/dialogs/event-editor.h @@ -0,0 +1,62 @@ +/* Evolution calendar - Event editor dialog + * + * Copyright (C) 2000 Helix Code, Inc. + * Copyright (C) 2001 Ximian, Inc. + * + * Authors: Miguel de Icaza + * Federico Mena-Quintero + * Seth Alves + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __EVENT_EDITOR_H__ +#define __EVENT_EDITOR_H__ + +#include +#include +#include "comp-editor.h" + + + +#define TYPE_EVENT_EDITOR (event_editor_get_type ()) +#define EVENT_EDITOR(obj) (GTK_CHECK_CAST ((obj), TYPE_EVENT_EDITOR, EventEditor)) +#define EVENT_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_EVENT_EDITOR, EventEditorClass)) +#define IS_EVENT_EDITOR(obj) (GTK_CHECK_TYPE ((obj), TYPE_EVENT_EDITOR)) +#define IS_EVENT_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), TYPE_EVENT_EDITOR)) + +typedef struct _EventEditor EventEditor; +typedef struct _EventEditorClass EventEditorClass; +typedef struct _EventEditorPrivate EventEditorPrivate; + +struct _EventEditor { + CompEditor parent; + + /* Private data */ + EventEditorPrivate *priv; +}; + +struct _EventEditorClass { + CompEditorClass parent_class; +}; + +GtkType event_editor_get_type (void); +EventEditor *event_editor_construct (EventEditor *ee); +EventEditor *event_editor_new (void); +void event_editor_update_widgets (EventEditor *ee); + + + +#endif /* __EVENT_EDITOR_H__ */ diff --git a/calendar/gui/dialogs/event-page.c b/calendar/gui/dialogs/event-page.c index 940ccf815c..8ade431f36 100644 --- a/calendar/gui/dialogs/event-page.c +++ b/calendar/gui/dialogs/event-page.c @@ -31,9 +31,10 @@ #include #include #include -#include "cal-util/timeutil.h" #include "e-util/e-dialog-widgets.h" #include "widgets/misc/e-dateedit.h" +#include "cal-util/timeutil.h" +#include "../widget-util.h" #include "../calendar-config.h" #include "event-page.h" @@ -65,6 +66,8 @@ struct _EventPagePrivate { GtkWidget *categories_btn; GtkWidget *categories; + + gboolean updating; }; @@ -73,22 +76,15 @@ static void event_page_class_init (EventPageClass *class); static void event_page_init (EventPage *epage); static void event_page_destroy (GtkObject *object); -static GtkWidget *event_page_get_widget (EditorPage *page); -static void event_page_fill_widgets (EditorPage *page, CalComponent *comp); -static void event_page_fill_component (EditorPage *page, CalComponent *comp); -static void event_page_set_summary (EditorPage *page, const char *summary); -static char *event_page_get_summary (EditorPage *page); -static void event_page_set_dates (EditorPage *page, time_t start, time_t end); - -/* Signal IDs */ -enum { - DATES_CHANGED, - LAST_SIGNAL -}; +static GtkWidget *event_page_get_widget (CompEditorPage *page); +static void event_page_fill_widgets (CompEditorPage *page, CalComponent *comp); +static void event_page_fill_component (CompEditorPage *page, CalComponent *comp); +static void event_page_set_summary (CompEditorPage *page, const char *summary); +static void event_page_set_dates (CompEditorPage *page, CompEditorPageDates *dates); -static guint event_page_signals[LAST_SIGNAL] = { 0 }; +GtkWidget *make_date_edit (void); -static EditorPageClass *parent_class = NULL; +static CompEditorPageClass *parent_class = NULL; @@ -117,7 +113,8 @@ event_page_get_type (void) (GtkClassInitFunc) NULL }; - event_page_type = gtk_type_unique (TYPE_EDITOR_PAGE, &event_page_info); + event_page_type = gtk_type_unique (TYPE_COMP_EDITOR_PAGE, + &event_page_info); } return event_page_type; @@ -127,31 +124,18 @@ event_page_get_type (void) static void event_page_class_init (EventPageClass *class) { - EditorPageClass *editor_page_class; + CompEditorPageClass *editor_page_class; GtkObjectClass *object_class; - editor_page_class = (EditorPageClass *) class; + editor_page_class = (CompEditorPageClass *) class; object_class = (GtkObjectClass *) class; - parent_class = gtk_type_class (TYPE_EDITOR_PAGE); - - event_page_signals[DATES_CHANGED] = - gtk_signal_new ("dates_changed", - GTK_RUN_FIRST, - object_class->type, - GTK_SIGNAL_OFFSET (EventPageClass, dates_changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - gtk_object_class_add_signals (object_class, event_page_signals, LAST_SIGNAL); - - class->dates_changed = NULL; + parent_class = gtk_type_class (TYPE_COMP_EDITOR_PAGE); editor_page_class->get_widget = event_page_get_widget; editor_page_class->fill_widgets = event_page_fill_widgets; editor_page_class->fill_component = event_page_fill_component; editor_page_class->set_summary = event_page_set_summary; - editor_page_class->get_summary = event_page_get_summary; editor_page_class->set_dates = event_page_set_dates; object_class->destroy = event_page_destroy; @@ -181,6 +165,8 @@ event_page_init (EventPage *epage) priv->contacts = NULL; priv->categories_btn = NULL; priv->categories = NULL; + + priv->updating = FALSE; } /* Destroy handler for the event page */ @@ -219,7 +205,7 @@ static const int classification_map[] = { /* get_widget handler for the event page */ static GtkWidget * -event_page_get_widget (EditorPage *page) +event_page_get_widget (CompEditorPage *page) { EventPage *epage; EventPagePrivate *priv; @@ -230,8 +216,8 @@ event_page_get_widget (EditorPage *page) return priv->main; } -/* Checks if the event's time starts and ends at midnight, and sets the "all day - * event" box accordingly. +/* Checks if the event's time starts and ends at midnight, and sets the + *"all day event" box accordingly. */ static void check_all_day (EventPage *epage) @@ -251,12 +237,15 @@ check_all_day (EventPage *epage) g_assert (ev_end != -1); /* all day event checkbox */ - if (time_day_begin (ev_start) == ev_start && time_day_begin (ev_end) == ev_end) + if (time_day_begin (ev_start) == ev_start + && time_day_begin (ev_end) == ev_end) all_day = TRUE; - gtk_signal_handler_block_by_data (GTK_OBJECT (priv->all_day_event), epage); + 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); + gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->all_day_event), + epage); 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); @@ -278,14 +267,17 @@ clear_widgets (EventPage *epage) e_dialog_editable_set (priv->description, NULL); /* Start and end times */ - gtk_signal_handler_block_by_data (GTK_OBJECT (priv->start_time), epage); + 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_time (E_DATE_EDIT (priv->start_time), now); e_date_edit_set_time (E_DATE_EDIT (priv->end_time), now); - gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time), epage); - gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time), epage); + gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time), + epage); + gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time), + epage); check_all_day (epage); @@ -299,7 +291,7 @@ clear_widgets (EventPage *epage) /* fill_widgets handler for the event page */ static void -event_page_fill_widgets (EditorPage *page, CalComponent *comp) +event_page_fill_widgets (CompEditorPage *page, CalComponent *comp) { EventPage *epage; EventPagePrivate *priv; @@ -313,6 +305,10 @@ event_page_fill_widgets (EditorPage *page, CalComponent *comp) epage = EVENT_PAGE (page); priv = epage->priv; + /* Don't send off changes during this time */ + priv->updating = TRUE; + + /* Clean the page */ clear_widgets (epage); /* Summary, description(s) */ @@ -341,17 +337,21 @@ event_page_fill_widgets (EditorPage *page, CalComponent *comp) dtend = icaltime_as_timet (*d.value); cal_component_free_datetime (&d); - if (time_day_begin (dtstart) == dtstart && time_day_begin (dtend) == dtend) + if (time_day_begin (dtstart) == dtstart + && time_day_begin (dtend) == dtend) dtend = time_add_day (dtend, -1); - gtk_signal_handler_block_by_data (GTK_OBJECT (priv->start_time), epage); + 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_time (E_DATE_EDIT (priv->start_time), dtstart); e_date_edit_set_time (E_DATE_EDIT (priv->end_time), dtend); - gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time), epage); - gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time), epage); + gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time), + epage); + gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time), + epage); check_all_day (epage); @@ -361,17 +361,20 @@ event_page_fill_widgets (EditorPage *page, CalComponent *comp) switch (cl) { case CAL_COMPONENT_CLASS_PUBLIC: - e_dialog_radio_set (priv->classification_public, CAL_COMPONENT_CLASS_PUBLIC, + e_dialog_radio_set (priv->classification_public, + CAL_COMPONENT_CLASS_PUBLIC, classification_map); break; case CAL_COMPONENT_CLASS_PRIVATE: - e_dialog_radio_set (priv->classification_public, CAL_COMPONENT_CLASS_PRIVATE, + e_dialog_radio_set (priv->classification_public, + CAL_COMPONENT_CLASS_PRIVATE, classification_map); break; case CAL_COMPONENT_CLASS_CONFIDENTIAL: - e_dialog_radio_set (priv->classification_public, CAL_COMPONENT_CLASS_CONFIDENTIAL, + e_dialog_radio_set (priv->classification_public, + CAL_COMPONENT_CLASS_CONFIDENTIAL, classification_map); break; @@ -382,14 +385,15 @@ event_page_fill_widgets (EditorPage *page, CalComponent *comp) } /* Categories */ - cal_component_get_categories (comp, &categories); e_dialog_editable_set (priv->categories, categories); + + priv->updating = FALSE; } /* fill_component handler for the event page */ static void -event_page_fill_component (EditorPage *page, CalComponent *comp) +event_page_fill_component (CompEditorPage *page, CalComponent *comp) { EventPage *epage; EventPagePrivate *priv; @@ -477,13 +481,14 @@ event_page_fill_component (EditorPage *page, CalComponent *comp) /* Classification */ - classif = e_dialog_radio_get (priv->classification_public, classification_map); + classif = e_dialog_radio_get (priv->classification_public, + classification_map); cal_component_set_classification (comp, classif); } /* set_summary handler for the event page */ static void -event_page_set_summary (EditorPage *page, const char *summary) +event_page_set_summary (CompEditorPage *page, const char *summary) { EventPage *epage; EventPagePrivate *priv; @@ -496,24 +501,8 @@ event_page_set_summary (EditorPage *page, const char *summary) gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->summary), epage); } -/* get_summary handler for the event page */ -static char * -event_page_get_summary (EditorPage *page) -{ - EventPage *epage; - EventPagePrivate *priv; - - epage = EVENT_PAGE (page); - priv = epage->priv; - - return e_utf8_gtk_entry_get_text (GTK_ENTRY (priv->summary)); -} - -/* set_dates handler for the event page. We do nothing since we are *the* - * only provider of the date values. - */ static void -event_page_set_dates (EditorPage *page, time_t start, time_t end) +event_page_set_dates (CompEditorPage *page, CompEditorPageDates *dates) { /* nothing */ } @@ -525,22 +514,17 @@ static gboolean get_widgets (EventPage *epage) { EventPagePrivate *priv; - GtkWidget *toplevel; priv = epage->priv; #define GW(name) glade_xml_get_widget (priv->xml, name) - toplevel = GW ("event-toplevel"); priv->main = GW ("event-page"); - if (!(toplevel && priv->main)) - return FALSE; - + g_assert (priv->main); gtk_widget_ref (priv->main); gtk_widget_unparent (priv->main); - gtk_widget_destroy (toplevel); - priv->summary = GW ("summary"); + priv->summary = GW ("general-summary"); priv->start_time = GW ("start-time"); priv->end_time = GW ("end-time"); @@ -579,9 +563,19 @@ static void summary_changed_cb (GtkEditable *editable, gpointer data) { EventPage *epage; + EventPagePrivate *priv; + gchar *summary; epage = EVENT_PAGE (data); - editor_page_notify_summary_changed (EDITOR_PAGE (epage)); + priv = epage->priv; + + if (priv->updating) + return; + + summary = gtk_editable_get_chars (editable, 0, -1); + comp_editor_page_notify_summary_changed (COMP_EDITOR_PAGE (epage), + summary); + g_free (summary); } /* Callback used when the start or end date widgets change. We check that the @@ -594,12 +588,15 @@ date_changed_cb (EDateEdit *dedit, gpointer data) EventPagePrivate *priv; time_t start, end; struct tm tm_start, tm_end; - + CompEditorPageDates dates; + epage = EVENT_PAGE (data); priv = epage->priv; - /* Ensure that start < end */ + if (priv->updating) + return; + /* Ensure that start < end */ start = e_date_edit_get_time (E_DATE_EDIT (priv->start_time)); g_assert (start != -1); end = e_date_edit_get_time (E_DATE_EDIT (priv->end_time)); @@ -611,10 +608,10 @@ date_changed_cb (EDateEdit *dedit, gpointer data) if (start == end && tm_start.tm_hour == 0 && tm_start.tm_min == 0 && tm_start.tm_sec == 0) { - /* If the start and end times are the same, but both are - * on day boundaries, then that is OK since it means we - * have an all-day event lasting 1 day. So we do - * nothing here. + /* If the start and end times are the same, but both + * are on day boundaries, then that is OK since it + * means we have an all-day event lasting 1 day. So + * we do nothing here. */ } else if (GTK_WIDGET (dedit) == priv->start_time) { /* Modify the end time */ @@ -627,7 +624,8 @@ date_changed_cb (EDateEdit *dedit, gpointer data) tm_end.tm_sec = tm_start.tm_sec; gtk_signal_handler_block_by_data (GTK_OBJECT (priv->end_time), epage); - e_date_edit_set_time (E_DATE_EDIT (priv->end_time), mktime (&tm_end)); + end = mktime (&tm_end); + e_date_edit_set_time (E_DATE_EDIT (priv->end_time), end); gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time), epage); } else if (GTK_WIDGET (dedit) == priv->end_time) { /* Modify the start time */ @@ -640,7 +638,8 @@ date_changed_cb (EDateEdit *dedit, gpointer data) tm_start.tm_sec = tm_end.tm_sec; gtk_signal_handler_block_by_data (GTK_OBJECT (priv->start_time), epage); - e_date_edit_set_time (E_DATE_EDIT (priv->start_time), mktime (&tm_start)); + start = mktime (&tm_start); + e_date_edit_set_time (E_DATE_EDIT (priv->start_time), start); gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time), epage); } else g_assert_not_reached (); @@ -650,7 +649,12 @@ date_changed_cb (EDateEdit *dedit, gpointer data) check_all_day (epage); /* Notify upstream */ - gtk_signal_emit (GTK_OBJECT (epage), event_page_signals[DATES_CHANGED]); + dates.start = start; + dates.end = end; + dates.due = 0; + dates.complete = 0; + comp_editor_page_notify_dates_changed (COMP_EDITOR_PAGE (epage), + &dates); } /* Callback: all day event button toggled. @@ -666,19 +670,21 @@ all_day_event_toggled_cb (GtkWidget *toggle, gpointer data) struct tm start_tm, end_tm; time_t start_t, end_t; gboolean all_day; - + CompEditorPageDates dates; + 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 do not round it down to the previous - * day, since if we do that and the user repeatedly turns the all_day - * toggle on and off, the event keeps shrinking. (We'd also need to - * make sure we didn't adjust the time when the radio button is - * initially set.) + /* 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 do not round it down to the previous + * day, since if we do that and the user repeatedly turns the + * all_day toggle on and off, the event keeps shrinking. + * (We'd also need to make sure we didn't adjust the time when + * the radio button is initially set.) * * When the all_day_toggle is turned off, we set the event start to the * start of the working day, and if the event end is on or before the @@ -737,20 +743,30 @@ all_day_event_toggled_cb (GtkWidget *toggle, gpointer data) } } - gtk_signal_handler_block_by_data (GTK_OBJECT (priv->start_time), epage); - gtk_signal_handler_block_by_data (GTK_OBJECT (priv->end_time), epage); + 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_time (E_DATE_EDIT (priv->start_time), mktime (&start_tm)); - e_date_edit_set_time (E_DATE_EDIT (priv->end_time), mktime (&end_tm)); + start_t = mktime (&start_tm); + end_t = mktime (&end_tm); + e_date_edit_set_time (E_DATE_EDIT (priv->start_time), start_t); + e_date_edit_set_time (E_DATE_EDIT (priv->end_time), end_t); - gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time), epage); - gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time), epage); + gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time), + epage); + gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time), + epage); 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); /* Notify upstream */ - gtk_signal_emit (GTK_OBJECT (epage), event_page_signals[DATES_CHANGED]); + dates.start = start_t; + dates.end = end_t; + dates.due = 0; + comp_editor_page_notify_dates_changed (COMP_EDITOR_PAGE (epage), + &dates); } /* Callback used when the categories button is clicked; we must bring up the @@ -792,9 +808,13 @@ static void field_changed_cb (GtkWidget *widget, gpointer data) { EventPage *epage; - + EventPagePrivate *priv; + epage = EVENT_PAGE (data); - editor_page_notify_changed (EDITOR_PAGE (epage)); + priv = epage->priv; + + if (!priv->updating) + comp_editor_page_notify_changed (COMP_EDITOR_PAGE (epage)); } /* Hooks the widget signals */ @@ -836,12 +856,15 @@ init_widgets (EventPage *epage) GTK_SIGNAL_FUNC (field_changed_cb), epage); gtk_signal_connect (GTK_OBJECT (priv->description), "changed", GTK_SIGNAL_FUNC (field_changed_cb), epage); - gtk_signal_connect (GTK_OBJECT (priv->classification_public), "toggled", - GTK_SIGNAL_FUNC (field_changed_cb), epage); - gtk_signal_connect (GTK_OBJECT (priv->classification_private), "toggled", - GTK_SIGNAL_FUNC (field_changed_cb), epage); - gtk_signal_connect (GTK_OBJECT (priv->classification_confidential), "toggled", - GTK_SIGNAL_FUNC (field_changed_cb), epage); + gtk_signal_connect (GTK_OBJECT (priv->classification_public), + "toggled", GTK_SIGNAL_FUNC (field_changed_cb), + epage); + gtk_signal_connect (GTK_OBJECT (priv->classification_private), + "toggled", GTK_SIGNAL_FUNC (field_changed_cb), + epage); + gtk_signal_connect (GTK_OBJECT (priv->classification_confidential), + "toggled", GTK_SIGNAL_FUNC (field_changed_cb), + epage); gtk_signal_connect (GTK_OBJECT (priv->categories), "changed", GTK_SIGNAL_FUNC (field_changed_cb), epage); @@ -869,14 +892,17 @@ event_page_construct (EventPage *epage) priv = epage->priv; - priv->xml = glade_xml_new (EVOLUTION_GLADEDIR "/event-page.glade", NULL); + priv->xml = glade_xml_new (EVOLUTION_GLADEDIR "/event-page.glade", + NULL); if (!priv->xml) { - g_message ("event_page_construct(): Could not load the Glade XML file!"); + g_message ("event_page_construct(): " + "Could not load the Glade XML file!"); return NULL; } if (!get_widgets (epage)) { - g_message ("event_page_construct(): Could not find all widgets in the XML file!"); + g_message ("event_page_construct(): " + "Could not find all widgets in the XML file!"); return NULL; } @@ -907,27 +933,8 @@ event_page_new (void) return epage; } -/** - * event_page_get_dates: - * @page: An event page. - * @start: Return value for the start date, can be NULL. - * @end: Return value for the end date, can be NULL. - * - * Queries the start and end dates for the calendar component in an event page. - **/ -void -event_page_get_dates (EventPage *page, time_t *start, time_t *end) +GtkWidget * +make_date_edit (void) { - EventPagePrivate *priv; - - g_return_if_fail (page != NULL); - g_return_if_fail (IS_EVENT_PAGE (page)); - - priv = page->priv; - - if (start) - *start = e_date_edit_get_time (E_DATE_EDIT (priv->start_time)); - - if (end) - *end = e_date_edit_get_time (E_DATE_EDIT (priv->end_time)); + return date_edit_new (TRUE, TRUE); } diff --git a/calendar/gui/dialogs/event-page.glade b/calendar/gui/dialogs/event-page.glade index 76d2d4043e..e9b774fe41 100644 --- a/calendar/gui/dialogs/event-page.glade +++ b/calendar/gui/dialogs/event-page.glade @@ -18,6 +18,7 @@ GtkWindow event-toplevel + False window1 GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE @@ -349,7 +350,6 @@ GtkButton contacts-button True - GTK_RELIEF_NORMAL 0 False @@ -388,7 +388,6 @@ GtkButton categories-button True - GTK_RELIEF_NORMAL 0 False diff --git a/calendar/gui/dialogs/event-page.h b/calendar/gui/dialogs/event-page.h index 04b01a0333..232455e491 100644 --- a/calendar/gui/dialogs/event-page.h +++ b/calendar/gui/dialogs/event-page.h @@ -25,7 +25,7 @@ #ifndef EVENT_PAGE_H #define EVENT_PAGE_H -#include "editor-page.h" +#include "comp-editor-page.h" BEGIN_GNOME_DECLS @@ -33,35 +33,27 @@ BEGIN_GNOME_DECLS #define TYPE_EVENT_PAGE (event_page_get_type ()) #define EVENT_PAGE(obj) (GTK_CHECK_CAST ((obj), TYPE_EVENT_PAGE, EventPage)) -#define EVENT_PAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_EVENT_PAGE, \ - EventPageClass)) +#define EVENT_PAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_EVENT_PAGE, EventPageClass)) #define IS_EVENT_PAGE(obj) (GTK_CHECK_TYPE ((obj), TYPE_EVENT_PAGE)) #define IS_EVENT_PAGE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), TYPE_EVENT_PAGE)) typedef struct _EventPagePrivate EventPagePrivate; typedef struct { - EditorPage page; + CompEditorPage page; /* Private data */ EventPagePrivate *priv; } EventPage; typedef struct { - EditorPageClass parent_class; - - /* Notification signals */ - - void (* dates_changed) (EventPage *epage); + CompEditorPageClass parent_class; } EventPageClass; -GtkType event_page_get_type (void); +GtkType event_page_get_type (void); EventPage *event_page_construct (EventPage *epage); - -EventPage *event_page_new (void); - -void event_page_get_dates (EventPage *epage, time_t *start, time_t *end); +EventPage *event_page_new (void); diff --git a/calendar/gui/dialogs/recurrence-page.c b/calendar/gui/dialogs/recurrence-page.c index 363ca94cc5..4d690be6dc 100644 --- a/calendar/gui/dialogs/recurrence-page.c +++ b/calendar/gui/dialogs/recurrence-page.c @@ -39,6 +39,7 @@ #include "../tag-calendar.h" #include "../weekday-picker.h" #include "../widget-util.h" +#include "comp-editor-util.h" #include "recurrence-page.h" @@ -102,6 +103,9 @@ static const int ending_types_map[] = { /* Private part of the RecurrencePage structure */ struct _RecurrencePagePrivate { + /* Component we use to expand the recurrence rules for the preview */ + CalComponent *comp; + /* Glade XML data */ GladeXML *xml; @@ -110,7 +114,7 @@ struct _RecurrencePagePrivate { GtkWidget *main; GtkWidget *summary; - GtkWidget *starting_date; + GtkWidget *date_time; GtkWidget *none; GtkWidget *simple; @@ -157,8 +161,7 @@ struct _RecurrencePagePrivate { /* For the recurrence preview, the actual widget */ GtkWidget *preview_calendar; - /* Component we use to expand the recurrence rules for the preview calendar */ - CalComponent *comp; + gboolean updating; }; @@ -167,14 +170,15 @@ static void recurrence_page_class_init (RecurrencePageClass *class); static void recurrence_page_init (RecurrencePage *rpage); static void recurrence_page_destroy (GtkObject *object); -static GtkWidget *recurrence_page_get_widget (EditorPage *page); -static void recurrence_page_fill_widgets (EditorPage *page, CalComponent *comp); -static void recurrence_page_fill_component (EditorPage *page, CalComponent *comp); -static void recurrence_page_set_summary (EditorPage *page, const char *summary); -static char *recurrence_page_get_summary (EditorPage *page); -static void recurrence_page_set_dates (EditorPage *page, time_t start, time_t end); +static GtkWidget *recurrence_page_get_widget (CompEditorPage *page); +static void recurrence_page_fill_widgets (CompEditorPage *page, CalComponent *comp); +static void recurrence_page_fill_component (CompEditorPage *page, CalComponent *comp); +static void recurrence_page_set_summary (CompEditorPage *page, const char *summary); +static void recurrence_page_set_dates (CompEditorPage *page, CompEditorPageDates *dates); -static EditorPageClass *parent_class = NULL; +static void field_changed (RecurrencePage *apage); + +static CompEditorPageClass *parent_class = NULL; @@ -203,7 +207,8 @@ recurrence_page_get_type (void) (GtkClassInitFunc) NULL }; - recurrence_page_type = gtk_type_unique (TYPE_EDITOR_PAGE, &recurrence_page_info); + recurrence_page_type = gtk_type_unique (TYPE_COMP_EDITOR_PAGE, + &recurrence_page_info); } return recurrence_page_type; @@ -213,19 +218,18 @@ recurrence_page_get_type (void) static void recurrence_page_class_init (RecurrencePageClass *class) { - EditorPageClass *editor_page_class; + CompEditorPageClass *editor_page_class; GtkObjectClass *object_class; - editor_page_class = (EditorPageClass *) class; + editor_page_class = (CompEditorPageClass *) class; object_class = (GtkObjectClass *) class; - parent_class = gtk_type_class (TYPE_EDITOR_PAGE); + parent_class = gtk_type_class (TYPE_COMP_EDITOR_PAGE); editor_page_class->get_widget = recurrence_page_get_widget; editor_page_class->fill_widgets = recurrence_page_fill_widgets; editor_page_class->fill_component = recurrence_page_fill_component; editor_page_class->set_summary = recurrence_page_set_summary; - editor_page_class->get_summary = recurrence_page_get_summary; editor_page_class->set_dates = recurrence_page_set_dates; object_class->destroy = recurrence_page_destroy; @@ -244,7 +248,7 @@ recurrence_page_init (RecurrencePage *rpage) priv->main = NULL; priv->summary = NULL; - priv->starting_date = NULL; + priv->date_time = NULL; priv->none = NULL; priv->simple = NULL; priv->custom = NULL; @@ -276,22 +280,23 @@ static void free_exception_clist_data (RecurrencePage *rpage) { RecurrencePagePrivate *priv; - GtkCList *clist; int i; priv = rpage->priv; - clist = GTK_CLIST (priv->exception_list); - - for (i = 0; i < clist->rows; i++) { - gpointer data; + if (priv->exception_list) { + GtkCList *clist = GTK_CLIST (priv->exception_list); - data = gtk_clist_get_row_data (clist, i); - g_free (data); - gtk_clist_set_row_data (clist, i, NULL); + for (i = 0; i < clist->rows; i++) { + gpointer data; + + data = gtk_clist_get_row_data (clist, i); + g_free (data); + gtk_clist_set_row_data (clist, i, NULL); + } + + gtk_clist_clear (clist); } - - gtk_clist_clear (clist); } /* Destroy handler for the recurrence page */ @@ -325,7 +330,7 @@ recurrence_page_destroy (GtkObject *object) /* get_widget handler for the recurrence page */ static GtkWidget * -recurrence_page_get_widget (EditorPage *page) +recurrence_page_get_widget (CompEditorPage *page) { RecurrencePage *rpage; RecurrencePagePrivate *priv; @@ -366,7 +371,9 @@ clear_widgets (RecurrencePage *rpage) menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (priv->interval_unit)); gtk_signal_handler_block_by_data (GTK_OBJECT (menu), rpage); - e_dialog_option_menu_set (priv->interval_unit, ICAL_DAILY_RECURRENCE, freq_map); + e_dialog_option_menu_set (priv->interval_unit, + ICAL_DAILY_RECURRENCE, + freq_map); gtk_signal_handler_unblock_by_data (GTK_OBJECT (menu), rpage); priv->ending_date = time (NULL); @@ -374,7 +381,9 @@ clear_widgets (RecurrencePage *rpage) menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (priv->ending_menu)); gtk_signal_handler_block_by_data (GTK_OBJECT (menu), rpage); - e_dialog_option_menu_set (priv->ending_menu, ENDING_FOREVER, ending_types_map); + e_dialog_option_menu_set (priv->ending_menu, + ENDING_FOREVER, + ending_types_map); gtk_signal_handler_unblock_by_data (GTK_OBJECT (menu), rpage); /* Exceptions list */ @@ -455,8 +464,8 @@ fill_exception_widgets (RecurrencePage *rpage, CalComponent *comp) gtk_clist_select_row (GTK_CLIST (priv->exception_list), 0, 0); } -/* Computes a weekday mask for the start day of a calendar component, for use in - * a WeekdayPicker widget. +/* Computes a weekday mask for the start day of a calendar component, + * for use in a WeekdayPicker widget. */ static guint8 get_start_weekday_mask (CalComponent *comp) @@ -533,9 +542,11 @@ sensitize_recur_widgets (RecurrencePage *rpage) gtk_widget_set_sensitive (priv->params, FALSE); gtk_widget_hide (priv->params); - label = gtk_label_new (_("This appointment contains recurrences that Evolution " + label = gtk_label_new (_("This appointment contains " + "recurrences that Evolution " "cannot edit.")); - gtk_container_add (GTK_CONTAINER (priv->custom_warning_bin), label); + gtk_container_add (GTK_CONTAINER (priv->custom_warning_bin), + label); gtk_widget_show_all (priv->custom_warning_bin); break; @@ -574,7 +585,8 @@ simple_recur_to_comp (RecurrencePage *rpage, CalComponent *comp) r.freq = e_dialog_option_menu_get (priv->interval_unit, freq_map); r.interval = e_dialog_spin_get_int (priv->interval_value); - r.week_start = ICAL_SUNDAY_WEEKDAY + calendar_config_get_week_start_day (); + r.week_start = ICAL_SUNDAY_WEEKDAY + + calendar_config_get_week_start_day (); /* Frequency-specific data */ @@ -639,31 +651,38 @@ simple_recur_to_comp (RecurrencePage *rpage, CalComponent *comp) break; case MONTH_DAY_MON: - r.by_day[0] = nth_weekday (day_index, ICAL_MONDAY_WEEKDAY); + r.by_day[0] = nth_weekday (day_index, + ICAL_MONDAY_WEEKDAY); break; case MONTH_DAY_TUE: - r.by_day[0] = nth_weekday (day_index, ICAL_TUESDAY_WEEKDAY); + r.by_day[0] = nth_weekday (day_index, + ICAL_TUESDAY_WEEKDAY); break; case MONTH_DAY_WED: - r.by_day[0] = nth_weekday (day_index, ICAL_WEDNESDAY_WEEKDAY); + r.by_day[0] = nth_weekday (day_index, + ICAL_WEDNESDAY_WEEKDAY); break; case MONTH_DAY_THU: - r.by_day[0] = nth_weekday (day_index, ICAL_THURSDAY_WEEKDAY); + r.by_day[0] = nth_weekday (day_index, + ICAL_THURSDAY_WEEKDAY); break; case MONTH_DAY_FRI: - r.by_day[0] = nth_weekday (day_index, ICAL_FRIDAY_WEEKDAY); + r.by_day[0] = nth_weekday (day_index, + ICAL_FRIDAY_WEEKDAY); break; case MONTH_DAY_SAT: - r.by_day[0] = nth_weekday (day_index, ICAL_SATURDAY_WEEKDAY); + r.by_day[0] = nth_weekday (day_index, + ICAL_SATURDAY_WEEKDAY); break; case MONTH_DAY_SUN: - r.by_day[0] = nth_weekday (day_index, ICAL_SUNDAY_WEEKDAY); + r.by_day[0] = nth_weekday (day_index, + ICAL_SUNDAY_WEEKDAY); break; default: @@ -683,7 +702,8 @@ simple_recur_to_comp (RecurrencePage *rpage, CalComponent *comp) /* Ending date */ - ending_type = e_dialog_option_menu_get (priv->ending_menu, ending_types_map); + ending_type = e_dialog_option_menu_get (priv->ending_menu, + ending_types_map); switch (ending_type) { case ENDING_FOR: @@ -842,7 +862,7 @@ weekday_picker_changed_cb (WeekdayPicker *wp, gpointer data) rpage = RECURRENCE_PAGE (data); - editor_page_notify_changed (EDITOR_PAGE (rpage)); + field_changed (rpage); preview_recur (rpage); } @@ -882,7 +902,8 @@ make_weekly_special (RecurrencePage *rpage) weekday_picker_set_blocked_days (wp, priv->weekday_blocked_day_mask); gtk_signal_connect (GTK_OBJECT (wp), "changed", - GTK_SIGNAL_FUNC (weekday_picker_changed_cb), rpage); + GTK_SIGNAL_FUNC (weekday_picker_changed_cb), + rpage); } /* Creates the option menu for the monthly recurrence days */ @@ -938,7 +959,8 @@ adjust_day_index_spin (RecurrencePage *rpage) g_assert (priv->month_index_spin != NULL); g_assert (GTK_IS_SPIN_BUTTON (priv->month_index_spin)); - month_day = e_dialog_option_menu_get (priv->month_day_menu, month_day_options_map); + month_day = e_dialog_option_menu_get (priv->month_day_menu, + month_day_options_map); adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->month_index_spin)); @@ -970,9 +992,9 @@ adjust_day_index_spin (RecurrencePage *rpage) } } -/* Callback used when the monthly day selection menu changes. We need to change - * the valid range of the day index spin button; e.g. days are 1-31 while a - * Sunday is the 1st through 5th. +/* Callback used when the monthly day selection menu changes. We need + * to change the valid range of the day index spin button; e.g. days + * are 1-31 while a Sunday is the 1st through 5th. */ static void month_day_menu_selection_done_cb (GtkMenuShell *menu_shell, gpointer data) @@ -982,7 +1004,7 @@ month_day_menu_selection_done_cb (GtkMenuShell *menu_shell, gpointer data) rpage = RECURRENCE_PAGE (data); adjust_day_index_spin (rpage); - editor_page_notify_changed (EDITOR_PAGE (rpage)); + field_changed (rpage); preview_recur (rpage); } @@ -994,7 +1016,7 @@ month_index_value_changed_cb (GtkAdjustment *adj, gpointer data) rpage = RECURRENCE_PAGE (data); - editor_page_notify_changed (EDITOR_PAGE (rpage)); + field_changed (rpage); preview_recur (rpage); } @@ -1024,13 +1046,15 @@ make_monthly_special (RecurrencePage *rpage) adj = GTK_ADJUSTMENT (gtk_adjustment_new (1, 1, 31, 1, 10, 10)); priv->month_index_spin = gtk_spin_button_new (adj, 1, 0); - gtk_box_pack_start (GTK_BOX (hbox), priv->month_index_spin, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), priv->month_index_spin, + FALSE, FALSE, 0); label = gtk_label_new (_("th")); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); priv->month_day_menu = make_recur_month_menu (); - gtk_box_pack_start (GTK_BOX (hbox), priv->month_day_menu, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), priv->month_day_menu, + FALSE, FALSE, 0); gtk_widget_show_all (hbox); @@ -1043,11 +1067,13 @@ make_monthly_special (RecurrencePage *rpage) adjust_day_index_spin (rpage); gtk_signal_connect (GTK_OBJECT (adj), "value_changed", - GTK_SIGNAL_FUNC (month_index_value_changed_cb), rpage); + GTK_SIGNAL_FUNC (month_index_value_changed_cb), + rpage); menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (priv->month_day_menu)); gtk_signal_connect (GTK_OBJECT (menu), "selection_done", - GTK_SIGNAL_FUNC (month_day_menu_selection_done_cb), rpage); + GTK_SIGNAL_FUNC (month_day_menu_selection_done_cb), + rpage); } /* Changes the recurrence-special widget to match the interval units. @@ -1099,7 +1125,7 @@ make_recurrence_special (RecurrencePage *rpage) } } -/* Counts the number of elements in the by_xxx fields of an icalrecurrencetype */ +/* Counts the elements in the by_xxx fields of an icalrecurrencetype */ static int count_by_xxx (short *field, int max_elements) { @@ -1119,7 +1145,7 @@ ending_until_changed_cb (EDateEdit *de, gpointer data) RecurrencePage *rpage; rpage = RECURRENCE_PAGE (data); - editor_page_notify_changed (EDITOR_PAGE (rpage)); + field_changed (rpage); preview_recur (rpage); } @@ -1140,7 +1166,8 @@ make_ending_until_special (RecurrencePage *rpage) priv->ending_date_edit = date_edit_new (TRUE, FALSE); de = E_DATE_EDIT (priv->ending_date_edit); - gtk_container_add (GTK_CONTAINER (priv->ending_special), GTK_WIDGET (de)); + gtk_container_add (GTK_CONTAINER (priv->ending_special), + GTK_WIDGET (de)); gtk_widget_show_all (GTK_WIDGET (de)); /* Set the value */ @@ -1158,7 +1185,7 @@ ending_count_value_changed_cb (GtkAdjustment *adj, gpointer data) RecurrencePage *rpage; rpage = RECURRENCE_PAGE (data); - editor_page_notify_changed (EDITOR_PAGE (rpage)); + field_changed (rpage); preview_recur (rpage); } @@ -1183,7 +1210,8 @@ make_ending_count_special (RecurrencePage *rpage) adj = GTK_ADJUSTMENT (gtk_adjustment_new (1, 1, 10000, 1, 10, 10)); priv->ending_count_spin = gtk_spin_button_new (adj, 1, 0); - gtk_box_pack_start (GTK_BOX (hbox), priv->ending_count_spin, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), priv->ending_count_spin, + FALSE, FALSE, 0); label = gtk_label_new (_("occurrences")); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); @@ -1195,10 +1223,11 @@ make_ending_count_special (RecurrencePage *rpage) e_dialog_spin_set (priv->ending_count_spin, priv->ending_count); gtk_signal_connect (GTK_OBJECT (adj), "value_changed", - GTK_SIGNAL_FUNC (ending_count_value_changed_cb), rpage); + GTK_SIGNAL_FUNC (ending_count_value_changed_cb), + rpage); } -/* Changes the recurrence-ending-special widget to match the ending date option. +/* Changes the recurrence-ending-special widget to match the ending date option * * For: [days, weeks, months, years, occurrences] * Until: @@ -1219,7 +1248,8 @@ make_ending_special (RecurrencePage *rpage) priv->ending_count_spin = NULL; } - ending_type = e_dialog_option_menu_get (priv->ending_menu, ending_types_map); + ending_type = e_dialog_option_menu_get (priv->ending_menu, + ending_types_map); switch (ending_type) { case ENDING_FOR: @@ -1290,10 +1320,12 @@ fill_ending_date (RecurrencePage *rpage, struct icalrecurrencetype *r) * no rdates or exrules (exdates are handled just fine elsewhere). */ static void -recurrence_page_fill_widgets (EditorPage *page, CalComponent *comp) +recurrence_page_fill_widgets (CompEditorPage *page, CalComponent *comp) { RecurrencePage *rpage; RecurrencePagePrivate *priv; + CalComponentText text; + CompEditorPageDates dates; GSList *rrule_list; int len; struct icalrecurrencetype *r; @@ -1306,8 +1338,8 @@ recurrence_page_fill_widgets (EditorPage *page, CalComponent *comp) rpage = RECURRENCE_PAGE (page); priv = rpage->priv; - /* Keep a copy of the component so that we can expand the recurrence set - * for the preview. + /* Keep a copy of the component so that we can expand the recurrence + * set for the preview. */ if (priv->comp) @@ -1315,10 +1347,21 @@ recurrence_page_fill_widgets (EditorPage *page, CalComponent *comp) priv->comp = cal_component_clone (comp); - /* Clean the page */ + /* Don't send off changes during this time */ + priv->updating = TRUE; + /* Clean the page */ clear_widgets (rpage); + /* Summary */ + cal_component_get_summary (comp, &text); + recurrence_page_set_summary (page, text.value); + + /* Dates */ + comp_editor_dates (&dates, comp); + recurrence_page_set_dates (page, &dates); + + /* Exceptions */ fill_exception_widgets (rpage, comp); /* Set up defaults for the special widgets */ @@ -1329,13 +1372,19 @@ recurrence_page_fill_widgets (EditorPage *page, CalComponent *comp) if (!cal_component_has_rdates (comp) && !cal_component_has_rrules (comp) && !cal_component_has_exrules (comp)) { - gtk_signal_handler_block_by_data (GTK_OBJECT (priv->none), rpage); - gtk_signal_handler_block_by_data (GTK_OBJECT (priv->simple), rpage); - gtk_signal_handler_block_by_data (GTK_OBJECT (priv->custom), rpage); + gtk_signal_handler_block_by_data (GTK_OBJECT (priv->none), + rpage); + gtk_signal_handler_block_by_data (GTK_OBJECT (priv->simple), + rpage); + gtk_signal_handler_block_by_data (GTK_OBJECT (priv->custom), + rpage); e_dialog_radio_set (priv->none, RECUR_NONE, type_map); - gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->none), rpage); - gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->simple), rpage); - gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->custom), rpage); + gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->none), + rpage); + gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->simple), + rpage); + gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->custom), + rpage); gtk_widget_set_sensitive (priv->custom, FALSE); @@ -1400,7 +1449,9 @@ recurrence_page_fill_widgets (EditorPage *page, CalComponent *comp) menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (priv->interval_unit)); gtk_signal_handler_block_by_data (GTK_OBJECT (menu), rpage); - e_dialog_option_menu_set (priv->interval_unit, ICAL_DAILY_RECURRENCE, freq_map); + e_dialog_option_menu_set (priv->interval_unit, + ICAL_DAILY_RECURRENCE, + freq_map); gtk_signal_handler_unblock_by_data (GTK_OBJECT (menu), rpage); break; @@ -1465,7 +1516,9 @@ recurrence_page_fill_widgets (EditorPage *page, CalComponent *comp) menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (priv->interval_unit)); gtk_signal_handler_block_by_data (GTK_OBJECT (menu), rpage); - e_dialog_option_menu_set (priv->interval_unit, ICAL_WEEKLY_RECURRENCE, freq_map); + e_dialog_option_menu_set (priv->interval_unit, + ICAL_WEEKLY_RECURRENCE, + freq_map); gtk_signal_handler_unblock_by_data (GTK_OBJECT (menu), rpage); break; } @@ -1537,7 +1590,9 @@ recurrence_page_fill_widgets (EditorPage *page, CalComponent *comp) menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (priv->interval_unit)); gtk_signal_handler_block_by_data (GTK_OBJECT (menu), rpage); - e_dialog_option_menu_set (priv->interval_unit, ICAL_MONTHLY_RECURRENCE, freq_map); + e_dialog_option_menu_set (priv->interval_unit, + ICAL_MONTHLY_RECURRENCE, + freq_map); gtk_signal_handler_unblock_by_data (GTK_OBJECT (menu), rpage); break; @@ -1552,7 +1607,9 @@ recurrence_page_fill_widgets (EditorPage *page, CalComponent *comp) menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (priv->interval_unit)); gtk_signal_handler_block_by_data (GTK_OBJECT (menu), rpage); - e_dialog_option_menu_set (priv->interval_unit, ICAL_YEARLY_RECURRENCE, freq_map); + e_dialog_option_menu_set (priv->interval_unit, + ICAL_YEARLY_RECURRENCE, + freq_map); gtk_signal_handler_unblock_by_data (GTK_OBJECT (menu), rpage); break; @@ -1601,11 +1658,13 @@ recurrence_page_fill_widgets (EditorPage *page, CalComponent *comp) cal_component_free_recur_list (rrule_list); preview_recur (rpage); + + priv->updating = FALSE; } /* fill_component handler for the recurrence page */ static void -recurrence_page_fill_component (EditorPage *page, CalComponent *comp) +recurrence_page_fill_component (CompEditorPage *page, CalComponent *comp) { RecurrencePage *rpage; @@ -1615,52 +1674,33 @@ recurrence_page_fill_component (EditorPage *page, CalComponent *comp) /* set_summary handler for the recurrence page */ static void -recurrence_page_set_summary (EditorPage *page, const char *summary) +recurrence_page_set_summary (CompEditorPage *page, const char *summary) { RecurrencePage *rpage; RecurrencePagePrivate *priv; - + gchar *s; + rpage = RECURRENCE_PAGE (page); priv = rpage->priv; - gtk_signal_handler_block_by_data (GTK_OBJECT (priv->summary), rpage); - e_utf8_gtk_entry_set_text (GTK_ENTRY (priv->summary), summary); - gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->summary), rpage); -} - -/* get_summary handler for the recurrence page */ -static char * -recurrence_page_get_summary (EditorPage *page) -{ - RecurrencePage *rpage; - RecurrencePagePrivate *priv; - - rpage = RECURRENCE_PAGE (page); - priv = rpage->priv; - - return e_utf8_gtk_entry_get_text (GTK_ENTRY (priv->summary)); + s = e_utf8_to_gtk_string (priv->summary, summary); + gtk_label_set_text (GTK_LABEL (priv->summary), s); + g_free (s); } /* set_dates handler for the recurrence page */ static void -recurrence_page_set_dates (EditorPage *page, time_t start, time_t end) +recurrence_page_set_dates (CompEditorPage *page, CompEditorPageDates *dates) { RecurrencePage *rpage; RecurrencePagePrivate *priv; - char str[128]; - struct tm tm; CalComponentDateTime dt; struct icaltimetype icaltime; rpage = RECURRENCE_PAGE (page); priv = rpage->priv; - /* Set the starting date label */ - - tm = *localtime (&start); - strftime (str, sizeof (str), _("%A %b %d %Y %H:%M:%S"), &tm); - - gtk_label_set_text (GTK_LABEL (priv->starting_date), str); + comp_editor_date_label (dates, priv->date_time); /* Copy the dates to our component */ @@ -1670,11 +1710,13 @@ recurrence_page_set_dates (EditorPage *page, time_t start, time_t end) dt.value = &icaltime; dt.tzid = NULL; - *dt.value = icaltime_from_timet (start, FALSE); + *dt.value = icaltime_from_timet (dates->start, FALSE); cal_component_set_dtstart (priv->comp, &dt); - *dt.value = icaltime_from_timet (end, FALSE); - cal_component_set_dtend (priv->comp, &dt); + if (dates->end != 0) { + *dt.value = icaltime_from_timet (dates->end, FALSE); + cal_component_set_dtend (priv->comp, &dt); + } } @@ -1684,23 +1726,18 @@ static gboolean get_widgets (RecurrencePage *rpage) { RecurrencePagePrivate *priv; - GtkWidget *toplevel; priv = rpage->priv; #define GW(name) glade_xml_get_widget (priv->xml, name) - toplevel = GW ("recurrence-toplevel"); priv->main = GW ("recurrence-page"); - if (!(toplevel && priv->main)) - return FALSE; - + g_assert (priv->main); gtk_widget_ref (priv->main); gtk_widget_unparent (priv->main); - gtk_widget_destroy (toplevel); priv->summary = GW ("summary"); - priv->starting_date = GW ("starting-date"); + priv->date_time = GW ("date-time"); priv->none = GW ("none"); priv->simple = GW ("simple"); @@ -1723,9 +1760,9 @@ get_widgets (RecurrencePage *rpage) priv->preview_bin = GW ("preview-bin"); #undef GW - + return (priv->summary - && priv->starting_date + && priv->date_time && priv->none && priv->simple && priv->custom @@ -1744,16 +1781,6 @@ get_widgets (RecurrencePage *rpage) && priv->preview_bin); } -/* Callback used when the summary changes; we emit the notification signal. */ -static void -summary_changed_cb (GtkEditable *editable, gpointer data) -{ - RecurrencePage *rpage; - - rpage = RECURRENCE_PAGE (data); - editor_page_notify_summary_changed (EDITOR_PAGE (rpage)); -} - /* Callback used when the displayed date range in the recurrence preview * calendar changes. */ @@ -1776,7 +1803,7 @@ type_toggled_cb (GtkToggleButton *toggle, gpointer data) rpage = RECURRENCE_PAGE (data); - editor_page_notify_changed (EDITOR_PAGE (rpage)); + field_changed (rpage); if (toggle->active) { sensitize_recur_widgets (rpage); @@ -1792,7 +1819,7 @@ interval_value_changed_cb (GtkAdjustment *adj, gpointer data) rpage = RECURRENCE_PAGE (data); - editor_page_notify_changed (EDITOR_PAGE (rpage)); + field_changed (rpage); preview_recur (rpage); } @@ -1806,7 +1833,7 @@ interval_selection_done_cb (GtkMenuShell *menu_shell, gpointer data) rpage = RECURRENCE_PAGE (data); - editor_page_notify_changed (EDITOR_PAGE (rpage)); + field_changed (rpage); make_recurrence_special (rpage); preview_recur (rpage); } @@ -1821,7 +1848,7 @@ ending_selection_done_cb (GtkMenuShell *menu_shell, gpointer data) rpage = RECURRENCE_PAGE (data); - editor_page_notify_changed (EDITOR_PAGE (rpage)); + field_changed (rpage); make_ending_special (rpage); preview_recur (rpage); } @@ -1837,7 +1864,7 @@ exception_add_cb (GtkWidget *widget, gpointer data) rpage = RECURRENCE_PAGE (data); priv = rpage->priv; - editor_page_notify_changed (EDITOR_PAGE (rpage)); + field_changed (rpage); t = e_date_edit_get_time (E_DATE_EDIT (priv->exception_date)); append_exception (rpage, t); @@ -1861,7 +1888,7 @@ exception_modify_cb (GtkWidget *widget, gpointer data) if (!clist->selection) return; - editor_page_notify_changed (EDITOR_PAGE (rpage)); + field_changed (rpage); sel = GPOINTER_TO_INT (clist->selection->data); @@ -1890,7 +1917,7 @@ exception_delete_cb (GtkWidget *widget, gpointer data) if (!clist->selection) return; - editor_page_notify_changed (EDITOR_PAGE (rpage)); + field_changed (rpage); sel = GPOINTER_TO_INT (clist->selection->data); @@ -1912,11 +1939,13 @@ exception_delete_cb (GtkWidget *widget, gpointer data) preview_recur (rpage); } -/* Callback used when a row is selected in the list of exception dates. We must - * update the date/time widgets to reflect the exception's value. +/* Callback used when a row is selected in the list of exception + * dates. We must update the date/time widgets to reflect the + * exception's value. */ static void -exception_select_row_cb (GtkCList *clist, gint row, gint col, GdkEvent *event, gpointer data) +exception_select_row_cb (GtkCList *clist, gint row, gint col, + GdkEvent *event, gpointer data) { RecurrencePage *rpage; RecurrencePagePrivate *priv; @@ -1931,6 +1960,18 @@ exception_select_row_cb (GtkCList *clist, gint row, gint col, GdkEvent *event, g e_date_edit_set_time (E_DATE_EDIT (priv->exception_date), *t); } +/* This is called when any field is changed; it notifies upstream. */ +static void +field_changed (RecurrencePage *rpage) +{ + RecurrencePagePrivate *priv; + + priv = rpage->priv; + + if (!priv->updating) + comp_editor_page_notify_changed (COMP_EDITOR_PAGE (rpage)); +} + /* Hooks the widget signals */ static void init_widgets (RecurrencePage *rpage) @@ -1942,19 +1983,17 @@ init_widgets (RecurrencePage *rpage) priv = rpage->priv; - /* Summary */ - gtk_signal_connect (GTK_OBJECT (priv->summary), "changed", - GTK_SIGNAL_FUNC (summary_changed_cb), rpage); - /* Recurrence preview */ priv->preview_calendar = e_calendar_new (); ecal = E_CALENDAR (priv->preview_calendar); gtk_signal_connect (GTK_OBJECT (ecal->calitem), "date_range_changed", - GTK_SIGNAL_FUNC (preview_date_range_changed_cb), rpage); + GTK_SIGNAL_FUNC (preview_date_range_changed_cb), + rpage); calendar_config_configure_e_calendar (ecal); e_calendar_item_set_max_days_sel (ecal->calitem, 0); - gtk_container_add (GTK_CONTAINER (priv->preview_bin), priv->preview_calendar); + gtk_container_add (GTK_CONTAINER (priv->preview_bin), + priv->preview_calendar); gtk_widget_show (priv->preview_calendar); /* Recurrence types */ @@ -1970,13 +2009,15 @@ init_widgets (RecurrencePage *rpage) adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->interval_value)); gtk_signal_connect (GTK_OBJECT (adj), "value_changed", - GTK_SIGNAL_FUNC (interval_value_changed_cb), rpage); + GTK_SIGNAL_FUNC (interval_value_changed_cb), + rpage); /* Recurrence units */ menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (priv->interval_unit)); gtk_signal_connect (GTK_OBJECT (menu), "selection_done", - GTK_SIGNAL_FUNC (interval_selection_done_cb), rpage); + GTK_SIGNAL_FUNC (interval_selection_done_cb), + rpage); /* Recurrence ending */ @@ -2017,14 +2058,17 @@ recurrence_page_construct (RecurrencePage *rpage) priv = rpage->priv; - priv->xml = glade_xml_new (EVOLUTION_GLADEDIR "/recurrence-page.glade", NULL); + priv->xml = glade_xml_new (EVOLUTION_GLADEDIR + "/recurrence-page.glade", NULL); if (!priv->xml) { - g_message ("recurrence_page_construct(): Could not load the Glade XML file!"); + g_message ("recurrence_page_construct(): " + "Could not load the Glade XML file!"); return NULL; } if (!get_widgets (rpage)) { - g_message ("recurrence_page_construct(): Could not find all widgets in the XML file!"); + g_message ("recurrence_page_construct(): " + "Could not find all widgets in the XML file!"); return NULL; } diff --git a/calendar/gui/dialogs/recurrence-page.glade b/calendar/gui/dialogs/recurrence-page.glade index b84a3c288c..1793e175d7 100644 --- a/calendar/gui/dialogs/recurrence-page.glade +++ b/calendar/gui/dialogs/recurrence-page.glade @@ -18,6 +18,7 @@ GtkWindow recurrence-toplevel + False window1 GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE @@ -36,7 +37,7 @@ GtkFrame frame35 - + 0 GTK_SHADOW_ETCHED_IN @@ -58,14 +59,13 @@ GtkLabel label66 - + GTK_JUSTIFY_CENTER False 0 0.5 0 0 - recurrence-summary 0 1 @@ -85,7 +85,7 @@ GtkLabel label67 - + GTK_JUSTIFY_CENTER False 0 @@ -109,13 +109,15 @@ - GtkEntry - recurrence-summary - True - True - True - 0 - + GtkLabel + summary + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 4 + 0 1 2 @@ -123,9 +125,9 @@ 1 0 0 - True + False False - True + False False True False @@ -133,12 +135,15 @@ - GtkAlignment - alignment40 + GtkLabel + date-time + + GTK_JUSTIFY_CENTER + False 0 0.5 - 0 - 0 + 4 + 0 1 2 @@ -151,17 +156,8 @@ False False True - True + False - - - Custom - recurrence-starting-date - make_date_edit - 0 - 0 - Fri, 22 Sep 2000 20:51:38 GMT - @@ -209,7 +205,7 @@ GtkRadioButton - recurrence-none + none True False @@ -224,7 +220,7 @@ GtkRadioButton - recurrence-simple + simple True False @@ -239,7 +235,7 @@ GtkRadioButton - recurrence-custom + custom True False @@ -266,7 +262,7 @@ GtkHBox - recurrence-params + params False 2 @@ -294,7 +290,7 @@ GtkSpinButton - recurrence-interval-value + interval-value True 1 0 @@ -317,7 +313,7 @@ GtkOptionMenu - recurrence-interval-unit + interval-unit True day(s) week(s) @@ -334,7 +330,7 @@ year(s) GtkAlignment - recurrence-special + special 0.5 0.5 0 @@ -352,7 +348,7 @@ year(s) GtkOptionMenu - recurrence-ending-menu + ending-menu True for until @@ -368,7 +364,7 @@ forever GtkAlignment - recurrence-ending-special + ending-special 0.5 0.5 0 @@ -387,7 +383,7 @@ forever GtkAlignment - recurrence-custom-warning-bin + custom-warning-bin 0 0.5 1 @@ -449,10 +445,9 @@ forever GtkButton - recurrence-exception-add + exception-add True - GTK_RELIEF_NORMAL 0 False @@ -462,10 +457,9 @@ forever GtkButton - recurrence-exception-modify + exception-modify True - GTK_RELIEF_NORMAL 0 False @@ -475,10 +469,9 @@ forever GtkButton - recurrence-exception-delete + exception-delete True - GTK_RELIEF_NORMAL 0 False @@ -500,7 +493,7 @@ forever Custom - recurrence-exception-date + exception-date make_date_edit 0 0 @@ -527,7 +520,7 @@ forever GtkCList - recurrence-exception-list + exception-list True 1 80 @@ -583,7 +576,7 @@ forever GtkAlignment - recurrence-preview-bin + preview-bin 0 0 1 diff --git a/calendar/gui/dialogs/recurrence-page.h b/calendar/gui/dialogs/recurrence-page.h index 39123644b4..aba59003f7 100644 --- a/calendar/gui/dialogs/recurrence-page.h +++ b/calendar/gui/dialogs/recurrence-page.h @@ -25,7 +25,7 @@ #ifndef RECURRENCE_PAGE_H #define RECURRENCE_PAGE_H -#include "editor-page.h" +#include "comp-editor-page.h" BEGIN_GNOME_DECLS @@ -33,29 +33,27 @@ BEGIN_GNOME_DECLS #define TYPE_RECURRENCE_PAGE (recurrence_page_get_type ()) #define RECURRENCE_PAGE(obj) (GTK_CHECK_CAST ((obj), TYPE_RECURRENCE_PAGE, RecurrencePage)) -#define RECURRENCE_PAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_RECURRENCE_PAGE, \ - RecurrencePageClass)) +#define RECURRENCE_PAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_RECURRENCE_PAGE, RecurrencePageClass)) #define IS_RECURRENCE_PAGE(obj) (GTK_CHECK_TYPE ((obj), TYPE_RECURRENCE_PAGE)) #define IS_RECURRENCE_PAGE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), TYPE_RECURRENCE_PAGE)) typedef struct _RecurrencePagePrivate RecurrencePagePrivate; typedef struct { - EditorPage page; + CompEditorPage page; /* Private data */ RecurrencePagePrivate *priv; } RecurrencePage; typedef struct { - EditorPageClass parent_class; + CompEditorPageClass parent_class; } RecurrencePageClass; -GtkType recurrence_page_get_type (void); +GtkType recurrence_page_get_type (void); RecurrencePage *recurrence_page_construct (RecurrencePage *rpage); - -RecurrencePage *recurrence_page_new (void); +RecurrencePage *recurrence_page_new (void); diff --git a/calendar/gui/dialogs/task-details-page.c b/calendar/gui/dialogs/task-details-page.c new file mode 100644 index 0000000000..317f36dbe6 --- /dev/null +++ b/calendar/gui/dialogs/task-details-page.c @@ -0,0 +1,461 @@ +/* Evolution calendar - Main page of the task editor dialog + * + * Copyright (C) 2001 Ximian, Inc. + * + * Authors: Federico Mena-Quintero + * Miguel de Icaza + * Seth Alves + * JP Rosevear + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include "e-util/e-dialog-widgets.h" +#include "../widget-util.h" +#include "comp-editor-util.h" +#include "task-details-page.h" + + + +/* Private part of the TaskDetailsPage structure */ +struct _TaskDetailsPagePrivate { + /* Glade XML data */ + GladeXML *xml; + + /* Widgets from the Glade file */ + GtkWidget *main; + + GtkWidget *summary; + GtkWidget *date_time; + + GtkWidget *completed_date; + GtkWidget *url; + + gboolean updating; +}; + + + +static void task_details_page_class_init (TaskDetailsPageClass *class); +static void task_details_page_init (TaskDetailsPage *tdpage); +static void task_details_page_destroy (GtkObject *object); + +static GtkWidget *task_details_page_get_widget (CompEditorPage *page); +static void task_details_page_fill_widgets (CompEditorPage *page, CalComponent *comp); +static void task_details_page_fill_component (CompEditorPage *page, CalComponent *comp); +static void task_details_page_set_summary (CompEditorPage *page, const char *summary); +static void task_details_page_set_dates (CompEditorPage *page, CompEditorPageDates *dates); + +static CompEditorPageClass *parent_class = NULL; + + + +/** + * task_details_page_get_type: + * + * Registers the #TaskDetailsPage class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the #TaskDetailsPage class. + **/ +GtkType +task_details_page_get_type (void) +{ + static GtkType task_details_page_type; + + if (!task_details_page_type) { + static const GtkTypeInfo task_details_page_info = { + "TaskDetailsPage", + sizeof (TaskDetailsPage), + sizeof (TaskDetailsPageClass), + (GtkClassInitFunc) task_details_page_class_init, + (GtkObjectInitFunc) task_details_page_init, + NULL, /* reserved_1 */ + NULL, /* reserved_2 */ + (GtkClassInitFunc) NULL + }; + + task_details_page_type = + gtk_type_unique (TYPE_COMP_EDITOR_PAGE, + &task_details_page_info); + } + + return task_details_page_type; +} + +/* Class initialization function for the task page */ +static void +task_details_page_class_init (TaskDetailsPageClass *class) +{ + CompEditorPageClass *editor_page_class; + GtkObjectClass *object_class; + + editor_page_class = (CompEditorPageClass *) class; + object_class = (GtkObjectClass *) class; + + parent_class = gtk_type_class (TYPE_COMP_EDITOR_PAGE); + + editor_page_class->get_widget = task_details_page_get_widget; + editor_page_class->fill_widgets = task_details_page_fill_widgets; + editor_page_class->fill_component = task_details_page_fill_component; + editor_page_class->set_summary = task_details_page_set_summary; + editor_page_class->set_dates = task_details_page_set_dates; + + object_class->destroy = task_details_page_destroy; +} + +/* Object initialization function for the task page */ +static void +task_details_page_init (TaskDetailsPage *tdpage) +{ + TaskDetailsPagePrivate *priv; + + priv = g_new0 (TaskDetailsPagePrivate, 1); + tdpage->priv = priv; + + priv->xml = NULL; + + priv->main = NULL; + priv->summary = NULL; + priv->date_time = NULL; + priv->completed_date = NULL; + priv->url = NULL; + + priv->updating = FALSE; +} + +/* Destroy handler for the task page */ +static void +task_details_page_destroy (GtkObject *object) +{ + TaskDetailsPage *tdpage; + TaskDetailsPagePrivate *priv; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_TASK_DETAILS_PAGE (object)); + + tdpage = TASK_DETAILS_PAGE (object); + priv = tdpage->priv; + + if (priv->xml) { + gtk_object_unref (GTK_OBJECT (priv->xml)); + priv->xml = NULL; + } + + g_free (priv); + tdpage->priv = NULL; + + if (GTK_OBJECT_CLASS (parent_class)->destroy) + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + + + +/* get_widget handler for the task page */ +static GtkWidget * +task_details_page_get_widget (CompEditorPage *page) +{ + TaskDetailsPage *tdpage; + TaskDetailsPagePrivate *priv; + + tdpage = TASK_DETAILS_PAGE (page); + priv = tdpage->priv; + + return priv->main; +} + +/* Fills the widgets with default values */ +static void +clear_widgets (TaskDetailsPage *tdpage) +{ + TaskDetailsPagePrivate *priv; + + priv = tdpage->priv; + + /* Summary */ + gtk_label_set_text (GTK_LABEL (priv->summary), ""); + + /* Start date */ + gtk_label_set_text (GTK_LABEL (priv->date_time), ""); + + /* Date completed */ + e_date_edit_set_time (E_DATE_EDIT (priv->completed_date), -1); + + /* URL */ + e_dialog_editable_set (priv->url, NULL); +} + +/* fill_widgets handler for the task page */ +static void +task_details_page_fill_widgets (CompEditorPage *page, CalComponent *comp) +{ + TaskDetailsPage *tdpage; + TaskDetailsPagePrivate *priv; + CalComponentText text; + const char *url; + CompEditorPageDates dates; + + tdpage = TASK_DETAILS_PAGE (page); + priv = tdpage->priv; + + priv->updating = TRUE; + + /* Clean the screen */ + clear_widgets (tdpage); + + /* Summary */ + cal_component_get_summary (comp, &text); + task_details_page_set_summary (page, text.value); + + /* Dates */ + comp_editor_dates (&dates, comp); + task_details_page_set_dates (page, &dates); + + /* URL */ + cal_component_get_url (comp, &url); + e_dialog_editable_set (priv->url, url); + + priv->updating = FALSE; +} + +/* fill_component handler for the task page */ +static void +task_details_page_fill_component (CompEditorPage *page, CalComponent *comp) +{ + TaskDetailsPage *tdpage; + TaskDetailsPagePrivate *priv; + CalComponentDateTime date; + time_t t; + char *url; + + tdpage = TASK_DETAILS_PAGE (page); + priv = tdpage->priv; + + /* Completed Date. */ + date.value = g_new (struct icaltimetype, 1); + date.tzid = NULL; + + t = e_date_edit_get_time (E_DATE_EDIT (priv->completed_date)); + if (t != -1) { + *date.value = icaltime_from_timet (t, FALSE); + cal_component_set_completed (comp, date.value); + } else { + cal_component_set_completed (comp, NULL); + } + + g_free (date.value); + + /* URL. */ + url = e_dialog_editable_get (priv->url); + cal_component_set_url (comp, url); + if (url) + g_free (url); +} + +/* set_summary handler for the task page */ +static void +task_details_page_set_summary (CompEditorPage *page, const char *summary) +{ + TaskDetailsPage *tdpage; + TaskDetailsPagePrivate *priv; + gchar *s; + + tdpage = TASK_DETAILS_PAGE (page); + priv = tdpage->priv; + + s = e_utf8_to_gtk_string (priv->summary, summary); + gtk_label_set_text (GTK_LABEL (priv->summary), s); + g_free (s); +} + +static void +task_details_page_set_dates (CompEditorPage *page, CompEditorPageDates *dates) +{ + TaskDetailsPage *tdpage; + TaskDetailsPagePrivate *priv; + + tdpage = TASK_DETAILS_PAGE (page); + priv = tdpage->priv; + + comp_editor_date_label (dates, priv->date_time); +} + + + +/* Gets the widgets from the XML file and returns if they are all available. */ +static gboolean +get_widgets (TaskDetailsPage *tdpage) +{ + TaskDetailsPagePrivate *priv; + + priv = tdpage->priv; + +#define GW(name) glade_xml_get_widget (priv->xml, name) + + priv->main = GW ("task-details-page"); + g_assert (priv->main); + gtk_widget_ref (priv->main); + gtk_widget_unparent (priv->main); + + priv->summary = GW ("summary"); + priv->date_time = GW ("date-time"); + + priv->completed_date = GW ("completed-date"); + priv->url = GW ("url"); + +#undef GW + + return (priv->summary + && priv->date_time + && priv->completed_date + && priv->url); +} + +/* Callback used when the start or end date widgets change. We check that the + * start date < end date and we set the "all day task" button as appropriate. + */ +static void +date_changed_cb (EDateEdit *dedit, gpointer data) +{ + TaskDetailsPage *tdpage; + TaskDetailsPagePrivate *priv; + CompEditorPageDates dates; + + tdpage = TASK_DETAILS_PAGE (data); + priv = tdpage->priv; + + if (priv->updating) + return; + + dates.start = 0; + dates.end = 0; + dates.due = 0; + dates.complete = e_date_edit_get_time (E_DATE_EDIT (priv->completed_date)); + + /* Notify upstream */ + comp_editor_page_notify_dates_changed (COMP_EDITOR_PAGE (tdpage), &dates); +} + +/* This is called when any field is changed; it notifies upstream. */ +static void +field_changed_cb (GtkWidget *widget, gpointer data) +{ + TaskDetailsPage *tdpage; + TaskDetailsPagePrivate *priv; + + tdpage = TASK_DETAILS_PAGE (data); + priv = tdpage->priv; + + if (!priv->updating) + comp_editor_page_notify_changed (COMP_EDITOR_PAGE (tdpage)); +} + +/* Hooks the widget signals */ +static void +init_widgets (TaskDetailsPage *tdpage) +{ + TaskDetailsPagePrivate *priv; + + priv = tdpage->priv; + + /* Completed Date */ + gtk_signal_connect (GTK_OBJECT (priv->completed_date), "changed", + GTK_SIGNAL_FUNC (date_changed_cb), tdpage); + + /* URL */ + gtk_signal_connect (GTK_OBJECT (priv->url), "changed", + GTK_SIGNAL_FUNC (field_changed_cb), tdpage); +} + + + +/** + * task_details_page_construct: + * @tdpage: An task details page. + * + * Constructs an task page by loading its Glade data. + * + * Return value: The same object as @tdpage, or NULL if the widgets could not + * be created. + **/ +TaskDetailsPage * +task_details_page_construct (TaskDetailsPage *tdpage) +{ + TaskDetailsPagePrivate *priv; + + priv = tdpage->priv; + + priv->xml = glade_xml_new (EVOLUTION_GLADEDIR + "/task-details-page.glade", NULL); + if (!priv->xml) { + g_message ("task_details_page_construct(): " + "Could not load the Glade XML file!"); + return NULL; + } + + if (!get_widgets (tdpage)) { + g_message ("task_details_page_construct(): " + "Could not find all widgets in the XML file!"); + return NULL; + } + + init_widgets (tdpage); + + return tdpage; +} + +/** + * task_details_page_new: + * + * Creates a new task details page. + * + * Return value: A newly-created task details page, or NULL if the page could + * not be created. + **/ +TaskDetailsPage * +task_details_page_new (void) +{ + TaskDetailsPage *tdpage; + + tdpage = gtk_type_new (TYPE_TASK_DETAILS_PAGE); + if (!task_details_page_construct (tdpage)) { + gtk_object_unref (GTK_OBJECT (tdpage)); + return NULL; + } + + return tdpage; +} + +GtkWidget *task_details_page_create_date_edit (void); + +GtkWidget * +task_details_page_create_date_edit (void) +{ + GtkWidget *dedit; + + dedit = date_edit_new (TRUE, TRUE); + e_date_edit_set_allow_no_date_set (E_DATE_EDIT (dedit), TRUE); + + return dedit; +} diff --git a/calendar/gui/dialogs/task-details-page.glade b/calendar/gui/dialogs/task-details-page.glade index 31e3aba6c4..9d13387d59 100644 --- a/calendar/gui/dialogs/task-details-page.glade +++ b/calendar/gui/dialogs/task-details-page.glade @@ -15,6 +15,7 @@ GtkWindow task-details-toplevel + False window1 GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE @@ -24,112 +25,253 @@ False - GtkTable + GtkVBox task-details-page 4 - 2 - 2 False - 2 - 4 + 4 - GtkLabel - label12 - - GTK_JUSTIFY_CENTER - False - 0 - 0.5 - 0 - 0 + GtkFrame + frame1 + + 0 + GTK_SHADOW_ETCHED_IN - 0 - 1 - 0 - 1 - 0 - 0 - False - False - False - False - True - False + 0 + False + False + + + GtkTable + table1 + 4 + 2 + 2 + False + 2 + 2 + + + GtkLabel + label15 + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 0 + 1 + 0 + 1 + 0 + 0 + False + False + False + False + False + False + + + + + GtkLabel + label16 + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 0 + 1 + 1 + 2 + 0 + 0 + False + False + False + False + False + False + + + + + GtkLabel + date-time + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 4 + 0 + + 1 + 2 + 1 + 2 + 0 + 0 + False + False + False + False + True + False + + + + + GtkLabel + summary + + GTK_JUSTIFY_LEFT + False + 0 + 0.5 + 4 + 0 + + 1 + 2 + 0 + 1 + 0 + 0 + False + False + False + False + True + False + + + - GtkLabel - label14 - - GTK_JUSTIFY_CENTER - False - 0 - 0.5 - 0 - 0 + GtkTable + table1 + 4 + 2 + 2 + False + 2 + 4 - 0 - 1 - 1 - 2 - 0 - 0 - False - False - False - False - True - False + 0 + True + True - - - GtkEntry - url - True - True - True - 0 - - - 1 - 2 - 1 - 2 + + GtkLabel + label12 + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 0 0 - True - False - False - False - True - False - - + + 0 + 1 + 0 + 1 + 0 + 0 + False + False + False + False + True + False + + - - Custom - completed-date - task_editor_create_date_edit - 0 - 0 - Sun, 10 Sep 2000 17:34:07 GMT - - 1 - 2 - 0 - 1 + + GtkLabel + label14 + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 0 0 - True - False - False - False - True - False - + + 0 + 1 + 1 + 2 + 0 + 0 + False + False + False + False + True + False + + + + + GtkEntry + url + True + True + True + 0 + + + 1 + 2 + 1 + 2 + 0 + 0 + True + False + False + False + True + False + + + + + Custom + completed-date + task_details_page_create_date_edit + 0 + 0 + Fri, 01 Jun 2001 18:58:51 GMT + + 1 + 2 + 0 + 1 + 0 + 0 + True + False + False + False + True + False + + diff --git a/calendar/gui/dialogs/task-details-page.h b/calendar/gui/dialogs/task-details-page.h new file mode 100644 index 0000000000..d285eb9cc0 --- /dev/null +++ b/calendar/gui/dialogs/task-details-page.h @@ -0,0 +1,62 @@ +/* Evolution calendar - Main page of the task editor dialog + * + * Copyright (C) 2001 Ximian, Inc. + * + * Authors: Federico Mena-Quintero + * Miguel de Icaza + * Seth Alves + * JP Rosevear + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef TASK_DETAILS_PAGE_H +#define TASK_DETAILS_PAGE_H + +#include "comp-editor-page.h" + +BEGIN_GNOME_DECLS + + + +#define TYPE_TASK_DETAILS_PAGE (task_details_page_get_type ()) +#define TASK_DETAILS_PAGE(obj) (GTK_CHECK_CAST ((obj), TYPE_TASK_DETAILS_PAGE, TaskDetailsPage)) +#define TASK_DETAILS_PAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_TASK_DETAILS_PAGE, TaskDetailsPageClass)) +#define IS_TASK_DETAILS_PAGE(obj) (GTK_CHECK_TYPE ((obj), TYPE_TASK_DETAILS_PAGE)) +#define IS_TASK_DETAILS_PAGE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), TYPE_TASK_DETAILS_PAGE)) + +typedef struct _TaskDetailsPagePrivate TaskDetailsPagePrivate; + +typedef struct { + CompEditorPage page; + + /* Private data */ + TaskDetailsPagePrivate *priv; +} TaskDetailsPage; + +typedef struct { + CompEditorPageClass parent_class; +} TaskDetailsPageClass; + + +GtkType task_details_page_get_type (void); +TaskDetailsPage *task_details_page_construct (TaskDetailsPage *epage); +TaskDetailsPage *task_details_page_new (void); + + + +END_GNOME_DECLS + +#endif diff --git a/calendar/gui/dialogs/task-editor-dialog.glade b/calendar/gui/dialogs/task-editor-dialog.glade deleted file mode 100644 index ae7ea9681a..0000000000 --- a/calendar/gui/dialogs/task-editor-dialog.glade +++ /dev/null @@ -1,695 +0,0 @@ - - - - - task-editor-dialog - task-editor-dialog - - src - pixmaps - C - True - True - - - - GnomePropertyBox - task-editor-dialog - False - GTK_WIN_POS_NONE - False - False - False - False - - - GtkNotebook - GnomeDock:contents - notebook1 - 2 - True - True - True - GTK_POS_TOP - False - 2 - 2 - False - - - GtkVBox - vbox1 - 4 - False - 4 - - - GtkTable - table3 - 1 - 2 - False - 4 - 4 - - 0 - False - True - - - - GtkLabel - label3 - - GTK_JUSTIFY_CENTER - False - 0.5 - 0.5 - 0 - 0 - summary - - 0 - 1 - 0 - 1 - 0 - 0 - False - False - False - False - False - False - - - - - GtkEntry - summary - True - True - True - 0 - - - 1 - 2 - 0 - 1 - 0 - 0 - True - False - False - False - True - False - - - - - - GtkFrame - frame2 - - 0 - GTK_SHADOW_ETCHED_IN - - 0 - False - True - - - - GtkHBox - hbox4 - 4 - False - 0 - - - GtkTable - table1 - 2 - 2 - False - 2 - 4 - - 0 - False - True - - - - GtkLabel - label6 - - GTK_JUSTIFY_CENTER - False - 0 - 0.5 - 0 - 0 - - 0 - 1 - 1 - 2 - 0 - 0 - False - False - False - False - True - False - - - - - GtkLabel - label5 - - GTK_JUSTIFY_CENTER - False - 0 - 0.5 - 0 - 0 - - 0 - 1 - 0 - 1 - 0 - 0 - False - False - False - False - True - False - - - - - Custom - due-date - task_editor_create_date_edit - 0 - 0 - Sun, 10 Sep 2000 17:32:18 GMT - - 1 - 2 - 0 - 1 - 0 - 0 - True - False - False - False - True - False - - - - - Custom - start-date - task_editor_create_date_edit - 0 - 0 - Sun, 10 Sep 2000 17:33:31 GMT - - 1 - 2 - 1 - 2 - 0 - 0 - True - False - False - False - True - False - - - - - - - - GtkScrolledWindow - scrolledwindow1 - GTK_POLICY_NEVER - GTK_POLICY_AUTOMATIC - GTK_UPDATE_CONTINUOUS - GTK_UPDATE_CONTINUOUS - - 0 - False - True - - - - GtkText - description - 80 - True - True - - - - - - GtkFrame - frame23 - - 0 - GTK_SHADOW_ETCHED_IN - - 0 - False - True - - - - GtkHBox - hbox3 - 4 - False - 4 - - - GtkLabel - label7 - - GTK_JUSTIFY_CENTER - False - 0.5 - 0.5 - 0 - 0 - status - - 0 - False - False - - - - - GtkOptionMenu - status - True - Not Started -In Progress -Completed -Cancelled - - 0 - - 0 - False - False - - - - - GtkLabel - label8 - - GTK_JUSTIFY_CENTER - False - 0.5 - 0.5 - 0 - 0 - priority - - 0 - False - False - - - - - GtkOptionMenu - priority - True - High -Normal -Low -Undefined - - 0 - - 0 - False - False - - - - - GtkLabel - label9 - - GTK_JUSTIFY_CENTER - False - 0.5 - 0.5 - 0 - 0 - percent-complete - - 0 - False - False - - - - - GtkSpinButton - percent-complete - 60 - True - 1 - 0 - False - GTK_UPDATE_ALWAYS - False - False - 0 - 0 - 100 - 10 - 10 - 10 - - 0 - False - False - - - - - - - GtkFrame - frame24 - - 0 - GTK_SHADOW_ETCHED_IN - - 0 - False - True - - - - GtkHBox - hbox6 - 2 - False - 4 - - - GtkRadioButton - classification-public - True - - True - True - classification_radio_group - - 0 - False - False - - - - - GtkRadioButton - classification-private - True - - False - True - classification_radio_group - - 0 - False - False - - - - - GtkRadioButton - classification-confidential - True - - False - True - classification_radio_group - - 0 - False - False - - - - - - - GtkHBox - hbox2 - False - 2 - - 0 - True - True - - - - GtkButton - contacts-button - True - - 0 - False - False - - - - GtkLabel - label16 - - GTK_JUSTIFY_CENTER - False - 0.5 - 0.5 - 4 - 0 - - - - - GtkEntry - contacts - True - True - True - 0 - - - 0 - True - True - - - - - GtkButton - categories-button - True - - 0 - False - False - - - - GtkLabel - label17 - - GTK_JUSTIFY_CENTER - False - 0.5 - 0.5 - 4 - 0 - - - - - GtkEntry - categories - True - True - True - 0 - - - 0 - True - True - - - - - - - GtkLabel - Notebook:tab - label1 - - GTK_JUSTIFY_CENTER - False - 0.5 - 0.5 - 0 - 0 - - - - GtkTable - table4 - 4 - 2 - 2 - False - 2 - 4 - - - GtkLabel - label12 - - GTK_JUSTIFY_CENTER - False - 0 - 0.5 - 0 - 0 - - 0 - 1 - 0 - 1 - 0 - 0 - False - False - False - False - True - False - - - - - GtkLabel - label14 - - GTK_JUSTIFY_CENTER - False - 0 - 0.5 - 0 - 0 - - 0 - 1 - 1 - 2 - 0 - 0 - False - False - False - False - True - False - - - - - GtkEntry - url - True - True - True - 0 - - - 1 - 2 - 1 - 2 - 0 - 0 - True - False - False - False - True - False - - - - - Custom - completed-date - task_editor_create_date_edit - 0 - 0 - Sun, 10 Sep 2000 17:34:07 GMT - - 1 - 2 - 0 - 1 - 0 - 0 - True - False - False - False - True - False - - - - - - GtkLabel - Notebook:tab - label2 - - GTK_JUSTIFY_CENTER - False - 0.5 - 0.5 - 0 - 0 - - - - - diff --git a/calendar/gui/dialogs/task-editor.c b/calendar/gui/dialogs/task-editor.c index b21de4bd32..2a1f25cfbf 100644 --- a/calendar/gui/dialogs/task-editor.c +++ b/calendar/gui/dialogs/task-editor.c @@ -1,16 +1,18 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Author : - * Damon Chaplin +/* Evolution calendar - Event editor dialog * - * Copyright 2000, Helix Code, Inc. - * Copyright 2000, Ximian, Inc. + * Copyright (C) 2000 Helix Code, Inc. + * Copyright (C) 2001 Ximian, Inc. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. + * Authors: Miguel de Icaza + * Federico Mena-Quintero + * Seth Alves + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,1276 +21,127 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -/* - * TaskEditor - a GtkObject which handles a libglade-loaded dialog to edit - * tasks. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ #include +#include #include -#include -#include -#include #include -#include -#include -#include -#include -#include "delete-comp.h" -#include "save-comp.h" -#include "task-editor.h" -#include "../calendar-config.h" -#include "../widget-util.h" - - -typedef struct { - /* Glade XML data */ - GladeXML *xml; - - /* Client to use */ - CalClient *client; - - /* Calendar component we are editing; this is an internal copy and is - * not one of the read-only objects from the parent calendar. - */ - CalComponent *comp; - - - /* This is TRUE while we are setting the widget values. We just return - from any signal handlers. */ - gboolean ignore_callbacks; - - /* Widgets from the Glade file */ - - GtkWidget *app; - - GtkWidget *summary; - - GtkWidget *due_date; - GtkWidget *start_date; - - GtkWidget *percent_complete; - - GtkWidget *status; - GtkWidget *priority; - - GtkWidget *description; - - GtkWidget *classification_public; - GtkWidget *classification_private; - GtkWidget *classification_confidential; - - GtkWidget *contacts_btn; - GtkWidget *contacts; - - GtkWidget *categories_btn; - GtkWidget *categories; - - GtkWidget *completed_date; - GtkWidget *url; - - /* Call task_editor_set_changed() to set this to TRUE when any field - in the dialog is changed. When the user closes the dialog we will - prompt to save changes. */ - gboolean changed; -} TaskEditorPrivate; - - -/* Note that these two arrays must match. */ -static const int status_map[] = { - ICAL_STATUS_NEEDSACTION, - ICAL_STATUS_INPROCESS, - ICAL_STATUS_COMPLETED, - ICAL_STATUS_CANCELLED, - -1 -}; +#include -typedef enum { - PRIORITY_HIGH, - PRIORITY_NORMAL, - PRIORITY_LOW, - PRIORITY_UNDEFINED, -} TaskEditorPriority; +#include "task-page.h" +#include "task-details-page.h" +#include "recurrence-page.h" +#include "task-editor.h" -static const int priority_map[] = { - PRIORITY_HIGH, - PRIORITY_NORMAL, - PRIORITY_LOW, - PRIORITY_UNDEFINED, - -1 +struct _TaskEditorPrivate { + TaskPage *task_page; + TaskDetailsPage *task_details_page; }; -static const int classification_map[] = { - CAL_COMPONENT_CLASS_PUBLIC, - CAL_COMPONENT_CLASS_PRIVATE, - CAL_COMPONENT_CLASS_CONFIDENTIAL, - -1 -}; + static void task_editor_class_init (TaskEditorClass *class); -static void task_editor_init (TaskEditor *tedit); -static void tedit_apply_event_cb (GtkWidget *widget, gint page_num, gpointer data); -static gint tedit_close_event_cb (GtkWidget *widget, gpointer data); -static gint tedit_delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer data); -static void close_dialog (TaskEditor *tedit); -static gboolean get_widgets (TaskEditor *tedit); -static void init_widgets (TaskEditor *tedit); +static void task_editor_init (TaskEditor *te); static void task_editor_destroy (GtkObject *object); -static char * make_title_from_comp (CalComponent *comp); -static void set_title_from_comp (TaskEditor *tedit, CalComponent *comp); -static void clear_widgets (TaskEditor *tedit); -static void fill_widgets (TaskEditor *tedit); - -static void save_todo_object (TaskEditor *tedit); -static void dialog_to_comp_object (TaskEditor *tedit); - -static void obj_updated_cb (CalClient *client, const char *uid, gpointer data); -static void obj_removed_cb (CalClient *client, const char *uid, gpointer data); -static void raise_and_focus (GtkWidget *widget); - -static TaskEditorPriority priority_value_to_index (int priority_value); -static int priority_index_to_value (TaskEditorPriority priority); - -static void completed_changed (EDateEdit *dedit, - TaskEditor *tedit); -static void status_changed (GtkMenu *menu, - TaskEditor *tedit); -static void percent_complete_changed (GtkAdjustment *adj, - TaskEditor *tedit); -static void field_changed (GtkWidget *widget, - TaskEditor *tedit); -static void task_editor_set_changed (TaskEditor *tedit, - gboolean changed); -static gboolean prompt_to_save_changes (TaskEditor *tedit); -static CalComponentClassification classification_get (GtkWidget *widget); -static void categories_clicked (GtkWidget *button, - TaskEditor *editor); - -/* The function libglade calls to create the EDateEdit widgets in the GUI. */ -GtkWidget * task_editor_create_date_edit (void); - -static GtkObjectClass *parent_class; - -E_MAKE_TYPE(task_editor, "TaskEditor", TaskEditor, - task_editor_class_init, task_editor_init, GTK_TYPE_OBJECT) - - -static void -task_editor_class_init (TaskEditorClass *class) -{ - GtkObjectClass *object_class; - - object_class = (GtkObjectClass *) class; - - parent_class = gtk_type_class (GTK_TYPE_OBJECT); - - object_class->destroy = task_editor_destroy; -} - - -static void -task_editor_init (TaskEditor *tedit) -{ - TaskEditorPrivate *priv; - - priv = g_new0 (TaskEditorPrivate, 1); - tedit->priv = priv; - - priv->ignore_callbacks = FALSE; - - task_editor_set_changed (tedit, FALSE); -} - -/** - * task_editor_new: - * @Returns: a new #TaskEditor. - * - * Creates a new #TaskEditor. - **/ -TaskEditor * -task_editor_new (void) -{ - TaskEditor *tedit; +static CompEditor *parent_class; - tedit = TASK_EDITOR (gtk_type_new (task_editor_get_type ())); - return task_editor_construct (tedit); -} + /** - * task_editor_construct: - * @tedit: A #TaskEditor. + * task_editor_get_type: * - * Constructs a task editor by loading its Glade XML file. + * Registers the #TaskEditor class if necessary, and returns the type ID + * associated to it. * - * Return value: The same object as @tedit, or NULL if the widgets could not be - * created. In the latter case, the task editor will automatically be - * destroyed. + * Return value: The type ID of the #TaskEditor class. **/ -TaskEditor * -task_editor_construct (TaskEditor *tedit) +GtkType +task_editor_get_type (void) { - TaskEditorPrivate *priv; + static GtkType task_editor_type = 0; - g_return_val_if_fail (tedit != NULL, NULL); - g_return_val_if_fail (IS_TASK_EDITOR (tedit), NULL); + if (!task_editor_type) { + static const GtkTypeInfo task_editor_info = { + "TaskEditor", + sizeof (TaskEditor), + sizeof (TaskEditorClass), + (GtkClassInitFunc) task_editor_class_init, + (GtkObjectInitFunc) task_editor_init, + NULL, /* reserved_1 */ + NULL, /* reserved_2 */ + (GtkClassInitFunc) NULL + }; - priv = tedit->priv; - - /* Load the content widgets */ - - priv->xml = glade_xml_new (EVOLUTION_GLADEDIR "/task-editor-dialog.glade", NULL); - if (!priv->xml) { - g_message ("task_editor_construct(): Could not load the Glade XML file!"); - goto error; + task_editor_type = gtk_type_unique (TYPE_COMP_EDITOR, + &task_editor_info); } - if (!get_widgets (tedit)) { - g_message ("task_editor_construct(): Could not find all widgets in the XML file!"); - goto error; - } - - init_widgets (tedit); - - /* Hook to destruction of the dialog */ - gtk_signal_connect (GTK_OBJECT (priv->app), "apply", - GTK_SIGNAL_FUNC (tedit_apply_event_cb), tedit); - gtk_signal_connect (GTK_OBJECT (priv->app), "close", - GTK_SIGNAL_FUNC (tedit_close_event_cb), tedit); - gtk_signal_connect (GTK_OBJECT (priv->app), "delete_event", - GTK_SIGNAL_FUNC (tedit_delete_event_cb), tedit); - - /* Add focus to the summary entry */ - gtk_widget_grab_focus (GTK_WIDGET (priv->summary)); - - - return tedit; - - error: - - gtk_object_unref (GTK_OBJECT (tedit)); - return NULL; -} - - -/* Called by libglade to create our custom EDateEdit widgets. */ -GtkWidget * -task_editor_create_date_edit (void) -{ - GtkWidget *dedit; - - dedit = date_edit_new (TRUE, TRUE); - e_date_edit_set_allow_no_date_set (E_DATE_EDIT (dedit), TRUE); - - return dedit; -} - -/* Callback used when the dialog box is destroyed */ -static void -tedit_apply_event_cb (GtkWidget *widget, gint page_num, gpointer data) -{ - TaskEditor *tedit; - - g_return_if_fail (IS_TASK_EDITOR (data)); - - tedit = TASK_EDITOR (data); - - if (page_num != -1) - return; - - save_todo_object (tedit); -} - -/* Callback used when the dialog box is destroyed */ -static gint -tedit_close_event_cb (GtkWidget *widget, gpointer data) -{ - TaskEditor *tedit; - - g_return_val_if_fail (IS_TASK_EDITOR (data), TRUE); - - tedit = TASK_EDITOR (data); - - if (prompt_to_save_changes (tedit)) - close_dialog (tedit); - - return TRUE; -} - -/* Callback used when the dialog box is destroyed */ -static gint -tedit_delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer data) -{ - TaskEditor *tedit; - - g_return_val_if_fail (IS_TASK_EDITOR (data), TRUE); - - tedit = TASK_EDITOR (data); - - if (prompt_to_save_changes (tedit)) - close_dialog (tedit); - - return TRUE; + return task_editor_type; } - -/* Closes the dialog box and emits the appropriate signals */ +/* Class initialization function for the event editor */ static void -close_dialog (TaskEditor *tedit) -{ - TaskEditorPrivate *priv; - - priv = tedit->priv; - - g_assert (priv->app != NULL); - - gtk_object_destroy (GTK_OBJECT (tedit)); -} - - -/* Gets the widgets from the XML file and returns if they are all available. - * For the widgets whose values can be simply set with e-dialog-utils, it does - * that as well. - */ -static gboolean -get_widgets (TaskEditor *tedit) +task_editor_class_init (TaskEditorClass *class) { - TaskEditorPrivate *priv; - - priv = tedit->priv; - -#define GW(name) glade_xml_get_widget (priv->xml, name) - - priv->app = GW ("task-editor-dialog"); - - priv->summary = GW ("summary"); - - priv->due_date = GW ("due-date"); - priv->start_date = GW ("start-date"); - - priv->percent_complete = GW ("percent-complete"); - - priv->status = GW ("status"); - priv->priority = GW ("priority"); - - priv->description = GW ("description"); - - priv->classification_public = GW ("classification-public"); - priv->classification_private = GW ("classification-private"); - priv->classification_confidential = GW ("classification-confidential"); - - priv->contacts_btn = GW ("contacts-button"); - priv->contacts = GW ("contacts"); - - priv->categories_btn = GW ("categories-button"); - priv->categories = GW ("categories"); + GtkObjectClass *object_class; - priv->completed_date = GW ("completed-date"); - priv->url = GW ("url"); + object_class = (GtkObjectClass *) class; -#undef GW + parent_class = gtk_type_class (TYPE_COMP_EDITOR); - return (priv->app - && priv->summary - && priv->due_date - && priv->start_date - && priv->percent_complete - && priv->status - && priv->priority - && priv->classification_public - && priv->classification_private - && priv->classification_confidential - && priv->description - && priv->contacts_btn - && priv->contacts - && priv->categories_btn - && priv->categories - && priv->completed_date - && priv->url); + object_class->destroy = task_editor_destroy; } - -/* Hooks the widget signals */ +/* Object initialization function for the event editor */ static void -init_widgets (TaskEditor *tedit) +task_editor_init (TaskEditor *te) { TaskEditorPrivate *priv; + + priv = g_new0 (TaskEditorPrivate, 1); + te->priv = priv; - priv = tedit->priv; - - /* Connect signals. The Status, Percent Complete & Date Completed - properties are closely related so whenever one changes we may need - to update the other 2. */ - gtk_signal_connect (GTK_OBJECT (priv->completed_date), "changed", - GTK_SIGNAL_FUNC (completed_changed), tedit); - - gtk_signal_connect (GTK_OBJECT (GTK_OPTION_MENU (priv->status)->menu), - "deactivate", - GTK_SIGNAL_FUNC (status_changed), tedit); - - gtk_signal_connect (GTK_OBJECT (GTK_SPIN_BUTTON (priv->percent_complete)->adjustment), - "value_changed", - GTK_SIGNAL_FUNC (percent_complete_changed), tedit); - - /* Classification */ - gtk_signal_connect (GTK_OBJECT (priv->description), "changed", - GTK_SIGNAL_FUNC (field_changed), tedit); - gtk_signal_connect (GTK_OBJECT (priv->classification_public), - "toggled", - GTK_SIGNAL_FUNC (field_changed), tedit); - gtk_signal_connect (GTK_OBJECT (priv->classification_private), - "toggled", - GTK_SIGNAL_FUNC (field_changed), tedit); - gtk_signal_connect (GTK_OBJECT (priv->classification_confidential), - "toggled", - GTK_SIGNAL_FUNC (field_changed), tedit); - - /* Connect the default signal handler to use to make sure the "changed" - field gets set whenever a field is changed. */ - gtk_signal_connect (GTK_OBJECT (priv->summary), "changed", - GTK_SIGNAL_FUNC (field_changed), tedit); - gtk_signal_connect (GTK_OBJECT (priv->due_date), "changed", - GTK_SIGNAL_FUNC (field_changed), tedit); - gtk_signal_connect (GTK_OBJECT (priv->start_date), "changed", - GTK_SIGNAL_FUNC (field_changed), tedit); - gtk_signal_connect (GTK_OBJECT (GTK_OPTION_MENU (priv->priority)->menu), - "deactivate", - GTK_SIGNAL_FUNC (field_changed), tedit); - gtk_signal_connect (GTK_OBJECT (priv->description), "changed", - GTK_SIGNAL_FUNC (field_changed), tedit); - gtk_signal_connect (GTK_OBJECT (priv->contacts), "changed", - GTK_SIGNAL_FUNC (field_changed), tedit); - gtk_signal_connect (GTK_OBJECT (priv->categories), "changed", - GTK_SIGNAL_FUNC (field_changed), tedit); - gtk_signal_connect (GTK_OBJECT (priv->url), "changed", - GTK_SIGNAL_FUNC (field_changed), tedit); - - /* Button clicks */ - gtk_signal_connect (GTK_OBJECT (priv->categories_btn), "clicked", - GTK_SIGNAL_FUNC (categories_clicked), tedit); - - /* FIXME: we do not support these fields yet, so we disable them */ + priv->task_page = task_page_new (); + comp_editor_append_page (COMP_EDITOR (te), + COMP_EDITOR_PAGE (priv->task_page), + _("Task")); - gtk_widget_set_sensitive (priv->contacts_btn, FALSE); - gtk_widget_set_sensitive (priv->contacts, FALSE); + priv->task_details_page = task_details_page_new (); + comp_editor_append_page (COMP_EDITOR (te), + COMP_EDITOR_PAGE (priv->task_details_page), + _("Details")); } +/* Destroy handler for the event editor */ static void task_editor_destroy (GtkObject *object) { - TaskEditor *tedit; + TaskEditor *te; TaskEditorPrivate *priv; g_return_if_fail (object != NULL); g_return_if_fail (IS_TASK_EDITOR (object)); - tedit = TASK_EDITOR (object); - priv = tedit->priv; - - if (priv->app) { - gtk_widget_destroy (priv->app); - priv->app = NULL; - } - - if (priv->comp) { - gtk_object_unref (GTK_OBJECT (priv->comp)); - priv->comp = NULL; - } - - if (priv->client) { - gtk_signal_disconnect_by_data (GTK_OBJECT (priv->client), - tedit); - gtk_object_unref (GTK_OBJECT (priv->client)); - priv->client = NULL; - } - - if (priv->xml) { - gtk_object_unref (GTK_OBJECT (priv->xml)); - priv->xml = NULL; - } - - g_free (priv); - tedit->priv = NULL; + te = TASK_EDITOR (object); + priv = te->priv; if (GTK_OBJECT_CLASS (parent_class)->destroy) (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); } - -void -task_editor_set_cal_client (TaskEditor *tedit, - CalClient *client) -{ - TaskEditorPrivate *priv; - - g_return_if_fail (tedit != NULL); - g_return_if_fail (IS_TASK_EDITOR (tedit)); - - priv = tedit->priv; - - if (client == priv->client) - return; - - if (client) - g_return_if_fail (IS_CAL_CLIENT (client)); - - if (client) - g_return_if_fail (cal_client_get_load_state (client) == CAL_CLIENT_LOAD_LOADED); - - if (client) - gtk_object_ref (GTK_OBJECT (client)); - - if (priv->client) { - gtk_signal_disconnect_by_data (GTK_OBJECT (priv->client), - tedit); - gtk_object_unref (GTK_OBJECT (priv->client)); - } - - priv->client = client; - - if (priv->client) { - gtk_signal_connect (GTK_OBJECT (priv->client), "obj_updated", - GTK_SIGNAL_FUNC (obj_updated_cb), tedit); - gtk_signal_connect (GTK_OBJECT (priv->client), "obj_removed", - GTK_SIGNAL_FUNC (obj_removed_cb), tedit); - } -} - - -/* Callback used when the calendar client tells us that an object changed */ -static void -obj_updated_cb (CalClient *client, const char *uid, gpointer data) -{ - /* FIXME: Do something sensible if the component changes under our feet */ -#if 0 - TaskEditor *tedit; - TaskEditorPrivate *priv; - CalComponent *comp; - CalClientGetStatus status; - const gchar *editing_uid; - - tedit = TASK_EDITOR (data); - - g_return_if_fail (IS_TASK_EDITOR (tedit)); - - priv = tedit->priv; - - /* If we aren't showing the object which has been updated, return. */ - if (!priv->comp) - return; - cal_component_get_uid (priv->comp, &editing_uid); - if (strcmp (uid, editing_uid)) - return; - - - /* Get the task from the server. */ - status = cal_client_get_object (priv->client, uid, &comp); - - switch (status) { - case CAL_CLIENT_GET_SUCCESS: - /* Everything is fine */ - break; - - case CAL_CLIENT_GET_SYNTAX_ERROR: - g_message ("obj_updated_cb(): Syntax error when getting object `%s'", uid); - return; - - case CAL_CLIENT_GET_NOT_FOUND: - /* The object is no longer in the server, so do nothing */ - return; - - default: - g_assert_not_reached (); - return; - } - - raise_and_focus (priv->app); -#endif -} - -/* Callback used when the calendar client tells us that an object was removed */ -static void -obj_removed_cb (CalClient *client, const char *uid, gpointer data) -{ - /* FIXME: Do something sensible if the component is removed under our - * feet. - */ -#if 0 - TaskEditor *tedit; - TaskEditorPrivate *priv; - const gchar *editing_uid; - - tedit = TASK_EDITOR (data); - - g_return_if_fail (tedit != NULL); - g_return_if_fail (IS_TASK_EDITOR (tedit)); - - priv = tedit->priv; - - /* If we aren't showing the object which has been updated, return. */ - if (!priv->comp) - return; - cal_component_get_uid (priv->comp, &editing_uid); - if (strcmp (uid, editing_uid)) - return; - - - raise_and_focus (priv->app); -#endif -} - - -/* Brings attention to a window by raising it and giving it focus */ -static void -raise_and_focus (GtkWidget *widget) -{ - g_assert (GTK_WIDGET_REALIZED (widget)); - gdk_window_show (widget->window); - gtk_widget_grab_focus (widget); -} - - /** - * task_editor_set_todo_object: - * @tedit: A #TaskEditor. - * @comp: A todo object. + * task_editor_new: + * + * Creates a new event editor dialog. * - * Sets the todo object that a task editor dialog will manipulate. + * Return value: A newly-created event editor dialog, or NULL if the event + * editor could not be created. **/ -void -task_editor_set_todo_object (TaskEditor *tedit, - CalComponent *comp) -{ - TaskEditorPrivate *priv; - - g_return_if_fail (tedit != NULL); - g_return_if_fail (IS_TASK_EDITOR (tedit)); - - priv = tedit->priv; - - if (priv->comp) { - gtk_object_unref (GTK_OBJECT (priv->comp)); - priv->comp = NULL; - } - - if (comp) - priv->comp = cal_component_clone (comp); - - set_title_from_comp (tedit, priv->comp); - fill_widgets (tedit); -} - -void -task_editor_focus (TaskEditor *tedit) -{ - TaskEditorPrivate *priv; - - g_return_if_fail (tedit != NULL); - g_return_if_fail (IS_TASK_EDITOR (tedit)); - - priv = tedit->priv; - gtk_widget_show_now (priv->app); - raise_and_focus (priv->app); -} - -#warning this is duplicated function from ../event-editor.c -/* Creates an appropriate title for the task editor dialog */ -static char * -make_title_from_comp (CalComponent *comp) -{ - char *title; - const char *type_string; - CalComponentVType type; - CalComponentText text; - - if (!comp) - return g_strdup (_("Edit Task")); - - type = cal_component_get_vtype (comp); - switch (type) { - case CAL_COMPONENT_EVENT: - type_string = _("Appointment - %s"); - break; - case CAL_COMPONENT_TODO: - type_string = _("Task - %s"); - break; - case CAL_COMPONENT_JOURNAL: - type_string = _("Journal entry - %s"); - break; - default: - g_message ("make_title_from_comp(): Cannot handle object of type %d", type); - return NULL; - } - - cal_component_get_summary (comp, &text); - if (text.value) { - char *summary; - summary = e_utf8_to_locale_string (text.value); - title = g_strdup_printf (type_string, summary); - g_free (summary); - } else - title = g_strdup_printf (type_string, _("No summary")); - - return title; -} - -/* Sets the event editor's window title from a calendar component */ -static void -set_title_from_comp (TaskEditor *tedit, CalComponent *comp) -{ - TaskEditorPrivate *priv = tedit->priv; - char *title; - - title = make_title_from_comp (comp); - gtk_window_set_title (GTK_WINDOW (priv->app), title); - g_free (title); -} - -/* Fills the widgets with default values */ -static void -clear_widgets (TaskEditor *tedit) -{ - TaskEditorPrivate *priv; - - priv = tedit->priv; - - -} - -/* Fills in the widgets with the proper values */ -static void -fill_widgets (TaskEditor *tedit) -{ - TaskEditorPrivate *priv; - CalComponentText text; - CalComponentDateTime d; - CalComponentClassification cl; - struct icaltimetype *completed; - GSList *l; - time_t t; - int *priority_value, *percent; - icalproperty_status status; - TaskEditorPriority priority; - const char *url; - const char *categories; - - priv = tedit->priv; - - task_editor_set_changed (tedit, FALSE); - - clear_widgets (tedit); - - if (!priv->comp) - return; - - /* We want to ignore any signals emitted while changing fields. */ - priv->ignore_callbacks = TRUE; - - - cal_component_get_summary (priv->comp, &text); - e_dialog_editable_set (priv->summary, text.value); - - cal_component_get_description_list (priv->comp, &l); - if (l) { - text = *(CalComponentText *)l->data; - e_dialog_editable_set (priv->description, text.value); - } else { - e_dialog_editable_set (priv->description, NULL); - } - cal_component_free_text_list (l); - - /* Due Date. */ - cal_component_get_due (priv->comp, &d); - if (d.value) { - t = icaltime_as_timet (*d.value); - } else { - t = -1; - } - e_date_edit_set_time (E_DATE_EDIT (priv->due_date), t); - - /* Start Date. */ - cal_component_get_dtstart (priv->comp, &d); - if (d.value) { - t = icaltime_as_timet (*d.value); - } else { - t = -1; - } - e_date_edit_set_time (E_DATE_EDIT (priv->start_date), t); - - /* Completed Date. */ - cal_component_get_completed (priv->comp, &completed); - if (completed) { - t = icaltime_as_timet (*completed); - cal_component_free_icaltimetype (completed); - } else { - t = -1; - } - e_date_edit_set_time (E_DATE_EDIT (priv->completed_date), t); - - /* Percent Complete. */ - cal_component_get_percent (priv->comp, &percent); - if (percent) { - e_dialog_spin_set (priv->percent_complete, *percent); - cal_component_free_percent (percent); - } else { - /* FIXME: Could check if task is completed and set 100%. */ - e_dialog_spin_set (priv->percent_complete, 0); - } - - /* Status. */ - cal_component_get_status (priv->comp, &status); - if (status == ICAL_STATUS_NONE) { - /* Try to user the percent value. */ - if (percent) { - if (*percent == 0) - status = ICAL_STATUS_NEEDSACTION; - else if (*percent == 100) - status = ICAL_STATUS_COMPLETED; - else - status = ICAL_STATUS_INPROCESS; - } else - status = ICAL_STATUS_NEEDSACTION; - } - e_dialog_option_menu_set (priv->status, status, status_map); - - /* Priority. */ - cal_component_get_priority (priv->comp, &priority_value); - if (priority_value) { - priority = priority_value_to_index (*priority_value); - cal_component_free_priority (priority_value); - } else { - priority = PRIORITY_UNDEFINED; - } - e_dialog_option_menu_set (priv->priority, priority, priority_map); - - - /* Classification. */ - cal_component_get_classification (priv->comp, &cl); - - switch (cl) { - case CAL_COMPONENT_CLASS_PUBLIC: - e_dialog_radio_set (priv->classification_public, CAL_COMPONENT_CLASS_PUBLIC, - classification_map); - case CAL_COMPONENT_CLASS_PRIVATE: - e_dialog_radio_set (priv->classification_public, CAL_COMPONENT_CLASS_PRIVATE, - classification_map); - case CAL_COMPONENT_CLASS_CONFIDENTIAL: - e_dialog_radio_set (priv->classification_public, CAL_COMPONENT_CLASS_CONFIDENTIAL, - classification_map); - default: - /* What do do? We can't g_assert_not_reached() since it is a - * value from an external file. - */ - } - - /* Categories */ - cal_component_get_categories (priv->comp, &categories); - e_dialog_editable_set (priv->categories, categories); - - /* URL. */ - cal_component_get_url (priv->comp, &url); - e_dialog_editable_set (priv->url, url); - - priv->ignore_callbacks = FALSE; -} - - -static void -save_todo_object (TaskEditor *tedit) -{ - TaskEditorPrivate *priv; - - priv = tedit->priv; - - g_return_if_fail (priv->client != NULL); - - if (!priv->comp) - return; - - dialog_to_comp_object (tedit); - set_title_from_comp (tedit, priv->comp); - - if (!cal_client_update_object (priv->client, priv->comp)) - g_message ("save_todo_object(): Could not update the object!"); - else - task_editor_set_changed (tedit, FALSE); -} - - -/* Get the values of the widgets in the event editor and put them in the iCalObject */ -static void -dialog_to_comp_object (TaskEditor *tedit) -{ - TaskEditorPrivate *priv; - CalComponent *comp; - CalComponentDateTime date; - time_t t; - icalproperty_status status; - TaskEditorPriority priority; - int priority_value, percent; - char *url, *cat; - char *str; - - priv = tedit->priv; - comp = priv->comp; - - /* Summary. */ - - str = e_dialog_editable_get (priv->summary); - if (!str || strlen (str) == 0) - cal_component_set_summary (comp, NULL); - else { - CalComponentText text; - - text.value = str; - text.altrep = NULL; - - cal_component_set_summary (comp, &text); - } - - if (str) - g_free (str); - - /* Description */ - - str = e_dialog_editable_get (priv->description); - if (!str || strlen (str) == 0) - cal_component_set_description_list (comp, NULL); - else { - GSList l; - CalComponentText text; - - text.value = str; - text.altrep = NULL; - l.data = &text; - l.next = NULL; - - cal_component_set_description_list (comp, &l); - } - - if (!str) - g_free (str); - - /* Dates */ - - date.value = g_new (struct icaltimetype, 1); - date.tzid = NULL; - - /* Due Date. */ - t = e_date_edit_get_time (E_DATE_EDIT (priv->due_date)); - if (t != -1) { - *date.value = icaltime_from_timet (t, FALSE); - cal_component_set_due (comp, &date); - } else { - cal_component_set_due (comp, NULL); - } - - /* Start Date. */ - t = e_date_edit_get_time (E_DATE_EDIT (priv->start_date)); - if (t != -1) { - *date.value = icaltime_from_timet (t, FALSE); - cal_component_set_dtstart (comp, &date); - } else { - cal_component_set_dtstart (comp, NULL); - } - - /* Completed Date. */ - t = e_date_edit_get_time (E_DATE_EDIT (priv->completed_date)); - if (t != -1) { - *date.value = icaltime_from_timet (t, FALSE); - cal_component_set_completed (comp, date.value); - } else { - cal_component_set_completed (comp, NULL); - } - - g_free (date.value); - - /* Percent Complete. */ - percent = e_dialog_spin_get_int (priv->percent_complete); - cal_component_set_percent (comp, &percent); - - /* Status. */ - status = e_dialog_option_menu_get (priv->status, status_map); - cal_component_set_status (comp, status); - - /* Priority. */ - priority = e_dialog_option_menu_get (priv->priority, priority_map); - priority_value = priority_index_to_value (priority); - cal_component_set_priority (comp, &priority_value); - - /* Classification. */ - cal_component_set_classification (comp, classification_get (priv->classification_public)); - - /* Categories */ - cat = e_dialog_editable_get (priv->categories); - cal_component_set_categories (comp, cat); - - if (cat) - g_free (cat); - - /* URL. */ - url = e_dialog_editable_get (priv->url); - cal_component_set_url (comp, url); - - if (url) - g_free (url); - - cal_component_commit_sequence (comp); -} - -static TaskEditorPriority -priority_value_to_index (int priority_value) -{ - TaskEditorPriority retval; - - if (priority_value == 0) - retval = PRIORITY_UNDEFINED; - else if (priority_value <= 4) - retval = PRIORITY_HIGH; - else if (priority_value == 5) - retval = PRIORITY_NORMAL; - else - retval = PRIORITY_LOW; - - return retval; -} - - -static int -priority_index_to_value (TaskEditorPriority priority) -{ - int retval; - - switch (priority) { - case PRIORITY_UNDEFINED: - retval = 0; - break; - case PRIORITY_HIGH: - retval = 3; - break; - case PRIORITY_NORMAL: - retval = 5; - break; - case PRIORITY_LOW: - retval = 7; - break; - default: - retval = -1; - g_assert_not_reached (); - break; - } - - return retval; -} - - -static void -completed_changed (EDateEdit *dedit, - TaskEditor *tedit) -{ - TaskEditorPrivate *priv; - time_t t; - - g_return_if_fail (IS_TASK_EDITOR (tedit)); - - priv = tedit->priv; - - if (priv->ignore_callbacks) - return; - - task_editor_set_changed (tedit, TRUE); - - priv->ignore_callbacks = TRUE; - t = e_date_edit_get_time (E_DATE_EDIT (priv->completed_date)); - if (t == -1) { - /* If the 'Completed Date' is set to 'None', we set the - status to 'Not Started' and the percent-complete to 0. - The task may actually be partially-complete, but we leave - it to the user to set those fields. */ - e_dialog_option_menu_set (priv->status, ICAL_STATUS_NEEDSACTION, - status_map); - e_dialog_spin_set (priv->percent_complete, 0); - } else { - e_dialog_option_menu_set (priv->status, ICAL_STATUS_COMPLETED, - status_map); - e_dialog_spin_set (priv->percent_complete, 100); - } - priv->ignore_callbacks = FALSE; -} - - -static void -status_changed (GtkMenu *menu, - TaskEditor *tedit) -{ - TaskEditorPrivate *priv; - icalproperty_status status; - - g_return_if_fail (IS_TASK_EDITOR (tedit)); - - priv = tedit->priv; - - if (priv->ignore_callbacks) - return; - - task_editor_set_changed (tedit, TRUE); - - status = e_dialog_option_menu_get (priv->status, status_map); - priv->ignore_callbacks = TRUE; - if (status == ICAL_STATUS_NEEDSACTION) { - e_dialog_spin_set (priv->percent_complete, 0); - e_date_edit_set_time (E_DATE_EDIT (priv->completed_date), -1); - } else if (status == ICAL_STATUS_COMPLETED) { - e_dialog_spin_set (priv->percent_complete, 100); - e_date_edit_set_time (E_DATE_EDIT (priv->completed_date), - time (NULL)); - } - priv->ignore_callbacks = FALSE; -} - - -static void -percent_complete_changed (GtkAdjustment *adj, - TaskEditor *tedit) -{ - TaskEditorPrivate *priv; - gint percent; - icalproperty_status status; - time_t date_completed; - - g_return_if_fail (IS_TASK_EDITOR (tedit)); - - priv = tedit->priv; - - if (priv->ignore_callbacks) - return; - - task_editor_set_changed (tedit, TRUE); - - percent = e_dialog_spin_get_int (priv->percent_complete); - priv->ignore_callbacks = TRUE; - - if (percent == 100) { - date_completed = time (NULL); - status = ICAL_STATUS_COMPLETED; - } else { - /* FIXME: Set to 'None'. */ - date_completed = time (NULL); - - if (percent == 0) - status = ICAL_STATUS_NEEDSACTION; - else - status = ICAL_STATUS_INPROCESS; - } - - e_date_edit_set_time (E_DATE_EDIT (priv->completed_date), - date_completed); - e_dialog_option_menu_set (priv->status, status, status_map); - - priv->ignore_callbacks = FALSE; -} - -/* Decode the radio button group for classifications */ -static CalComponentClassification -classification_get (GtkWidget *widget) -{ - return e_dialog_radio_get (widget, classification_map); -} - - -/* This is called when all fields except those handled above (status, percent - complete & completed date) are changed. It just sets the "changed" flag. */ -static void -field_changed (GtkWidget *widget, - TaskEditor *tedit) -{ - TaskEditorPrivate *priv; - - g_return_if_fail (IS_TASK_EDITOR (tedit)); - - priv = tedit->priv; - - if (priv->ignore_callbacks) - return; - - task_editor_set_changed (tedit, TRUE); -} - - -static void -task_editor_set_changed (TaskEditor *tedit, - gboolean changed) -{ - TaskEditorPrivate *priv; - - priv = tedit->priv; - -#if 0 - g_print ("In task_editor_set_changed: %s\n", - changed ? "TRUE" : "FALSE"); -#endif - - priv->changed = changed; - - if (priv->app) - gnome_property_box_set_state (GNOME_PROPERTY_BOX (priv->app), changed); -} - - -/* This checks if the "changed" field is set, and if so it prompts to save - the changes using a "Save/Discard/Cancel" modal dialog. It then saves the - changes if requested. It returns TRUE if the dialog should now be closed. */ -static gboolean -prompt_to_save_changes (TaskEditor *tedit) -{ - TaskEditorPrivate *priv; - - priv = tedit->priv; - - if (!priv->changed) - return TRUE; - - switch (save_component_dialog (GTK_WINDOW (priv->app))) { - case 0: /* Save */ - /* FIXME: If an error occurs here, we should popup a dialog - and then return FALSE. */ - save_todo_object (tedit); - return TRUE; - case 1: /* Discard */ - return TRUE; - case 2: /* Cancel */ - default: - return FALSE; - break; - } - -} - -static void -categories_clicked(GtkWidget *button, TaskEditor *tedit) +TaskEditor * +task_editor_new (void) { - char *categories; - GnomeDialog *dialog; - int result; - GtkWidget *entry; - - entry = ((TaskEditorPrivate *)tedit->priv)->categories; - categories = e_utf8_gtk_entry_get_text (GTK_ENTRY (entry)); - - dialog = GNOME_DIALOG (e_categories_new (categories)); - result = gnome_dialog_run (dialog); - g_free (categories); - - if (result == 0) { - gtk_object_get (GTK_OBJECT (dialog), - "categories", &categories, - NULL); - e_utf8_gtk_entry_set_text (GTK_ENTRY (entry), categories); - g_free (categories); - } - gtk_object_destroy (GTK_OBJECT (dialog)); + return TASK_EDITOR (gtk_type_new (TYPE_TASK_EDITOR)); } diff --git a/calendar/gui/dialogs/task-editor.h b/calendar/gui/dialogs/task-editor.h index 7327803a72..bd29d7989d 100644 --- a/calendar/gui/dialogs/task-editor.h +++ b/calendar/gui/dialogs/task-editor.h @@ -1,16 +1,16 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - -/* - * Author : - * Damon Chaplin +/* Evolution calendar - Task editor dialog + * + * Copyright (C) 2000 Helix Code, Inc. + * Copyright (C) 2001 Ximian, Inc. * - * Copyright 2000, Helix Code, Inc. - * Copyright 2000, Ximian, Inc. + * Authors: Miguel de Icaza + * Federico Mena-Quintero + * Seth Alves * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,52 +19,45 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ -#ifndef _TASK_EDITOR_H_ -#define _TASK_EDITOR_H_ - -#include -#include -#include -#include -BEGIN_GNOME_DECLS +#ifndef __TASK_EDITOR_H__ +#define __TASK_EDITOR_H__ +#include +#include +#include "comp-editor.h" -#define TASK_EDITOR(obj) GTK_CHECK_CAST (obj, task_editor_get_type (), TaskEditor) -#define TASK_EDITOR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, task_editor_get_type (), TaskEditorClass) -#define IS_TASK_EDITOR(obj) GTK_CHECK_TYPE (obj, task_editor_get_type ()) + +#define TYPE_TASK_EDITOR (task_editor_get_type ()) +#define TASK_EDITOR(obj) (GTK_CHECK_CAST ((obj), TYPE_TASK_EDITOR, TaskEditor)) +#define TASK_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_TASK_EDITOR, \ + TaskEditorClass)) +#define IS_TASK_EDITOR(obj) (GTK_CHECK_TYPE ((obj), TYPE_TASK_EDITOR)) +#define IS_TASK_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), TYPE_TASK_EDITOR)) -typedef struct _TaskEditor TaskEditor; -typedef struct _TaskEditorClass TaskEditorClass; +typedef struct _TaskEditor TaskEditor; +typedef struct _TaskEditorClass TaskEditorClass; +typedef struct _TaskEditorPrivate TaskEditorPrivate; -struct _TaskEditor -{ - GtkObject object; +struct _TaskEditor { + CompEditor parent; /* Private data */ - gpointer priv; + TaskEditorPrivate *priv; }; -struct _TaskEditorClass -{ - GtkObjectClass parent_class; +struct _TaskEditorClass { + CompEditorClass parent_class; }; -GtkType task_editor_get_type (void); -TaskEditor* task_editor_construct (TaskEditor *tedit); -TaskEditor* task_editor_new (void); -void task_editor_set_cal_client (TaskEditor *tedit, - CalClient *client); -void task_editor_set_todo_object (TaskEditor *tedit, - CalComponent *comp); -void task_editor_focus (TaskEditor *tedit); - - +GtkType task_editor_get_type (void); +TaskEditor *task_editor_construct (TaskEditor *ee); +TaskEditor *task_editor_new (void); +void task_editor_update_widgets (TaskEditor *ee); -END_GNOME_DECLS + -#endif /* _TASK_EDITOR_H_ */ +#endif /* __TASK_EDITOR_H__ */ diff --git a/calendar/gui/dialogs/task-page.c b/calendar/gui/dialogs/task-page.c new file mode 100644 index 0000000000..a1e66260c2 --- /dev/null +++ b/calendar/gui/dialogs/task-page.c @@ -0,0 +1,966 @@ +/* Evolution calendar - Main page of the task editor dialog + * + * Copyright (C) 2001 Ximian, Inc. + * + * Authors: Federico Mena-Quintero + * Miguel de Icaza + * Seth Alves + * JP Rosevear + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "e-util/e-dialog-widgets.h" +#include "../widget-util.h" +#include "task-page.h" + + + +/* Private part of the TaskPage structure */ +struct _TaskPagePrivate { + /* Glade XML data */ + GladeXML *xml; + + /* Widgets from the Glade file */ + GtkWidget *main; + + GtkWidget *summary; + + GtkWidget *due_date; + GtkWidget *start_date; + + GtkWidget *percent_complete; + + GtkWidget *status; + GtkWidget *priority; + + GtkWidget *description; + + GtkWidget *classification_public; + GtkWidget *classification_private; + GtkWidget *classification_confidential; + + GtkWidget *contacts_btn; + GtkWidget *contacts; + + GtkWidget *categories_btn; + GtkWidget *categories; + + gboolean updating; +}; + +/* Note that these two arrays must match. */ +static const int status_map[] = { + ICAL_STATUS_NEEDSACTION, + ICAL_STATUS_INPROCESS, + ICAL_STATUS_COMPLETED, + ICAL_STATUS_CANCELLED, + -1 +}; + +typedef enum { + PRIORITY_HIGH, + PRIORITY_NORMAL, + PRIORITY_LOW, + PRIORITY_UNDEFINED, +} TaskEditorPriority; + +static const int priority_map[] = { + PRIORITY_HIGH, + PRIORITY_NORMAL, + PRIORITY_LOW, + PRIORITY_UNDEFINED, + -1 +}; + +static const int classification_map[] = { + CAL_COMPONENT_CLASS_PUBLIC, + CAL_COMPONENT_CLASS_PRIVATE, + CAL_COMPONENT_CLASS_CONFIDENTIAL, + -1 +}; + + + +static void task_page_class_init (TaskPageClass *class); +static void task_page_init (TaskPage *tpage); +static void task_page_destroy (GtkObject *object); + +static GtkWidget *task_page_get_widget (CompEditorPage *page); +static void task_page_fill_widgets (CompEditorPage *page, CalComponent *comp); +static void task_page_fill_component (CompEditorPage *page, CalComponent *comp); +static void task_page_set_summary (CompEditorPage *page, const char *summary); +static void task_page_set_dates (CompEditorPage *page, CompEditorPageDates *dates); + +static CompEditorPageClass *parent_class = NULL; + + + +/** + * task_page_get_type: + * + * Registers the #TaskPage class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the #TaskPage class. + **/ +GtkType +task_page_get_type (void) +{ + static GtkType task_page_type; + + if (!task_page_type) { + static const GtkTypeInfo task_page_info = { + "TaskPage", + sizeof (TaskPage), + sizeof (TaskPageClass), + (GtkClassInitFunc) task_page_class_init, + (GtkObjectInitFunc) task_page_init, + NULL, /* reserved_1 */ + NULL, /* reserved_2 */ + (GtkClassInitFunc) NULL + }; + + task_page_type = gtk_type_unique (TYPE_COMP_EDITOR_PAGE, + &task_page_info); + } + + return task_page_type; +} + +/* Class initialization function for the task page */ +static void +task_page_class_init (TaskPageClass *class) +{ + CompEditorPageClass *editor_page_class; + GtkObjectClass *object_class; + + editor_page_class = (CompEditorPageClass *) class; + object_class = (GtkObjectClass *) class; + + parent_class = gtk_type_class (TYPE_COMP_EDITOR_PAGE); + + editor_page_class->get_widget = task_page_get_widget; + editor_page_class->fill_widgets = task_page_fill_widgets; + editor_page_class->fill_component = task_page_fill_component; + editor_page_class->set_summary = task_page_set_summary; + editor_page_class->set_dates = task_page_set_dates; + + object_class->destroy = task_page_destroy; +} + +/* Object initialization function for the task page */ +static void +task_page_init (TaskPage *tpage) +{ + TaskPagePrivate *priv; + + priv = g_new0 (TaskPagePrivate, 1); + tpage->priv = priv; + + priv->xml = NULL; + + priv->main = NULL; + priv->summary = NULL; + priv->due_date = NULL; + priv->start_date = NULL; + priv->percent_complete = NULL; + priv->status = NULL; + priv->description = NULL; + priv->classification_public = NULL; + priv->classification_private = NULL; + priv->classification_confidential = NULL; + priv->contacts_btn = NULL; + priv->contacts = NULL; + priv->categories_btn = NULL; + priv->categories = NULL; + + priv->updating = FALSE; +} + +/* Destroy handler for the task page */ +static void +task_page_destroy (GtkObject *object) +{ + TaskPage *tpage; + TaskPagePrivate *priv; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_TASK_PAGE (object)); + + tpage = TASK_PAGE (object); + priv = tpage->priv; + + if (priv->xml) { + gtk_object_unref (GTK_OBJECT (priv->xml)); + priv->xml = NULL; + } + + g_free (priv); + tpage->priv = NULL; + + if (GTK_OBJECT_CLASS (parent_class)->destroy) + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + + + +/* get_widget handler for the task page */ +static GtkWidget * +task_page_get_widget (CompEditorPage *page) +{ + TaskPage *tpage; + TaskPagePrivate *priv; + + tpage = TASK_PAGE (page); + priv = tpage->priv; + + return priv->main; +} + +/* Fills the widgets with default values */ +static void +clear_widgets (TaskPage *tpage) +{ + TaskPagePrivate *priv; + time_t now; + + priv = tpage->priv; + + now = time (NULL); + + /* Summary, description */ + e_dialog_editable_set (priv->summary, NULL); + e_dialog_editable_set (priv->description, NULL); + + /* Start, due times */ + e_date_edit_set_time (E_DATE_EDIT (priv->start_date), now); + e_date_edit_set_time (E_DATE_EDIT (priv->due_date), now); + + /* Classification */ + e_dialog_radio_set (priv->classification_public, + CAL_COMPONENT_CLASS_PRIVATE, classification_map); + + /* Status, priority, complete percent */ + e_dialog_spin_set (priv->percent_complete, 0.0); + e_dialog_option_menu_set (priv->status, 0, status_map); + e_dialog_option_menu_set (priv->priority, 0, priority_map); + + /* Categories */ + e_dialog_editable_set (priv->categories, NULL); +} + +static TaskEditorPriority +priority_value_to_index (int priority_value) +{ + TaskEditorPriority retval; + + if (priority_value == 0) + retval = PRIORITY_UNDEFINED; + else if (priority_value <= 4) + retval = PRIORITY_HIGH; + else if (priority_value == 5) + retval = PRIORITY_NORMAL; + else + retval = PRIORITY_LOW; + + return retval; +} + +static int +priority_index_to_value (TaskEditorPriority priority) +{ + int retval; + + switch (priority) { + case PRIORITY_UNDEFINED: + retval = 0; + break; + case PRIORITY_HIGH: + retval = 3; + break; + case PRIORITY_NORMAL: + retval = 5; + break; + case PRIORITY_LOW: + retval = 7; + break; + default: + retval = -1; + g_assert_not_reached (); + break; + } + + return retval; +} + +/* Decode the radio button group for classifications */ +static CalComponentClassification +classification_get (GtkWidget *widget) +{ + return e_dialog_radio_get (widget, classification_map); +} + +/* fill_widgets handler for the task page */ +static void +task_page_fill_widgets (CompEditorPage *page, CalComponent *comp) +{ + TaskPage *tpage; + TaskPagePrivate *priv; + CalComponentText text; + CalComponentDateTime d; + CalComponentClassification cl; + GSList *l; + time_t t; + int *priority_value, *percent; + icalproperty_status status; + TaskEditorPriority priority; + const char *categories; + + tpage = TASK_PAGE (page); + priv = tpage->priv; + + priv->updating = TRUE; + + /* Clean the screen */ + clear_widgets (tpage); + + /* Summary, description(s) */ + cal_component_get_summary (comp, &text); + e_dialog_editable_set (priv->summary, text.value); + + cal_component_get_description_list (comp, &l); + if (l) { + text = *(CalComponentText *)l->data; + e_dialog_editable_set (priv->description, text.value); + } else { + e_dialog_editable_set (priv->description, NULL); + } + cal_component_free_text_list (l); + + /* Due Date. */ + cal_component_get_due (comp, &d); + if (d.value) { + t = icaltime_as_timet (*d.value); + } else { + t = -1; + } + e_date_edit_set_time (E_DATE_EDIT (priv->due_date), t); + + /* Start Date. */ + cal_component_get_dtstart (comp, &d); + if (d.value) { + t = icaltime_as_timet (*d.value); + } else { + t = -1; + } + e_date_edit_set_time (E_DATE_EDIT (priv->start_date), t); + + /* Percent Complete. */ + cal_component_get_percent (comp, &percent); + if (percent) { + e_dialog_spin_set (priv->percent_complete, *percent); + cal_component_free_percent (percent); + } else { + /* FIXME: Could check if task is completed and set 100%. */ + e_dialog_spin_set (priv->percent_complete, 0); + } + + /* Status. */ + cal_component_get_status (comp, &status); + if (status == ICAL_STATUS_NONE) { + /* Try to user the percent value. */ + if (percent) { + if (*percent == 0) + status = ICAL_STATUS_NEEDSACTION; + else if (*percent == 100) + status = ICAL_STATUS_COMPLETED; + else + status = ICAL_STATUS_INPROCESS; + } else + status = ICAL_STATUS_NEEDSACTION; + } + e_dialog_option_menu_set (priv->status, status, status_map); + + /* Priority. */ + cal_component_get_priority (comp, &priority_value); + if (priority_value) { + priority = priority_value_to_index (*priority_value); + cal_component_free_priority (priority_value); + } else { + priority = PRIORITY_UNDEFINED; + } + e_dialog_option_menu_set (priv->priority, priority, priority_map); + + + /* Classification. */ + cal_component_get_classification (comp, &cl); + + switch (cl) { + case CAL_COMPONENT_CLASS_PUBLIC: + e_dialog_radio_set (priv->classification_public, + CAL_COMPONENT_CLASS_PUBLIC, + classification_map); + case CAL_COMPONENT_CLASS_PRIVATE: + e_dialog_radio_set (priv->classification_public, + CAL_COMPONENT_CLASS_PRIVATE, + classification_map); + case CAL_COMPONENT_CLASS_CONFIDENTIAL: + e_dialog_radio_set (priv->classification_public, + CAL_COMPONENT_CLASS_CONFIDENTIAL, + classification_map); + default: + /* What do do? We can't g_assert_not_reached() since it is a + * value from an external file. + */ + } + + /* Categories */ + cal_component_get_categories (comp, &categories); + e_dialog_editable_set (priv->categories, categories); + + priv->updating = FALSE; +} + +/* fill_component handler for the task page */ +static void +task_page_fill_component (CompEditorPage *page, CalComponent *comp) +{ + TaskPage *tpage; + TaskPagePrivate *priv; + CalComponentDateTime date; + time_t t; + icalproperty_status status; + TaskEditorPriority priority; + int priority_value, percent; + char *cat; + char *str; + + tpage = TASK_PAGE (page); + priv = tpage->priv; + + /* Summary. */ + + str = e_dialog_editable_get (priv->summary); + if (!str || strlen (str) == 0) + cal_component_set_summary (comp, NULL); + else { + CalComponentText text; + + text.value = str; + text.altrep = NULL; + + cal_component_set_summary (comp, &text); + } + + if (str) + g_free (str); + + /* Description */ + + str = e_dialog_editable_get (priv->description); + if (!str || strlen (str) == 0) + cal_component_set_description_list (comp, NULL); + else { + GSList l; + CalComponentText text; + + text.value = str; + text.altrep = NULL; + l.data = &text; + l.next = NULL; + + cal_component_set_description_list (comp, &l); + } + + if (!str) + g_free (str); + + /* Dates */ + + date.value = g_new (struct icaltimetype, 1); + date.tzid = NULL; + + /* Due Date. */ + t = e_date_edit_get_time (E_DATE_EDIT (priv->due_date)); + if (t != -1) { + *date.value = icaltime_from_timet (t, FALSE); + cal_component_set_due (comp, &date); + } else { + cal_component_set_due (comp, NULL); + } + + /* Start Date. */ + t = e_date_edit_get_time (E_DATE_EDIT (priv->start_date)); + if (t != -1) { + *date.value = icaltime_from_timet (t, FALSE); + cal_component_set_dtstart (comp, &date); + } else { + cal_component_set_dtstart (comp, NULL); + } + + /* Percent Complete. */ + percent = e_dialog_spin_get_int (priv->percent_complete); + cal_component_set_percent (comp, &percent); + + /* Status. */ + status = e_dialog_option_menu_get (priv->status, status_map); + cal_component_set_status (comp, status); + + /* Priority. */ + priority = e_dialog_option_menu_get (priv->priority, priority_map); + priority_value = priority_index_to_value (priority); + cal_component_set_priority (comp, &priority_value); + + /* Classification. */ + cal_component_set_classification (comp, classification_get (priv->classification_public)); + + /* Categories */ + cat = e_dialog_editable_get (priv->categories); + cal_component_set_categories (comp, cat); + + if (cat) + g_free (cat); +} + +/* set_summary handler for the task page */ +static void +task_page_set_summary (CompEditorPage *page, const char *summary) +{ + TaskPage *tpage; + TaskPagePrivate *priv; + + tpage = TASK_PAGE (page); + priv = tpage->priv; + + gtk_signal_handler_block_by_data (GTK_OBJECT (priv->summary), tpage); + e_utf8_gtk_entry_set_text (GTK_ENTRY (priv->summary), summary); + gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->summary), tpage); +} + +static void +task_page_set_dates (CompEditorPage *page, CompEditorPageDates *dates) +{ + TaskPage *tpage; + TaskPagePrivate *priv; + + tpage = TASK_PAGE (page); + priv = tpage->priv; + + priv->updating = TRUE; + + if (dates->complete != 0) { + if (dates->complete == -1) { + /* If the 'Completed Date' is set to 'None', + we set the status to 'Not Started' and the + percent-complete to 0. The task may + actually be partially-complete, but we + leave it to the user to set those + fields. */ + e_dialog_option_menu_set (priv->status, + ICAL_STATUS_NEEDSACTION, + status_map); + e_dialog_spin_set (priv->percent_complete, 0); + } else { + e_dialog_option_menu_set (priv->status, + ICAL_STATUS_COMPLETED, + status_map); + e_dialog_spin_set (priv->percent_complete, 100); + } + } + + priv->updating = FALSE; +} + + + +/* Gets the widgets from the XML file and returns if they are all available. */ +static gboolean +get_widgets (TaskPage *tpage) +{ + TaskPagePrivate *priv; + + priv = tpage->priv; + +#define GW(name) glade_xml_get_widget (priv->xml, name) + + priv->main = GW ("task-page"); + g_assert (priv->main); + gtk_widget_ref (priv->main); + gtk_widget_unparent (priv->main); + + priv->summary = GW ("summary"); + + priv->due_date = GW ("due-date"); + priv->start_date = GW ("start-date"); + + priv->percent_complete = GW ("percent-complete"); + + priv->status = GW ("status"); + priv->priority = GW ("priority"); + + priv->description = GW ("description"); + + priv->classification_public = GW ("classification-public"); + priv->classification_private = GW ("classification-private"); + priv->classification_confidential = GW ("classification-confidential"); + + priv->contacts_btn = GW ("contacts-button"); + priv->contacts = GW ("contacts"); + + priv->categories_btn = GW ("categories-button"); + priv->categories = GW ("categories"); + +#undef GW + + return (priv->summary + && priv->due_date + && priv->start_date + && priv->percent_complete + && priv->status + && priv->priority + && priv->classification_public + && priv->classification_private + && priv->classification_confidential + && priv->description + && priv->contacts_btn + && priv->contacts + && priv->categories_btn + && priv->categories); +} + +/* Callback used when the summary changes; we emit the notification signal. */ +static void +summary_changed_cb (GtkEditable *editable, gpointer data) +{ + TaskPage *tpage; + TaskPagePrivate *priv; + gchar *summary; + + tpage = TASK_PAGE (data); + priv = tpage->priv; + + if (priv->updating) + return; + + summary = gtk_editable_get_chars (editable, 0, -1); + comp_editor_page_notify_summary_changed (COMP_EDITOR_PAGE (tpage), + summary); + g_free (summary); +} + +/* Callback used when the start or end date widgets change. We check that the + * start date < end date and we set the "all day task" button as appropriate. + */ +static void +date_changed_cb (EDateEdit *dedit, gpointer data) +{ + TaskPage *tpage; + TaskPagePrivate *priv; + CompEditorPageDates dates; + + tpage = TASK_PAGE (data); + priv = tpage->priv; + + if (priv->updating) + return; + + dates.start = e_date_edit_get_time (E_DATE_EDIT (priv->start_date)); + dates.end = 0; + dates.due = e_date_edit_get_time (E_DATE_EDIT (priv->due_date)); + dates.complete = 0; + + /* Notify upstream */ + comp_editor_page_notify_dates_changed (COMP_EDITOR_PAGE (tpage), + &dates); +} + +/* Callback used when the categories button is clicked; we must bring up the + * category list dialog. + */ +static void +categories_clicked_cb (GtkWidget *button, gpointer data) +{ + TaskPage *tpage; + TaskPagePrivate *priv; + char *categories; + GnomeDialog *dialog; + int result; + GtkWidget *entry; + + tpage = TASK_PAGE (data); + priv = tpage->priv; + + entry = priv->categories; + categories = e_utf8_gtk_entry_get_text (GTK_ENTRY (entry)); + + dialog = GNOME_DIALOG (e_categories_new (categories)); + result = gnome_dialog_run (dialog); + g_free (categories); + + if (result == 0) { + gtk_object_get (GTK_OBJECT (dialog), + "categories", &categories, + NULL); + e_utf8_gtk_entry_set_text (GTK_ENTRY (entry), categories); + g_free (categories); + } + + gtk_object_destroy (GTK_OBJECT (dialog)); +} + +/* This is called when any field is changed; it notifies upstream. */ +static void +field_changed_cb (GtkWidget *widget, gpointer data) +{ + TaskPage *tpage; + TaskPagePrivate *priv; + + tpage = TASK_PAGE (data); + priv = tpage->priv; + + if (!priv->updating) + comp_editor_page_notify_changed (COMP_EDITOR_PAGE (tpage)); +} + +static void +complete_date_changed (TaskPage *tpage, time_t complete) +{ + TaskPagePrivate *priv; + CompEditorPageDates dates; + + priv = tpage->priv; + + if (priv->updating) + return; + + dates.start = 0; + dates.end = 0; + dates.due = 0; + dates.complete = complete; + + /* Notify upstream */ + comp_editor_page_notify_dates_changed (COMP_EDITOR_PAGE (tpage), + &dates); +} + +static void +status_changed (GtkMenu *menu, TaskPage *tpage) +{ + TaskPagePrivate *priv; + icalproperty_status status; + + priv = tpage->priv; + + if (priv->updating) + return; + + status = e_dialog_option_menu_get (priv->status, status_map); + if (status == ICAL_STATUS_NEEDSACTION) { + e_dialog_spin_set (priv->percent_complete, 0); + complete_date_changed (tpage, -1); + } else if (status == ICAL_STATUS_INPROCESS) { + e_dialog_spin_set (priv->percent_complete, 50); + complete_date_changed (tpage, -1); + } else if (status == ICAL_STATUS_COMPLETED) { + e_dialog_spin_set (priv->percent_complete, 100); + complete_date_changed (tpage, time (NULL)); + } + + comp_editor_page_notify_changed (COMP_EDITOR_PAGE (tpage)); +} + +static void +percent_complete_changed (GtkAdjustment *adj, TaskPage *tpage) +{ + TaskPagePrivate *priv; + gint percent; + icalproperty_status status; + time_t date_completed; + + priv = tpage->priv; + + if (priv->updating) + return; + + percent = e_dialog_spin_get_int (priv->percent_complete); + if (percent == 100) { + date_completed = time (NULL); + status = ICAL_STATUS_COMPLETED; + } else { + date_completed = -1; + + if (percent == 0) + status = ICAL_STATUS_NEEDSACTION; + else + status = ICAL_STATUS_INPROCESS; + } + + complete_date_changed (tpage, date_completed); + e_dialog_option_menu_set (priv->status, status, status_map); + + comp_editor_page_notify_changed (COMP_EDITOR_PAGE (tpage)); +} + + +/* Hooks the widget signals */ +static void +init_widgets (TaskPage *tpage) +{ + TaskPagePrivate *priv; + + priv = tpage->priv; + + + /* Summary */ + gtk_signal_connect (GTK_OBJECT (priv->summary), "changed", + GTK_SIGNAL_FUNC (summary_changed_cb), tpage); + + /* Dates */ + gtk_signal_connect (GTK_OBJECT (priv->start_date), "changed", + GTK_SIGNAL_FUNC (date_changed_cb), tpage); + gtk_signal_connect (GTK_OBJECT (priv->due_date), "changed", + GTK_SIGNAL_FUNC (date_changed_cb), tpage); + + /* Connect signals. The Status, Percent Complete & Date Completed + properties are closely related so whenever one changes we may need + to update the other 2. */ + gtk_signal_connect (GTK_OBJECT (GTK_OPTION_MENU (priv->status)->menu), + "deactivate", + GTK_SIGNAL_FUNC (status_changed), tpage); + + gtk_signal_connect (GTK_OBJECT (GTK_SPIN_BUTTON (priv->percent_complete)->adjustment), + "value_changed", + GTK_SIGNAL_FUNC (percent_complete_changed), tpage); + + /* Classification */ + gtk_signal_connect (GTK_OBJECT (priv->description), "changed", + GTK_SIGNAL_FUNC (field_changed_cb), tpage); + gtk_signal_connect (GTK_OBJECT (priv->classification_public), + "toggled", + GTK_SIGNAL_FUNC (field_changed_cb), tpage); + gtk_signal_connect (GTK_OBJECT (priv->classification_private), + "toggled", + GTK_SIGNAL_FUNC (field_changed_cb), tpage); + gtk_signal_connect (GTK_OBJECT (priv->classification_confidential), + "toggled", + GTK_SIGNAL_FUNC (field_changed_cb), tpage); + + /* Connect the default signal handler to use to make sure the "changed" + field gets set whenever a field is changed. */ + gtk_signal_connect (GTK_OBJECT (GTK_OPTION_MENU (priv->priority)->menu), + "deactivate", + GTK_SIGNAL_FUNC (field_changed_cb), tpage); + gtk_signal_connect (GTK_OBJECT (priv->description), "changed", + GTK_SIGNAL_FUNC (field_changed_cb), tpage); + gtk_signal_connect (GTK_OBJECT (priv->contacts), "changed", + GTK_SIGNAL_FUNC (field_changed_cb), tpage); + gtk_signal_connect (GTK_OBJECT (priv->categories), "changed", + GTK_SIGNAL_FUNC (field_changed_cb), tpage); + + /* Button clicks */ + gtk_signal_connect (GTK_OBJECT (priv->categories_btn), "clicked", + GTK_SIGNAL_FUNC (categories_clicked_cb), tpage); + + /* FIXME: we do not support these fields yet, so we disable them */ + + gtk_widget_set_sensitive (priv->contacts_btn, FALSE); + gtk_widget_set_sensitive (priv->contacts, FALSE); +} + + + +/** + * task_page_construct: + * @tpage: An task page. + * + * Constructs an task page by loading its Glade data. + * + * Return value: The same object as @tpage, or NULL if the widgets could not be + * created. + **/ +TaskPage * +task_page_construct (TaskPage *tpage) +{ + TaskPagePrivate *priv; + + priv = tpage->priv; + + priv->xml = glade_xml_new (EVOLUTION_GLADEDIR "/task-page.glade", + NULL); + if (!priv->xml) { + g_message ("task_page_construct(): " + "Could not load the Glade XML file!"); + return NULL; + } + + if (!get_widgets (tpage)) { + g_message ("task_page_construct(): " + "Could not find all widgets in the XML file!"); + return NULL; + } + + init_widgets (tpage); + + return tpage; +} + +/** + * task_page_new: + * + * Creates a new task page. + * + * Return value: A newly-created task page, or NULL if the page could + * not be created. + **/ +TaskPage * +task_page_new (void) +{ + TaskPage *tpage; + + tpage = gtk_type_new (TYPE_TASK_PAGE); + if (!task_page_construct (tpage)) { + gtk_object_unref (GTK_OBJECT (tpage)); + return NULL; + } + + return tpage; +} + +GtkWidget *task_page_create_date_edit (void); + +GtkWidget * +task_page_create_date_edit (void) +{ + GtkWidget *dedit; + + dedit = date_edit_new (TRUE, TRUE); + e_date_edit_set_allow_no_date_set (E_DATE_EDIT (dedit), TRUE); + + return dedit; +} diff --git a/calendar/gui/dialogs/task-page.glade b/calendar/gui/dialogs/task-page.glade index e9f0d4700d..b6182cd860 100644 --- a/calendar/gui/dialogs/task-page.glade +++ b/calendar/gui/dialogs/task-page.glade @@ -15,6 +15,7 @@ GtkWindow task-toplevel + False window1 GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE @@ -184,10 +185,10 @@ Custom due-date - task_editor_create_date_edit + task_page_create_date_edit 0 0 - Sun, 10 Sep 2000 17:32:18 GMT + Fri, 01 Jun 2001 18:59:52 GMT 1 2 @@ -207,10 +208,10 @@ Custom start-date - task_editor_create_date_edit + task_page_create_date_edit 0 0 - Sun, 10 Sep 2000 17:33:31 GMT + Fri, 01 Jun 2001 18:59:57 GMT 1 2 @@ -239,7 +240,7 @@ GTK_UPDATE_CONTINUOUS 0 - False + True True @@ -459,7 +460,7 @@ Undefined 2 0 - True + False True @@ -467,7 +468,6 @@ Undefined GtkButton contacts-button True - GTK_RELIEF_NORMAL 0 False @@ -506,7 +506,6 @@ Undefined GtkButton categories-button True - GTK_RELIEF_NORMAL 0 False diff --git a/calendar/gui/dialogs/task-page.h b/calendar/gui/dialogs/task-page.h new file mode 100644 index 0000000000..cc56892c5b --- /dev/null +++ b/calendar/gui/dialogs/task-page.h @@ -0,0 +1,61 @@ +/* Evolution calendar - Main page of the task editor dialog + * + * Copyright (C) 2001 Ximian, Inc. + * + * Authors: Federico Mena-Quintero + * Miguel de Icaza + * Seth Alves + * JP Rosevear + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef TASK_PAGE_H +#define TASK_PAGE_H + +#include "comp-editor-page.h" + +BEGIN_GNOME_DECLS + + + +#define TYPE_TASK_PAGE (task_page_get_type ()) +#define TASK_PAGE(obj) (GTK_CHECK_CAST ((obj), TYPE_TASK_PAGE, TaskPage)) +#define TASK_PAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_TASK_PAGE, TaskPageClass)) +#define IS_TASK_PAGE(obj) (GTK_CHECK_TYPE ((obj), TYPE_TASK_PAGE)) +#define IS_TASK_PAGE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), TYPE_TASK_PAGE)) + +typedef struct _TaskPagePrivate TaskPagePrivate; + +typedef struct { + CompEditorPage page; + + /* Private data */ + TaskPagePrivate *priv; +} TaskPage; + +typedef struct { + CompEditorPageClass parent_class; +} TaskPageClass; + +GtkType task_page_get_type (void); +TaskPage *task_page_construct (TaskPage *epage); +TaskPage *task_page_new (void); + + + +END_GNOME_DECLS + +#endif -- cgit v1.2.3