aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/gui/event-editor.c
diff options
context:
space:
mode:
Diffstat (limited to 'calendar/gui/event-editor.c')
-rw-r--r--calendar/gui/event-editor.c373
1 files changed, 302 insertions, 71 deletions
diff --git a/calendar/gui/event-editor.c b/calendar/gui/event-editor.c
index 2df6d8ebf7..5082db36cc 100644
--- a/calendar/gui/event-editor.c
+++ b/calendar/gui/event-editor.c
@@ -40,7 +40,9 @@ typedef struct {
/* UI handler */
BonoboUIHandler *uih;
- /* Calendar object we are editing */
+ /* Calendar object we are editing; this is an internal copy and is not
+ * one of the read-only objects from the parent calendar.
+ */
iCalObject *ico;
/* Widgets from the Glade file */
@@ -114,6 +116,12 @@ typedef struct {
+/* Signal IDs */
+enum {
+ ICAL_OBJECT_RELEASED,
+ LAST_SIGNAL
+};
+
static void event_editor_class_init (EventEditorClass *class);
static void event_editor_init (EventEditor *ee);
static void event_editor_destroy (GtkObject *object);
@@ -137,6 +145,8 @@ static void recurrence_exception_added (GtkWidget *widget, EventEditor *ee);
static void recurrence_exception_deleted (GtkWidget *widget, EventEditor *ee);
static void recurrence_exception_changed (GtkWidget *widget, EventEditor *ee);
+static guint event_editor_signals[LAST_SIGNAL];
+
/**
@@ -181,6 +191,17 @@ event_editor_class_init (EventEditorClass *class)
parent_class = gtk_type_class (gnome_app_get_type ());
+ event_editor_signals[ICAL_OBJECT_RELEASED] =
+ gtk_signal_new ("ical_object_released",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EventEditorClass, ical_object_released),
+ gtk_marshal_NONE__STRING,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ gtk_object_class_add_signals (object_class, event_editor_signals, LAST_SIGNAL);
+
object_class->destroy = event_editor_destroy;
}
@@ -207,11 +228,21 @@ event_editor_destroy (GtkObject *object)
ee = EVENT_EDITOR (object);
priv = ee->priv;
+ if (priv->ico) {
+ gtk_signal_emit (GTK_OBJECT (ee), event_editor_signals[ICAL_OBJECT_RELEASED],
+ priv->ico->uid);
+ ical_object_unref (priv->ico);
+ priv->ico = NULL;
+ }
+
if (priv->xml) {
gtk_object_unref (GTK_OBJECT (priv->xml));
priv->xml = NULL;
}
+ bonobo_object_unref (BONOBO_OBJECT (priv->uih));
+ priv->uih = NULL;
+
if (GTK_OBJECT_CLASS (parent_class)->destroy)
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}
@@ -222,6 +253,9 @@ make_title_from_ico (iCalObject *ico)
{
const char *summary;
+ if (!ico)
+ return g_strdup (_("Edit Appointment"));
+
if (ico->summary)
summary = ico->summary;
else
@@ -436,22 +470,43 @@ recur_options_get (GtkWidget *widget)
static const int month_pos_map[] = { 0, 1, 2, 3, 4, -1 };
static const int weekday_map[] = { 0, 1, 2, 3, 4, 5, 6, -1 };
-/* Initializes the widget's values and signals */
+/* Frees the rows and the row data in the recurrence exceptions GtkCList */
static void
-init_widgets (EventEditor *ee)
+free_exception_clist_data (GtkCList *clist)
{
+ int i;
+
+ 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);
+}
+
+/* Callback used when the exception date GtkCList is destroyed */
+static void
+exception_clist_destroyed (GtkObject *object, gpointer data)
+{
+ EventEditor *ee;
EventEditorPrivate *priv;
- GList *list;
+ ee = EVENT_EDITOR (data);
priv = ee->priv;
- /* Owner, summary */
+ free_exception_clist_data (GTK_CLIST (priv->recurrence_exceptions_list));
+}
- e_dialog_editable_set (priv->general_owner,
- priv->ico->organizer->addr ?
- priv->ico->organizer->addr : _("?"));
+/* Hooks the widget signals */
+static void
+init_widgets (EventEditor *ee)
+{
+ EventEditorPrivate *priv;
- e_dialog_editable_set (priv->general_summary, priv->ico->summary);
+ priv = ee->priv;
/* Start and end times */
@@ -465,24 +520,11 @@ init_widgets (EventEditor *ee)
gtk_signal_connect (GTK_OBJECT (priv->end_time), "time_changed",
GTK_SIGNAL_FUNC (check_times), ee);
- e_dialog_dateedit_set (priv->start_time, priv->ico->dtstart);
- e_dialog_dateedit_set (priv->end_time, priv->ico->dtend);
-
- check_all_day (ee);
-
gtk_signal_connect (GTK_OBJECT (priv->all_day_event), "toggled",
GTK_SIGNAL_FUNC (set_all_day), ee);
/* Alarms */
- e_dialog_toggle_set (priv->alarm_display, priv->ico->dalarm.enabled);
- e_dialog_toggle_set (priv->alarm_program, priv->ico->palarm.enabled);
- e_dialog_toggle_set (priv->alarm_audio, priv->ico->aalarm.enabled);
- e_dialog_toggle_set (priv->alarm_mail, priv->ico->malarm.enabled);
- alarm_toggle (priv->alarm_display, ee);
- alarm_toggle (priv->alarm_program, ee);
- alarm_toggle (priv->alarm_audio, ee);
- alarm_toggle (priv->alarm_mail, ee);
gtk_signal_connect (GTK_OBJECT (priv->alarm_display), "toggled",
GTK_SIGNAL_FUNC (alarm_toggle), ee);
gtk_signal_connect (GTK_OBJECT (priv->alarm_program), "toggled",
@@ -492,6 +534,165 @@ init_widgets (EventEditor *ee)
gtk_signal_connect (GTK_OBJECT (priv->alarm_mail), "toggled",
GTK_SIGNAL_FUNC (alarm_toggle), ee);
+ /* Recurrence types */
+
+ gtk_signal_connect (GTK_OBJECT (priv->recurrence_rule_none), "toggled",
+ GTK_SIGNAL_FUNC (recurrence_toggled), ee);
+ gtk_signal_connect (GTK_OBJECT (priv->recurrence_rule_daily), "toggled",
+ GTK_SIGNAL_FUNC (recurrence_toggled), ee);
+ gtk_signal_connect (GTK_OBJECT (priv->recurrence_rule_weekly), "toggled",
+ GTK_SIGNAL_FUNC (recurrence_toggled), ee);
+ gtk_signal_connect (GTK_OBJECT (priv->recurrence_rule_monthly), "toggled",
+ GTK_SIGNAL_FUNC (recurrence_toggled), ee);
+ gtk_signal_connect (GTK_OBJECT (priv->recurrence_rule_yearly), "toggled",
+ GTK_SIGNAL_FUNC (recurrence_toggled), ee);
+
+ /* Exception buttons */
+
+ gtk_signal_connect (GTK_OBJECT (priv->recurrence_exception_add), "clicked",
+ GTK_SIGNAL_FUNC (recurrence_exception_added), ee);
+ gtk_signal_connect (GTK_OBJECT (priv->recurrence_exception_delete), "clicked",
+ GTK_SIGNAL_FUNC (recurrence_exception_deleted), ee);
+ gtk_signal_connect (GTK_OBJECT (priv->recurrence_exception_change), "clicked",
+ GTK_SIGNAL_FUNC (recurrence_exception_changed), ee);
+
+ /* Exception list */
+
+ gtk_signal_connect (GTK_OBJECT (priv->recurrence_exceptions_list), "destroy",
+ GTK_SIGNAL_FUNC (exception_clist_destroyed), ee);
+}
+
+/* Fills the widgets with default values */
+static void
+clear_widgets (EventEditor *ee)
+{
+ EventEditorPrivate *priv;
+ time_t now;
+
+ priv = ee->priv;
+
+ now = time (NULL);
+
+ /* Owner, summary */
+
+ e_dialog_editable_set (priv->general_owner, _("?"));
+ e_dialog_editable_set (priv->general_summary, NULL);
+
+ /* Start and end times */
+
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->start_time), ee);
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->end_time), ee);
+
+ e_dialog_dateedit_set (priv->start_time, now);
+ e_dialog_dateedit_set (priv->end_time, now);
+
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time), ee);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time), ee);
+
+ check_all_day (ee);
+
+ /* Alarms */
+
+ /* FIXMe: these should use configurable defaults */
+
+ e_dialog_toggle_set (priv->alarm_display, FALSE);
+ e_dialog_toggle_set (priv->alarm_program, FALSE);
+ e_dialog_toggle_set (priv->alarm_audio, FALSE);
+ e_dialog_toggle_set (priv->alarm_mail, FALSE);
+
+ e_dialog_spin_set (priv->alarm_display_amount, 15);
+ e_dialog_spin_set (priv->alarm_audio_amount, 15);
+ e_dialog_spin_set (priv->alarm_program_amount, 15);
+ e_dialog_spin_set (priv->alarm_mail_amount, 15);
+
+ alarm_unit_set (priv->alarm_display_unit, ALARM_MINUTES);
+ alarm_unit_set (priv->alarm_audio_unit, ALARM_MINUTES);
+ alarm_unit_set (priv->alarm_program_unit, ALARM_MINUTES);
+ alarm_unit_set (priv->alarm_mail_unit, ALARM_MINUTES);
+
+ e_dialog_editable_set (priv->alarm_program_run_program_entry, NULL);
+ e_dialog_editable_set (priv->alarm_mail_mail_to, NULL);
+
+ /* Classification */
+
+ e_dialog_radio_set (priv->classification_radio, CLASSIFICATION_PRIVATE, classification_map);
+
+ /* Recurrences */
+
+ e_dialog_radio_set (priv->recurrence_rule_none, RECUR_OPTION_NONE, recur_options_map);
+
+ e_dialog_spin_set (priv->recurrence_rule_daily_days, 1);
+
+ e_dialog_spin_set (priv->recurrence_rule_weekly_weeks, 1);
+ e_dialog_toggle_set (priv->recurrence_rule_weekly_sun, FALSE);
+ e_dialog_toggle_set (priv->recurrence_rule_weekly_mon, FALSE);
+ e_dialog_toggle_set (priv->recurrence_rule_weekly_tue, FALSE);
+ e_dialog_toggle_set (priv->recurrence_rule_weekly_wed, FALSE);
+ e_dialog_toggle_set (priv->recurrence_rule_weekly_thu, FALSE);
+ e_dialog_toggle_set (priv->recurrence_rule_weekly_fri, FALSE);
+ e_dialog_toggle_set (priv->recurrence_rule_weekly_sat, FALSE);
+
+ e_dialog_toggle_set (priv->recurrence_rule_monthly_on_day, TRUE);
+ e_dialog_spin_set (priv->recurrence_rule_monthly_day_nth, 1);
+ e_dialog_spin_set (priv->recurrence_rule_monthly_every_n_months, 1);
+ e_dialog_option_menu_set (priv->recurrence_rule_monthly_week, 0, month_pos_map);
+ e_dialog_option_menu_set (priv->recurrence_rule_monthly_weekpos, 0, weekday_map);
+ e_dialog_spin_set (priv->recurrence_rule_monthly_every_n_months, 1);
+
+ e_dialog_spin_set (priv->recurrence_rule_yearly_every_n_years, 1);
+
+ e_dialog_toggle_set (priv->recurrence_ending_date_repeat_forever, TRUE);
+ e_dialog_spin_set (priv->recurrence_ending_date_end_after_count, 1);
+ e_dialog_dateedit_set (priv->recurrence_ending_date_end_on_date,
+ time_add_day (time (NULL), 1));
+
+ /* Exceptions list */
+
+ free_exception_clist_data (GTK_CLIST (priv->recurrence_exceptions_list));
+}
+
+/* Fills in the widgets with the proper values */
+static void
+fill_widgets (EventEditor *ee)
+{
+ EventEditorPrivate *priv;
+ GList *list;
+
+ priv = ee->priv;
+
+ clear_widgets (ee);
+
+ if (!priv->ico)
+ return;
+
+ /* Owner, summary */
+
+ e_dialog_editable_set (priv->general_owner,
+ priv->ico->organizer->addr ?
+ priv->ico->organizer->addr : _("?"));
+
+ e_dialog_editable_set (priv->general_summary, priv->ico->summary);
+
+ /* Start and end times */
+
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->start_time), ee);
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->end_time), ee);
+
+ e_dialog_dateedit_set (priv->start_time, priv->ico->dtstart);
+ e_dialog_dateedit_set (priv->end_time, priv->ico->dtend);
+
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time), ee);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time), ee);
+
+ check_all_day (ee);
+
+ /* Alarms */
+
+ e_dialog_toggle_set (priv->alarm_display, priv->ico->dalarm.enabled);
+ e_dialog_toggle_set (priv->alarm_program, priv->ico->palarm.enabled);
+ e_dialog_toggle_set (priv->alarm_audio, priv->ico->aalarm.enabled);
+ e_dialog_toggle_set (priv->alarm_mail, priv->ico->malarm.enabled);
+
/* Alarm data */
e_dialog_spin_set (priv->alarm_display_amount, priv->ico->dalarm.count);
@@ -519,28 +720,14 @@ init_widgets (EventEditor *ee)
e_dialog_radio_set (priv->classification_radio, CLASSIFICATION_CONFIDENTIAL,
classification_map);
else {
- /* What do do? */
+ /* What do do? We can't g_assert_not_reached() since it is a
+ * value from an external file.
+ */
}
- /* Recurrence types */
-
- gtk_signal_connect (GTK_OBJECT (priv->recurrence_rule_none), "toggled",
- GTK_SIGNAL_FUNC (recurrence_toggled), ee);
- gtk_signal_connect (GTK_OBJECT (priv->recurrence_rule_daily), "toggled",
- GTK_SIGNAL_FUNC (recurrence_toggled), ee);
- gtk_signal_connect (GTK_OBJECT (priv->recurrence_rule_weekly), "toggled",
- GTK_SIGNAL_FUNC (recurrence_toggled), ee);
- gtk_signal_connect (GTK_OBJECT (priv->recurrence_rule_monthly), "toggled",
- GTK_SIGNAL_FUNC (recurrence_toggled), ee);
- gtk_signal_connect (GTK_OBJECT (priv->recurrence_rule_yearly), "toggled",
- GTK_SIGNAL_FUNC (recurrence_toggled), ee);
-
- /* Recurrence rules */
+ /* Recurrences */
- if (!priv->ico->recur)
- e_dialog_radio_set (priv->recurrence_rule_none, RECUR_OPTION_NONE,
- recur_options_map);
- else {
+ if (priv->ico->recur) {
switch (priv->ico->recur->type) {
case RECUR_DAILY:
e_dialog_radio_set (priv->recurrence_rule_daily, RECUR_OPTION_DAILY,
@@ -619,21 +806,12 @@ init_widgets (EventEditor *ee)
} else {
e_dialog_toggle_set (priv->recurrence_ending_date_end_on, TRUE);
/* Shorten by one day, as we store end-on date a day ahead */
- /* FIX ME is this correct? */
+ /* FIXME is this correct? */
e_dialog_dateedit_set (priv->recurrence_ending_date_end_on_date,
time_add_day (priv->ico->recur->enddate, -1));
}
}
- /* Exception buttons */
-
- gtk_signal_connect (GTK_OBJECT (priv->recurrence_exception_add), "clicked",
- GTK_SIGNAL_FUNC (recurrence_exception_added), ee);
- gtk_signal_connect (GTK_OBJECT (priv->recurrence_exception_delete), "clicked",
- GTK_SIGNAL_FUNC (recurrence_exception_deleted), ee);
- gtk_signal_connect (GTK_OBJECT (priv->recurrence_exception_change), "clicked",
- GTK_SIGNAL_FUNC (recurrence_exception_changed), ee);
-
/* Exceptions list */
for (list = priv->ico->exdate; list; list = list->next)
@@ -874,11 +1052,22 @@ create_toolbar (EventEditor *ee)
gtk_toolbar_set_style (GTK_TOOLBAR (child), GTK_TOOLBAR_ICONS);
}
+/**
+ * event_editor_construct:
+ * @ee: An event editor.
+ * @gcal: Calendar that this event editor will operate on.
+ *
+ * Constructs an event editor by binding it to the specified calendar and creating
+ * its widgets.
+ *
+ * Return value: The same object as @ee, or NULL if the widgets could not be
+ * created. In the latter case, the event editor will automatically be
+ * destroyed.
+ **/
GtkWidget *
-event_editor_construct (EventEditor *ee, GnomeCalendar *gcal, iCalObject *ico)
+event_editor_construct (EventEditor *ee, GnomeCalendar *gcal)
{
EventEditorPrivate *priv;
- char *title;
GtkWidget *toplevel;
GtkWidget *contents;
@@ -886,8 +1075,6 @@ event_editor_construct (EventEditor *ee, GnomeCalendar *gcal, iCalObject *ico)
g_return_val_if_fail (IS_EVENT_EDITOR (ee), NULL);
g_return_val_if_fail (gcal != NULL, NULL);
g_return_val_if_fail (GNOME_IS_CALENDAR (gcal), NULL);
- g_return_val_if_fail (ico != NULL, NULL);
- g_return_val_if_fail (ico->uid != NULL, NULL);
priv = ee->priv;
@@ -907,7 +1094,6 @@ event_editor_construct (EventEditor *ee, GnomeCalendar *gcal, iCalObject *ico)
}
priv->gcal = gcal;
- priv->ico = ico;
if (!get_widgets (ee)) {
g_message ("event_editor_construct(): Could not find all widgets in the XML file!");
@@ -922,11 +1108,7 @@ event_editor_construct (EventEditor *ee, GnomeCalendar *gcal, iCalObject *ico)
/* Construct the app */
- title = make_title_from_ico (ico);
- gnome_app_construct (GNOME_APP (ee), "event-editor", title);
- g_free (title);
-
- /* Create the UI handler */
+ gnome_app_construct (GNOME_APP (ee), "event-editor", N_("Edit Appointment"));
priv->uih = bonobo_ui_handler_new ();
if (!priv->uih) {
@@ -953,24 +1135,63 @@ event_editor_construct (EventEditor *ee, GnomeCalendar *gcal, iCalObject *ico)
return NULL;
}
+/**
+ * event_editor_new:
+ * @gcal: Calendar that this event editor will operate on.
+ *
+ * Creates a new event editor dialog.
+ *
+ * Return value: A newly-created event editor dialog, or NULL if the event
+ * editor could not be created.
+ **/
GtkWidget *
-event_editor_new (GnomeCalendar *gcal, iCalObject *ico)
+event_editor_new (GnomeCalendar *gcal)
{
GtkWidget *ee;
g_return_val_if_fail (gcal != NULL, NULL);
g_return_val_if_fail (GNOME_IS_CALENDAR (gcal), NULL);
- g_return_val_if_fail (ico != NULL, NULL);
- g_return_val_if_fail (ico->uid != NULL, NULL);
ee = GTK_WIDGET (gtk_type_new (TYPE_EVENT_EDITOR));
+ return event_editor_construct (EVENT_EDITOR (ee), gcal);
+}
+
+/**
+ * event_editor_set_ical_object:
+ * @ee: An event editor.
+ * @ico: A calendar object.
+ *
+ * Sets the calendar object that an event editor dialog will manipulate.
+ **/
+void
+event_editor_set_ical_object (EventEditor *ee, iCalObject *ico)
+{
+ EventEditorPrivate *priv;
+ char *title;
+
+ g_return_if_fail (ee != NULL);
+ g_return_if_fail (IS_EVENT_EDITOR (ee));
+
+ if (ico)
+ g_return_if_fail (ico->uid != NULL);
+
+ priv = ee->priv;
+
+ if (priv->ico) {
+ gtk_signal_emit (GTK_OBJECT (ee), event_editor_signals[ICAL_OBJECT_RELEASED],
+ priv->ico->uid);
+ ical_object_unref (priv->ico);
+ priv->ico = NULL;
+ }
- ee = event_editor_construct (EVENT_EDITOR (ee), gcal, ico);
+ if (ico)
+ priv->ico = ical_object_duplicate (ico);
- if (ee)
- gtk_widget_show (ee);
+ title = make_title_from_ico (priv->ico);
+ gtk_window_set_title (GTK_WINDOW (ee), title);
+ g_free (title);
- return ee;
+ fill_widgets (ee);
}
#if 0
@@ -1328,13 +1549,19 @@ check_dates (GnomeDateEdit *gde, EventEditor *ee)
tm_end.tm_mon = tm_start.tm_mon;
tm_end.tm_mday = tm_start.tm_mday;
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->end_time), ee);
e_dialog_dateedit_set (priv->end_time, mktime (&tm_end));
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time), ee);
} else if (GTK_WIDGET (gde) == priv->end_time) {
tm_start.tm_year = tm_end.tm_year;
tm_start.tm_mon = tm_end.tm_mon;
tm_start.tm_mday = tm_end.tm_mday;
-/* e_dialog_dateedit_set (priv->start_time, mktime (&tm_start)); */
+#if 0
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->start_time), ee);
+ e_dialog_dateedit_set (priv->start_time, mktime (&tm_start));
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time), ee);
+#endif
}
}
}
@@ -1351,10 +1578,10 @@ check_times (GnomeDateEdit *gde, EventEditor *ee)
struct tm tm_start, tm_end;
priv = ee->priv;
-
+#if 0
gdk_pointer_ungrab (GDK_CURRENT_TIME);
gdk_flush ();
-
+#endif
start = e_dialog_dateedit_get (priv->start_time);
end = e_dialog_dateedit_get (priv->end_time);
@@ -1373,7 +1600,9 @@ check_times (GnomeDateEdit *gde, EventEditor *ee)
tm_end.tm_sec = 0;
}
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->end_time), ee);
e_dialog_dateedit_set (priv->end_time, mktime (&tm_end));
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time), ee);
} else if (GTK_WIDGET (gde) == priv->end_time) {
tm_start.tm_min = tm_end.tm_min;
tm_start.tm_sec = tm_end.tm_sec;
@@ -1385,7 +1614,9 @@ check_times (GnomeDateEdit *gde, EventEditor *ee)
tm_start.tm_min = 0;
}
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->start_time), ee);
e_dialog_dateedit_set (priv->start_time, mktime (&tm_start));
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time), ee);
}
}