Logo Search packages:      
Sourcecode: dates version File versions  Download package

dates_callbacks.c

/* -*- mode:C; tab-width:8; -*- */
/* 
 *  Author: Chris Lord        <chris@o-hand.com>
 *  Author: Tomas Frydrych    <tf@o-hand.com>
 *  Author: Robert Bradford   <rob@o-hand.com>
 *
 *  Copyright (c) 2005 - 2006 OpenedHand Ltd - http://o-hand.com
 *
 *  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, 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.
 *
 */
#include "dates_callbacks.h"
#include "dates_types.h"
#include "dates_platform.h"

#include <gdk/gdkkeysyms.h>
#include <string.h>

#include <libecal/e-cal-time-util.h>
#include <libical/icaltime.h>
#include <gconf/gconf-client.h>

#ifdef WITH_HILDON
#include <libosso.h>
#include <hildon/hildon-window.h>
#include <hildon/hildon-program.h>
#include <hildon/hildon-time-editor.h>
#include <hildon/hildon-date-editor.h>
#include <hildon/hildon-note.h>
#endif

#define TIME_MARKUP "%k:%M\n<small>%d %b %Y</small>"

#define CONVERT_CHILD_ITER(_filter,_child,_iter)\
      (gtk_tree_model_filter_convert_child_iter_to_iter (\
      GTK_TREE_MODEL_FILTER (_filter), _child, _iter))

static void
dates_date_change (DatesData *data, int direction)
{
    icaltimetype *time, *oldtime;
      
    oldtime = (icaltimetype *)dates_view_get_date (data->view);
    time = g_new (icaltimetype, 1);
    g_memmove (time, oldtime, sizeof (icaltimetype));

    if (data->zoom == 16)
      time->year += direction;
    else if (data->zoom >= 11) {
      int days;
      time->month += direction;
      if (time->month > 12) {
          time->month = 1;
          time->year++;
      } else if (time->month < 1) {
          time->month = 12;
          time->year--;
      }
      days = icaltime_days_in_month (time->month, time->year);
      if (time->day > days) time->day = days;
    } else if (data->zoom >= 8)
      icaltime_adjust (time, direction * 7, 0, 0, 0);
    else
      icaltime_adjust (time, direction, 0, 0, 0);
      
    dates_view_set_date (data->view, time);
      
    g_free (time);
}

void
dates_back_cb (GtkButton *button, DatesData *data)
{
    dates_date_change (data, -1);
}

void
dates_forward_cb (GtkButton *button, DatesData *data)
{
    dates_date_change (data, 1);
}

void
dates_today_cb (GtkButton *button, DatesData *data)
{
    icaltimetype today = icaltime_today ();
    dates_view_set_date (data->view, &today);
}

void
dates_zoom_change (guint pos, DatesView *dates_view)
{
    GConfClient *client;
      
    switch (pos) {
      case 1 :
          dates_view_set_visible_months (dates_view, 0);
          dates_view_set_visible_days (dates_view, 1);
          dates_view_set_visible_hours (dates_view, 4);
          break;
      case 2 :
          dates_view_set_visible_months (dates_view, 0);
          dates_view_set_visible_days (dates_view, 1);
          dates_view_set_visible_hours (dates_view, 8);
          break;
      case 3 :
          dates_view_set_visible_months (dates_view, 0);
          dates_view_set_visible_days (dates_view, 1);
          dates_view_set_visible_hours (dates_view, 12);
          break;
      case 4 :
          dates_view_set_visible_months (dates_view, 0);
          dates_view_set_visible_days (dates_view, 1);
          dates_view_set_visible_hours (dates_view, 12);
          break;
      case 5 :
          dates_view_set_visible_months (dates_view, 0);
          dates_view_set_visible_days (dates_view, 2);
          dates_view_set_visible_hours (dates_view, 12);
          break;
      case 6 :
          dates_view_set_visible_months (dates_view, 0);
          dates_view_set_visible_days (dates_view, 1);
          dates_view_set_visible_hours (dates_view, 24);
          break;
      case 7 :
          dates_view_set_visible_months (dates_view, 0);
          dates_view_set_visible_days (dates_view, 5);
          dates_view_set_visible_hours (dates_view, 12);
          break;
      case 8 :
          dates_view_set_visible_months (dates_view, 0);
          dates_view_set_visible_days (dates_view, 5);
          dates_view_set_visible_hours (dates_view, 24);
          break;
      case 9 :
          dates_view_set_visible_months (dates_view, 0);
          dates_view_set_visible_days (dates_view, 7);
          dates_view_set_visible_hours (dates_view, 12);
          break;
      case 10 :
          dates_view_set_visible_months (dates_view, 0);
          dates_view_set_visible_days (dates_view, 7);
          dates_view_set_visible_hours (dates_view, 24);
          break;
      case 11 :
          dates_view_set_visible_months (dates_view, 1);
          dates_view_set_visible_days (dates_view, 7);
          dates_view_set_visible_hours (dates_view, 24);
          break;
      case 12 :
          dates_view_set_visible_months (dates_view, 2);
          dates_view_set_visible_days (dates_view, 7);
          dates_view_set_visible_hours (dates_view, 24);
          break;
      case 13 :
          dates_view_set_visible_months (dates_view, 3);
          dates_view_set_visible_days (dates_view, 7);
          dates_view_set_visible_hours (dates_view, 24);
          break;
      case 14 :
          dates_view_set_visible_months (dates_view, 4);
          dates_view_set_visible_days (dates_view, 7);
          dates_view_set_visible_hours (dates_view, 24);
          break;
      case 15 :
          dates_view_set_visible_months (dates_view, 8);
          dates_view_set_visible_days (dates_view, 7);
          dates_view_set_visible_hours (dates_view, 24);
          break;
      case 16 :
          dates_view_set_visible_months (dates_view, 12);
          dates_view_set_visible_days (dates_view, 7);
          dates_view_set_visible_hours (dates_view, 24);
          break;
    }
      
    client = gconf_client_get_default ();
    gconf_client_set_int (client, DATES_GCONF_ZOOM, pos, NULL);
}

/*
 * because the zoom level is persistent (via gconf) we have to ensure that
 * all values 1-16 get handled so that if in case of upgrading we load in a
 * zoom value that is not handled, the zoom buttons do not stop working
 */
void
dates_zoom_in_cb (GtkButton *button, DatesData *data)
{
    switch (data->zoom)
      {
            case 1:
            case 2:
            case 3:
            case 4:
            case 6:
                  if (data->TBZoomIn)
                        gtk_widget_set_sensitive (data->TBZoomIn, FALSE);

                  if (data->MIZoomIn)
                        gtk_widget_set_sensitive (data->MIZoomIn, FALSE);
                  data->zoom = 3;
                  break;

            case 5:
            case 7:
            case 8:
                  data->zoom = 6;
                  break;
            case 9:
            case 10:
                  data->zoom = 7;
                  break;
            case 11:
            case 12:
            case 13:
            case 14:
            case 15:
                  data->zoom = 10;
                  break;

            case 16:
                  if (data->TBZoomOut)
                        gtk_widget_set_sensitive (data->TBZoomOut, TRUE);
            
                  if (data->MIZoomOut)
                        gtk_widget_set_sensitive (data->MIZoomOut, TRUE);
                  data->zoom = 11;
                  break;
            default:
                  return;
    }
      
    dates_zoom_change (data->zoom, data->view);
}

