/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 2 -*- */ /* * gcal-event-view.c * Copyright (C) 2012 Erick Pérez Castellanos * * gnome-calendar 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 3 of the License, or * (at your option) any later version. * * gnome-calendar 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, see . */ #include "gcal-event-view.h" #include "gcal-editable-entry.h" #include "gcal-editable-text.h" #include "gcal-editable-date.h" #include "gcal-editable-combo.h" #include "gcal-editable-reminder.h" #include struct _GcalEventViewPrivate { GcalEditableMode edit_mode; gchar *source_uid; gchar *event_uid; GSList *e_widgets; GtkWidget *e_what; GtkWidget *e_host; GtkWidget *d_when; GtkWidget *e_where; GtkWidget *cb_cal; GtkWidget *t_desc; GtkWidget *reminders; GtkWidget *attending_yes; GtkWidget *attending_maybe; GtkWidget *attending_no; GtkWidget *delete_button; GcalManager *manager; }; enum { WILL_DELETE = 1, NUM_SIGNALS }; static guint signals[NUM_SIGNALS] = { 0, }; static void gcal_event_view_constructed (GObject *object); static void gcal_event_view_finalize (GObject *object); static void gcal_event_view_set_combo_box (GcalEventView *view); static void gcal_event_view_update (GcalEventView *view); static void gcal_event_view_delete_event (GtkWidget *button, gpointer user_data); G_DEFINE_TYPE(GcalEventView, gcal_event_view, GTK_TYPE_GRID) static void gcal_event_view_class_init(GcalEventViewClass *klass) { GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); object_class->constructed = gcal_event_view_constructed; object_class->finalize = gcal_event_view_finalize; signals[WILL_DELETE] = g_signal_new ("will-delete", GCAL_TYPE_EVENT_VIEW, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GcalEventViewClass, will_delete), NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); g_type_class_add_private((gpointer)klass, sizeof(GcalEventViewPrivate)); } static void gcal_event_view_init(GcalEventView *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, GCAL_TYPE_EVENT_VIEW, GcalEventViewPrivate); gtk_style_context_add_class ( gtk_widget_get_style_context (GTK_WIDGET (self)), "event-details"); } static void gcal_event_view_constructed (GObject *object) { GcalEventViewPrivate *priv; GtkWidget *what; GtkWidget *when; GtkWidget *calendar; GtkWidget *where; GtkWidget *desc; GtkWidget *rem; GtkWidget *attending; GtkWidget *attending_box; priv = GCAL_EVENT_VIEW (object)->priv; if (G_OBJECT_CLASS (gcal_event_view_parent_class)->constructed != NULL) G_OBJECT_CLASS (gcal_event_view_parent_class)->constructed (object); priv->edit_mode = GCAL_EDIT_MODE; priv->source_uid = NULL; priv->event_uid = NULL; priv->e_widgets = NULL; priv->e_what = gcal_editable_entry_new (); priv->e_widgets = g_slist_append (priv->e_widgets, priv->e_what); priv->d_when = gcal_editable_date_new (); priv->e_widgets = g_slist_append (priv->e_widgets, priv->d_when); priv->e_where = gcal_editable_entry_new (); priv->e_widgets = g_slist_append (priv->e_widgets, priv->e_where); priv->cb_cal = gcal_editable_combo_new (); priv->e_widgets = g_slist_append (priv->e_widgets, priv->cb_cal); gtk_widget_set_halign (priv->cb_cal, GTK_ALIGN_START); priv->t_desc = gcal_editable_text_new (); priv->e_widgets = g_slist_append (priv->e_widgets, priv->t_desc); priv->reminders = gcal_editable_reminder_new (); priv->e_widgets = g_slist_append (priv->e_widgets, priv->reminders); /* FIXME: do something with this to add it on the slist of widget * something like, turning all the three into on widget */ priv->attending_yes = gtk_toggle_button_new_with_label (_("Yes")); priv->attending_maybe = gtk_toggle_button_new_with_label (_("Maybe")); priv->attending_no = gtk_toggle_button_new_with_label (_("No")); attending_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL); gtk_box_set_spacing (GTK_BOX (attending_box), 2); gtk_button_box_set_layout (GTK_BUTTON_BOX (attending_box), GTK_BUTTONBOX_SPREAD); gtk_widget_set_halign (attending_box, GTK_ALIGN_START); gtk_container_add (GTK_CONTAINER (attending_box), priv->attending_yes); gtk_container_add (GTK_CONTAINER (attending_box), priv->attending_maybe); gtk_container_add (GTK_CONTAINER (attending_box), priv->attending_no); /* Building the skel grid */ what = gtk_label_new (_("What")); gtk_widget_set_halign (what, GTK_ALIGN_END); gtk_grid_attach (GTK_GRID (object), what, 0, 0, 1, 1); gtk_grid_attach (GTK_GRID (object), priv->e_what, 1, 0, 1, 1); when = gtk_label_new (_("When")); gtk_widget_set_valign (when, GTK_ALIGN_START); gtk_widget_set_halign (when, GTK_ALIGN_END); gtk_grid_attach (GTK_GRID (object), when, 0, 1, 1, 1); gtk_grid_attach (GTK_GRID (object), priv->d_when, 1, 1, 1, 1); where = gtk_label_new (_("Where")); gtk_widget_set_halign (where, GTK_ALIGN_END); gtk_grid_attach (GTK_GRID (object), where, 0, 2, 1, 1); gtk_grid_attach (GTK_GRID (object), priv->e_where, 1, 2, 1, 1); calendar = gtk_label_new (_("Calendar")); gtk_widget_set_halign (calendar, GTK_ALIGN_END); gtk_grid_attach (GTK_GRID (object), calendar, 0, 3, 1, 1); gtk_grid_attach (GTK_GRID (object), priv->cb_cal, 1, 3, 1, 1); desc = gtk_label_new (_("Description")); gtk_widget_set_halign (desc, GTK_ALIGN_END); gtk_widget_set_valign (desc, GTK_ALIGN_START); gtk_grid_attach (GTK_GRID (object), desc, 0, 4, 1, 1); gtk_grid_attach (GTK_GRID (object), priv->t_desc, 1, 4, 1, 1); rem = gtk_label_new (_("Reminders")); gtk_widget_set_halign (rem, GTK_ALIGN_END); gtk_widget_set_valign (rem, GTK_ALIGN_START); gtk_widget_set_margin_top (rem, 10); gtk_grid_attach (GTK_GRID (object), rem, 0, 5, 1, 1); gtk_grid_attach (GTK_GRID (object), priv->reminders, 1, 5, 1, 1); attending = gtk_label_new (_("Attending")); gtk_widget_set_halign (attending, GTK_ALIGN_END); gtk_grid_attach (GTK_GRID (object), attending, 0, 6, 1, 1); gtk_grid_attach (GTK_GRID (object), attending_box, 1, 6, 1, 1); priv->delete_button = gtk_button_new_with_label (_("Delete Event")); gtk_widget_set_halign (priv->delete_button, GTK_ALIGN_START); gtk_widget_set_valign (priv->delete_button, GTK_ALIGN_END); gtk_widget_set_hexpand (priv->delete_button, FALSE); gtk_grid_attach (GTK_GRID (object), priv->delete_button, 1, 7, 1, 1); g_object_set (object, "row-spacing", 12, "column-spacing", 12, NULL); gtk_widget_show_all (GTK_WIDGET (object)); gtk_widget_hide (priv->delete_button); /* Signals */ g_signal_connect (priv->delete_button, "clicked", G_CALLBACK (gcal_event_view_delete_event), object); } static void gcal_event_view_finalize (GObject *object) { GcalEventViewPrivate *priv; priv = GCAL_EVENT_VIEW (object)->priv; if (priv->source_uid != NULL) g_free (priv->source_uid); if (priv->event_uid != NULL) g_free (priv->event_uid); if (G_OBJECT_CLASS (gcal_event_view_parent_class)->finalize != NULL) G_OBJECT_CLASS (gcal_event_view_parent_class)->finalize (object); } static void gcal_event_view_set_combo_box (GcalEventView *view) { GcalEventViewPrivate *priv; priv = view->priv; gcal_editable_combo_set_model ( GCAL_EDITABLE_COMBO (priv->cb_cal), GTK_TREE_MODEL (gcal_manager_get_sources_model (priv->manager))); } /** * gcal_event_view_update: * @view: A GcalEventView widget * * Update the contents of the widget. */ static void gcal_event_view_update (GcalEventView *view) { GcalEventViewPrivate *priv; g_return_if_fail (GCAL_IS_EVENT_VIEW (view)); priv = view->priv; if (priv->event_uid == NULL) { /* Setting the widget to blank state */ g_slist_foreach (priv->e_widgets, (GFunc) gcal_editable_clear, NULL); } else { gchar *summary; gchar *when; const gchar *location; gchar *description; GList *reminders; g_slist_foreach (priv->e_widgets, (GFunc) gcal_editable_leave_edit_mode, NULL); summary = gcal_manager_get_event_summary (priv->manager, priv->source_uid, priv->event_uid); gcal_editable_entry_set_content (GCAL_EDITABLE_ENTRY (priv->e_what), summary, FALSE); when = gcal_manager_get_event_date (priv->manager, priv->source_uid, priv->event_uid); gcal_editable_date_set_content (GCAL_EDITABLE_DATE (priv->d_when), when); location = gcal_manager_get_event_location (priv->manager, priv->source_uid, priv->event_uid); gcal_editable_entry_set_content (GCAL_EDITABLE_ENTRY (priv->e_where), location, FALSE); gcal_editable_combo_set_content ( GCAL_EDITABLE_COMBO (priv->cb_cal), gcal_manager_get_source_name (priv->manager, priv->source_uid)); description = gcal_manager_get_event_description (priv->manager, priv->source_uid, priv->event_uid); gcal_editable_text_set_content (GCAL_EDITABLE_TEXT (priv->t_desc), description); reminders = gcal_manager_get_event_reminders (priv->manager, priv->source_uid, priv->event_uid); gcal_editable_reminder_set_content ( GCAL_EDITABLE_REMINDER (priv->reminders), reminders); /* since this loading is for viewing, we hide delete_button */ gtk_widget_hide (priv->delete_button); g_free (description); g_free (when); g_free (summary); g_list_free_full (reminders, (GDestroyNotify) g_free); } } static void gcal_event_view_delete_event (GtkWidget *button, gpointer user_data) { GcalEventViewPrivate *priv; gchar *event_uuid; g_return_if_fail (GCAL_IS_EVENT_VIEW (user_data)); priv = GCAL_EVENT_VIEW (user_data)->priv; event_uuid = g_strdup_printf ("%s:%s", priv->source_uid, priv->event_uid); /* Reset the widget, and let the windows it work it's done */ gcal_event_view_load_new (GCAL_EVENT_VIEW (user_data)); g_signal_emit (GCAL_EVENT_VIEW (user_data), signals[WILL_DELETE], 0, event_uuid); g_free (event_uuid); } /* Public API */ /** * gcal_event_view_new_with_manager: * @manager: A GcalManager instance, the app singleton * * Returns: (transfer full): */ GtkWidget* gcal_event_view_new_with_manager (GcalManager *manager) { GtkWidget *view; GcalEventViewPrivate *priv; view = g_object_new (GCAL_TYPE_EVENT_VIEW, NULL); priv = GCAL_EVENT_VIEW (view)->priv; priv->manager = manager; gcal_event_view_set_combo_box (GCAL_EVENT_VIEW (view)); return view; } /** * gcal_event_view_load_new: * @view: A GcalEventView widget * * Sets the widget in a edit mode for creating a new * event. */ void gcal_event_view_load_new (GcalEventView *view) { GcalEventViewPrivate *priv; g_return_if_fail (GCAL_IS_EVENT_VIEW (view)); priv = view->priv; if (priv->source_uid != NULL) g_free (priv->source_uid); if (priv->event_uid != NULL) g_free (priv->event_uid); priv->source_uid = NULL; priv->event_uid = NULL; /* Setting the widget to blank state to load a new event */ g_slist_foreach (priv->e_widgets, (GFunc) gcal_editable_clear, NULL); gcal_event_view_update (view); gcal_event_view_enter_edit_mode (view); } /** * gcal_event_view_load_event: * @view: A GcalEventView widget * @event_uuid: the uuid of the event as referenced in GcalManager * * Loads events data in the widget, for viewing */ void gcal_event_view_load_event (GcalEventView *view, const gchar *event_uuid) { GcalEventViewPrivate *priv; gchar **tokens; g_return_if_fail (GCAL_IS_EVENT_VIEW (view)); priv = view->priv; if (event_uuid != NULL) { tokens = g_strsplit (event_uuid, ":", -1); if (gcal_manager_exists_event (priv->manager, tokens[0], tokens[1])) { if (priv->source_uid != NULL) g_free (priv->source_uid); if (priv->event_uid != NULL) g_free (priv->event_uid); priv->source_uid = tokens[0]; priv->event_uid = tokens[1]; /* Setting the widget to blank state to load a new event */ g_slist_foreach (priv->e_widgets, (GFunc) gcal_editable_clear, NULL); gcal_event_view_update (view); } } } /** * gcal_event_view_enter_edit_mode: * @view: A GcalEventView widget * * Sets the widget into edit mode. If it has an event set * then edit that events, otherwise acts as load_new method. */ void gcal_event_view_enter_edit_mode (GcalEventView *view) { GcalEventViewPrivate *priv; g_return_if_fail (GCAL_IS_EVENT_VIEW (view)); priv = view->priv; /* Setting the widget to blank state to load a new event */ g_slist_foreach (priv->e_widgets, (GFunc) gcal_editable_enter_edit_mode, NULL); /* showing delete button */ if (priv->event_uid != NULL) gtk_widget_show (priv->delete_button); } /** * gcal_event_view_leave_edit_mode: * @view: A GcalEventView widget * * Sets the widget into view. * FIXME: Maybe this is the place for update/create the event. */ void gcal_event_view_leave_edit_mode (GcalEventView *view) { GcalEventViewPrivate *priv; g_return_if_fail (GCAL_IS_EVENT_VIEW (view)); priv = view->priv; /* Setting the widget to blank state to load a new event */ g_slist_foreach (priv->e_widgets, (GFunc) gcal_editable_leave_edit_mode, NULL); gtk_widget_hide (priv->delete_button); }