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

koto-actions.c

/*
 * Copyright (C) 2007 OpenedHand Ltd
 *
 * 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., 51
 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <config.h>
#include <string.h>
#include <glib/gi18n.h>
#include <libecal/e-cal.h>

#include "koto-task.h"
#include "koto-actions.h"

/* Closures */

typedef struct {
  ECal *cal;
  char *uid; /* The UID to remove */
  icalcomponent *comp; /* The task to add */
} AddRemoveData;

typedef struct {
  ECal *cal;
  icalcomponent *before, *after;
} ModifyData;


/* Workers */

static void
add_remove_task_undo (gpointer closure)
{
  GError *error = NULL;
  AddRemoveData *data = closure;

  if (!data->cal) {
    g_warning ("ECal has been destroyed");
    return;
  }

  /* TODO Set ->comp now? */

  if (!e_cal_remove_object (data->cal, data->uid, &error)) {
    g_warning (G_STRLOC ": cannot remove task: %s", error->message);
    g_error_free (error);
  }
  
  g_free (data->uid);
  data->uid = NULL;
}

static void
add_remove_task_redo (gpointer closure)
{
  GError *error = NULL;
  AddRemoveData *data = closure;

  if (!data->cal) {
    g_warning ("ECal has been destroyed");
    return;
  }
  
  g_free (data->uid);
  data->uid = NULL;

  if (!e_cal_create_object (data->cal, data->comp, &data->uid, &error)) {
    g_warning (G_STRLOC ": cannot create task: %s", error->message);
    g_error_free (error);
  }
}

static void
add_remove_task_destroy (gpointer closure)
{
  AddRemoveData *data = closure;

  g_object_unref (data->cal);
  g_free (data->uid);
  icalcomponent_free (data->comp);
  g_slice_free (AddRemoveData, data);
}

static void
modify_task_undo (gpointer closure)
{
  GError *error = NULL;
  ModifyData *data = closure;

  if (!data->cal) {
    g_warning ("ECal has been destroyed");
    return;
  }
  
  if (!e_cal_modify_object (data->cal, data->before, CALOBJ_MOD_THIS, &error)) {
    g_warning (G_STRLOC ": cannot modify task: %s", error->message);
    g_error_free (error);
  }
}

static void
modify_task_redo (gpointer closure)
{
  GError *error = NULL;
  ModifyData *data = closure;

  if (!data->cal) {
    g_warning ("ECal has been destroyed");
    return;
  }
  
  if (!e_cal_modify_object (data->cal, data->after, CALOBJ_MOD_THIS, &error)) {
    g_warning (G_STRLOC ": cannot modify task: %s", error->message);
    g_error_free (error);
  }
}

static void
modify_task_destroy (gpointer closure)
{
  ModifyData *data = closure;

  g_object_unref (data->cal);
  icalcomponent_free (data->before);
  icalcomponent_free (data->after);
  g_slice_free (ModifyData, data);
}


/* Public API */

gboolean
koto_action_delete_task (ECal *cal, KotoTask *task, KotoUndoContext *undo)
{
  GError *error = NULL;

  g_return_val_if_fail (E_IS_CAL (cal), FALSE);
  g_return_val_if_fail (task, FALSE);
  
  if (!e_cal_remove_object (cal, icalcomponent_get_uid (task->comp), &error)) {    
    g_warning ("Cannot remove object: %s", error->message);
    g_error_free (error);
    return FALSE;
  }
  
  if (undo) {
    KotoUndoable *u;
    AddRemoveData *c;
    
    c = g_slice_new0 (AddRemoveData);
    c->cal = cal;
    g_object_add_weak_pointer (G_OBJECT (cal), (gpointer)&c->cal);
    c->uid = NULL;
    c->comp = icalcomponent_new_clone (task->comp);
    
    u = koto_undoable_new (add_remove_task_redo,
                           add_remove_task_undo,
                           add_remove_task_destroy,
                           c);
    
    koto_undo_context_add (undo, u);
  }
  
  return TRUE;
}

gboolean
koto_action_create_task (ECal *cal, icalcomponent *comp, char **uid, KotoUndoContext *undo)
{
  GError *error = NULL;
  char *real_uid = NULL;

  g_return_val_if_fail (E_IS_CAL (cal), FALSE);
  g_return_val_if_fail (comp, FALSE);

  if (!e_cal_create_object (cal, comp, &real_uid, &error)) {
    g_warning (G_STRLOC ": cannot create task: %s", error->message);
    g_error_free (error);
    return FALSE;
  }

  if (uid)
    *uid = real_uid;
  
  if (undo) {
    AddRemoveData *c;
    KotoUndoable *u;
    
    c = g_slice_new0 (AddRemoveData);
    c->cal = cal;
    g_object_add_weak_pointer (G_OBJECT (cal), (gpointer)&c->cal);
    c->uid = g_strdup (real_uid);
    c->comp = icalcomponent_new_clone (comp);
    
    u = koto_undoable_new (add_remove_task_undo,
                           add_remove_task_redo,
                           add_remove_task_destroy,
                           c);
    
    koto_undo_context_add (undo, u);
  }
  
  return TRUE;
}

/* Note that this function takes ownership of old */
gboolean
koto_action_modify_task (ECal *cal, KotoTask *task, icalcomponent *old, KotoUndoContext *undo)
{
  GError *error = NULL;
  gboolean ret;

  g_return_val_if_fail (E_IS_CAL (cal), FALSE);
  g_return_val_if_fail (task, FALSE);
  /* If we have an undo context, we need an old task */
  g_return_val_if_fail (undo ? old != NULL : TRUE, FALSE);

  if (!e_cal_modify_object (cal, task->comp, CALOBJ_MOD_THIS, &error)) {
    g_warning (G_STRLOC ": cannot modify task: %s", error->message);
    g_error_free (error);
    ret = FALSE;
    goto done;
  }

  if (undo) {
    ModifyData *c;
    KotoUndoable *u;
    
    c = g_slice_new0 (ModifyData);
    c->cal = cal;
    g_object_add_weak_pointer (G_OBJECT (cal), (gpointer)&c->cal);
    c->before = old;
    old = NULL; /* Set old to NULL so that it isn't freed later */
    c->after = icalcomponent_new_clone (task->comp);
    
    u = koto_undoable_new (modify_task_undo,
                           modify_task_redo,
                           modify_task_destroy,
                           c);
    
    koto_undo_context_add (undo, u);
  }

 done:
  if (old) {
    icalcomponent_free (old);
  }
  
  return TRUE;
}

Generated by  Doxygen 1.6.0   Back to index