void
dates_zoom_out_cb (GtkButton *button, DatesData *data)
{
    switch (data->zoom)
      {
            case 1:
            case 2:
            case 3:
            case 4:
                  if (data->TBZoomIn)
                        gtk_widget_set_sensitive (data->TBZoomIn, TRUE);

                  if (data->MIZoomIn)
                        gtk_widget_set_sensitive (data->MIZoomIn, TRUE);
                  data->zoom = 6;
                  break;

            case 6:
                  data->zoom = 7;
                  break;
            case 5:
            case 7:
            case 8:
                  data->zoom = 10;
                  break;
            case 9:
            case 10:
                  data->zoom = 11;
                  break;
            case 11:
            case 12:
            case 13:
            case 14:
            case 15:
                  if (data->TBZoomOut)
                        gtk_widget_set_sensitive (data->TBZoomOut, FALSE);
            
                  if (data->MIZoomOut)
                        gtk_widget_set_sensitive (data->MIZoomOut, FALSE);
                  data->zoom = 16;
                  break;
            default:
                  return;
    }

    dates_zoom_change (data->zoom, data->view);
}


void
dates_date_changed_cb (DatesView *view, DatesData *d)
{
    struct tm timem;
    gchar buffer[256];
    gchar *buffer_utf8;

    const icaltimetype *date = dates_view_get_date (view);
#ifndef WITH_HILDON
    gchar *text;
#endif
      
    timem = icaltimetype_to_tm ((icaltimetype *)date);
    strftime (buffer, 255, "%a, %F", &timem);

#ifdef WITH_HILDON
    gtk_window_set_title (GTK_WINDOW (d->main_window), buffer);
#else
    text = g_strdup_printf ("%s - %s", buffer, _("Dates"));
    gtk_window_set_title (GTK_WINDOW (d->main_window), text);
    g_free (text);
#endif

    strftime (buffer, 255, "<big><b>%A %d %B, %Y</b></big>", &timem);
    buffer_utf8 = g_locale_to_utf8(buffer, -1,
            NULL, NULL, NULL);
    gtk_label_set_markup (GTK_LABEL (d->header_label), buffer_utf8);
    g_free (buffer_utf8);
}

void
dates_about_cb (GtkWidget *widget, DatesData *d)
{
      static GdkPixbuf *pixb;
      GError *error = NULL;

      /* NOTE: The hildon version of the about menu does not handle the
       * credits button well (it is misplaced and not thematised), so we add
       * the authors to the (c) string.
       */
#ifndef WITH_HILDON
      const gchar *authors[] = {
            "Principal author: Chris Lord <chris@o-hand.com>",
            "Maemo port: Tomas Frydrych <tf@o-hand.com>",
            "Rob Bradford <rob@o-hand.com>",
            NULL
      };

      const gchar *licence =
            _("This program is free software; you can redistribute it and/or modify\n"
                  "it under the terms of the GNU General Public License as published by\n"
                  "the Free Software Foundation; either version 2, or (at your option)\n"
                  "any later version.\n"
                  "\n"
                  "This program is distributed in the hope that it will be useful,\n"
                  "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
                  "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
                  "GNU General Public License for more details.");

        /* Translators: please translate this as your own name and optionally email
         like so: "Your Name <your@email.com>" */
        const char *translator_credits = _("translator-credits");
#endif
      
      if (!pixb)
            pixb = gdk_pixbuf_new_from_file (
                  PKGDATADIR G_DIR_SEPARATOR_S "oh-about-logo.png", &error);  

      if (!pixb) {
            g_assert (error);
            g_warning (error->message);
            g_clear_error (&error);
      }

      gtk_show_about_dialog (
                  GTK_WINDOW (d->main_window),

                  "copyright",
                  "(c) 2006 OpenedHand Ltd",

#ifndef WITH_HILDON
                  "authors",
                  authors,
                  
                  "license",
                  licence,

                        "translator-credits",
                        translator_credits,
#endif

                  "logo",
                  pixb,

                  "version",
                  PACKAGE_VERSION,
                  
                  "website",
                  "http://www.pimlico-project.org/dates",
                  NULL);
}


static void
dates_fill_details_dialog (DatesView *view, DatesData *d)
{
    const gchar *location = NULL;
    gchar *string = NULL;
    GSList *text_list;
    ECalComponentDateTime time;
    struct tm timem;
    gchar time_text[256];
    GtkTextBuffer *buffer;
    ECalComponentText summary;
    GtkWidget *widget;

    /* Set summary entry */
    e_cal_component_get_summary (d->comp, &summary);
    widget = d->details_summary_entry;
    if (summary.value)
      gtk_entry_set_text (GTK_ENTRY (widget), summary.value);
    else if (summary.altrep)
      gtk_entry_set_text (GTK_ENTRY (widget), summary.altrep);
    else
      gtk_entry_set_text (GTK_ENTRY (widget), "");
      
    /* Set event description textview */
    /* NOTE: Docs say that only journal entries can have more than one
     * description, so just use text_list->data
     */
    e_cal_component_get_location (d->comp, &location);
    e_cal_component_get_description_list (d->comp, &text_list);
    buffer = gtk_text_view_get_buffer (
      GTK_TEXT_VIEW (d->details_textview));
    /* NOTE: If there's a location property, we move it to the description
     */
    if (location)
      string = g_strconcat (location, "\n", NULL);
    gtk_text_buffer_set_text (buffer, string ? string : "", -1);
    g_free (string);
    if (text_list) {
      ECalComponentText *desc = text_list->data;
      if (desc->value) {
          GtkTextIter iter;
          gtk_text_buffer_get_end_iter (buffer, &iter);
          gtk_text_buffer_insert (buffer, &iter, desc->value, -1);
      }
      e_cal_component_free_text_list (text_list);
    }
      
    /* Set time buttons and dialog */
    e_cal_component_get_dtstart (d->comp, &time);
    timem = icaltimetype_to_tm (time.value);
    strftime (time_text, 256, TIME_MARKUP, &timem);
    gtk_label_set_markup (GTK_LABEL (d->details_start_label), time_text);
    e_cal_component_free_datetime (&time);

    e_cal_component_get_dtend (d->comp, &time);
    timem = icaltimetype_to_tm (time.value);
    strftime (time_text, 256, TIME_MARKUP, &timem);
    gtk_label_set_markup (GTK_LABEL (d->details_end_label),
                    time_text);
    e_cal_component_free_datetime (&time);
}

