diff options
-rw-r--r-- | calendar/ChangeLog | 22 | ||||
-rw-r--r-- | calendar/gui/e-calendar-table.c | 215 | ||||
-rw-r--r-- | calendar/gui/e-calendar-table.h | 4 | ||||
-rw-r--r-- | calendar/idl/evolution-calendar.idl | 3 | ||||
-rw-r--r-- | calendar/pcs/cal-backend-db.c | 11 | ||||
-rw-r--r-- | calendar/pcs/cal-backend-file.c | 8 | ||||
-rw-r--r-- | calendar/pcs/cal-backend.c | 26 | ||||
-rw-r--r-- | calendar/pcs/cal-backend.h | 3 | ||||
-rw-r--r-- | calendar/pcs/cal.c | 35 |
9 files changed, 327 insertions, 0 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog index 5d97924c80..b4f169e2cd 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,19 @@ +2001-06-20 Rodrigo Moya <rodrigo@ximian.com> + + * idl/evolution-calendar.idl: added getFreeBusy method + + * pcs/cal.c (impl_Cal_get_free_busy): implementation of the new + getFreeBusy added method + + * pcs/cal-backend.[ch]: added new virtual method to the CalBackend + class (get_free_busy) + + * pcs/cal-backend-db.c (cal_backend_db_get_free_busy): new function, + not implemented yet + + * pcs/cal-backend-file.c (cal_backend_file_get_free_busy): new funtion, + not implemented yet + 2001-06-20 Damon Chaplin <damon@ximian.com> * gui/calendar-config.[hc]: @@ -19,6 +35,12 @@ set the "None" item string before adding it to the combo, to stop the combo putting "None" in the entry initially. +2001-06-19 Rodrigo Moya <rodrigo@ximian.com> + + * gui/e-calendar-table.[ch]: added cut/copy/paste support. It works + with single selections (a single component selected) and with + multiple ones (several components selected) + 2001-06-19 Damon Chaplin <damon@ximian.com> * gui/dialogs/event-page.c: if the timezones of the start and end of diff --git a/calendar/gui/e-calendar-table.c b/calendar/gui/e-calendar-table.c index d95318cb04..2c862de720 100644 --- a/calendar/gui/e-calendar-table.c +++ b/calendar/gui/e-calendar-table.c @@ -32,6 +32,7 @@ #include <sys/stat.h> #include <unistd.h> #include <gnome.h> +#include <gtk/gtkinvisible.h> #include <gal/e-table/e-cell-checkbox.h> #include <gal/e-table/e-cell-toggle.h> #include <gal/e-table/e-cell-text.h> @@ -67,6 +68,12 @@ static gint e_calendar_table_on_right_click (ETable *table, ECalendarTable *cal_table); static void e_calendar_table_on_open_task (GtkWidget *menuitem, gpointer data); +static void e_calendar_table_on_cut (GtkWidget *menuitem, + gpointer data); +static void e_calendar_table_on_copy (GtkWidget *menuitem, + gpointer data); +static void e_calendar_table_on_paste (GtkWidget *menuitem, + gpointer data); static gint e_calendar_table_on_key_press (ETable *table, gint row, gint col, @@ -85,6 +92,21 @@ static void e_calendar_table_on_rows_deleted (ETableModel *model, int count, ECalendarTable *cal_table); +static void selection_clear_event (GtkWidget *invisible, + GdkEventSelection *event, + ECalendarTable *cal_table); +static void selection_received (GtkWidget *invisible, + GtkSelectionData *selection_data, + guint time, + ECalendarTable *cal_table); +static void selection_get (GtkWidget *invisible, + GtkSelectionData *selection_data, + guint info, + guint time_stamp, + ECalendarTable *cal_table); +static void invisible_destroyed (GtkWidget *invisible, + ECalendarTable *cal_table); + /* The icons to represent the task. */ #define E_CALENDAR_MODEL_NUM_ICONS 4 @@ -94,6 +116,7 @@ static char** icon_xpm_data[E_CALENDAR_MODEL_NUM_ICONS] = { static GdkPixbuf* icon_pixbufs[E_CALENDAR_MODEL_NUM_ICONS] = { 0 }; static GtkTableClass *parent_class; +static GdkAtom clipboard_atom = GDK_NONE; GtkType @@ -143,6 +166,10 @@ e_calendar_table_class_init (ECalendarTableClass *class) widget_class->focus_out_event = e_calendar_table_focus_out; widget_class->key_press_event = e_calendar_table_key_press; #endif + + /* clipboard atom */ + if (!clipboard_atom) + clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); } #ifdef JUST_FOR_TRANSLATORS @@ -463,6 +490,30 @@ e_calendar_table_init (ECalendarTable *cal_table) gtk_signal_connect (GTK_OBJECT (e_table), "key_press", GTK_SIGNAL_FUNC (e_calendar_table_on_key_press), cal_table); + + /* Set up the invisible widget for the clipboard selections */ + cal_table->invisible = gtk_invisible_new (); + gtk_selection_add_target (cal_table->invisible, + clipboard_atom, + GDK_SELECTION_TYPE_STRING, + 0); + gtk_signal_connect (GTK_OBJECT (cal_table->invisible), + "selection_get", + GTK_SIGNAL_FUNC (selection_get), + (gpointer) cal_table); + gtk_signal_connect (GTK_OBJECT (cal_table->invisible), + "selection_clear_event", + GTK_SIGNAL_FUNC (selection_clear_event), + (gpointer) cal_table); + gtk_signal_connect (GTK_OBJECT (cal_table->invisible), + "selection_received", + GTK_SIGNAL_FUNC (selection_received), + (gpointer) cal_table); + gtk_signal_connect (GTK_OBJECT (cal_table->invisible), + "destroy", + GTK_SIGNAL_FUNC (invisible_destroyed), + (gpointer) cal_table); + cal_table->clipboard_selection = NULL; } @@ -514,6 +565,11 @@ e_calendar_table_destroy (GtkObject *object) gtk_object_unref (GTK_OBJECT (cal_table->subset_model)); cal_table->subset_model = NULL; + if (cal_table->invisible) + gtk_widget_destroy (cal_table->invisible); + if (cal_table->clipboard_selection) + g_free (cal_table->clipboard_selection); + GTK_OBJECT_CLASS (parent_class)->destroy (object); } @@ -735,6 +791,9 @@ delete_cb (GtkWidget *menuitem, gpointer data) static GnomeUIInfo tasks_popup_one[] = { GNOMEUIINFO_ITEM_NONE (N_("Edit this task"), NULL, e_calendar_table_on_open_task), + GNOMEUIINFO_ITEM_NONE (N_("Cut"), NULL, e_calendar_table_on_cut), + GNOMEUIINFO_ITEM_NONE (N_("Copy"), NULL, e_calendar_table_on_copy), + GNOMEUIINFO_ITEM_NONE (N_("Paste"), NULL, e_calendar_table_on_paste), GNOMEUIINFO_SEPARATOR, GNOMEUIINFO_ITEM_NONE (N_("Mark as complete"), NULL, mark_as_complete_cb), GNOMEUIINFO_ITEM_NONE (N_("Delete this task"), NULL, delete_cb), @@ -742,6 +801,10 @@ static GnomeUIInfo tasks_popup_one[] = { }; static GnomeUIInfo tasks_popup_many[] = { + GNOMEUIINFO_ITEM_NONE (N_("Cut"), NULL, e_calendar_table_on_cut), + GNOMEUIINFO_ITEM_NONE (N_("Copy"), NULL, e_calendar_table_on_copy), + GNOMEUIINFO_ITEM_NONE (N_("Paste"), NULL, e_calendar_table_on_paste), + GNOMEUIINFO_SEPARATOR, GNOMEUIINFO_ITEM_NONE (N_("Mark tasks as complete"), NULL, mark_as_complete_cb), GNOMEUIINFO_ITEM_NONE (N_("Delete selected tasks"), NULL, delete_cb), GNOMEUIINFO_END @@ -785,6 +848,84 @@ e_calendar_table_on_open_task (GtkWidget *menuitem, open_task (cal_table, comp); } +static void +e_calendar_table_on_cut (GtkWidget *menuitem, gpointer data) +{ + ECalendarTable *cal_table; + + cal_table = E_CALENDAR_TABLE (data); + + e_calendar_table_on_copy (menuitem, data); + delete_selected_components (cal_table); +} + +static void +copy_row_cb (int model_row, gpointer data) +{ + ECalendarTable *cal_table; + CalComponent *comp; + gchar *comp_str; + icalcomponent *new_comp; + + cal_table = E_CALENDAR_TABLE (data); + + comp = calendar_model_get_component (cal_table->model, model_row); + if (!comp) + return; + + + if (cal_table->clipboard_selection) { + //new_comp = icalparser_parse_string (cal_table->clipboard_selection); + //if (!new_comp) + // return; + + //icalcomponent_add_component (new_comp, + // cal_component_get_icalcomponent (comp)); + //g_free (cal_table->clipboard_selection); + } + else { + new_comp = icalparser_parse_string ( + icalcomponent_as_ical_string (cal_component_get_icalcomponent (comp))); + if (!new_comp) + return; + } + + comp_str = icalcomponent_as_ical_string (new_comp); + cal_table->clipboard_selection = g_strdup (comp_str); + + free (comp_str); + icalcomponent_free (new_comp); +} + +static void +e_calendar_table_on_copy (GtkWidget *menuitem, gpointer data) +{ + ECalendarTable *cal_table; + ETable *etable; + + cal_table = E_CALENDAR_TABLE (data); + + if (cal_table->clipboard_selection) { + g_free (cal_table->clipboard_selection); + cal_table->clipboard_selection = NULL; + } + + etable = e_table_scrolled_get_table (E_TABLE_SCROLLED (cal_table->etable)); + e_table_selected_row_foreach (etable, copy_row_cb, cal_table); + + gtk_selection_owner_set (cal_table->invisible, clipboard_atom, GDK_CURRENT_TIME); +} + +static void +e_calendar_table_on_paste (GtkWidget *menuitem, gpointer data) +{ + ECalendarTable *cal_table = E_CALENDAR_TABLE (data); + + gtk_selection_convert (cal_table->invisible, + clipboard_atom, + GDK_SELECTION_TYPE_STRING, + GDK_CURRENT_TIME); +} static gint e_calendar_table_on_key_press (ETable *table, @@ -969,3 +1110,77 @@ e_calendar_table_get_spec (void) { return E_CALENDAR_TABLE_SPEC; } + +static void +invisible_destroyed (GtkWidget *invisible, ECalendarTable *cal_table) +{ + cal_table->invisible = NULL; +} + +static void +selection_get (GtkWidget *invisible, + GtkSelectionData *selection_data, + guint info, + guint time_stamp, + ECalendarTable *cal_table) +{ + if (cal_table->clipboard_selection != NULL) { + gtk_selection_data_set (selection_data, + GDK_SELECTION_TYPE_STRING, + 8, + cal_table->clipboard_selection, + strlen (cal_table->clipboard_selection)); + } +} + +static void +selection_clear_event (GtkWidget *invisible, + GdkEventSelection *event, + ECalendarTable *cal_table) +{ + if (cal_table->clipboard_selection != NULL) { + g_free (cal_table->clipboard_selection); + cal_table->clipboard_selection = NULL; + } +} + +static void +selection_received (GtkWidget *invisible, + GtkSelectionData *selection_data, + guint time, + ECalendarTable *cal_table) +{ + char *comp_str; + icalcomponent *icalcomp; + + if (selection_data->length < 0 || + selection_data->type != GDK_SELECTION_TYPE_STRING) { + return; + } + + comp_str = (char *) selection_data->data; + icalcomp = icalparser_parse_string ((const char *) comp_str); + if (icalcomp) { + icalcomponent *tmp_comp; + char *uid; + + /* there can be various components */ + tmp_comp = icalcomponent_get_first_component (icalcomp, ICAL_ANY_COMPONENT); + while (tmp_comp != NULL) { + CalComponent *comp; + + comp = cal_component_new (); + cal_component_set_icalcomponent (comp, icalcomp); + uid = cal_component_gen_uid (); + cal_component_set_uid (comp, (const char *) uid); + free (uid); + + tmp_comp = icalcomponent_get_next_component (icalcomp, ICAL_ANY_COMPONENT); + + cal_client_update_object ( + calendar_model_get_cal_client (cal_table->model), + comp); + gtk_object_unref (GTK_OBJECT (comp)); + } + } +} diff --git a/calendar/gui/e-calendar-table.h b/calendar/gui/e-calendar-table.h index 914a0bcd87..6ca523ac5c 100644 --- a/calendar/gui/e-calendar-table.h +++ b/calendar/gui/e-calendar-table.h @@ -83,6 +83,10 @@ struct _ECalendarTable /* The ECell used to view & edit dates. */ ECellDateEdit *dates_cell; + + /* The invisible widget used for cut/copy/paste */ + GtkWidget *invisible; + gchar *clipboard_selection; }; struct _ECalendarTableClass diff --git a/calendar/idl/evolution-calendar.idl b/calendar/idl/evolution-calendar.idl index ee8f91edcd..d14decca04 100644 --- a/calendar/idl/evolution-calendar.idl +++ b/calendar/idl/evolution-calendar.idl @@ -140,6 +140,9 @@ module Calendar { CalComponentAlarmsSeq getAlarmsInRange (in Time_t start, in Time_t end) raises (InvalidRange); + /* Returns free/busy objects for the given interval */ + CalObjUIDSeq getFreeBusy (in Time_t start, in Time_t end); + /* Gets the alarms for the specified component that trigger in * the specified time range. */ diff --git a/calendar/pcs/cal-backend-db.c b/calendar/pcs/cal-backend-db.c index d4773760f8..785ba98440 100644 --- a/calendar/pcs/cal-backend-db.c +++ b/calendar/pcs/cal-backend-db.c @@ -77,6 +77,9 @@ static GList* cal_backend_db_get_objects_in_range (CalBackend *backend, CalObjType type, time_t start, time_t end); +static GList *cal_backend_db_get_free_busy (CalBackend *backend, + time_t start, + time_t end); static GNOME_Evolution_Calendar_CalObjChangeSeq *cal_backend_db_get_changes ( CalBackend *backend, CalObjType type, const char *change_id); @@ -157,6 +160,7 @@ cal_backend_db_class_init (CalBackendDBClass *klass) backend_class->get_type_by_uid = cal_backend_db_get_type_by_uid; backend_class->get_uids = cal_backend_db_get_uids; backend_class->get_objects_in_range = cal_backend_db_get_objects_in_range; + backend_class->get_free_busy = cal_backend_db_get_free_busy; backend_class->get_changes = cal_backend_db_get_changes; backend_class->get_alarms_in_range = cal_backend_db_get_alarms_in_range; backend_class->get_alarms_for_object = cal_backend_db_get_alarms_for_object; @@ -934,6 +938,13 @@ cal_backend_db_get_objects_in_range (CalBackend *backend, return list; } +/* get_free_busy handler for the DB backend */ +static GList * +cal_backend_db_get_free_busy (CalBackend *backend, time_t start, time_t end) +{ + return NULL; +} + /* get_changes handler for the DB backend */ static GNOME_Evolution_Calendar_CalObjChangeSeq * cal_backend_db_get_changes (CalBackend *backend, CalObjType type, const char *change_id) diff --git a/calendar/pcs/cal-backend-file.c b/calendar/pcs/cal-backend-file.c index 1267f44e3f..d8951571f8 100644 --- a/calendar/pcs/cal-backend-file.c +++ b/calendar/pcs/cal-backend-file.c @@ -77,6 +77,7 @@ static CalObjType cal_backend_file_get_type_by_uid (CalBackend *backend, const c static GList *cal_backend_file_get_uids (CalBackend *backend, CalObjType type); static GList *cal_backend_file_get_objects_in_range (CalBackend *backend, CalObjType type, time_t start, time_t end); +static GList *cal_backend_file_get_free_busy (CalBackend *backend, time_t start, time_t end); static GNOME_Evolution_Calendar_CalObjChangeSeq *cal_backend_file_get_changes ( CalBackend *backend, CalObjType type, const char *change_id); @@ -150,6 +151,7 @@ cal_backend_file_class_init (CalBackendFileClass *class) backend_class->get_type_by_uid = cal_backend_file_get_type_by_uid; backend_class->get_uids = cal_backend_file_get_uids; backend_class->get_objects_in_range = cal_backend_file_get_objects_in_range; + backend_class->get_free_busy = cal_backend_file_get_free_busy; backend_class->get_changes = cal_backend_file_get_changes; backend_class->get_alarms_in_range = cal_backend_file_get_alarms_in_range; backend_class->get_alarms_for_object = cal_backend_file_get_alarms_for_object; @@ -976,6 +978,12 @@ cal_backend_file_get_objects_in_range (CalBackend *backend, CalObjType type, return event_list; } +/* Get_free_busy handler for the file backend */ +static GList * +cal_backend_file_get_free_busy (CalBackend *backend, time_t start, time_t end) +{ + return NULL; +} typedef struct { diff --git a/calendar/pcs/cal-backend.c b/calendar/pcs/cal-backend.c index 350e6468e4..d72a6fe5e6 100644 --- a/calendar/pcs/cal-backend.c +++ b/calendar/pcs/cal-backend.c @@ -134,11 +134,13 @@ cal_backend_class_init (CalBackendClass *class) class->get_uri = NULL; class->add_cal = NULL; class->open = NULL; + class->is_loaded = NULL; class->get_n_objects = NULL; class->get_object = NULL; class->get_type_by_uid = NULL; class->get_uids = NULL; class->get_objects_in_range = NULL; + class->get_free_busy = NULL; class->get_changes = NULL; class->get_alarms_in_range = NULL; class->get_alarms_for_object = NULL; @@ -326,6 +328,30 @@ cal_backend_get_objects_in_range (CalBackend *backend, CalObjType type, } /** + * cal_backend_get_free_busy: + * @backend: A calendar backend. + * @start: Start time for query. + * @end: End time for query. + * + * Builds a list of unique identifiers corresponding to free/busy calendar + * objects of the that occur or recur within the specified time range. + * + * Return value: A list of UID strings. The list should be freed using the + * cal_obj_uid_list_free() function. + **/ +GList * +cal_backend_get_free_busy (CalBackend *backend, time_t start, time_t end) +{ + g_return_val_if_fail (backend != NULL, NULL); + g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL); + g_return_val_if_fail (start != -1 && end != -1, NULL); + g_return_val_if_fail (start <= end, NULL); + + g_assert (CLASS (backend)->get_free_busy != NULL); + return (* CLASS (backend)->get_free_busy) (backend, start, end); +} + +/** * cal_backend_get_changes: * @backend: A calendar backend * @type: Bitmask with types of objects to return. diff --git a/calendar/pcs/cal-backend.h b/calendar/pcs/cal-backend.h index dab06b21e8..35cddaa492 100644 --- a/calendar/pcs/cal-backend.h +++ b/calendar/pcs/cal-backend.h @@ -88,6 +88,7 @@ struct _CalBackendClass { GList *(* get_objects_in_range) (CalBackend *backend, CalObjType type, time_t start, time_t end); + GList *(* get_free_busy) (CalBackend *backend, time_t start, time_t end); /* Change related virtual methods */ GNOME_Evolution_Calendar_CalObjChangeSeq * (* get_changes) ( @@ -125,6 +126,8 @@ GList *cal_backend_get_uids (CalBackend *backend, CalObjType type); GList *cal_backend_get_objects_in_range (CalBackend *backend, CalObjType type, time_t start, time_t end); +GList *cal_backend_get_free_busy (CalBackend *backend, time_t start, time_t end); + GNOME_Evolution_Calendar_CalObjChangeSeq * cal_backend_get_changes ( CalBackend *backend, CalObjType type, const char *change_id); diff --git a/calendar/pcs/cal.c b/calendar/pcs/cal.c index 42ccbf3cee..3bcc0c1f6b 100644 --- a/calendar/pcs/cal.c +++ b/calendar/pcs/cal.c @@ -227,6 +227,40 @@ impl_Cal_get_objects_in_range (PortableServer_Servant servant, return seq; } +/* Cal::get_free_busy method */ +static GNOME_Evolution_Calendar_CalObjUIDSeq * +impl_Cal_get_free_busy (PortableServer_Servant servant, + GNOME_Evolution_Calendar_Time_t start, + GNOME_Evolution_Calendar_Time_t end, + CORBA_Environment *ev) +{ + Cal *cal; + CalPrivate *priv; + time_t t_start, t_end; + GNOME_Evolution_Calendar_CalObjUIDSeq *seq; + GList *uids; + + cal = CAL (bonobo_object_from_servant (servant)); + priv = cal->priv; + + t_start = (time_t) start; + t_end = (time_t) end; + + if (t_start > t_end || t_start == -1 || t_end == -1) { + CORBA_exception_set (ev, CORBA_USER_EXCEPTION, + ex_GNOME_Evolution_Calendar_Cal_InvalidRange, + NULL); + return NULL; + } + + uids = cal_backend_get_free_busy (priv->backend, t_start, t_end); + seq = build_uid_seq (uids); + + cal_obj_uid_list_free (uids); + + return seq; +} + /* Cal::get_alarms_in_range method */ static GNOME_Evolution_Calendar_CalComponentAlarmsSeq * impl_Cal_get_alarms_in_range (PortableServer_Servant servant, @@ -503,6 +537,7 @@ cal_class_init (CalClass *klass) epv->getUIDs = impl_Cal_get_uids; epv->getChanges = impl_Cal_get_changes; epv->getObjectsInRange = impl_Cal_get_objects_in_range; + epv->getFreeBusy = impl_Cal_get_free_busy; epv->getAlarmsInRange = impl_Cal_get_alarms_in_range; epv->getAlarmsForObject = impl_Cal_get_alarms_for_object; epv->updateObject = impl_Cal_update_object; |