void
dates_event_selected_cb (DatesView *view, DatesData *d)
{
    GtkWidget *widget;

    if (d->comp) g_object_unref (d->comp);
    d->comp = dates_view_get_selected_event (d->view);

    if (d->comp) {
      GtkTreeIter iter;
      gboolean read_only = TRUE, cal_found = FALSE;
      GtkTreeModel *model;

/*          g_debug ("Selected event RID: %s",
            e_cal_component_get_recurid_as_string (d->comp));*/

      d->cal = dates_view_get_selected_event_cal (d->view);
                  
/*          widget = header_label;
            gtk_label_set_markup (GTK_LABEL (widget),
            "<big><b>Enter details</b></big>");*/
            
      /* Set the details calendar combo-box */
      widget = d->details_calendar_combobox;
      model = GTK_TREE_MODEL (d->cal_list_store);
      if (gtk_tree_model_get_iter_first (model, &iter)) {
          do {
            ECal *c;

            gtk_tree_model_get (
                model, &iter, COL_CALPTR, &c, -1);

            if (c != d->cal) continue;
            cal_found = TRUE;
                        
            gtk_tree_model_get (model, &iter,
                            COL_NOTREADONLY, &read_only,
                            -1);
            read_only = !read_only;
            d->read_only = read_only;
            if (!read_only) {
                GtkTreeIter filter_iter;
                              
                model = gtk_combo_box_get_model (
                  GTK_COMBO_BOX (widget));
                CONVERT_CHILD_ITER (model, &filter_iter,
                              &iter);
                              
                gtk_combo_box_set_active_iter (
                  GTK_COMBO_BOX (widget),
                  &filter_iter);

                gtk_widget_set_sensitive (widget, TRUE);
            } else {
#ifdef DEBUG
                if (d->debug & DATES_DEBUG_EDIT)
                  g_debug ("Read-only event"
                         " selected");
#endif
            }
            break;
          } while (gtk_tree_model_iter_next (model, &iter));
          if (!cal_found) {
            gtk_widget_set_sensitive (widget, FALSE);
            g_warning ("Event selected with "
                     "unknown calendar");
          }
      } else {
          g_warning ("Error accessing calendar list");
      }

      if (d->TBEdit)
            gtk_widget_set_sensitive (d->TBEdit, !read_only);

      if (d->TBDelete)
            gtk_widget_set_sensitive (d->TBDelete, !read_only);
      
    } else {
      d->cal = NULL;
      if (!d->waiting)
          dates_platform_details_dlg (d, FALSE);

      if (d->TBEdit)
            gtk_widget_set_sensitive (d->TBEdit, FALSE);

      if (d->TBDelete)
            gtk_widget_set_sensitive (d->TBDelete, FALSE);
    }
}

void
dates_commit_event_cb (GtkWidget *source, DatesData *data,
                   CalObjModType type)
{
    /* Commit changes */
#ifdef DEBUG
    if (data->debug & DATES_DEBUG_EDIT)
      g_debug ("Committing event (%p) changes", data->comp);
#endif
    e_cal_component_commit_sequence (data->comp);
    e_cal_modify_object (data->cal,
                   e_cal_component_get_icalcomponent (data->comp),
                   type, NULL);
}

void
dates_event_moved_cb (DatesView *view, ECalComponent *comp, DatesData *d)
{
    ECalComponentDateTime start, end;
    struct icaldurationtype duration = icaldurationtype_null_duration ();

    if (d->comp) g_object_unref (d->comp);
    d->comp = g_object_ref (comp);

    e_cal_component_get_dtstart (d->comp, &start);
    if (!start.value->is_date) {
      e_cal_component_get_dtend (d->comp, &end);
      duration = icaltime_subtract (*end.value, *start.value);
      *end.value = icaltime_add (*start.value, duration);
      e_cal_component_set_dtstart (d->comp, &start);
      e_cal_component_set_dtend (d->comp, &end);
      e_cal_component_free_datetime (&end);
    }
    e_cal_component_free_datetime (&start);
    dates_commit_event_cb (NULL, d, CALOBJ_MOD_THIS);
}

void
dates_event_sized_cb (DatesView *view, ECalComponent *comp, DatesData *d)
{
    if (d->comp) g_object_unref (d->comp);
    d->comp = g_object_ref (comp);

    dates_commit_event_cb (NULL, d, CALOBJ_MOD_THIS);
}

static void
dates_new (DatesData *d, icalcomponent *comp, gboolean select)
{
    GError *error = NULL;
    char *uid = NULL;

    if (!d->dcal) {
      /* TODO: Prompt to create a new calendar? */
      g_warning ("No calendars loaded");
      return;
    }
      
    if (e_cal_create_object (d->dcal, comp, (char **)&uid, &error)) {
      if (!select) return;
            
      d->event_type = NEW_EVENT;

      /* Bring up details dialog ASAP */
      if (d->comp) g_object_unref (d->comp);
      d->comp = e_cal_component_new ();
      e_cal_component_set_icalcomponent (d->comp, comp);
      dates_fill_details_dialog (d->view, d);
      dates_platform_details_dlg (d, TRUE);

      /* Disable calendar combo-box */
      gtk_widget_set_sensitive (d->details_calendar_combobox, FALSE);

      /* Select new event */
      d->waiting = PENDING_CREATE;
      d->uri_uid = g_strconcat (e_cal_get_uri (d->dcal), uid, NULL);
      g_idle_add (dates_select_event_idle_cb, d);
    } else {
      g_warning ("Failed to create calendar object: %s",
               error->message);
      icalcomponent_free (comp);
      g_error_free (error);
    }
}

void
dates_ical_drop_cb (DatesView *view, const gchar *ical, DatesData *d)
{
    icalcomponent *icalcomp, *icalcomp2;
    gint events;

    if (!d->cal_loaded) {
      /* TODO: Toggle the default calendar here maybe? */
      g_warning ("No calendars selected to add new event to");
      return;
    }
      
    icalcomp = icalcomponent_new_from_string (g_strdup (ical));
    if (!icalcomp)
      g_warning ("Error creating icalcomponent from string");

    switch (icalcomponent_isa (icalcomp)) {
      case ICAL_VEVENT_COMPONENT :
          icalcomponent_set_uid (icalcomp, "");
          dates_new (d, icalcomponent_new_clone (icalcomp), TRUE);
          return;
      case ICAL_VCALENDAR_COMPONENT :
          /* Iterate through events */
          /* TODO: A confirmation dialog when calendar has
           * multiple events?
           */
          events = icalcomponent_count_components (icalcomp,
                                         ICAL_VEVENT_COMPONENT);
          if (events == 0) {
            g_warning ("Dragged ical contains no supported "
                     "kinds.");
            break;
          }
                  
          icalcomp2 = icalcomponent_get_first_component (icalcomp,
                                             ICAL_VEVENT_COMPONENT);
          do {
            icalcomponent_set_uid (icalcomp2, "");
            dates_new (d, icalcomponent_new_clone (
                         icalcomp2), (events == 1) ?
                     TRUE : FALSE);
          } while ((icalcomp2 = icalcomponent_get_next_component (
                    icalcomp2, ICAL_VEVENT_COMPONENT))); 
          break;
      default :
          g_warning ("Dragged ical not a supported kind.");
          break;
    }

    icalcomponent_free (icalcomp);
}

void
dates_details_time_entry_changed (GtkEditable *entry, gchar *new_text,
                          gint new_text_length,
                          gint *position,
                          DatesData *d)
{
    gint i;
    gchar *c;
      
    for (i = 0, c = new_text; c;
       c = g_utf8_find_next_char (c, (new_text_length != -1) ?
                            (new_text + new_text_length) : NULL)) {
      if (*c < '0' || *c > '9') {
          g_signal_stop_emission (entry, g_signal_lookup (
                              "insert-text", GTK_TYPE_EDITABLE), 0);
          gdk_beep ();
          break;
      }
    }
}

gboolean
dates_details_time_entry_alt (GtkArrow *source, GtkWidget *entry,
                        DatesData *d, gint limit)
{
    gboolean overflow = FALSE;
    GtkEntry *widget;
    gchar buffer[33];
    gint hour;
    GtkArrowType direction;
      
    widget = GTK_ENTRY (entry);
    gtk_widget_grab_focus (GTK_WIDGET (widget));
    hour = atoi (gtk_entry_get_text (widget));
    g_object_get (G_OBJECT (source), "arrow-type", &direction, NULL);
    if (direction == GTK_ARROW_UP)
      hour ++;
    else
      hour --;
    if (hour < 0) { hour = limit; overflow = TRUE; }
    if (hour > limit) { hour = 0; overflow = TRUE; }
    snprintf (buffer, 33, "%d", hour);
    gtk_entry_set_text (widget, buffer);
      
    return overflow;
}

void
dates_details_time_hour_cb (GtkButton *source, DatesData *d)
{
    dates_details_time_entry_alt (GTK_ARROW (gtk_bin_get_child (
                                     GTK_BIN (source))), d->hour_entry, d, 23);
}

void
dates_details_time_lminute_cb (GtkButton *source, DatesData *d)
{
    dates_details_time_entry_alt (GTK_ARROW (gtk_bin_get_child (
                                     GTK_BIN (source))), d->lminute_entry, d, 5);
}

void
dates_details_time_rminute_cb (GtkButton *source, DatesData *d)
{
    if (dates_details_time_entry_alt (GTK_ARROW (gtk_bin_get_child (
                                         GTK_BIN (source))), d->rminute_entry, d, 9))
      dates_details_time_lminute_cb (source, d);
}
#if 0
void
dates_repeats_cb (GtkWidget *source, DatesData *d)
{
      if (GTK_IS_WINDOW (d->time_dialog) && GTK_IS_WINDOW (d->repeats_dialog))
      {
            gtk_window_set_transient_for (GTK_WINDOW (d->time_dialog),
                                                        GTK_WINDOW (d->repeats_dialog));
      }
      
    /* Run dialog */
      dates_platform_repeats_dlg (d, TRUE);
      
      if (GTK_IS_WINDOW (d->time_dialog) && GTK_IS_WINDOW (d->details_dialog))
      {
            gtk_window_set_transient_for (GTK_WINDOW (d->time_dialog),
                                                        GTK_WINDOW (d->details_dialog));
      }
}

void
dates_details_repeats_cb (GtkComboBox *combobox, DatesData *d)
{
    gint option = gtk_combo_box_get_active (combobox);
      
    if (option == OTHER)
      dates_repeats_cb (GTK_WIDGET (combobox), d);
    else {
      /* Ask for time */
      gtk_widget_show (d->time_forever_checkbutton);
      dates_platform_time_dlg (d, FALSE);
    }
}
#endif
void
dates_details_time_cb (DatesData *d, ECalComponentDateTime *time)
{
#ifndef WITH_HILDON
    gint i, hour, minute;
    gchar buffer[33];
    GtkCalendar *calendar;
      
    calendar = GTK_CALENDAR (d->time_calendar);
      
    /* Set time widgets */    
    gtk_calendar_select_month (calendar, time->value->month - 1,
                         time->value->year);
    gtk_calendar_select_day (calendar, time->value->day);

    g_snprintf (buffer, 33, "%d", time->value->hour);
    gtk_entry_set_text (GTK_ENTRY (d->hour_entry), buffer);
    i = time->value->minute / 10;
    g_snprintf (buffer, 33, "%d", i);
    gtk_entry_set_text (GTK_ENTRY (d->lminute_entry), buffer);
    i = time->value->minute - (i * 10);
    g_snprintf (buffer, 33, "%d", i);
    gtk_entry_set_text (GTK_ENTRY (d->rminute_entry), buffer);
    gtk_widget_show (d->time_table);
#else
    HildonDateEditor *date_edit = HILDON_DATE_EDITOR (d->time_date_editor);
    HildonTimeEditor *time_edit = HILDON_TIME_EDITOR (d->time_time_editor);
      
    /* Set date */
    hildon_date_editor_set_year (date_edit, time->value->year);
    hildon_date_editor_set_month (date_edit, time->value->month);
    hildon_date_editor_set_day (date_edit, time->value->day);
      
    /* Set time */
    hildon_time_editor_set_time (time_edit, time->value->hour,
                         time->value->minute, 0);
    hildon_time_editor_set_show_seconds (time_edit, FALSE);
#endif
      
    gtk_widget_hide (d->time_forever_checkbutton);

    /* Run dialog */
      dates_platform_time_dlg (d, TRUE);
      
    /* Retrieve time */
#ifndef WITH_HILDON
    gtk_calendar_get_date (calendar,
                     (guint *)(&time->value->year),
                     (guint *)(&time->value->month),
                     (guint *)(&time->value->day));
    time->value->month += 1;
      
    hour = atoi (gtk_entry_get_text (GTK_ENTRY (d->hour_entry)));
    if ((hour >= 0) && (hour <= 23))
      time->value->hour = hour;
    minute = (atoi (gtk_entry_get_text (GTK_ENTRY (d->lminute_entry))) * 10) +
      atoi (gtk_entry_get_text (GTK_ENTRY (d->rminute_entry)));
    if ((minute >= 0) && (minute <= 59))
      time->value->minute = minute;
#else
    time->value->year = hildon_date_editor_get_year (date_edit);
    time->value->month = hildon_date_editor_get_month (date_edit);
    time->value->day = hildon_date_editor_get_day (date_edit);
      
    hildon_time_editor_get_time (time_edit,
                         (guint *)(&time->value->hour),
                         (guint *)(&time->value->minute),
                         (guint *)(&time->value->second));
#endif
}

void
dates_details_update_time_label (DatesData *d, GtkWidget *label,
                         struct icaltimetype *time)
{
    struct tm timem;
    gchar time_text[256];

    timem = icaltimetype_to_tm (time);
    strftime (time_text, 255, TIME_MARKUP, &timem);
    gtk_label_set_markup (GTK_LABEL (label), time_text);
}

void
dates_details_time_start_cb (GtkWidget *source, DatesData *d)
{
    ECalComponentDateTime start, end;
    struct icaltimetype ostart;
      
    e_cal_component_get_dtstart (d->comp, &start);
    ostart = *start.value;
    dates_details_time_cb (d, &start);
      
    /* If start >= end, adjust end */
    e_cal_component_get_dtend (d->comp, &end);
    if (icaltime_compare (*start.value, *end.value) >= 0) {
      struct icaldurationtype duration =
          icaltime_subtract (*start.value, ostart);
      *end.value = icaltime_add (*end.value, duration);
      e_cal_component_set_dtend (d->comp, &end);

      dates_details_update_time_label (d, d->details_end_label,
                               end.value);
    }
      
    e_cal_component_set_dtstart (d->comp, &start);
    dates_details_update_time_label (d, d->details_start_label,
                             start.value);

    e_cal_component_free_datetime (&start);
    e_cal_component_free_datetime (&end);
}

void
dates_details_time_end_cb (GtkWidget *source, DatesData *d)
{
    ECalComponentDateTime start, end;
    struct icaltimetype oend;
      
    e_cal_component_get_dtend (d->comp, &end);
    oend = *end.value;
    dates_details_time_cb (d, &end);
      
    /* If end <= start, adjust start */
    e_cal_component_get_dtstart (d->comp, &start);
    if (icaltime_compare (*end.value, *start.value) <= 0) {
      struct icaldurationtype duration =
          icaltime_subtract (*end.value, oend);
      *start.value = icaltime_add (*end.value, duration);
      e_cal_component_set_dtstart (d->comp, &start);

      dates_details_update_time_label (d, d->details_start_label,
                               start.value);
    }
      
    e_cal_component_set_dtend (d->comp, &end);
    dates_details_update_time_label (d, d->details_end_label,
                             end.value);

    e_cal_component_free_datetime (&end);
    e_cal_component_free_datetime (&start);
}

void
dates_edit_cb (GtkWidget *source, DatesData *d)
{
    if (d->read_only) return;
    /* TODO: Handle recurring events */
    if (e_cal_component_has_recurrences (d->comp)) return;
    dates_fill_details_dialog (d->view, d);
      dates_platform_details_dlg (d, TRUE);
}

static void
dates_save_changes (DatesData *d)
{
    ECalComponentText text;
    const gchar *old_location = NULL;
    gchar *desc;
    GSList *desc_list;
    GtkTextIter start, middle, end;
    GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (
                                            d->details_textview));
    GtkWidget *widget;
    ECalComponentText summary, new_summary;
      
    gtk_text_buffer_get_start_iter (buffer, &start);
    e_cal_component_get_location (d->comp, &old_location);
    /* If there was a location field set, try not to overwrite it */
    if (old_location) {
      gtk_text_buffer_get_iter_at_line (buffer, &middle, 1);
      desc = gtk_text_buffer_get_text (
          buffer, &start, &middle, FALSE);
      if (desc) {
          /* Strip the trailing new-line, if necessary */
          gchar *strip;
          if ((strip = g_utf8_strchr (desc, -1, '\n')))
            *strip = '\0';
                  
          e_cal_component_set_location (d->comp, desc);
          g_free (desc);
      }
      start = middle;
    }

    /* Set the rest of the description */ 
    gtk_text_buffer_get_end_iter (buffer, &end);
    desc = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
    text.value = desc ? desc : "";
    text.altrep = NULL;
    desc_list = g_slist_prepend (NULL, &text);
    e_cal_component_set_description_list (d->comp, desc_list);
    g_free (desc);
    g_slist_free (desc_list);
      
    widget = d->details_summary_entry;
    e_cal_component_get_summary (d->comp, &summary);
    new_summary.altrep = summary.altrep;
    new_summary.value = g_strdup (gtk_entry_get_text (GTK_ENTRY (widget)));
    e_cal_component_set_summary (d->comp, &new_summary);

    dates_commit_event_cb (NULL, d, CALOBJ_MOD_ALL);
}

/* From contacts src/contacts-utils.c */
static GList *
contacts_set_widget_desensitive_recurse (GtkWidget *widget, GList **widgets)
{
      if (GTK_IS_WIDGET (widget)) {
            if (GTK_WIDGET_SENSITIVE (widget) &&
                GTK_WIDGET_VISIBLE (widget)) {
                  gtk_widget_set_sensitive (widget, FALSE);
                  *widgets = g_list_append (*widgets, widget);
            }
            
            if (GTK_IS_TABLE (widget) || GTK_IS_HBOX (widget) ||
                GTK_IS_VBOX (widget) || GTK_IS_EVENT_BOX (widget)) {
                  GList *c, *children = gtk_container_get_children (
                        GTK_CONTAINER (widget));
                  
                  for (c = children; c; c = c->next) {
                        contacts_set_widget_desensitive_recurse (
                              c->data, widgets);
                  }
                  g_list_free (children);
            }
      }
      
      return *widgets;
}

GList *
contacts_set_widgets_desensitive (GtkWidget *widget)
{
      GList *list = NULL;
      
      contacts_set_widget_desensitive_recurse (widget, &list);
      
      return list;
}

static void
contacts_set_widgets_sensitive (GList *widgets)
{
      GList *w;
      
      for (w = widgets; w; w = w->next) {
            gtk_widget_set_sensitive (GTK_WIDGET (w->data), TRUE);
      }
}

void
dates_details_ok_cb (GtkWidget *source, DatesData *d)
{
    if (d->waiting == NONE) {
      d->event_type = NORMAL;
      d->waiting = NONE;
      dates_save_changes (d);
      dates_platform_details_dlg (d, FALSE);
    } else {
      d->widgets = contacts_set_widgets_desensitive (d->details_dialog);
      d->waiting = PENDING_CHANGE;
    }
}

void
dates_delete_cb (GtkWidget *source, DatesData *d)
{
    ECalComponentText summary;
    GtkWidget *widget;
    const char *value;
#ifdef WITH_HILDON
    gchar *tmp;
#endif

    e_cal_component_get_summary (d->comp, &summary);
    widget = d->details_dialog;
    if (GTK_WIDGET_VISIBLE (widget))
      value = gtk_entry_get_text (GTK_ENTRY (d->details_summary_entry));
    else if (summary.value)
      value = summary.value;
    else if (summary.altrep)
      value = summary.altrep;
    else {
      g_warning ("Deleting event with no summary");
      value = _("Unknown event");
    }
            
#ifdef WITH_HILDON
    tmp = g_strdup_printf(_("Are you sure you want to delete event '%s'?"), value);
    widget = hildon_note_new_confirmation_add_buttons(
        GTK_WINDOW (d->main_window),
        tmp,
        _("Keep event"), GTK_RESPONSE_NO,
        _("Delete event"), GTK_RESPONSE_YES,
        NULL);
    g_free(tmp);
#else
    widget = gtk_message_dialog_new (
      GTK_WINDOW (d->main_window),
      GTK_DIALOG_MODAL,
      GTK_MESSAGE_QUESTION,
      GTK_BUTTONS_NONE,
      _("Are you sure you want to delete event '%s'?"),
      value);
    gtk_dialog_add_buttons (GTK_DIALOG (widget),
                      _("Keep event"), GTK_RESPONSE_NO,
                      _("Delete event"), GTK_RESPONSE_YES,
                      NULL);
#endif
    if (gtk_dialog_run (GTK_DIALOG (widget)) == GTK_RESPONSE_YES) {
      /* Reset event type, in case this was a new event */
      d->event_type = NORMAL;
            
      if (d->waiting == NONE) {
          const char *uid = NULL;
          e_cal_component_get_uid (d->comp, &uid);
          e_cal_remove_object (d->cal, uid, NULL);

          /* Hide the details dialog, in case we deleted
           * from there.
           */
          dates_platform_details_dlg (d, FALSE);
      } else {
          d->widgets = contacts_set_widgets_desensitive (
            d->details_dialog);
          d->waiting = PENDING_DELETE;
      }
    }
      
    gtk_widget_destroy (widget);
}

void
dates_details_cancel_cb (GtkWidget *source, DatesData *d)
{
    if (d->event_type == NEW_EVENT) {
      if (d->waiting == NONE) {
          const char *uid = NULL;
          d->event_type = NORMAL;
          e_cal_component_get_uid (d->comp, &uid);
          e_cal_remove_object (d->cal, uid, NULL);
      } else {
          d->widgets = contacts_set_widgets_desensitive (
            d->details_dialog);
          d->waiting = PENDING_DELETE;
          return;
      }
    }

      dates_platform_details_dlg (d, FALSE);
}

gboolean
dates_details_close_cb (GtkWidget *widget, GdkEvent *event, DatesData *d)
{
    dates_details_cancel_cb (widget, d);
    return TRUE;
}


gboolean
dates_select_event_idle_cb (gpointer data)
{
    DatesData *d = data;
    gboolean selected =
      dates_view_set_selected_event (d->view, d->uri_uid, NULL);
      
    if (selected) {
      const char *uid = NULL;
      g_free (d->uri_uid);
      d->uri_uid = NULL;
      
      if (d->widgets) {
          contacts_set_widgets_sensitive (d->widgets);
          g_list_free (d->widgets);
          d->widgets = NULL;
      }
      switch (d->waiting) {
          case NONE :
          case PENDING_CREATE :
            break;
          case PENDING_DELETE :
            e_cal_component_get_uid (d->comp, &uid);
            e_cal_remove_object (d->cal, uid, NULL);
          dates_platform_details_dlg (d, FALSE);
            break;
          case PENDING_CHANGE :
            dates_save_changes (d);
            gtk_widget_hide (d->details_dialog);
            break;
          case PENDING_CAL_CHANGE :
            break;
          default:
            g_warning ("Unknown pending state");
      }
      d->waiting = NONE;
    }
      
    return !selected;
}

void
dates_new_cb (GtkWidget *source, DatesData *d)
{
    icalcomponent *comp;
    struct icalperiodtype period;

    if (!dates_view_get_selected_period (d->view, &period)) {
      struct icaltimetype date, now;

      /* Create a default time event */
      date = *(dates_view_get_date (d->view));
      now = icaltime_current_time_with_zone (date.zone);
      date.is_date = FALSE;
      now.is_date = FALSE;
      period.duration = icaldurationtype_null_duration ();
      period.duration.minutes = 0;

      /* New events default to starting at 9am */
      period.duration.hours = 9;
      period.start = icaltime_add (
          date, period.duration);
            
      /* NOTE: 11 is the magic number where we're viewing a 
       * month or more. See dates_zoom_change.
       */
      period.duration.hours = (d->zoom >= 11) ? 8 : 2;
      period.end = icaltime_add (period.start, period.duration);
    }
      
    comp = icalcomponent_new_vevent ();
    icalcomponent_set_dtstart (comp, period.start);
    icalcomponent_set_dtend (comp, period.end);
    icalcomponent_set_summary (comp, _("New event"));
    dates_new (d, comp, TRUE);
}

void
dates_calendar_combo_changed_cb (GtkComboBox *widget, DatesData *d)
{
    ECal *c;
    ECalComponent *comp = d->comp;
    GtkTreeIter iter;
      
    if (!gtk_combo_box_get_active_iter (widget, &iter)) return;
    gtk_tree_model_get (gtk_combo_box_get_model (widget),
                  &iter, COL_CALPTR, &c, -1);
      
    if (c != d->cal) {
      /* Move event between calendars */
      const char *uid = NULL;
            
      g_object_ref (comp);
      if (!d->waiting)
          d->waiting = PENDING_CAL_CHANGE;
      e_cal_component_get_uid (comp, &uid);
      e_cal_remove_object (d->cal, uid, NULL);
            
      /* TODO: Error checking */
      e_cal_create_object (c,
                       e_cal_component_get_icalcomponent (comp),
                       (char **)&uid, NULL);
      g_object_unref (comp);
      d->uri_uid = g_strconcat (e_cal_get_uri (c), uid, NULL);
      d->widgets = contacts_set_widgets_desensitive (d->details_dialog);
      g_idle_add (dates_select_event_idle_cb, d);
    }
}

/* snippet from evolution/calendar/gui/calendar-component.c:294 */
static gboolean
is_in_uids (GSList *uids, ESource *source)
{
      GSList *l;

      for (l = uids; l; l = l->next)
      {
            const char *uid = l->data;
            if (strcmp (uid, e_source_peek_uid (source)) == 0)
                  return TRUE;
      }

      return FALSE;
}

void
dates_cal_open_cb (ECal *ecal, ECalendarStatus status, DatesData *d)
{
    gboolean read_only;
    GError *error = NULL;
    const char *ecal_name;
    ESource *source;
    ESourceGroup *group;
    GtkTreeIter iter;
    gchar *primary_uid;
    GSList *selected_list;
    gboolean selected;
      gchar * cal_name;
      
#ifdef DEBUG
    if (d->debug & DATES_DEBUG_CALENDAR)
      g_debug ("Calendar opened, setting up...");
#endif

    if (status != E_CALENDAR_STATUS_OK)
      {
            g_warning ("Error '%d' opening ecal", status);
            g_object_unref (ecal);
            if (d->first_load) {
                  GtkWidget *dialog = gtk_message_dialog_new (
                        GTK_WINDOW (d->main_window),
                        GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
                        GTK_MESSAGE_ERROR,
                        GTK_BUTTONS_CLOSE,
                        _("Dates failed to open the system calendar. "
                          "You will not be able to view or create "
                          "events; this may be remedied by restarting."));
                  gtk_dialog_run (GTK_DIALOG (dialog));
            }
            return;
    }
      
    source = e_cal_get_source (ecal);

    ecal_name = e_source_peek_name (source);

    if (!e_cal_is_read_only (ecal, &read_only, &error))
      {
            g_warning ("Error querying calendar's read-only status: %s",
                           error->message);
            g_error_free (error);
            g_object_unref (ecal);
            return;
    }

      /* 
       * Work around the fact that eds-dbus seems to be returning the wrong
       * value for e_cal_is_read_only on the calendar itself for the http
       * backend. But on the events themselves it is fine
       */
      group = e_source_peek_group (source);
      if (strncmp (e_source_group_peek_base_uri (group), "webcal://", 9) == 0)
            read_only = TRUE;
      
    selected_list = gconf_client_get_list (gconf_client_get_default (),
                                 CALENDAR_GCONF_SELECTED, GCONF_VALUE_STRING, NULL);
#ifdef DEBUG
            if (d->debug & DATES_DEBUG_CALENDAR)
                  g_debug ("selected_list %p: is in uids %d",
                               selected_list,
                               is_in_uids (selected_list, source));
#endif
      
    if (selected_list && is_in_uids (selected_list, source))
      {
            dates_view_add_calendar (d->view, ecal);
            g_signal_connect (G_OBJECT (ecal), "backend_died",
                                      G_CALLBACK (dates_backend_died_cb), d);
            selected = TRUE;
    }
      else
      {
            selected = FALSE;
    }
      
    if ((!read_only) && (selected))
      {
            if (!d->dcal)
                  d->dcal = ecal;
            else
            {
                  /* Find out if it's the default calendar */
                  primary_uid = gconf_client_get_string (
                        gconf_client_get_default (),
                        CALENDAR_GCONF_PRIMARY, NULL);
                  if (primary_uid) {
                        if (strcmp (e_source_peek_uid (source),
                                          primary_uid) == 0)
                              d->dcal = ecal;
                        g_free (primary_uid);
                  }
            }

            d->cal_loaded = TRUE;
      
            if (d->TBNew)
            {
#ifdef DEBUG
                  if (d->debug & DATES_DEBUG_CALENDAR)
                        g_debug ("*** Setting TBNew button sensitive ***");
#endif
                  gtk_widget_set_sensitive (d->TBNew, TRUE);
            }
    }
      else
      {
#ifdef DEBUG
            if (d->debug & DATES_DEBUG_CALENDAR)
                  g_debug ("*** RO %d, Selected %d ***", read_only, selected);
#endif
      }

      if (ecal_name && !read_only)
            cal_name = g_strdup (ecal_name);
      else if (ecal_name)
            cal_name = g_strconcat (ecal_name, _(" (Read Only)"), NULL);
      else if (!read_only)
            cal_name = g_strdup (_("Unknown"));
      else
            cal_name = g_strconcat (_("Unknown"), _(" (Read Only)"), NULL);
            
    gtk_list_store_insert_with_values (d->cal_list_store, &iter, G_MAXINT,
                                                COL_CALNAME, cal_name,
                                                COL_CALPTR, ecal,
                                                COL_NOTREADONLY, !read_only,
                                                COL_SELECTED, selected,
                                                -1);

      g_free (cal_name);
      
#ifdef DEBUG
    if (d->debug & DATES_DEBUG_CALENDAR)
            g_debug ("Calendar added.");
#endif

      dates_platform_cal_open (d);
}

/* The following function taken from gnome clock-applet
 * (gnome-panel/applets/clock/calendar-sources.c)
 */
ECal *
dates_load_esource (ESource        *esource,
            ECalSourceType  source_type,
            GSList         *existing_clients,
            DatesData      *d)
{
    ECal   *retval;
    GError *error;


    if (existing_clients)
    {
      GSList *l;

      for (l = existing_clients; l; l = l->next)
      {
          ECal *client = E_CAL (l->data);

          if (e_source_equal (esource, e_cal_get_source (client)))
          {
#ifdef DEBUG
            if (d->debug & DATES_DEBUG_CALENDAR)
                g_debug ("load_esource: found existing source, returning that");
#endif
            return g_object_ref (client);
          }
      }
    }

    retval = e_cal_new (esource, source_type);
    if (!retval)
    {
      g_warning ("Could not load source '%s' from '%s'\n",
               e_source_peek_name (esource),
               e_source_get_uri (esource));
      return NULL;
    }

    error = NULL;
    if (!e_cal_open (retval, FALSE, &error))
    {
      g_assert (error != NULL);
      g_warning ("Cannot open calendar from uri '%s': %s\n",
               e_cal_get_uri (retval), error->message);
      g_error_free (error);
      g_object_unref (retval);
      return NULL;
    }
#ifdef DEBUG
    if (d->debug & DATES_DEBUG_CALENDAR)
      g_debug ("Loaded calendar from uri '%s'",
             e_cal_get_uri (retval));
#endif

    /* 
     * Set the calendar mode to CAL_MODE_REMOTE. This is necessary to get the
     * remote (webcal) calendars to work. It doesn't seem to have any effect
     * on the file backend.
     */
    e_cal_set_mode (retval, CAL_MODE_REMOTE);

    return retval;
}

void
dates_backend_died_cb (ECal *client, DatesData *d)
{
#ifdef DEBUG
    if (d->debug & DATES_DEBUG_CALENDAR)
      g_debug ("Calendar died, removing");
#endif
    dates_view_remove_calendar (d->view, client);
}

void
dates_sources_changed_cb (ESourceList *cal_list, DatesData *d)
{
#ifdef DEBUG
    if (d->debug & DATES_DEBUG_CALENDAR)
      g_debug ("Sources changed, reloading calendars");
#endif
      if (d->first_load)
      {
            d->first_load = FALSE;
            dates_autoselect_calendars (d, cal_list);
      }

    dates_update_calendars (cal_list, d);
}

void
dates_update_calendars (ESourceList *cal_list, DatesData *d)
{
    GSList *groups, *g;

    /* TODO: Don't reload *all* calendars on update */
    d->dcal = NULL;
    gtk_list_store_clear (d->cal_list_store);
    dates_view_remove_all_calendars (d->view);
    groups = e_source_list_peek_groups (cal_list);

#ifdef DEBUG
    if (d->debug & DATES_DEBUG_CALENDAR)
      g_debug ("Updating Calendars");
#endif

    /* Disable creating of calendars until we know there's a valid
     * calendar to add events to.
     */
      d->cal_loaded = FALSE;
      
      if (d->TBNew)
      {
#ifdef DEBUG
            if (d->debug & DATES_DEBUG_CALENDAR)
                  g_debug ("*** Setting TBNew button insensitive ***");
#endif
            gtk_widget_set_sensitive (d->TBNew, FALSE);
      }
      
    for (g = groups; g; g = g->next) {
      GSList *sources, *s;
#ifdef DEBUG
      if (d->debug & DATES_DEBUG_CALENDAR)
          g_debug ("Group %s (%s)",
                 e_source_group_peek_name (
                   E_SOURCE_GROUP (g->data)),
                 e_source_group_peek_base_uri (
                   E_SOURCE_GROUP (g->data)));
#endif
      sources = e_source_group_peek_sources (
          E_SOURCE_GROUP (g->data));
      for (s = sources; s; s = s->next) {
          ESource *source = E_SOURCE (s->data);
          ECal *ecal;
                  
          ecal = dates_load_esource (source,
                         E_CAL_SOURCE_TYPE_EVENT, NULL, d);
          if (!ecal) {
#ifdef DEBUG
            if (d->debug & DATES_DEBUG_CALENDAR)
                g_debug ("No EVENTS in this source");
#endif
            continue;
          }

#ifdef DEBUG
          if (d->debug & DATES_DEBUG_CALENDAR)
            g_debug ("Found EVENTS in this source");
#endif

          g_signal_connect (G_OBJECT (ecal), "cal_opened",
                        G_CALLBACK (dates_cal_open_cb), d);

          e_cal_open_async (ecal, FALSE);
          
          /* 
           * Set the calendar mode to CAL_MODE_REMOTE. This is necessary to get the
           * remote (webcal) calendars to work. It doesn't seem to have any effect
           * on the file backend.
           */
          e_cal_set_mode (ecal, CAL_MODE_REMOTE);
      }
    } 
}

void
dates_gconf_selected_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry,
                   gpointer user_data)
{
    DatesData *d = (DatesData *)user_data;
      
    dates_update_calendars (d->source_list, d);
}

void
dates_calendars_dialog_cb (GtkButton *button, DatesData *d)
{
      dates_platform_calendars_dlg (d, TRUE);
}

void
dates_window_state_cb (GtkWidget *widget, GdkEventVisibility *event,
                   DatesData *d)
{
    GtkWidget *header = d->header_eventbox;
    if (gdk_window_get_state (widget->window) &
      GDK_WINDOW_STATE_FULLSCREEN) {
      gtk_widget_show (header);
    } else {
      gtk_widget_hide (header);
    }
}

gboolean
dates_cal_key_press_cb (GtkWidget *widget, GdkEventKey *event, DatesData *d)
{
    switch (event->keyval) {
      case GDK_3270_Enter :
      case GDK_ISO_Enter :
      case GDK_KP_Enter :
      case GDK_Return :
          if (d->cal_loaded)
            dates_new_cb (widget, d);
          return TRUE;
    }
    return FALSE;
}

gboolean
dates_key_press_cb (GtkWidget *widget, GdkEventKey *event, DatesData *d)
{
    switch (event->keyval) {
#ifdef WITH_HILDON
      case HILDON_HARDKEY_FULLSCREEN: {
          GtkWidget *window = d->main_window;
          GtkWidget *header = d->header_eventbox;
          if (!(gdk_window_get_state (window->window) &
              GDK_WINDOW_STATE_FULLSCREEN)) {
            gtk_window_fullscreen (GTK_WINDOW (widget));
            gtk_widget_show (header);
          } else {
            gtk_window_unfullscreen (GTK_WINDOW (widget));
            gtk_widget_hide (header);
          }
          return TRUE;
      }
      case HILDON_HARDKEY_DECREASE:
          dates_zoom_out_cb (NULL, d);
          return TRUE;
      case HILDON_HARDKEY_INCREASE:
          dates_zoom_in_cb (NULL, d);
          return TRUE;
#else
      case GDK_KP_Subtract :
      case GDK_minus :
          if (event->state & GDK_CONTROL_MASK) {
            dates_zoom_out_cb (NULL, d);
            return TRUE;
          } else
            return FALSE;
      case GDK_KP_Add :
      case GDK_plus :
          if (event->state & GDK_CONTROL_MASK) {
            dates_zoom_in_cb (NULL, d);
            return TRUE;
          } else
            return FALSE;
#endif
    }
      
    return FALSE;
}

gboolean
dates_button_press_cb (GtkWidget    *widget,
                   GdkEventButton   *event,
                   DatesData  *d)
{
      if ((event->button != 1) || (event->type != GDK_2BUTTON_PRESS) ||
          (d->comp))
            return FALSE;
      
      if (d->cal_loaded)
            dates_new_cb (widget, d);
      
      return TRUE;
}

void
dates_autoselect_calendars (DatesData *d, ESourceList * cal_list)
{
      GSList *selected_list;

      if (!cal_list)
            return;

      selected_list = gconf_client_get_list (gconf_client_get_default (),
                                     CALENDAR_GCONF_SELECTED,
                                     GCONF_VALUE_STRING, NULL);

      if (!selected_list) {
            /* select all available calendars */
            GSList *list = NULL, *groups, *g;
            groups = e_source_list_peek_groups (cal_list);
#ifdef DEBUG
            if (d->debug & DATES_DEBUG_CALENDAR)
                  g_debug ("Attempting to autoselect");
#endif
            
            for (g = groups; g; g = g->next) {
                  GSList *sources, *s;
                  sources =
                        e_source_group_peek_sources (E_SOURCE_GROUP (g->data));
                  for (s = sources; s; s = s->next) {
                        ESource *source = E_SOURCE (s->data);
                        ECal *ecal;
                        gchar * uid;
                  
                        ecal = dates_load_esource (source,
                                             E_CAL_SOURCE_TYPE_EVENT,
                                             NULL, d);
                        if (!ecal)
                        {
#ifdef DEBUG
                              if (d->debug & DATES_DEBUG_CALENDAR)
                                    g_debug ("No ecal");
#endif
                              
                              continue;
                        }
                        
                        uid = (gchar *)e_source_peek_uid (e_cal_get_source (ecal));
                        list = g_slist_prepend (list, uid);
                  }
            }

            if (list)
            {
#ifdef DEBUG
                  if (d->debug & DATES_DEBUG_CALENDAR)
                        g_debug ("Setting new list");
#endif
                  gconf_client_set_list (gconf_client_get_default (),
                                     CALENDAR_GCONF_SELECTED,
                                     GCONF_VALUE_STRING,
                                     list, NULL);
            }
      }
      else
#ifdef DEBUG
            if (d->debug & DATES_DEBUG_CALENDAR)
                  g_debug ("Have selected list");
#endif
}

gboolean
dates_import_calendar_data_from_file (ECal *cal, gchar *filename, GError **error)
{
  GError *tmp_error = NULL;
  GIOChannel *channel = NULL;
  gchar *line;
  gsize length;

  channel = g_io_channel_new_file (filename, "r", &tmp_error);

  if (tmp_error != NULL)
  {
    g_warning ("Error when opening file: %s", tmp_error->message);
    g_propagate_error (error, tmp_error);
    return FALSE;
  } else {
    GIOStatus status;
    icalparser *parser = icalparser_new ();

    /* Read the from the file line by line and until EOF */
    while ((status = g_io_channel_read_line (channel, &line, &length, NULL, &tmp_error))
        == G_IO_STATUS_NORMAL)
    {
      icalcomponent *icomp = NULL;

      /* The parser returns an icalcomponent when it has one */
      icomp = icalparser_add_line (parser, line);
      g_free (line);

    if (icomp)
      {
        gchar *uid = NULL;
        icalcompiter iter;
        icalcomponent *subcomp;

        /* The component is a top-level one and e_cal_create_object only
         * accepts VEVENTs. Iterate through the VEVENTS. */
        iter = icalcomponent_begin_component (icomp, ICAL_VEVENT_COMPONENT);

        while ((subcomp = icalcompiter_deref (&iter)) != NULL) 
        {
          if (!e_cal_create_object (cal, subcomp, &uid, &tmp_error))
          {
            g_warning ("Creation of imported event failed: %s", tmp_error->message);
            g_propagate_error (error, tmp_error);

            if (parser)
              icalparser_free (parser);

            if (icomp)
              icalcomponent_free (icomp);

            if (channel)
              g_io_channel_unref (channel);

            g_free (uid);
            return FALSE;
          }

          icalcompiter_next (&iter);
          g_free (uid);
        }

        icalcomponent_free (icomp);
      }
    }

    if (parser)
      icalparser_free (parser);

    if (tmp_error != NULL)
    {
      g_warning ("Error when reading from file: %s", tmp_error->message);
      g_propagate_error (error, tmp_error);

      g_io_channel_unref (channel);
      return FALSE;
    }
  }

  if (channel)
    g_io_channel_unref (channel);

  return TRUE;
}

void
dates_import_cb (GtkWidget *menu_item, gpointer user_data)
{
  dates_platform_import_dialog ((DatesData *)user_data);
}


Generated by  Doxygen 1.6.0   Back to index