diff options
author | Ettore Perazzoli <ettore@src.gnome.org> | 2003-10-22 02:49:34 +0800 |
---|---|---|
committer | Ettore Perazzoli <ettore@src.gnome.org> | 2003-10-22 02:49:34 +0800 |
commit | 653cfffc0e00dfb59b36813c1b45c53d3f773c65 (patch) | |
tree | 9b486d5e383ec1391d60973d9cc548be0ef6d9d5 /calendar | |
parent | 0fb08f3ff81575a4749d851404233f34252dd2f2 (diff) | |
download | gsoc2013-evolution-653cfffc0e00dfb59b36813c1b45c53d3f773c65.tar.gz gsoc2013-evolution-653cfffc0e00dfb59b36813c1b45c53d3f773c65.tar.zst gsoc2013-evolution-653cfffc0e00dfb59b36813c1b45c53d3f773c65.zip |
Merge new-ui-branch to the trunk.
svn path=/trunk/; revision=22965
Diffstat (limited to 'calendar')
63 files changed, 9850 insertions, 5005 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog index 0d6fb57dfe..023e9f7ecd 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,9 +1,239 @@ -2003-10-17 Jeffrey Stedfast <fejj@ximian.com> +2003-10-21 Rodrigo Moya <rodrigo@ximian.com> - * conduits/calendar/Makefile.am: Fixed for libical changes. + * gui/calendar-component.c (calendar_component_init): fixed + a leak caused by only freeing 'base_uri' in some cases. + +2003-10-21 JP Rosevear <jpr@ximian.com> + + * gui/control-factory.c (get_prop): fix parse error + (set_prop): gnome_calendar_open was renamed + + * conduits/todo/todo-conduit.c (start_calendar_server): adapt to + the cal_client_new changes and the lack of a default calendar + routine + (pre_sync): don't have to pass a type for the default object any + more + + * conduits/calendar/calendar-conduit.c (start_calendar_server): + adapt to the cal_client_new changes and the lack of a default + calendar routine + (pre_sync): don't have to pass a type for the default object any + more + + * cal-client/cal-client.c (cal_client_open_async): add FIXME + comment + +2003-10-21 Rodrigo Moya <rodrigo@ximian.com> + + * pcs/cal-backend-file.c: store recurrences per object. + (free_object): free correctly the CalBackendFileObject's + contained in 'priv->comp_uid_hash'. + (lookup_component, check_dup_uid, add_component, remove_component, + match_object_sexp): + adapted to changes in comp_uid_hash. + +2003-10-20 Rodrigo Moya <rodrigo@ximian.com> + + * gui/gnome-cal.[ch] (gnome_calendar_add_event_uri): renamed + from gnome_calendar_open. + + * gui/calendar-component.c (load_uri_for_source): call + gnome_calendar_add_event_uri instead of setting the URI property on + the Bonobo control. + +2003-10-17 Rodrigo Moya <rodrigo@ximian.com> + + * gui/migration.c (process_calendar_dir): process subfolders. + +2003-10-17 Rodrigo Moya <rodrigo@ximian.com> + + * gui/migration.[ch] (migrate_old_calendars): new function. + + * gui/calendar-component.c (calendar_component_init): call + the above function to migrate from old setups. + + * gui/Makefile.am: added new files. + +2003-10-17 Jeffrey Stedfast <fejj@ximian.com> + + * conduits/calendar/Makefile.am: Fixed for libical build changes. * conduits/todo/Makefile.am: Same. +2003-10-17 Rodrigo Moya <rodrigo@ximian.com> + + * gui/e-cal-view.c (on_print): call + e_cal_view_get_visible_time_range, not the gnome_calendar_ + version. + (e_cal_view_new_appointment_for, e_cal_view_new_appointment, + e_cal_view_edit_appointment): new functions. + + * gui/gnome-cal.[ch] (gnome_calendar_new_appointment_for, + gnome_calendar_new_appointment, gnome_calendar_edit_object): + removed these functions, now available in e-cal-view. + + * gui/calendar-commands.c: + * gui/e-day-view.c: + * gui/e-week-view-event-item.c: + * gui/e-week-view.c: replaced calls to gnome_calendar_* with + e_cal_view_* equivalents. + +2003-10-17 Rodrigo Moya <rodrigo@ximian.com> + + * gui/e-cal-view.[ch] (e_cal_view_get_default_category): + (e_cal_view_set_default_category): new functions. + (e_cal_view_destroy): free the default_category field. + + * gui/e-day-view.[ch] (e_day_view_set_default_category): + removed obsolete function. + (e_day_view_init, e_day_view_destroy, e_day_view_do_key_press): + use the ECalView's default_category. + + * gui/e-week-view.[ch] (e_week_view_set_default_category): + removed obsolete function. + (e_week_view_init, e_week_view_destroy, e_week_view_do_key_press): + use the ECalView's default_category. + + * gui/gnome-cal.c (gnome_calendar_set_query): set the query + also on the list view by using the priv->views array. + (search_bar_category_changed_cb, gnome_calendar_set_default_client): + use the priv->views array. + (gnome_calendar_get_calendar_model): return the model for the + current view widget. + (gnome_calendar_open): removed tasks opening code. + +2003-10-16 Rodrigo Moya <rodrigo@ximian.com> + + * gui/dialogs/new-calendar.c (new_calendar_dialog): if the user + presses Cancel, just terminate. + +2003-10-16 Rodrigo Moya <rodrigo@ximian.com> + + * gui/calendar-component.c (calendar_component_init): create + directories for the newly-created calendars. + + * gui/dialogs/new-calendar.c (create_new_source_with_group): use + e_mkdir_hier instead of mkdir. + +2003-10-16 Rodrigo Moya <rodrigo@ximian.com> + + * gui/calendar-component.c (calendar_component_init): if no groups + are present in the configuration, create the "On This Computer" + group and the "Personal" and "Work" calendars on it. + + * gui/dialogs/new-calendar.c (new_calendar_dialog): moved the + source creation... + (create_new_source_with_group): ...here, and made the code create + the directory for the new calendar. + +2003-10-15 Hans Petter Jansson <hpj@ximian.com> + + * gui/e-select-names-editable.c (e_selct_names_editable_get_address): + EDestination -> EABDestination. + + * gui/gnome-cal.c (setup_widgets): evolution_dir -> ".evolution". + +2003-10-15 Rodrigo Moya <rodrigo@ximian.com> + + * gui/e-select-names-editable.c (e_select_names_editable_get_address): + use EABDestination instead of EDestination. + + * gui/gnome-cal.c (gnome_calendar_open): disabled tasks opening code. + +2003-10-15 Rodrigo Moya <rodrigo@ximian.com> + + * gui/e-meeting-list-view.c: adapted to new addressbook API. + + * gui/e-meeting-store.c: adapted to new addressbook API. + (find_zone): fixed usage of icalcomponent where an icalproperty + is expected. + (refresh_busy_periods): fixed call to cal_client_get_free_busy(). + + * gui/e-meeting-time-sel.c (e_meeting_time_selector_construct): + added missing variable. + +2003-10-15 Jeffrey Stedfast <fejj@ximian.com> + + * gui/dialogs/meeting-page.c: #include <gal/e-table/e-table.h> + +2003-10-15 Rodrigo Moya <rodrigo@ximian.com> + + * gui/e-meeting-list-view.c (start_addressbook_server): + updated to new addressbook API. + (book_open_cb): removed unneeded function, since we load + the local addressbook synchronously. + +2003-10-15 Rodrigo Moya <rodrigo@ximian.com> + + * pcs/Makefile.am: added missing header directories. + + * pcs/cal-factory.h: include <libical/ical.h>, not <ical.h>. + + * gui/dialogs/meeting-page.c: added missing headers. + (meeting_page_construct): free 'backend_address' as returned + by cal_client_get_cal_address(). Removed code to create the + meeting model's ETable not removed with the merge. + + * gui/e-meeting-list-view.c: updated addressbook headers. + + * gui/gnome-cal.h: added missing ',' in the GnomeCalendarViewType + enum. + +2003-10-14 Rodrigo Moya <rodrigo@ximian.com> + + * gui/e-day-view.c (e_day_view_update_query): dont set status + messages here, already set in e_cal_view_update_query. + (update_query): removed this function. + (e_day_view_recalc_day_starts): call e_day_view_update_query, + not update_query. + + * gui/e-week-view.c (e_week_view_update_query): dont set status + messages here, already set in e_cal_view_update_query. + + * gui/gnome-cal.c (adjust_query_for_view): new function to adjust + the query for the visible time range on a given view. + (gnome_calendar_set_query): call adjust_query_for_view for each + one of the views. + +2003-10-14 Rodrigo Moya <rodrigo@ximian.com> + + * gui/e-cal-view.c (e_cal_view_init): connect to signals on the + model we create here, so that we get notifications for changes. + + * gui/gnome-cal.c (gnome_calendar_set_query): set the query + on all models. + (gnome_calendar_open): update the date navigator query. + +2003-10-14 Rodrigo Moya <rodrigo@ximian.com> + + * pcs/cal.c (cal_notify_timezone_requested): never send NULL + strings to ORBit. + + * gui/e-cal-view.c (e_cal_view_create_popup_menu): removed + unneeded variables. Also, fixed a typo that was making the + menu options be disabled when they should be enabled. + +2003-10-13 Rodrigo Moya <rodrigo@ximian.com> + + * gui/e-cal-model.[ch] (e_cal_model_get_client_for_uri): new function. + + * gui/gnome-cal.[ch] (gnome_calendar_set_default_client): new function. + + * gui/calendar-component.c (primary_source_selection_changed_callback): + set the default client on the calendar view to be the primary + selection on the source list. + +2003-10-13 Rodrigo Moya <rodrigo@ximian.com> + + * gui/dialogs/new-calendar.c (new_calendar_dialog): set a default group + on the calendar group option menu and create the source if all checks + are passed. + +2003-10-12 Rodrigo Moya <rodrigo@ximian.com> + + * gui/dialogs/new-calendar.c (new_calendar_dialog): set up widgets + loaded from the Glade file. + 2003-10-10 Hans Petter Jansson <hpj@ximian.com> * gui/Makefile.am (etspec_DATA): Add e-cal-list-view.etspec. @@ -44,6 +274,66 @@ * gui/e-cal-list-view.[ch]: Implement ECalListView, subclassing ECalView. +2003-10-10 Rodrigo Moya <rodrigo@ximian.com> + + * gui/dialogs/new-calendar.[ch]: added new widget, which implements + the dialog to create new calendars. + + * gui/dialogs/new-calendar.glade: basic mockup of the dialog. + + * gui/dialogs/Makefile.am: added new files. + + * gui/calendar-commands.c (file_new_calendar_cb): open the new calendar + dialog to allow user to create a new cal. + +2003-10-10 Rodrigo Moya <rodrigo@ximian.com> + + * gui/control-factory.c (calendar_properties_init): pass the + BonoboControl to get_prop/set_prop. + (get_prop): obtain the GnomeCalendar from the control. + (set_prop): ditto, and when the URI property is changed, + sensitize the UI as approppriate. + + * gui/calendar-commands.c (calendar_control_sensitize_calendar_commands): + made this function public. + + * gui/calendar-commands.h: added new prototype. + +2003-10-10 Rodrigo Moya <rodrigo@ximian.com> + + * gui/calendar-commands.c (file_new_calendar_cb, + file_new_appointment_cb, file_new_event_cb, file_new_meeting_cb, + file_new_task_cb): callbacks for "New..." verbs. + (sensitize_calendar_commands): sensitize new verbs, and made it + sensitize correctly based on the set of clients currently loaded. + (sensitize_taskpad_commands): likewise. + +2003-10-09 Hans Petter Jansson <hpj@ximian.com> + + * gui/e-cal-model.c (get_classification): Adapt to libical API changes. + (ecm_set_value_at): Break after each case, so we don't set the passed value + in more than one field. + +2003-10-09 Rodrigo Moya <rodrigo@ximian.com> + + * gui/e-cal-view.c (e_cal_view_delete_selected_occurrence): + * cal-client/cal-client.c (cal_client_remove_object): added missing + argument when calling cal_client_remove_object_with_mod(). + +2003-10-09 Rodrigo Moya <rodrigo@ximian.com> + + * idl/evolution-calendar.idl: added missing 'rid' argument to the + removeObject method. + + * cal-client/cal-client.c (cal_client_remove_object_with_mod): + * pcs/cal-backend.h: + * pcs/cal-backend.c (cal_backend_remove_object): + * pcs/cal-backend-sync.h: + * pcs/cal-backend-sync.c (cal_backend_sync_remove_object, + _cal_backend_remove_object): + * pcs/cal-backend-file.c (cal_backend_file_remove_object): + * pcs/cal.c (impl_cal_removeObject): adapted to changes in IDL. + 2003-10-09 Jeffrey Stedfast <fejj@ximian.com> * cal-client/Makefile.am: INCLUDE path fixes for changes made to @@ -90,6 +380,165 @@ * gui/dialogs/task-details-page.glade: Make percent-complete of task details dialog numeric only. +2003-10-08 Chris Toshok <toshok@ximian.com> + + * gui/dialogs/e-delegate-dialog.c (e_delegate_dialog_construct): + EDestination => EABDestination, and e_destination => + eab_destination. + (e_delegate_dialog_get_delegate): same. + (e_delegate_dialog_get_delegate_name): same. + + * gui/dialogs/comp-editor-util.c: remove unnecessary #include of + e-destination.h. + + * gui/dialogs/alarm-options.c (alarm_to_malarm_widgets): + EDestination => EABDestination, and e_destination => + eab_destination. + (malarm_widgets_to_alarm): same. + + * gui/e-meeting-model.c (book_open_cb): track change to error + return codes. + (start_addressbook_server): use + e_book_async_get_default_addressbook. + (contacts_cb): rename cursor_cb to this, as we no longer get + passed a cursur, and we don't need to check the email address + since the query is now "is" instead of "contains". + (refresh_busy_periods): use an "is" query, and use + e_book_async_get_contacts instead of getting a CardCursor. + (process_section): this takes an EABDestination** instead of a + SimpleCardList*, which is gone. + (select_names_ok_cb): get "destinations" instead of + "simple_card_list". + +2003-10-08 Rodrigo Moya <rodrigo@ximian.com> + + * cal-client/cal-client.c (cal_client_is_read_only): fixed + documentation comments. + + * gui/calendar-commands.c (sensitize_calendar_commands): figure + out read-only menu items to disable based on the currently + selected object's CalClient. + +2003-10-08 Rodrigo Moya <rodrigo@ximian.com> + + * cal-client/cal-client.c: set better error m,essages on the + E_CALENDAR_CHECK_STATUS macro. + (cal_client_get_error_message): new function. + + * cal-client/cal-client.h: added new prototype. + + * gui/dialogs/comp-editor.c (save_comp): use the GError argument + for the cal_client_create/_modify_object calls, and display the + error message coming from the backend. + + * gui/comp-util.c (cal_comp_is_on_server): likewise. + +2003-10-07 Dan Winship <danw@ximian.com> + + * idl/evolution-calendar.idl (getDefaultObject): Remove the "type" + arg; the backend knows what type it is + + * pcs/cal.c (impl_Cal_getDefaultObject): Likewise + + * pcs/cal-backend.c (cal_backend_get_default_object): Likewise + + * pcs/cal-backend-sync.c (cal_backend_sync_get_default_object, + _cal_backend_get_default_object): Likewise + + * pcs/cal-backend-file.c (cal_backend_file_get_default_object): + Likewise. (Use cal_backend_get_kind() instead.) + + * cal-client/cal-client.c (cal_client_get_default_object): + Likewise + + * gui/comp-util.c (cal_comp_event_new_with_defaults, + cal_comp_task_new_with_defaults): Update calls to + cal_client_get_default_object(). + + * pcs/cal-backend-sync.c (_cal_backend_get_static_capabilities): + Use the right cal notification + +2003-10-07 Rodrigo Moya <rodrigo@ximian.com> + + * gui/e-cal-model.c (e_cal_model_create_component_with_defaults): + dont clone NULL icalcomponent's. + +2003-10-07 Rodrigo Moya <rodrigo@ximian.com> + + * gui/e-cal-model.c (e_cal_model_get_default_client): make sure we + always return a default client, if possible, since we rely on having + a default client in many places. + + * gui/e-day-view.c (e_day_view_do_key_press): dont create event if + e_cal_model_create_component_with_defaults returns NULL. + + * gui/e-week-view.c (e_week_view_do_key_press): dont create event if + e_cal_model_create_component_with_defaults returns NULL. + +2003-10-06 Rodrigo Moya <rodrigo@ximian.com> + + * gui/e-cal-model.c (e_cal_model_create_component_with_defaults): + make sure the component has always an UID. + + * gui/e-day-view.c (e_day_view_find_event_from_uid): + * gui/e-week-view.c (e_week_view_find_event_from_uid): check + pointers passed to strcmp(). + +2003-10-06 Rodrigo Moya <rodrigo@ximian.com> + + * gui/gnome-cal.c (gnome_calendar_open): added missing call to + cal_client_open(). + + * cal-client/cal-client.c (cal_client_new): fixed documentation + comments. + (cal_client_open): emit CAL_OPENED signal with appropriate status codes. + (open_sync): dont emit CAL_OPENED signal, it's already emitted in + cal_client_open(). + +2003-10-06 Rodrigo Moya <rodrigo@ximian.com> + + * gui/comp-editor-factory.c (open_client): + * gui/gnome-cal.c (gnome_calendar_open, gnome_calendar_construct): + * gui/calendar-offline-handler.c (backend_go_offline, backend_go_online, + calendar_offline_handler_init): adapted to changes in cal_client and + manage GError's returned by cal_client_open. + + * gui/e-itip-control.c: dont run anymore sub event loops. + (start_calendar_server): use synchronous interface for opening calendars. + (start_default_server): renamed it from *_async. + (start_calendar_server_cb): removed unneeded function. + (object_requested_cb): use sync interface. + + * gui/e-tasks.c (e_tasks_construct): dont create the CalClient here. + (e_tasks_open): do it here, where we've got all the info needed. + + * importers/icalendar-importer.c (update_single_object): killed warning. + (ical_importer_new, vcal_importer_new): don't create CalClient's here. + (load_file_fn): create them here. + (vcal_load_file_fn): and here. + (gnome_calendar_import_data_fn): fixed usage of cal_client_*. + + * */*: integrated JP's changes for synchronous open's in cal_client + and one model per view instead of one model for all views. + +2003-10-02 Rodrigo Moya <rodrigo@ximian.com> + + * cal-client/cal-client.c (cal_client_modify_object): return FALSE + if the icalcomponent is NULL. + + * gui/e-day-view.c (e_day_view_finish_resize): commit sequence on + CalComponent after changing start/end dates. + +2003-10-01 Rodrigo Moya <rodrigo@ximian.com> + + * gui/e-day-view.c (process_component): + * gui/e-week-view.c (process_component): expand recurrences here. + +2003-09-30 Rodrigo Moya <rodrigo@ximian.com> + + * pcs/cal-backend-file.c (match_recurrence_sexp): removed. + (match_object_sexp): dont expand recurrences here. + 2003-09-30 Mike Kestner <mkestner@ximian.com> * cal-util/cal-util-marshal.list : new VOID:STRING,STRING,STRING @@ -113,6 +562,519 @@ * conduits/calendar/Makefile.am: ditto +2003-09-26 JP Rosevear <jpr@ximian.com> + + * pcs/cal-backend.c (cal_backend_class_init): remove cal_added + signal + +2003-09-26 JP Rosevear <jpr@ximian.com> + + * pcs/cal.h: add protos + + * pcs/cal.c (cal_get_backend): accessor + (cal_get_listener): ditto + + * pcs/cal-factory.c (impl_CalFactory_getCal): update to new + routine name + + * pcs/cal-backend.h: add protos + + * pcs/cal-backend.c (cal_backend_init): init client mutex + (cal_backend_finalize): destroy client mutex + (cal_destroy_cb): just remove the client + (listener_died_cb): remove the client, the listener died so it + can't really do anything + (last_client_gone): signal the last client gone + (cal_backend_add_client): add a client with locking and listen for + the death of the listener + (cal_backend_remove_client): remove client + +2003-09-26 Rodrigo Moya <rodrigo@ximian.com> + + * pcs/cal-backend-sync.c (_cal_backend_create_object): only free the + returned UID if it's not NULL. + + * pcs/cal.c (cal_notify_object_created): dont send NULL strings to + ORBit code. + +2003-09-26 Rodrigo Moya <rodrigo@ximian.com> + + * gui/comp-util.c (cal_comp_is_on_server): free the icalcomponent + returned from cal_client_get_object, and return TRUE if we find + the component on the backend. + + * gui/e-day-view.c (process_component): + * gui/e-week-view.c (process_component): added missing case, so that + we also display recurrent meetings starting before the time range and + ending after the time range. + + * cal-client/cal-listener.c (impl_notifyReadOnly): pass the + 'read_only' argument to the signal callback correctly (a gboolean + not a 'gboolean *'). + + * gui/comp-editor-factory.c (resolve_pending_requests): removed + the g_assert on 'oc->pending != NULL', since there are now cases + (local calendar) where we get to call this function (cal_opened_cb) + with no pending requests yet. + +2003-09-25 JP Rosevear <jpr@ximian.com> + + * gui/calendar-commands.c (publish_freebusy_cmd): adapt to new + get_free_busy api + + * conduits/calendar/calendar-conduit.c (post_sync): ditto + (pre_sync): ditto + + * conduits/todo/todo-conduit.c (pre_sync): ditto + (post_sync): ditto + + * gui/e-meeting-model.c (refresh_busy_periods): ditto + + * gui/e-itip-control.c (send_freebusy): ditto + + * gui/e-cal-view.c (on_publish): ditto + + * cal-client/cal-listener.h: add signals + + * cal-client/cal-listener.c (build_change_list): move here from + cal-client.c + (impl_notifyChanges): implement + (build_free_busy_list): util to create the GList of free busy + objects + (impl_notifyFreeBusy): implement + (cal_listener_class_init): set free busy and changes epv methods, + add signals + + * cal-client/cal-client.h: update protos + + * cal-client/cal-client.c (cal_get_changes_cb): get changes call + back + (cal_get_free_busy_cb): get free busy call back + (cal_client_init): listen for free busy and changes signals + (cal_client_get_changes): convert to new threaded sync api + (cal_client_get_free_busy): ditto + + * pcs/cal.h: add protos + + * pcs/cal.c: remove dead type conversion function + (impl_Cal_getChanges): implement by just calling, no return stuff + (impl_Cal_getFreeBusy): ditto + (cal_notify_changes): do getChanges callback + (cal_notify_free_busy): do getFreeBusy callback + + * pcs/cal-backend.h: update protos, vmethods + + * pcs/cal-backend.c (cal_backend_get_free_busy): call through + (cal_backend_get_changes): ditto + + * pcs/cal-backend-sync.h: add vmethods, protos + + * pcs/cal-backend-sync.c (cal_backend_sync_get_changes): call + through + (cal_backend_sync_get_free_busy): ditto + (_cal_backend_get_changes): backend implementation, notify + (_cal_backend_get_free_busy): ditto + (cal_backend_sync_class_init): set free busy and changes + implementations + + * pcs/cal-backend-file.c (cal_backend_file_get_free_busy): convert + to sync backend method + (cal_backend_file_compute_changes_foreach_key): remove from the + hash here + (cal_backend_file_compute_changes): no need to build the sequence + here + (cal_backend_file_get_changes): convert to sync backend method + (cal_backend_file_class_init): set sync backend methods for free + busy and changes + + * idl/evolution-calendar.idl: convert getChanges and getFreeBusy + to new async api + +2003-09-25 JP Rosevear <jpr@ximian.com> + + * pcs/cal-backend.h: remove dead result enums + + * pcs/cal-backend.c: fix comments + + * idl/evolution-calendar.idl: remove dead exceptions + +2003-09-25 JP Rosevear <jpr@ximian.com> + + * pcs/cal.c (cal_notify_default_object): send back the empty + string if the object is NULL + (cal_notify_object): ditto + +2003-09-25 JP Rosevear <jpr@ximian.com> + + * gui/comp-editor-factory.c (edit_existing): convert to api + changes + + * conduits/todo/todo-conduit.c (local_record_from_uid): ditto + (pre_sync): ditto + + * conduits/calendar/calendar-conduit.c (local_record_from_uid): + ditto + (pre_sync): ditto + + * importers/icalendar-importer.c (update_single_object): ditto + + * gui/dialogs/comp-editor.c (obj_updated_cb): ditto + + * gui/e-itip-control.c (get_real_item): ditto + (find_server): ditto + + * gui/comp-util.c (cal_comp_is_on_server): ditto + (cal_comp_event_new_with_defaults): ditto + (cal_comp_task_new_with_defaults): ditto + + * cal-client/cal-listener.h: add signals + + * cal-client/cal-listener.c (impl_notifyDefaultObjectRequested): + implement + (impl_notifyObjectRequested): ditto + (cal_listener_class_init): set above epv implementations, add signals + + * cal-client/cal-client.h: update protos + + * cal-client/cal-client.c (cal_default_object_requested_cb): get + default object callback + (cal_object_requested_cb): get object callback + (cal_client_init): listen for get and get default object signals + (cal_client_get_default_object): convert to new sync api + (cal_client_get_object): ditto + + * pcs/cal.h: add protos + + * pcs/cal.c (impl_Cal_getDefaultObject): just call the backend, it + does the notification now + (impl_Cal_getObject): ditto + (cal_notify_default_object): do getDefaultObject response + (cal_notify_object): do getObject response + + * pcs/cal-backend.h: remove vmethods, protos + + * pcs/cal-backend.c: remove a couple of dead functions + (cal_backend_class_init): get_object_component is no longer a + vmethod + (cal_backend_get_default_object): call through + (cal_backend_get_object): ditto + + * pcs/cal-backend-sync.h: add protos, vmethods + + * pcs/cal-backend-sync.c (cal_backend_sync_get_default_object): + call through + (cal_backend_sync_get_object): ditto + (_cal_backend_discard_alarm): pass correct params to + cal_notify_discard_alarm + (_cal_backend_get_default_object): call through and notify + (_cal_backend_get_object): ditto + (cal_backend_sync_class_init): set backend implementations + + * pcs/cal-backend-file.c (cal_backend_file_get_default_object): + convert to sync backend method + (cal_backend_file_get_object): ditto + (cal_backend_file_compute_changes_foreach_key): just look up the + component rather than using the backend vmethod + (cal_backend_file_remove_object): return valid sync status codes + (cal_backend_file_class_init): move get_object, get_default_object + to sync class + + * idl/evolution-calendar.idl: convert getObject and + getDefaultObject to new async idl + +2003-09-25 JP Rosevear <jpr@ximian.com> + + * pcs/cal.c (impl_Cal_discardAlarm): just call the backend + function, it does the notification + (cal_notify_alarm_discarded): notify of discard alarm call + + * pcs/cal-backend.h: update proto + + * pcs/cal-backend.c (cal_backend_discard_alarm): call through + + * pcs/cal-backend-sync.h: add proto, vmethod + + * pcs/cal-backend-sync.c (cal_backend_sync_discard_alarm): call + through + (_cal_backend_discard_alarm): call through and notify + (cal_backend_sync_class_init): set discard alarm implementation + + * pcs/cal-backend-file.c (cal_backend_file_discard_alarm): match + sync backend vmethod + (cal_backend_file_class_init): set alarm vmethod implementation + + * idl/evolution-calendar.idl: switch discardAlarm to new api + + * gui/alarm-notify/alarm-queue.c (remove_queued_alarm): match new + api + + * cal-client/cal-listener.h: add signal + + * cal-client/cal-listener.c (impl_notifyAlarmDiscarded): implement + (cal_listener_class_init): add alarm, send, receive epv functions, + alarm signal + + * cal-client/cal-client.h: update proto + + * cal-client/cal-client.c (cal_alarm_discarded_cb): discardAlarm + callback + (cal_client_init): listen to discard alarm signal + (cal_client_discard_alarm): implement with new threaded sync api + +2003-09-25 JP Rosevear <jpr@ximian.com> + + * idl/evolution-calendar.idl: remove unused user exceptions + +2003-09-24 Rodrigo Moya <rodrigo@ximian.com> + + * pcs/cal-backend-util.[ch] (cal_backend_util_fill_alarm_instances_seq): + removed unneeded function. + +2003-09-24 JP Rosevear <jpr@ximian.com> + + * conduits/*/*.c: adjust to new timezone api calls + + * gui/*.c: ditto + + * gui/dialogs/*.c: ditto + + * cal-client/cal-listener.h: add new signals + + * cal-client/cal-listener.c (convert_status): convert invalid + object as well + (impl_notifyTimezoneRequested): implement + (impl_notifyDefaultTimezoneSet): ditto + (cal_listener_class_init): set epv implementations for timezone + functions + (cal_listener_class_init): create timezone response signals + + * cal-client/cal-client.h: update protos + + * cal-client/cal-client.c: fix return values all over the place + (cal_get_timezone_cb): getTimezone response + (cal_query_cb): setDefaultTimezone response + (cal_client_init): listen for new response signals + (cal_client_get_timezone): implement using new thread sync api + (cal_client_ensure_timezone_on_server): use add timezone call + (cal_client_set_default_timezone): oimplement using new thread sync + api + + * cal-client/cal-client-types.h: add invalid object status code + + * idl/evolution-calendar.idl: getQuery no longer raises any user + exceptions, remove dead types and exceptions + +2003-09-24 JP Rosevear <jpr@ximian.com> + + * pcs/cal.h: new protos + + * pcs/cal.c (impl_Cal_getTimezone): call backend implementation + (impl_Cal_addTimezone): ditto + (impl_Cal_setDefaultTimezone): ditto + (cal_class_init): set epv implementations of timezone functions + (cal_notify_timezone_requested): notify of get timezone response + (cal_notify_default_timezone_set): notify of default timezone + being set + + * pcs/cal-backend.h: new vmethods, protos + + * pcs/cal-backend.c (cal_backend_class_init): init new timezone + vmethods + (cal_backend_get_timezone): call through + (cal_backend_set_default_timezone): ditto + (cal_backend_add_timezone): ditto + (cal_backend_internal_get_default_timezone): ditto + (cal_backend_internal_get_timezone): ditto + + * pcs/cal-backend-sync.h: add vmethods, protos + + * pcs/cal-backend-sync.c (cal_backend_sync_get_timezone): call + through + (cal_backend_sync_set_default_timezone): ditto + (_cal_backend_set_default_timezone): call through and notify + (_cal_backend_get_timezone): ditto + (cal_backend_sync_class_init): set backend implementations for new + funcs + + * pcs/cal-backend-object-sexp.c (func_occur_in_time_range): get + time_t values based on the zone + + * pcs/cal-backend-file.c: reorg so we don't have to prototype + everything + (cal_backend_file_get_timezone): implement the sync backend way + (cal_backend_file_add_timezone): ditto + (cal_backend_file_set_default_timezone): ditto + (cal_backend_file_internal_get_default_timezone): internal method, + for sexp comparison + (cal_backend_file_internal_get_timezone): ditto + + * idl/evolution-calendar.idl: convert timezone routines to async + api + +2003-09-23 Rodrigo Moya <rodrigo@ximian.com> + + * pcs/cal-backend-object-sexp.c (func_occur_in_time_range): dont expand + recurrences, since they are supposed to be expanded in the backends. + (instance_occur_cb, resolve_tzid): removed unneeded functions. + + * pcs/cal-backend-file.c (cal_backend_file_add_timezone): guard against + adding the timezone if it's already there. + +2003-09-23 JP Rosevear <jpr@ximian.com> + + * pcs/cal.c (cal_notify_object_created): notify with the object, + not the uid + + * gui/e-cal-model.c (add_new_client): don't listen for + non-existent signal + +2003-09-23 JP Rosevear <jpr@ximian.com> + + * cal-client/cal-client.h: remove dead proto + +2003-09-23 JP Rosevear <jpr@ximian.com> + + * cal-client/cal-client.h: remove send result enum + + * gui/itip-utils.c (comp_server_send): use the new send_objects + routine + +2003-09-23 JP Rosevear <jpr@ximian.com> + + * cal-client/cal-client.h: remove send result enum + +2003-09-23 JP Rosevear <jpr@ximian.com> + + * cal-client/cal-client.h: remove enum, protos + + * cal-client/cal-client.c: remove remove status enum typing + +2003-09-23 Rodrigo Moya <rodrigo@ximian.com> + + * importers/icalendar-importer.c (update_objects): new function + to manage the update of components, taking into account + VTIMEZONE components. + (process_item_fn, gnome_calendar_import_data_fn): use + update_objects instead of cal_client_update_objects. + +2003-09-23 JP Rosevear <jpr@ximian.com> + + * pcs/cal.h: update proto + + * pcs/cal.c (impl_Cal_addTimezone): just call add_timezone, it + does the notification + (cal_notify_object_created): only notify the query if the object + matches + (cal_notify_object_removed): ditto + + * pcs/cal-backend.h: update proto, vmethod + + * pcs/cal-backend.c (cal_backend_add_timezone): returns void + + * pcs/cal-backend-sync.h: update proto, vmethod + + * pcs/cal-backend-sync.c (cal_backend_sync_remove_object): add the + object as an out param + (_cal_backend_remove_object): get the object and pass it in the + notification + + * pcs/cal-backend-file.c (cal_backend_file_create_object): kill + cal_backend_file_update_objects call, its more efficient to create + the comp ourselves; stamp the creation time, add the component to + the toplevel + (cal_backend_file_modify_object): kill the + cal_backend_file_update_objects call, add the component to the + toplevel + (cal_backend_file_remove_object): pass back the object when + removing + +2003-09-23 JP Rosevear <jpr@ximian.com> + + * cal-client/cal-query.c (cal_query_finalize): disconnect the + signal handlers + + * cal-client/cal-client.c (cal_client_get_query): unref the + listener when done + +2003-09-23 Rodrigo Moya <rodrigo@ximian.com> + + * gui/e-cal-view.c (selection_received): add VTIMEZONE components + contained in the clipboard data to the backend. + +2003-09-22 JP Rosevear <jpr@ximian.com> + + * gui/dialogs/comp-editor.c (save_comp): modify and create instead + of update, simplify mod code + +2003-09-22 JP Rosevear <jpr@ximian.com> + + * gui/e-day-view.c (e_day_view_finish_long_event_resize): modify + the object instead of update, simplify the instance handling + (e_day_view_finish_resize): ditto + (e_day_view_on_top_canvas_drag_data_received): ditto + (e_day_view_on_main_canvas_drag_data_received): ditto + +2003-09-22 Rodrigo Moya <rodrigo@ximian.com> + + * cal-client/cal-client.c (cal_client_get_alarms_in_range): use + 'has-alarms' function in the search expression. + + * pcs/cal-backend-object-sexp.c (func_has_alarms): new SExp function. + +2003-09-22 JP Rosevear <jpr@ximian.com> + + * gui/e-day-view.c (e_day_view_on_editing_stopped): create the + object if its not on the server or modify it if it is + + * gui/e-week-view.c (e_week_view_on_editing_stopped): we return if + there is no text and it *not* on the server + +2003-09-22 JP Rosevear <jpr@ximian.com> + + * gui/e-week-view.c (e_week_view_on_editing_stopped): create the + object if its not on the server or modify it if it is + +2003-09-22 JP Rosevear <jpr@ximian.com> + + * gui/gnome-cal.h: remove proto + + * gui/gnome-cal.c: remove gnome_calendar_unrecur_selection + + * gui/e-week-view.h: remove proto + + * gui/e-week-view.c: remove e_week_view_unrecur_appointment + + * gui/e-day-view.h: remove proto + + * gui/e-day-view.c: remove e_day_view_unrecur_appointment + + * gui/e-cal-view.c: remove on_unrecur_appointment (this is handled + better via recurrence id's now) + +2003-09-22 JP Rosevear <jpr@ximian.com> + + * gui/e-itip-control.c (update_attendee_status): ifdef out, leave + temporarily for reference, but otherwise it shouldn't be needed + (update_item): switch to using receive objects + (ok_clicked_cb): update item when receiving a reply + + * gui/e-calendar-table.c (selection_received): switch to using + create object from update_objects + + * gui/e-cal-view.c (selection_received_add_event): util routine to + prevent duplication + (selection_received): use above + + * gui/e-cal-model.c (ecm_set_value_at): switch to using modify + object from update_objects + (ecm_append_row): switch to using create object from + update_objects + + * gui/e-cal-model-calendar.c (ecmc_set_value_at): switch to using + modify object from update_objects + + * gui/e-cal-model-tasks.c (ecmt_set_value_at): ditto + 2003-09-22 Hans Petter Jansson <hpj@ximian.com> * cal-util/Makefile.am (libical_util_la_LIBADD): @@ -121,10 +1083,177 @@ * importers/Makefile.am (libevolution_calendar_importers_la_LIBADD): libicalvcal.la -> libicalvcal-evolution.la + +2003-09-19 Rodrigo Moya <rodrigo@ximian.com> + + * idl/evolution-calendar.idl: removed getAlarmsInRange and + getAlarmsForObject methods. + + * pcs/cal.c (impl_Cal_getAlarmsInRange, impl_Cal_getAlarmsForObject): + removed unneeded CORBA methods. + (cal_class_init): dont set removed methods in the epv. + + * pcs/cal-backend.[ch]: removed get_alarms_in_range and + get_alarms_for_object virtual methods. + (cal_backend_get_alarms_in_range, cal_backend_get_alarms_for_object): + removed. + (cal_backend_class_init): dont set removed virtual methods. + + * pcs/cal-backend-file.c (cal_backend_file_get_alarms_in_range, + cal_backend_file_get_alarms_for_object): removed. + (cal_backend_file_class_init): dont set removed virtual methods. + +2003-09-19 Rodrigo Moya <rodrigo@ximian.com> + + * cal-client/cal-client.c (cal_client_get_alarms_in_range): changed + to use queries. + (build_component_alarms_list): create the alarm list from a list + of iCalendar strings. + (build_alarm_instance_list): removed. + (cal_client_get_alarms_for_object): dont call the CORBA methods, + just get alarms by itself. + +2003-09-18 Rodrigo Moya <rodrigo@ximian.com> + + * cal-client/cal-listener.[ch]: added "add_timezone" signal. + (impl_notifyTimezoneAdded): implemented new CalListener method. + (cal_listener_class_init): create "add_timezone" signal for the class. + + * cal-client/cal-client.[ch] (cal_client_add_timezone): new function. + (cal_client_init): connect to "add_timezone" signal on the + CalListener. + (cal_add_timezone_cb): callback for the "add_timezone" signal. + +2003-09-18 Rodrigo Moya <rodrigo@ximian.com> + + * idl/evolution-calendar.idl: added 'notifyTimezoneAdded' method + to the Calendar::Listener interface. + + * pcs/cal-backend-sync.[ch] (cal_backend_sync_add_timezone): + (_cal_backend_add_timezone): new functions for the new virtual + method implementation. + + * pcs/cal.[ch] (cal_notify_timezone_added): new function. + + * pcs/cal-backend-file.c (cal_backend_add_timezone): converted to + return a CalBackendSyncStatus. + (cal_backend_file_class_init): the 'add_timezone' method we implement + is the one in the CalBackendSync class. + (cancel_receive_object): added missing 'return'. + (free_cal_component): removed unused function. + +2003-09-17 Rodrigo Moya <rodrigo@ximian.com> + + * pcs/cal-backend-file.c (cal_backend_add_timezone): added new + virtual method implementation. + + * pcs/cal.c (impl_Cal_addTimezone): check return value from + cal_backend_add_timezone, and set an exception if an error is + returned. + +2003-09-16 Rodrigo Moya <rodrigo@ximian.com> + + * idl/evolution-calendar.idl: added addTimezone method. + + * pcs/cal.c (impl_Cal_addTimezone): implemented new method. + (cal_class_init): set new method on the epv. + + * pcs/cal-backend.[ch]: added 'add_timezone' virtual method. + (cal_backend_add_timezone): implemented new virtual method. + + * pcs/cal-backend-file.c (cal_backend_file_modify_object): it's + cal_component_get_as_string, not cal_component_as_string. + + * cal-client/cal-client.c (cal_client_ensure_timezone_on_server): + dont use anymore updateObjects method, use addTimezone instead. + 2003-09-16 Rodrigo Moya <rodrigo@ximian.com> * conduits/todo/Makefile.am: removed libwombat reference. +2003-09-15 Rodrigo Moya <rodrigo@ximian.com> + + * pcs/cal-backend-file.c (cal_backend_file_create_object): return + the UID of the added object. + (cal_backend_file_remove_object): ditto for old_object. + +2003-09-15 JP Rosevear <jpr@ximian.com> + + * conduits/todo/todo-conduit.c (replace_record): switch to modify + object + (add_record): switch to using create object + + * conduits/calendar/calendar-conduit.c (process_multi_day): switch + to using create object + (add_record): switch to using create object + (replace_record): switch to modify object + + * cal-client/cal-listener.h: add signals + + * cal-client/cal-listener.c (impl_notifyObjectsReceived): + implement listener method + (build_object_list): ditto + (cal_listener_class_init): create receive_objects and send_objects + signals + + * cal-client/cal-client.h: add, update protos + + * cal-client/cal-client.c (cal_objects_received_cb): + receive_objects callback + (cal_objects_sent_cb): send_objects callback + (cal_client_init): listen for above signals + (cal_client_create_object): pass back uid + (cal_client_receive_objects): implement + (cal_client_send_objects): ditto + + * idl/evolution-calendar.idl: add receive/send objects methods and + yank updateObjects + + * pcs/cal.h: add protos + + * pcs/cal.c (impl_Cal_receiveObjects): implement + (impl_Cal_sendObjects): ditto + (cal_class_init): add epv methods + (cal_notify_objects_received): notify of objects received call, + updating queries + (cal_notify_objects_sent): notify of objects sent + + * pcs/cal-backend.h: remove proto + + * pcs/cal-backend.c (cal_backend_class_init): remove obj_updated + signal + (cal_backend_class_init): init vmethods properly + (cal_backend_receive_objects): call through + (cal_backend_send_objects): ditto + + * pcs/cal-backend-sync.h: add protos, vmethods + + * pcs/cal-backend-sync.c (cal_backend_sync_receive_objects): call + through + (cal_backend_sync_send_objects): ditto + (_cal_backend_receive_objects): call backend method and notify + (_cal_backend_send_objects): ditto + (cal_backend_sync_class_init): override send/receive object + vmethods + + * pcs/cal-backend-file.c (cal_backend_file_class_init): set + remove/send objects sync vmethods + (cal_backend_file_create_object): remove call to dead method + (cal_backend_file_remove_object): ditto + (cal_backend_file_modify_object): ditto + (cancel_received_object): cancel an object + (check_tzids): check we have all the tzid's for the object + (cal_backend_file_receive_objects): receive a bunch of objects via + itip + (cal_backend_file_send_objects): skeleton implementation + +2003-09-15 Rodrigo Moya <rodrigo@ximian.com> + + * idl/evolution-calendar.idl: added InvalidObject CallStatus. + + * pcs/cal-backend-file.c (cal_backend_file_create_object): implemented. + (cal_backend_file_modify_object): implemented. + 2003-09-15 Harry Lu <harry.lu@sun.com> * gui/apps_evolution_calendar.schemas: change last_notification_time's @@ -137,6 +1266,219 @@ (e_week_view_jump_to_button_item): new function, jump to the day view. (e_week_view_is_jump_button_visible): new function. + +2003-09-12 Rodrigo Moya <rodrigo@ximian.com> + + * pcs/cal.c (cal_notify_cal_address, cal_notify_alarm_email_address, + cal_notify_ldap_attribute, cal_notify_static_capability): + make sure we always notify listeners, regardless of whether the + string is empty or not. + + * cal-client/cal-client.c (check_capability): guard against using + NULL strings with strstr. + +2003-09-12 JP Rosevear <jpr@ximian.com> + + * cal-client/client-test.c (cal_opened_cb): listen for other query + signals + + * cal-client/cal-listener.h: add signals + + * cal-client/cal-listener.c (impl_notifyObjectCreated): implement + (impl_notifyObjectModified): implement + (cal_listener_class_init): assign epv implementations + (cal_listener_class_init): add create/modify object signals + + * cal-client/cal-client.h: add protos + + * cal-client/cal-client.c (cal_object_created_cb): object created + callback + (cal_object_modified_cb): object modified callback + (cal_client_init): listen for create/modify object signals from + the listener + (cal_client_create_object): call the create object method + (cal_client_modify_object): call the modify object method + + * cal-client/client-test.c (cal_opened_cb): listen for all the + query signals, tidy + +2003-09-12 JP Rosevear <jpr@ximian.com> + + * pcs/cal.c (impl_Cal_createObject): implement + (impl_Cal_modifyObject): ditto + (cal_class_init): set epv methods for create/modify + + * pcs/cal-backend.h: add protos, vmethod + + * pcs/cal-backend.c (cal_backend_class_init): init new vmethods + (cal_backend_create_object): call through + (cal_backend_modify_object): ditto + + * pcs/cal-backend-sync.h: add protos, vmethods + + * pcs/cal-backend-sync.c (cal_backend_sync_create_object): call + through + (cal_backend_sync_modify_object): ditto + (_cal_backend_create_object): create object and notify + (_cal_backend_modify_object): modify object and notify + + * pcs/cal-backend-file.c (cal_backend_file_create_object): + skeleton routine for creating objects + (cal_backend_file_modify_object): ditto for modifying + + * idl/evolution-calendar.idl: add createObject and modifyObject + calls + +2003-09-12 JP Rosevear <jpr@ximian.com> + + * pcs/cal.c (cal_notify_object_removed): its uid, not uids + +2003-09-12 JP Rosevear <jpr@ximian.com> + + * pcs/query.h: add protos + + * pcs/query.c (query_object_matches): use the sexp to check for a + match + (query_notify_objects_added_1): notify of one object added to + query + (query_notify_objects_modified_1): ditto for modification + (query_notify_objects_removed_1): ditto for removal + + * pcs/cal.h: add protos + + * pcs/cal.c (cal_notify_object_created): notify of object creation + (cal_notify_object_modified): notify of object modification + (cal_notify_object_removed): use the _1 routines + + * pcs/cal-backend-file.c (match_recurrence_sexp): this returns a + boolean + (cal_backend_file_update_objects): don't signal removals here now + + * idl/evolution-calendar.idl: add object created and modified + responses + + +2003-09-11 JP Rosevear <jpr@ximian.com> + + * pcs/cal.h: update proto + + * pcs/cal.c (cal_notify_object_removed): notify relevant queries + of removal + + * pcs/cal-backend.c (cal_backend_get_queries): ref the list before + passing it back + + * pcs/cal-backend-sync.c (_cal_backend_remove_object): pass uid to + notification + +2003-09-11 JP Rosevear <jpr@ximian.com> + + * pcs/cal-backend-file.c (match_recurrence_sexp): don't unref the + component + + * cal-client/client-test.c (cal_opened_cb): listen to objects + added signal + (objects_added_cb): print the object uid + +2003-09-11 JP Rosevear <jpr@ximian.com> + + * pcs/cal-backend-object-sexp.c (cal_backend_object_sexp_text): + return the base text + +2003-09-11 JP Rosevear <jpr@ximian.com> + + * gui/gnome-cal.c (update_query): fix c/p typo + +2003-09-11 JP Rosevear <jpr@ximian.com> + + * gui/gnome-cal.c (update_query): start the query + + * gui/e-cal-model.c (update_query_for_client): ditto + + * cal-client/client-test.c (cal_opened_cb): ditto + +2003-09-11 JP Rosevear <jpr@ximian.com> + + * cal-client/cal-query.h: add proto + + * cal-client/cal-query.c (cal_query_start): start the query + +2003-09-11 JP Rosevear <jpr@ximian.com> + + * gui/dialogs/delete-error.c (delete_error_dialog): accept GError + and base error messages on that + + * gui/dialogs/delete-error.h: update proto + + * gui/e-tasks.c (e_tasks_delete_completed): pass extra param to + cal_client_remove_object + + * conduits/todo/todo-conduit.c (delete_record): ditto + + * conduits/calendar/calendar-conduit.c (process_multi_day): ditto + (delete_record): ditto + + * gui/gnome-cal.c (gnome_calendar_purge): ditto + + * gui/dialogs/comp-editor.c (delete_comp): ditto + + * gui/e-cal-view.c (e_cal_view_cut_clipboard): pass the error to + delete_error_dialog + (delete_event): ditto + (e_cal_view_delete_selected_occurrence): ditto + + * gui/e-itip-control.c (remove_item): ditto + + * gui/e-calendar-table.c (delete_selected_components): ditto + + * cal-client/cal-listener.h: add signal + + * cal-client/cal-listener.c (impl_notifyObjectRemoved): implement + (cal_listener_class_init): set object removed implementation and + create signal + + * cal-client/cal-client.h: update protos + + * cal-client/cal-client.c (cal_object_removed_cb): object removal + callback + (cal_client_init): listen for object removal signal + (cal_client_remove_object_with_mod): make call synchronous + (cal_client_remove_object): pass new params + + * pcs/cal.h: add proto + + * pcs/cal.c (impl_Cal_removeObject): just call the backend + function + (cal_notify_object_removed): notify of removal + + * pcs/cal-backend.h: remove and update protos, remove signal + + * pcs/cal-backend.c (cal_backend_class_init): kill obj_removed + signal + (cal_backend_remove_object): there is no return value now + + * pcs/cal-backend-sync.h: add vmethod, proto + + * pcs/cal-backend-sync.c (cal_backend_sync_remove_object): call + through + (_cal_backend_remove_object): remove the object and then do the + notification + + * pcs/cal-backend-file.c (cal_backend_file_class_init): remove + object is not part of the sync class + (cal_backend_file_update_objects): there is no more removed signal + (cal_backend_file_remove_object): return sync status codes + + * idl/evolution-calendar.idl: make removeObject oneway and and a + notification method in the listener + +2003-09-11 Rodrigo Moya <rodrigo@ximian.com> + + * pcs/query.[ch] (query_get_text): new function. + (query_get_object_sexp): new function. + + * pcs/cal-backend-file.c (cal_backend_file_start_query): implemented. + 2003-09-11 Hans Petter Jansson <hpj@ximian.com> * cal-util/Makefile.am (libcal_util_la_LIBADD): @@ -193,12 +1535,279 @@ Statically link with wombat. Fix ETodo conduit. (Mdk bug #5348) + +2003-09-10 JP Rosevear <jpr@ximian.com> + + * pcs/cal.h: update proto + + * pcs/cal.c (impl_Cal_getObjectList): just call the backend, it + will do the notification now + (cal_notify_object_list): the list is a list of strings + + * pcs/cal-backend.h: update vmethod, proto + + * pcs/cal-backend.c (cal_backend_get_object_list): call through + + * pcs/cal-backend-sync.h: add proto, vmethod + + * pcs/cal-backend-sync.c (cal_backend_sync_get_object_list): call + through + (_cal_backend_get_object_list): get the list of objects from the + sync backend and do the notification + (cal_backend_sync_class_init): set vmethod implementation + + * pcs/cal-backend-file.c (cal_backend_file_class_init): the get + object list call is now part of the sync backend + (cal_backend_file_get_object_list): return a status and put the + object list in the passed in param + +2003-09-10 JP Rosevear <jpr@ximian.com> + + * pcs/cal-backend.c (cal_backend_finalize): unref the elist + (cal_backend_init): init the query elist + +2003-09-10 JP Rosevear <jpr@ximian.com> + + * gui/gnome-cal.c (dn_query_objects_added_cb): match new query + signals - just tag here + (dn_query_objects_modified_cb): always retag + (dn_query_objects_removed_cb): ditto + (update_query): connect to new signals + (gnome_calendar_destroy): we don't keep a list of expunging + queries + (gnome_calendar_purge): no need to do the + expunge async, just get the object list immediately + + * gui/e-tasks.c (e_tasks_delete_completed): no need to do the + expunge async, just get the object list immediately + + * gui/e-cal-model.c (query_objects_added_cb): callback for objects + added to the query + (query_objects_modified_cb): ditto for modifications + (query_objects_removed_cb): ditto for removed + (query_progress_cb): progress of the query + (query_done_cb): query is done + (update_query_for_client): connect to the new signals + + * cal-client/client-test.c (cal_opened_cb): run a query + + * cal-client/cal-query.c: we are given the listener now - listen + for signals from the listener and emit signals matching the api + changes + + * cal-client/query-listener.[hc]: rewrite to match new query + listener methods and emit signals rather than using function + callbacks + + * cal-client/cal-marshal.list: add to marshallers + + * cal-client/cal-listener.h: add query signal + + * cal-client/cal-listener.c (impl_notifyQuery): implement + (cal_listener_class_init): set notifyQuery method + (cal_listener_class_init): add query signal + + * cal-client/cal-client.h: update protos + + * cal-client/cal-client.c (cal_query_cb): handle response to + getQuery + (cal_client_init): listen for query signal + (cal_client_get_query): get a query from the calendar + + * pcs/query.h: update protos + + * pcs/query.c: rewrite to implement the query start method and + provide notification calls + + * pcs/cal.h: add proto + + * pcs/cal.c (impl_Cal_getQuery): re-implement so the backend + doesn't create the query for us + (cal_notify_query): respond with the query + + * pcs/cal-factory.c: re-order includes + + * pcs/cal-common.h: add types + + * pcs/cal-backend.h: update protos, vmethods + + * pcs/cal-backend.c (cal_backend_class_init): init start_query + vmethod + (cal_backend_finalize): free mutex + (cal_backend_start_query): call through + (cal_backend_add_query): add a query to the list the backend is + running + (cal_backend_get_queries): get the query list + + * pcs/cal-backend-object-sexp.h: add proto + + * pcs/cal-backend-file.c (cal_backend_file_start_query): skeleton + for new backend implementation + + * pcs/Makefile.am: don't build dead files + + * idl/evolution-calendar.idl: make the getQuery call async, make + the query listener calls oneway and match the addressbook + +2003-09-09 Rodrigo Moya <rodrigo@ximian.com> + + * pcs/cal-backend-file.c (cal_backend_file_get_object_component): + added case for getting the individual recurrences if 'rid' is + not NULL, + +2003-09-09 Rodrigo Moya <rodrigo@ximian.com> + + * pcs/cal-backend-file.c (match_object_sexp): expand recurrences + for recurrent objects. + (match_recurrence_sexp): add the recurrences that match the query + expression to the object list. + +2003-09-08 Rodrigo Moya <rodrigo@ximian.com> + + * pcs/cal-backend-file.c: don't store all recurrences in the + private structure. + +2003-09-04 Rodrigo Moya <rodrigo@ximian.com> + + * gui/e-day-view.c (process_component): + * gui/e-week-view.c (process_component): dont expand recurrences, + since they are now expanded by the backends. + +2003-09-02 JP Rosevear <jpr@ximian.com> + + * gui/tasks-control.c (sensitize_commands): adapt to cal-client + threaded sync api changes + + * gui/itip-utils.c (itip_organizer_is_user): ditto + + * gui/gnome-cal.c (gnome_calendar_purge): ditto + + * gui/e-meeting-model.c (process_section): ditto + + * gui/e-calendar-table.c (e_calendar_table_show_popup_menu): ditto + + * gui/e-cal-view.c (e_cal_view_create_popup_menu): ditto + + * gui/calendar-commands.c (sensitize_calendar_commands): ditto + (sensitize_taskpad_commands): ditto + + * gui/dialogs/task-editor.c (set_menu_sens): ditto + + * gui/dialogs/meeting-page.c (meeting_page_construct): ditto + + * gui/dialogs/event-editor.c (set_menu_sens): ditto + + * gui/dialogs/alarm-page.c (add_clicked_cb): ditto + + * conduits/calendar/calendar-conduit.c (pre_sync): convert to + cal_client api changes + + * conduits/todo/todo-conduit.c (pre_sync): ditto + + * cal-client/client-test.c (list_uids): match new error handling + + * cal-client/cal-marshal.list: marshallers + + * cal-client/cal-listener.[hc]: emit signals for corba listener + callbacks - start with is_read_only, get_static_capabilities, + get_cal_address, get_ldap_attribute, open, remove and object_list + + * cal-client/cal-client.h: move the status enum away from here, + update protos to new thread sync api standard + + * cal-client/cal-client.c: the listener emits signals instead of + using callback functions now and we return booleans + GError in + outs for results + (e_calendar_error_quark): for GError handling + (cal_read_only_cb): handle listener op callback + (cal_cal_address_cb): ditto + (cal_alarm_address_cb): ditto + (cal_ldap_attribute_cb): ditto + (cal_static_capabilities_cb): ditto + (cal_opened_cb): ditto + (cal_removed_cb): ditto + (cal_object_list_cb): ditto + + * cal-client/cal-client-types.h: add GError stuff + + * cal-client/Makefile.am: build glib marshal stuff + + * pcs/query.c (backend_opened_cb): comment out some break + temporarily + + * pcs/cal.h: add protos + + * pcs/cal.c (impl_Cal_open): just call the backend method, it will + handle the notification + (impl_Cal_remove): ditto + (impl_Cal_isReadOnly): ditto + (impl_Cal_getCalAddress): ditto + (impl_Cal_getAlarmEmailAddress): ditto + (impl_Cal_getLdapAttribute): ditto + (impl_Cal_getStaticCapabilities): ditto + (impl_Cal_getObjectList): simplify + (cal_new): set poa to be threaded + (cal_notify_read_only): notification utils + (cal_notify_cal_address): ditto + (cal_notify_alarm_email_address): ditto + (cal_notify_ldap_attribute): ditto + (cal_notify_static_capabilities): ditto + (cal_notify_open): ditto + (cal_notify_remove): ditto + (cal_notify_object_list): ditto + + * pcs/cal-factory.c (impl_CalFactory_getCal): dup the key and the + object + (cal_factory_new): set poa to be threaded + + * pcs/cal-backend.h: update vmethods and protos + + * pcs/cal-backend.c (cal_backend_get_cal_address): we no longer + return anything - the callee is responsible for notification + (cal_backend_get_alarm_email_address): ditto + (cal_backend_get_ldap_attribute): ditto + (cal_backend_get_static_capabilities): ditto + (cal_backend_open): ditto + (cal_backend_remove): ditto + + * pcs/cal-backend-file.h: update inheritance + + * pcs/cal-backend-file.c: inherit from CalBackendSync and make + is_read_only, get_static_capabilities, get_cal_address, get_ldap_attribute, open and + remove match + + * pcs/Makefile.am: build new files + +2003-09-02 JP Rosevear <jpr@ximian.com> + + * idl/evolution-calendar.idl: make all listener callbacks one ways + +2003-09-02 Rodrigo Moya <rodrigo@ximian.com> + + * pcs/cal-backend-file.c (match_recurrence_sexp, match_object_sexp): + new callbacks for g_hash_table_foreach in get_object_list. + (cal_backend_file_get_object_list): don't use the priv->comp list + to check the components, use the hash table, which contains all + the recurrences already expanded. + (add_component): only expand recurrences for recurrent components. + 2003-09-01 Andrew Wu <Yang.Wu@sun.com> - * gui/e-day-view.c: - (e_day_view_change_event_end_time_up): - (e_day_view_change_event_end_time_down): - Use "ctrl+shift+alt+Up/Down" to change the end time of the editing event. + * gui/e-day-view.c: + (e_day_view_change_event_end_time_up): + (e_day_view_change_event_end_time_down): Use + "ctrl+shift+alt+Up/Down" to change the end time of the editing + event. + +2003-08-29 Rodrigo Moya <rodrigo@ximian.com> + + * pcs/cal-backend-file.c (lookup_component): take into account the 'rid' + argument. + (get_rid_string): new function to convert the recurrence ID to string. + (add_recurrence_to_object): callback for cal_recur_generate_instances. + (add_component): expand recurrences and g_strdup the hash's key. + (free_cal_component): free also the hash's key. + 2003-08-28 Hans Petter Jansson <hpj@ximian.com> * gui/alarm-notify/alarm-queue.c (tray_icon_blink_cb) @@ -243,6 +1852,72 @@ * gui/alarm-notify/alarm-notify.c (AlarmNotify_removeCalendar): set the initial value of lc_ptr and orig_str_ptr to NULL to avoid crash. + +2003-08-26 Rodrigo Moya <rodrigo@ximian.com> + + * idl/evolution-calendar.idl: QueryListener::notifyObjUpdated now gets + a sequence of CalObj's. + + * pcs/query.c (add_component): send the whole object to the listener, + not just the UID. Improved the way the listeners are notified, by allocating + a CORBA sequence to be used for all listeners, not one for each. + (match_component): pass the CalComponent to add_component, not only the UID. + (start_cached_query_cb): send the whole object to the listener. + + * cal-client/cal-query.[ch]: changed argument names for "obj_updated" + signal. + (obj_updated_cb): pass the calobj's, not uid's. + + * gui/e-tasks.c (query_obj_updated_cb): + * gui/gnome-cal.c (dn_query_obj_updated_cb, purging_obj_updated_cb): + * gui/e-cal-model.c (query_obj_updated_cb): we now get the object's + string representation instead of the UID. + +2003-08-25 Rodrigo Moya <rodrigo@ximian.com> + + * cal-client/cal-client.c (cal_client_get_object): added a 'rid' argument + to match the IDL method. + + * conduits/calendar/calendar-conduit.c (local_record_from_uid): + * conduits/todo/todo-conduit.c (local_record_from_uid): + * gui/comp-editor-factory.c (edit_existing): + * gui/comp-util.c (cal_comp_is_on_server): + * gui/e-cal-model.c (query_obj_updated_cb): + * gui/e-itip-control.c (find_server, get_real_item, update_attendee_status): + * gui/gnome-cal.c (dn_query_obj_updated_cb, purging_obj_updated_cb): + * gui/dialogs/comp-editor.c (obj_updated_cb): adapted to changes in + cal_client_get_object(). + +2003-08-23 Rodrigo Moya <rodrigo@ximian.com> + + * pcs/query-backend.c (object_updated_cb): + * pcs/cal-backend.c (cal_backend_get_type_by_uid): use 'rid' parameter + where appropriate. + + * pcs/cal-backend-file.c (check_dup_uid): removed unused variables. + (cal_backend_file_compute_changes_foreach_key): pass a NULL 'rid' + to cal_backend_get_object(). + (lookup_component): get a 'rid' argument also. + (cal_backend_file_cancel_object, cal_backend_file_remove_object): + pass correct number of parameters to lookup_component(). + +2003-08-22 Rodrigo Moya <rodrigo@ximian.com> + + * idl/evolution-calendar.idl: use UID/RID pairs to identify objects. + + * pcs/cal.c (impl_Cal_getObject): added 'rid' parameter. + + * pcs/cal-backend.c (cal_backend_get_object): added 'rid' parameter. + (cal_backend_get_object_component): ditto. + (get_object): ditto. + + * pcs/cal-backend-file.c (cal_backend_file_get_object_component): + added 'rid' parameter. + (lookup_component): added 'rid' parameter and made it search for the + recurrence when that parameter is not NULL. + (cal_backend_file_get_alarms_for_object, cal_backend_file_update_object): + adapted to changes in lookup_component(). + 2003-08-22 Frederic Crozat <fcrozat@mandrakesoft.com> * gui/alarm-notify/notify-main.c: (main): @@ -300,6 +1975,111 @@ (gnome_calendar_get_search_bar_widget), (gnome_calendar_get_view_notebook_widget): new functions + +2003-08-20 Rodrigo Moya <rodrigo@ximian.com> + + * pcs/query-backend.c (foreach_uid_cb): use the icalcomponent + to call icalcomponent_get_uid, not the string. + +2003-08-20 Rodrigo Moya <rodrigo@ximian.com> + + * pcs/cal-backend-file.c: store objects by UID and RID. + (free_object): new function to free the CalBackendFileObject structure. + (cal_backend_file_dispose): use free_object callback to remove the + objects in the comp_uid_hash. + (lookup_component): search correctly the component in the new hash + table organizarion. + (check_dup_uid): ditto. + (add_component): ditto. + (remove_component): ditto. + +2003-08-19 JP Rosevear <jpr@ximian.com> + + * gui/gnome-cal.c (setup_widgets): set up models here + (gnome_calendar_construct): not here + + * conduits/calendar/calendar-conduit.c + (e_calendar_context_destroy): we have a list of calcomponents + rather than uids now + (process_multi_day): build a list of components rather than uids + (pre_sync): use get_object_list instead of getting uids + (for_each): create local records from calcomponents + + * conduits/todo/todo-conduit.c: as above + + * gui/print.c (instance_cb): mark as true if we found an instance + (print_month_small): see if atleast one instance exists in a + slight different way + + * cal-client/client-test.c (list_uids): use get_object_list + + * cal-client/cal-listener.h: update protos + + * cal-client/cal-listener.c (cal_listener_class_init): set object + list callback implementation + (impl_notifyObjectListRequested): implement + (cal_listener_construct): take object list callback function + (cal_listener_new): ditto + + * cal-client/cal-client.h: update protos, add status + + * cal-client/cal-client.c (e_calendar_new_op): create new op + (e_calendar_get_op): retrieve current op + (e_calendar_free_op): free the op + (e_calendar_remove_op): clear current op + (cal_client_init): create new mutex + (cal_client_finalize): destroy mutex + (build_object_list): build list of icalcomponents + (cal_object_list_cb): handle getObjectList response + (real_open_calendar): pass extra listener arg + (cal_client_get_object_list): implement using thread safe mutex + locking + (cal_client_get_object_list_as_comp): return calcomponents instead + of icalcomponents + (cal_client_generate_instances): just get the object list - no + need to make it atomic since get_object_list is already atomic + + * pcs/query.c (query_finalize): free new sexp class + (parse_sexp): use new sexp class + (match_component): ditto + + * pcs/query-backend.c (foreach_uid_cb): use icalcomponent to + extract uid + (query_backend_new): get all objects using object list call + + * pcs/cal.c (impl_Cal_getObjectList): implement + (cal_class_init): adjust for idl method changes + + * pcs/cal-backend.h: update vmethods, add proto + + * pcs/cal-backend.c (cal_backend_class_init): remove get_uids and + get_objects_in_range vmethods, add get_object_list vmethod + (cal_backend_get_object_list): call through to vmethod implementation + + * pcs/cal-backend-object-sexp.[hc]: nice class to represent a sexp + and search cal components + + * pcs/cal-backend-file.c (cal_backend_file_class_init): remove + get_uids and get_objects_in_range calls and set get_object_list + call + (cal_backend_file_get_object_list): implement + (create_user_free_busy): use sexp ops to implement + (cal_backend_file_compute_changes): just iterate over the + component list rather than fetching uids + + * pcs/Makefile.am: build new files + + * idl/evolution-calendar.idl: make opening a oneway call, add + getObjectList call, remove getUIDS and getObjectsInRange call - + both can be done with getObjectList; make listener callbacks + oneway + +2003-08-19 Rodrigo Moya <rodrigo@ximian.com> + + * gui/gnome-cal.c (gnome_calendar_purge): don't leak the client list. + (gnome_calendar_destroy): disconnect from all callbacks on all + loaded clients. + 2003-08-19 Rodrigo Moya <rodrigo@ximian.com> * gui/e-cal-model-tasks.c (ecmt_get_color_for_component): use @@ -321,6 +2101,51 @@ * gui/e-week-view.c (e_week_view_add_event, e_week_view_do_key_press): same as e-day-view.c +2003-08-18 Ettore Perazzoli <ettore@ximian.com> + + * gui/calendar-component.c (impl_createControls): Oops, pass + [NULL, NULL] to gtk_scrolled_window_new(). + +2003-08-18 Ettore Perazzoli <ettore@ximian.com> + + * gui/main.c (factory): Ref the object from + calendar_component_peek() before returning it. + +2003-08-17 Ettore Perazzoli <ettore@ximian.com> + + * gui/control-factory.h: #include <bonobo/bonobo-control.h>. + + * gui/Makefile.am (libevolution_calendar_la_LIBADD): Link to + libeutil. + + * gui/e-calendar-table.c (e_calendar_table_set_status_message): + Don't use the global_shell_client. + + * gui/main.c (factory): Call calendar_component_peek() for the + GNOME_Evolution_Calendar_Component OAFIID. + + * gui/GNOME_Evolution_Calendar.server.in.in: Set up the + GNOME_Evolution_Calendar_Component server and rename + GNOME_Evolution_Calendar_Factory to + GNOME_Evolution_Calendar_Factory_2. + * gui/main.c: Updated IDs accordingly. + + * gui/e-meeting-time-sel.c (e_meeting_time_selector_construct): + Use calendar_component_peek_config_directory() instead of + evolution_dir. + * gui/gnome-cal.c (setup_widgets): Likewise. + (gnome_calendar_destroy): Likewise. + * gui/dialogs/meeting-page.c (meeting_page_construct): Likewise. + + * gui/gnome-cal.c (gnome_calendar_open): #if 0 some code for + figuring out where the task list is. + + * gui/calendar-component.c: New file. + * gui/calendar-component.h: New file. + + * gui/itip-utils.c (itip_addresses_get): Unref the GConf client + from gconf_client_get_default. + 2003-08-15 Rodrigo Moya <rodrigo@ximian.com> * gui/e-cal-model.c (ecm_get_color_for_component): use tigert's @@ -341,16 +2166,6 @@ 2003-08-14 Rodrigo Moya <rodrigo@ximian.com> - * gui/e-cal-model.c (e_cal_model_create_component_with_defaults): - use the default client to call cal_comp_*_new_with_defaults, and - if no client is available, just create an empty icalcomponent. - - * gui/e-cal-view.c (e_cal_view_init): create an empty model. - - * gui/e-week-view.c (e_week_view_add_event): use the event's client. - -2003-08-14 Rodrigo Moya <rodrigo@ximian.com> - * gui/e-cal-model.[ch] (e_cal_model_free_component_data): new function. @@ -367,6 +2182,46 @@ e_week_view_update_event_cb, e_week_view_remove_event_cb, e_week_view_free_events): same as EDayView. +2003-08-14 Rodrigo Moya <rodrigo@ximian.com> + + * gui/e-cal-model.c (e_cal_model_create_component_with_defaults): + use the default client to call cal_comp_*_new_with_defaults, and + if no client is available, just create an empty icalcomponent. + + * gui/e-cal-view.c (e_cal_view_init): create an empty model. + + * gui/e-week-view.c (e_week_view_add_event): use the event's client. + +2003-08-13 Rodrigo Moya <rodrigo@ximian.com> + + * gui/gnome-cal.c (gnome_calendar_open): unref the client if there + is an error. + (update_query): set status bar messages for progress. + (update_query_timeout): re-enabled. + (client_cal_opened_cb): install timeout handler for the query updates. + + * gui/e-cal-view.c (e_cal_view_set_model): connect to all appropriate + signals on the model, to be called for every change. + (model_row_changed_cb, model_rows_changed_cb): new model callbacks. + + * gui/e-week-view-event-item.c (e_week_view_event_item_draw): colorize + the background for multiple days events. + +2003-08-13 Rodrigo Moya <rodrigo@ximian.com> + + * gui/e-cal-model.c (ecm_append_row, ecm_get_color_for_component): + * gui/e-cal-model-tasks.c (ecmt_get_color_for_component): merged + missing bith from calendar-views-with-model branch. + +2003-08-13 JP Rosevear <jpr@ximian.com> + + * cal-client/cal-client.c (real_open_calendar): set the priv->cal + pointer in a slightly different spot so we have it in the call + back + + * gui/e-cal-model.c (e_cal_model_get_client_list): merge this in + properly + 2003-08-13 Rodrigo Moya <rodrigo@ximian.com> * gui/e-cal-model.c (ecm_get_color_for_component): assign the colors @@ -393,7 +2248,170 @@ * gui/e-week-view-event-item.c (e_week_view_event_item_draw): colorize the background for multiple days events. + +2003-08-13 JP Rosevear <jpr@ximian.com> + + * cal-client/client-test.c (create_client): there is no more + object updated signal + + * cal-client/cal-listener.c: clean up comment + + * cal-client/cal-client.c (cal_client_class_init): remove + obj_updated and obj_removed signals + + * cal-client/cal-client.h: ditto + +2003-08-12 JP Rosevear <jpr@ximian.com> + + * pcs/cal-backend.h: remove get_uri vmethod + + * pcs/cal-backend.c (cal_backend_class_init): remove get_uri + vmethod init + + * pcs/cal-backend-file.c (cal_backend_file_class_init): no longer + a get uri vmethod + (cal_backend_file_get_uri): remove implementation of above + +2003-08-12 JP Rosevear <jpr@ximian.com> + + * cal-client/client-test.c (main): use tmp uris + + * cal-client/cal-listener.h: update protos + + * cal-client/cal-listener.c (cal_listener_init): init removed + function + (cal_listener_finalize): clear removed function + (impl_notifyCalOpened): take file status + (impl_notifyCalRemoved): implement + (cal_listener_construct): take remove function arg + (cal_listener_new): ditto + + * cal-client/cal-client.h: update protos, add remove status + + * cal-client/cal-client.c + (cal_client_remove_status_enum_get_type): add remove status type + (cal_client_class_init): add removed signal + (cal_opened_cb): can no longer get unsupported exception here + (cal_removed_cb): emit removed status + (real_open_calendar): pass removed callback function to listener + (get_fall_back_uri): no longer append tasks.ics or calendar.ics + (cal_client_remove_calendar): new c wrapper for corba function - + calendar must be open currently + + * pcs/query.c (backend_opened_cb): only disconnect the open + callback + (backend_removed_cb): handle calendar removal + (query_construct): listen for remove signal as well + + * pcs/cal.h: cal no longer takes uri during construction + + * pcs/cal.c (backend_to_listener_status): convert backend to corba + status code + (impl_Cal_open): backend open no longer takes uri, use above to + send back status + (impl_Cal_remove): implement + (cal_construct): we no longer track the uri + (cal_finalize): ditto + (cal_class_init): set remove epv method + + * pcs/cal-factory.c (impl_CalFactory_getCal): instantiate backend + with uri and kind properties + + * pcs/cal-backend.h: list file status enum, add protos + + * pcs/cal-backend.c (cal_backend_set_property): implement object + properties + (cal_backend_get_property): ditto + (cal_backend_class_init): add properties vmethods and uri, kind + properties, removed signal + (cal_backend_get_uri): don't get the uri from the backend + (cal_backend_get_kind): get the kind from the backend + (cal_backend_open): adapt to new open call, no uri passed in + (cal_backend_remove): call through to remove implementation + (cal_backend_opened): use new file status + (cal_backend_removed): emit removed signal + + * pcs/cal-backend-file.h: update protos + + * pcs/cal-backend-file.c (cal_backend_file_class_init): override + remove vmethod + (cal_backend_file_init): default file name to calendar.ics + (cal_backend_file_set_file_name): accessor for filename tacked on + to uri + (cal_backend_file_get_file_name): ditto + (open_cal): return "file" type status codes + (create_cal): ditto + (get_uri_string): construct the full uri string + (cal_backend_file_open): use above + (cal_backend_file_remove): implement + + * pcs/cal-backend-file-todos.c (cal_backend_file_todos_init): set + the file name to tasks.ics + + * pcs/cal-backend-file-events.c (cal_backend_file_events_init): + set the file name to calendar.ics + + * cal-util/cal-util.c (cal_util_expand_uri): just return a copy of + the uri now + + * idl/evolution-calendar.idl: convert OpenStatus to FileStatus so + remove() can use it as well + + * gui/gnome-cal.c (gnome_calendar_open): just open the default + folder in all cases + +2003-08-12 Rodrigo Moya <rodrigo@ximian.com> + + * cal-util/cal-util.[ch] (cal_util_component_has_alarms): new function. + + * gui/gnome-cal.[ch]: + * gui/goto.c: + * gui/itip-bonobo-control.c: + * gui/print.c: + * gui/e-week-view.[ch]: + * gui/e-day-view.[ch]: lots of fixes to make all compile with no + warnings. + +2003-08-12 Rodrigo Moya <rodrigo@ximian.com> + * cal-util/cal-util.[ch] (cal_util_component_has_organizer): + new function. + + * gui/e-day-view-main-item.c: + * gui/e-day-view-top-item.c: + * gui/e-week-view-event-item.c: + * gui/e-week-view.c: adaptated to changes in ECalViewEvent. + + * gui/e-cal-model.[ch] (e_cal_model_get_client_list): new function. + (ecm_append_row): fixed usage of icalcomponent variable. + + * gui/e-cal-view.c (e_cal_view_class_init): removed unused variable. + (selection_received): use default client for pasting from clipboard. + (e_cal_view_cut_clipboard): cut the appointment from its client. + (e_cal_view_copy_clipboard, delete_event, on_save_as, om_print_event, + e_cal_view_delete_selected_occurrence, on_meeting, on_forward, + e_cal_view_create_popup_menu): adapted to changes in ECalViewEvent. + (e_cal_view_delete_selected_event, e_cal_view_delete_selected_events): + pass the ECalViewEvent to delete_event, so that it knows which + CalClient to use. + (on_edit_appointment): pass CalClient and icalcomponent to + gnome_calendar_edit_object. + (on_publish): publish F/B info for all the clients currently loaded + in the view. + (setup_popup_icons): added missing argument to gtk_image_new_from_stock. + + * gui/calendar-commands.c (publish_freebusy_cmd): publish F/B info + for all the clients currently loaded in the view. + (sensitize_calendar_commands): use icalcomponent functions. + + * gui/e-day-view.c: + * gui/comp-editor-factory.c (impl_editExisting): + * gui/calendar-offline-handler.c (backend_cal_opened_online): + * gui/e-alarm-list.c (e_alarm_list_finalize): + * gui/e-cal-model-tasks.c (ecmt_get_color_for_component): + * gui/e-date-time-list.c (e_date_time_list_finalize): + * gui/control-factory.c (get_prop): fixed warnings. + 2003-08-12 Hans Petter Jansson <hpj@ximian.com> * gui/calendar-offline-handler.c (impl_dispose): Chain. Prevent @@ -799,6 +2817,27 @@ * cal-client/cal-client-multi.[ch]: * cal-client/Makefile.am: removed obsolete code. +2003-07-30 Ettore Perazzoli <ettore@ximian.com> + + * gui/main.c (factory): Do not depend on global_shell_client being + not NULL for creating the calendar preferences dialog. + + * gui/e-itip-control.c (show_current): Don't call get_servers + anymore [to be fixed]. + (get_servers): #if 0ed out. + (object_requested_cb): Don't create the folder selector button. + + * gui/e-cal-view.c (e_cal_view_set_status_message): Don't create + an activity client. + + * gui/calendar-model.c (calendar_model_set_status_message): Don't + create an activity client. + + * gui/calendar-component.c: Removed global variable + global_shell_client. + (owner_set_cb): Don't set global_shell_client. + (owner_unset_cb): Don't set it here either. + 2003-07-29 Rodrigo Moya <rodrigo@ximian.com> Fixes all "alarm daemon doesn't start with session" diff --git a/calendar/cal-client/.cvsignore b/calendar/cal-client/.cvsignore index 1537e6e01d..f2aa4f92ae 100644 --- a/calendar/cal-client/.cvsignore +++ b/calendar/cal-client/.cvsignore @@ -10,6 +10,8 @@ evolution-calendar.h evolution-calendar-common.lo evolution-calendar-skels.lo evolution-calendar-stubs.lo +cal-marshal.c +cal-marshal.h *.lo *.la client-test diff --git a/calendar/cal-client/Makefile.am b/calendar/cal-client/Makefile.am index 5e48e7db23..5f8b5a3cf1 100644 --- a/calendar/cal-client/Makefile.am +++ b/calendar/cal-client/Makefile.am @@ -38,6 +38,8 @@ libcal_clientincludedir = $(privincludedir)/cal-client libcal_client_la_SOURCES = \ $(CORBA_GENERATED_C) \ cal-client-types.c \ + cal-marshal.c \ + cal--marshal.h \ cal-client.c \ cal-listener.c \ cal-listener.h \ @@ -72,7 +74,10 @@ client_test_LDADD = \ libcal-client.la \ $(EVOLUTION_CALENDAR_LIBS) -BUILT_SOURCES = $(CORBA_GENERATED) +MARSHAL_GENERATED = cal-marshal.c cal-marshal.h +@EVO_MARSHAL_RULE@ + +BUILT_SOURCES = $(CORBA_GENERATED) $(MARSHAL_GENERATED) CLEANFILES = $(BUILT_SOURCES) dist-hook: diff --git a/calendar/cal-client/cal-client-types.h b/calendar/cal-client/cal-client-types.h index c160a1fa94..925628337b 100644 --- a/calendar/cal-client/cal-client-types.h +++ b/calendar/cal-client/cal-client-types.h @@ -29,6 +29,10 @@ G_BEGIN_DECLS +#define E_CALENDAR_ERROR e_calendar_error_quark() + +GQuark e_calendar_error_quark (void) G_GNUC_CONST; + typedef enum { CAL_CLIENT_CHANGE_ADDED = 1 << 0, CAL_CLIENT_CHANGE_MODIFIED = 1 << 1, @@ -41,6 +45,28 @@ typedef struct CalClientChangeType type; } CalClientChange; +typedef enum { + E_CALENDAR_STATUS_OK, + E_CALENDAR_STATUS_INVALID_ARG, + E_CALENDAR_STATUS_BUSY, + E_CALENDAR_STATUS_REPOSITORY_OFFLINE, + E_CALENDAR_STATUS_NO_SUCH_CALENDAR, + E_CALENDAR_STATUS_OBJECT_NOT_FOUND, + E_CALENDAR_STATUS_INVALID_OBJECT, + E_CALENDAR_STATUS_URI_NOT_LOADED, + E_CALENDAR_STATUS_URI_ALREADY_LOADED, + E_CALENDAR_STATUS_PERMISSION_DENIED, + E_CALENDAR_STATUS_CARD_NOT_FOUND, + E_CALENDAR_STATUS_CARD_ID_ALREADY_EXISTS, + E_CALENDAR_STATUS_PROTOCOL_NOT_SUPPORTED, + E_CALENDAR_STATUS_CANCELLED, + E_CALENDAR_STATUS_COULD_NOT_CANCEL, + E_CALENDAR_STATUS_AUTHENTICATION_FAILED, + E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED, + E_CALENDAR_STATUS_CORBA_EXCEPTION, + E_CALENDAR_STATUS_OTHER_ERROR +} ECalendarStatus; + void cal_client_change_list_free (GList *list); G_END_DECLS diff --git a/calendar/cal-client/cal-client.c b/calendar/cal-client/cal-client.c index e40d405120..95efdd6d5d 100644 --- a/calendar/cal-client/cal-client.c +++ b/calendar/cal-client/cal-client.c @@ -22,20 +22,39 @@ #include <config.h> #endif +#include <pthread.h> #include <string.h> #include <bonobo-activation/bonobo-activation.h> #include <bonobo/bonobo-exception.h> +#include <bonobo/bonobo-i18n.h> #include <libgnome/gnome-util.h> #include "e-util/e-component-listener.h" #include "e-util/e-config-listener.h" +#include "e-util/e-url.h" +#include "e-util/e-msgport.h" #include "cal-util/cal-util-marshal.h" -#include "cal-client-types.h" +#include "cal-util/timeutil.h" #include "cal-client.h" #include "cal-listener.h" +#include "query-listener.h" +typedef struct { + EMutex *mutex; + pthread_cond_t cond; + ECalendarStatus status; + + char *uid; + GList *list; + gboolean bool; + char *string; + + CalQuery *query; + QueryListener *listener; +} ECalendarOp; + /* Private part of the CalClient structure */ struct _CalClientPrivate { /* Load state to avoid multiple loads */ @@ -45,7 +64,12 @@ struct _CalClientPrivate { * NULL if we are not loaded. */ char *uri; + CalObjType type; + + ECalendarOp *current_op; + EMutex *mutex; + /* Email address associated with this calendar, or NULL */ char *cal_address; char *alarm_email_address; @@ -85,8 +109,6 @@ struct _CalClientPrivate { enum { CAL_OPENED, CAL_SET_MODE, - OBJ_UPDATED, - OBJ_REMOVED, BACKEND_ERROR, CATEGORIES_CHANGED, FORGET_PASSWORD, @@ -94,10 +116,6 @@ enum { LAST_SIGNAL }; -static void cal_client_class_init (CalClientClass *klass); -static void cal_client_init (CalClient *client, CalClientClass *klass); -static void cal_client_finalize (GObject *object); - static void cal_client_get_object_timezones_cb (icalparameter *param, void *data); @@ -105,36 +123,28 @@ static guint cal_client_signals[LAST_SIGNAL]; static GObjectClass *parent_class; +#define E_CALENDAR_CHECK_STATUS(status,error) G_STMT_START{ \ + if ((status) == E_CALENDAR_STATUS_OK) { \ + return TRUE; \ + } \ + else { \ + const char *msg; \ + msg = cal_client_get_error_message ((status)); \ + g_set_error ((error), E_CALENDAR_ERROR, (status), msg, (status)); \ + return FALSE; \ + } }G_STMT_END + -/** - * cal_client_get_type: - * - * Registers the #CalClient class if necessary, and returns the type ID assigned - * to it. - * - * Return value: The type ID of the #CalClient class. - **/ -GType -cal_client_get_type (void) +/* Error quark */ +GQuark +e_calendar_error_quark (void) { - static GType cal_client_type = 0; - - if (!cal_client_type) { - static GTypeInfo info = { - sizeof (CalClientClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) cal_client_class_init, - NULL, NULL, - sizeof (CalClient), - 0, - (GInstanceInitFunc) cal_client_init - }; - cal_client_type = g_type_register_static (G_TYPE_OBJECT, "CalClient", &info, 0); - } + static GQuark q = 0; + if (q == 0) + q = g_quark_from_static_string ("e-calendar-error-quark"); - return cal_client_type; + return q; } GType @@ -198,118 +208,48 @@ cal_mode_enum_get_type (void) return cal_mode_enum_type; } -/* Class initialization function for the calendar client */ -static void -cal_client_class_init (CalClientClass *klass) +/* EBookOp calls */ + +static ECalendarOp* +e_calendar_new_op (CalClient *client) { - GObjectClass *object_class; + ECalendarOp *op = g_new0 (ECalendarOp, 1); - object_class = (GObjectClass *) klass; + op->mutex = e_mutex_new (E_MUTEX_SIMPLE); + pthread_cond_init (&op->cond, 0); - parent_class = g_type_class_peek_parent (klass); - - cal_client_signals[CAL_OPENED] = - g_signal_new ("cal_opened", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, cal_opened), - NULL, NULL, - g_cclosure_marshal_VOID__ENUM, - G_TYPE_NONE, 1, - CAL_CLIENT_OPEN_STATUS_ENUM_TYPE); - cal_client_signals[CAL_SET_MODE] = - g_signal_new ("cal_set_mode", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, cal_set_mode), - NULL, NULL, - cal_util_marshal_VOID__ENUM_ENUM, - G_TYPE_NONE, 2, - CAL_CLIENT_SET_MODE_STATUS_ENUM_TYPE, - CAL_MODE_ENUM_TYPE); - cal_client_signals[OBJ_UPDATED] = - g_signal_new ("obj_updated", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, obj_updated), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - cal_client_signals[OBJ_REMOVED] = - g_signal_new ("obj_removed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, obj_removed), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - cal_client_signals[BACKEND_ERROR] = - g_signal_new ("backend_error", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, backend_error), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - cal_client_signals[CATEGORIES_CHANGED] = - g_signal_new ("categories_changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, categories_changed), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, - G_TYPE_POINTER); - cal_client_signals[FORGET_PASSWORD] = - g_signal_new ("forget_password", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, forget_password), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - cal_client_signals[BACKEND_DIED] = - g_signal_new ("backend_died", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, backend_died), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + client->priv->current_op = op; - klass->cal_opened = NULL; - klass->obj_updated = NULL; - klass->obj_removed = NULL; - klass->categories_changed = NULL; - klass->forget_password = NULL; - klass->backend_died = NULL; + return op; +} - object_class->finalize = cal_client_finalize; +static ECalendarOp* +e_calendar_get_op (CalClient *client) +{ + if (!client->priv->current_op) { + g_warning (G_STRLOC ": Unexpected response"); + return NULL; + } + + return client->priv->current_op; } -/* Object initialization function for the calendar client */ static void -cal_client_init (CalClient *client, CalClientClass *klass) +e_calendar_free_op (ECalendarOp *op) { - CalClientPrivate *priv; + /* XXX more stuff here */ + pthread_cond_destroy (&op->cond); + e_mutex_destroy (op->mutex); + g_free (op); +} - priv = g_new0 (CalClientPrivate, 1); - client->priv = priv; +static void +e_calendar_remove_op (CalClient *client, ECalendarOp *op) +{ + if (client->priv->current_op != op) + g_warning (G_STRLOC ": Cannot remove op, it's not current"); - priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; - priv->uri = NULL; - priv->cal_address = NULL; - priv->alarm_email_address = NULL; - priv->ldap_attribute = NULL; - priv->capabilities = FALSE; - priv->factories = NULL; - priv->timezones = g_hash_table_new (g_str_hash, g_str_equal); - priv->default_zone = icaltimezone_get_utc_timezone (); - priv->comp_listener = NULL; + client->priv->current_op = NULL; } /* Gets rid of the factories that a client knows about */ @@ -364,7 +304,7 @@ destroy_cal (CalClient *client) CORBA_exception_init (&ev); result = CORBA_Object_is_nil (priv->cal, &ev); if (BONOBO_EX (&ev)) { - g_message ("destroy_cal(): could not see if the " + g_message (G_STRLOC ": could not see if the " "calendar client interface object was nil"); priv->cal = CORBA_OBJECT_NIL; CORBA_exception_free (&ev); @@ -375,19 +315,7 @@ destroy_cal (CalClient *client) if (result) return; - CORBA_exception_init (&ev); - GNOME_Evolution_Calendar_Cal_unref (priv->cal, &ev); - if (BONOBO_EX (&ev)) - g_message ("destroy_cal(): could not unref the calendar client interface object"); - - CORBA_exception_free (&ev); - - CORBA_exception_init (&ev); - CORBA_Object_release (priv->cal, &ev); - if (BONOBO_EX (&ev)) - g_message ("destroy_cal(): could not release the calendar client interface object"); - - CORBA_exception_free (&ev); + bonobo_object_release_unref (priv->cal, NULL); priv->cal = CORBA_OBJECT_NIL; } @@ -400,184 +328,541 @@ free_timezone (gpointer key, gpointer value, gpointer data) icaltimezone_free (value, TRUE); } -/* Finalize handler for the calendar client */ + + static void -cal_client_finalize (GObject *object) +backend_died_cb (EComponentListener *cl, gpointer user_data) { - CalClient *client; CalClientPrivate *priv; + CalClient *client = (CalClient *) user_data; - g_return_if_fail (object != NULL); - g_return_if_fail (IS_CAL_CLIENT (object)); + g_return_if_fail (IS_CAL_CLIENT (client)); - client = CAL_CLIENT (object); priv = client->priv; + priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; + g_signal_emit (G_OBJECT (client), cal_client_signals[BACKEND_DIED], 0); +} - if (priv->listener) { - cal_listener_stop_notification (priv->listener); - bonobo_object_unref (priv->listener); - priv->listener = NULL; +/* Signal handlers for the listener's signals */ +/* Handle the cal_opened notification from the listener */ + +static void +cal_read_only_cb (CalListener *listener, ECalendarStatus status, gboolean read_only, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; } - if (priv->comp_listener) { - g_signal_handlers_disconnect_matched (G_OBJECT (priv->comp_listener), - G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, - client); - g_object_unref (G_OBJECT (priv->comp_listener)); - priv->comp_listener = NULL; + e_mutex_lock (op->mutex); + + op->status = status; + op->bool = read_only; + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_cal_address_cb (CalListener *listener, ECalendarStatus status, const char *address, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; } - destroy_factories (client); - destroy_cal (client); + e_mutex_lock (op->mutex); - priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; + op->status = status; + op->string = g_strdup (address); - if (priv->uri) { - g_free (priv->uri); - priv->uri = NULL; + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_alarm_address_cb (CalListener *listener, ECalendarStatus status, const char *address, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; } - if (priv->cal_address) { - g_free (priv->cal_address); - priv->cal_address = NULL; + e_mutex_lock (op->mutex); + + op->status = status; + op->string = g_strdup (address); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_ldap_attribute_cb (CalListener *listener, ECalendarStatus status, const char *attribute, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; } - if (priv->alarm_email_address) { - g_free (priv->alarm_email_address); - priv->alarm_email_address = NULL; + + e_mutex_lock (op->mutex); + + op->status = status; + op->string = g_strdup (attribute); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_static_capabilities_cb (CalListener *listener, ECalendarStatus status, const char *capabilities, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; } - if (priv->ldap_attribute) { - g_free (priv->ldap_attribute); - priv->ldap_attribute = NULL; + + e_mutex_lock (op->mutex); + + op->status = status; + op->string = g_strdup (capabilities); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_opened_cb (CalListener *listener, ECalendarStatus status, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; } - if (priv->capabilities) { - g_free (priv->capabilities); - priv->capabilities = NULL; + + e_mutex_lock (op->mutex); + + op->status = status; + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_removed_cb (CalListener *listener, ECalendarStatus status, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; } - g_hash_table_foreach (priv->timezones, free_timezone, NULL); - g_hash_table_destroy (priv->timezones); - priv->timezones = NULL; + e_mutex_lock (op->mutex); - g_free (priv); - client->priv = NULL; + op->status = status; - if (G_OBJECT_CLASS (parent_class)->finalize) - (* G_OBJECT_CLASS (parent_class)->finalize) (object); + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); } - +static void +cal_object_created_cb (CalListener *listener, ECalendarStatus status, const char *uid, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + op->uid = g_strdup (uid); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} static void -backend_died_cb (EComponentListener *cl, gpointer user_data) +cal_object_modified_cb (CalListener *listener, ECalendarStatus status, gpointer data) { - CalClientPrivate *priv; - CalClient *client = (CalClient *) user_data; + CalClient *client = data; + ECalendarOp *op; - g_return_if_fail (IS_CAL_CLIENT (client)); + op = e_calendar_get_op (client); - priv = client->priv; - priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; - g_signal_emit (G_OBJECT (client), cal_client_signals[BACKEND_DIED], 0); + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); } -/* Signal handlers for the listener's signals */ -/* Handle the cal_opened notification from the listener */ static void -cal_opened_cb (CalListener *listener, - GNOME_Evolution_Calendar_Listener_OpenStatus status, - GNOME_Evolution_Calendar_Cal cal, - gpointer data) +cal_object_removed_cb (CalListener *listener, ECalendarStatus status, gpointer data) { - CalClient *client; - CalClientPrivate *priv; - CORBA_Environment ev; - GNOME_Evolution_Calendar_Cal cal_copy; - CalClientOpenStatus client_status; + CalClient *client = data; + ECalendarOp *op; - client = CAL_CLIENT (data); - priv = client->priv; + op = e_calendar_get_op (client); - g_assert (priv->load_state == CAL_CLIENT_LOAD_LOADING); - g_assert (priv->uri != NULL); + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } - client_status = CAL_CLIENT_OPEN_ERROR; + e_mutex_lock (op->mutex); - switch (status) { - case GNOME_Evolution_Calendar_Listener_SUCCESS: - CORBA_exception_init (&ev); - cal_copy = CORBA_Object_duplicate (cal, &ev); - if (BONOBO_EX (&ev)) { - g_message ("cal_opened_cb(): could not duplicate the " - "calendar client interface"); - CORBA_exception_free (&ev); - goto error; - } - CORBA_exception_free (&ev); + op->status = status; - priv->cal = cal_copy; - priv->load_state = CAL_CLIENT_LOAD_LOADED; + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} - client_status = CAL_CLIENT_OPEN_SUCCESS; +static void +cal_alarm_discarded_cb (CalListener *listener, ECalendarStatus status, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; - /* setup component listener */ - priv->comp_listener = e_component_listener_new (priv->cal); - g_signal_connect (G_OBJECT (priv->comp_listener), "component_died", - G_CALLBACK (backend_died_cb), client); - goto out; + op = e_calendar_get_op (client); - case GNOME_Evolution_Calendar_Listener_ERROR: - client_status = CAL_CLIENT_OPEN_ERROR; - goto error; + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } - case GNOME_Evolution_Calendar_Listener_NOT_FOUND: - client_status = CAL_CLIENT_OPEN_NOT_FOUND; - goto error; + e_mutex_lock (op->mutex); - case GNOME_Evolution_Calendar_Listener_METHOD_NOT_SUPPORTED: - client_status = CAL_CLIENT_OPEN_METHOD_NOT_SUPPORTED; - goto error; + op->status = status; - case GNOME_Evolution_Calendar_Listener_PERMISSION_DENIED : - client_status = CAL_CLIENT_OPEN_PERMISSION_DENIED; - goto error; + pthread_cond_signal (&op->cond); - default: - g_assert_not_reached (); + e_mutex_unlock (op->mutex); +} + +static void +cal_objects_received_cb (CalListener *listener, ECalendarStatus status, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; } - error: + e_mutex_lock (op->mutex); - bonobo_object_unref (BONOBO_OBJECT (priv->listener)); - priv->listener = NULL; + op->status = status; - /* We free the priv->uri and set the priv->load_state until after the - * "cal_opened" signal has been emitted so that handlers will be able to - * access this information. - */ + pthread_cond_signal (&op->cond); - out: + e_mutex_unlock (op->mutex); +} - /* We are *not* inside a signal handler (this is just a simple callback - * called from the listener), so there is not a temporary reference to - * the client object. We ref() so that we can safely emit our own - * signal and clean up. - */ +static void +cal_objects_sent_cb (CalListener *listener, ECalendarStatus status, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; - g_object_ref (G_OBJECT (client)); + op = e_calendar_get_op (client); - g_signal_emit (G_OBJECT (client), cal_client_signals[CAL_OPENED], - 0, client_status); + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } - if (client_status != CAL_CLIENT_OPEN_SUCCESS) { - priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; - g_free (priv->uri); - priv->uri = NULL; + e_mutex_lock (op->mutex); + + op->status = status; + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_default_object_requested_cb (CalListener *listener, ECalendarStatus status, const char *object, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; } - g_assert (priv->load_state != CAL_CLIENT_LOAD_LOADING); + e_mutex_lock (op->mutex); - g_object_unref (G_OBJECT (client)); + op->status = status; + op->string = g_strdup (object); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_object_requested_cb (CalListener *listener, ECalendarStatus status, const char *object, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + op->string = g_strdup (object); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_object_list_cb (CalListener *listener, ECalendarStatus status, GList *objects, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + GList *l; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + op->list = g_list_copy (objects); + + for (l = op->list; l; l = l->next) + l->data = icalcomponent_new_clone (l->data); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_get_timezone_cb (CalListener *listener, ECalendarStatus status, const char *object, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + op->string = g_strdup (object); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); + +} + +static void +cal_add_timezone_cb (CalListener *listener, ECalendarStatus status, const char *tzid, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + op->uid = g_strdup (tzid); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); + +} + +static void +cal_set_default_timezone_cb (CalListener *listener, ECalendarStatus status, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_get_changes_cb (CalListener *listener, ECalendarStatus status, GList *changes, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + GList *l; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + op->list = g_list_copy (changes); + + for (l = op->list; l; l = l->next) { + CalClientChange *ccc = l->data, *new_ccc; + + new_ccc = g_new (CalClientChange, 1); + new_ccc->comp = cal_component_clone (ccc->comp); + new_ccc->type = ccc->type; + + l->data = new_ccc; + } + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_get_free_busy_cb (CalListener *listener, ECalendarStatus status, GList *freebusy, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + GList *l; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + op->list = g_list_copy (freebusy); + + for (l = op->list; l; l = l->next) + l->data = cal_component_clone (l->data); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); +} + +static void +cal_query_cb (CalListener *listener, ECalendarStatus status, GNOME_Evolution_Calendar_Query query, gpointer data) +{ + CalClient *client = data; + ECalendarOp *op; + + op = e_calendar_get_op (client); + + if (op == NULL) { + g_warning (G_STRLOC ": Cannot find operation "); + return; + } + + e_mutex_lock (op->mutex); + + op->status = status; + op->query = cal_query_new (query, op->listener, client); + + pthread_cond_signal (&op->cond); + + e_mutex_unlock (op->mutex); } /* Handle the cal_set_mode notification from the listener */ @@ -624,26 +909,6 @@ cal_set_mode_cb (CalListener *listener, g_object_unref (G_OBJECT (client)); } -/* Handle the obj_updated signal from the listener */ -static void -obj_updated_cb (CalListener *listener, const CORBA_char *uid, gpointer data) -{ - CalClient *client; - - client = CAL_CLIENT (data); - g_signal_emit (G_OBJECT (client), cal_client_signals[OBJ_UPDATED], 0, uid); -} - -/* Handle the obj_removed signal from the listener */ -static void -obj_removed_cb (CalListener *listener, const CORBA_char *uid, gpointer data) -{ - CalClient *client; - - client = CAL_CLIENT (data); - g_signal_emit (G_OBJECT (client), cal_client_signals[OBJ_REMOVED], 0, uid); -} - /* Handle the error_occurred signal from the listener */ static void backend_error_cb (CalListener *listener, const char *message, gpointer data) @@ -678,97 +943,343 @@ categories_changed_cb (CalListener *listener, const GNOME_Evolution_Calendar_Str -static GList * -get_factories (void) +static gboolean +get_factories (const char *str_uri, GList **factories) { - GList *factories = NULL; GNOME_Evolution_Calendar_CalFactory factory; Bonobo_ServerInfoList *servers; - CORBA_Environment ev; + EUri *uri; + char *query; int i; - CORBA_exception_init (&ev); - servers = bonobo_activation_query ("repo_ids.has ('IDL:GNOME/Evolution/Calendar/CalFactory:1.0')", NULL, &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - g_message ("Cannot perform OAF query for Calendar servers."); - CORBA_exception_free (&ev); - return NULL; + /* Determine the protocol and query for factory supporting that */ + uri = e_uri_new (str_uri); + if (!uri) { + g_warning (G_STRLOC ": Invalid uri string"); + + return FALSE; } - if (servers->_length == 0) - g_warning ("No Calendar servers installed."); + query = g_strdup_printf ("repo_ids.has ('IDL:GNOME/Evolution/Calendar/CalFactory:1.0')" + " AND calendar:supported_protocols.has ('%s')", uri->protocol); + + + servers = bonobo_activation_query (query, NULL, NULL); + + g_free (query); + e_uri_free (uri); + if (!servers) { + g_warning (G_STRLOC ": Unable to query for calendar factories"); + + return FALSE; + } + + /* Try to activate the servers for the protocol */ for (i = 0; i < servers->_length; i++) { const Bonobo_ServerInfo *info; info = servers->_buffer + i; - factory = (GNOME_Evolution_Calendar_CalFactory) - bonobo_activation_activate_from_id (info->iid, 0, NULL, &ev); - if (BONOBO_EX (&ev)) { -#if 0 - g_warning ("cal_client_construct: Could not activate calendar server %s", info->iid); - CORBA_free (servers); - CORBA_exception_free (&ev); - return NULL; -#endif - } + g_message (G_STRLOC ": Activating calendar factory (%s)", info->iid); + factory = bonobo_activation_activate_from_id (info->iid, 0, NULL, NULL); + + if (factory == CORBA_OBJECT_NIL) + g_warning (G_STRLOC ": Could not activate calendar factory (%s)", info->iid); else - factories = g_list_prepend (factories, factory); + *factories = g_list_append (*factories, factory); } CORBA_free (servers); - CORBA_exception_free (&ev); - return factories; + + return TRUE; +} + +/* Object initialization function for the calendar client */ +static void +cal_client_init (CalClient *client, CalClientClass *klass) +{ + CalClientPrivate *priv; + + priv = g_new0 (CalClientPrivate, 1); + client->priv = priv; + + priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; + priv->uri = NULL; + priv->mutex = e_mutex_new (E_MUTEX_REC); + priv->listener = cal_listener_new (cal_set_mode_cb, + backend_error_cb, + categories_changed_cb, + client); + + priv->cal_address = NULL; + priv->alarm_email_address = NULL; + priv->ldap_attribute = NULL; + priv->capabilities = FALSE; + priv->factories = NULL; + priv->timezones = g_hash_table_new (g_str_hash, g_str_equal); + priv->default_zone = icaltimezone_get_utc_timezone (); + priv->comp_listener = NULL; + + g_signal_connect (G_OBJECT (priv->listener), "read_only", G_CALLBACK (cal_read_only_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "cal_address", G_CALLBACK (cal_cal_address_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "alarm_address", G_CALLBACK (cal_alarm_address_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "ldap_attribute", G_CALLBACK (cal_ldap_attribute_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "static_capabilities", G_CALLBACK (cal_static_capabilities_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "open", G_CALLBACK (cal_opened_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "remove", G_CALLBACK (cal_removed_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "create_object", G_CALLBACK (cal_object_created_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "modify_object", G_CALLBACK (cal_object_modified_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "remove_object", G_CALLBACK (cal_object_removed_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "discard_alarm", G_CALLBACK (cal_alarm_discarded_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "receive_objects", G_CALLBACK (cal_objects_received_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "send_objects", G_CALLBACK (cal_objects_sent_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "default_object", G_CALLBACK (cal_default_object_requested_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "object", G_CALLBACK (cal_object_requested_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "object_list", G_CALLBACK (cal_object_list_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "get_timezone", G_CALLBACK (cal_get_timezone_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "add_timezone", G_CALLBACK (cal_add_timezone_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "set_default_timezone", G_CALLBACK (cal_set_default_timezone_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "get_changes", G_CALLBACK (cal_get_changes_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "get_free_busy", G_CALLBACK (cal_get_free_busy_cb), client); + g_signal_connect (G_OBJECT (priv->listener), "query", G_CALLBACK (cal_query_cb), client); +} + +/* Finalize handler for the calendar client */ +static void +cal_client_finalize (GObject *object) +{ + CalClient *client; + CalClientPrivate *priv; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_CAL_CLIENT (object)); + + client = CAL_CLIENT (object); + priv = client->priv; + + if (priv->listener) { + cal_listener_stop_notification (priv->listener); + bonobo_object_unref (priv->listener); + priv->listener = NULL; + } + + if (priv->comp_listener) { + g_signal_handlers_disconnect_matched (G_OBJECT (priv->comp_listener), + G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, + client); + g_object_unref (G_OBJECT (priv->comp_listener)); + priv->comp_listener = NULL; + } + + destroy_factories (client); + destroy_cal (client); + + priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; + + if (priv->uri) { + g_free (priv->uri); + priv->uri = NULL; + } + + if (priv->mutex) { + e_mutex_destroy (priv->mutex); + priv->mutex = NULL; + } + + if (priv->cal_address) { + g_free (priv->cal_address); + priv->cal_address = NULL; + } + if (priv->alarm_email_address) { + g_free (priv->alarm_email_address); + priv->alarm_email_address = NULL; + } + if (priv->ldap_attribute) { + g_free (priv->ldap_attribute); + priv->ldap_attribute = NULL; + } + if (priv->capabilities) { + g_free (priv->capabilities); + priv->capabilities = NULL; + } + + g_hash_table_foreach (priv->timezones, free_timezone, NULL); + g_hash_table_destroy (priv->timezones); + priv->timezones = NULL; + + g_free (priv); + client->priv = NULL; + + if (G_OBJECT_CLASS (parent_class)->finalize) + (* G_OBJECT_CLASS (parent_class)->finalize) (object); +} + +/* Class initialization function for the calendar client */ +static void +cal_client_class_init (CalClientClass *klass) +{ + GObjectClass *object_class; + + object_class = (GObjectClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + cal_client_signals[CAL_OPENED] = + g_signal_new ("cal_opened", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalClientClass, cal_opened), + NULL, NULL, + g_cclosure_marshal_VOID__ENUM, + G_TYPE_NONE, 1, + CAL_CLIENT_OPEN_STATUS_ENUM_TYPE); + cal_client_signals[CAL_SET_MODE] = + g_signal_new ("cal_set_mode", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalClientClass, cal_set_mode), + NULL, NULL, + cal_util_marshal_VOID__ENUM_ENUM, + G_TYPE_NONE, 2, + CAL_CLIENT_SET_MODE_STATUS_ENUM_TYPE, + CAL_MODE_ENUM_TYPE); + cal_client_signals[BACKEND_ERROR] = + g_signal_new ("backend_error", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalClientClass, backend_error), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + cal_client_signals[CATEGORIES_CHANGED] = + g_signal_new ("categories_changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalClientClass, categories_changed), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, + G_TYPE_POINTER); + cal_client_signals[FORGET_PASSWORD] = + g_signal_new ("forget_password", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalClientClass, forget_password), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + cal_client_signals[BACKEND_DIED] = + g_signal_new ("backend_died", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalClientClass, backend_died), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + klass->cal_opened = NULL; + klass->categories_changed = NULL; + klass->forget_password = NULL; + klass->backend_died = NULL; + + object_class->finalize = cal_client_finalize; } /** - * cal_client_construct: - * @client: A calendar client. + * cal_client_get_type: * - * Constructs a calendar client object by contacting all available - * calendar factories. + * Registers the #CalClient class if necessary, and returns the type ID assigned + * to it. * - * Return value: The same object as the @client argument, or NULL if the - * calendar factory could not be contacted. + * Return value: The type ID of the #CalClient class. **/ -CalClient * -cal_client_construct (CalClient *client) +GType +cal_client_get_type (void) { - CalClientPrivate *priv; + static GType cal_client_type = 0; - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + if (!cal_client_type) { + static GTypeInfo info = { + sizeof (CalClientClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) cal_client_class_init, + NULL, NULL, + sizeof (CalClient), + 0, + (GInstanceInitFunc) cal_client_init + }; + cal_client_type = g_type_register_static (G_TYPE_OBJECT, "CalClient", &info, 0); + } + return cal_client_type; +} + + +static gboolean +fetch_corba_cal (CalClient *client, const char *str_uri, CalObjType type) +{ + CalClientPrivate *priv; + GList *f; + CORBA_Environment ev; + priv = client->priv; - priv->factories = get_factories (); + g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_NOT_LOADED, FALSE); + g_assert (priv->uri == NULL); - return client; + g_return_val_if_fail (str_uri != NULL, FALSE); + + if (!get_factories (str_uri, &priv->factories)) + return FALSE; + + priv->uri = g_strdup (str_uri); + priv->type = type; + + for (f = priv->factories; f; f = f->next) { + GNOME_Evolution_Calendar_Cal cal; + + CORBA_exception_init (&ev); + + cal = GNOME_Evolution_Calendar_CalFactory_getCal (f->data, priv->uri, priv->type, + BONOBO_OBJREF (priv->listener), &ev); + if (BONOBO_EX (&ev)) + continue; + + priv->cal = cal; + + return TRUE; + } + + return FALSE; } /** * cal_client_new: * * Creates a new calendar client. It should be initialized by calling - * cal_client_open_calendar(). + * cal_client_open(). * * Return value: A newly-created calendar client, or NULL if the client could * not be constructed because it could not contact the calendar server. **/ CalClient * -cal_client_new (void) +cal_client_new (const char *uri, CalObjType type) { CalClient *client; client = g_object_new (CAL_CLIENT_TYPE, NULL); - if (!cal_client_construct (client)) { - g_message ("cal_client_new(): could not construct the calendar client"); - g_object_unref (G_OBJECT (client)); + if (!fetch_corba_cal (client, uri, type)) { + g_object_unref (client); + return NULL; } - + return client; } @@ -800,74 +1311,8 @@ cal_client_set_auth_func (CalClient *client, CalClientAuthFunc func, gpointer da client->priv->auth_user_data = data; } -static gboolean -real_open_calendar (CalClient *client, const char *str_uri, gboolean only_if_exists, gboolean *supported) -{ - CalClientPrivate *priv; - GNOME_Evolution_Calendar_Listener corba_listener; - int unsupported; - GList *f; - CORBA_Environment ev; - - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_NOT_LOADED, FALSE); - g_assert (priv->uri == NULL); - - g_return_val_if_fail (str_uri != NULL, FALSE); - - priv->listener = cal_listener_new (cal_opened_cb, - cal_set_mode_cb, - obj_updated_cb, - obj_removed_cb, - backend_error_cb, - categories_changed_cb, - client); - if (!priv->listener) { - g_message ("cal_client_open_calendar(): could not create the listener"); - return FALSE; - } - - corba_listener = (GNOME_Evolution_Calendar_Listener) (BONOBO_OBJREF (priv->listener)); - - priv->load_state = CAL_CLIENT_LOAD_LOADING; - priv->uri = g_strdup (str_uri); - - unsupported = 0; - for (f = priv->factories; f; f = f->next) { - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_CalFactory_open (f->data, str_uri, - only_if_exists, - corba_listener, &ev); - if (!BONOBO_EX (&ev)) { - if (supported != NULL) - *supported = TRUE; - return TRUE; - } - - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_CalFactory_UnsupportedMethod)) - unsupported++; - CORBA_exception_free (&ev); - } - - if (supported != NULL) { - if (unsupported == g_list_length (priv->factories)) - *supported = FALSE; - else - *supported = TRUE; - } - - bonobo_object_unref (BONOBO_OBJECT (priv->listener)); - priv->listener = NULL; - priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; - g_free (priv->uri); - priv->uri = NULL; - - return FALSE; -} - /** - * cal_client_open_calendar: + * cal_client_open * @client: A calendar client. * @str_uri: URI of calendar to open. * @only_if_exists: FALSE if the calendar should be opened even if there @@ -882,93 +1327,167 @@ real_open_calendar (CalClient *client, const char *str_uri, gboolean only_if_exi * Return value: TRUE on success, FALSE on failure to issue the open request. **/ gboolean -cal_client_open_calendar (CalClient *client, const char *str_uri, gboolean only_if_exists) +cal_client_open (CalClient *client, gboolean only_if_exists, GError **error) { + CalClientPrivate *priv; + CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; + g_return_val_if_fail (client != NULL, FALSE); g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - return real_open_calendar (client, str_uri, only_if_exists, NULL); -} + priv = client->priv; + + e_mutex_lock (client->priv->mutex); -static char * -get_fall_back_uri (gboolean tasks) -{ - if (tasks) - return g_concat_dir_and_file (g_get_home_dir (), - "evolution/local/" - "Tasks/tasks.ics"); - else - return g_concat_dir_and_file (g_get_home_dir (), - "evolution/local/" - "Calendar/calendar.ics"); -} + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } -static char * -get_default_uri (gboolean tasks) -{ - EConfigListener *db; - char *uri; + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); + + CORBA_exception_init (&ev); + + priv->load_state = CAL_CLIENT_LOAD_LOADING; + + GNOME_Evolution_Calendar_Cal_open (priv->cal, only_if_exists, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + g_signal_emit (G_OBJECT (client), cal_client_signals[CAL_OPENED], 0, + E_CALENDAR_STATUS_CORBA_EXCEPTION); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } + + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); - db = e_config_listener_new (); + status = our_op->status; - if (tasks) - uri = e_config_listener_get_string (db, "/apps/evolution/shell/default_folders/tasks_uri"); - else - uri = e_config_listener_get_string (db, "/apps/evolution/shell/default_folders/calendar_uri"); - g_object_unref (G_OBJECT (db)); + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - if (!uri || *uri == '\0') - uri = get_fall_back_uri (tasks); + if (status == E_CALENDAR_STATUS_OK) + priv->load_state = CAL_CLIENT_LOAD_LOADED; else - uri = cal_util_expand_uri (uri, tasks); - - return uri; + priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; + + g_signal_emit (G_OBJECT (client), cal_client_signals[CAL_OPENED], 0, status); + E_CALENDAR_CHECK_STATUS (status, error); } -gboolean -cal_client_open_default_calendar (CalClient *client, gboolean only_if_exists) +typedef struct { + CalClient *client; + + gboolean exists; +} CalClientAsyncData; + +static gboolean +open_async (gpointer data) { - char *default_uri, *fall_back; - gboolean result, supported; + CalClientAsyncData *ccad = data; + GError *error = NULL; - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); + cal_client_open (ccad->client, ccad->exists, &error); - default_uri = get_default_uri (FALSE); - fall_back = get_fall_back_uri (FALSE); - - result = real_open_calendar (client, default_uri, only_if_exists, &supported); - if (!supported && strcmp (fall_back, default_uri)) - result = real_open_calendar (client, fall_back, only_if_exists, NULL); + g_clear_error (&error); - g_free (default_uri); - g_free (fall_back); + g_object_unref (ccad); + g_free (ccad); - return result; + return FALSE; } -gboolean -cal_client_open_default_tasks (CalClient *client, gboolean only_if_exists) +void +cal_client_open_async (CalClient *client, gboolean only_if_exists) { - char *default_uri, *fall_back; - gboolean result, supported; + CalClientAsyncData *ccad; + + g_return_if_fail (client != NULL); + g_return_if_fail (IS_CAL_CLIENT (client)); + + ccad = g_new0 (CalClientAsyncData, 1); + ccad->client = g_object_ref (client); + ccad->exists = only_if_exists; + /* FIXME This should really spawn a new thread */ + g_idle_add (open_async, ccad); +} + +gboolean +cal_client_remove_calendar (CalClient *client, GError **error) +{ + CalClientPrivate *priv; + CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; + g_return_val_if_fail (client != NULL, FALSE); g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - default_uri = get_default_uri (TRUE); - fall_back = get_fall_back_uri (TRUE); + priv = client->priv; + + e_mutex_lock (client->priv->mutex); + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); - result = real_open_calendar (client, default_uri, only_if_exists, &supported); - if (!supported && strcmp (fall_back, default_uri)) - result = real_open_calendar (client, fall_back, only_if_exists, NULL); + e_mutex_lock (our_op->mutex); - g_free (default_uri); - g_free (fall_back); + e_mutex_unlock (client->priv->mutex); + + + CORBA_exception_init (&ev); - return result; + GNOME_Evolution_Calendar_Cal_remove (priv->cal, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } + + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } +#if 0 /* Builds an URI list out of a CORBA string sequence */ static GList * build_uri_list (GNOME_Evolution_Calendar_StringSeq *seq) @@ -981,6 +1500,7 @@ build_uri_list (GNOME_Evolution_Calendar_StringSeq *seq) return uris; } +#endif /** * cal_client_uri_list: @@ -993,6 +1513,7 @@ build_uri_list (GNOME_Evolution_Calendar_StringSeq *seq) GList * cal_client_uri_list (CalClient *client, CalMode mode) { +#if 0 CalClientPrivate *priv; GNOME_Evolution_Calendar_StringSeq *uri_seq; GList *uris = NULL; @@ -1026,8 +1547,12 @@ cal_client_uri_list (CalClient *client, CalMode mode) } return uris; +#endif + + return NULL; } + /** * cal_client_get_load_state: * @client: A calendar client. @@ -1076,33 +1601,72 @@ cal_client_get_uri (CalClient *client) * @client: A calendar client. * * Queries whether the calendar client can perform modifications - * on the calendar or not. + * on the calendar or not. Whether the backend is read only or not + * is specified, on exit, in the @read_only argument. * - * Return value: TRUE if the calendar is read-only, FALSE otherwise. + * Return value: TRUE if the call was successful, FALSE if there was an error. */ gboolean -cal_client_is_read_only (CalClient *client) +cal_client_is_read_only (CalClient *client, gboolean *read_only, GError **error) { CalClientPrivate *priv; CORBA_Environment ev; - CORBA_boolean read_only; - + ECalendarStatus status; + ECalendarOp *our_op; + g_return_val_if_fail (client != NULL, FALSE); g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; + + e_mutex_lock (client->priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); - if (priv->load_state != CAL_CLIENT_LOAD_LOADED) - return FALSE; CORBA_exception_init (&ev); - read_only = GNOME_Evolution_Calendar_Cal_isReadOnly (priv->cal, &ev); + + GNOME_Evolution_Calendar_Cal_isReadOnly (priv->cal, &ev); if (BONOBO_EX (&ev)) { - g_message ("cal_client_is_read_only: could not call isReadOnly method"); + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } + CORBA_exception_free (&ev); - return read_only; + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + *read_only = our_op->bool; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + return status; } /** @@ -1115,119 +1679,269 @@ cal_client_is_read_only (CalClient *client) * is loaded or being loaded, or %NULL if the client has not started a * load request yet or the calendar has no associated email address. **/ -const char * -cal_client_get_cal_address (CalClient *client) +gboolean +cal_client_get_cal_address (CalClient *client, char **cal_address, GError **error) { CalClientPrivate *priv; - - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; + + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, NULL); + + e_mutex_lock (client->priv->mutex); - if (priv->cal_address == NULL) { - CORBA_Environment ev; - CORBA_char *cal_address; + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); + + + CORBA_exception_init (&ev); + + GNOME_Evolution_Calendar_Cal_getCalAddress (priv->cal, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - CORBA_exception_init (&ev); - cal_address = GNOME_Evolution_Calendar_Cal_getCalAddress (priv->cal, &ev); - if (!BONOBO_EX (&ev)) { - priv->cal_address = g_strdup (cal_address); - CORBA_free (cal_address); - } CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } - return priv->cal_address; + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + *cal_address = our_op->string; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } -const char * -cal_client_get_alarm_email_address (CalClient *client) +gboolean +cal_client_get_alarm_email_address (CalClient *client, char **alarm_address, GError **error) { CalClientPrivate *priv; + CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, NULL); - if (priv->alarm_email_address == NULL) { - CORBA_Environment ev; - CORBA_char *email_address; + e_mutex_lock (client->priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); + + + CORBA_exception_init (&ev); + + GNOME_Evolution_Calendar_Cal_getAlarmEmailAddress (priv->cal, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - CORBA_exception_init (&ev); - email_address = GNOME_Evolution_Calendar_Cal_getAlarmEmailAddress (priv->cal, &ev); - if (!BONOBO_EX (&ev)) { - priv->alarm_email_address = g_strdup (email_address); - CORBA_free (email_address); - } CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } - return priv->alarm_email_address; + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + *alarm_address = our_op->string; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } -const char * -cal_client_get_ldap_attribute (CalClient *client) +gboolean +cal_client_get_ldap_attribute (CalClient *client, char **ldap_attribute, GError **error) { CalClientPrivate *priv; + CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, NULL); - if (priv->ldap_attribute == NULL) { - CORBA_Environment ev; - CORBA_char *ldap_attribute; + e_mutex_lock (client->priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); + + + CORBA_exception_init (&ev); + + GNOME_Evolution_Calendar_Cal_getLdapAttribute (priv->cal, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - CORBA_exception_init (&ev); - ldap_attribute = GNOME_Evolution_Calendar_Cal_getLdapAttribute (priv->cal, &ev); - if (!BONOBO_EX (&ev)) { - priv->ldap_attribute = g_strdup (ldap_attribute); - CORBA_free (ldap_attribute); - } CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } - return priv->ldap_attribute; + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + *ldap_attribute = our_op->string; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } -static void -load_static_capabilities (CalClient *client) +static gboolean +load_static_capabilities (CalClient *client, GError **error) { CalClientPrivate *priv; CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; char *cap; priv = client->priv; if (priv->capabilities) - return; - + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error); + + e_mutex_lock (client->priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); + + CORBA_exception_init (&ev); - cap = GNOME_Evolution_Calendar_Cal_getStaticCapabilities (priv->cal, &ev); - if (!BONOBO_EX (&ev)) - priv->capabilities = g_strdup (cap); - else - priv->capabilities = g_strdup (""); - CORBA_free (cap); + GNOME_Evolution_Calendar_Cal_getStaticCapabilities (priv->cal, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + cap = our_op->string; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } static gboolean check_capability (CalClient *client, const char *cap) { CalClientPrivate *priv; - + priv = client->priv; - load_static_capabilities (client); - if (strstr (priv->capabilities, cap)) + /* FIXME Check result */ + load_static_capabilities (client, NULL); + if (priv->capabilities && strstr (priv->capabilities, cap)) return TRUE; return FALSE; @@ -1269,15 +1983,6 @@ cal_client_get_save_schedules (CalClient *client) return check_capability (client, CAL_STATIC_CAPABILITY_SAVE_SCHEDULES); } -/* Converts our representation of a calendar component type into its CORBA representation */ -static GNOME_Evolution_Calendar_CalObjType -corba_obj_type (CalObjType type) -{ - return (((type & CALOBJ_TYPE_EVENT) ? GNOME_Evolution_Calendar_TYPE_EVENT : 0) - | ((type & CALOBJ_TYPE_TODO) ? GNOME_Evolution_Calendar_TYPE_TODO : 0) - | ((type & CALOBJ_TYPE_JOURNAL) ? GNOME_Evolution_Calendar_TYPE_JOURNAL : 0)); -} - gboolean cal_client_set_mode (CalClient *client, CalMode mode) { @@ -1302,45 +2007,6 @@ cal_client_set_mode (CalClient *client, CalMode mode) return retval; } -/** - * cal_client_get_n_objects: - * @client: A calendar client. - * @type: Type of objects that will be counted. - * - * Counts the number of calendar components of the specified @type. This can be - * used to count how many events, to-dos, or journals there are, for example. - * - * Return value: Number of components. - **/ -int -cal_client_get_n_objects (CalClient *client, CalObjType type) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - int n; - int t; - - g_return_val_if_fail (client != NULL, -1); - g_return_val_if_fail (IS_CAL_CLIENT (client), -1); - - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, -1); - - t = corba_obj_type (type); - - CORBA_exception_init (&ev); - n = GNOME_Evolution_Calendar_Cal_countObjects (priv->cal, t, &ev); - - if (BONOBO_EX (&ev)) { - g_message ("cal_client_get_n_objects(): could not get the number of objects"); - CORBA_exception_free (&ev); - return -1; - } - - CORBA_exception_free (&ev); - return n; -} - /* This is used in the callback which fetches all the timezones needed for an object. */ @@ -1348,68 +2014,93 @@ typedef struct _CalClientGetTimezonesData CalClientGetTimezonesData; struct _CalClientGetTimezonesData { CalClient *client; - /* This starts out at CAL_CLIENT_GET_SUCCESS. If an error occurs this + /* This starts out at E_CALENDAR_STATUS_OK. If an error occurs this contains the last error. */ - CalClientGetStatus status; + ECalendarStatus status; }; -CalClientGetStatus -cal_client_get_default_object (CalClient *client, CalObjType type, icalcomponent **icalcomp) +gboolean +cal_client_get_default_object (CalClient *client, icalcomponent **icalcomp, GError **error) { CalClientPrivate *priv; CORBA_Environment ev; - GNOME_Evolution_Calendar_CalObj comp_str; - CalClientGetStatus retval; - CalClientGetTimezonesData cb_data; + ECalendarStatus status; + ECalendarOp *our_op; - g_return_val_if_fail (client != NULL, CAL_CLIENT_GET_NOT_FOUND); - g_return_val_if_fail (IS_CAL_CLIENT (client), CAL_CLIENT_GET_NOT_FOUND); + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, CAL_CLIENT_GET_NOT_FOUND); - g_return_val_if_fail (icalcomp != NULL, CAL_CLIENT_GET_NOT_FOUND); + e_mutex_lock (client->priv->mutex); - retval = CAL_CLIENT_GET_NOT_FOUND; - *icalcomp = NULL; + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); CORBA_exception_init (&ev); - comp_str = GNOME_Evolution_Calendar_Cal_getDefaultObject (priv->cal, type, &ev); - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - goto out; - else if (BONOBO_EX (&ev)) { - g_message ("cal_client_get_default_object(): could not get the object"); - goto out; - } + GNOME_Evolution_Calendar_Cal_getDefaultObject (priv->cal, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - *icalcomp = icalparser_parse_string (comp_str); - CORBA_free (comp_str); + CORBA_exception_free (&ev); - if (!*icalcomp) { - retval = CAL_CLIENT_GET_SYNTAX_ERROR; - goto out; + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } - /* Now make sure we have all timezones needed for this object. - We do this to try to avoid any problems caused by getting a timezone - in the middle of other code. Any calls to ORBit result in a - recursive call of the GTK+ main loop, which can cause problems for - code that doesn't expect it. Currently GnomeCanvas has problems if - we try to get a timezone in the middle of a redraw, and there is a - resize pending, which leads to an assert failure and an abort. */ - cb_data.client = client; - cb_data.status = CAL_CLIENT_GET_SUCCESS; - icalcomponent_foreach_tzid (*icalcomp, - cal_client_get_object_timezones_cb, - &cb_data); + CORBA_exception_free (&ev); - retval = cb_data.status; + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); - out: + status = our_op->status; + *icalcomp = icalparser_parse_string (our_op->string); + g_free (our_op->string); - CORBA_exception_free (&ev); - return retval; + if (!*icalcomp) { + status = E_CALENDAR_STATUS_INVALID_OBJECT; + } else { + CalClientGetTimezonesData cb_data; + + /* Now make sure we have all timezones needed for this object. + We do this to try to avoid any problems caused by getting a timezone + in the middle of other code. Any calls to ORBit result in a + recursive call of the GTK+ main loop, which can cause problems for + code that doesn't expect it. Currently GnomeCanvas has problems if + we try to get a timezone in the middle of a redraw, and there is a + resize pending, which leads to an assert failure and an abort. */ + cb_data.client = client; + cb_data.status = E_CALENDAR_STATUS_OK; + icalcomponent_foreach_tzid (*icalcomp, + cal_client_get_object_timezones_cb, + &cb_data); + + status = cb_data.status; + } + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } /** @@ -1423,64 +2114,89 @@ cal_client_get_default_object (CalClient *client, CalObjType type, icalcomponent * * Return value: Result code based on the status of the operation. **/ -CalClientGetStatus -cal_client_get_object (CalClient *client, const char *uid, icalcomponent **icalcomp) +gboolean +cal_client_get_object (CalClient *client, const char *uid, const char *rid, icalcomponent **icalcomp, GError **error) { + CalClientPrivate *priv; CORBA_Environment ev; - GNOME_Evolution_Calendar_CalObj comp_str; - CalClientGetStatus retval; - CalClientGetTimezonesData cb_data; + ECalendarStatus status; + ECalendarOp *our_op; - g_return_val_if_fail (client != NULL, CAL_CLIENT_GET_NOT_FOUND); - g_return_val_if_fail (IS_CAL_CLIENT (client), CAL_CLIENT_GET_NOT_FOUND); + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, CAL_CLIENT_GET_NOT_FOUND); - g_return_val_if_fail (uid != NULL, CAL_CLIENT_GET_NOT_FOUND); - g_return_val_if_fail (icalcomp != NULL, CAL_CLIENT_GET_NOT_FOUND); + e_mutex_lock (client->priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } - retval = CAL_CLIENT_GET_NOT_FOUND; - *icalcomp = NULL; + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); CORBA_exception_init (&ev); - comp_str = GNOME_Evolution_Calendar_Cal_getObject (priv->cal, (char *) uid, &ev); - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - goto out; - else if (BONOBO_EX (&ev)) { - g_message ("cal_client_get_object(): could not get the object"); - goto out; - } + GNOME_Evolution_Calendar_Cal_getObject (priv->cal, uid, rid ? rid : "", &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - *icalcomp = icalparser_parse_string (comp_str); - CORBA_free (comp_str); + CORBA_exception_free (&ev); - if (!*icalcomp) { - retval = CAL_CLIENT_GET_SYNTAX_ERROR; - goto out; + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } - /* Now make sure we have all timezones needed for this object. - We do this to try to avoid any problems caused by getting a timezone - in the middle of other code. Any calls to ORBit result in a - recursive call of the GLib main loop, which can cause problems for - code that doesn't expect it. Currently GnomeCanvas has problems if - we try to get a timezone in the middle of a redraw, and there is a - resize pending, which leads to an assert failure and an abort. */ - cb_data.client = client; - cb_data.status = CAL_CLIENT_GET_SUCCESS; - icalcomponent_foreach_tzid (*icalcomp, - cal_client_get_object_timezones_cb, - &cb_data); + CORBA_exception_free (&ev); - retval = cb_data.status; + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); - out: + status = our_op->status; + *icalcomp = icalparser_parse_string (our_op->string); + g_free (our_op->string); - CORBA_exception_free (&ev); - return retval; + if (!*icalcomp) { + status = E_CALENDAR_STATUS_INVALID_OBJECT; + } else { + CalClientGetTimezonesData cb_data; + + /* Now make sure we have all timezones needed for this object. + We do this to try to avoid any problems caused by getting a timezone + in the middle of other code. Any calls to ORBit result in a + recursive call of the GTK+ main loop, which can cause problems for + code that doesn't expect it. Currently GnomeCanvas has problems if + we try to get a timezone in the middle of a redraw, and there is a + resize pending, which leads to an assert failure and an abort. */ + cb_data.client = client; + cb_data.status = E_CALENDAR_STATUS_OK; + icalcomponent_foreach_tzid (*icalcomp, + cal_client_get_object_timezones_cb, + &cb_data); + + status = cb_data.status; + } + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } @@ -1491,106 +2207,18 @@ cal_client_get_object_timezones_cb (icalparameter *param, CalClientGetTimezonesData *cb_data = data; const char *tzid; icaltimezone *zone; - CalClientGetStatus status; + GError *error = NULL; tzid = icalparameter_get_tzid (param); if (!tzid) { - cb_data->status = CAL_CLIENT_GET_SYNTAX_ERROR; + cb_data->status = E_CALENDAR_STATUS_INVALID_OBJECT; return; } - status = cal_client_get_timezone (cb_data->client, tzid, &zone); - if (status != CAL_CLIENT_GET_SUCCESS) - cb_data->status = status; -} - - -CalClientGetStatus -cal_client_get_timezone (CalClient *client, - const char *tzid, - icaltimezone **zone) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - GNOME_Evolution_Calendar_CalObj comp_str; - CalClientGetStatus retval; - icalcomponent *icalcomp; - icaltimezone *tmp_zone; - - g_return_val_if_fail (client != NULL, CAL_CLIENT_GET_NOT_FOUND); - g_return_val_if_fail (IS_CAL_CLIENT (client), CAL_CLIENT_GET_NOT_FOUND); - - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, - CAL_CLIENT_GET_NOT_FOUND); - - g_return_val_if_fail (zone != NULL, CAL_CLIENT_GET_NOT_FOUND); - - /* If tzid is NULL or "" we return NULL, since it is a 'local time'. */ - if (!tzid || !tzid[0]) { - *zone = NULL; - return CAL_CLIENT_GET_SUCCESS; - } - - /* If it is UTC, we return the special UTC timezone. */ - if (!strcmp (tzid, "UTC")) { - *zone = icaltimezone_get_utc_timezone (); - return CAL_CLIENT_GET_SUCCESS; - } - - /* See if we already have it in the cache. */ - tmp_zone = g_hash_table_lookup (priv->timezones, tzid); - if (tmp_zone) { - *zone = tmp_zone; - return CAL_CLIENT_GET_SUCCESS; - } - - retval = CAL_CLIENT_GET_NOT_FOUND; - *zone = NULL; - - /* We don't already have it, so we try to get it from the server. */ - CORBA_exception_init (&ev); - comp_str = GNOME_Evolution_Calendar_Cal_getTimezoneObject (priv->cal, (char *) tzid, &ev); - - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - goto out; - else if (BONOBO_EX (&ev)) { - g_message ("cal_client_get_timezone(): could not get the object"); - goto out; - } - - icalcomp = icalparser_parse_string (comp_str); - CORBA_free (comp_str); - - if (!icalcomp) { - retval = CAL_CLIENT_GET_SYNTAX_ERROR; - goto out; - } - - tmp_zone = icaltimezone_new (); - if (!tmp_zone) { - /* FIXME: Needs better error code - out of memory. Or just - abort like GLib does? */ - retval = CAL_CLIENT_GET_NOT_FOUND; - goto out; - } - - if (!icaltimezone_set_component (tmp_zone, icalcomp)) { - retval = CAL_CLIENT_GET_SYNTAX_ERROR; - goto out; - } - - /* Now add it to the cache, to avoid the server call in future. */ - g_hash_table_insert (priv->timezones, icaltimezone_get_tzid (tmp_zone), - tmp_zone); - - *zone = tmp_zone; - retval = CAL_CLIENT_GET_SUCCESS; - - out: - - CORBA_exception_free (&ev); - return retval; + if (!cal_client_get_timezone (cb_data->client, tzid, &zone, &error)) + cb_data->status = error->code; + + g_clear_error (&error); } /* Resolves TZIDs for the recurrence generator. */ @@ -1599,7 +2227,6 @@ cal_client_resolve_tzid_cb (const char *tzid, gpointer data) { CalClient *client; icaltimezone *zone = NULL; - CalClientGetStatus status; g_return_val_if_fail (data != NULL, NULL); g_return_val_if_fail (IS_CAL_CLIENT (data), NULL); @@ -1607,219 +2234,180 @@ cal_client_resolve_tzid_cb (const char *tzid, gpointer data) client = CAL_CLIENT (data); /* FIXME: Handle errors. */ - status = cal_client_get_timezone (client, tzid, &zone); + cal_client_get_timezone (client, tzid, &zone, NULL); return zone; } - -/* Builds an UID list out of a CORBA UID sequence */ -static GList * -build_uid_list (GNOME_Evolution_Calendar_CalObjUIDSeq *seq) -{ - GList *uids; - int i; - - uids = NULL; - - for (i = 0; i < seq->_length; i++) - uids = g_list_prepend (uids, g_strdup (seq->_buffer[i])); - - return uids; -} - -/** - * cal_client_get_uids: - * @client: A calendar client. - * @type: Bitmask with types of objects to return. - * - * Queries a calendar for a list of unique identifiers corresponding to calendar - * objects whose type matches one of the types specified in the @type flags. - * - * Return value: A list of strings that are the sought UIDs. This should be - * freed using the cal_obj_uid_list_free() function. - **/ -GList * -cal_client_get_uids (CalClient *client, CalObjType type) +gboolean +cal_client_get_changes (CalClient *client, CalObjType type, const char *change_id, GList **changes, GError **error) { - CalClientPrivate *priv; CORBA_Environment ev; - GNOME_Evolution_Calendar_CalObjUIDSeq *seq; - int t; - GList *uids; + ECalendarOp *our_op; + ECalendarStatus status; - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + g_return_val_if_fail (client != NULL, E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (IS_CAL_CLIENT (client), E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (change_id != NULL, E_CALENDAR_STATUS_INVALID_ARG); - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, NULL); + e_mutex_lock (client->priv->mutex); - t = corba_obj_type (type); - - CORBA_exception_init (&ev); + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } - seq = GNOME_Evolution_Calendar_Cal_getUIDs (priv->cal, t, &ev); - if (BONOBO_EX (&ev)) { - g_message ("cal_client_get_uids(): could not get the list of UIDs"); - CORBA_exception_free (&ev); - return NULL; + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); } - CORBA_exception_free (&ev); + our_op = e_calendar_new_op (client); - uids = build_uid_list (seq); - CORBA_free (seq); + e_mutex_lock (our_op->mutex); - return uids; -} + e_mutex_unlock (client->priv->mutex); -/* Builds a GList of CalClientChange structures from the CORBA sequence */ -static GList * -build_change_list (GNOME_Evolution_Calendar_CalObjChangeSeq *seq) -{ - GList *list = NULL; - icalcomponent *icalcomp; - int i; + CORBA_exception_init (&ev); - /* Create the list in reverse order */ - for (i = 0; i < seq->_length; i++) { - GNOME_Evolution_Calendar_CalObjChange *corba_coc; - CalClientChange *ccc; + GNOME_Evolution_Calendar_Cal_getChanges (client->priv->cal, type, change_id, &ev); - corba_coc = &seq->_buffer[i]; - ccc = g_new (CalClientChange, 1); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - icalcomp = icalparser_parse_string (corba_coc->calobj); - if (!icalcomp) - continue; + CORBA_exception_free (&ev); - ccc->comp = cal_component_new (); - if (!cal_component_set_icalcomponent (ccc->comp, icalcomp)) { - icalcomponent_free (icalcomp); - g_object_unref (G_OBJECT (ccc->comp)); - continue; - } - ccc->type = corba_coc->type; + g_warning (G_STRLOC ": Unable to contact backend"); - list = g_list_prepend (list, ccc); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } + + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); - list = g_list_reverse (list); + status = our_op->status; + *changes = our_op->list; - return list; + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } -GList * -cal_client_get_changes (CalClient *client, CalObjType type, const char *change_id) + +/** + * cal_client_get_object_list: + * @client: + * @query: + * + * + * + * Return value: + **/ +gboolean +cal_client_get_object_list (CalClient *client, const char *query, GList **objects, GError **error) { - CalClientPrivate *priv; CORBA_Environment ev; - GNOME_Evolution_Calendar_CalObjChangeSeq *seq; - int t; - GList *changes; + ECalendarOp *our_op; + ECalendarStatus status; - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + g_return_val_if_fail (client != NULL, E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (IS_CAL_CLIENT (client), E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (query != NULL, E_CALENDAR_STATUS_INVALID_ARG); - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, NULL); + e_mutex_lock (client->priv->mutex); - t = corba_obj_type (type); - CORBA_exception_init (&ev); + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } - seq = GNOME_Evolution_Calendar_Cal_getChanges (priv->cal, t, change_id, &ev); - if (BONOBO_EX (&ev)) { - g_message ("cal_client_get_changes(): could not get the list of changes"); - CORBA_exception_free (&ev); - return NULL; + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); } - CORBA_exception_free (&ev); + our_op = e_calendar_new_op (client); - changes = build_change_list (seq); - CORBA_free (seq); + e_mutex_lock (our_op->mutex); - return changes; -} + e_mutex_unlock (client->priv->mutex); -/* FIXME: Not used? */ -#if 0 -/* Builds a GList of CalObjInstance structures from the CORBA sequence */ -static GList * -build_object_instance_list (GNOME_Evolution_Calendar_CalObjInstanceSeq *seq) -{ - GList *list; - int i; + CORBA_exception_init (&ev); - /* Create the list in reverse order */ + GNOME_Evolution_Calendar_Cal_getObjectList (client->priv->cal, query, &ev); - list = NULL; - for (i = 0; i < seq->_length; i++) { - GNOME_Evolution_Calendar_CalObjInstance *corba_icoi; - CalObjInstance *icoi; + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - corba_icoi = &seq->_buffer[i]; - icoi = g_new (CalObjInstance, 1); + CORBA_exception_free (&ev); - icoi->uid = g_strdup (corba_icoi->uid); - icoi->start = corba_icoi->start; - icoi->end = corba_icoi->end; + g_warning (G_STRLOC ": Unable to contact backend"); - list = g_list_prepend (list, icoi); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } + + CORBA_exception_free (&ev); - list = g_list_reverse (list); - return list; -} -#endif - -/** - * cal_client_get_objects_in_range: - * @client: A calendar client. - * @type: Bitmask with types of objects to return. - * @start: Start time for query. - * @end: End time for query. - * - * Queries a calendar for the objects that occur or recur in the specified range - * of time. - * - * Return value: A list of UID strings. This should be freed using the - * cal_obj_uid_list_free() function. - **/ -GList * -cal_client_get_objects_in_range (CalClient *client, CalObjType type, time_t start, time_t end) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - GNOME_Evolution_Calendar_CalObjUIDSeq *seq; - GList *uids; - int t; - - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, NULL); + status = our_op->status; + *objects = our_op->list; - g_return_val_if_fail (start != -1 && end != -1, NULL); - g_return_val_if_fail (start <= end, NULL); + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - CORBA_exception_init (&ev); - - t = corba_obj_type (type); + E_CALENDAR_CHECK_STATUS (status, error); +} - seq = GNOME_Evolution_Calendar_Cal_getObjectsInRange (priv->cal, t, start, end, &ev); - if (BONOBO_EX (&ev)) { - g_message ("cal_client_get_objects_in_range(): could not get the objects"); - CORBA_exception_free (&ev); - return NULL; +gboolean +cal_client_get_object_list_as_comp (CalClient *client, const char *query, GList **objects, GError **error) +{ + GList *ical_objects = NULL; + GList *l; + + g_return_val_if_fail (client != NULL, E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (IS_CAL_CLIENT (client), E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (query != NULL, E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (objects != NULL, E_CALENDAR_STATUS_INVALID_ARG); + + if (!cal_client_get_object_list (client, query, &ical_objects, error)) + return FALSE; + + *objects = NULL; + for (l = ical_objects; l; l = l->next) { + CalComponent *comp; + + comp = cal_component_new (); + cal_component_set_icalcomponent (comp, l->data); + *objects = g_list_prepend (*objects, comp); } - CORBA_exception_free (&ev); + + g_list_free (ical_objects); - uids = build_uid_list (seq); - CORBA_free (seq); + return TRUE; +} + +void +cal_client_free_object_list (GList *objects) +{ + GList *l; + + for (l = objects; l; l = l->next) + icalcomponent_free (l->data); - return uids; + g_list_free (objects); } /** @@ -1833,57 +2421,81 @@ cal_client_get_objects_in_range (CalClient *client, CalObjType type, time_t star * * Returns: a GList of VFREEBUSY CalComponents */ -GList * -cal_client_get_free_busy (CalClient *client, GList *users, - time_t start, time_t end) +gboolean +cal_client_get_free_busy (CalClient *client, GList *users, time_t start, time_t end, + GList **freebusy, GError **error) { - CalClientPrivate *priv; CORBA_Environment ev; - GNOME_Evolution_Calendar_UserList *corba_list; - GNOME_Evolution_Calendar_CalObjSeq *calobj_list; + ECalendarOp *our_op; + ECalendarStatus status; + GNOME_Evolution_Calendar_UserList corba_users; GList *l; - GList *comp_list = NULL; - int len, i; + int i, len; + + g_return_val_if_fail (client != NULL, E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (IS_CAL_CLIENT (client), E_CALENDAR_STATUS_INVALID_ARG); - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + e_mutex_lock (client->priv->mutex); - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, NULL); + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } - g_return_val_if_fail (start != -1 && end != -1, NULL); - g_return_val_if_fail (start <= end, NULL); + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); /* create the CORBA user list to be passed to the backend */ len = g_list_length (users); - corba_list = GNOME_Evolution_Calendar_UserList__alloc (); - CORBA_sequence_set_release (corba_list, TRUE); - corba_list->_length = len; - corba_list->_buffer = CORBA_sequence_GNOME_Evolution_Calendar_User_allocbuf (len); + corba_users._length = len; + corba_users._buffer = CORBA_sequence_GNOME_Evolution_Calendar_User_allocbuf (len); - for (l = g_list_first (users), i = 0; l; l = l->next, i++) - corba_list->_buffer[i] = CORBA_string_dup ((CORBA_char *) l->data); + for (l = users, i = 0; l; l = l->next, i++) + corba_users._buffer[i] = CORBA_string_dup (l->data); - /* call the method on the backend */ CORBA_exception_init (&ev); - calobj_list = GNOME_Evolution_Calendar_Cal_getFreeBusy (priv->cal, corba_list, - start, end, &ev); - CORBA_free (corba_list); - if (BONOBO_EX (&ev) || !calobj_list) { - if (!BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - g_message ("cal_client_get_free_busy(): could not get the objects"); + GNOME_Evolution_Calendar_Cal_getFreeBusy (client->priv->cal, &corba_users, start, end, &ev); + + CORBA_free (corba_users._buffer); + + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + CORBA_exception_free (&ev); - return NULL; + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } + + CORBA_exception_free (&ev); - for (i = 0; i < calobj_list->_length; i++) { + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + + *freebusy = NULL; + for (l = our_op->list; l; l = l->next) { CalComponent *comp; + icalcomponent *icalcomp; icalcomponent_kind kind; - icalcomp = icalparser_parse_string (calobj_list->_buffer[i]); + icalcomp = icalparser_parse_string (l->data); if (!icalcomp) continue; @@ -1896,184 +2508,17 @@ cal_client_get_free_busy (CalClient *client, GList *users, continue; } - comp_list = g_list_append (comp_list, comp); + *freebusy = g_list_append (*freebusy, comp); } else icalcomponent_free (icalcomp); } - CORBA_exception_free (&ev); - CORBA_free (calobj_list); - - return comp_list; -} - -/* Callback used when an object is updated and we must update the copy we have */ -static void -generate_instances_obj_updated_cb (CalClient *client, const char *uid, gpointer data) -{ - GHashTable *uid_comp_hash; - CalComponent *comp; - icalcomponent *icalcomp; - CalClientGetStatus status; - const char *comp_uid; - - uid_comp_hash = data; - - comp = g_hash_table_lookup (uid_comp_hash, uid); - if (!comp) - /* OK, so we don't care about new objects that may indeed be in - * the requested time range. We only care about the ones that - * were returned by the first query to - * cal_client_get_objects_in_range(). - */ - return; - - g_hash_table_remove (uid_comp_hash, uid); - g_object_unref (G_OBJECT (comp)); - - status = cal_client_get_object (client, uid, &icalcomp); - - switch (status) { - case CAL_CLIENT_GET_SUCCESS: - comp = cal_component_new (); - if (cal_component_set_icalcomponent (comp, icalcomp)) { - /* The hash key comes from the component's internal data */ - cal_component_get_uid (comp, &comp_uid); - g_hash_table_insert (uid_comp_hash, (char *) comp_uid, comp); - } else { - g_object_unref (comp); - icalcomponent_free (icalcomp); - } - break; - - case CAL_CLIENT_GET_NOT_FOUND: - /* No longer in the server, too bad */ - break; - - case CAL_CLIENT_GET_SYNTAX_ERROR: - g_message ("obj_updated_cb(): Syntax error when getting " - "object `%s'; ignoring...", uid); - break; - - } -} - -/* Callback used when an object is removed and we must delete the copy we have */ -static void -generate_instances_obj_removed_cb (CalClient *client, const char *uid, gpointer data) -{ - GHashTable *uid_comp_hash; - CalComponent *comp; - - uid_comp_hash = data; - - comp = g_hash_table_lookup (uid_comp_hash, uid); - if (!comp) - return; - - g_hash_table_remove (uid_comp_hash, uid); - g_object_unref (G_OBJECT (comp)); -} - -/* Adds a component to the list; called from g_hash_table_foreach() */ -static void -add_component (gpointer key, gpointer value, gpointer data) -{ - CalComponent *comp; - GList **list; - - comp = CAL_COMPONENT (value); - list = data; - - *list = g_list_prepend (*list, comp); -} - -/* Gets a list of components that recur within the specified range of time. It - * ensures that the resulting list of CalComponent objects contains only objects - * that are actually in the server at the time the initial - * cal_client_get_objects_in_range() query ends. - */ -static GList * -get_objects_atomically (CalClient *client, CalObjType type, time_t start, time_t end) -{ - GList *uids; - GHashTable *uid_comp_hash; - GList *objects; - guint obj_updated_id; - guint obj_removed_id; - GList *l; - - uids = cal_client_get_objects_in_range (client, type, start, end); - - uid_comp_hash = g_hash_table_new (g_str_hash, g_str_equal); - - /* While we are getting the actual object data, keep track of changes */ - - obj_updated_id = g_signal_connect (G_OBJECT (client), "obj_updated", - G_CALLBACK (generate_instances_obj_updated_cb), - uid_comp_hash); - - obj_removed_id = g_signal_connect (G_OBJECT (client), "obj_removed", - G_CALLBACK (generate_instances_obj_removed_cb), - uid_comp_hash); - - /* Get the objects */ - - for (l = uids; l; l = l->next) { - CalComponent *comp; - icalcomponent *icalcomp; - CalClientGetStatus status; - char *uid; - const char *comp_uid; - - uid = l->data; - - status = cal_client_get_object (client, uid, &icalcomp); - - switch (status) { - case CAL_CLIENT_GET_SUCCESS: - comp = cal_component_new (); - if (cal_component_set_icalcomponent (comp, icalcomp)) { - /* The hash key comes from the component's internal data - * instead of the duped UID from the list of UIDS. - */ - cal_component_get_uid (comp, &comp_uid); - g_hash_table_insert (uid_comp_hash, (char *) comp_uid, comp); - } else { - g_object_unref (comp); - icalcomponent_free (icalcomp); - } - break; - - case CAL_CLIENT_GET_NOT_FOUND: - /* Object disappeared from the server, so don't log it */ - break; - - case CAL_CLIENT_GET_SYNTAX_ERROR: - g_message ("get_objects_atomically(): Syntax error when getting " - "object `%s'; ignoring...", uid); - break; - - default: - g_assert_not_reached (); - } - } - - cal_obj_uid_list_free (uids); - - /* Now our state is consistent with the server, so disconnect from the - * notification signals and generate the final list of components. - */ + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - g_signal_handler_disconnect (client, obj_updated_id); - g_signal_handler_disconnect (client, obj_removed_id); - - objects = NULL; - g_hash_table_foreach (uid_comp_hash, add_component, &objects); - g_hash_table_destroy (uid_comp_hash); - - return objects; + E_CALENDAR_CHECK_STATUS (status, error); } struct comp_instance { @@ -2127,10 +2572,8 @@ compare_comp_instance (gconstpointer a, gconstpointer b) * @cb: Callback for each generated instance. * @cb_data: Closure data for the callback. * - * Does a combination of cal_client_get_objects_in_range() and - * cal_recur_generate_instances(). It fetches the list of objects in an atomic - * way so that the generated instances are actually in the server at the time - * the initial cal_client_get_objects_in_range() query ends. + * Does a combination of cal_client_get_object_list () and + * cal_recur_generate_instances(). * * The callback function should do a g_object_ref() of the calendar component * it gets passed if it intends to keep it around. @@ -2144,7 +2587,8 @@ cal_client_generate_instances (CalClient *client, CalObjType type, GList *objects; GList *instances; GList *l; - + char *query; + g_return_if_fail (client != NULL); g_return_if_fail (IS_CAL_CLIENT (client)); @@ -2156,8 +2600,13 @@ cal_client_generate_instances (CalClient *client, CalObjType type, g_return_if_fail (cb != NULL); /* Generate objects */ + query = g_strdup_printf ("(occur-in-time-range? (%lu) (%lu))", start, end); + if (!cal_client_get_object_list (client, query, &objects, NULL)) { + g_free (query); + return; + } + g_free (query); - objects = get_objects_atomically (client, type, start, end); instances = NULL; for (l = objects; l; l = l->next) { @@ -2201,64 +2650,22 @@ cal_client_generate_instances (CalClient *client, CalObjType type, g_list_free (instances); } -/* Builds a list of CalAlarmInstance structures */ -static GSList * -build_alarm_instance_list (CalComponent *comp, GNOME_Evolution_Calendar_CalAlarmInstanceSeq *seq) -{ - GSList *alarms; - int i; - - alarms = NULL; - - for (i = 0; i < seq->_length; i++) { - GNOME_Evolution_Calendar_CalAlarmInstance *corba_instance; - CalComponentAlarm *alarm; - const char *auid; - CalAlarmInstance *instance; - - corba_instance = seq->_buffer + i; - - /* Since we want the in-commponent auid, we look for the alarm - * in the component and fetch its "real" auid. - */ - - alarm = cal_component_get_alarm (comp, corba_instance->auid); - if (!alarm) - continue; - - auid = cal_component_alarm_get_uid (alarm); - cal_component_alarm_free (alarm); - - instance = g_new (CalAlarmInstance, 1); - instance->auid = auid; - instance->trigger = corba_instance->trigger; - instance->occur_start = corba_instance->occur_start; - instance->occur_end = corba_instance->occur_end; - - alarms = g_slist_prepend (alarms, instance); - } - - return g_slist_reverse (alarms); -} - /* Builds a list of CalComponentAlarms structures */ static GSList * -build_component_alarms_list (GNOME_Evolution_Calendar_CalComponentAlarmsSeq *seq) +build_component_alarms_list (CalClient *client, GList *object_list, time_t start, time_t end) { GSList *comp_alarms; - int i; + GList *l; comp_alarms = NULL; - for (i = 0; i < seq->_length; i++) { - GNOME_Evolution_Calendar_CalComponentAlarms *corba_alarms; + for (l = object_list; l != NULL; l = l->next) { CalComponent *comp; CalComponentAlarms *alarms; icalcomponent *icalcomp; + CalAlarmAction omit[] = {-1}; - corba_alarms = seq->_buffer + i; - - icalcomp = icalparser_parse_string (corba_alarms->calobj); + icalcomp = icalparser_parse_string (l->data); if (!icalcomp) continue; @@ -2269,11 +2676,10 @@ build_component_alarms_list (GNOME_Evolution_Calendar_CalComponentAlarmsSeq *seq continue; } - alarms = g_new (CalComponentAlarms, 1); - alarms->comp = comp; - alarms->alarms = build_alarm_instance_list (comp, &corba_alarms->alarms); - - comp_alarms = g_slist_prepend (comp_alarms, alarms); + alarms = cal_util_generate_alarms_for_comp (comp, start, end, omit, cal_client_resolve_tzid_cb, + icalcomp, client->priv->default_zone); + if (alarms) + comp_alarms = g_slist_prepend (comp_alarms, alarms); } return comp_alarms; @@ -2297,9 +2703,9 @@ GSList * cal_client_get_alarms_in_range (CalClient *client, time_t start, time_t end) { CalClientPrivate *priv; - CORBA_Environment ev; - GNOME_Evolution_Calendar_CalComponentAlarmsSeq *seq; GSList *alarms; + char *sexp; + GList *object_list = NULL; g_return_val_if_fail (client != NULL, NULL); g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); @@ -2310,18 +2716,20 @@ cal_client_get_alarms_in_range (CalClient *client, time_t start, time_t end) g_return_val_if_fail (start != -1 && end != -1, NULL); g_return_val_if_fail (start <= end, NULL); - CORBA_exception_init (&ev); + /* build the query string */ + sexp = g_strdup ("(and (has-alarms? #t))"); - seq = GNOME_Evolution_Calendar_Cal_getAlarmsInRange (priv->cal, start, end, &ev); - if (BONOBO_EX (&ev)) { - g_message ("cal_client_get_alarms_in_range(): could not get the alarm range"); - CORBA_exception_free (&ev); + /* execute the query on the server */ + if (!cal_client_get_object_list (client, sexp, &object_list, NULL)) { + g_free (sexp); return NULL; } - CORBA_exception_free (&ev); - alarms = build_component_alarms_list (seq); - CORBA_free (seq); + alarms = build_component_alarms_list (client, object_list, start, end); + + g_list_foreach (object_list, (GFunc) g_free, NULL); + g_list_free (object_list); + g_free (sexp); return alarms; } @@ -2371,11 +2779,9 @@ cal_client_get_alarms_for_object (CalClient *client, const char *uid, CalComponentAlarms **alarms) { CalClientPrivate *priv; - CORBA_Environment ev; - GNOME_Evolution_Calendar_CalComponentAlarms *corba_alarms; - gboolean retval; icalcomponent *icalcomp; CalComponent *comp; + CalAlarmAction omit[] = {-1}; g_return_val_if_fail (client != NULL, FALSE); g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); @@ -2389,40 +2795,23 @@ cal_client_get_alarms_for_object (CalClient *client, const char *uid, g_return_val_if_fail (alarms != NULL, FALSE); *alarms = NULL; - retval = FALSE; - - CORBA_exception_init (&ev); - - corba_alarms = GNOME_Evolution_Calendar_Cal_getAlarmsForObject (priv->cal, (char *) uid, - start, end, &ev); - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - goto out; - else if (BONOBO_EX (&ev)) { - g_message ("cal_client_get_alarms_for_object(): could not get the alarm range"); - goto out; - } - icalcomp = icalparser_parse_string (corba_alarms->calobj); + if (!cal_client_get_object (client, uid, NULL, &icalcomp, NULL)) + return FALSE; if (!icalcomp) - goto out; + return FALSE; comp = cal_component_new (); if (!cal_component_set_icalcomponent (comp, icalcomp)) { icalcomponent_free (icalcomp); g_object_unref (G_OBJECT (comp)); - goto out; + return FALSE; } - retval = TRUE; - - *alarms = g_new (CalComponentAlarms, 1); - (*alarms)->comp = comp; - (*alarms)->alarms = build_alarm_instance_list (comp, &corba_alarms->alarms); - CORBA_free (corba_alarms); + *alarms = cal_util_generate_alarms_for_comp (comp, start, end, omit, cal_client_resolve_tzid_cb, + icalcomp, priv->default_zone); - out: - CORBA_exception_free (&ev); - return retval; + return TRUE; } /** @@ -2439,33 +2828,68 @@ cal_client_get_alarms_for_object (CalClient *client, const char *uid, * Return value: a #CalClientResult value indicating the result of the * operation. */ -CalClientResult -cal_client_discard_alarm (CalClient *client, CalComponent *comp, const char *auid) +gboolean +cal_client_discard_alarm (CalClient *client, CalComponent *comp, const char *auid, GError **error) { CalClientPrivate *priv; - CalClientResult retval; CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; const char *uid; - - g_return_val_if_fail (IS_CAL_CLIENT (client), CAL_CLIENT_RESULT_NOT_FOUND); - g_return_val_if_fail (IS_CAL_COMPONENT (comp), CAL_CLIENT_RESULT_NOT_FOUND); - g_return_val_if_fail (auid != NULL, CAL_CLIENT_RESULT_NOT_FOUND); + + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; + e_mutex_lock (client->priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); + cal_component_get_uid (comp, &uid); CORBA_exception_init (&ev); + GNOME_Evolution_Calendar_Cal_discardAlarm (priv->cal, uid, auid, &ev); - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - retval = CAL_CLIENT_RESULT_NOT_FOUND; - else if (BONOBO_EX (&ev)) - retval = CAL_CLIENT_RESULT_CORBA_ERROR; - else - retval = CAL_CLIENT_RESULT_SUCCESS; + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } CORBA_exception_free (&ev); - return retval; + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } typedef struct _ForeachTZIDCallbackData ForeachTZIDCallbackData; @@ -2500,10 +2924,7 @@ foreach_tzid_callback (icalparameter *param, void *cbdata) return; if (data->include_all_timezones) { - CalClientGetStatus status; - - status = cal_client_get_timezone (data->client, tzid, &zone); - if (status != CAL_CLIENT_GET_SUCCESS) { + if (!cal_client_get_timezone (data->client, tzid, &zone, NULL)) { data->success = FALSE; return; } @@ -2642,163 +3063,192 @@ cal_client_get_component_as_string (CalClient *client, icalcomponent *icalcomp) return cal_client_get_component_as_string_internal (client, icalcomp, TRUE); } -CalClientResult -cal_client_update_object_with_mod (CalClient *client, CalComponent *comp, CalObjModType mod) +gboolean +cal_client_create_object (CalClient *client, icalcomponent *icalcomp, char **uid, GError **error) { CalClientPrivate *priv; CORBA_Environment ev; - CalClientResult retval; - char *obj_string; + ECalendarStatus status; + ECalendarOp *our_op; - g_return_val_if_fail (client != NULL, CAL_CLIENT_RESULT_INVALID_OBJECT); - g_return_val_if_fail (IS_CAL_CLIENT (client), CAL_CLIENT_RESULT_INVALID_OBJECT); + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, CAL_CLIENT_RESULT_INVALID_OBJECT); - g_return_val_if_fail (comp != NULL, CAL_CLIENT_RESULT_INVALID_OBJECT); + e_mutex_lock (client->priv->mutex); - cal_component_commit_sequence (comp); + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } - obj_string = cal_client_get_component_as_string_internal (client, - cal_component_get_icalcomponent (comp), - FALSE); - if (obj_string == NULL) - return CAL_CLIENT_RESULT_INVALID_OBJECT; + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); CORBA_exception_init (&ev); - GNOME_Evolution_Calendar_Cal_updateObjects (priv->cal, obj_string, mod, &ev); - g_free (obj_string); - - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_InvalidObject)) - retval = CAL_CLIENT_RESULT_INVALID_OBJECT; - else if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - retval = CAL_CLIENT_RESULT_NOT_FOUND; - else if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_PermissionDenied)) - retval = CAL_CLIENT_RESULT_PERMISSION_DENIED; - else if (BONOBO_EX (&ev)) { - g_message ("cal_client_update_object(): could not update the object"); - retval = CAL_CLIENT_RESULT_CORBA_ERROR; + + GNOME_Evolution_Calendar_Cal_createObject (priv->cal, icalcomponent_as_ical_string (icalcomp), &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } - else - retval = CAL_CLIENT_RESULT_SUCCESS; CORBA_exception_free (&ev); - return retval; -} + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); -/** - * cal_client_update_object: - * @client: A calendar client. - * @comp: A calendar component object. - * - * Asks a calendar to update a component. Any existing component with the - * specified component's UID will be replaced. The client program should not - * assume that the object is actually in the server's storage until it has - * received the "obj_updated" notification signal. - * - * Return value: a #CalClientResult value indicating the result of the - * operation. - **/ -CalClientResult -cal_client_update_object (CalClient *client, CalComponent *comp) -{ + status = our_op->status; + if (uid) + *uid = our_op->uid; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); - return cal_client_update_object_with_mod (client, comp, CALOBJ_MOD_ALL); + E_CALENDAR_CHECK_STATUS (status, error); } -/** - * cal_client_update_objects: - * @client: A calendar client. - * @icalcomp: A toplevel VCALENDAR libical component. - * - * Asks a calendar to add or update one or more components, possibly including - * VTIMEZONE data. Any existing components with the same UIDs will be - * replaced. The VTIMEZONE data will be compared to existing VTIMEZONEs in - * the calendar, and the VTIMEZONEs may possibly be renamed, as well as all - * references to them throughout the VCALENDAR. - * - * The client program should not assume that the objects are actually in the - * server's storage until it has received the "obj_updated" notification - * signal. - * - * Return value: a #CalClientResult value indicating the result of the - * operation. - **/ -CalClientResult -cal_client_update_objects (CalClient *client, icalcomponent *icalcomp) +gboolean +cal_client_modify_object (CalClient *client, icalcomponent *icalcomp, CalObjModType mod, GError **error) { CalClientPrivate *priv; CORBA_Environment ev; - CalClientResult retval; - char *obj_string; + ECalendarStatus status; + ECalendarOp *our_op; - g_return_val_if_fail (client != NULL, CAL_CLIENT_RESULT_INVALID_OBJECT); - g_return_val_if_fail (IS_CAL_CLIENT (client), CAL_CLIENT_RESULT_INVALID_OBJECT); + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); + g_return_val_if_fail (icalcomp != NULL, FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, - CAL_CLIENT_RESULT_INVALID_OBJECT); - g_return_val_if_fail (icalcomp != NULL, CAL_CLIENT_RESULT_INVALID_OBJECT); + e_mutex_lock (client->priv->mutex); - /* Libical owns this memory, using one of its temporary buffers. */ - obj_string = icalcomponent_as_ical_string (icalcomp); + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); CORBA_exception_init (&ev); - GNOME_Evolution_Calendar_Cal_updateObjects (priv->cal, obj_string, GNOME_Evolution_Calendar_MOD_ALL, &ev); - - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_InvalidObject)) - retval = CAL_CLIENT_RESULT_INVALID_OBJECT; - else if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - retval = CAL_CLIENT_RESULT_NOT_FOUND; - else if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_PermissionDenied)) - retval = CAL_CLIENT_RESULT_PERMISSION_DENIED; - else if (BONOBO_EX (&ev)) { - g_message ("cal_client_update_objects(): could not update the objects"); - retval = CAL_CLIENT_RESULT_CORBA_ERROR; + + GNOME_Evolution_Calendar_Cal_modifyObject (priv->cal, icalcomponent_as_ical_string (icalcomp), mod, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } - else - retval = CAL_CLIENT_RESULT_SUCCESS; CORBA_exception_free (&ev); - return retval; + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } -CalClientResult -cal_client_remove_object_with_mod (CalClient *client, const char *uid, CalObjModType mod) +gboolean +cal_client_remove_object_with_mod (CalClient *client, const char *uid, + const char *rid, CalObjModType mod, GError **error) { CalClientPrivate *priv; CORBA_Environment ev; - CalClientResult retval; + ECalendarStatus status; + ECalendarOp *our_op; - g_return_val_if_fail (client != NULL, CAL_CLIENT_RESULT_INVALID_OBJECT); - g_return_val_if_fail (IS_CAL_CLIENT (client), CAL_CLIENT_RESULT_INVALID_OBJECT); + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, CAL_CLIENT_RESULT_INVALID_OBJECT); - g_return_val_if_fail (uid != NULL, CAL_CLIENT_RESULT_NOT_FOUND); + e_mutex_lock (client->priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); + CORBA_exception_init (&ev); - GNOME_Evolution_Calendar_Cal_removeObject (priv->cal, (char *) uid, mod, &ev); - - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_InvalidObject)) - retval = CAL_CLIENT_RESULT_INVALID_OBJECT; - else if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - retval = CAL_CLIENT_RESULT_NOT_FOUND; - else if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_PermissionDenied)) - retval = CAL_CLIENT_RESULT_PERMISSION_DENIED; - else if (BONOBO_EX (&ev)) { - g_message ("cal_client_remove_object(): could not remove the object"); - retval = CAL_CLIENT_RESULT_CORBA_ERROR; + + GNOME_Evolution_Calendar_Cal_removeObject (priv->cal, uid, rid ? rid : "", mod, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); } - else - retval = CAL_CLIENT_RESULT_SUCCESS; CORBA_exception_free (&ev); - return retval; + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } /** @@ -2813,69 +3263,319 @@ cal_client_remove_object_with_mod (CalClient *client, const char *uid, CalObjMod * Return value: a #CalClientResult value indicating the result of the * operation. **/ -CalClientResult -cal_client_remove_object (CalClient *client, const char *uid) +gboolean +cal_client_remove_object (CalClient *client, const char *uid, GError **error) { - return cal_client_remove_object_with_mod (client, uid, CALOBJ_MOD_ALL); + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); + + return cal_client_remove_object_with_mod (client, uid, NULL, CALOBJ_MOD_ALL, error); } -CalClientResult -cal_client_send_object (CalClient *client, icalcomponent *icalcomp, - icalcomponent **new_icalcomp, GList **users, - char **error_msg) +gboolean +cal_client_receive_objects (CalClient *client, icalcomponent *icalcomp, GError **error) { CalClientPrivate *priv; CORBA_Environment ev; - CalClientResult retval; - GNOME_Evolution_Calendar_UserList *user_list; - char *obj_string; - int i; + ECalendarStatus status; + ECalendarOp *our_op; + + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); + + priv = client->priv; + + e_mutex_lock (client->priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); + + CORBA_exception_init (&ev); + + GNOME_Evolution_Calendar_Cal_receiveObjects (priv->cal, icalcomponent_as_ical_string (icalcomp), &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } + + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; - g_return_val_if_fail (client != NULL, CAL_CLIENT_RESULT_INVALID_OBJECT); - g_return_val_if_fail (IS_CAL_CLIENT (client), CAL_CLIENT_RESULT_INVALID_OBJECT); + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +} + +gboolean +cal_client_send_objects (CalClient *client, icalcomponent *icalcomp, GError **error) +{ + CalClientPrivate *priv; + CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; + + g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, - CAL_CLIENT_RESULT_INVALID_OBJECT); - g_return_val_if_fail (icalcomp != NULL, CAL_CLIENT_RESULT_INVALID_OBJECT); + e_mutex_lock (client->priv->mutex); - /* Libical owns this memory, using one of its temporary buffers. */ - obj_string = icalcomponent_as_ical_string (icalcomp); + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); CORBA_exception_init (&ev); - obj_string = GNOME_Evolution_Calendar_Cal_sendObject (priv->cal, obj_string, &user_list, &ev); - - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_InvalidObject)) { - retval = CAL_CLIENT_SEND_INVALID_OBJECT; - } else if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_Busy)) { - retval = CAL_CLIENT_SEND_BUSY; - if (error_msg) - *error_msg = g_strdup (((GNOME_Evolution_Calendar_Cal_Busy *)(CORBA_exception_value (&ev)))->errorMsg); - } else if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_PermissionDenied)) { - retval = CAL_CLIENT_SEND_PERMISSION_DENIED; - } else if (BONOBO_EX (&ev)) { - g_message ("cal_client_update_objects(): could not send the objects"); - retval = CAL_CLIENT_SEND_CORBA_ERROR; + + GNOME_Evolution_Calendar_Cal_sendObjects (priv->cal, icalcomponent_as_ical_string (icalcomp), &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } + + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +} + +gboolean +cal_client_get_timezone (CalClient *client, const char *tzid, icaltimezone **zone, GError **error) +{ + CalClientPrivate *priv; + CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; + icalcomponent *icalcomp; + + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); + g_return_val_if_fail (tzid != NULL, FALSE); + + priv = client->priv; + + e_mutex_lock (priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (priv->mutex); + + /* Check for well known zones and in the cache */ + *zone = NULL; + + /* If tzid is NULL or "" we return NULL, since it is a 'local time'. */ + if (!tzid || !tzid[0]) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error); + } + + /* If it is UTC, we return the special UTC timezone. */ + if (!strcmp (tzid, "UTC")) { + *zone = icaltimezone_get_utc_timezone (); } else { - retval = CAL_CLIENT_RESULT_SUCCESS; - - *new_icalcomp = icalparser_parse_string (obj_string); - CORBA_free (obj_string); - - if (*new_icalcomp == NULL) { - retval = CAL_CLIENT_RESULT_INVALID_OBJECT; - } else { - *users = NULL; - for (i = 0; i < user_list->_length; i++) - *users = g_list_append (*users, g_strdup (user_list->_buffer[i])); - CORBA_free (user_list); - } + /* See if we already have it in the cache. */ + *zone = g_hash_table_lookup (priv->timezones, tzid); + } + + if (*zone) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error); } + /* call the backend */ + CORBA_exception_init (&ev); + + GNOME_Evolution_Calendar_Cal_getTimezone (priv->cal, tzid, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } + CORBA_exception_free (&ev); - return retval; + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + + icalcomp = icalparser_parse_string (our_op->string); + g_free (our_op->string); + + /* FIXME Invalid object status? */ + if (!icalcomp) + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OBJECT_NOT_FOUND, error); + + *zone = icaltimezone_new (); + if (!icaltimezone_set_component (*zone, icalcomp)) { + icaltimezone_free (*zone, 1); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OBJECT_NOT_FOUND, error); + } + + /* Now add it to the cache, to avoid the server call in future. */ + g_hash_table_insert (priv->timezones, icaltimezone_get_tzid (*zone), *zone); + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); +} + +/** + * cal_client_add_timezone + * @client: A calendar client. + * @izone: The timezone to add. + * @error: Placeholder for error information. + * + * Add a VTIMEZONE object to the given calendar. + * + * Returns: TRUE if successful, FALSE otherwise. + */ +gboolean +cal_client_add_timezone (CalClient *client, icaltimezone *izone, GError **error) +{ + CalClientPrivate *priv; + CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; + const char *tzobj; + + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); + g_return_val_if_fail (izone != NULL, FALSE); + + priv = client->priv; + + e_mutex_lock (priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } + + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (priv->mutex); + + /* convert icaltimezone into a string */ + tzobj = icalcomponent_as_ical_string (icaltimezone_get_component (izone)); + + /* call the backend */ + CORBA_exception_init (&ev); + + GNOME_Evolution_Calendar_Cal_addTimezone (priv->cal, tzobj, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } + + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } /** @@ -2888,20 +3588,68 @@ cal_client_send_object (CalClient *client, icalcomponent *icalcomp, * Return value: A query object that will emit notification signals as calendar * components are added and removed from the query in the server. **/ -CalQuery * -cal_client_get_query (CalClient *client, const char *sexp) +gboolean +cal_client_get_query (CalClient *client, const char *sexp, CalQuery **query, GError **error) { - CalClientPrivate *priv; + CORBA_Environment ev; + ECalendarOp *our_op; + ECalendarStatus status; - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); + g_return_val_if_fail (client != NULL, E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (IS_CAL_CLIENT (client), E_CALENDAR_STATUS_INVALID_ARG); + g_return_val_if_fail (query != NULL, E_CALENDAR_STATUS_INVALID_ARG); - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, FALSE); + e_mutex_lock (client->priv->mutex); + + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); + } - g_return_val_if_fail (sexp != NULL, NULL); + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (client->priv->mutex); + + CORBA_exception_init (&ev); + + our_op->listener = query_listener_new (); + GNOME_Evolution_Calendar_Cal_getQuery (client->priv->cal, sexp, BONOBO_OBJREF (our_op->listener), &ev); - return cal_query_new (client, priv->cal, sexp); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } + + CORBA_exception_free (&ev); + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + *query = our_op->query; + + bonobo_object_unref (BONOBO_OBJECT (our_op->listener)); + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } @@ -2910,19 +3658,16 @@ cal_client_get_query (CalClient *client, const char *sexp) DATE-TIME values into specific times. (Most of our IDL interface uses time_t values to pass specific times from the server to the client.) */ static gboolean -cal_client_ensure_timezone_on_server (CalClient *client, icaltimezone *zone) +cal_client_ensure_timezone_on_server (CalClient *client, icaltimezone *zone, GError **error) { CalClientPrivate *priv; - char *tzid, *obj_string; + char *tzid; icaltimezone *tmp_zone; - GString *vcal_string; - gboolean retval = FALSE; - icalcomponent *vtimezone_comp; - char *vtimezone_as_string; - CORBA_Environment ev; priv = client->priv; + /* FIXME This is highly broken since there is no locking */ + /* If the zone is NULL or UTC we don't need to do anything. */ if (!zone) return TRUE; @@ -2940,89 +3685,128 @@ cal_client_ensure_timezone_on_server (CalClient *client, icaltimezone *zone) /* Now we have to send it to the server, in case it doesn't already have it. */ - - vcal_string = g_string_new (NULL); - g_string_append (vcal_string, - "BEGIN:VCALENDAR\n" - "PRODID:-//Ximian//NONSGML Evolution Calendar//EN\n" - "VERSION:2.0\n"); - - /* Convert the timezone to a string and add it. */ - vtimezone_comp = icaltimezone_get_component (zone); - if (!vtimezone_comp) { - g_string_free (vcal_string, TRUE); - return FALSE; - } - - /* We don't need to free this string as libical owns it. */ - vtimezone_as_string = icalcomponent_as_ical_string (vtimezone_comp); - g_string_append (vcal_string, vtimezone_as_string); - - g_string_append (vcal_string, "END:VCALENDAR\n"); - - obj_string = vcal_string->str; - g_string_free (vcal_string, FALSE); - - CORBA_exception_init (&ev); - GNOME_Evolution_Calendar_Cal_updateObjects (priv->cal, obj_string, GNOME_Evolution_Calendar_MOD_ALL, &ev); - g_free (obj_string); - - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_InvalidObject)) - goto out; - else if (BONOBO_EX (&ev)) { - g_message ("cal_client_ensure_timezone_on_server(): could not add the timezone to the server"); - goto out; - } - - retval = TRUE; - - out: - CORBA_exception_free (&ev); - return retval; + return cal_client_add_timezone (client, zone, error); } - gboolean -cal_client_set_default_timezone (CalClient *client, icaltimezone *zone) +cal_client_set_default_timezone (CalClient *client, icaltimezone *zone, GError **error) { CalClientPrivate *priv; - gboolean retval = FALSE; CORBA_Environment ev; + ECalendarStatus status; + ECalendarOp *our_op; const char *tzid; - - g_return_val_if_fail (client != NULL, FALSE); + g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); g_return_val_if_fail (zone != NULL, FALSE); priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, - FALSE); - /* Make sure the server has the VTIMEZONE data. */ - if (!cal_client_ensure_timezone_on_server (client, zone)) + if (!cal_client_ensure_timezone_on_server (client, zone, error)) return FALSE; - /* Now set the default timezone on the server. */ - CORBA_exception_init (&ev); - tzid = icaltimezone_get_tzid (zone); - GNOME_Evolution_Calendar_Cal_setDefaultTimezone (priv->cal, - (char *) tzid, &ev); + e_mutex_lock (priv->mutex); - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound)) - goto out; - else if (BONOBO_EX (&ev)) { - g_message ("cal_client_set_default_timezone(): could not set the default timezone"); - goto out; + if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); } - retval = TRUE; + if (client->priv->current_op != NULL) { + e_mutex_unlock (client->priv->mutex); + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); + } + + our_op = e_calendar_new_op (client); + + e_mutex_lock (our_op->mutex); + + e_mutex_unlock (priv->mutex); - priv->default_zone = zone; + /* FIXME Adding it to the server to change the tzid */ + tzid = icaltimezone_get_tzid (zone); + + /* call the backend */ + CORBA_exception_init (&ev); - out: + GNOME_Evolution_Calendar_Cal_setDefaultTimezone (priv->cal, tzid, &ev); + if (BONOBO_EX (&ev)) { + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + CORBA_exception_free (&ev); + + g_warning (G_STRLOC ": Unable to contact backend"); + + E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); + } CORBA_exception_free (&ev); - return retval; + + /* wait for something to happen (both cancellation and a + successful response will notity us via our cv */ + e_mutex_cond_wait (&our_op->cond, our_op->mutex); + + status = our_op->status; + + e_calendar_remove_op (client, our_op); + e_mutex_unlock (our_op->mutex); + e_calendar_free_op (our_op); + + E_CALENDAR_CHECK_STATUS (status, error); } +/** + * cal_client_get_error_message + * @status: A status code. + * + * Get an error message for the given status code. + * + * Returns: the error message. + */ +const char * +cal_client_get_error_message (ECalendarStatus status) +{ + switch (status) { + case E_CALENDAR_STATUS_INVALID_ARG : + return _("Invalid argument"); + case E_CALENDAR_STATUS_BUSY : + return _("Backend is busy"); + case E_CALENDAR_STATUS_REPOSITORY_OFFLINE : + return _("Repository is offline"); + case E_CALENDAR_STATUS_NO_SUCH_CALENDAR : + return _("No such calendar"); + case E_CALENDAR_STATUS_OBJECT_NOT_FOUND : + return _("Object not found"); + case E_CALENDAR_STATUS_INVALID_OBJECT : + return _("Invalid object"); + case E_CALENDAR_STATUS_URI_NOT_LOADED : + return _("URI not loaded"); + case E_CALENDAR_STATUS_URI_ALREADY_LOADED : + return _("URI already loaded"); + case E_CALENDAR_STATUS_PERMISSION_DENIED : + return _("Permission denied"); + case E_CALENDAR_STATUS_CARD_NOT_FOUND : + return _("Object not found"); + case E_CALENDAR_STATUS_CARD_ID_ALREADY_EXISTS : + return _("Object ID already exists"); + case E_CALENDAR_STATUS_PROTOCOL_NOT_SUPPORTED : + return _("Protocol not supported"); + case E_CALENDAR_STATUS_CANCELLED : + return _("Operation has been cancelled"); + case E_CALENDAR_STATUS_COULD_NOT_CANCEL : + return _("Could not cancel operation"); + case E_CALENDAR_STATUS_AUTHENTICATION_FAILED : + return _("Authentication failed"); + case E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED : + return _("Authentication required"); + case E_CALENDAR_STATUS_CORBA_EXCEPTION : + return _("A CORBA esception has occurred"); + case E_CALENDAR_STATUS_OTHER_ERROR : + return _("Unknown error"); + } + + return NULL; +} diff --git a/calendar/cal-client/cal-client.h b/calendar/cal-client/cal-client.h index 961ba5d993..277522f097 100644 --- a/calendar/cal-client/cal-client.h +++ b/calendar/cal-client/cal-client.h @@ -25,6 +25,7 @@ #include <cal-util/cal-recur.h> #include <cal-util/cal-util.h> #include <cal-client/cal-query.h> +#include "cal-client-types.h" G_BEGIN_DECLS @@ -37,6 +38,7 @@ G_BEGIN_DECLS #define IS_CAL_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CAL_CLIENT_TYPE)) #define CAL_CLIENT_OPEN_STATUS_ENUM_TYPE (cal_client_open_status_enum_get_type ()) +#define CAL_CLIENT_REMOVE_STATUS_ENUM_TYPE (cal_client_remove_status_enum_get_type ()) #define CAL_CLIENT_SET_MODE_STATUS_ENUM_TYPE (cal_client_set_mode_status_enum_get_type ()) #define CAL_MODE_ENUM_TYPE (cal_mode_enum_get_type ()) @@ -76,14 +78,6 @@ typedef enum { CAL_CLIENT_RESULT_PERMISSION_DENIED } CalClientResult; -typedef enum { - CAL_CLIENT_SEND_SUCCESS, - CAL_CLIENT_SEND_CORBA_ERROR, - CAL_CLIENT_SEND_INVALID_OBJECT, - CAL_CLIENT_SEND_BUSY, - CAL_CLIENT_SEND_PERMISSION_DENIED -} CalClientSendResult; - /* Whether the client is not loaded, is being loaded, or is already loaded */ typedef enum { CAL_CLIENT_LOAD_NOT_LOADED, @@ -104,10 +98,7 @@ struct _CalClientClass { /* Notification signals */ void (* cal_opened) (CalClient *client, CalClientOpenStatus status); - void (* cal_set_mode) (CalClient *client, CalClientSetModeStatus status, CalMode mode); - - void (* obj_updated) (CalClient *client, const char *uid); - void (* obj_removed) (CalClient *client, const char *uid); + void (* cal_set_mode) (CalClient *client, CalClientSetModeStatus status, CalMode mode); void (* backend_error) (CalClient *client, const char *message); @@ -129,21 +120,13 @@ GType cal_client_open_status_enum_get_type (void); GType cal_client_set_mode_status_enum_get_type (void); GType cal_mode_enum_get_type (void); -CalClient *cal_client_construct (CalClient *client); - -CalClient *cal_client_new (void); +CalClient *cal_client_new (const char *uri, CalObjType type); void cal_client_set_auth_func (CalClient *client, CalClientAuthFunc func, gpointer data); -/* Sets the default timezone to use to resolve DATE and floating DATE-TIME - values. This will typically be from the user's timezone setting. Call this - before using any other functions. It will pass the default timezone on to - the server. Returns TRUE on success. */ -gboolean cal_client_set_default_timezone (CalClient *client, icaltimezone *zone); - -gboolean cal_client_open_calendar (CalClient *client, const char *str_uri, gboolean only_if_exists); -gboolean cal_client_open_default_calendar (CalClient *client, gboolean only_if_exists); -gboolean cal_client_open_default_tasks (CalClient *client, gboolean only_if_exists); +gboolean cal_client_open (CalClient *client, gboolean only_if_exists, GError **error); +void cal_client_open_async (CalClient *client, gboolean only_if_exists); +gboolean cal_client_remove_calendar (CalClient *client, GError **error); GList *cal_client_uri_list (CalClient *client, CalMode mode); @@ -151,11 +134,10 @@ CalClientLoadState cal_client_get_load_state (CalClient *client); const char *cal_client_get_uri (CalClient *client); -gboolean cal_client_is_read_only (CalClient *client); - -const char *cal_client_get_cal_address (CalClient *client); -const char *cal_client_get_alarm_email_address (CalClient *client); -const char *cal_client_get_ldap_attribute (CalClient *client); +gboolean cal_client_is_read_only (CalClient *client, gboolean *read_only, GError **error); +gboolean cal_client_get_cal_address (CalClient *client, char **cal_address, GError **error); +gboolean cal_client_get_alarm_email_address (CalClient *client, char **alarm_address, GError **error); +gboolean cal_client_get_ldap_attribute (CalClient *client, char **ldap_attribute, GError **error); gboolean cal_client_get_one_alarm_only (CalClient *client); gboolean cal_client_get_organizer_must_attend (CalClient *client); @@ -164,28 +146,23 @@ gboolean cal_client_get_static_capability (CalClient *client, const char *cap); gboolean cal_client_set_mode (CalClient *client, CalMode mode); -int cal_client_get_n_objects (CalClient *client, CalObjType type); - -CalClientGetStatus cal_client_get_default_object (CalClient *client, - CalObjType type, - icalcomponent **icalcomp); +gboolean cal_client_get_default_object (CalClient *client, + icalcomponent **icalcomp, GError **error); -CalClientGetStatus cal_client_get_object (CalClient *client, - const char *uid, - icalcomponent **icalcomp); +gboolean cal_client_get_object (CalClient *client, + const char *uid, + const char *rid, + icalcomponent **icalcomp, + GError **error); -CalClientGetStatus cal_client_get_timezone (CalClient *client, - const char *tzid, - icaltimezone **zone); +gboolean cal_client_get_changes (CalClient *client, CalObjType type, const char *change_id, GList **changes, GError **error); -GList *cal_client_get_uids (CalClient *client, CalObjType type); -GList *cal_client_get_changes (CalClient *client, CalObjType type, const char *change_id); +gboolean cal_client_get_object_list (CalClient *client, const char *query, GList **objects, GError **error); +gboolean cal_client_get_object_list_as_comp (CalClient *client, const char *query, GList **objects, GError **error); +void cal_client_free_object_list (GList *objects); -GList *cal_client_get_objects_in_range (CalClient *client, CalObjType type, - time_t start, time_t end); - -GList *cal_client_get_free_busy (CalClient *client, GList *users, - time_t start, time_t end); +gboolean cal_client_get_free_busy (CalClient *client, GList *users, time_t start, time_t end, + GList **freebusy, GError **error); void cal_client_generate_instances (CalClient *client, CalObjType type, time_t start, time_t end, @@ -199,24 +176,25 @@ gboolean cal_client_get_alarms_for_object (CalClient *client, const char *uid, time_t start, time_t end, CalComponentAlarms **alarms); -CalClientResult cal_client_discard_alarm (CalClient *client, CalComponent *comp, const char *auid); - -/* Add or update a single object. When adding an object only builtin timezones - are allowed. To use external VTIMEZONE data call update_objects() instead.*/ -CalClientResult cal_client_update_object (CalClient *client, CalComponent *comp); -CalClientResult cal_client_update_object_with_mod (CalClient *client, CalComponent *comp, CalObjModType mod); +gboolean cal_client_create_object (CalClient *client, icalcomponent *icalcomp, char **uid, GError **error); +gboolean cal_client_modify_object (CalClient *client, icalcomponent *icalcomp, CalObjModType mod, GError **error); +gboolean cal_client_remove_object (CalClient *client, const char *uid, GError **error); +gboolean cal_client_remove_object_with_mod (CalClient *client, const char *uid, const char *rid, CalObjModType mod, GError **error); -/* Add or update multiple objects, possibly including VTIMEZONE data. */ -CalClientResult cal_client_update_objects (CalClient *client, icalcomponent *icalcomp); +gboolean cal_client_discard_alarm (CalClient *client, CalComponent *comp, const char *auid, GError **error); -CalClientResult cal_client_remove_object (CalClient *client, const char *uid); -CalClientResult cal_client_remove_object_with_mod (CalClient *client, const char *uid, CalObjModType mod); +gboolean cal_client_receive_objects (CalClient *client, icalcomponent *icalcomp, GError **error); +gboolean cal_client_send_objects (CalClient *client, icalcomponent *icalcomp, GError **error); -CalClientSendResult cal_client_send_object (CalClient *client, icalcomponent *icalcomp, - icalcomponent **new_icalcomp, GList **users, - char **error_msg); +gboolean cal_client_get_timezone (CalClient *client, const char *tzid, icaltimezone **zone, GError **error); +gboolean cal_client_add_timezone (CalClient *client, icaltimezone *izone, GError **error); +/* Sets the default timezone to use to resolve DATE and floating DATE-TIME + values. This will typically be from the user's timezone setting. Call this + before using any other functions. It will pass the default timezone on to + the server. Returns TRUE on success. */ +gboolean cal_client_set_default_timezone (CalClient *client, icaltimezone *zone, GError **error); -CalQuery *cal_client_get_query (CalClient *client, const char *sexp); +gboolean cal_client_get_query (CalClient *client, const char *sexp, CalQuery **query, GError **error); /* Resolves TZIDs for the recurrence generator. */ icaltimezone *cal_client_resolve_tzid_cb (const char *tzid, gpointer data); @@ -225,6 +203,7 @@ icaltimezone *cal_client_resolve_tzid_cb (const char *tzid, gpointer data); used by the component. It also includes a 'METHOD:PUBLISH' property. */ char* cal_client_get_component_as_string (CalClient *client, icalcomponent *icalcomp); +const char * cal_client_get_error_message (ECalendarStatus status); diff --git a/calendar/cal-client/cal-listener.c b/calendar/cal-client/cal-listener.c index c7beef8c97..ac04be7c07 100644 --- a/calendar/cal-client/cal-listener.c +++ b/calendar/cal-client/cal-listener.c @@ -19,6 +19,9 @@ */ #include <config.h> + +#include <bonobo/bonobo-main.h> +#include "cal-marshal.h" #include "cal-listener.h" @@ -26,10 +29,7 @@ /* Private part of the CalListener structure */ struct CalListenerPrivate { /* Notification functions and their closure data */ - CalListenerCalOpenedFn cal_opened_fn; CalListenerCalSetModeFn cal_set_mode_fn; - CalListenerObjUpdatedFn obj_updated_fn; - CalListenerObjRemovedFn obj_removed_fn; CalListenerErrorOccurredFn error_occurred_fn; CalListenerCategoriesChangedFn categories_changed_fn; gpointer fn_data; @@ -38,124 +38,178 @@ struct CalListenerPrivate { gboolean notify : 1; }; - +/* Signal IDs */ +enum { + READ_ONLY, + CAL_ADDRESS, + ALARM_ADDRESS, + LDAP_ATTRIBUTE, + STATIC_CAPABILITIES, + OPEN, + REMOVE, + CREATE_OBJECT, + MODIFY_OBJECT, + REMOVE_OBJECT, + DISCARD_ALARM, + RECEIVE_OBJECTS, + SEND_OBJECTS, + DEFAULT_OBJECT, + OBJECT, + OBJECT_LIST, + GET_TIMEZONE, + ADD_TIMEZONE, + SET_DEFAULT_TIMEZONE, + GET_CHANGES, + GET_FREE_BUSY, + QUERY, + LAST_SIGNAL +}; -static void cal_listener_class_init (CalListenerClass *klass); -static void cal_listener_init (CalListener *listener, CalListenerClass *klass); -static void cal_listener_finalize (GObject *object); - -static void impl_notifyCalOpened (PortableServer_Servant servant, - GNOME_Evolution_Calendar_Listener_OpenStatus status, - GNOME_Evolution_Calendar_Cal cal, - CORBA_Environment *ev); -static void impl_notifyCalSetMode (PortableServer_Servant servant, - GNOME_Evolution_Calendar_Listener_SetModeStatus status, - GNOME_Evolution_Calendar_CalMode mode, - CORBA_Environment *ev); -static void impl_notifyObjUpdated (PortableServer_Servant servant, - const CORBA_char *uid, - CORBA_Environment *ev); -static void impl_notifyObjRemoved (PortableServer_Servant servant, - const CORBA_char *uid, - CORBA_Environment *ev); -static void impl_notifyErrorOccurred (PortableServer_Servant servant, - const CORBA_char *message, - CORBA_Environment *ev); -static void impl_notifyCategoriesChanged (PortableServer_Servant servant, - const GNOME_Evolution_Calendar_StringSeq *categories, - CORBA_Environment *ev); +static guint signals[LAST_SIGNAL] = { 0 }; static BonoboObjectClass *parent_class; - - -BONOBO_TYPE_FUNC_FULL (CalListener, - GNOME_Evolution_Calendar_Listener, - BONOBO_TYPE_OBJECT, - cal_listener); +static ECalendarStatus +convert_status (const GNOME_Evolution_Calendar_CallStatus status) +{ + switch (status) { + case GNOME_Evolution_Calendar_Success: + return E_CALENDAR_STATUS_OK; + case GNOME_Evolution_Calendar_RepositoryOffline: + return E_CALENDAR_STATUS_REPOSITORY_OFFLINE; + case GNOME_Evolution_Calendar_PermissionDenied: + return E_CALENDAR_STATUS_PERMISSION_DENIED; + case GNOME_Evolution_Calendar_ObjectNotFound: + return E_CALENDAR_STATUS_OBJECT_NOT_FOUND; + case GNOME_Evolution_Calendar_InvalidObject: + return E_CALENDAR_STATUS_INVALID_OBJECT; + case GNOME_Evolution_Calendar_CardIdAlreadyExists: + return E_CALENDAR_STATUS_CARD_ID_ALREADY_EXISTS; + case GNOME_Evolution_Calendar_AuthenticationFailed: + return E_CALENDAR_STATUS_AUTHENTICATION_FAILED; + case GNOME_Evolution_Calendar_AuthenticationRequired: + return E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED; + case GNOME_Evolution_Calendar_OtherError: + default: + return E_CALENDAR_STATUS_OTHER_ERROR; + } +} -/* Class initialization function for the calendar listener */ static void -cal_listener_class_init (CalListenerClass *klass) +impl_notifyReadOnly (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + const CORBA_boolean read_only, + CORBA_Environment *ev) { - GObjectClass *object_class; - - object_class = (GObjectClass *) klass; + CalListener *listener; + CalListenerPrivate *priv; - parent_class = g_type_class_peek_parent (klass); + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; - klass->epv.notifyCalOpened = impl_notifyCalOpened; - klass->epv.notifyCalSetMode = impl_notifyCalSetMode; - klass->epv.notifyObjUpdated = impl_notifyObjUpdated; - klass->epv.notifyObjRemoved = impl_notifyObjRemoved; - klass->epv.notifyErrorOccurred = impl_notifyErrorOccurred; - klass->epv.notifyCategoriesChanged = impl_notifyCategoriesChanged; + if (!priv->notify) + return; - object_class->finalize = cal_listener_finalize; + g_signal_emit (G_OBJECT (listener), signals[READ_ONLY], 0, convert_status (status), read_only); } -/* Object initialization function for the calendar listener */ static void -cal_listener_init (CalListener *listener, CalListenerClass *klass) +impl_notifyCalAddress (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + const CORBA_char *address, + CORBA_Environment *ev) { + CalListener *listener; CalListenerPrivate *priv; - priv = g_new0 (CalListenerPrivate, 1); - listener->priv = priv; + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; - priv->cal_opened_fn = NULL; - priv->obj_updated_fn = NULL; - priv->obj_removed_fn = NULL; - priv->error_occurred_fn = NULL; - priv->categories_changed_fn = NULL; + if (!priv->notify) + return; - priv->notify = TRUE; + g_signal_emit (G_OBJECT (listener), signals[CAL_ADDRESS], 0, convert_status (status), address); } -/* Finalize handler for the calendar listener */ static void -cal_listener_finalize (GObject *object) +impl_notifyAlarmEmailAddress (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + const CORBA_char *address, + CORBA_Environment *ev) { CalListener *listener; CalListenerPrivate *priv; - g_return_if_fail (object != NULL); - g_return_if_fail (IS_CAL_LISTENER (object)); - - listener = CAL_LISTENER (object); + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); priv = listener->priv; - priv->cal_opened_fn = NULL; - priv->obj_updated_fn = NULL; - priv->obj_removed_fn = NULL; - priv->error_occurred_fn = NULL; - priv->categories_changed_fn = NULL; - priv->fn_data = NULL; + if (!priv->notify) + return; - priv->notify = FALSE; + g_signal_emit (G_OBJECT (listener), signals[ALARM_ADDRESS], 0, convert_status (status), address); +} - g_free (priv); - listener->priv = NULL; +static void +impl_notifyLDAPAttribute (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + const CORBA_char *ldap_attribute, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; - if (G_OBJECT_CLASS (parent_class)->finalize) - (* G_OBJECT_CLASS (parent_class)->finalize) (object); + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[LDAP_ATTRIBUTE], 0, convert_status (status), ldap_attribute); } - +static void +impl_notifyStaticCapabilities (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + const CORBA_char *capabilities, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; -/* CORBA servant implementation */ + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[STATIC_CAPABILITIES], 0, convert_status (status)); +} /* ::notifyCalOpened method */ static void impl_notifyCalOpened (PortableServer_Servant servant, - GNOME_Evolution_Calendar_Listener_OpenStatus status, - GNOME_Evolution_Calendar_Cal cal, + GNOME_Evolution_Calendar_CallStatus status, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[OPEN], 0, convert_status (status)); +} + +static void +impl_notifyCalRemoved (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, CORBA_Environment *ev) { CalListener *listener; CalListenerPrivate *priv; - CORBA_Environment aev; - GNOME_Evolution_Calendar_Cal cal_copy; listener = CAL_LISTENER (bonobo_object_from_servant (servant)); priv = listener->priv; @@ -163,63 +217,388 @@ impl_notifyCalOpened (PortableServer_Servant servant, if (!priv->notify) return; - CORBA_exception_init (&aev); - cal_copy = CORBA_Object_duplicate (cal, &aev); + g_signal_emit (G_OBJECT (listener), signals[REMOVE], 0, convert_status (status)); +} + +static void +impl_notifyObjectCreated (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + const CORBA_char *uid, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[CREATE_OBJECT], 0, convert_status (status), uid); +} + +static void +impl_notifyObjectModified (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; - if (aev._major != CORBA_NO_EXCEPTION) { - g_message ("Listener_notifyCalOpened(): could not duplicate the calendar"); - CORBA_exception_free (&aev); + if (!priv->notify) return; + + g_signal_emit (G_OBJECT (listener), signals[MODIFY_OBJECT], 0, convert_status (status)); +} + +static void +impl_notifyObjectRemoved (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[REMOVE_OBJECT], 0, convert_status (status)); +} + +static void +impl_notifyAlarmDiscarded (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[DISCARD_ALARM], 0, convert_status (status)); +} + +static void +impl_notifyObjectsReceived (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[RECEIVE_OBJECTS], 0, convert_status (status)); +} + +static void +impl_notifyObjectsSent (PortableServer_Servant servant, + GNOME_Evolution_Calendar_CallStatus status, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[SEND_OBJECTS], 0, convert_status (status)); +} + +static void +impl_notifyDefaultObjectRequested (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CallStatus status, + const CORBA_char *object, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[DEFAULT_OBJECT], 0, convert_status (status), object); +} + +static void +impl_notifyObjectRequested (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CallStatus status, + const CORBA_char *object, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[OBJECT], 0, convert_status (status), object); +} + +static GList * +build_object_list (const GNOME_Evolution_Calendar_stringlist *seq) +{ + GList *list; + int i; + + list = NULL; + for (i = 0; i < seq->_length; i++) { + icalcomponent *comp; + + comp = icalcomponent_new_from_string (seq->_buffer[i]); + if (!comp) + continue; + + list = g_list_prepend (list, comp); } - CORBA_exception_free (&aev); - g_assert (priv->cal_opened_fn != NULL); - (* priv->cal_opened_fn) (listener, status, cal, priv->fn_data); + return list; +} + +static void +impl_notifyObjectListRequested (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CallStatus status, + const GNOME_Evolution_Calendar_stringlist *objects, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + GList *object_list, *l; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + object_list = build_object_list (objects); + + g_signal_emit (G_OBJECT (listener), signals[OBJECT_LIST], 0, convert_status (status), object_list); + + for (l = object_list; l; l = l->next) + icalcomponent_free (l->data); + g_list_free (object_list); } -/* ::notifyCalSetMode method */ static void -impl_notifyCalSetMode (PortableServer_Servant servant, - GNOME_Evolution_Calendar_Listener_SetModeStatus status, - GNOME_Evolution_Calendar_CalMode mode, - CORBA_Environment *ev) +impl_notifyTimezoneRequested (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CallStatus status, + const CORBA_char *object, + CORBA_Environment *ev) { CalListener *listener; CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[GET_TIMEZONE], 0, convert_status (status), object); +} +static void +impl_notifyTimezoneAdded (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CallStatus status, + const CORBA_char *tzid, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); priv = listener->priv; if (!priv->notify) return; + + g_signal_emit (G_OBJECT (listener), signals[ADD_TIMEZONE], 0, convert_status (status), tzid); +} - g_assert (priv->cal_set_mode_fn != NULL); - (* priv->cal_set_mode_fn) (listener, status, mode, priv->fn_data); +static void +impl_notifyDefaultTimezoneSet (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CallStatus status, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[SET_DEFAULT_TIMEZONE], 0, convert_status (status)); +} + +static GList * +build_change_list (const GNOME_Evolution_Calendar_CalObjChangeSeq *seq) +{ + GList *list = NULL; + icalcomponent *icalcomp; + int i; + + /* Create the list in reverse order */ + for (i = 0; i < seq->_length; i++) { + GNOME_Evolution_Calendar_CalObjChange *corba_coc; + CalClientChange *ccc; + + corba_coc = &seq->_buffer[i]; + ccc = g_new (CalClientChange, 1); + + icalcomp = icalparser_parse_string (corba_coc->calobj); + if (!icalcomp) + continue; + + ccc->comp = cal_component_new (); + if (!cal_component_set_icalcomponent (ccc->comp, icalcomp)) { + icalcomponent_free (icalcomp); + g_object_unref (G_OBJECT (ccc->comp)); + continue; + } + ccc->type = corba_coc->type; + + list = g_list_prepend (list, ccc); + } + + list = g_list_reverse (list); + + return list; } -/* ::notifyObjUpdated method */ static void -impl_notifyObjUpdated (PortableServer_Servant servant, - const CORBA_char *uid, - CORBA_Environment *ev) +impl_notifyChanges (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CallStatus status, + const GNOME_Evolution_Calendar_CalObjChangeSeq *seq, + CORBA_Environment *ev) { CalListener *listener; CalListenerPrivate *priv; + GList *changes, *l; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + if (!priv->notify) + return; + + changes = build_change_list (seq); + + g_signal_emit (G_OBJECT (listener), signals[GET_CHANGES], 0, convert_status (status), changes); + + for (l = changes; l; l = l->next) + g_free (l->data); + g_list_free (changes); +} + +static GList * +build_free_busy_list (const GNOME_Evolution_Calendar_CalObjSeq *seq) +{ + GList *list = NULL; + int i; + + /* Create the list in reverse order */ + for (i = 0; i < seq->_length; i++) { + CalComponent *comp; + icalcomponent *icalcomp; + icalcomponent_kind kind; + + icalcomp = icalcomponent_new_from_string (seq->_buffer[i]); + if (!icalcomp) + continue; + + kind = icalcomponent_isa (icalcomp); + if (kind == ICAL_VFREEBUSY_COMPONENT) { + comp = cal_component_new (); + if (!cal_component_set_icalcomponent (comp, icalcomp)) { + icalcomponent_free (icalcomp); + g_object_unref (G_OBJECT (comp)); + continue; + } + + list = g_list_append (list, comp); + } else { + icalcomponent_free (icalcomp); + } + } + + return list; +} + +static void +impl_notifyFreeBusy (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CallStatus status, + const GNOME_Evolution_Calendar_CalObjSeq *seq, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + GList *freebusy, *l; + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); priv = listener->priv; if (!priv->notify) return; + + freebusy = build_free_busy_list (seq); + + g_signal_emit (G_OBJECT (listener), signals[GET_FREE_BUSY], 0, convert_status (status), freebusy); + + for (l = freebusy; l; l = l->next) + g_free (l->data); + g_list_free (freebusy); +} - g_assert (priv->obj_updated_fn != NULL); - (* priv->obj_updated_fn) (listener, uid, priv->fn_data); +static void +impl_notifyQuery (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CallStatus status, + const GNOME_Evolution_Calendar_Query query, + CORBA_Environment *ev) +{ + CalListener *listener; + CalListenerPrivate *priv; + + listener = CAL_LISTENER (bonobo_object_from_servant (servant)); + priv = listener->priv; + + if (!priv->notify) + return; + + g_signal_emit (G_OBJECT (listener), signals[QUERY], 0, convert_status (status), query); } -/* ::notifyObjRemoved method */ +/* ::notifyCalSetMode method */ static void -impl_notifyObjRemoved (PortableServer_Servant servant, - const CORBA_char *uid, +impl_notifyCalSetMode (PortableServer_Servant servant, + GNOME_Evolution_Calendar_Listener_SetModeStatus status, + GNOME_Evolution_Calendar_CalMode mode, CORBA_Environment *ev) { CalListener *listener; @@ -231,10 +610,13 @@ impl_notifyObjRemoved (PortableServer_Servant servant, if (!priv->notify) return; - g_assert (priv->obj_removed_fn != NULL); - (* priv->obj_removed_fn) (listener, uid, priv->fn_data); + g_message ("notify_set_mode"); + + g_assert (priv->cal_set_mode_fn != NULL); + (* priv->cal_set_mode_fn) (listener, status, mode, priv->fn_data); } + /* ::notifyErrorOccurred method */ static void impl_notifyErrorOccurred (PortableServer_Servant servant, @@ -250,6 +632,8 @@ impl_notifyErrorOccurred (PortableServer_Servant servant, if (!priv->notify) return; + g_message ("notify_error"); + g_assert (priv->error_occurred_fn != NULL); (* priv->error_occurred_fn) (listener, message, priv->fn_data); } @@ -269,21 +653,283 @@ impl_notifyCategoriesChanged (PortableServer_Servant servant, if (!priv->notify) return; + g_message ("notify_categories"); + g_assert (priv->categories_changed_fn != NULL); (* priv->categories_changed_fn) (listener, categories, priv->fn_data); } +/* Object initialization function for the calendar listener */ +static void +cal_listener_init (CalListener *listener, CalListenerClass *klass) +{ + CalListenerPrivate *priv; + + priv = g_new0 (CalListenerPrivate, 1); + listener->priv = priv; + + priv->error_occurred_fn = NULL; + priv->categories_changed_fn = NULL; + + priv->notify = TRUE; +} + +/* Finalize handler for the calendar listener */ +static void +cal_listener_finalize (GObject *object) +{ + CalListener *listener; + CalListenerPrivate *priv; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_CAL_LISTENER (object)); + + listener = CAL_LISTENER (object); + priv = listener->priv; + + priv->error_occurred_fn = NULL; + priv->categories_changed_fn = NULL; + priv->fn_data = NULL; + + priv->notify = FALSE; + + g_free (priv); + listener->priv = NULL; + + if (G_OBJECT_CLASS (parent_class)->finalize) + (* G_OBJECT_CLASS (parent_class)->finalize) (object); +} + +/* Class initialization function for the calendar listener */ +static void +cal_listener_class_init (CalListenerClass *klass) +{ + GObjectClass *object_class; + + object_class = (GObjectClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + klass->epv.notifyReadOnly = impl_notifyReadOnly; + klass->epv.notifyCalAddress = impl_notifyCalAddress; + klass->epv.notifyAlarmEmailAddress = impl_notifyAlarmEmailAddress; + klass->epv.notifyLDAPAttribute = impl_notifyLDAPAttribute; + klass->epv.notifyStaticCapabilities = impl_notifyStaticCapabilities; + klass->epv.notifyCalOpened = impl_notifyCalOpened; + klass->epv.notifyCalRemoved = impl_notifyCalRemoved; + klass->epv.notifyObjectCreated = impl_notifyObjectCreated; + klass->epv.notifyObjectModified = impl_notifyObjectModified; + klass->epv.notifyObjectRemoved = impl_notifyObjectRemoved; + klass->epv.notifyAlarmDiscarded = impl_notifyAlarmDiscarded; + klass->epv.notifyObjectsReceived = impl_notifyObjectsReceived; + klass->epv.notifyObjectsSent = impl_notifyObjectsSent; + klass->epv.notifyDefaultObjectRequested = impl_notifyDefaultObjectRequested; + klass->epv.notifyObjectRequested = impl_notifyObjectRequested; + klass->epv.notifyObjectListRequested = impl_notifyObjectListRequested; + klass->epv.notifyTimezoneRequested = impl_notifyTimezoneRequested; + klass->epv.notifyTimezoneAdded = impl_notifyTimezoneAdded; + klass->epv.notifyDefaultTimezoneSet = impl_notifyDefaultTimezoneSet; + klass->epv.notifyChanges = impl_notifyChanges; + klass->epv.notifyFreeBusy = impl_notifyFreeBusy; + klass->epv.notifyQuery = impl_notifyQuery; + klass->epv.notifyCalSetMode = impl_notifyCalSetMode; + klass->epv.notifyErrorOccurred = impl_notifyErrorOccurred; + klass->epv.notifyCategoriesChanged = impl_notifyCategoriesChanged; + + object_class->finalize = cal_listener_finalize; + + signals[READ_ONLY] = + g_signal_new ("read_only", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, read_only), + NULL, NULL, + cal_marshal_VOID__INT_BOOLEAN, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_BOOLEAN); + signals[CAL_ADDRESS] = + g_signal_new ("cal_address", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, cal_address), + NULL, NULL, + cal_marshal_VOID__INT_STRING, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + signals[ALARM_ADDRESS] = + g_signal_new ("alarm_address", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, alarm_address), + NULL, NULL, + cal_marshal_VOID__INT_STRING, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + signals[LDAP_ATTRIBUTE] = + g_signal_new ("ldap_attribute", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, ldap_attribute), + NULL, NULL, + cal_marshal_VOID__INT_STRING, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + signals[STATIC_CAPABILITIES] = + g_signal_new ("static_capabilities", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, static_capabilities), + NULL, NULL, + cal_marshal_VOID__INT_STRING, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + signals[OPEN] = + g_signal_new ("open", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, open), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + signals[REMOVE] = + g_signal_new ("remove", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, remove), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + signals[CREATE_OBJECT] = + g_signal_new ("create_object", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, create_object), + NULL, NULL, + cal_marshal_VOID__INT_STRING, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + signals[MODIFY_OBJECT] = + g_signal_new ("modify_object", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, modify_object), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + signals[REMOVE_OBJECT] = + g_signal_new ("remove_object", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, remove_object), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + signals[DISCARD_ALARM] = + g_signal_new ("discard_alarm", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, discard_alarm), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + signals[RECEIVE_OBJECTS] = + g_signal_new ("receive_objects", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, receive_objects), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + signals[SEND_OBJECTS] = + g_signal_new ("send_objects", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, send_objects), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + signals[DEFAULT_OBJECT] = + g_signal_new ("default_object", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, default_object), + NULL, NULL, + cal_marshal_VOID__INT_STRING, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + signals[OBJECT] = + g_signal_new ("object", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, object), + NULL, NULL, + cal_marshal_VOID__INT_STRING, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + signals[OBJECT_LIST] = + g_signal_new ("object_list", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, object_list), + NULL, NULL, + cal_marshal_VOID__INT_POINTER, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_POINTER); + signals[GET_TIMEZONE] = + g_signal_new ("get_timezone", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, get_timezone), + NULL, NULL, + cal_marshal_VOID__INT_STRING, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + signals[ADD_TIMEZONE] = + g_signal_new ("add_timezone", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, add_timezone), + NULL, NULL, + cal_marshal_VOID__INT_STRING, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + signals[SET_DEFAULT_TIMEZONE] = + g_signal_new ("set_default_timezone", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, set_default_timezone), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + signals[GET_CHANGES] = + g_signal_new ("get_changes", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, get_changes), + NULL, NULL, + cal_marshal_VOID__INT_POINTER, + G_TYPE_NONE, 1, G_TYPE_INT, G_TYPE_POINTER); + signals[GET_FREE_BUSY] = + g_signal_new ("get_free_busy", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, get_free_busy), + NULL, NULL, + cal_marshal_VOID__INT_POINTER, + G_TYPE_NONE, 1, G_TYPE_INT, G_TYPE_POINTER); + signals[QUERY] = + g_signal_new ("query", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CalListenerClass, query), + NULL, NULL, + cal_marshal_VOID__INT_POINTER, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_POINTER); +} + +BONOBO_TYPE_FUNC_FULL (CalListener, + GNOME_Evolution_Calendar_Listener, + BONOBO_TYPE_OBJECT, + cal_listener); + /** * cal_listener_construct: * @listener: A calendar listener. * @cal_opened_fn: Function that will be called to notify that a calendar was * opened. - * @obj_updated_fn: Function that will be called to notify that an object in the - * calendar was updated. - * @obj_removed_fn: Function that will be called to notify that an object in the - * calendar was removed. + * @cal_removed_fn: Function that will be called to notify that a calendar was + * removed * @error_occurred_fn: Function that will be called to notify errors. * @categories_changed_fn: Function that will be called to notify that the list * of categories that are present in the calendar's objects has changed. @@ -297,10 +943,7 @@ impl_notifyCategoriesChanged (PortableServer_Servant servant, **/ CalListener * cal_listener_construct (CalListener *listener, - CalListenerCalOpenedFn cal_opened_fn, CalListenerCalSetModeFn cal_set_mode_fn, - CalListenerObjUpdatedFn obj_updated_fn, - CalListenerObjRemovedFn obj_removed_fn, CalListenerErrorOccurredFn error_occurred_fn, CalListenerCategoriesChangedFn categories_changed_fn, gpointer fn_data) @@ -309,19 +952,13 @@ cal_listener_construct (CalListener *listener, g_return_val_if_fail (listener != NULL, NULL); g_return_val_if_fail (IS_CAL_LISTENER (listener), NULL); - g_return_val_if_fail (cal_opened_fn != NULL, NULL); g_return_val_if_fail (cal_set_mode_fn != NULL, NULL); - g_return_val_if_fail (obj_updated_fn != NULL, NULL); - g_return_val_if_fail (obj_removed_fn != NULL, NULL); g_return_val_if_fail (error_occurred_fn != NULL, NULL); g_return_val_if_fail (categories_changed_fn != NULL, NULL); priv = listener->priv; - priv->cal_opened_fn = cal_opened_fn; priv->cal_set_mode_fn = cal_set_mode_fn; - priv->obj_updated_fn = obj_updated_fn; - priv->obj_removed_fn = obj_removed_fn; priv->error_occurred_fn = error_occurred_fn; priv->categories_changed_fn = categories_changed_fn; priv->fn_data = fn_data; @@ -333,10 +970,6 @@ cal_listener_construct (CalListener *listener, * cal_listener_new: * @cal_opened_fn: Function that will be called to notify that a calendar was * opened. - * @obj_updated_fn: Function that will be called to notify that an object in the - * calendar was updated. - * @obj_removed_fn: Function that will be called to notify that an object in the - * calendar was removed. * @error_occurred_fn: Function that will be called to notify errors. * @categories_changed_fn: Function that will be called to notify that the list * of categories that are present in the calendar's objects has changed. @@ -348,28 +981,22 @@ cal_listener_construct (CalListener *listener, * Return value: A newly-created #CalListener object. **/ CalListener * -cal_listener_new (CalListenerCalOpenedFn cal_opened_fn, - CalListenerCalSetModeFn cal_set_mode_fn, - CalListenerObjUpdatedFn obj_updated_fn, - CalListenerObjRemovedFn obj_removed_fn, +cal_listener_new (CalListenerCalSetModeFn cal_set_mode_fn, CalListenerErrorOccurredFn error_occurred_fn, CalListenerCategoriesChangedFn categories_changed_fn, gpointer fn_data) { CalListener *listener; - g_return_val_if_fail (cal_opened_fn != NULL, NULL); - g_return_val_if_fail (obj_updated_fn != NULL, NULL); - g_return_val_if_fail (obj_removed_fn != NULL, NULL); g_return_val_if_fail (error_occurred_fn != NULL, NULL); g_return_val_if_fail (categories_changed_fn != NULL, NULL); - listener = g_object_new (CAL_LISTENER_TYPE, NULL); + listener = g_object_new (CAL_LISTENER_TYPE, + "poa", bonobo_poa_get_threaded (ORBIT_THREAD_HINT_PER_REQUEST, NULL), + NULL); + return cal_listener_construct (listener, - cal_opened_fn, cal_set_mode_fn, - obj_updated_fn, - obj_removed_fn, error_occurred_fn, categories_changed_fn, fn_data); diff --git a/calendar/cal-client/cal-listener.h b/calendar/cal-client/cal-listener.h index d0f9a718a4..1230104999 100644 --- a/calendar/cal-client/cal-listener.h +++ b/calendar/cal-client/cal-listener.h @@ -23,6 +23,7 @@ #include <bonobo/bonobo-object.h> #include "evolution-calendar.h" +#include "cal-client-types.h" G_BEGIN_DECLS @@ -48,26 +49,46 @@ typedef struct { BonoboObjectClass parent_class; POA_GNOME_Evolution_Calendar_Listener__epv epv; + + /* Signals */ + void (*read_only) (CalListener *listener, ECalendarStatus status, gboolean read_only); + void (*cal_address) (CalListener *listener, ECalendarStatus status, const char *address); + void (*alarm_address) (CalListener *listener, ECalendarStatus status, const char *address); + void (*ldap_attribute) (CalListener *listener, ECalendarStatus status, const char *ldap_attribute); + void (*static_capabilities) (CalListener *listener, ECalendarStatus status, const char *capabilities); + + void (*open) (CalListener *listener, ECalendarStatus status); + void (*remove) (CalListener *listener, ECalendarStatus status); + + void (*create_object) (CalListener *listener, ECalendarStatus status, const char *id); + void (*modify_object) (CalListener *listener, ECalendarStatus status); + void (*remove_object) (CalListener *listener, ECalendarStatus status); + + void (*discard_alarm) (CalListener *listener, ECalendarStatus status); + + void (*receive_objects) (CalListener *listener, ECalendarStatus status); + void (*send_objects) (CalListener *listener, ECalendarStatus status); + + void (*default_object) (CalListener *listener, ECalendarStatus status, const char *object); + void (*object) (CalListener *listener, ECalendarStatus status, const char *object); + void (*object_list) (CalListener *listener, ECalendarStatus status, GList **objects); + + void (*get_timezone) (CalListener *listener, ECalendarStatus status, const char *object); + void (*add_timezone) (CalListener *listener, ECalendarStatus status, const char *tzid); + void (*set_default_timezone) (CalListener *listener, ECalendarStatus status, const char *tzid); + + void (*get_changes) (CalListener *listener, ECalendarStatus status, GList *changes); + void (*get_free_busy) (CalListener *listener, ECalendarStatus status, GList *freebusy); + + void (*query) (CalListener *listener, ECalendarStatus status, GNOME_Evolution_Calendar_Query query); } CalListenerClass; /* Notification functions */ -typedef void (* CalListenerCalOpenedFn) (CalListener *listener, - GNOME_Evolution_Calendar_Listener_OpenStatus status, - GNOME_Evolution_Calendar_Cal cal, - gpointer data); - typedef void (* CalListenerCalSetModeFn) (CalListener *listener, GNOME_Evolution_Calendar_Listener_SetModeStatus status, GNOME_Evolution_Calendar_CalMode mode, gpointer data); -typedef void (* CalListenerObjUpdatedFn) (CalListener *listener, - const CORBA_char *uid, - gpointer data); -typedef void (* CalListenerObjRemovedFn) (CalListener *listener, - const CORBA_char *uid, - gpointer data); - typedef void (* CalListenerErrorOccurredFn) (CalListener *listener, const char *message, gpointer data); @@ -80,18 +101,12 @@ typedef void (* CalListenerCategoriesChangedFn) (CalListener *listener, GType cal_listener_get_type (void); CalListener *cal_listener_construct (CalListener *listener, - CalListenerCalOpenedFn cal_opened_fn, CalListenerCalSetModeFn cal_set_mode_fn, - CalListenerObjUpdatedFn obj_updated_fn, - CalListenerObjRemovedFn obj_removed_fn, CalListenerErrorOccurredFn error_occurred_fn, CalListenerCategoriesChangedFn categories_changed_fn, gpointer fn_data); -CalListener *cal_listener_new (CalListenerCalOpenedFn cal_opened_fn, - CalListenerCalSetModeFn cal_set_mode_fn, - CalListenerObjUpdatedFn obj_updated_fn, - CalListenerObjRemovedFn obj_removed_fn, +CalListener *cal_listener_new (CalListenerCalSetModeFn cal_set_mode_fn, CalListenerErrorOccurredFn error_occurred_fn, CalListenerCategoriesChangedFn categories_changed_fn, gpointer fn_data); diff --git a/calendar/cal-client/cal-marshal.list b/calendar/cal-client/cal-marshal.list new file mode 100644 index 0000000000..e0ca019669 --- /dev/null +++ b/calendar/cal-client/cal-marshal.list @@ -0,0 +1,6 @@ +NONE:INT +NONE:POINTER +NONE:INT,STRING +NONE:INT,BOOL +NONE:INT,POINTER +NONE:STRING,INT diff --git a/calendar/cal-client/cal-query.c b/calendar/cal-client/cal-query.c index 914af5db28..e77f5ad3e9 100644 --- a/calendar/cal-client/cal-query.c +++ b/calendar/cal-client/cal-query.c @@ -24,7 +24,8 @@ #include <string.h> #include <bonobo/bonobo-exception.h> -#include "cal-util/cal-util-marshal.h" +#include "cal-marshal.h" +#include "cal-client.h" #include "cal-query.h" #include "query-listener.h" @@ -32,143 +33,88 @@ /* Private part of the CalQuery structure */ struct _CalQueryPrivate { - /* Our query listener implementation */ - QueryListener *ql; - /* Handle to the query in the server */ - GNOME_Evolution_Calendar_Query corba_query; + GNOME_Evolution_Calendar_Query query; + + /* Our query listener implementation */ + QueryListener *listener; /* The CalClient associated with this query */ CalClient *client; }; - - -static void cal_query_class_init (CalQueryClass *klass); -static void cal_query_init (CalQuery *query, CalQueryClass *klass); -static void cal_query_finalize (GObject *object); +/* Property IDs */ +enum props { + PROP_0, + PROP_QUERY, + PROP_LISTENER, + PROP_CLIENT +}; /* Signal IDs */ enum { - OBJ_UPDATED, - OBJ_REMOVED, + OBJECTS_ADDED, + OBJECTS_MODIFIED, + OBJECTS_REMOVED, + QUERY_PROGRESS, QUERY_DONE, - EVAL_ERROR, LAST_SIGNAL }; -static guint query_signals[LAST_SIGNAL]; +static guint signals[LAST_SIGNAL]; static GObjectClass *parent_class; -/** - * cal_query_get_type: - * - * Registers the #CalQuery class if necessary, and returns the type ID assigned - * to it. - * - * Return value: The type ID of the #CalQuery class. - **/ -GType -cal_query_get_type (void) +static void +objects_added_cb (QueryListener *listener, GList *objects, gpointer data) { - static GType cal_query_type = 0; + CalQuery *query; - if (!cal_query_type) { - static GTypeInfo info = { - sizeof (CalQueryClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) cal_query_class_init, - NULL, NULL, - sizeof (CalQuery), - 0, - (GInstanceInitFunc) cal_query_init - }; - cal_query_type = g_type_register_static (G_TYPE_OBJECT, "CalQuery", &info, 0); - } + query = CAL_QUERY (data); - return cal_query_type; + g_signal_emit (G_OBJECT (query), signals[OBJECTS_ADDED], 0, objects); } -GType -cal_query_done_status_enum_get_type (void) +static void +objects_modified_cb (QueryListener *listener, GList *objects, gpointer data) { - static GType cal_query_done_status_enum_type = 0; + CalQuery *query; - if (!cal_query_done_status_enum_type) { - static GEnumValue values [] = { - { CAL_QUERY_DONE_SUCCESS, "CalQueryDoneSuccess", "success" }, - { CAL_QUERY_DONE_PARSE_ERROR, "CalQueryDoneParseError", "parse-error" }, - { -1, NULL, NULL } - }; + query = CAL_QUERY (data); - cal_query_done_status_enum_type = - g_enum_register_static ("CalQueryDoneStatusEnum", values); - } + g_signal_emit (G_OBJECT (query), signals[OBJECTS_MODIFIED], 0, objects); +} + +static void +objects_removed_cb (QueryListener *listener, GList *uids, gpointer data) +{ + CalQuery *query; + + query = CAL_QUERY (data); - return cal_query_done_status_enum_type; + g_signal_emit (G_OBJECT (query), signals[OBJECTS_REMOVED], 0, uids); } -/* Class initialization function for the calendar query */ static void -cal_query_class_init (CalQueryClass *klass) +query_progress_cb (QueryListener *listener, const char *message, int percent, gpointer data) { - GObjectClass *object_class; + CalQuery *query; - object_class = (GObjectClass *) klass; + query = CAL_QUERY (data); - parent_class = g_type_class_peek_parent (klass); + g_signal_emit (G_OBJECT (query), signals[QUERY_PROGRESS], 0, message, percent); +} - query_signals[OBJ_UPDATED] = - g_signal_new ("obj_updated", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalQueryClass, obj_updated), - NULL, NULL, - cal_util_marshal_VOID__STRING_BOOLEAN_INT_INT, - G_TYPE_NONE, 4, - G_TYPE_STRING, - G_TYPE_BOOLEAN, - G_TYPE_INT, - G_TYPE_INT); - query_signals[OBJ_REMOVED] = - g_signal_new ("obj_removed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalQueryClass, obj_removed), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - query_signals[QUERY_DONE] = - g_signal_new ("query_done", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalQueryClass, query_done), - NULL, NULL, - cal_util_marshal_VOID__ENUM_STRING, - G_TYPE_NONE, 2, - CAL_QUERY_DONE_STATUS_ENUM_TYPE, - G_TYPE_STRING); - query_signals[EVAL_ERROR] = - g_signal_new ("eval_error", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalQueryClass, eval_error), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); +static void +query_done_cb (QueryListener *listener, ECalendarStatus status, gpointer data) +{ + CalQuery *query; - klass->obj_updated = NULL; - klass->obj_removed = NULL; - klass->query_done = NULL; - klass->eval_error = NULL; + query = CAL_QUERY (data); - object_class->finalize = cal_query_finalize; + g_signal_emit (G_OBJECT (query), signals[QUERY_DONE], 0, status); } /* Object initialization function for the calendar query */ @@ -180,191 +126,193 @@ cal_query_init (CalQuery *query, CalQueryClass *klass) priv = g_new0 (CalQueryPrivate, 1); query->priv = priv; - priv->ql = NULL; - priv->corba_query = CORBA_OBJECT_NIL; + priv->listener = NULL; + priv->query = CORBA_OBJECT_NIL; } -/* Finalize handler for the calendar query */ static void -cal_query_finalize (GObject *object) +cal_query_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { CalQuery *query; CalQueryPrivate *priv; - - g_return_if_fail (object != NULL); - g_return_if_fail (IS_CAL_QUERY (object)); - + query = CAL_QUERY (object); priv = query->priv; - - /* The server keeps a copy of the query listener, so we must unref it */ - query_listener_stop_notification (priv->ql); - bonobo_object_unref (BONOBO_OBJECT (priv->ql)); - priv->ql = NULL; - - if (priv->corba_query != CORBA_OBJECT_NIL) { - CORBA_Environment ev; - - CORBA_exception_init (&ev); - bonobo_object_release_unref (priv->corba_query, &ev); - - if (BONOBO_EX (&ev)) - g_message ("cal_query_destroy(): Could not release/unref the query"); - - CORBA_exception_free (&ev); - priv->corba_query = CORBA_OBJECT_NIL; + + switch (property_id) { + case PROP_QUERY: + priv->query = bonobo_object_dup_ref (g_value_get_pointer (value), NULL); + break; + case PROP_LISTENER: + priv->listener = bonobo_object_ref (g_value_get_pointer (value)); + + g_signal_connect (G_OBJECT (priv->listener), "objects_added", + G_CALLBACK (objects_added_cb), query); + g_signal_connect (G_OBJECT (priv->listener), "objects_modified", + G_CALLBACK (objects_modified_cb), query); + g_signal_connect (G_OBJECT (priv->listener), "objects_removed", + G_CALLBACK (objects_removed_cb), query); + g_signal_connect (G_OBJECT (priv->listener), "query_progress", + G_CALLBACK (query_progress_cb), query); + g_signal_connect (G_OBJECT (priv->listener), "query_done", + G_CALLBACK (query_done_cb), query); + break; + case PROP_CLIENT: + priv->client = CAL_CLIENT (g_value_dup_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; } - - g_free (priv); - query->priv = NULL; - - if (G_OBJECT_CLASS (parent_class)->finalize) - (* G_OBJECT_CLASS (parent_class)->finalize) (object); } - - -/* Callback used when an object is updated in the query */ static void -obj_updated_cb (QueryListener *ql, - const GNOME_Evolution_Calendar_CalObjUIDSeq *uids, - CORBA_boolean query_in_progress, - CORBA_long n_scanned, - CORBA_long total, - gpointer data) +cal_query_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { CalQuery *query; - int n; - - query = CAL_QUERY (data); + CalQueryPrivate *priv; + + query = CAL_QUERY (object); + priv = query->priv; - for (n = 0; n < uids->_length; n++) { - g_signal_emit (G_OBJECT (query), query_signals[OBJ_UPDATED], 0, - uids->_buffer[n], query_in_progress, - (int) n_scanned, (int) total); + switch (property_id) { + case PROP_QUERY: + g_value_set_pointer (value, priv->query); + break; + case PROP_LISTENER: + g_value_set_pointer (value, priv->listener); + break; + case PROP_CLIENT: + g_value_set_object (value, priv->client); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; } } -/* Callback used when an object is removed from the query */ -static void -obj_removed_cb (QueryListener *ql, - const CORBA_char *uid, - gpointer data) -{ - CalQuery *query; - - query = CAL_QUERY (data); - - g_signal_emit (G_OBJECT (query), query_signals[OBJ_REMOVED], - 0, uid); -} -/* Callback used when the query terminates */ +/* Finalize handler for the calendar query */ static void -query_done_cb (QueryListener *ql, - GNOME_Evolution_Calendar_QueryListener_QueryDoneStatus corba_status, - const CORBA_char *error_str, - gpointer data) +cal_query_finalize (GObject *object) { CalQuery *query; - CalQueryDoneStatus status; + CalQueryPrivate *priv; - query = CAL_QUERY (data); + g_return_if_fail (object != NULL); + g_return_if_fail (IS_CAL_QUERY (object)); - switch (corba_status) { - case GNOME_Evolution_Calendar_QueryListener_SUCCESS: - status = CAL_QUERY_DONE_SUCCESS; - break; + query = CAL_QUERY (object); + priv = query->priv; - case GNOME_Evolution_Calendar_QueryListener_PARSE_ERROR: - status = CAL_QUERY_DONE_PARSE_ERROR; - break; + /* The server keeps a copy of the query listener, so we must unref it */ + g_signal_handlers_disconnect_matched (priv->listener, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, query); + bonobo_object_unref (BONOBO_OBJECT (priv->listener)); - default: - g_assert_not_reached (); - return; - } + if (priv->query != CORBA_OBJECT_NIL) + bonobo_object_release_unref (priv->query, NULL); - g_signal_emit (G_OBJECT (query), query_signals[QUERY_DONE], 0, - status, error_str); + g_free (priv); + + if (G_OBJECT_CLASS (parent_class)->finalize) + (* G_OBJECT_CLASS (parent_class)->finalize) (object); } -/* Callback used when an error occurs when evaluating the query */ +/* Class initialization function for the calendar query */ static void -eval_error_cb (QueryListener *ql, - const CORBA_char *error_str, - gpointer data) +cal_query_class_init (CalQueryClass *klass) { - CalQuery *query; + GObjectClass *object_class; + GParamSpec *param; + + object_class = (GObjectClass *) klass; - query = CAL_QUERY (data); + parent_class = g_type_class_peek_parent (klass); + + object_class->set_property = cal_query_set_property; + object_class->get_property = cal_query_get_property; + object_class->finalize = cal_query_finalize; - g_signal_emit (G_OBJECT (query), query_signals[EVAL_ERROR], 0, - error_str); + param = g_param_spec_pointer ("query", NULL, NULL, + G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (object_class, PROP_QUERY, param); + param = g_param_spec_pointer ("listener", NULL, NULL, + G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (object_class, PROP_LISTENER, param); + param = g_param_spec_object ("client", NULL, NULL, CAL_CLIENT_TYPE, + G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (object_class, PROP_CLIENT, param); + + signals[OBJECTS_ADDED] = + g_signal_new ("objects_added", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalQueryClass, objects_added), + NULL, NULL, + cal_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + signals[OBJECTS_MODIFIED] = + g_signal_new ("objects_modified", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalQueryClass, objects_modified), + NULL, NULL, + cal_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + signals[OBJECTS_REMOVED] = + g_signal_new ("objects_removed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalQueryClass, objects_removed), + NULL, NULL, + cal_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + signals[QUERY_PROGRESS] = + g_signal_new ("query_progress", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalQueryClass, query_progress), + NULL, NULL, + cal_marshal_VOID__POINTER, + G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT); + signals[QUERY_DONE] = + g_signal_new ("query_done", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (CalQueryClass, query_done), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); } /** - * cal_query_construct: - * @query: A calendar query. - * @cal: Handle to an open calendar. - * @sexp: S-expression that defines the query. + * cal_query_get_type: * - * Constructs a query object by issuing the query creation request to the - * calendar server. + * Registers the #CalQuery class if necessary, and returns the type ID assigned + * to it. * - * Return value: The same value as @query on success, or NULL if the request - * failed. + * Return value: The type ID of the #CalQuery class. **/ -CalQuery * -cal_query_construct (CalQuery *query, - GNOME_Evolution_Calendar_Cal cal, - const char *sexp) +GType +cal_query_get_type (void) { - CalQueryPrivate *priv; - GNOME_Evolution_Calendar_QueryListener corba_ql; - CORBA_Environment ev; - - g_return_val_if_fail (query != NULL, NULL); - g_return_val_if_fail (IS_CAL_QUERY (query), NULL); - g_return_val_if_fail (sexp != NULL, NULL); - - priv = query->priv; - - priv->ql = query_listener_new (obj_updated_cb, - obj_removed_cb, - query_done_cb, - eval_error_cb, - query); - if (!priv->ql) { - g_message ("cal_query_construct(): Could not create the query listener"); - return NULL; - } + static GType cal_query_type = 0; - corba_ql = BONOBO_OBJREF (priv->ql); - - CORBA_exception_init (&ev); - priv->corba_query = GNOME_Evolution_Calendar_Cal_getQuery (cal, sexp, corba_ql, &ev); - - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_CouldNotCreate)) { - g_message ("cal_query_construct(): The server could not create the query"); - goto error; - } else if (BONOBO_EX (&ev)) { - g_message ("cal_query_construct(): Could not issue the getQuery() request"); - goto error; + if (!cal_query_type) { + static GTypeInfo info = { + sizeof (CalQueryClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) cal_query_class_init, + NULL, NULL, + sizeof (CalQuery), + 0, + (GInstanceInitFunc) cal_query_init + }; + cal_query_type = g_type_register_static (G_TYPE_OBJECT, "CalQuery", &info, 0); } - CORBA_exception_free (&ev); - - return query; - - error: - - CORBA_exception_free (&ev); - - bonobo_object_unref (BONOBO_OBJECT (priv->ql)); - priv->ql = NULL; - priv->corba_query = CORBA_OBJECT_NIL; - return NULL; + return cal_query_type; } /** @@ -379,20 +327,12 @@ cal_query_construct (CalQuery *query, * Return value: A newly-created query object, or NULL if the request failed. **/ CalQuery * -cal_query_new (CalClient *client, - GNOME_Evolution_Calendar_Cal cal, - const char *sexp) +cal_query_new (GNOME_Evolution_Calendar_Query corba_query, QueryListener *listener, CalClient *client) { CalQuery *query; - query = g_object_new (CAL_QUERY_TYPE, NULL); - - if (!cal_query_construct (query, cal, sexp)) { - g_object_unref (G_OBJECT (query)); - return NULL; - } - - query->priv->client = client; + query = g_object_new (CAL_QUERY_TYPE, "query", corba_query, "listener", + listener, "client", client, NULL); return query; } @@ -412,3 +352,23 @@ cal_query_get_client (CalQuery *query) return query->priv->client; } + +void +cal_query_start (CalQuery *query) +{ + CalQueryPrivate *priv; + CORBA_Environment ev; + + g_return_if_fail (query != NULL); + g_return_if_fail (IS_CAL_QUERY (query)); + + priv = query->priv; + + CORBA_exception_init (&ev); + + GNOME_Evolution_Calendar_Query_start (priv->query, &ev); + if (BONOBO_EX (&ev)) + g_warning (G_STRLOC ": Unable to start query"); + + CORBA_exception_free (&ev); +} diff --git a/calendar/cal-client/cal-query.h b/calendar/cal-client/cal-query.h index 77429035fa..05390dd12a 100644 --- a/calendar/cal-client/cal-query.h +++ b/calendar/cal-client/cal-query.h @@ -22,7 +22,8 @@ #define CAL_QUERY_H #include <glib-object.h> - +#include "cal-client-types.h" +#include "query-listener.h" #include "evolution-calendar.h" G_BEGIN_DECLS @@ -37,14 +38,6 @@ typedef struct _CalClient CalClient; #define IS_CAL_QUERY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CAL_QUERY_TYPE)) #define IS_CAL_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CAL_QUERY_TYPE)) -#define CAL_QUERY_DONE_STATUS_ENUM_TYPE (cal_query_done_status_enum_get_type ()) - -/* Status values when a query terminates */ -typedef enum { - CAL_QUERY_DONE_SUCCESS, - CAL_QUERY_DONE_PARSE_ERROR -} CalQueryDoneStatus; - typedef struct _CalQueryPrivate CalQueryPrivate; typedef struct { @@ -58,30 +51,18 @@ typedef struct { GObjectClass parent_class; /* Notification signals */ - - void (* obj_updated) (CalQuery *query, const char *uid, - gboolean query_in_progress, int n_scanned, int total); - void (* obj_removed) (CalQuery *query, const char *uid); - - void (* query_done) (CalQuery *query, CalQueryDoneStatus status, const char *error_str); - - void (* eval_error) (CalQuery *query, const char *error_str); + void (* objects_added) (CalQuery *query, GList *objects); + void (* objects_modified) (CalQuery *query, GList *objects); + void (* objects_removed) (CalQuery *query, GList *uids); + void (* query_progress) (CalQuery *query, char *message, int percent); + void (* query_done) (CalQuery *query, ECalendarStatus status); } CalQueryClass; GType cal_query_get_type (void); -GType cal_query_done_status_enum_get_type (void); - -CalQuery *cal_query_construct (CalQuery *query, - GNOME_Evolution_Calendar_Cal cal, - const char *sexp); - -CalQuery *cal_query_new (CalClient *client, - GNOME_Evolution_Calendar_Cal cal, - const char *sexp); +CalQuery *cal_query_new (GNOME_Evolution_Calendar_Query corba_query, QueryListener *listener, CalClient *client); CalClient *cal_query_get_client (CalQuery *query); - - +void cal_query_start (CalQuery *query); G_END_DECLS diff --git a/calendar/cal-client/client-test.c b/calendar/cal-client/client-test.c index cb6eed17b2..48763be50a 100644 --- a/calendar/cal-client/client-test.c +++ b/calendar/cal-client/client-test.c @@ -45,24 +45,37 @@ cl_printf (CalClient *client, const char *format, ...) va_end (args); } -/* Dumps some interesting data from a component */ static void -dump_component (CalComponent *comp) +objects_added_cb (GObject *object, GList *objects, gpointer data) { - const char *uid; - CalComponentText summary; + GList *l; + + for (l = objects; l; l = l->next) + cl_printf (data, "Object added %s\n", icalcomponent_get_uid (l->data)); +} - cal_component_get_uid (comp, &uid); +static void +objects_modified_cb (GObject *object, GList *objects, gpointer data) +{ + GList *l; + + for (l = objects; l; l = l->next) + cl_printf (data, "Object modified %s\n", icalcomponent_get_uid (l->data)); +} - printf ("UID %s\n", uid); +static void +objects_removed_cb (GObject *object, GList *objects, gpointer data) +{ + GList *l; + + for (l = objects; l; l = l->next) + cl_printf (data, "Object removed %s\n", icalcomponent_get_uid (l->data)); +} - cal_component_get_summary (comp, &summary); - if (summary.value) - printf ("\tSummary: `%s', altrep `%s'\n", - summary.value, - summary.altrep ? summary.altrep : "NONE"); - else - printf ("\tNo summary\n"); +static void +query_done_cb (GObject *object, ECalendarStatus status, gpointer data) +{ + cl_printf (data, "Query done\n"); } /* Lists the UIDs of objects in a calendar, called as an idle handler */ @@ -70,47 +83,38 @@ static gboolean list_uids (gpointer data) { CalClient *client; - GList *uids; + GList *objects = NULL; GList *l; - + client = CAL_CLIENT (data); - uids = cal_client_get_uids (client, CALOBJ_TYPE_ANY); - - cl_printf (client, "UIDs: "); + g_message ("Blah"); + + if (!cal_client_get_object_list (client, "(contains? \"any\" \"Test4\")", &objects, NULL)) + return FALSE; + + cl_printf (client, "UIDS: "); - if (!uids) + if (!objects) printf ("none\n"); else { - for (l = uids; l; l = l->next) { - char *uid; + for (l = objects; l; l = l->next) { + const char *uid; - uid = l->data; + uid = icalcomponent_get_uid (l->data); printf ("`%s' ", uid); } printf ("\n"); - for (l = uids; l; l = l->next) { - char *uid; - CalComponent *comp; - CalClientGetStatus status; - - uid = l->data; - status = cal_client_get_object (client, uid, &comp); - - if (status == CAL_CLIENT_GET_SUCCESS) { - printf ("------------------------------\n"); - dump_component (comp); - printf ("------------------------------\n"); - g_object_unref (comp); - } else { - printf ("FAILED: %d\n", status); - } + for (l = objects; l; l = l->next) { + printf ("------------------------------\n"); + printf ("%s", icalcomponent_as_ical_string (l->data)); + printf ("------------------------------\n"); } } - cal_obj_uid_list_free (uids); + cal_client_free_object_list (objects); g_object_unref (client); @@ -121,6 +125,8 @@ list_uids (gpointer data) static void cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer data) { + CalQuery *query; + cl_printf (client, "Load/create %s\n", ((status == CAL_CLIENT_OPEN_SUCCESS) ? "success" : (status == CAL_CLIENT_OPEN_ERROR) ? "error" : @@ -129,40 +135,29 @@ cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer data) "unknown status value")); if (status == CAL_CLIENT_OPEN_SUCCESS) { - GList *comp_list; - - /* get free/busy information */ - comp_list = cal_client_get_free_busy (client, NULL, 0, time (NULL)); - if (comp_list) { - GList *l; - - for (l = comp_list; l; l = l->next) { - char *comp_str; - - comp_str = cal_component_get_as_string (CAL_COMPONENT (l->data)); - g_object_unref (l->data); - cl_printf (client, "Free/Busy -> %s\n", comp_str); - g_free (comp_str); - } - g_list_free (comp_list); - } - + if (!cal_client_get_query (client, "(contains? \"any\" \"Test4\")", &query, NULL)) + g_warning (G_STRLOC ": Unable to obtain query"); + + g_signal_connect (G_OBJECT (query), "objects_added", + G_CALLBACK (objects_added_cb), client); + g_signal_connect (G_OBJECT (query), "objects_modified", + G_CALLBACK (objects_modified_cb), client); + g_signal_connect (G_OBJECT (query), "objects_removed", + G_CALLBACK (objects_removed_cb), client); + g_signal_connect (G_OBJECT (query), "query_done", + G_CALLBACK (query_done_cb), client); + + cal_query_start (query); + g_idle_add (list_uids, client); } else g_object_unref (client); } -/* Callback used when an object is updated */ -static void -obj_updated_cb (CalClient *client, const char *uid, gpointer data) -{ - cl_printf (client, "Object updated: %s\n", uid); -} - /* Callback used when a client is destroyed */ static void -client_destroy_cb (GObject *object, gpointer data) +client_destroy_cb (gpointer data, GObject *object) { if (CAL_CLIENT (object) == client1) client1 = NULL; @@ -177,33 +172,24 @@ client_destroy_cb (GObject *object, gpointer data) /* Creates a calendar client and tries to load the specified URI into it */ static void -create_client (CalClient **client, const char *uri, gboolean only_if_exists) +create_client (CalClient **client, const char *uri, CalObjType type, gboolean only_if_exists) { - gboolean result; - - *client = cal_client_new (); + *client = cal_client_new (uri, type); if (!*client) { - g_message ("create_client(): could not create the client"); + g_message (G_STRLOC ": could not create the client"); exit (1); } - g_signal_connect (*client, "destroy", - G_CALLBACK (client_destroy_cb), - NULL); + g_object_weak_ref (G_OBJECT (*client), client_destroy_cb, NULL); g_signal_connect (*client, "cal_opened", G_CALLBACK (cal_opened_cb), NULL); - g_signal_connect (*client, "obj_updated", - G_CALLBACK (obj_updated_cb), - NULL); printf ("Calendar loading `%s'...\n", uri); - result = cal_client_open_calendar (*client, uri, only_if_exists); - - if (!result) { - g_message ("create_client(): failure when issuing calendar open request `%s'", + if (!cal_client_open (*client, only_if_exists, NULL)) { + g_message (G_STRLOC ": failure when issuing calendar open request `%s'", uri); exit (1); } @@ -212,8 +198,6 @@ create_client (CalClient **client, const char *uri, gboolean only_if_exists) int main (int argc, char **argv) { - char *dir; - bindtextdomain (GETTEXT_PACKAGE, EVOLUTION_LOCALEDIR); textdomain (GETTEXT_PACKAGE); @@ -225,10 +209,9 @@ main (int argc, char **argv) exit (1); } - dir = g_strdup_printf ("%s/evolution/local/Calendar/calendar.ics", g_get_home_dir ()); - create_client (&client1, dir, FALSE); - g_free (dir); - create_client (&client2, "/cvs/evolution/calendar/cal-client/test.ics", TRUE); + create_client (&client1, "file:///home/gnome24-evolution-new-calendar/evolution/local/Calendar", + CALOBJ_TYPE_EVENT, FALSE); +// create_client (&client2, "file:///tmp/tasks", TRUE); bonobo_main (); return 0; diff --git a/calendar/cal-client/query-listener.c b/calendar/cal-client/query-listener.c index 6bd7bfc6f7..4c8cbb4fe5 100644 --- a/calendar/cal-client/query-listener.c +++ b/calendar/cal-client/query-listener.c @@ -22,6 +22,7 @@ #include <config.h> #endif +#include "cal-marshal.h" #include "query-listener.h" @@ -29,166 +30,164 @@ /* Private part of the QueryListener structure */ struct _QueryListenerPrivate { - /* Callbacks for notification and their closure data */ - QueryListenerObjUpdatedFn obj_updated_fn; - QueryListenerObjRemovedFn obj_removed_fn; - QueryListenerQueryDoneFn query_done_fn; - QueryListenerEvalErrorFn eval_error_fn; - gpointer fn_data; - - /* Whether notification is desired */ - gboolean notify : 1; + int dummy; }; - - -static void query_listener_class_init (QueryListenerClass *class); -static void query_listener_init (QueryListener *ql, QueryListenerClass *class); -static void query_listener_finalize (GObject *object); - -static void impl_notifyObjUpdated (PortableServer_Servant servant, - const GNOME_Evolution_Calendar_CalObjUIDSeq *uids, - CORBA_boolean query_in_progress, - CORBA_long n_scanned, - CORBA_long total, - CORBA_Environment *ev); - -static void impl_notifyObjRemoved (PortableServer_Servant servant, - const CORBA_char *uid, - CORBA_Environment *ev); - -static void impl_notifyQueryDone (PortableServer_Servant servant, - GNOME_Evolution_Calendar_QueryListener_QueryDoneStatus corba_status, - const CORBA_char *error_str, - CORBA_Environment *ev); +/* Signal IDs */ +enum { + OBJECTS_ADDED, + OBJECTS_MODIFIED, + OBJECTS_REMOVED, + QUERY_PROGRESS, + QUERY_DONE, + LAST_SIGNAL +}; -static void impl_notifyEvalError (PortableServer_Servant servant, - const CORBA_char *error_str, - CORBA_Environment *ev); +static guint signals[LAST_SIGNAL] = { 0 }; static BonoboObjectClass *parent_class; - - -BONOBO_TYPE_FUNC_FULL (QueryListener, - GNOME_Evolution_Calendar_QueryListener, - BONOBO_TYPE_OBJECT, - query_listener); - -/* Class initialization function for the live search query listener */ -static void -query_listener_class_init (QueryListenerClass *class) +/* CORBA method implementations */ +/* FIXME This is duplicated from cal-listener.c */ +static ECalendarStatus +convert_status (const GNOME_Evolution_Calendar_CallStatus status) { - GObjectClass *object_class; + switch (status) { + case GNOME_Evolution_Calendar_Success: + return E_CALENDAR_STATUS_OK; + case GNOME_Evolution_Calendar_RepositoryOffline: + return E_CALENDAR_STATUS_REPOSITORY_OFFLINE; + case GNOME_Evolution_Calendar_PermissionDenied: + return E_CALENDAR_STATUS_PERMISSION_DENIED; + case GNOME_Evolution_Calendar_ObjectNotFound: + return E_CALENDAR_STATUS_OBJECT_NOT_FOUND; + case GNOME_Evolution_Calendar_CardIdAlreadyExists: + return E_CALENDAR_STATUS_CARD_ID_ALREADY_EXISTS; + case GNOME_Evolution_Calendar_AuthenticationFailed: + return E_CALENDAR_STATUS_AUTHENTICATION_FAILED; + case GNOME_Evolution_Calendar_AuthenticationRequired: + return E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED; + case GNOME_Evolution_Calendar_OtherError: + default: + return E_CALENDAR_STATUS_OTHER_ERROR; + } +} - object_class = (GObjectClass *) class; +/* FIXME This is duplicated from cal-listener.c */ +static GList * +build_object_list (const GNOME_Evolution_Calendar_stringlist *seq) +{ + GList *list; + int i; + + list = NULL; + for (i = 0; i < seq->_length; i++) { + icalcomponent *comp; + + comp = icalcomponent_new_from_string (seq->_buffer[i]); + if (!comp) + continue; + + list = g_list_prepend (list, comp); + } + + return list; +} - parent_class = g_type_class_peek_parent (class); +static GList * +build_uid_list (const GNOME_Evolution_Calendar_CalObjUIDSeq *seq) +{ + GList *list; + int i; - object_class->finalize = query_listener_finalize; + list = NULL; + for (i = 0; i < seq->_length; i++) + list = g_list_prepend (list, g_strdup (seq->_buffer[i])); - class->epv.notifyObjUpdated = impl_notifyObjUpdated; - class->epv.notifyObjRemoved = impl_notifyObjRemoved; - class->epv.notifyQueryDone = impl_notifyQueryDone; - class->epv.notifyEvalError = impl_notifyEvalError; + return list; } -/* Object initialization function for the live search query listener */ static void -query_listener_init (QueryListener *ql, QueryListenerClass *class) +impl_notifyObjectsAdded (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_stringlist *objects, + CORBA_Environment *ev) { + QueryListener *ql; QueryListenerPrivate *priv; + GList *object_list, *l; + + ql = QUERY_LISTENER (bonobo_object_from_servant (servant)); + priv = ql->priv; - priv = g_new0 (QueryListenerPrivate, 1); - ql->priv = priv; - - priv->obj_updated_fn = NULL; - priv->obj_removed_fn = NULL; - priv->query_done_fn = NULL; - priv->eval_error_fn = NULL; - priv->fn_data = NULL; + object_list = build_object_list (objects); + + g_signal_emit (G_OBJECT (ql), signals[OBJECTS_ADDED], 0, object_list); - priv->notify = TRUE; + for (l = object_list; l; l = l->next) + icalcomponent_free (l->data); + g_list_free (object_list); } -/* Finalize handler for the live search query listener */ static void -query_listener_finalize (GObject *object) +impl_notifyObjectsModified (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_stringlist *objects, + CORBA_Environment *ev) { QueryListener *ql; QueryListenerPrivate *priv; - - g_return_if_fail (object != NULL); - g_return_if_fail (IS_QUERY_LISTENER (object)); - - ql = QUERY_LISTENER (object); + GList *object_list, *l; + + ql = QUERY_LISTENER (bonobo_object_from_servant (servant)); priv = ql->priv; - priv->obj_updated_fn = NULL; - priv->obj_removed_fn = NULL; - priv->query_done_fn = NULL; - priv->eval_error_fn = NULL; - priv->fn_data = NULL; - - priv->notify = FALSE; + object_list = build_object_list (objects); + + g_signal_emit (G_OBJECT (ql), signals[OBJECTS_MODIFIED], 0, object_list); - g_free (priv); - ql->priv = NULL; - - if (G_OBJECT_CLASS (parent_class)->finalize) - (* G_OBJECT_CLASS (parent_class)->finalize) (object); + for (l = object_list; l; l = l->next) + icalcomponent_free (l->data); + g_list_free (object_list); } - - -/* CORBA method implementations */ - -/* ::notifyObjUpdated() method */ static void -impl_notifyObjUpdated (PortableServer_Servant servant, - const GNOME_Evolution_Calendar_CalObjUIDSeq *uids, - CORBA_boolean query_in_progress, - CORBA_long n_scanned, - CORBA_long total, - CORBA_Environment *ev) +impl_notifyObjectsRemoved (PortableServer_Servant servant, + const GNOME_Evolution_Calendar_CalObjUIDSeq *uids, + CORBA_Environment *ev) { QueryListener *ql; QueryListenerPrivate *priv; - + GList *uid_list, *l; + ql = QUERY_LISTENER (bonobo_object_from_servant (servant)); priv = ql->priv; - if (!priv->notify) - return; + uid_list = build_uid_list (uids); + + g_signal_emit (G_OBJECT (ql), signals[OBJECTS_REMOVED], 0, uid_list); - g_assert (priv->obj_updated_fn != NULL); - (* priv->obj_updated_fn) (ql, uids, query_in_progress, n_scanned, total, priv->fn_data); + for (l = uid_list; l; l = l->next) + g_free (l->data); + g_list_free (uid_list); } -/* ::notifyObjRemoved() method */ static void -impl_notifyObjRemoved (PortableServer_Servant servant, - const CORBA_char *uid, - CORBA_Environment *ev) +impl_notifyQueryProgress (PortableServer_Servant servant, + const CORBA_char *message, + const CORBA_short percent, + CORBA_Environment *ev) { QueryListener *ql; QueryListenerPrivate *priv; ql = QUERY_LISTENER (bonobo_object_from_servant (servant)); priv = ql->priv; - - if (!priv->notify) - return; - - g_assert (priv->obj_removed_fn != NULL); - (* priv->obj_removed_fn) (ql, uid, priv->fn_data); + + g_signal_emit (G_OBJECT (ql), signals[QUERY_PROGRESS], 0, message, percent); } -/* ::notifyQueryDone() method */ static void impl_notifyQueryDone (PortableServer_Servant servant, - GNOME_Evolution_Calendar_QueryListener_QueryDoneStatus corba_status, - const CORBA_char *error_str, + const GNOME_Evolution_Calendar_CallStatus status, CORBA_Environment *ev) { QueryListener *ql; @@ -196,126 +195,110 @@ impl_notifyQueryDone (PortableServer_Servant servant, ql = QUERY_LISTENER (bonobo_object_from_servant (servant)); priv = ql->priv; + + g_signal_emit (G_OBJECT (ql), signals[QUERY_DONE], 0, convert_status (status)); +} - if (!priv->notify) - return; +/* Object initialization function for the live search query listener */ +static void +query_listener_init (QueryListener *ql, QueryListenerClass *class) +{ + QueryListenerPrivate *priv; - g_assert (priv->query_done_fn != NULL); - (* priv->query_done_fn) (ql, corba_status, error_str, priv->fn_data); + priv = g_new0 (QueryListenerPrivate, 1); + ql->priv = priv; } -/* ::notifyEvalError() method */ +/* Finalize handler for the live search query listener */ static void -impl_notifyEvalError (PortableServer_Servant servant, - const CORBA_char *error_str, - CORBA_Environment *ev) +query_listener_finalize (GObject *object) { QueryListener *ql; QueryListenerPrivate *priv; - ql = QUERY_LISTENER (bonobo_object_from_servant (servant)); + g_return_if_fail (object != NULL); + g_return_if_fail (IS_QUERY_LISTENER (object)); + + ql = QUERY_LISTENER (object); priv = ql->priv; - if (!priv->notify) - return; + g_free (priv); - g_assert (priv->eval_error_fn != NULL); - (* priv->eval_error_fn) (ql, error_str, priv->fn_data); + if (G_OBJECT_CLASS (parent_class)->finalize) + (* G_OBJECT_CLASS (parent_class)->finalize) (object); } - - -/** - * query_listener_construct: - * @ql: A query listener. - * @obj_updated_fn: Callback to use when a component is updated in the query. - * @obj_removed_fn: Callback to use when a component is removed from the query. - * @query_done_fn: Callback to use when a query is done. - * @eval_error_fn: Callback to use when an evaluation error happens during a query. - * @fn_data: Closure data to pass to the callbacks. - * - * Constructs a query listener by setting the callbacks it will use for - * notification from the calendar server. - * - * Return value: The same value as @ql. - **/ -QueryListener * -query_listener_construct (QueryListener *ql, - QueryListenerObjUpdatedFn obj_updated_fn, - QueryListenerObjRemovedFn obj_removed_fn, - QueryListenerQueryDoneFn query_done_fn, - QueryListenerEvalErrorFn eval_error_fn, - gpointer fn_data) +/* Class initialization function for the live search query listener */ +static void +query_listener_class_init (QueryListenerClass *klass) { - QueryListenerPrivate *priv; + GObjectClass *object_class; - g_return_val_if_fail (ql != NULL, NULL); - g_return_val_if_fail (IS_QUERY_LISTENER (ql), NULL); - g_return_val_if_fail (obj_updated_fn != NULL, NULL); - g_return_val_if_fail (obj_removed_fn != NULL, NULL); - g_return_val_if_fail (query_done_fn != NULL, NULL); - g_return_val_if_fail (eval_error_fn != NULL, NULL); + object_class = (GObjectClass *) klass; - priv = ql->priv; + parent_class = g_type_class_peek_parent (klass); - priv->obj_updated_fn = obj_updated_fn; - priv->obj_removed_fn = obj_removed_fn; - priv->query_done_fn = query_done_fn; - priv->eval_error_fn = eval_error_fn; - priv->fn_data = fn_data; + object_class->finalize = query_listener_finalize; - return ql; + klass->epv.notifyObjectsAdded = impl_notifyObjectsAdded; + klass->epv.notifyObjectsModified = impl_notifyObjectsModified; + klass->epv.notifyObjectsRemoved = impl_notifyObjectsRemoved; + klass->epv.notifyQueryProgress = impl_notifyQueryProgress; + klass->epv.notifyQueryDone = impl_notifyQueryDone; + + signals[OBJECTS_ADDED] = + g_signal_new ("objects_added", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (QueryListenerClass, objects_added), + NULL, NULL, + cal_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + signals[OBJECTS_MODIFIED] = + g_signal_new ("objects_modified", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (QueryListenerClass, objects_modified), + NULL, NULL, + cal_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + signals[OBJECTS_REMOVED] = + g_signal_new ("objects_removed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (QueryListenerClass, objects_removed), + NULL, NULL, + cal_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + signals[QUERY_PROGRESS] = + g_signal_new ("query_progress", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (QueryListenerClass, query_progress), + NULL, NULL, + cal_marshal_VOID__POINTER, + G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT); + signals[QUERY_DONE] = + g_signal_new ("query_done", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (QueryListenerClass, query_done), + NULL, NULL, + cal_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); } -/** - * query_listener_new: - * @obj_updated_fn: Callback to use when a component is updated in the query. - * @obj_removed_fn: Callback to use when a component is removed from the query. - * @query_done_fn: Callback to use when a query is done. - * @eval_error_fn: Callback to use when an evaluation error happens during a query. - * @fn_data: Closure data to pass to the callbacks. - * - * Creates a new query listener object. - * - * Return value: A newly-created query listener object. - **/ +BONOBO_TYPE_FUNC_FULL (QueryListener, + GNOME_Evolution_Calendar_QueryListener, + BONOBO_TYPE_OBJECT, + query_listener); + QueryListener * -query_listener_new (QueryListenerObjUpdatedFn obj_updated_fn, - QueryListenerObjRemovedFn obj_removed_fn, - QueryListenerQueryDoneFn query_done_fn, - QueryListenerEvalErrorFn eval_error_fn, - gpointer fn_data) +query_listener_new (void) { QueryListener *ql; ql = g_object_new (QUERY_LISTENER_TYPE, NULL); - return query_listener_construct (ql, - obj_updated_fn, - obj_removed_fn, - query_done_fn, - eval_error_fn, - fn_data); -} - -/** - * query_listener_stop_notification: - * @ql: A query listener. - * - * Informs a query listener that no further notification is desired. The - * callbacks specified when the listener was created will no longer be invoked - * after this function is called. - **/ -void -query_listener_stop_notification (QueryListener *ql) -{ - QueryListenerPrivate *priv; - - g_return_if_fail (ql != NULL); - g_return_if_fail (IS_QUERY_LISTENER (ql)); - - priv = ql->priv; - g_return_if_fail (priv->notify != FALSE); - - priv->notify = FALSE; + return ql; } diff --git a/calendar/cal-client/query-listener.h b/calendar/cal-client/query-listener.h index eeb42afc7e..6a204bbf77 100644 --- a/calendar/cal-client/query-listener.h +++ b/calendar/cal-client/query-listener.h @@ -22,6 +22,7 @@ #define QUERY_LISTENER_H #include <bonobo/bonobo-object.h> +#include "cal-client-types.h" #include "evolution-calendar.h" G_BEGIN_DECLS @@ -48,47 +49,18 @@ typedef struct { BonoboObjectClass parent_class; POA_GNOME_Evolution_Calendar_QueryListener__epv epv; + + void (*objects_added) (QueryListener *listener, GList *objects); + void (*objects_modified) (QueryListener *listener, GList *objects); + void (*objects_removed) (QueryListener *listener, GList *uids); + void (*query_progress) (QueryListener *listener, const char *message, int percent); + void (*query_done) (QueryListener *listener, ECalendarStatus status); } QueryListenerClass; /* Notification functions */ -typedef void (* QueryListenerObjUpdatedFn) (QueryListener *ql, - const GNOME_Evolution_Calendar_CalObjUIDSeq *uids, - CORBA_boolean query_in_progress, - CORBA_long n_scanned, - CORBA_long total, - gpointer data); - -typedef void (* QueryListenerObjRemovedFn) (QueryListener *ql, - const CORBA_char *uid, - gpointer data); - -typedef void (* QueryListenerQueryDoneFn) ( - QueryListener *ql, - GNOME_Evolution_Calendar_QueryListener_QueryDoneStatus status, - const CORBA_char *error_str, - gpointer data); - -typedef void (* QueryListenerEvalErrorFn) (QueryListener *ql, - const CORBA_char *error_str, - gpointer data); - GType query_listener_get_type (void); - -QueryListener *query_listener_construct (QueryListener *ql, - QueryListenerObjUpdatedFn obj_updated_fn, - QueryListenerObjRemovedFn obj_removed_fn, - QueryListenerQueryDoneFn query_done_fn, - QueryListenerEvalErrorFn eval_error_fn, - gpointer fn_data); - -QueryListener *query_listener_new (QueryListenerObjUpdatedFn obj_updated_fn, - QueryListenerObjRemovedFn obj_removed_fn, - QueryListenerQueryDoneFn query_done_fn, - QueryListenerEvalErrorFn eval_error_fn, - gpointer fn_data); - -void query_listener_stop_notification (QueryListener *ql); +QueryListener *query_listener_new (void); diff --git a/calendar/cal-util/cal-util.c b/calendar/cal-util/cal-util.c index 1e03c86d75..f1c32610c1 100644 --- a/calendar/cal-util/cal-util.c +++ b/calendar/cal-util/cal-util.c @@ -584,29 +584,7 @@ cal_util_priority_from_string (const char *string) char * cal_util_expand_uri (char *uri, gboolean tasks) { - char *file_uri, *file_name; - - if (!strncmp (uri, "file://", 7)) { - file_uri = uri + 7; - if (strlen (file_uri) > 4 - && !strcmp (file_uri + strlen (file_uri) - 4, ".ics")) { - - /* it's a .ics file */ - return g_strdup (uri); - } - - /* we assume it's a dir and glom <type>.ics onto the end. */ - if (tasks) - file_name = g_concat_dir_and_file (file_uri, "tasks.ics"); - else - file_name = g_concat_dir_and_file (file_uri, "calendar.ics"); - file_uri = g_strdup_printf("file://%s", file_name); - g_free(file_name); - } else { - file_uri = g_strdup (uri); - } - - return file_uri; + return g_strdup (uri); } /* callback for icalcomponent_foreach_tzid */ diff --git a/calendar/conduits/calendar/calendar-conduit.c b/calendar/conduits/calendar/calendar-conduit.c index 1893e6b34c..05ddde2c7f 100644 --- a/calendar/conduits/calendar/calendar-conduit.c +++ b/calendar/conduits/calendar/calendar-conduit.c @@ -253,7 +253,7 @@ struct _ECalConduitContext { icaltimezone *timezone; CalComponent *default_comp; - GList *uids; + GList *comps; GList *changed; GHashTable *changed_hash; GList *locals; @@ -276,7 +276,7 @@ e_calendar_context_new (guint32 pilot_id) ctxt->client = NULL; ctxt->timezone = NULL; ctxt->default_comp = NULL; - ctxt->uids = NULL; + ctxt->comps = NULL; ctxt->changed = NULL; ctxt->changed_hash = NULL; ctxt->locals = NULL; @@ -311,8 +311,11 @@ e_calendar_context_destroy (ECalConduitContext *ctxt) g_object_unref (ctxt->client); if (ctxt->default_comp != NULL) g_object_unref (ctxt->default_comp); - if (ctxt->uids != NULL) - cal_obj_uid_list_free (ctxt->uids); + if (ctxt->comps != NULL) { + for (l = ctxt->comps; l; l = l->next) + g_object_unref (l->data); + g_list_free (ctxt->comps); + } if (ctxt->changed != NULL) cal_client_change_list_free (ctxt->changed); @@ -404,16 +407,24 @@ start_calendar_server_cb (CalClient *cal_client, static int start_calendar_server (ECalConduitContext *ctxt) { + char *uri; gboolean success = FALSE; g_return_val_if_fail (ctxt != NULL, -2); - ctxt->client = cal_client_new (); - + /* FIXME Need a mechanism for the user to select uri's */ + /* FIXME Can we use the cal model? */ + uri = g_strdup_printf ("file://%s/local/Calendar/", g_get_home_dir ()); + ctxt->client = cal_client_new (uri, CALOBJ_TYPE_EVENT); + g_free (uri); + + if (!ctxt->client) + return -1; + g_signal_connect (ctxt->client, "cal_opened", G_CALLBACK (start_calendar_server_cb), &success); - if (!cal_client_open_default_calendar (ctxt->client, FALSE)) + if (!cal_client_open (ctxt->client, FALSE, NULL)) return -1; /* run a sub event loop to turn cal-client's async load @@ -433,8 +444,8 @@ get_timezone (CalClient *client, const char *tzid) icaltimezone *timezone = NULL; timezone = icaltimezone_get_builtin_timezone_from_tzid (tzid); - if (timezone == NULL) - cal_client_get_timezone (client, tzid, &timezone); + if (timezone == NULL) + cal_client_get_timezone (client, tzid, &timezone, NULL); return timezone; } @@ -550,7 +561,7 @@ is_all_day (CalClient *client, CalComponentDateTime *dt_start, CalComponentDateT } static gboolean -process_multi_day (ECalConduitContext *ctxt, CalClientChange *ccc, GList **multi_uid, GList **multi_ccc) +process_multi_day (ECalConduitContext *ctxt, CalClientChange *ccc, GList **multi_comp, GList **multi_ccc) { CalComponentDateTime dt_start, dt_end; icaltimezone *tz_start, *tz_end; @@ -562,7 +573,7 @@ process_multi_day (ECalConduitContext *ctxt, CalClientChange *ccc, GList **multi gboolean ret = TRUE; *multi_ccc = NULL; - *multi_uid = NULL; + *multi_comp = NULL; if (ccc->type == CAL_CLIENT_CHANGE_DELETED) return FALSE; @@ -617,13 +628,14 @@ process_multi_day (ECalConduitContext *ctxt, CalClientChange *ccc, GList **multi dt_end.value = &end_value; cal_component_set_dtend (clone, &dt_end); - cal_client_update_object (ctxt->client, clone); + /* FIXME Error handling */ + cal_client_create_object (ctxt->client, cal_component_get_icalcomponent (clone), NULL, NULL); c->comp = clone; c->type = CAL_CLIENT_CHANGE_ADDED; *multi_ccc = g_list_prepend (*multi_ccc, c); - *multi_uid = g_list_prepend (*multi_uid, new_uid); + *multi_comp = g_list_prepend (*multi_comp, g_object_ref (c->comp)); event_start = day_end; day_end = time_day_end_with_zone (event_start, ctxt->timezone); @@ -632,7 +644,8 @@ process_multi_day (ECalConduitContext *ctxt, CalClientChange *ccc, GList **multi dt_end.value = old_end_value; cal_component_get_uid (ccc->comp, &uid); - cal_client_remove_object (ctxt->client, uid); + /* FIXME Error handling */ + cal_client_remove_object (ctxt->client, uid, NULL); ccc->type = CAL_CLIENT_CHANGE_DELETED; cleanup: @@ -1007,13 +1020,11 @@ local_record_from_uid (ECalLocalRecord *local, { CalComponent *comp; icalcomponent *icalcomp; - CalClientGetStatus status; + GError *error = NULL; g_assert(local!=NULL); - status = cal_client_get_object (ctxt->client, uid, &icalcomp); - - if (status == CAL_CLIENT_GET_SUCCESS) { + if (cal_client_get_object (ctxt->client, uid, NULL, &icalcomp, &error)) { comp = cal_component_new (); if (!cal_component_set_icalcomponent (comp, icalcomp)) { g_object_unref (comp); @@ -1023,7 +1034,7 @@ local_record_from_uid (ECalLocalRecord *local, local_record_from_comp (local, comp, ctxt); g_object_unref (comp); - } else if (status == CAL_CLIENT_GET_NOT_FOUND) { + } else if (error->code == E_CALENDAR_STATUS_OBJECT_NOT_FOUND) { comp = cal_component_new (); cal_component_set_new_vtype (comp, CAL_COMPONENT_EVENT); cal_component_set_uid (comp, uid); @@ -1031,7 +1042,9 @@ local_record_from_uid (ECalLocalRecord *local, g_object_unref (comp); } else { INFO ("Object did not exist"); - } + } + + g_clear_error (&error); } static CalComponent * @@ -1283,21 +1296,6 @@ comp_from_remote_record (GnomePilotConduitSyncAbs *conduit, } static void -update_comp (GnomePilotConduitSyncAbs *conduit, CalComponent *comp, - ECalConduitContext *ctxt) -{ - CalClientResult success; - - g_return_if_fail (conduit != NULL); - g_return_if_fail (comp != NULL); - - success = cal_client_update_object (ctxt->client, comp); - - if (success != CAL_CLIENT_RESULT_SUCCESS) - WARN (_("Error while communicating with calendar server")); -} - -static void check_for_slow_setting (GnomePilotConduit *c, ECalConduitContext *ctxt) { GnomePilotConduitStandard *conduit = GNOME_PILOT_CONDUIT_STANDARD (c); @@ -1360,11 +1358,13 @@ pre_sync (GnomePilotConduit *conduit, LOG (g_message ( " Using timezone: %s", icaltimezone_get_tzid (ctxt->timezone) )); /* Set the default timezone on the backend. */ - if (ctxt->timezone) - cal_client_set_default_timezone (ctxt->client, ctxt->timezone); + if (ctxt->timezone) { + if (!cal_client_set_default_timezone (ctxt->client, ctxt->timezone, NULL)) + return -1; + } /* Get the default component */ - if (cal_client_get_default_object (ctxt->client, CALOBJ_TYPE_EVENT, &icalcomp) != CAL_CLIENT_GET_SUCCESS) + if (!cal_client_get_default_object (ctxt->client, &icalcomp, NULL)) return -1; ctxt->default_comp = cal_component_new (); @@ -1374,27 +1374,36 @@ pre_sync (GnomePilotConduit *conduit, return -1; } + ctxt->default_comp = cal_component_new (); + if (!cal_component_set_icalcomponent (ctxt->default_comp, icalcomp)) { + g_object_unref (ctxt->default_comp); + icalcomponent_free (icalcomp); + return -1; + } + /* Load the uid <--> pilot id mapping */ filename = map_name (ctxt); e_pilot_map_read (filename, &ctxt->map); g_free (filename); /* Get the local database */ - ctxt->uids = cal_client_get_uids (ctxt->client, CALOBJ_TYPE_EVENT); + if (!cal_client_get_object_list_as_comp (ctxt->client, "(#t)", &ctxt->comps, NULL)) + return -1; /* Find the added, modified and deleted items */ change_id = g_strdup_printf ("pilot-sync-evolution-calendar-%d", ctxt->cfg->pilot_id); - ctxt->changed = cal_client_get_changes (ctxt->client, CALOBJ_TYPE_EVENT, change_id); + if (!cal_client_get_changes (ctxt->client, CALOBJ_TYPE_EVENT, change_id, &ctxt->changed, NULL)) + return -1; ctxt->changed_hash = g_hash_table_new (g_str_hash, g_str_equal); g_free (change_id); /* See if we need to split up any events */ for (l = ctxt->changed; l != NULL; l = l->next) { CalClientChange *ccc = l->data; - GList *multi_uid = NULL, *multi_ccc = NULL; + GList *multi_comp = NULL, *multi_ccc = NULL; - if (process_multi_day (ctxt, ccc, &multi_uid, &multi_ccc)) { - ctxt->uids = g_list_concat (ctxt->uids, multi_uid); + if (process_multi_day (ctxt, ccc, &multi_comp, &multi_ccc)) { + ctxt->comps = g_list_concat (ctxt->comps, multi_comp); added = g_list_concat (added, multi_ccc); removed = g_list_prepend (removed, ccc); @@ -1442,7 +1451,7 @@ pre_sync (GnomePilotConduit *conduit, } /* Set the count information */ - num_records = cal_client_get_n_objects (ctxt->client, CALOBJ_TYPE_EVENT); + num_records = g_list_length (ctxt->comps); gnome_pilot_conduit_sync_abs_set_num_local_records(abs_conduit, num_records); gnome_pilot_conduit_sync_abs_set_num_new_local_records (abs_conduit, add_records); gnome_pilot_conduit_sync_abs_set_num_updated_local_records (abs_conduit, mod_records); @@ -1492,8 +1501,8 @@ post_sync (GnomePilotConduit *conduit, * a race condition if anyone changes a record elsewhere during sycnc */ change_id = g_strdup_printf ("pilot-sync-evolution-calendar-%d", ctxt->cfg->pilot_id); - changed = cal_client_get_changes (ctxt->client, CALOBJ_TYPE_EVENT, change_id); - cal_client_change_list_free (changed); + if (cal_client_get_changes (ctxt->client, CALOBJ_TYPE_EVENT, change_id, &changed, NULL)) + cal_client_change_list_free (changed); g_free (change_id); LOG (g_message ( "---------------------------------------------------------\n" )); @@ -1537,7 +1546,7 @@ for_each (GnomePilotConduitSyncAbs *conduit, ECalLocalRecord **local, ECalConduitContext *ctxt) { - static GList *uids, *iterator; + static GList *comps, *iterator; static int count; g_return_val_if_fail (local != NULL, -1); @@ -1545,17 +1554,17 @@ for_each (GnomePilotConduitSyncAbs *conduit, if (*local == NULL) { LOG (g_message ( "beginning for_each" )); - uids = ctxt->uids; + comps = ctxt->comps; count = 0; - if (uids != NULL) { - LOG (g_message ( "iterating over %d records", g_list_length (uids) )); + if (comps != NULL) { + LOG (g_message ( "iterating over %d records", g_list_length (comps))); *local = g_new0 (ECalLocalRecord, 1); - local_record_from_uid (*local, uids->data, ctxt); + local_record_from_comp (*local, comps->data, ctxt); g_list_prepend (ctxt->locals, *local); - iterator = uids; + iterator = comps; } else { LOG (g_message ( "no events" )); (*local) = NULL; @@ -1681,8 +1690,10 @@ add_record (GnomePilotConduitSyncAbs *conduit, /* Give it a new UID otherwise it will be the uid of the default comp */ uid = cal_component_gen_uid (); cal_component_set_uid (comp, uid); + + if (!cal_client_create_object (ctxt->client, cal_component_get_icalcomponent (comp), NULL, NULL)) + return -1; - update_comp (conduit, comp, ctxt); e_pilot_map_insert (ctxt->map, remote->ID, uid, FALSE); g_free (uid); @@ -1709,7 +1720,10 @@ replace_record (GnomePilotConduitSyncAbs *conduit, new_comp = comp_from_remote_record (conduit, remote, local->comp, ctxt->client, ctxt->timezone); g_object_unref (local->comp); local->comp = new_comp; - update_comp (conduit, local->comp, ctxt); + + if (!cal_client_modify_object (ctxt->client, cal_component_get_icalcomponent (new_comp), + CALOBJ_MOD_ALL, NULL)) + return -1; return retval; } @@ -1729,7 +1743,8 @@ delete_record (GnomePilotConduitSyncAbs *conduit, LOG (g_message ( "delete_record: deleting %s\n", uid )); e_pilot_map_remove_by_uid (ctxt->map, uid); - cal_client_remove_object (ctxt->client, uid); + /* FIXME Error handling */ + cal_client_remove_object (ctxt->client, uid, NULL); return 0; } diff --git a/calendar/conduits/todo/todo-conduit.c b/calendar/conduits/todo/todo-conduit.c index 6868368129..35251f4eb6 100644 --- a/calendar/conduits/todo/todo-conduit.c +++ b/calendar/conduits/todo/todo-conduit.c @@ -255,7 +255,7 @@ struct _EToDoConduitContext { icaltimezone *timezone; CalComponent *default_comp; - GList *uids; + GList *comps; GList *changed; GHashTable *changed_hash; GList *locals; @@ -275,7 +275,7 @@ e_todo_context_new (guint32 pilot_id) ctxt->client = NULL; ctxt->timezone = NULL; ctxt->default_comp = NULL; - ctxt->uids = NULL; + ctxt->comps = NULL; ctxt->changed_hash = NULL; ctxt->changed = NULL; ctxt->locals = NULL; @@ -311,8 +311,11 @@ e_todo_context_destroy (EToDoConduitContext *ctxt) if (ctxt->default_comp != NULL) g_object_unref (ctxt->default_comp); - if (ctxt->uids != NULL) - cal_obj_uid_list_free (ctxt->uids); + if (ctxt->comps != NULL) { + for (l = ctxt->comps; l; l = l->next) + g_object_unref (l->data); + g_list_free (ctxt->comps); + } if (ctxt->changed_hash != NULL) { g_hash_table_foreach_remove (ctxt->changed_hash, e_todo_context_foreach_change, NULL); @@ -411,16 +414,24 @@ start_calendar_server_cb (CalClient *cal_client, static int start_calendar_server (EToDoConduitContext *ctxt) { + char *uri; gboolean success = FALSE; g_return_val_if_fail (ctxt != NULL, -2); - ctxt->client = cal_client_new (); + /* FIXME Need a mechanism for the user to select uri's */ + /* FIXME Can we use the cal model? */ + uri = g_strdup_printf ("file://%s/local/Tasks/", g_get_home_dir ()); + ctxt->client = cal_client_new (uri, CALOBJ_TYPE_TODO); + g_free (uri); + + if (!ctxt->client) + return -1; g_signal_connect (ctxt->client, "cal_opened", G_CALLBACK (start_calendar_server_cb), &success); - if (!cal_client_open_default_tasks (ctxt->client, FALSE)) + if (!cal_client_open (ctxt->client, FALSE, NULL)) return -1; /* run a sub event loop to turn cal-client's async load @@ -441,7 +452,7 @@ get_timezone (CalClient *client, const char *tzid) timezone = icaltimezone_get_builtin_timezone_from_tzid (tzid); if (timezone == NULL) - cal_client_get_timezone (client, tzid, &timezone); + cal_client_get_timezone (client, tzid, &timezone, NULL); return timezone; } @@ -676,13 +687,11 @@ local_record_from_uid (EToDoLocalRecord *local, { CalComponent *comp; icalcomponent *icalcomp; - CalClientGetStatus status; + GError *error = NULL; g_assert(local!=NULL); - status = cal_client_get_object (ctxt->client, uid, &icalcomp); - - if (status == CAL_CLIENT_GET_SUCCESS) { + if (cal_client_get_object (ctxt->client, uid, NULL, &icalcomp, &error)) { comp = cal_component_new (); if (!cal_component_set_icalcomponent (comp, icalcomp)) { g_object_unref (comp); @@ -692,7 +701,7 @@ local_record_from_uid (EToDoLocalRecord *local, local_record_from_comp (local, comp, ctxt); g_object_unref (comp); - } else if (status == CAL_CLIENT_GET_NOT_FOUND) { + } else if (error->code == E_CALENDAR_STATUS_OBJECT_NOT_FOUND) { comp = cal_component_new (); cal_component_set_new_vtype (comp, CAL_COMPONENT_TODO); cal_component_set_uid (comp, uid); @@ -702,7 +711,7 @@ local_record_from_uid (EToDoLocalRecord *local, INFO ("Object did not exist"); } - + g_clear_error (&error); } @@ -824,21 +833,6 @@ comp_from_remote_record (GnomePilotConduitSyncAbs *conduit, } static void -update_comp (GnomePilotConduitSyncAbs *conduit, CalComponent *comp, - EToDoConduitContext *ctxt) -{ - CalClientResult success; - - g_return_if_fail (conduit != NULL); - g_return_if_fail (comp != NULL); - - success = cal_client_update_object (ctxt->client, comp); - - if (success != CAL_CLIENT_RESULT_SUCCESS) - WARN (_("Error while communicating with calendar server")); -} - -static void check_for_slow_setting (GnomePilotConduit *c, EToDoConduitContext *ctxt) { GnomePilotConduitStandard *conduit = GNOME_PILOT_CONDUIT_STANDARD (c); @@ -902,11 +896,13 @@ pre_sync (GnomePilotConduit *conduit, LOG (g_message ( " Using timezone: %s", icaltimezone_get_tzid (ctxt->timezone) )); /* Set the default timezone on the backend. */ - if (ctxt->timezone) - cal_client_set_default_timezone (ctxt->client, ctxt->timezone); + if (ctxt->timezone) { + if (!cal_client_set_default_timezone (ctxt->client, ctxt->timezone, NULL)) + return -1; + } /* Get the default component */ - if (cal_client_get_default_object (ctxt->client, CALOBJ_TYPE_TODO, &icalcomp) != CAL_CLIENT_GET_SUCCESS) + if (!cal_client_get_default_object (ctxt->client, &icalcomp, NULL)) return -1; ctxt->default_comp = cal_component_new (); @@ -916,17 +912,26 @@ pre_sync (GnomePilotConduit *conduit, return -1; } + ctxt->default_comp = cal_component_new (); + if (!cal_component_set_icalcomponent (ctxt->default_comp, icalcomp)) { + g_object_unref (ctxt->default_comp); + icalcomponent_free (icalcomp); + return -1; + } + /* Load the uid <--> pilot id map */ filename = map_name (ctxt); e_pilot_map_read (filename, &ctxt->map); g_free (filename); /* Get the local database */ - ctxt->uids = cal_client_get_uids (ctxt->client, CALOBJ_TYPE_TODO); + if (!cal_client_get_object_list_as_comp (ctxt->client, "(#t)", &ctxt->comps, NULL)) + return -1; /* Count and hash the changes */ change_id = g_strdup_printf ("pilot-sync-evolution-todo-%d", ctxt->cfg->pilot_id); - ctxt->changed = cal_client_get_changes (ctxt->client, CALOBJ_TYPE_TODO, change_id); + if (!cal_client_get_changes (ctxt->client, CALOBJ_TYPE_TODO, change_id, &ctxt->changed, NULL)) + return -1; ctxt->changed_hash = g_hash_table_new (g_str_hash, g_str_equal); g_free (change_id); @@ -956,7 +961,7 @@ pre_sync (GnomePilotConduit *conduit, } /* Set the count information */ - num_records = cal_client_get_n_objects (ctxt->client, CALOBJ_TYPE_TODO); + num_records = g_list_length (ctxt->comps); gnome_pilot_conduit_sync_abs_set_num_local_records(abs_conduit, num_records); gnome_pilot_conduit_sync_abs_set_num_new_local_records (abs_conduit, add_records); gnome_pilot_conduit_sync_abs_set_num_updated_local_records (abs_conduit, mod_records); @@ -1006,8 +1011,8 @@ post_sync (GnomePilotConduit *conduit, * a race condition if anyone changes a record elsewhere during sycnc */ change_id = g_strdup_printf ("pilot-sync-evolution-todo-%d", ctxt->cfg->pilot_id); - changed = cal_client_get_changes (ctxt->client, CALOBJ_TYPE_TODO, change_id); - cal_client_change_list_free (changed); + if (cal_client_get_changes (ctxt->client, CALOBJ_TYPE_TODO, change_id, &changed, NULL)) + cal_client_change_list_free (changed); g_free (change_id); LOG (g_message ( "---------------------------------------------------------\n" )); @@ -1051,7 +1056,7 @@ for_each (GnomePilotConduitSyncAbs *conduit, EToDoLocalRecord **local, EToDoConduitContext *ctxt) { - static GList *uids, *iterator; + static GList *comps, *iterator; static int count; g_return_val_if_fail (local != NULL, -1); @@ -1059,17 +1064,17 @@ for_each (GnomePilotConduitSyncAbs *conduit, if (*local == NULL) { LOG (g_message ( "beginning for_each" )); - uids = ctxt->uids; + comps = ctxt->comps; count = 0; - if (uids != NULL) { - LOG (g_message ( "iterating over %d records", g_list_length (uids) )); + if (comps != NULL) { + LOG (g_message ( "iterating over %d records", g_list_length (comps))); *local = g_new0 (EToDoLocalRecord, 1); - local_record_from_uid (*local, uids->data, ctxt); + local_record_from_comp (*local, comps->data, ctxt); g_list_prepend (ctxt->locals, *local); - iterator = uids; + iterator = comps; } else { LOG (g_message ( "no events" )); (*local) = NULL; @@ -1196,7 +1201,9 @@ add_record (GnomePilotConduitSyncAbs *conduit, uid = cal_component_gen_uid (); cal_component_set_uid (comp, uid); - update_comp (conduit, comp, ctxt); + if (!cal_client_create_object (ctxt->client, cal_component_get_icalcomponent (comp), NULL, NULL)) + return -1; + e_pilot_map_insert (ctxt->map, remote->ID, uid, FALSE); g_object_unref (comp); @@ -1221,7 +1228,10 @@ replace_record (GnomePilotConduitSyncAbs *conduit, new_comp = comp_from_remote_record (conduit, remote, local->comp, ctxt->timezone); g_object_unref (local->comp); local->comp = new_comp; - update_comp (conduit, local->comp, ctxt); + + if (!cal_client_modify_object (ctxt->client, cal_component_get_icalcomponent (new_comp), + CALOBJ_MOD_ALL, NULL)) + return -1; return retval; } @@ -1241,7 +1251,8 @@ delete_record (GnomePilotConduitSyncAbs *conduit, LOG (g_message ( "delete_record: deleting %s\n", uid )); e_pilot_map_remove_by_uid (ctxt->map, uid); - cal_client_remove_object (ctxt->client, uid); + /* FIXME Error handling */ + cal_client_remove_object (ctxt->client, uid, NULL); return 0; } diff --git a/calendar/gui/GNOME_Evolution_Calendar.server.in.in b/calendar/gui/GNOME_Evolution_Calendar.server.in.in index 801cada120..09f424f69a 100644 --- a/calendar/gui/GNOME_Evolution_Calendar.server.in.in +++ b/calendar/gui/GNOME_Evolution_Calendar.server.in.in @@ -1,6 +1,6 @@ <oaf_info> -<oaf_server iid="OAFIID:GNOME_Evolution_Calendar_Factory" +<oaf_server iid="OAFIID:GNOME_Evolution_Calendar_Factory_2" type="shlib" location="@COMPONENTDIR@/libevolution-calendar.so"> @@ -15,7 +15,7 @@ <oaf_server iid="OAFIID:GNOME_Evolution_Calendar_iTip_Control" type="factory" - location="OAFIID:GNOME_Evolution_Calendar_Factory"> + location="OAFIID:GNOME_Evolution_Calendar_Factory_2"> <oaf_attribute name="repo_ids" type="stringv"> <item value="IDL:Bonobo/Control:1.0"/> @@ -31,26 +31,20 @@ _value="Evolution Calendar scheduling message viewer"/> </oaf_server> -<oaf_server iid="OAFIID:GNOME_Evolution_Calendar_ShellComponent" +<oaf_server iid="OAFIID:GNOME_Evolution_Calendar_Component" type="factory" - location="OAFIID:GNOME_Evolution_Calendar_Factory"> + location="OAFIID:GNOME_Evolution_Calendar_Factory_2"> <oaf_attribute name="repo_ids" type="stringv"> - <item value="IDL:GNOME/Evolution/ShellComponent:1.0"/> + <item value="IDL:GNOME/Evolution/Component:1.0"/> </oaf_attribute> - <oaf_attribute name="name" type="string" - _value="Evolution Calendar and Tasks component"/> - - <oaf_attribute name="evolution:shell_component_icon" type="string" - value="evolution-calendar.png"/> - <oaf_attribute name="evolution:shell_component_launch_order" type="number" - value="3"/> + <oaf_attribute name="name" type="string" _value="Evolution's Calendar component"/> </oaf_server> <oaf_server iid="OAFIID:GNOME_Evolution_Calendar_Control" type="factory" - location="OAFIID:GNOME_Evolution_Calendar_Factory"> + location="OAFIID:GNOME_Evolution_Calendar_Factory_2"> <oaf_attribute name="repo_ids" type="stringv"> <item value="IDL:BonoboControl/calendar-control:1.0"/> @@ -68,7 +62,7 @@ <oaf_server iid="OAFIID:GNOME_Evolution_Tasks_Control" type="factory" - location="OAFIID:GNOME_Evolution_Calendar_Factory"> + location="OAFIID:GNOME_Evolution_Calendar_Factory_2"> <oaf_attribute name="repo_ids" type="stringv"> <item value="IDL:BonoboControl/tasks-control:1.0"/> @@ -86,7 +80,7 @@ <oaf_server iid="OAFIID:GNOME_Evolution_Calendar_CompEditorFactory" type="factory" - location="OAFIID:GNOME_Evolution_Calendar_Factory"> + location="OAFIID:GNOME_Evolution_Calendar_Factory_2"> <oaf_attribute name="repo_ids" type="stringv"> <item value="IDL:GNOME/Evolution/Calendar/CompEditorFactory:1.0"/> @@ -99,7 +93,7 @@ <oaf_server iid="OAFIID:GNOME_Evolution_Calendar_ConfigControl" type="factory" - location="OAFIID:GNOME_Evolution_Calendar_Factory"> + location="OAFIID:GNOME_Evolution_Calendar_Factory_2"> <oaf_attribute name="repo_ids" type="stringv"> <item value="IDL:GNOME/Evolution/ConfigControl:1.0"/> diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am index 3ee9362b65..19edf95953 100644 --- a/calendar/gui/Makefile.am +++ b/calendar/gui/Makefile.am @@ -169,6 +169,8 @@ libevolution_calendar_la_SOURCES = \ itip-utils.c \ itip-utils.h \ main.c \ + migration.c \ + migration.h \ misc.c \ misc.h \ print.c \ @@ -189,7 +191,8 @@ libevolution_calendar_la_LIBADD = \ $(top_builddir)/calendar/gui/dialogs/libcal-dialogs.la \ $(top_builddir)/widgets/e-timezone-dialog/libetimezonedialog.la \ $(top_builddir)/widgets/misc/libemiscwidgets.la \ - $(top_builddir)/a11y/calendar/libevolution-calendar-a11y.la \ + $(top_builddir)/e-util/libeutil.la \ + $(top_builddir)/a11y/calendar/libevolution-calendar-a11y.la \ $(EVOLUTION_CALENDAR_LIBS) libevolution_calendar_la_LDFLAGS = -avoid-version -module diff --git a/calendar/gui/alarm-notify/alarm-notify.c b/calendar/gui/alarm-notify/alarm-notify.c index 133448e7cd..006533c6bf 100644 --- a/calendar/gui/alarm-notify/alarm-notify.c +++ b/calendar/gui/alarm-notify/alarm-notify.c @@ -31,26 +31,6 @@ -/* A loaded client */ -typedef struct { - /* The actual client */ - CalClient *client; - - /* The URI of the client in gnome-vfs's format. This *is* the key that - * is stored in the uri_client_hash hash table below. - */ - EUri *uri; - - /* Number of times clients have requested this URI to be added to the - * alarm notification system. - */ - int refcount; - - /* the ID of the retry timeout function - */ - int timeout_id; -} LoadedClient; - /* Private part of the AlarmNotify structure */ struct _AlarmNotifyPrivate { /* Mapping from EUri's to LoadedClient structures */ @@ -105,23 +85,7 @@ alarm_notify_init (AlarmNotify *an, AlarmNotifyClass *klass) priv = g_new0 (AlarmNotifyPrivate, 1); an->priv = priv; - priv->uri_client_hash = g_hash_table_new (g_str_hash, g_str_equal); -} - -/* Callback used from g_hash-table_forach(), used to destroy a loade client */ -static void -destroy_loaded_client_cb (gpointer key, gpointer value, gpointer data) -{ - LoadedClient *lc; - char *str_uri; - - str_uri = key; - lc = value; - - g_free (str_uri); - g_object_unref (G_OBJECT (lc->client)); - e_uri_free (lc->uri); - g_free (lc); + priv->uri_client_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); } /* Finalize handler for the alarm notify system */ @@ -137,13 +101,9 @@ alarm_notify_finalize (GObject *object) an = ALARM_NOTIFY (object); priv = an->priv; - g_hash_table_foreach (priv->uri_client_hash, destroy_loaded_client_cb, NULL); - g_hash_table_destroy (priv->uri_client_hash); - priv->uri_client_hash = NULL; g_free (priv); - an->priv = NULL; if (G_OBJECT_CLASS (parent_class)->finalize) (* G_OBJECT_CLASS (parent_class)->finalize) (object); @@ -193,21 +153,15 @@ free_uris (GPtrArray *uris) /* Adds an URI to the list of calendars to load on startup */ static void -add_uri_to_load (EUri *uri) +add_uri_to_load (const char *str_uri) { - char *str_uri; GPtrArray *loaded_uris; int i; - /* Canonicalize the URI */ - str_uri = e_uri_to_string (uri, FALSE); - g_assert (str_uri != NULL); - loaded_uris = get_calendars_to_load (); if (!loaded_uris) { g_message ("add_uri_to_load(): Could not get the list of calendars to load; " "will not add `%s'", str_uri); - g_free (str_uri); return; } @@ -219,12 +173,11 @@ add_uri_to_load (EUri *uri) * calendars. */ if (i != -1) { - g_free (str_uri); free_uris (loaded_uris); return; } - g_ptr_array_add (loaded_uris, str_uri); + g_ptr_array_add (loaded_uris, g_strdup (str_uri)); save_calendars_to_load (loaded_uris); free_uris (loaded_uris); @@ -232,29 +185,22 @@ add_uri_to_load (EUri *uri) /* Removes an URI from the list of calendars to load on startup */ static void -remove_uri_to_load (EUri *uri) +remove_uri_to_load (const char *str_uri) { - char *str_uri; GPtrArray *loaded_uris; char *loaded_uri; int i; - /* Canonicalize the URI */ - str_uri = e_uri_to_string (uri, FALSE); - g_assert (str_uri != NULL); - loaded_uris = get_calendars_to_load (); if (!loaded_uris) { g_message ("remove_uri_to_load(): Could not get the list of calendars to load; " "will not add `%s'", str_uri); - g_free (str_uri); return; } /* Look for the URI in the list of calendars to load */ i = find_uri_index (loaded_uris, str_uri); - g_free (str_uri); /* If we didn't find it, there is no need to remove it */ if (i == -1) { @@ -291,61 +237,19 @@ AlarmNotify_removeCalendar (PortableServer_Servant servant, { AlarmNotify *an; AlarmNotifyPrivate *priv; - LoadedClient *lc; - EUri *uri; - char *orig_str; - gpointer lc_ptr, orig_str_ptr; - gboolean found; - - lc_ptr = NULL; - orig_str_ptr = NULL; + CalClient *client; an = ALARM_NOTIFY (bonobo_object_from_servant (servant)); priv = an->priv; - uri = e_uri_new (str_uri); - if (!uri) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_GNOME_Evolution_Calendar_AlarmNotify_InvalidURI, - NULL); - return; - } + client = g_hash_table_lookup (priv->uri_client_hash, str_uri); + if (client) { + alarm_queue_remove_client (client); - remove_uri_to_load (uri); - - found = g_hash_table_lookup_extended (priv->uri_client_hash, str_uri, - &orig_str_ptr, - &lc_ptr); - orig_str = orig_str_ptr; - lc = lc_ptr; - - e_uri_free (uri); - - if (!lc) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_GNOME_Evolution_Calendar_AlarmNotify_NotFound, - NULL); - return; + g_hash_table_remove (priv->uri_client_hash, str_uri); } - g_assert (lc->refcount > 0); - - lc->refcount--; - if (lc->refcount > 0) - return; - - g_hash_table_remove (priv->uri_client_hash, str_uri); - - g_free (orig_str); - g_signal_handlers_disconnect_matched (lc->client, - G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, lc); - if (lc->timeout_id != -1) - g_source_remove (lc->timeout_id); - alarm_queue_remove_client (lc->client); - g_object_unref (G_OBJECT (lc->client)); - e_uri_free (lc->uri); - g_free (lc); + remove_uri_to_load (str_uri); } @@ -367,40 +271,6 @@ alarm_notify_new (void) return an; } -static gboolean -retry_timeout_cb (gpointer data) -{ - LoadedClient *lc = data; - char *str_uri; - - if (cal_client_get_load_state (lc->client) != CAL_CLIENT_LOAD_LOADED) { - str_uri = e_uri_to_string (lc->uri, FALSE); - cal_client_open_calendar (lc->client, str_uri, FALSE); - - g_free (str_uri); - } - - return FALSE; -} - -static void -cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer data) -{ - LoadedClient *lc = (LoadedClient *) data; - - if (status == CAL_CLIENT_OPEN_SUCCESS) { - add_uri_to_load (lc->uri); - alarm_queue_add_client (client); - lc->timeout_id = -1; - } - else { - remove_uri_to_load (lc->uri); - - /* we set a timeout of 5 mins before retrying */ - lc->timeout_id = g_timeout_add (300000, (GSourceFunc) retry_timeout_cb, lc); - } -} - /** * alarm_notify_add_calendar: * @an: An alarm notification service. @@ -418,10 +288,7 @@ alarm_notify_add_calendar (AlarmNotify *an, const char *str_uri, gboolean load_a CORBA_Environment *ev) { AlarmNotifyPrivate *priv; - EUri *uri; CalClient *client; - LoadedClient *lc; - gpointer lc_ptr, s_ptr; g_return_if_fail (an != NULL); g_return_if_fail (IS_ALARM_NOTIFY (an)); @@ -430,49 +297,23 @@ alarm_notify_add_calendar (AlarmNotify *an, const char *str_uri, gboolean load_a priv = an->priv; - uri = e_uri_new (str_uri); - if (!uri) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_GNOME_Evolution_Calendar_AlarmNotify_InvalidURI, - NULL); + /* See if we already know about this uri */ + if (g_hash_table_lookup (priv->uri_client_hash, str_uri)) return; - } - if (g_hash_table_lookup_extended (priv->uri_client_hash, str_uri, &s_ptr, &lc_ptr)) { - lc = lc_ptr; - lc->refcount++; - } else { - client = cal_client_new (); - - if (client) { - /* we only add the URI to load_afterwards if we open it - correctly */ - lc = g_new (LoadedClient, 1); - lc->client = client; - lc->uri = uri; - lc->refcount = 1; - lc->timeout_id = -1; - - - g_signal_connect (G_OBJECT (client), "cal_opened", - G_CALLBACK (cal_opened_cb), - lc); - - if (cal_client_open_calendar (client, str_uri, FALSE)) { - g_hash_table_insert (priv->uri_client_hash, - g_strdup (str_uri), lc); - } else { - g_free (lc); - g_object_unref (G_OBJECT (client)); - client = NULL; - } - } else { - e_uri_free (uri); - - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_GNOME_Evolution_Calendar_AlarmNotify_BackendContactError, - NULL); - return; + client = cal_client_new (str_uri, CALOBJ_TYPE_EVENT); + + if (client) { + if (cal_client_open (client, FALSE, NULL)) { + add_uri_to_load (str_uri); + + g_hash_table_insert (priv->uri_client_hash, + g_strdup (str_uri), client); } + } else { + CORBA_exception_set (ev, CORBA_USER_EXCEPTION, + ex_GNOME_Evolution_Calendar_AlarmNotify_BackendContactError, + NULL); + return; } } diff --git a/calendar/gui/alarm-notify/alarm-queue.c b/calendar/gui/alarm-notify/alarm-queue.c index cb792e466f..cee17bd97e 100644 --- a/calendar/gui/alarm-notify/alarm-queue.c +++ b/calendar/gui/alarm-notify/alarm-queue.c @@ -227,7 +227,7 @@ remove_queued_alarm (CompQueuedAlarms *cqa, gpointer alarm_id, if (remove_alarm) { cqa->expecting_update = TRUE; cal_client_discard_alarm (cqa->parent_client->client, cqa->alarms->comp, - qa->instance->auid); + qa->instance->auid, NULL); cqa->expecting_update = FALSE; } diff --git a/calendar/gui/calendar-commands.c b/calendar/gui/calendar-commands.c index c0d1b3c589..77305098bc 100644 --- a/calendar/gui/calendar-commands.c +++ b/calendar/gui/calendar-commands.c @@ -59,6 +59,7 @@ #include "goto.h" #include "print.h" #include "dialogs/cal-prefs-dialog.h" +#include "dialogs/new-calendar.h" #include "itip-utils.h" #include "evolution-shell-component-utils.h" @@ -73,6 +74,68 @@ typedef struct { guint taskpad_focused : 1; } FocusData; +static void +file_new_calendar_cb (BonoboUIComponent *uic, gpointer data, const char *path) +{ + GnomeCalendar *gcal; + + gcal = GNOME_CALENDAR (data); + + new_calendar_dialog (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (gcal)))); +} + +static void +file_new_appointment_cb (BonoboUIComponent *uic, gpointer data, const char *path) +{ + GnomeCalendar *gcal; + time_t dtstart, dtend; + ECalView *cal_view; + + gcal = GNOME_CALENDAR (data); + + cal_view = (ECalView *) gnome_calendar_get_current_view_widget (gcal); + e_cal_view_get_selected_time_range (cal_view, &dtstart, &dtend); + e_cal_view_new_appointment_for (cal_view, dtstart, dtend, FALSE, FALSE); +} + +static void +file_new_event_cb (BonoboUIComponent *uic, gpointer data, const char *path) +{ + GnomeCalendar *gcal; + time_t dtstart, dtend; + ECalView *cal_view; + + gcal = GNOME_CALENDAR (data); + + cal_view = (ECalView *) gnome_calendar_get_current_view_widget (gcal); + e_cal_view_get_selected_time_range (cal_view, &dtstart, &dtend); + e_cal_view_new_appointment_for (cal_view, dtstart, dtend, TRUE, FALSE); +} + +static void +file_new_meeting_cb (BonoboUIComponent *uic, gpointer data, const char *path) +{ + GnomeCalendar *gcal; + time_t dtstart, dtend; + ECalView *cal_view; + + gcal = GNOME_CALENDAR (data); + + cal_view = (ECalView *) gnome_calendar_get_current_view_widget (gcal); + e_cal_view_get_selected_time_range (cal_view, &dtstart, &dtend); + e_cal_view_new_appointment_for (cal_view, dtstart, dtend, FALSE, TRUE); +} + +static void +file_new_task_cb (BonoboUIComponent *uic, gpointer data, const char *path) +{ + GnomeCalendar *gcal; + + gcal = GNOME_CALENDAR (data); + + gnome_calendar_new_task (gcal); +} + /* Prints the calendar at its current view and time range */ static void print (GnomeCalendar *gcal, gboolean preview) @@ -335,12 +398,10 @@ publish_freebusy_cmd (BonoboUIComponent *uic, gpointer data, const gchar *path) start = time_day_begin_with_zone (start, utc); end = time_add_week_with_zone (start, 6, utc); + /* FIXME Should we aggregate the data? */ client_list = e_cal_model_get_client_list (gnome_calendar_get_calendar_model (gcal)); for (cl = client_list; cl != NULL; cl = cl->next) { - GList *tmp_comp_list; - - tmp_comp_list = cal_client_get_free_busy ((CalClient *) cl->data, NULL, start, end); - if (tmp_comp_list) { + if (cal_client_get_free_busy ((CalClient *) cl->data, NULL, start, end, &comp_list, NULL)) { GList *l; for (l = comp_list; l; l = l->next) { @@ -599,19 +660,42 @@ control_util_show_settings (GnomeCalendar *gcal) * is FALSE, all will be disabled. Otherwise, the currently-selected number of * events will be used. */ -static void -sensitize_calendar_commands (GnomeCalendar *gcal, BonoboControl *control, gboolean enable) +void +calendar_control_sensitize_calendar_commands (BonoboControl *control, GnomeCalendar *gcal, gboolean enable) { BonoboUIComponent *uic; + ECalViewEvent *event; + GList *list; int n_selected; - gboolean read_only, has_recurrences; + GtkWidget *view; + CalClient *cal_client; + gboolean read_only = FALSE, has_recurrences; uic = bonobo_control_get_ui_component (control); g_assert (uic != NULL); - n_selected = enable ? gnome_calendar_get_num_events_selected (gcal) : 0; - read_only = cal_client_is_read_only (e_cal_model_get_default_client (gnome_calendar_get_calendar_model (gcal))); + view = gnome_calendar_get_current_view_widget (gcal); + list = e_cal_view_get_selected_events (E_CAL_VIEW (view)); + + n_selected = enable ? g_list_length (list) : 0; + event = (ECalViewEvent *) list ? list->data : NULL; + if (event) { + cal_client_is_read_only (event->comp_data->client, &read_only, NULL); + } else { + cal_client = e_cal_model_get_default_client (gnome_calendar_get_calendar_model (gcal)); + if (cal_client) + cal_client_is_read_only (cal_client, &read_only, NULL); + else + read_only = TRUE; + } + + bonobo_ui_component_set_prop (uic, "/commands/NewAppointment", "sensitive", + read_only ? "0" : "1", NULL); + bonobo_ui_component_set_prop (uic, "/commands/NewAllDayEvent", "sensitive", + read_only ? "0" : "1", NULL); + bonobo_ui_component_set_prop (uic, "/commands/NewMeeting", "sensitive", + read_only ? "0" : "1", NULL); bonobo_ui_component_set_prop (uic, "/commands/Cut", "sensitive", n_selected == 0 || read_only ? "0" : "1", NULL); @@ -628,19 +712,8 @@ sensitize_calendar_commands (GnomeCalendar *gcal, BonoboControl *control, gboole /* occurrence-related menu items */ has_recurrences = FALSE; if (n_selected > 0 && !read_only) { - ECalViewEvent *event; - GList *list; - GtkWidget *view; - - view = gnome_calendar_get_current_view_widget (gcal); - list = e_cal_view_get_selected_events (E_CAL_VIEW (view)); if (list) { event = (ECalViewEvent *) list->data; - g_list_free (list); - } else - event = NULL; - - if (event) { if (cal_util_component_has_recurrences (event->comp_data->icalcomp)) has_recurrences = TRUE; } @@ -652,6 +725,10 @@ sensitize_calendar_commands (GnomeCalendar *gcal, BonoboControl *control, gboole bonobo_ui_component_set_prop (uic, "/commands/DeleteAllOccurrences", "sensitive", has_recurrences ? "1" : "0", NULL); + + /* free memory */ + if (list) + g_list_free (list); } /* Sensitizes the UI Component menu/toolbar tasks commands based on the number @@ -663,14 +740,21 @@ sensitize_taskpad_commands (GnomeCalendar *gcal, BonoboControl *control, gboolea { BonoboUIComponent *uic; int n_selected; - gboolean read_only; + CalClient *cal_client; + gboolean read_only = TRUE; uic = bonobo_control_get_ui_component (control); g_assert (uic != NULL); n_selected = enable ? gnome_calendar_get_num_tasks_selected (gcal) : 0; - read_only = cal_client_is_read_only (gnome_calendar_get_task_pad_cal_client (gcal)); - + cal_client = gnome_calendar_get_task_pad_cal_client (gcal); + if (cal_client) + cal_client_is_read_only (cal_client, &read_only, NULL); + else + read_only = TRUE; + + bonobo_ui_component_set_prop (uic, "/commands/NewTask", "sensitive", + read_only ? "0" : "1", NULL); bonobo_ui_component_set_prop (uic, "/commands/Cut", "sensitive", n_selected == 0 || read_only ? "0" : "1", NULL); @@ -705,7 +789,7 @@ gcal_calendar_selection_changed_cb (GnomeCalendar *gcal, gpointer data) control = BONOBO_CONTROL (data); - sensitize_calendar_commands (gcal, control, TRUE); + calendar_control_sensitize_calendar_commands (control, gcal, TRUE); } /* Callback used when the selection in the taskpad changes */ @@ -734,13 +818,13 @@ gcal_calendar_focus_change_cb (GnomeCalendar *gcal, gboolean in, gpointer data) if (in) { g_signal_connect (gcal, "calendar_selection_changed", G_CALLBACK (gcal_calendar_selection_changed_cb), control); - sensitize_calendar_commands (gcal, control, TRUE); + calendar_control_sensitize_calendar_commands (control, gcal, TRUE); focus->calendar_focused = TRUE; } else if (focus->calendar_focused) { gtk_signal_disconnect_by_func (GTK_OBJECT (gcal), G_CALLBACK (gcal_calendar_selection_changed_cb), control); - sensitize_calendar_commands (gcal, control, FALSE); + calendar_control_sensitize_calendar_commands (control, gcal, FALSE); focus->calendar_focused = FALSE; } } @@ -779,6 +863,11 @@ gcal_taskpad_focus_change_cb (GnomeCalendar *gcal, gboolean in, gpointer data) static BonoboUIVerb verbs [] = { + BONOBO_UI_VERB ("NewCalendar", file_new_calendar_cb), + BONOBO_UI_VERB ("NewAppointment", file_new_appointment_cb), + BONOBO_UI_VERB ("NewAllDayEvent", file_new_event_cb), + BONOBO_UI_VERB ("NewMeeting", file_new_meeting_cb), + BONOBO_UI_VERB ("NewTask", file_new_task_cb), BONOBO_UI_VERB ("CalendarPrint", file_print_cb), BONOBO_UI_VERB ("CalendarPrintPreview", file_print_preview_cb), @@ -808,11 +897,15 @@ static BonoboUIVerb verbs [] = { static EPixmap pixmaps [] = { - E_PIXMAP ("/Toolbar/DayView", "buttons/dayview.xpm"), - E_PIXMAP ("/Toolbar/WorkWeekView", "buttons/workweekview.xpm"), - E_PIXMAP ("/Toolbar/WeekView", "buttons/weekview.xpm"), - E_PIXMAP ("/Toolbar/MonthView", "buttons/monthview.xpm"), - E_PIXMAP ("/Toolbar/ListView", "buttons/listview.xpm"), + E_PIXMAP ("/commands/NewAppointment", "new_appointment.xpm"), + E_PIXMAP ("/commands/NewAllDayEvent", "new_all_day_event.png"), + E_PIXMAP ("/commands/NewMeeting", "meeting-request-16.png"), + E_PIXMAP ("/commands/NewTask", "new_task-16.png"), + E_PIXMAP ("/Toolbar/DayView", "buttons/dayview.xpm"), + E_PIXMAP ("/Toolbar/WorkWeekView", "buttons/workweekview.xpm"), + E_PIXMAP ("/Toolbar/WeekView", "buttons/weekview.xpm"), + E_PIXMAP ("/Toolbar/MonthView", "buttons/monthview.xpm"), + E_PIXMAP ("/Toolbar/ListView", "buttons/listview.xpm"), E_PIXMAP_END }; @@ -855,7 +948,7 @@ calendar_control_activate (BonoboControl *control, g_signal_connect (gcal, "taskpad_focus_change", G_CALLBACK (gcal_taskpad_focus_change_cb), control); - sensitize_calendar_commands (gcal, control, FALSE); + calendar_control_sensitize_calendar_commands (control, gcal, FALSE); sensitize_taskpad_commands (gcal, control, FALSE); bonobo_ui_component_thaw (uic, NULL); diff --git a/calendar/gui/calendar-commands.h b/calendar/gui/calendar-commands.h index 6f418799d2..3e74074140 100644 --- a/calendar/gui/calendar-commands.h +++ b/calendar/gui/calendar-commands.h @@ -38,6 +38,8 @@ GnomeCalendar *new_calendar (void); void calendar_control_activate (BonoboControl *control, GnomeCalendar *gcal); void calendar_control_deactivate (BonoboControl *control, GnomeCalendar *gcal); +void calendar_control_sensitize_calendar_commands (BonoboControl *control, GnomeCalendar *gcal, gboolean enable); + void calendar_goto_today (GnomeCalendar *gcal); void calendar_set_folder_bar_label (GnomeCalendar *gcal, BonoboControl *control); diff --git a/calendar/gui/calendar-component.c b/calendar/gui/calendar-component.c index 98f0964cc4..3e8782f45b 100644 --- a/calendar/gui/calendar-component.c +++ b/calendar/gui/calendar-component.c @@ -1,7 +1,7 @@ /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* component-factory.c +/* calendar-component.c * - * Copyright (C) 2000, 2001, 2002, 2003 Ximian, Inc. + * Copyright (C) 2003 Ettore Perazzoli * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public @@ -20,752 +20,269 @@ * Author: Ettore Perazzoli <ettore@ximian.com> */ +#ifdef CONFIG_H #include <config.h> +#endif -#include <errno.h> -#include <libgnome/gnome-util.h> -#include <libgnomevfs/gnome-vfs-types.h> -#include <libgnomevfs/gnome-vfs-uri.h> -#include <libgnomevfs/gnome-vfs-ops.h> -#include <libgnomevfs/gnome-vfs-directory.h> -#include <libgnomevfs/gnome-vfs-file-info.h> - -#include <bonobo/bonobo-generic-factory.h> -#include <bonobo/bonobo-context.h> -#include <bonobo/bonobo-exception.h> - -#include "evolution-shell-component.h" -#include "calendar-offline-handler.h" #include "calendar-component.h" -#include "tasks-control.h" #include "control-factory.h" -#include "calendar-config.h" -#include "tasks-control.h" -#include "e-comp-editor-registry.h" -#include "dialogs/comp-editor.h" - - -/* OAFIID for the component. */ -#define COMPONENT_ID "OAFIID:GNOME_Evolution_Calendar_ShellComponent" - -/* Folder type IDs */ -#define FOLDER_CALENDAR "calendar" -#define FOLDER_TASKS "tasks" -#define FOLDER_PUBLIC_CALENDAR "calendar/public" -#define FOLDER_PUBLIC_TASKS "tasks/public" - -/* IDs for user creatable items */ -#define CREATE_EVENT_ID "event" -#define CREATE_ALLDAY_EVENT_ID "allday-event" -#define CREATE_MEETING_ID "meeting" -#define CREATE_TASK_ID "task" - -char *evolution_dir = NULL; -EvolutionShellClient *global_shell_client = NULL; -extern ECompEditorRegistry *comp_editor_registry; - -static const EvolutionShellComponentFolderType folder_types[] = { - { FOLDER_CALENDAR, - "evolution-calendar.png", - N_("Calendar"), - N_("Folder containing appointments and events"), - TRUE, NULL, NULL }, - { FOLDER_PUBLIC_CALENDAR, - "evolution-calendar.png", - N_("Public Calendar"), - N_("Public folder containing appointments and events"), - FALSE, NULL, NULL }, - { FOLDER_TASKS, - "evolution-tasks.png", - N_("Tasks"), - N_("Folder containing to-do items"), - TRUE, NULL, NULL }, - { FOLDER_PUBLIC_TASKS, - "evolution-tasks.png", - N_("Public Tasks"), - N_("Public folder containing to-do items"), - FALSE, NULL, NULL }, - { NULL, NULL } -}; +#include "gnome-cal.h" +#include "migration.h" - - -static inline gboolean -type_is_calendar (const char *type) -{ - return !strcmp (type, FOLDER_CALENDAR) || - !strcmp (type, FOLDER_PUBLIC_CALENDAR); -} +#include "widgets/misc/e-source-selector.h" -static inline gboolean -type_is_tasks (const char *type) -{ - return !strcmp (type, FOLDER_TASKS) || - !strcmp (type, FOLDER_PUBLIC_TASKS); -} +#include <bonobo/bonobo-control.h> +#include <bonobo/bonobo-i18n.h> +#include <gal/util/e-util.h> -/* EvolutionShellComponent methods and signals. */ +#include <errno.h> -static EvolutionShellComponentResult -create_view (EvolutionShellComponent *shell_component, - const char *physical_uri, - const char *type, - const char *view_info, - BonoboControl **control_return, - void *closure) -{ - BonoboControl *control; - - if (type_is_calendar (type)) { - control = control_factory_new_control (); - if (!control) - return EVOLUTION_SHELL_COMPONENT_CORBAERROR; - } else if (type_is_tasks (type)) { - control = tasks_control_new (); - if (!control) - return EVOLUTION_SHELL_COMPONENT_CORBAERROR; - } else { - return EVOLUTION_SHELL_COMPONENT_UNSUPPORTEDTYPE; - } - bonobo_control_set_property (control, NULL, "folder_uri", TC_CORBA_string, physical_uri, NULL); - if (type_is_calendar (type) && *view_info) - bonobo_control_set_property (control, NULL, "view", TC_CORBA_string, view_info, NULL); +#define PARENT_TYPE bonobo_object_get_type () +static BonoboObjectClass *parent_class = NULL; - *control_return = control; - return EVOLUTION_SHELL_COMPONENT_OK; -} +struct _CalendarComponentPrivate { + char *config_directory; -static void -create_folder (EvolutionShellComponent *shell_component, - const char *physical_uri, - const char *type, - const GNOME_Evolution_ShellComponentListener listener, - void *closure) -{ - CORBA_Environment ev; - GnomeVFSURI *uri; + GConfClient *gconf_client; + ESourceList *source_list; +}; - CORBA_exception_init (&ev); - if (!type_is_calendar (type) && !type_is_tasks (type)) { - GNOME_Evolution_ShellComponentListener_notifyResult ( - listener, - GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, - &ev); - CORBA_exception_free (&ev); - return; - } +/* Utility functions. */ - uri = gnome_vfs_uri_new (physical_uri); - if (uri) { - /* we don't need to do anything */ - GNOME_Evolution_ShellComponentListener_notifyResult ( - listener, - GNOME_Evolution_ShellComponentListener_OK, &ev); - gnome_vfs_uri_unref (uri); - } - else { - GNOME_Evolution_ShellComponentListener_notifyResult ( - listener, - GNOME_Evolution_ShellComponentListener_INVALID_URI, - &ev); - } +static void +load_uri_for_source (ESource *source, BonoboControl *view_control) +{ + GnomeCalendar *gcal; + char *uri = e_source_get_uri (source); - CORBA_exception_free (&ev); + gcal = (GnomeCalendar *) bonobo_control_get_widget (view_control); + gnome_calendar_add_event_uri (gcal, uri); + g_free (uri); } -/* Asks the alarm daemon to stop monitoring the specified URI */ static void -stop_alarms (GnomeVFSURI *uri) +load_uri_for_selection (ESourceSelector *selector, BonoboControl *view_control) { - char *str_uri; - CORBA_Environment ev; - GNOME_Evolution_Calendar_AlarmNotify an; - - /* Activate the alarm notification service */ - - CORBA_exception_init (&ev); - an = bonobo_activation_activate_from_id ("OAFIID:GNOME_Evolution_Calendar_AlarmNotify", 0, NULL, &ev); - - if (BONOBO_EX (&ev)) { - g_message ("stop_alarms(): Could not activate the alarm notification service"); - CORBA_exception_free (&ev); - return; - } - CORBA_exception_free (&ev); - - /* Ask the service to remove the URI from its list of calendars */ - - str_uri = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE); - g_assert (str_uri != NULL); - - CORBA_exception_init (&ev); - GNOME_Evolution_Calendar_AlarmNotify_removeCalendar (an, str_uri, &ev); - g_free (str_uri); - - if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_AlarmNotify_InvalidURI)) { - g_message ("stop_alarms(): Invalid URI reported from the alarm notification service"); - } else if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_AlarmNotify_NotFound)) { - /* This is OK; the service may not have loaded that calendar */ - } else if (BONOBO_EX (&ev)) { - g_message ("stop_alarms(): Could not issue the removeCalendar request"); - } + GSList *selection, *l; - CORBA_exception_free (&ev); - - /* Get rid of the service */ - - CORBA_exception_init (&ev); - bonobo_object_release_unref (an, &ev); - if (BONOBO_EX (&ev)) - g_message ("stop_alarms(): Could not unref the alarm notification service"); - CORBA_exception_free (&ev); + selection = e_source_selector_get_selection (selector); + for (l = selection; l; l = l->next) { + ESource *selected_source = l->data; + + load_uri_for_source (selected_source, view_control); + } } +/* Callbacks. */ static void -remove_folder (EvolutionShellComponent *shell_component, - const char *physical_uri, - const char *type, - const GNOME_Evolution_ShellComponentListener listener, - void *closure) +source_selection_changed_callback (ESourceSelector *selector, + BonoboControl *view_control) { - GnomeVFSURI *dir_uri, *data_uri, *backup_uri; - GnomeVFSResult data_result, backup_result; - - /* check type */ - if (!type_is_calendar (type) && !type_is_tasks (type)) { - CORBA_Environment ev; - - CORBA_exception_init (&ev); - GNOME_Evolution_ShellComponentListener_notifyResult ( - listener, - GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, - &ev); - - if (BONOBO_EX (&ev)) - g_message ("remove_folder(): Could not notify the listener of " - "an unsupported folder type"); + + load_uri_for_selection (selector, view_control); +} - CORBA_exception_free (&ev); - return; - } +static void +primary_source_selection_changed_callback (ESourceSelector *selector, + BonoboControl *view_control) +{ + ESource *source; + GnomeCalendar *gcal; + ECalModel *model; + CalClient *client; - /* check URI */ - dir_uri = gnome_vfs_uri_new (physical_uri); - if (!dir_uri) { - CORBA_Environment ev; - - CORBA_exception_init (&ev); - GNOME_Evolution_ShellComponentListener_notifyResult ( - listener, - GNOME_Evolution_ShellComponentListener_INVALID_URI, - &ev); - CORBA_exception_free (&ev); + source = e_source_selector_peek_primary_selection (selector); + if (!source) return; - } - /* Compute the URIs of the appropriate files */ - - if (type_is_calendar (type)) { - data_uri = gnome_vfs_uri_append_file_name (dir_uri, "calendar.ics"); - backup_uri = gnome_vfs_uri_append_file_name (dir_uri, "calendar.ics~"); - } else if (type_is_tasks (type)) { - data_uri = gnome_vfs_uri_append_file_name (dir_uri, "tasks.ics"); - backup_uri = gnome_vfs_uri_append_file_name (dir_uri, "tasks.ics~"); - } else { - g_assert_not_reached (); + /* set the default client on the GnomeCalendar */ + gcal = (GnomeCalendar *) bonobo_control_get_widget (view_control); + if (!GNOME_IS_CALENDAR (gcal)) return; - } - - if (!data_uri || !backup_uri) { - CORBA_Environment ev; - - g_message ("remove_folder(): Could not generate the data/backup URIs"); - - CORBA_exception_init (&ev); - GNOME_Evolution_ShellComponentListener_notifyResult ( - listener, - GNOME_Evolution_ShellComponentListener_INVALID_URI, - &ev); - - if (BONOBO_EX (&ev)) - g_message ("remove_folder(): Could not notify the listener " - "of an invalid URI"); - - CORBA_exception_free (&ev); - - goto out; - } - - /* Ask the alarm daemon to stop monitoring this URI */ - - stop_alarms (data_uri); - - /* Delete the data and backup files; the shell will take care of the rest */ - - data_result = gnome_vfs_unlink_from_uri (data_uri); - backup_result = gnome_vfs_unlink_from_uri (backup_uri); - - if ((data_result == GNOME_VFS_OK || data_result == GNOME_VFS_ERROR_NOT_FOUND) - && (backup_result == GNOME_VFS_OK || backup_result == GNOME_VFS_ERROR_NOT_FOUND)) { - CORBA_Environment ev; - - CORBA_exception_init (&ev); - GNOME_Evolution_ShellComponentListener_notifyResult ( - listener, - GNOME_Evolution_ShellComponentListener_OK, - &ev); - - if (BONOBO_EX (&ev)) - g_message ("remove_folder(): Could not notify the listener about success"); - - CORBA_exception_free (&ev); - } else { - CORBA_Environment ev; - - CORBA_exception_init (&ev); - GNOME_Evolution_ShellComponentListener_notifyResult ( - listener, - GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED, - &ev); - - if (BONOBO_EX (&ev)) - g_message ("remove_folder(): Could not notify the listener about failure"); - - CORBA_exception_free (&ev); - } - out: - - gnome_vfs_uri_unref (dir_uri); - - if (data_uri) - gnome_vfs_uri_unref (data_uri); - - if (backup_uri) - gnome_vfs_uri_unref (backup_uri); + model = gnome_calendar_get_calendar_model (gcal); + client = e_cal_model_get_client_for_uri (model, e_source_get_uri (source)); + if (client) + gnome_calendar_set_default_client (gcal, client); } -static GNOME_Evolution_ShellComponentListener_Result -xfer_file (GnomeVFSURI *base_src_uri, - GnomeVFSURI *base_dest_uri, - const char *file_name, - int remove_source) -{ - GnomeVFSURI *src_uri, *dest_uri; - GnomeVFSHandle *hin, *hout; - GnomeVFSResult result; - GnomeVFSFileInfo file_info; - GnomeVFSFileSize size; - char *buffer; - - src_uri = gnome_vfs_uri_append_file_name (base_src_uri, file_name); - - result = gnome_vfs_open_uri (&hin, src_uri, GNOME_VFS_OPEN_READ); - if (result == GNOME_VFS_ERROR_NOT_FOUND) { - gnome_vfs_uri_unref (src_uri); - return GNOME_Evolution_ShellComponentListener_OK; /* No need to xfer anything. */ - } - if (result != GNOME_VFS_OK) { - gnome_vfs_uri_unref (src_uri); - return GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED; - } - - result = gnome_vfs_get_file_info_uri (src_uri, &file_info, GNOME_VFS_FILE_INFO_DEFAULT); - if (result != GNOME_VFS_OK) { - gnome_vfs_uri_unref (src_uri); - return GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED; - } - - dest_uri = gnome_vfs_uri_append_file_name (base_dest_uri, file_name); - - result = gnome_vfs_create_uri (&hout, dest_uri, GNOME_VFS_OPEN_WRITE, FALSE, 0600); - if (result != GNOME_VFS_OK) { - gnome_vfs_close (hin); - gnome_vfs_uri_unref (src_uri); - gnome_vfs_uri_unref (dest_uri); - return GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED; - } +/* GObject methods. */ - /* write source file to destination file */ - buffer = g_malloc (file_info.size); - result = gnome_vfs_read (hin, buffer, file_info.size, &size); - if (result != GNOME_VFS_OK) { - gnome_vfs_close (hin); - gnome_vfs_close (hout); - gnome_vfs_uri_unref (src_uri); - gnome_vfs_uri_unref (dest_uri); - g_free (buffer); - return GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED; - } +static void +impl_dispose (GObject *object) +{ + CalendarComponentPrivate *priv = CALENDAR_COMPONENT (object)->priv; - result = gnome_vfs_write (hout, buffer, file_info.size, &size); - if (result != GNOME_VFS_OK) { - gnome_vfs_close (hin); - gnome_vfs_close (hout); - gnome_vfs_uri_unref (src_uri); - gnome_vfs_uri_unref (dest_uri); - g_free (buffer); - return GNOME_Evolution_ShellComponentListener_PERMISSION_DENIED; + if (priv->source_list != NULL) { + g_object_unref (priv->source_list); + priv->source_list = NULL; } - if (remove_source) { - char *text_uri; - - /* Sigh, we have to do this as there is no gnome_vfs_unlink_uri(). :-( */ - - text_uri = gnome_vfs_uri_to_string (src_uri, GNOME_VFS_URI_HIDE_NONE); - result = gnome_vfs_unlink (text_uri); - g_free (text_uri); + if (priv->gconf_client != NULL) { + g_object_unref (priv->gconf_client); + priv->gconf_client = NULL; } - gnome_vfs_close (hin); - gnome_vfs_close (hout); - gnome_vfs_uri_unref (src_uri); - gnome_vfs_uri_unref (dest_uri); - g_free (buffer); - - return GNOME_Evolution_ShellComponentListener_OK; + (* G_OBJECT_CLASS (parent_class)->dispose) (object); } static void -xfer_folder (EvolutionShellComponent *shell_component, - const char *source_physical_uri, - const char *destination_physical_uri, - const char *type, - gboolean remove_source, - const GNOME_Evolution_ShellComponentListener listener, - void *closure) +impl_finalize (GObject *object) { - CORBA_Environment ev; - GnomeVFSURI *src_uri; - GnomeVFSURI *dest_uri; - GnomeVFSResult result; - char *filename, *backup_filename; - - CORBA_exception_init (&ev); - - /* check type */ - if (!type_is_calendar (type) && !type_is_tasks (type)) { - GNOME_Evolution_ShellComponentListener_notifyResult ( - listener, - GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, - &ev); - CORBA_exception_free (&ev); - return; - } - - /* check URIs */ - src_uri = gnome_vfs_uri_new (source_physical_uri); - dest_uri = gnome_vfs_uri_new (destination_physical_uri); - if (!src_uri || ! dest_uri) { - GNOME_Evolution_ShellComponentListener_notifyResult ( - listener, - GNOME_Evolution_ShellComponentListener_INVALID_URI, - &ev); - gnome_vfs_uri_unref (src_uri); - gnome_vfs_uri_unref (dest_uri); - CORBA_exception_free (&ev); - return; - } - - if (type_is_calendar (type)) { - filename = "calendar.ics"; - backup_filename = "calendar.ics~"; - } else if (type_is_tasks (type)) { - filename = "tasks.ics"; - backup_filename = "tasks.ics~"; - } else { - g_assert_not_reached (); - return; - } - - result = xfer_file (src_uri, dest_uri, filename, remove_source); - if (result == GNOME_Evolution_ShellComponentListener_OK) - result = xfer_file (src_uri, dest_uri, backup_filename, remove_source); - - GNOME_Evolution_ShellComponentListener_notifyResult (listener, result, &ev); + CalendarComponentPrivate *priv = CALENDAR_COMPONENT (object)->priv; - gnome_vfs_uri_unref (src_uri); - gnome_vfs_uri_unref (dest_uri); + g_free (priv->config_directory); + g_free (priv); - CORBA_exception_free (&ev); + (* G_OBJECT_CLASS (parent_class)->finalize) (object); } -static gboolean -request_quit (EvolutionShellComponent *shell_component, void *closure) -{ - return e_comp_editor_registry_close_all (comp_editor_registry); -} -static void -owner_set_cb (EvolutionShellComponent *shell_component, - EvolutionShellClient *shell_client, - const char *evolution_homedir, - gpointer user_data) -{ - if (evolution_dir) - g_free (evolution_dir); - evolution_dir = g_strdup (evolution_homedir); - global_shell_client = shell_client; -} +/* Evolution::Component CORBA methods. */ static void -owner_unset_cb (EvolutionShellComponent *shell_component, - gpointer user_data) +impl_createControls (PortableServer_Servant servant, + Bonobo_Control *corba_sidebar_control, + Bonobo_Control *corba_view_control, + CORBA_Environment *ev) { - global_shell_client = NULL; -} + CalendarComponent *calendar_component = CALENDAR_COMPONENT (bonobo_object_from_servant (servant)); + GtkWidget *selector; + GtkWidget *selector_scrolled_window; + BonoboControl *sidebar_control; + BonoboControl *view_control; -/* Computes the final URI for a calendar component */ -static char * -get_data_uri (const char *uri, CalComponentVType vtype) -{ - if (uri) { - if (*uri != '/' && strncmp (uri, "file:", 5) != 0) - return g_strdup (uri); - - if (vtype == CAL_COMPONENT_EVENT) - return cal_util_expand_uri ((char *) uri, FALSE); - else if (vtype == CAL_COMPONENT_TODO) - return cal_util_expand_uri ((char *) uri, TRUE); - else - g_assert_not_reached (); - } else { - if (vtype == CAL_COMPONENT_EVENT) - return g_concat_dir_and_file (g_get_home_dir (), - "evolution/local/Calendar/calendar.ics"); - else if (vtype == CAL_COMPONENT_TODO) - return g_concat_dir_and_file (g_get_home_dir (), - "evolution/local/Tasks/tasks.ics"); - else - g_assert_not_reached (); - } + selector = e_source_selector_new (calendar_component->priv->source_list); + gtk_widget_show (selector); - return NULL; -} + selector_scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_container_add (GTK_CONTAINER (selector_scrolled_window), selector); + gtk_widget_show (selector_scrolled_window); -/* Creates a calendar component at a specified URI. If the URI is NULL then it - * uses the default folder for that type of component. - */ -static void -create_component (const char *uri, GNOME_Evolution_Calendar_CompEditorFactory_CompEditorMode type) -{ - char *real_uri; - CORBA_Environment ev; - GNOME_Evolution_Calendar_CompEditorFactory factory; - CalComponentVType vtype; - - switch (type) { - case GNOME_Evolution_Calendar_CompEditorFactory_EDITOR_MODE_EVENT: - case GNOME_Evolution_Calendar_CompEditorFactory_EDITOR_MODE_ALLDAY_EVENT: - case GNOME_Evolution_Calendar_CompEditorFactory_EDITOR_MODE_MEETING: - vtype = CAL_COMPONENT_EVENT; - break; - case GNOME_Evolution_Calendar_CompEditorFactory_EDITOR_MODE_TODO: - vtype = CAL_COMPONENT_TODO; - break; - default: - g_assert_not_reached (); - return; - } + sidebar_control = bonobo_control_new (selector_scrolled_window); - real_uri = get_data_uri (uri, vtype); + view_control = control_factory_new_control (); - /* Get the factory */ + g_signal_connect_object (selector, "selection_changed", + G_CALLBACK (source_selection_changed_callback), + G_OBJECT (view_control), 0); + g_signal_connect_object (selector, "primary_selection_changed", + G_CALLBACK (primary_source_selection_changed_callback), + G_OBJECT (view_control), 0); - CORBA_exception_init (&ev); - factory = bonobo_activation_activate_from_id ("OAFIID:GNOME_Evolution_Calendar_CompEditorFactory", - 0, NULL, &ev); + load_uri_for_selection (E_SOURCE_SELECTOR (selector), view_control); - if (BONOBO_EX (&ev)) { - g_message ("create_component(): Could not activate the component editor factory"); - CORBA_exception_free (&ev); - g_free (real_uri); - return; - } - CORBA_exception_free (&ev); + *corba_sidebar_control = CORBA_Object_duplicate (BONOBO_OBJREF (sidebar_control), ev); + *corba_view_control = CORBA_Object_duplicate (BONOBO_OBJREF (view_control), ev); +} - /* Create the item */ - CORBA_exception_init (&ev); - GNOME_Evolution_Calendar_CompEditorFactory_editNew (factory, real_uri, type, &ev); +/* Initialization. */ - if (BONOBO_EX (&ev)) - g_message ("create_component(): Exception while creating the component"); +static void +calendar_component_class_init (CalendarComponentClass *class) +{ + POA_GNOME_Evolution_Component__epv *epv = &class->epv; + GObjectClass *object_class = G_OBJECT_CLASS (class); - CORBA_exception_free (&ev); - g_free (real_uri); + parent_class = g_type_class_peek_parent (class); - /* Get rid of the factory */ + epv->createControls = impl_createControls; - CORBA_exception_init (&ev); - bonobo_object_release_unref (factory, &ev); - if (BONOBO_EX (&ev)) - g_message ("create_component(): Could not unref the calendar component factory"); + object_class->dispose = impl_dispose; + object_class->finalize = impl_finalize; - CORBA_exception_free (&ev); + epv->createControls = impl_createControls; } -/* Callback used when we must create a user-creatable item */ static void -sc_user_create_new_item_cb (EvolutionShellComponent *shell_component, - const char *id, - const char *parent_folder_physical_uri, - const char *parent_folder_type) +calendar_component_init (CalendarComponent *component) { - char *tmp_uri; - - if (strcmp (id, CREATE_EVENT_ID) == 0) { - if (type_is_calendar (parent_folder_type)) - create_component (parent_folder_physical_uri, - GNOME_Evolution_Calendar_CompEditorFactory_EDITOR_MODE_EVENT); - else { - tmp_uri = calendar_config_default_calendar_folder (); - create_component (tmp_uri, - GNOME_Evolution_Calendar_CompEditorFactory_EDITOR_MODE_EVENT); - g_free (tmp_uri); - } - } else if (strcmp (id, CREATE_ALLDAY_EVENT_ID) == 0) { - if (type_is_calendar (parent_folder_type)) - create_component (parent_folder_physical_uri, - GNOME_Evolution_Calendar_CompEditorFactory_EDITOR_MODE_ALLDAY_EVENT); - else { - tmp_uri = calendar_config_default_calendar_folder (); - create_component (tmp_uri, - GNOME_Evolution_Calendar_CompEditorFactory_EDITOR_MODE_ALLDAY_EVENT); - g_free (tmp_uri); - } - } else if (strcmp (id, CREATE_MEETING_ID) == 0) { - if (type_is_calendar (parent_folder_type)) - create_component (parent_folder_physical_uri, - GNOME_Evolution_Calendar_CompEditorFactory_EDITOR_MODE_MEETING); - else { - tmp_uri = calendar_config_default_calendar_folder (); - create_component (tmp_uri, - GNOME_Evolution_Calendar_CompEditorFactory_EDITOR_MODE_MEETING); - g_free (tmp_uri); + CalendarComponentPrivate *priv; + GSList *groups; + + priv = g_new0 (CalendarComponentPrivate, 1); + + priv->config_directory = g_build_filename (g_get_home_dir (), + ".evolution", "calendar", "config", + NULL); + + /* EPFIXME: Should use a custom one instead? Also we should add + * calendar_component_peek_gconf_client(). */ + priv->gconf_client = gconf_client_get_default (); + + priv->source_list = e_source_list_new_for_gconf (priv->gconf_client, + "/apps/evolution/calendar/sources"); + + /* create default calendars if there are no groups */ + groups = e_source_list_peek_groups (priv->source_list); + if (!groups) { + ESourceGroup *group; + ESource *source; + char *base_uri, *new_dir; + + /* create the source group */ + base_uri = g_build_filename (g_get_home_dir (), + "/.evolution/calendar/local/OnThisComputer/", + NULL); + group = e_source_group_new (_("On This Computer"), base_uri); + e_source_list_add_group (priv->source_list, group, -1); + + /* migrate calendars from older setup */ + if (!migrate_old_calendars (group)) { + /* create default calendars */ + new_dir = g_build_filename (base_uri, "Personal/", NULL); + if (!e_mkdir_hier (new_dir, 0700)) { + source = e_source_new (_("Personal"), "Personal"); + e_source_group_add_source (group, source, -1); + } + g_free (new_dir); + + new_dir = g_build_filename (base_uri, "Work/", NULL); + if (!e_mkdir_hier (new_dir, 0700)) { + source = e_source_new (_("Work"), "Work"); + e_source_group_add_source (group, source, -1); + } + g_free (new_dir); } - } else if (strcmp (id, CREATE_TASK_ID) == 0) { - if (type_is_tasks (parent_folder_type)) - create_component (parent_folder_physical_uri, - GNOME_Evolution_Calendar_CompEditorFactory_EDITOR_MODE_TODO); - else { - tmp_uri = calendar_config_default_tasks_folder (); - create_component (tmp_uri, - GNOME_Evolution_Calendar_CompEditorFactory_EDITOR_MODE_TODO); - g_free (tmp_uri); - } - } else - g_assert_not_reached (); -} - -/* The factory function. */ - -static void -add_creatable_item (EvolutionShellComponent *shell_component, - const char *id, - const char *description, - const char *menu_description, - const char *tooltip, - const char *folder_type, - char menu_shortcut, - const char *icon_name) -{ - char *icon_path; - GdkPixbuf *icon; - - if (icon_name == NULL) { - icon_path = NULL; - icon = NULL; - } else { - icon_path = g_concat_dir_and_file (EVOLUTION_IMAGESDIR, icon_name); - icon = gdk_pixbuf_new_from_file (icon_path, NULL); + g_free (base_uri); } - evolution_shell_component_add_user_creatable_item (shell_component, - id, - description, - menu_description, - tooltip, - folder_type, - menu_shortcut, - icon); - - if (icon != NULL) - gdk_pixbuf_unref (icon); - g_free (icon_path); + component->priv = priv; } -static BonoboObject * -create_object (void) -{ - EvolutionShellComponent *shell_component; - CalendarOfflineHandler *offline_handler; - - shell_component = evolution_shell_component_new (folder_types, - NULL, - create_view, - create_folder, - remove_folder, - xfer_folder, - NULL, /* populate_folder_context_menu_fn */ - NULL, /* unpopulate_folder_context_menu_fn */ - NULL, /* get_dnd_selection_fn */ - request_quit, - NULL /* closure */); - - /* Offline handler */ - offline_handler = calendar_offline_handler_new (); - bonobo_object_add_interface (BONOBO_OBJECT (shell_component), - BONOBO_OBJECT (offline_handler)); - - g_signal_connect (shell_component, "owner_set", G_CALLBACK (owner_set_cb), NULL); - g_signal_connect (shell_component, "owner_unset", G_CALLBACK (owner_unset_cb), NULL); - - /* User creatable items */ - add_creatable_item (shell_component, CREATE_EVENT_ID, - _("New appointment"), _("_Appointment"), - _("Create a new appointment"), - FOLDER_CALENDAR, 'a', "new_appointment.xpm"); +/* Public API. */ - add_creatable_item (shell_component, CREATE_MEETING_ID, - _("New meeting"), _("M_eeting"), - _("Create a new meeting request"), - FOLDER_CALENDAR, 'e', "meeting-request-16.png"); - - add_creatable_item (shell_component, CREATE_TASK_ID, - _("New task"), _("_Task"), - _("Create a new task"), - FOLDER_TASKS, 't', "new_task-16.png"); +CalendarComponent * +calendar_component_peek (void) +{ + static CalendarComponent *component = NULL; - add_creatable_item (shell_component, CREATE_ALLDAY_EVENT_ID, - _("New All Day Appointment"), _("All _Day Appointment"), - _("Create a new all-day appointment"), - FOLDER_CALENDAR, 'd', "new_all_day_event.png"); + if (component == NULL) { + component = g_object_new (calendar_component_get_type (), NULL); - g_signal_connect (shell_component, "user_create_new_item", - G_CALLBACK (sc_user_create_new_item_cb), NULL); + if (e_mkdir_hier (calendar_component_peek_config_directory (component), 0777) != 0) { + g_warning ("Cannot create directory %s: %s", + calendar_component_peek_config_directory (component), + g_strerror (errno)); + g_object_unref (component); + component = NULL; + } + } - return BONOBO_OBJECT (shell_component); + return component; } - -BonoboObject * -calendar_component_get_object (void) +const char * +calendar_component_peek_config_directory (CalendarComponent *component) { - static BonoboObject *object = NULL; + return component->priv->config_directory; +} - if (object != NULL) { - bonobo_object_ref (BONOBO_OBJECT (object)); - } else { - object = create_object (); - g_object_add_weak_pointer (G_OBJECT (object), (void *) &object); - } - return object; -} +BONOBO_TYPE_FUNC_FULL (CalendarComponent, GNOME_Evolution_Component, PARENT_TYPE, calendar_component) diff --git a/calendar/gui/calendar-component.h b/calendar/gui/calendar-component.h index 2d94920adc..96630add5f 100644 --- a/calendar/gui/calendar-component.h +++ b/calendar/gui/calendar-component.h @@ -1,7 +1,7 @@ /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* component-factory.h +/* calendar-component.h * - * Copyright (C) 2000, 2001, 2002, 2003 Ximian, Inc. + * Copyright (C) 2003 Ettore Perazzoli * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public @@ -20,13 +20,47 @@ * Author: Ettore Perazzoli <ettore@ximian.com> */ -#ifndef _COMPONENT_FACTORY_H_ -#define _COMPONENT_FACTORY_H_ +#ifndef _CALENDAR_COMPONENT_H_ +#define _CALENDAR_COMPONENT_H_ + #include <bonobo/bonobo-object.h> -extern char *evolution_dir; +#include "Evolution.h" +#include "e-util/e-source-list.h" + + +#define CALENDAR_TYPE_COMPONENT (calendar_component_get_type ()) +#define CALENDAR_COMPONENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALENDAR_TYPE_COMPONENT, CalendarComponent)) +#define CALENDAR_COMPONENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CALENDAR_TYPE_COMPONENT, CalendarComponentClass)) +#define CALENDAR_IS_COMPONENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALENDAR_TYPE_COMPONENT)) +#define CALENDAR_IS_COMPONENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), CALENDAR_TYPE_COMPONENT)) + + +typedef struct _CalendarComponent CalendarComponent; +typedef struct _CalendarComponentPrivate CalendarComponentPrivate; +typedef struct _CalendarComponentClass CalendarComponentClass; + +struct _CalendarComponent { + BonoboObject parent; + + CalendarComponentPrivate *priv; +}; + +struct _CalendarComponentClass { + BonoboObjectClass parent_class; + + POA_GNOME_Evolution_Component__epv epv; +}; + + +GType calendar_component_get_type (void); + +CalendarComponent *calendar_component_peek (void); + +const char *calendar_component_peek_config_directory (CalendarComponent *component); + +ESourceList *calendar_component_peek_source_list (CalendarComponent *component); -BonoboObject *calendar_component_get_object (void); -#endif /* _COMPONENT_FACTORY_H_ */ +#endif /* _CALENDAR_COMPONENT_H_ */ diff --git a/calendar/gui/calendar-offline-handler.c b/calendar/gui/calendar-offline-handler.c index 458f951d9a..ff30299746 100644 --- a/calendar/gui/calendar-offline-handler.c +++ b/calendar/gui/calendar-offline-handler.c @@ -29,6 +29,7 @@ #include <gtk/gtkmain.h> #include <gtk/gtksignal.h> #include <bonobo/bonobo-exception.h> +#include <bonobo/bonobo-i18n.h> #include <gal/util/e-util.h> #include "e-util/e-url.h" #include <cal-client/cal-client.h> @@ -180,13 +181,16 @@ backend_go_offline (gpointer data, gpointer user_data) char *uri = data; CalClient *client; gboolean success; + GError *error = NULL; - client = cal_client_new (); + client = cal_client_new (uri, CALOBJ_TYPE_ANY); g_signal_connect (client, "cal_opened", G_CALLBACK (backend_cal_opened_offline), offline_handler); - success = cal_client_open_calendar (client, uri, TRUE); + success = cal_client_open (client, TRUE, &error); if (!success) { + g_warning (_("backend_go_offline(): %s"), error->message); update_offline (offline_handler); g_object_unref (client); + g_error_free (error); return; } } @@ -198,13 +202,16 @@ backend_go_online (gpointer data, gpointer user_data) char *uri = data; CalClient *client; gboolean success; + GError *error = NULL; - client = cal_client_new (); + client = cal_client_new (uri, CALOBJ_TYPE_ANY); g_signal_connect (G_OBJECT (client), "cal_opened", G_CALLBACK (backend_cal_opened_online), offline_handler); - success = cal_client_open_calendar (client, uri, TRUE); + success = cal_client_open (client, TRUE, &error); if (!success) { + g_warning (_("backend_go_online(): %s"), error->message); g_object_unref (G_OBJECT (client)); + g_error_free (error); return; } } @@ -319,7 +326,8 @@ calendar_offline_handler_init (CalendarOfflineHandler *offline_handler) priv = g_new (CalendarOfflineHandlerPrivate, 1); offline_handler->priv = priv; - priv->client = cal_client_new (); + /* FIXME: what URI to use? */ + priv->client = cal_client_new ("", CALOBJ_TYPE_ANY); priv->listener_interface = CORBA_OBJECT_NIL; priv->is_offline = FALSE; } diff --git a/calendar/gui/comp-editor-factory.c b/calendar/gui/comp-editor-factory.c index f76e0d4f03..7b7dcb4c87 100644 --- a/calendar/gui/comp-editor-factory.c +++ b/calendar/gui/comp-editor-factory.c @@ -241,39 +241,26 @@ edit_existing (OpenClient *oc, const char *uid) { CalComponent *comp; icalcomponent *icalcomp; - CalClientGetStatus status; CompEditor *editor; CalComponentVType vtype; g_assert (oc->open); /* Get the object */ + if (!cal_client_get_object (oc->client, uid, NULL, &icalcomp, NULL)) { + /* FIXME Better error handling */ + g_warning (G_STRLOC ": Syntax error while getting component `%s'", uid); - status = cal_client_get_object (oc->client, uid, &icalcomp); - - switch (status) { - case CAL_CLIENT_GET_SUCCESS: - comp = cal_component_new (); - if (!cal_component_set_icalcomponent (comp, icalcomp)) { - g_object_unref (comp); - icalcomponent_free (icalcomp); - return; - } - break; - - case CAL_CLIENT_GET_NOT_FOUND: - /* The object disappeared from the server */ - return; - - case CAL_CLIENT_GET_SYNTAX_ERROR: - g_message ("edit_exiting(): Syntax error while getting component `%s'", uid); return; - - default: - g_assert_not_reached (); + } + + comp = cal_component_new (); + if (!cal_component_set_icalcomponent (comp, icalcomp)) { + g_object_unref (comp); + icalcomponent_free (icalcomp); return; } - + /* Create the appropriate type of editor */ vtype = cal_component_get_vtype (comp); @@ -405,13 +392,15 @@ resolve_pending_requests (OpenClient *oc) factory = oc->factory; priv = factory->priv; - g_assert (oc->pending != NULL); + if (!oc->pending) + return; /* Set the default timezone in the backend. */ location = calendar_config_get_timezone (); zone = icaltimezone_get_builtin_timezone (location); if (zone) - cal_client_set_default_timezone (oc->client, zone); + /* FIXME Error handling? */ + cal_client_set_default_timezone (oc->client, zone, NULL); for (l = oc->pending; l; l = l->next) { Request *request; @@ -501,10 +490,11 @@ open_client (CompEditorFactory *factory, const char *uristr) CompEditorFactoryPrivate *priv; CalClient *client; OpenClient *oc; + GError *error = NULL; priv = factory->priv; - client = cal_client_new (); + client = cal_client_new (uristr, CALOBJ_TYPE_ANY); if (!client) return NULL; @@ -522,10 +512,12 @@ open_client (CompEditorFactory *factory, const char *uristr) g_hash_table_insert (priv->uri_client_hash, oc->uri, oc); - if (!cal_client_open_calendar (oc->client, uristr, FALSE)) { + if (!cal_client_open (oc->client, FALSE, &error)) { + g_warning (_("open_client(): %s"), error->message); g_free (oc->uri); g_object_unref (oc->client); g_free (oc); + g_error_free (error); return NULL; } diff --git a/calendar/gui/comp-util.c b/calendar/gui/comp-util.c index 28bc66bd54..aceff667c2 100644 --- a/calendar/gui/comp-util.c +++ b/calendar/gui/comp-util.c @@ -95,7 +95,6 @@ cal_comp_util_compare_event_timezones (CalComponent *comp, CalClient *client, icaltimezone *zone) { - CalClientGetStatus status; CalComponentDateTime start_datetime, end_datetime; const char *tzid; gboolean retval = FALSE; @@ -143,10 +142,8 @@ cal_comp_util_compare_event_timezones (CalComponent *comp, /* If the TZIDs differ, we have to compare the UTC offsets of the start and end times, using their own timezones and the given timezone. */ - status = cal_client_get_timezone (client, - start_datetime.tzid, - &start_zone); - if (status != CAL_CLIENT_GET_SUCCESS) + if (!cal_client_get_timezone (client, start_datetime.tzid, + &start_zone, NULL)) goto out; if (start_datetime.value) { @@ -160,10 +157,8 @@ cal_comp_util_compare_event_timezones (CalComponent *comp, goto out; } - status = cal_client_get_timezone (client, - end_datetime.tzid, - &end_zone); - if (status != CAL_CLIENT_GET_SUCCESS) + if (!cal_client_get_timezone (client, end_datetime.tzid, + &end_zone, NULL)) goto out; if (end_datetime.value) { @@ -210,8 +205,8 @@ gboolean cal_comp_is_on_server (CalComponent *comp, CalClient *client) { const char *uid; - CalClientGetStatus status; icalcomponent *icalcomp; + GError *error = NULL; g_return_val_if_fail (comp != NULL, FALSE); g_return_val_if_fail (IS_CAL_COMPONENT (comp), FALSE); @@ -226,24 +221,15 @@ cal_comp_is_on_server (CalComponent *comp, CalClient *client) */ cal_component_get_uid (comp, &uid); - status = cal_client_get_object (client, uid, &icalcomp); - - switch (status) { - case CAL_CLIENT_GET_SUCCESS: + if (cal_client_get_object (client, uid, NULL, &icalcomp, &error)) { icalcomponent_free (icalcomp); - return TRUE; - case CAL_CLIENT_GET_SYNTAX_ERROR: - g_message ("confirm_delete_empty_appointment(): Syntax error when getting " - "object `%s'", - uid); return TRUE; + } - case CAL_CLIENT_GET_NOT_FOUND: - return FALSE; - - default: - g_assert_not_reached (); + if (error) { + g_warning ("cal_comp_is_on_server(): %s", error->message); + g_error_free (error); } return FALSE; @@ -268,7 +254,7 @@ cal_comp_event_new_with_defaults (CalClient *client) icalproperty *icalprop; CalAlarmTrigger trigger; - if (cal_client_get_default_object (client, CALOBJ_TYPE_EVENT, &icalcomp) != CAL_CLIENT_GET_SUCCESS) + if (!cal_client_get_default_object (client, &icalcomp, NULL)) return NULL; comp = cal_component_new (); @@ -334,8 +320,16 @@ cal_comp_task_new_with_defaults (CalClient *client) CalComponent *comp; icalcomponent *icalcomp; - if (cal_client_get_default_object (client, CALOBJ_TYPE_TODO, &icalcomp) != CAL_CLIENT_GET_SUCCESS) + if (!cal_client_get_default_object (client, &icalcomp, NULL)) + return NULL; + + comp = cal_component_new (); + if (!cal_component_set_icalcomponent (comp, icalcomp)) { + g_object_unref (comp); + icalcomponent_free (icalcomp); + return NULL; + } comp = cal_component_new (); if (!cal_component_set_icalcomponent (comp, icalcomp)) { diff --git a/calendar/gui/control-factory.c b/calendar/gui/control-factory.c index 191a8d85ea..7adc5e83df 100644 --- a/calendar/gui/control-factory.c +++ b/calendar/gui/control-factory.c @@ -69,8 +69,11 @@ get_prop (BonoboPropertyBag *bag, CORBA_Environment *ev, gpointer user_data) { - GnomeCalendar *gcal = user_data; + GnomeCalendar *gcal; const char *uri; + BonoboControl *control = user_data; + + gcal = (GnomeCalendar *) bonobo_control_get_widget (control); switch (arg_id) { @@ -96,6 +99,7 @@ get_prop (BonoboPropertyBag *bag, case GNOME_CAL_LIST_VIEW: BONOBO_ARG_SET_STRING (arg, "list"); break; + default: } break; @@ -104,7 +108,6 @@ get_prop (BonoboPropertyBag *bag, } } - static void set_prop (BonoboPropertyBag *bag, const BonoboArg *arg, @@ -112,14 +115,19 @@ set_prop (BonoboPropertyBag *bag, CORBA_Environment *ev, gpointer user_data) { - GnomeCalendar *gcal = user_data; + GnomeCalendar *gcal; char *string; GnomeCalendarViewType view; + BonoboControl *control = user_data; + + gcal = (GnomeCalendar *) bonobo_control_get_widget (control); switch (arg_id) { case PROPERTY_CALENDAR_URI_IDX: string = BONOBO_ARG_GET_STRING (arg); - if (!gnome_calendar_open (gcal, string)) { + if (gnome_calendar_add_event_uri (gcal, string)) { + calendar_control_sensitize_calendar_commands (control, gcal, TRUE); + } else { char *msg; msg = g_strdup_printf (_("Could not open the folder in '%s'"), string); @@ -161,7 +169,7 @@ calendar_properties_init (GnomeCalendar *gcal, BonoboControl *control) { BonoboPropertyBag *pbag; - pbag = bonobo_property_bag_new (get_prop, set_prop, gcal); + pbag = bonobo_property_bag_new (get_prop, set_prop, control); bonobo_property_bag_add (pbag, PROPERTY_CALENDAR_URI, diff --git a/calendar/gui/control-factory.h b/calendar/gui/control-factory.h index f599f7b3b8..bab1611c03 100644 --- a/calendar/gui/control-factory.h +++ b/calendar/gui/control-factory.h @@ -23,6 +23,8 @@ #ifndef _CONTROL_FACTORY_H_ #define _CONTROL_FACTORY_H_ +#include <bonobo/bonobo-control.h> + BonoboControl *control_factory_new_control (void); #endif /* _CONTROL_FACTORY_H_ */ diff --git a/calendar/gui/dialogs/Makefile.am b/calendar/gui/dialogs/Makefile.am index 2466ffaa14..84424f8cc0 100644 --- a/calendar/gui/dialogs/Makefile.am +++ b/calendar/gui/dialogs/Makefile.am @@ -61,6 +61,8 @@ libcal_dialogs_la_SOURCES = \ event-page.h \ meeting-page.c \ meeting-page.h \ + new-calendar.c \ + new-calendar.h \ recurrence-page.c \ recurrence-page.h \ recur-comp.c \ @@ -85,6 +87,7 @@ glade_DATA = \ e-delegate-dialog.glade \ event-page.glade \ meeting-page.glade \ + new-calendar.glade \ recurrence-page.glade \ schedule-page.glade \ task-details-page.glade \ diff --git a/calendar/gui/dialogs/alarm-options.c b/calendar/gui/dialogs/alarm-options.c index ef13b78b13..b105dc3c23 100644 --- a/calendar/gui/dialogs/alarm-options.c +++ b/calendar/gui/dialogs/alarm-options.c @@ -39,7 +39,7 @@ #include <bonobo/bonobo-widget.h> #include <libgnomeui/gnome-file-entry.h> #include <glade/glade.h> -#include <ebook/e-destination.h> +#include <addressbook/util/eab-destination.h> #include "Evolution-Addressbook-SelectNames.h" #include "e-util/e-dialog-widgets.h" #include "alarm-options.h" @@ -307,7 +307,7 @@ alarm_to_malarm_widgets (Dialog *dialog, CalComponentAlarm *alarm) CalComponentText description; GtkTextBuffer *text_buffer; GSList *attendee_list, *l; - EDestination **destv; + EABDestination **destv; int len, i; /* Recipients */ @@ -315,22 +315,22 @@ alarm_to_malarm_widgets (Dialog *dialog, CalComponentAlarm *alarm) len = g_slist_length (attendee_list); if (len <= 0) { - destv = g_new0 (EDestination *, 2); - destv[0] = e_destination_new (); - e_destination_set_email (destv[0], dialog->email); + destv = g_new0 (EABDestination *, 2); + destv[0] = eab_destination_new (); + eab_destination_set_email (destv[0], dialog->email); destv[1] = NULL; len = 1; } else { - destv = g_new0 (EDestination *, len + 1); + destv = g_new0 (EABDestination *, len + 1); for (l = attendee_list, i = 0; l != NULL; l = l->next, i++) { CalComponentAttendee *a = l->data; - EDestination *dest; + EABDestination *dest; - dest = e_destination_new (); + dest = eab_destination_new (); if (a->cn != NULL && *a->cn) - e_destination_set_name (dest, a->cn); + eab_destination_set_name (dest, a->cn); if (a->value != NULL && *a->value) - e_destination_set_email (dest, a->value); + eab_destination_set_email (dest, a->value); destv[i] = dest; } @@ -338,7 +338,7 @@ alarm_to_malarm_widgets (Dialog *dialog, CalComponentAlarm *alarm) } bonobo_widget_set_property (BONOBO_WIDGET (dialog->malarm_addresses), - "destinations", e_destination_exportv (destv), NULL); + "destinations", eab_destination_exportv (destv), NULL); for (i = 0; i < len; i++) g_object_unref (GTK_OBJECT (destv[i])); @@ -617,7 +617,7 @@ malarm_widgets_to_alarm (Dialog *dialog, CalComponentAlarm *alarm) char *str; CalComponentText description; GSList *attendee_list = NULL; - EDestination **destv; + EABDestination **destv; GtkTextBuffer *text_buffer; GtkTextIter text_iter_start, text_iter_end; icalcomponent *icalcomp; @@ -627,18 +627,18 @@ malarm_widgets_to_alarm (Dialog *dialog, CalComponentAlarm *alarm) /* Attendees */ bonobo_widget_get_property (BONOBO_WIDGET (dialog->malarm_addresses), "destinations", TC_CORBA_string, &str, NULL); - destv = e_destination_importv (str); + destv = eab_destination_importv (str); g_free (str); for (i = 0; destv[i] != NULL; i++) { - EDestination *dest; + EABDestination *dest; CalComponentAttendee *a; dest = destv[i]; a = g_new0 (CalComponentAttendee, 1); - a->value = e_destination_get_email (dest); - a->cn = e_destination_get_name (dest); + a->value = eab_destination_get_email (dest); + a->cn = eab_destination_get_name (dest); attendee_list = g_slist_append (attendee_list, a); } @@ -646,7 +646,7 @@ malarm_widgets_to_alarm (Dialog *dialog, CalComponentAlarm *alarm) cal_component_alarm_set_attendee_list (alarm, attendee_list); cal_component_free_attendee_list (attendee_list); - e_destination_freev (destv); + eab_destination_freev (destv); /* Description */ text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dialog->dalarm_description)); diff --git a/calendar/gui/e-cal-model-calendar.c b/calendar/gui/e-cal-model-calendar.c index 82de4e6d5a..593d342e70 100644 --- a/calendar/gui/e-cal-model-calendar.c +++ b/calendar/gui/e-cal-model-calendar.c @@ -129,7 +129,7 @@ get_dtend (ECalModelComponent *comp_data) /* FIXME: handle errors */ cal_client_get_timezone (comp_data->client, icaltime_get_tzid (tt_end), - &zone); + &zone, NULL); comp_data->dtend->zone = zone; } @@ -308,8 +308,12 @@ ecmc_set_value_at (ETableModel *etm, int col, int row, const void *value) break; } - if (cal_client_update_objects (comp_data->client, comp_data->icalcomp) != CAL_CLIENT_RESULT_SUCCESS) - g_message ("ecmc_set_value_at(): Could not update the object!"); + /* FIXME ask about mod type */ + if (!cal_client_modify_object (comp_data->client, comp_data->icalcomp, CALOBJ_MOD_ALL, NULL)) { + g_warning (G_STRLOC ": Could not modify the object!"); + + /* FIXME Show error dialog */ + } } static gboolean diff --git a/calendar/gui/e-cal-model-tasks.c b/calendar/gui/e-cal-model-tasks.c index 6bca52586c..76e2e140f3 100644 --- a/calendar/gui/e-cal-model-tasks.c +++ b/calendar/gui/e-cal-model-tasks.c @@ -223,7 +223,7 @@ get_completed (ECalModelComponent *comp_data) /* FIXME: handle errors */ cal_client_get_timezone (comp_data->client, icaltime_get_tzid (tt_completed), - &zone); + &zone, NULL); comp_data->completed->zone = zone; } @@ -253,7 +253,7 @@ get_due (ECalModelComponent *comp_data) /* FIXME: handle errors */ cal_client_get_timezone (comp_data->client, icaltime_get_tzid (tt_due), - &zone); + &zone, NULL); comp_data->due->zone = zone; } @@ -399,7 +399,7 @@ get_due_status (ECalModelTasks *model, ECalModelComponent *comp_data) /* Get the current time in the same timezone as the DUE date.*/ status = cal_client_get_timezone (comp_data->client, icaltime_get_tzid (due_tt), - &zone); + &zone, NULL); if (status != CAL_CLIENT_GET_SUCCESS) return E_CAL_MODEL_TASKS_DUE_FUTURE; @@ -756,8 +756,12 @@ ecmt_set_value_at (ETableModel *etm, int col, int row, const void *value) break; } - if (cal_client_update_objects (comp_data->client, comp_data->icalcomp) != CAL_CLIENT_RESULT_SUCCESS) - g_message ("ecmt_set_value_at(): Could not update the object!"); + /* FIXME ask about mod type */ + if (!cal_client_modify_object (comp_data->client, comp_data->icalcomp, CALOBJ_MOD_ALL, NULL)) { + g_warning (G_STRLOC ": Could not modify the object!"); + + /* FIXME Show error dialog */ + } } static gboolean diff --git a/calendar/gui/e-cal-model.c b/calendar/gui/e-cal-model.c index 1c231f9c72..c8b706c66e 100644 --- a/calendar/gui/e-cal-model.c +++ b/calendar/gui/e-cal-model.c @@ -41,6 +41,9 @@ struct _ECalModelPrivate { /* The list of clients we are managing. Each element is of type ECalModelClient */ GList *clients; + /* The default client in the list */ + CalClient *default_client; + /* Array for storing the objects. Each element is of type ECalModelComponent */ GPtrArray *objects; @@ -352,7 +355,7 @@ get_dtstart (ECalModel *model, ECalModelComponent *comp_data) /* FIXME: handle errors */ cal_client_get_timezone (comp_data->client, icaltime_get_tzid (tt_start), - &zone); + &zone, NULL); comp_data->dtstart->zone = zone; } @@ -609,8 +612,12 @@ ecm_set_value_at (ETableModel *etm, int col, int row, const void *value) break; } - if (cal_client_update_objects (comp_data->client, comp_data->icalcomp) != CAL_CLIENT_RESULT_SUCCESS) - g_message ("ecm_set_value_at(): Could not update the object!"); + /* FIXME ask about mod type */ + if (!cal_client_modify_object (comp_data->client, comp_data->icalcomp, CALOBJ_MOD_ALL, NULL)) { + g_warning (G_STRLOC ": Could not modify the object!"); + + /* FIXME Show error dialog */ + } } static gboolean @@ -673,7 +680,10 @@ ecm_append_row (ETableModel *etm, ETableModel *source, int row) model_class->fill_component_from_model (model, &comp_data, source_model, row); } - if (cal_client_update_objects (comp_data.client, comp_data.icalcomp) != CAL_CLIENT_RESULT_SUCCESS) { + + if (!cal_client_create_object (comp_data.client, comp_data.icalcomp, NULL, NULL)) { + g_warning (G_STRLOC ": Could not create the object!"); + /* FIXME: show error dialog */ } @@ -987,46 +997,53 @@ CalClient * e_cal_model_get_default_client (ECalModel *model) { ECalModelPrivate *priv; - GList *l; - gchar *default_uri = NULL; - EConfigListener *db; ECalModelClient *client_data; + g_return_val_if_fail (model != NULL, NULL); g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL); - + priv = model->priv; + /* we always return a valid CalClient, since we rely on it in many places */ + if (priv->default_client) + return priv->default_client; + if (!priv->clients) return NULL; - db = e_config_listener_new (); + client_data = (ECalModelClient *) priv->clients->data; - /* look at the configuration and return the real default calendar if we've got it loaded */ - if (priv->kind == ICAL_VEVENT_COMPONENT) - default_uri = e_config_listener_get_string (db, "/apps/evolution/shell/default_folders/calendar_uri"); - else if (priv->kind == ICAL_VTODO_COMPONENT) - default_uri = e_config_listener_get_string (db, "/apps/evolution/shell/default_folders/tasks_uri"); + return client_data ? client_data->client : NULL; +} - g_object_unref (db); +void +e_cal_model_set_default_client (ECalModel *model, CalClient *client) +{ + ECalModelPrivate *priv; + GList *l; + gboolean found = FALSE; + + g_return_if_fail (model != NULL); + g_return_if_fail (E_IS_CAL_MODEL (model)); + g_return_if_fail (client != NULL); + g_return_if_fail (IS_CAL_CLIENT (client)); - if (!default_uri) { - client_data = (ECalModelClient *) priv->clients->data; - return client_data->client; - } + priv = model->priv; + /* See if we already know about the client */ for (l = priv->clients; l != NULL; l = l->next) { - client_data = (ECalModelClient *) l->data; + ECalModelClient *client_data = l->data; - if (!strcmp (default_uri, cal_client_get_uri (client_data->client))) { - g_free (default_uri); - return client_data->client; - } + if (client == client_data->client) + found = TRUE; } - g_free (default_uri); - - client_data = (ECalModelClient *) priv->clients->data; - return client_data->client; + /* If its not found, add it */ + if (!found) + e_cal_model_add_client (model, client); + + /* Store the default client */ + priv->default_client = client; } /** @@ -1048,6 +1065,29 @@ e_cal_model_get_client_list (ECalModel *model) return list; } +/** + * e_cal_model_get_client_for_uri + * @model: A calendar model. + * @uri: Uri for the client to get. + */ +CalClient * +e_cal_model_get_client_for_uri (ECalModel *model, const char *uri) +{ + GList *l; + + g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL); + g_return_val_if_fail (uri != NULL, NULL); + + for (l = model->priv->clients; l != NULL; l = l->next) { + ECalModelClient *client_data = (ECalModelClient *) l->data; + + if (!strcmp (uri, cal_client_get_uri (client_data->client))) + return client_data->client; + } + + return NULL; +} + static ECalModelComponent * search_by_uid_and_client (ECalModelPrivate *priv, CalClient *client, const char *uid) { @@ -1084,124 +1124,119 @@ get_position_in_array (GPtrArray *objects, gpointer item) } static void -query_obj_updated_cb (CalQuery *query, const char *uid, - gboolean query_in_progress, - int n_scanned, int total, - gpointer user_data) +query_objects_added_cb (CalQuery *query, GList *objects, gpointer user_data) { - ECalModelPrivate *priv; - icalcomponent *new_icalcomp; - CalClientGetStatus status; - ECalModelComponent *comp_data; - gint pos; ECalModel *model = (ECalModel *) user_data; - - g_return_if_fail (E_IS_CAL_MODEL (model)); - + ECalModelPrivate *priv; + GList *l; + int start_row; + priv = model->priv; e_table_model_pre_change (E_TABLE_MODEL (model)); - comp_data = search_by_uid_and_client (priv, cal_query_get_client (query), uid); - status = cal_client_get_object (cal_query_get_client (query), uid, &new_icalcomp); - switch (status) { - case CAL_CLIENT_GET_SUCCESS : - if (comp_data) { - if (comp_data->icalcomp) - icalcomponent_free (comp_data->icalcomp); - if (comp_data->dtstart) { - g_free (comp_data->dtstart); - comp_data->dtstart = NULL; - } - if (comp_data->dtend) { - g_free (comp_data->dtend); - comp_data->dtend = NULL; - } - if (comp_data->due) { - g_free (comp_data->due); - comp_data->due = NULL; - } - if (comp_data->completed) { - g_free (comp_data->completed); - comp_data->completed = NULL; - } + start_row = priv->objects->len ? priv->objects->len - 1 : 0; + + for (l = objects; l; l = l->next) { + ECalModelComponent *comp_data; - comp_data->icalcomp = new_icalcomp; + comp_data = g_new0 (ECalModelComponent, 1); + comp_data->client = cal_query_get_client (query); + comp_data->icalcomp = icalcomponent_new_clone (l->data); - e_table_model_row_changed (E_TABLE_MODEL (model), get_position_in_array (priv->objects, comp_data)); - } else { - comp_data = g_new0 (ECalModelComponent, 1); - comp_data->client = cal_query_get_client (query); - comp_data->icalcomp = new_icalcomp; + g_ptr_array_add (priv->objects, comp_data); + } - g_ptr_array_add (priv->objects, comp_data); - e_table_model_row_inserted (E_TABLE_MODEL (model), priv->objects->len - 1); - } - break; - case CAL_CLIENT_GET_NOT_FOUND : - case CAL_CLIENT_GET_SYNTAX_ERROR : - if (comp_data) { - /* Nothing; the object may have been removed from the server. We just - notify that the old object was deleted. - */ - pos = get_position_in_array (priv->objects, comp_data); + e_table_model_rows_inserted (E_TABLE_MODEL (model), start_row, priv->objects->len - start_row); +} - g_ptr_array_remove (priv->objects, comp_data); - free_comp_data (comp_data); +static void +query_objects_modified_cb (CalQuery *query, GList *objects, gpointer user_data) +{ + ECalModelPrivate *priv; + ECalModel *model = (ECalModel *) user_data; + GList *l; + + priv = model->priv; - e_table_model_row_deleted (E_TABLE_MODEL (model), pos); - } else - e_table_model_no_change (E_TABLE_MODEL (model)); - break; - default : - g_assert_not_reached (); + for (l = objects; l; l = l->next) { + ECalModelComponent *comp_data; + + e_table_model_pre_change (E_TABLE_MODEL (model)); + + comp_data = search_by_uid_and_client (priv, cal_query_get_client (query), icalcomponent_get_uid (l->data)); + g_assert (comp_data); + + if (comp_data->icalcomp) + icalcomponent_free (comp_data->icalcomp); + if (comp_data->dtstart) { + g_free (comp_data->dtstart); + comp_data->dtstart = NULL; + } + if (comp_data->dtend) { + g_free (comp_data->dtend); + comp_data->dtend = NULL; + } + if (comp_data->due) { + g_free (comp_data->due); + comp_data->due = NULL; + } + if (comp_data->completed) { + g_free (comp_data->completed); + comp_data->completed = NULL; + } + + comp_data->icalcomp = icalcomponent_new_clone (l->data); + + e_table_model_row_changed (E_TABLE_MODEL (model), get_position_in_array (priv->objects, comp_data)); } } static void -query_obj_removed_cb (CalQuery *query, const char *uid, gpointer user_data) +query_objects_removed_cb (CalQuery *query, GList *uids, gpointer user_data) { - ECalModelComponent *comp_data; ECalModelPrivate *priv; ECalModel *model = (ECalModel *) user_data; - - g_return_if_fail (E_IS_CAL_MODEL (model)); - + GList *l; + priv = model->priv; - e_table_model_pre_change (E_TABLE_MODEL (model)); - - comp_data = search_by_uid_and_client (priv, cal_query_get_client (query), uid); - if (comp_data) { - gint pos = get_position_in_array (priv->objects, comp_data); + for (l = uids; l; l = l->next) { + ECalModelComponent *comp_data; + int pos; + e_table_model_pre_change (E_TABLE_MODEL (model)); + + comp_data = search_by_uid_and_client (priv, cal_query_get_client (query), l->data); + g_assert (comp_data); + + pos = get_position_in_array (priv->objects, comp_data); + g_ptr_array_remove (priv->objects, comp_data); free_comp_data (comp_data); - + e_table_model_row_deleted (E_TABLE_MODEL (model), pos); - } else - e_table_model_no_change (E_TABLE_MODEL (model)); + } } static void -query_done_cb (CalQuery *query, CalQueryDoneStatus status, const char *error_str, gpointer user_data) +query_progress_cb (CalQuery *query, const char *message, int percent, gpointer user_data) { ECalModel *model = (ECalModel *) user_data; g_return_if_fail (E_IS_CAL_MODEL (model)); - if (status != CAL_QUERY_DONE_SUCCESS) - g_warning ("query done: %s\n", error_str); + /* FIXME Update status bar */ } static void -query_eval_error_cb (CalQuery *query, const char *error_str, gpointer user_data) +query_done_cb (CalQuery *query, ECalendarStatus status, gpointer user_data) { - ECalModel *model = (ECalModel *) user_data; + ECalModel *model = (ECalModel *) user_data; g_return_if_fail (E_IS_CAL_MODEL (model)); - g_warning ("eval error: %s\n", error_str); + /* FIXME Clear status bar */ } /* Builds a complete query sexp for the calendar model by adding the predicates @@ -1248,24 +1283,28 @@ update_query_for_client (ECalModel *model, ECalModelClient *client_data) g_signal_handlers_disconnect_matched (client_data->query, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, model); g_object_unref (client_data->query); + client_data->query = NULL; } /* prepare the query */ g_assert (priv->sexp != NULL); real_sexp = adjust_query_sexp (model, priv->sexp); - client_data->query = cal_client_get_query (client_data->client, real_sexp); - g_free (real_sexp); + if (!cal_client_get_query (client_data->client, real_sexp, &client_data->query, NULL)) { + g_warning (G_STRLOC ": Unable to get query"); + g_free (real_sexp); - if (!client_data->query) { - g_message ("update_query_for_client(): Could not create the query"); return; - } + } + g_free (real_sexp); - g_signal_connect (client_data->query, "obj_updated", G_CALLBACK (query_obj_updated_cb), model); - g_signal_connect (client_data->query, "obj_removed", G_CALLBACK (query_obj_removed_cb), model); + g_signal_connect (client_data->query, "objects_added", G_CALLBACK (query_objects_added_cb), model); + g_signal_connect (client_data->query, "objects_modified", G_CALLBACK (query_objects_modified_cb), model); + g_signal_connect (client_data->query, "objects_removed", G_CALLBACK (query_objects_removed_cb), model); + g_signal_connect (client_data->query, "query_progress", G_CALLBACK (query_progress_cb), model); g_signal_connect (client_data->query, "query_done", G_CALLBACK (query_done_cb), model); - g_signal_connect (client_data->query, "eval_error", G_CALLBACK (query_eval_error_cb), model); + + cal_query_start (client_data->query); } static void @@ -1465,9 +1504,22 @@ e_cal_model_create_component_with_defaults (ECalModel *model) return NULL; } + if (!comp) + return icalcomponent_new (priv->kind); + icalcomp = icalcomponent_new_clone (cal_component_get_icalcomponent (comp)); g_object_unref (comp); + /* make sure the component has an UID */ + if (!icalcomponent_get_uid (icalcomp)) { + char *uid; + + uid = cal_component_gen_uid (); + icalcomponent_set_uid (icalcomp, uid); + + g_free (uid); + } + return icalcomp; } diff --git a/calendar/gui/e-cal-model.h b/calendar/gui/e-cal-model.h index ec8ab36c44..9c673ca439 100644 --- a/calendar/gui/e-cal-model.h +++ b/calendar/gui/e-cal-model.h @@ -88,7 +88,9 @@ void e_cal_model_set_default_category (ECalModel *model, const gc void e_cal_model_set_use_24_hour_format (ECalModel *model, gboolean use24); CalClient *e_cal_model_get_default_client (ECalModel *model); +void e_cal_model_set_default_client (ECalModel *model, CalClient *client); GList *e_cal_model_get_client_list (ECalModel *model); +CalClient *e_cal_model_get_client_for_uri (ECalModel *model, const char *uri); void e_cal_model_add_client (ECalModel *model, CalClient *client); void e_cal_model_remove_client (ECalModel *model, CalClient *client); void e_cal_model_remove_all_clients (ECalModel *model); diff --git a/calendar/gui/e-cal-view.c b/calendar/gui/e-cal-view.c index 381dca2542..869c8001a3 100644 --- a/calendar/gui/e-cal-view.c +++ b/calendar/gui/e-cal-view.c @@ -37,9 +37,11 @@ #include "comp-util.h" #include "e-cal-model-calendar.h" #include "e-cal-view.h" +#include "e-comp-editor-registry.h" #include "itip-utils.h" #include "dialogs/delete-comp.h" #include "dialogs/delete-error.h" +#include "dialogs/event-editor.h" #include "dialogs/send-comp.h" #include "dialogs/cancel-comp.h" #include "dialogs/recur-comp.h" @@ -70,15 +72,28 @@ struct _ECalViewPrivate { /* The timezone. */ icaltimezone *zone; + + /* The default category */ + char *default_category; }; static void e_cal_view_class_init (ECalViewClass *klass); static void e_cal_view_init (ECalView *cal_view, ECalViewClass *klass); +static void e_cal_view_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec); +static void e_cal_view_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); static void e_cal_view_destroy (GtkObject *object); static GObjectClass *parent_class = NULL; static GdkAtom clipboard_atom = GDK_NONE; +extern ECompEditorRegistry *comp_editor_registry; + +/* Property IDs */ +enum props { + PROP_0, + PROP_MODEL, +}; +/* FIXME Why are we emitting these event signals here? Can't the model just be listened to? */ /* Signal IDs */ enum { SELECTION_CHANGED, @@ -91,12 +106,71 @@ enum { static guint e_cal_view_signals[LAST_SIGNAL] = { 0 }; static void +e_cal_view_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + ECalView *cal_view; + ECalViewPrivate *priv; + + cal_view = E_CAL_VIEW (object); + priv = cal_view->priv; + + switch (property_id) { + case PROP_MODEL: + e_cal_view_set_model (cal_view, E_CAL_MODEL (g_value_get_object (value))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +e_cal_view_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + ECalView *cal_view; + ECalViewPrivate *priv; + + cal_view = E_CAL_VIEW (object); + priv = cal_view->priv; + + switch (property_id) { + case PROP_MODEL: + g_value_set_object (value, e_cal_view_get_model (cal_view)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void e_cal_view_class_init (ECalViewClass *klass) { + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); + /* Method override */ + gobject_class->set_property = e_cal_view_set_property; + gobject_class->get_property = e_cal_view_get_property; + object_class->destroy = e_cal_view_destroy; + + klass->selection_changed = NULL; + klass->event_changed = NULL; + klass->event_added = NULL; + + klass->get_selected_events = NULL; + klass->get_selected_time_range = NULL; + klass->set_selected_time_range = NULL; + klass->get_visible_time_range = NULL; + klass->update_query = NULL; + + g_object_class_install_property (gobject_class, PROP_MODEL, + g_param_spec_object ("model", NULL, NULL, E_TYPE_CAL_MODEL, + G_PARAM_READABLE | G_PARAM_WRITABLE + | G_PARAM_CONSTRUCT)); + /* Create class' signals */ e_cal_view_signals[SELECTION_CHANGED] = g_signal_new ("selection_changed", @@ -135,19 +209,6 @@ e_cal_view_class_init (ECalViewClass *klass) G_TYPE_NONE, 1, G_TYPE_POINTER); - /* Method override */ - object_class->destroy = e_cal_view_destroy; - - klass->selection_changed = NULL; - klass->event_changed = NULL; - klass->event_added = NULL; - - klass->get_selected_events = NULL; - klass->get_selected_time_range = NULL; - klass->set_selected_time_range = NULL; - klass->get_visible_time_range = NULL; - klass->update_query = NULL; - /* clipboard atom */ if (!clipboard_atom) clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); @@ -208,6 +269,45 @@ selection_clear_event (GtkWidget *invisible, } static void +selection_received_add_event (ECalView *cal_view, CalClient *client, time_t selected_time_start, + icaltimezone *default_zone, icalcomponent *icalcomp) +{ + CalComponent *comp; + struct icaltimetype itime; + time_t tt_start, tt_end; + struct icaldurationtype ic_dur; + char *uid; + + tt_start = icaltime_as_timet (icalcomponent_get_dtstart (icalcomp)); + tt_end = icaltime_as_timet (icalcomponent_get_dtend (icalcomp)); + ic_dur = icaldurationtype_from_int (tt_end - tt_start); + itime = icaltime_from_timet_with_zone (selected_time_start, FALSE, default_zone); + + icalcomponent_set_dtstart (icalcomp, itime); + itime = icaltime_add (itime, ic_dur); + icalcomponent_set_dtend (icalcomp, itime); + + /* FIXME The new uid stuff can go away once we actually set it in the backend */ + uid = cal_component_gen_uid (); + comp = cal_component_new (); + cal_component_set_icalcomponent ( + comp, icalcomponent_new_clone (icalcomp)); + cal_component_set_uid (comp, uid); + + /* FIXME Error handling */ + cal_client_create_object (client, cal_component_get_icalcomponent (comp), NULL, NULL); + if (itip_organizer_is_user (comp, client) && + send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (cal_view)), + client, comp, TRUE)) { + itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, + client, NULL); + } + + free (uid); + g_object_unref (comp); +} + +static void selection_received (GtkWidget *invisible, GtkSelectionData *selection_data, guint time, @@ -216,12 +316,7 @@ selection_received (GtkWidget *invisible, char *comp_str, *default_tzid; icalcomponent *icalcomp; icalcomponent_kind kind; - CalComponent *comp; time_t selected_time_start, selected_time_end; - struct icaltimetype itime; - time_t tt_start, tt_end; - struct icaldurationtype ic_dur; - char *uid; icaltimezone *default_zone; CalClient *client; @@ -238,21 +333,21 @@ selection_received (GtkWidget *invisible, return; default_tzid = calendar_config_get_timezone (); + client = e_cal_model_get_default_client (cal_view->priv->model); - cal_client_get_timezone (client, default_tzid, &default_zone); + /* FIXME Error checking */ + cal_client_get_timezone (client, default_tzid, &default_zone, NULL); /* check the type of the component */ + /* FIXME An error dialog if we return? */ kind = icalcomponent_isa (icalcomp); - if (kind != ICAL_VCALENDAR_COMPONENT && - kind != ICAL_VEVENT_COMPONENT && - kind != ICAL_VTODO_COMPONENT && - kind != ICAL_VJOURNAL_COMPONENT) { + if (kind != ICAL_VCALENDAR_COMPONENT && kind != ICAL_VEVENT_COMPONENT) return; - } e_cal_view_set_status_message (cal_view, _("Updating objects")); e_cal_view_get_selected_time_range (cal_view, &selected_time_start, &selected_time_end); + /* FIXME Timezone handling */ if (kind == ICAL_VCALENDAR_COMPONENT) { icalcomponent_kind child_kind; icalcomponent *subcomp; @@ -260,69 +355,27 @@ selection_received (GtkWidget *invisible, subcomp = icalcomponent_get_first_component (icalcomp, ICAL_ANY_COMPONENT); while (subcomp) { child_kind = icalcomponent_isa (subcomp); - if (child_kind == ICAL_VEVENT_COMPONENT || - child_kind == ICAL_VTODO_COMPONENT || - child_kind == ICAL_VJOURNAL_COMPONENT) { - tt_start = icaltime_as_timet (icalcomponent_get_dtstart (subcomp)); - tt_end = icaltime_as_timet (icalcomponent_get_dtend (subcomp)); - ic_dur = icaldurationtype_from_int (tt_end - tt_start); - itime = icaltime_from_timet_with_zone (selected_time_start, - FALSE, default_zone); - - icalcomponent_set_dtstart (subcomp, itime); - itime = icaltime_add (itime, ic_dur); - icalcomponent_set_dtend (subcomp, itime); - - uid = cal_component_gen_uid (); - comp = cal_component_new (); - cal_component_set_icalcomponent ( - comp, icalcomponent_new_clone (subcomp)); - cal_component_set_uid (comp, uid); - - cal_client_update_object (client, comp); - if (itip_organizer_is_user (comp, client) && - send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (cal_view)), - client, comp, TRUE)) { - itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, - client, NULL); - } - - free (uid); - g_object_unref (comp); + if (child_kind == ICAL_VEVENT_COMPONENT) + selection_received_add_event (cal_view, client, selected_time_start, + default_zone, subcomp); + else if (child_kind == ICAL_VTIMEZONE_COMPONENT) { + icaltimezone *zone; + + zone = icaltimezone_new (); + icaltimezone_set_component (zone, subcomp); + cal_client_add_timezone (client, zone, NULL); + + icaltimezone_free (zone, 1); } + subcomp = icalcomponent_get_next_component ( icalcomp, ICAL_ANY_COMPONENT); } icalcomponent_free (icalcomp); - } - else { - tt_start = icaltime_as_timet (icalcomponent_get_dtstart (icalcomp)); - tt_end = icaltime_as_timet (icalcomponent_get_dtend (icalcomp)); - ic_dur = icaldurationtype_from_int (tt_end - tt_start); - itime = icaltime_from_timet_with_zone (selected_time_start, FALSE, default_zone); - - icalcomponent_set_dtstart (icalcomp, itime); - itime = icaltime_add (itime, ic_dur); - icalcomponent_set_dtend (icalcomp, itime); - - uid = cal_component_gen_uid (); - comp = cal_component_new (); - cal_component_set_icalcomponent ( - comp, icalcomponent_new_clone (icalcomp)); - cal_component_set_uid (comp, uid); - - cal_client_update_object (client, comp); - if (itip_organizer_is_user (comp, client) && - send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (cal_view)), - client, comp, TRUE)) { - itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, - client, NULL); - } - - free (uid); - g_object_unref (comp); + } else { + selection_received_add_event (cal_view, client, selected_time_start, default_zone, icalcomp); } e_cal_view_set_status_message (cal_view, NULL); @@ -334,6 +387,14 @@ e_cal_view_init (ECalView *cal_view, ECalViewClass *klass) cal_view->priv = g_new0 (ECalViewPrivate, 1); cal_view->priv->model = (ECalModel *) e_cal_model_calendar_new (); + g_signal_connect (G_OBJECT (cal_view->priv->model), "model_changed", + G_CALLBACK (model_changed_cb), cal_view); + g_signal_connect (G_OBJECT (cal_view->priv->model), "model_row_changed", + G_CALLBACK (model_row_changed_cb), cal_view); + g_signal_connect (G_OBJECT (cal_view->priv->model), "model_rows_inserted", + G_CALLBACK (model_rows_changed_cb), cal_view); + g_signal_connect (G_OBJECT (cal_view->priv->model), "model_rows_deleted", + G_CALLBACK (model_rows_changed_cb), cal_view); /* Set up the invisible widget for the clipboard selections */ cal_view->priv->invisible = gtk_invisible_new (); @@ -380,6 +441,11 @@ e_cal_view_destroy (GtkObject *object) cal_view->priv->clipboard_selection = NULL; } + if (cal_view->priv->default_category) { + g_free (cal_view->priv->default_category); + cal_view->priv->default_category = NULL; + } + g_free (cal_view->priv); cal_view->priv = NULL; } @@ -460,11 +526,35 @@ e_cal_view_set_timezone (ECalView *cal_view, icaltimezone *zone) old_zone, cal_view->priv->zone); } +const char * +e_cal_view_get_default_category (ECalView *cal_view) +{ + g_return_val_if_fail (E_IS_CAL_VIEW (cal_view), NULL); + return (const char *) cal_view->priv->default_category; +} + +/** + * e_cal_view_set_default_category + * @cal_view: A calendar view. + * @category: Default category name or NULL for no category. + * + * Sets the default category that will be used when creating new calendar + * components from the given calendar view. + */ void -e_cal_view_set_status_message (ECalView *cal_view, const gchar *message) +e_cal_view_set_default_category (ECalView *cal_view, const char *category) { - extern EvolutionShellClient *global_shell_client; /* ugly */ + g_return_if_fail (E_IS_CAL_VIEW (cal_view)); + + if (cal_view->priv->default_category) + g_free (cal_view->priv->default_category); + + cal_view->priv->default_category = g_strdup (category); +} +void +e_cal_view_set_status_message (ECalView *cal_view, const gchar *message) +{ g_return_if_fail (E_IS_CAL_VIEW (cal_view)); if (!message || !*message) { @@ -473,14 +563,19 @@ e_cal_view_set_status_message (ECalView *cal_view, const gchar *message) cal_view->priv->activity = NULL; } } else if (!cal_view->priv->activity) { +#if 0 int display; +#endif char *client_id = g_strdup_printf ("%p", cal_view); if (progress_icon[0] == NULL) progress_icon[0] = gdk_pixbuf_new_from_file (EVOLUTION_IMAGESDIR "/" EVOLUTION_CALENDAR_PROGRESS_IMAGE, NULL); + +#if 0 cal_view->priv->activity = evolution_activity_client_new ( global_shell_client, client_id, progress_icon, message, TRUE, &display); +#endif g_free (client_id); } else @@ -564,9 +659,9 @@ e_cal_view_cut_clipboard (ECalView *cal_view) e_cal_view_copy_clipboard (cal_view); for (l = selected; l != NULL; l = l->next) { CalComponent *comp; - ECalViewEvent *event = (ECalViewEvent *) l->data; - + GError *error = NULL; + if (!event) continue; @@ -580,9 +675,11 @@ e_cal_view_cut_clipboard (ECalView *cal_view) event->comp_data->client, NULL); cal_component_get_uid (comp, &uid); - delete_error_dialog (cal_client_remove_object (event->comp_data->client, uid), - CAL_COMPONENT_EVENT); + cal_client_remove_object (event->comp_data->client, uid, &error); + delete_error_dialog (error, CAL_COMPONENT_EVENT); + g_clear_error (&error); + g_object_unref (comp); } @@ -657,7 +754,8 @@ delete_event (ECalView *cal_view, ECalViewEvent *event) if (delete_component_dialog (comp, FALSE, 1, vtype, GTK_WIDGET (cal_view))) { const char *uid; - + GError *error = NULL; + if (itip_organizer_is_user (comp, event->comp_data->client) && cancel_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (cal_view)), event->comp_data->client, @@ -670,9 +768,10 @@ delete_event (ECalView *cal_view, ECalViewEvent *event) g_object_unref (comp); return; } - - delete_error_dialog ( - cal_client_remove_object (event->comp_data->client, uid), CAL_COMPONENT_EVENT); + + cal_client_remove_object (event->comp_data->client, uid, &error); + delete_error_dialog (error, CAL_COMPONENT_EVENT); + g_clear_error (&error); } g_object_unref (comp); @@ -719,35 +818,21 @@ e_cal_view_delete_selected_occurrence (ECalView *cal_view) { ECalViewEvent *event; GList *selected; - + const char *uid; + GError *error = NULL; + selected = e_cal_view_get_selected_events (cal_view); if (!selected) return; event = (ECalViewEvent *) selected->data; - if (cal_util_component_is_instance (event->comp_data->icalcomp)) { - const char *uid; - - uid = icalcomponent_get_uid (event->comp_data->icalcomp); - delete_error_dialog ( - cal_client_remove_object_with_mod (event->comp_data->client, uid, CALOBJ_MOD_THIS), - CAL_COMPONENT_EVENT); - } else { - CalComponent *comp; + uid = icalcomponent_get_uid (event->comp_data->icalcomp); + /* FIXME: use 'rid' argument */ + cal_client_remove_object_with_mod (event->comp_data->client, uid, NULL, CALOBJ_MOD_THIS, &error); - /* we must duplicate the CalComponent, or we won't know it has changed - when we get the "update_event" signal */ - comp = cal_component_new (); - cal_component_set_icalcomponent (comp, icalcomponent_new_clone (event->comp_data->icalcomp)); - cal_comp_util_add_exdate (comp, event->start, cal_view->priv->zone); - - if (cal_client_update_object (event->comp_data->client, comp) - != CAL_CLIENT_RESULT_SUCCESS) - g_message ("e_cal_view_delete_selected_occurrence(): Could not update the object!"); - - g_object_unref (comp); - } + delete_error_dialog (error, CAL_COMPONENT_EVENT); + g_clear_error (&error); /* free memory */ g_list_free (selected); @@ -756,11 +841,9 @@ e_cal_view_delete_selected_occurrence (ECalView *cal_view) static void on_new_appointment (GtkWidget *widget, gpointer user_data) { - time_t dtstart, dtend; ECalView *cal_view = (ECalView *) user_data; - e_cal_view_get_selected_time_range (cal_view, &dtstart, &dtend); - gnome_calendar_new_appointment_for (cal_view->priv->calendar, dtstart, dtend, FALSE, FALSE); + e_cal_view_new_appointment (cal_view); } static void @@ -770,7 +853,7 @@ on_new_event (GtkWidget *widget, gpointer user_data) ECalView *cal_view = (ECalView *) user_data; e_cal_view_get_selected_time_range (cal_view, &dtstart, &dtend); - gnome_calendar_new_appointment_for (cal_view->priv->calendar, dtstart, dtend, TRUE, FALSE); + e_cal_view_new_appointment_for (cal_view, dtstart, dtend, TRUE, FALSE); } static void @@ -780,7 +863,7 @@ on_new_meeting (GtkWidget *widget, gpointer user_data) ECalView *cal_view = (ECalView *) user_data; e_cal_view_get_selected_time_range (cal_view, &dtstart, &dtend); - gnome_calendar_new_appointment_for (cal_view->priv->calendar, dtstart, dtend, FALSE, TRUE); + e_cal_view_new_appointment_for (cal_view, dtstart, dtend, FALSE, TRUE); } static void @@ -817,8 +900,8 @@ on_edit_appointment (GtkWidget *widget, gpointer user_data) ECalViewEvent *event = (ECalViewEvent *) selected->data; if (event) - gnome_calendar_edit_object (cal_view->priv->calendar, event->comp_data->client, - event->comp_data->icalcomp, FALSE); + e_cal_view_edit_appointment (cal_view, event->comp_data->client, + event->comp_data->icalcomp, FALSE); g_list_free (selected); } @@ -834,7 +917,7 @@ on_print (GtkWidget *widget, gpointer user_data) cal_view = E_CAL_VIEW (user_data); - gnome_calendar_get_current_time_range (cal_view->priv->calendar, &start, NULL); + e_cal_view_get_visible_time_range (cal_view, &start, NULL); view_type = gnome_calendar_get_view (cal_view->priv->calendar); switch (view_type) { @@ -930,7 +1013,7 @@ on_meeting (GtkWidget *widget, gpointer user_data) selected = e_cal_view_get_selected_events (cal_view); if (selected) { ECalViewEvent *event = (ECalViewEvent *) selected->data; - gnome_calendar_edit_object (cal_view->priv->calendar, event->comp_data->client, event->comp_data->icalcomp, TRUE); + e_cal_view_edit_appointment (cal_view, event->comp_data->client, event->comp_data->icalcomp, TRUE); g_list_free (selected); } @@ -962,7 +1045,7 @@ on_publish (GtkWidget *widget, gpointer user_data) ECalView *cal_view; icaltimezone *utc; time_t start = time (NULL), end; - GList *comp_list, *client_list, *cl; + GList *comp_list = NULL, *client_list, *cl; cal_view = E_CAL_VIEW (user_data); @@ -972,8 +1055,7 @@ on_publish (GtkWidget *widget, gpointer user_data) client_list = e_cal_model_get_client_list (cal_view->priv->model); for (cl = client_list; cl != NULL; cl = cl->next) { - comp_list = cal_client_get_free_busy ((CalClient *) cl->data, NULL, start, end); - if (comp_list) { + if (cal_client_get_free_busy ((CalClient *) cl->data, NULL, start, end, &comp_list, NULL)) { GList *l; for (l = comp_list; l; l = l->next) { @@ -1041,14 +1123,6 @@ on_paste (GtkWidget *widget, gpointer user_data) e_cal_view_paste_clipboard (cal_view); } -static void -on_unrecur_appointment (GtkWidget *widget, gpointer user_data) -{ - ECalView *cal_view = E_CAL_VIEW (user_data); - - gnome_calendar_unrecur_selection (cal_view->priv->calendar); -} - enum { /* * This is used to "flag" events that can not be editted @@ -1142,7 +1216,6 @@ static EPopupMenu child_items [] = { E_POPUP_SEPARATOR, E_POPUP_ITEM (N_("_Delete"), GTK_SIGNAL_FUNC (on_delete_appointment), MASK_EDITABLE | MASK_SINGLE | MASK_EDITING), - E_POPUP_ITEM (N_("Make this Occurrence _Movable"), GTK_SIGNAL_FUNC (on_unrecur_appointment), MASK_RECURRING | MASK_EDITING | MASK_EDITABLE | MASK_INSTANCE), E_POPUP_ITEM (N_("Delete this _Occurrence"), GTK_SIGNAL_FUNC (on_delete_occurrence), MASK_RECURRING | MASK_EDITING | MASK_EDITABLE), E_POPUP_ITEM (N_("Delete _All Occurrences"), GTK_SIGNAL_FUNC (on_delete_appointment), MASK_RECURRING | MASK_EDITING | MASK_EDITABLE), @@ -1209,21 +1282,18 @@ setup_popup_icons (EPopupMenu *context_menu) GtkMenu * e_cal_view_create_popup_menu (ECalView *cal_view) { - gboolean being_edited, have_selection; GList *selected; EPopupMenu *context_menu; guint32 disable_mask = 0, hide_mask = 0; GtkMenu *popup; CalClient *client = NULL; - + gboolean read_only = TRUE; + g_return_val_if_fail (E_IS_CAL_VIEW (cal_view), NULL); /* get the selection */ - being_edited = FALSE; selected = e_cal_view_get_selected_events (cal_view); - have_selection = GTK_WIDGET_HAS_FOCUS (cal_view) && selected != NULL; - if (selected == NULL) { cal_view->priv->view_menu = gnome_calendar_setup_view_popup (cal_view->priv->calendar); main_items[9].submenu = cal_view->priv->view_menu; @@ -1260,15 +1330,158 @@ e_cal_view_create_popup_menu (ECalView *cal_view) client = event->comp_data->client; } - if (cal_client_is_read_only (client)) + cal_client_is_read_only (client, &read_only, NULL); + if (read_only) disable_mask |= MASK_EDITABLE; - if (being_edited) - disable_mask |= MASK_EDITING; - setup_popup_icons (context_menu); popup = e_popup_menu_create (context_menu, disable_mask, hide_mask, cal_view); g_signal_connect (popup, "selection-done", G_CALLBACK (free_view_popup), cal_view); return popup; } + +/** + * e_cal_view_new_appointment_for + * @cal_view: A calendar view. + * @dtstart: A Unix time_t that marks the beginning of the appointment. + * @dtend: A Unix time_t that marks the end of the appointment. + * @all_day: If TRUE, the dtstart and dtend are expanded to cover + * the entire day, and the event is set to TRANSPARENT. + * @meeting: Whether the appointment is a meeting or not. + * + * Opens an event editor dialog for a new appointment. + */ +void +e_cal_view_new_appointment_for (ECalView *cal_view, + time_t dtstart, time_t dtend, + gboolean all_day, + gboolean meeting) +{ + ECalViewPrivate *priv; + struct icaltimetype itt; + CalComponentDateTime dt; + CalComponent *comp; + icalcomponent *icalcomp; + CalComponentTransparency transparency; + + g_return_if_fail (E_IS_CAL_VIEW (cal_view)); + + priv = cal_view->priv; + + dt.value = &itt; + if (all_day) + dt.tzid = NULL; + else + dt.tzid = icaltimezone_get_tzid (priv->zone); + + icalcomp = e_cal_model_create_component_with_defaults (priv->model); + comp = cal_component_new (); + cal_component_set_icalcomponent (comp, icalcomp); + + /* DTSTART, DTEND */ + itt = icaltime_from_timet_with_zone (dtstart, FALSE, priv->zone); + if (all_day) { + itt.hour = itt.minute = itt.second = 0; + itt.is_date = TRUE; + } + cal_component_set_dtstart (comp, &dt); + + itt = icaltime_from_timet_with_zone (dtend, FALSE, priv->zone); + if (all_day) { + /* We round it up to the end of the day, unless it is + already set to midnight */ + if (itt.hour != 0 || itt.minute != 0 || itt.second != 0) { + icaltime_adjust (&itt, 1, 0, 0, 0); + } + itt.hour = itt.minute = itt.second = 0; + itt.is_date = TRUE; + } + cal_component_set_dtend (comp, &dt); + + /* TRANSPARENCY */ + transparency = all_day ? CAL_COMPONENT_TRANSP_TRANSPARENT + : CAL_COMPONENT_TRANSP_OPAQUE; + cal_component_set_transparency (comp, transparency); + + /* CATEGORY */ + cal_component_set_categories (comp, priv->default_category); + + /* edit the object */ + cal_component_commit_sequence (comp); + + e_cal_view_edit_appointment (cal_view, + e_cal_model_get_default_client (priv->model), + icalcomp, meeting); + + g_object_unref (comp); +} + +/** + * e_cal_view_new_appointment + * @cal_view: A calendar view. + * + * Opens an event editor dialog for a new appointment. The appointment's + * start and end times are set to the currently selected time range in + * the calendar view. + */ +void +e_cal_view_new_appointment (ECalView *cal_view) +{ + time_t dtstart, dtend; + + g_return_if_fail (E_IS_CAL_VIEW (cal_view)); + + e_cal_view_get_selected_time_range (cal_view, &dtstart, &dtend); + e_cal_view_new_appointment_for (cal_view, dtstart, dtend, FALSE, FALSE); +} + +/** + * e_cal_view_edit_appointment + * @cal_view: A calendar view. + * @client: Calendar client. + * @icalcomp: The object to be edited. + * @meeting: Whether the appointment is a meeting or not. + * + * Opens an editor window to allow the user to edit the selected + * object. + */ +void +e_cal_view_edit_appointment (ECalView *cal_view, + CalClient *client, + icalcomponent *icalcomp, + gboolean meeting) +{ + ECalViewPrivate *priv; + CompEditor *ce; + const char *uid; + CalComponent *comp; + + g_return_if_fail (E_IS_CAL_VIEW (cal_view)); + g_return_if_fail (IS_CAL_CLIENT (client)); + g_return_if_fail (icalcomp != NULL); + + priv = cal_view->priv; + + uid = icalcomponent_get_uid (icalcomp); + + ce = e_comp_editor_registry_find (comp_editor_registry, uid); + if (!ce) { + EventEditor *ee; + + ee = event_editor_new (client); + ce = COMP_EDITOR (ee); + + comp = cal_component_new (); + cal_component_set_icalcomponent (comp, icalcomponent_new_clone (icalcomp)); + comp_editor_edit_comp (ce, comp); + if (meeting) + event_editor_show_meeting (ee); + + e_comp_editor_registry_add (comp_editor_registry, ce, FALSE); + + g_object_unref (comp); + } + + comp_editor_focus (ce); +} diff --git a/calendar/gui/e-cal-view.h b/calendar/gui/e-cal-view.h index ea7c11a00d..9a09a5236a 100644 --- a/calendar/gui/e-cal-view.h +++ b/calendar/gui/e-cal-view.h @@ -96,6 +96,8 @@ ECalModel *e_cal_view_get_model (ECalView *cal_view); void e_cal_view_set_model (ECalView *cal_view, ECalModel *model); icaltimezone *e_cal_view_get_timezone (ECalView *cal_view); void e_cal_view_set_timezone (ECalView *cal_view, icaltimezone *zone); +const char *e_cal_view_get_default_category (ECalView *cal_view); +void e_cal_view_set_default_category (ECalView *cal_view, const char *category); void e_cal_view_set_status_message (ECalView *cal_view, const gchar *message); @@ -114,6 +116,17 @@ void e_cal_view_delete_selected_occurrence (ECalView *cal_view); GtkMenu *e_cal_view_create_popup_menu (ECalView *cal_view); +void e_cal_view_new_appointment_for (ECalView *cal_view, + time_t dtstart, + time_t dtend, + gboolean all_day, + gboolean meeting); +void e_cal_view_new_appointment (ECalView *cal_view); +void e_cal_view_edit_appointment (ECalView *cal_view, + CalClient *client, + icalcomponent *icalcomp, + gboolean meeting); + G_END_DECLS #endif diff --git a/calendar/gui/e-calendar-table.c b/calendar/gui/e-calendar-table.c index 5b3f98f373..fdea4d33bb 100644 --- a/calendar/gui/e-calendar-table.c +++ b/calendar/gui/e-calendar-table.c @@ -725,10 +725,12 @@ delete_selected_components (ECalendarTable *cal_table) for (l = objs; l; l = l->next) { ECalModelComponent *comp_data = (ECalModelComponent *) l->data; - - delete_error_dialog (cal_client_remove_object (comp_data->client, - icalcomponent_get_uid (comp_data->icalcomp)), - CAL_COMPONENT_TODO); + GError *error = NULL; + + cal_client_remove_object (comp_data->client, + icalcomponent_get_uid (comp_data->icalcomp), &error); + delete_error_dialog (error, CAL_COMPONENT_TODO); + g_clear_error (&error); } e_calendar_table_set_status_message (cal_table, NULL); @@ -1052,7 +1054,8 @@ e_calendar_table_show_popup_menu (ETable *table, GtkMenu *gtk_menu; icalproperty *prop; ECalModelComponent *comp_data; - + gboolean read_only = TRUE; + n_selected = e_table_selected_count (table); if (n_selected <= 0) return TRUE; @@ -1071,7 +1074,8 @@ e_calendar_table_show_popup_menu (ETable *table, } else hide_mask = MASK_SINGLE; - if (cal_client_is_read_only (comp_data->client)) + cal_client_is_read_only (comp_data->client, &read_only, NULL); + if (!read_only) disable_mask |= MASK_EDITABLE; if (cal_client_get_static_capability (comp_data->client, CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT)) @@ -1315,6 +1319,7 @@ selection_received (GtkWidget *invisible, icalcomponent *icalcomp; char *uid; CalComponent *comp; + CalClient *client; icalcomponent_kind kind; g_return_if_fail (E_IS_CALENDAR_TABLE (cal_table)); @@ -1338,6 +1343,8 @@ selection_received (GtkWidget *invisible, return; } + client = e_cal_model_get_default_client (cal_table->model); + e_calendar_table_set_status_message (cal_table, _("Updating objects")); if (kind == ICAL_VCALENDAR_COMPONENT) { @@ -1360,11 +1367,12 @@ selection_received (GtkWidget *invisible, cal_component_set_icalcomponent ( tmp_comp, icalcomponent_new_clone (subcomp)); cal_component_set_uid (tmp_comp, uid); - - cal_client_update_object ( - e_cal_model_get_default_client (cal_table->model), - tmp_comp); free (uid); + + /* FIXME should we convert start/due/complete times? */ + /* FIXME Error handling */ + cal_client_create_object (client, cal_component_get_icalcomponent (tmp_comp), NULL, NULL); + g_object_unref (tmp_comp); } subcomp = icalcomponent_get_next_component ( @@ -1378,9 +1386,8 @@ selection_received (GtkWidget *invisible, cal_component_set_uid (comp, (const char *) uid); free (uid); - cal_client_update_object ( - e_cal_model_get_default_client (cal_table->model), - comp); + cal_client_create_object (client, cal_component_get_icalcomponent (comp), NULL, NULL); + g_object_unref (comp); } @@ -1433,8 +1440,6 @@ static GdkPixbuf *progress_icon[2] = { NULL, NULL }; void e_calendar_table_set_status_message (ECalendarTable *cal_table, const gchar *message) { - extern EvolutionShellClient *global_shell_client; /* ugly */ - g_return_if_fail (E_IS_CALENDAR_TABLE (cal_table)); if (!message || !*message) { @@ -1448,9 +1453,12 @@ e_calendar_table_set_status_message (ECalendarTable *cal_table, const gchar *mes if (progress_icon[0] == NULL) progress_icon[0] = gdk_pixbuf_new_from_file (EVOLUTION_IMAGESDIR "/" EVOLUTION_TASKS_PROGRESS_IMAGE, NULL); + +#if 0 /* EPFIXME */ cal_table->activity = evolution_activity_client_new ( global_shell_client, client_id, progress_icon, message, TRUE, &display); +#endif g_free (client_id); } else diff --git a/calendar/gui/e-calendar-view.c b/calendar/gui/e-calendar-view.c index 381dca2542..869c8001a3 100644 --- a/calendar/gui/e-calendar-view.c +++ b/calendar/gui/e-calendar-view.c @@ -37,9 +37,11 @@ #include "comp-util.h" #include "e-cal-model-calendar.h" #include "e-cal-view.h" +#include "e-comp-editor-registry.h" #include "itip-utils.h" #include "dialogs/delete-comp.h" #include "dialogs/delete-error.h" +#include "dialogs/event-editor.h" #include "dialogs/send-comp.h" #include "dialogs/cancel-comp.h" #include "dialogs/recur-comp.h" @@ -70,15 +72,28 @@ struct _ECalViewPrivate { /* The timezone. */ icaltimezone *zone; + + /* The default category */ + char *default_category; }; static void e_cal_view_class_init (ECalViewClass *klass); static void e_cal_view_init (ECalView *cal_view, ECalViewClass *klass); +static void e_cal_view_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec); +static void e_cal_view_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); static void e_cal_view_destroy (GtkObject *object); static GObjectClass *parent_class = NULL; static GdkAtom clipboard_atom = GDK_NONE; +extern ECompEditorRegistry *comp_editor_registry; + +/* Property IDs */ +enum props { + PROP_0, + PROP_MODEL, +}; +/* FIXME Why are we emitting these event signals here? Can't the model just be listened to? */ /* Signal IDs */ enum { SELECTION_CHANGED, @@ -91,12 +106,71 @@ enum { static guint e_cal_view_signals[LAST_SIGNAL] = { 0 }; static void +e_cal_view_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + ECalView *cal_view; + ECalViewPrivate *priv; + + cal_view = E_CAL_VIEW (object); + priv = cal_view->priv; + + switch (property_id) { + case PROP_MODEL: + e_cal_view_set_model (cal_view, E_CAL_MODEL (g_value_get_object (value))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +e_cal_view_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + ECalView *cal_view; + ECalViewPrivate *priv; + + cal_view = E_CAL_VIEW (object); + priv = cal_view->priv; + + switch (property_id) { + case PROP_MODEL: + g_value_set_object (value, e_cal_view_get_model (cal_view)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void e_cal_view_class_init (ECalViewClass *klass) { + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); + /* Method override */ + gobject_class->set_property = e_cal_view_set_property; + gobject_class->get_property = e_cal_view_get_property; + object_class->destroy = e_cal_view_destroy; + + klass->selection_changed = NULL; + klass->event_changed = NULL; + klass->event_added = NULL; + + klass->get_selected_events = NULL; + klass->get_selected_time_range = NULL; + klass->set_selected_time_range = NULL; + klass->get_visible_time_range = NULL; + klass->update_query = NULL; + + g_object_class_install_property (gobject_class, PROP_MODEL, + g_param_spec_object ("model", NULL, NULL, E_TYPE_CAL_MODEL, + G_PARAM_READABLE | G_PARAM_WRITABLE + | G_PARAM_CONSTRUCT)); + /* Create class' signals */ e_cal_view_signals[SELECTION_CHANGED] = g_signal_new ("selection_changed", @@ -135,19 +209,6 @@ e_cal_view_class_init (ECalViewClass *klass) G_TYPE_NONE, 1, G_TYPE_POINTER); - /* Method override */ - object_class->destroy = e_cal_view_destroy; - - klass->selection_changed = NULL; - klass->event_changed = NULL; - klass->event_added = NULL; - - klass->get_selected_events = NULL; - klass->get_selected_time_range = NULL; - klass->set_selected_time_range = NULL; - klass->get_visible_time_range = NULL; - klass->update_query = NULL; - /* clipboard atom */ if (!clipboard_atom) clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); @@ -208,6 +269,45 @@ selection_clear_event (GtkWidget *invisible, } static void +selection_received_add_event (ECalView *cal_view, CalClient *client, time_t selected_time_start, + icaltimezone *default_zone, icalcomponent *icalcomp) +{ + CalComponent *comp; + struct icaltimetype itime; + time_t tt_start, tt_end; + struct icaldurationtype ic_dur; + char *uid; + + tt_start = icaltime_as_timet (icalcomponent_get_dtstart (icalcomp)); + tt_end = icaltime_as_timet (icalcomponent_get_dtend (icalcomp)); + ic_dur = icaldurationtype_from_int (tt_end - tt_start); + itime = icaltime_from_timet_with_zone (selected_time_start, FALSE, default_zone); + + icalcomponent_set_dtstart (icalcomp, itime); + itime = icaltime_add (itime, ic_dur); + icalcomponent_set_dtend (icalcomp, itime); + + /* FIXME The new uid stuff can go away once we actually set it in the backend */ + uid = cal_component_gen_uid (); + comp = cal_component_new (); + cal_component_set_icalcomponent ( + comp, icalcomponent_new_clone (icalcomp)); + cal_component_set_uid (comp, uid); + + /* FIXME Error handling */ + cal_client_create_object (client, cal_component_get_icalcomponent (comp), NULL, NULL); + if (itip_organizer_is_user (comp, client) && + send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (cal_view)), + client, comp, TRUE)) { + itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, + client, NULL); + } + + free (uid); + g_object_unref (comp); +} + +static void selection_received (GtkWidget *invisible, GtkSelectionData *selection_data, guint time, @@ -216,12 +316,7 @@ selection_received (GtkWidget *invisible, char *comp_str, *default_tzid; icalcomponent *icalcomp; icalcomponent_kind kind; - CalComponent *comp; time_t selected_time_start, selected_time_end; - struct icaltimetype itime; - time_t tt_start, tt_end; - struct icaldurationtype ic_dur; - char *uid; icaltimezone *default_zone; CalClient *client; @@ -238,21 +333,21 @@ selection_received (GtkWidget *invisible, return; default_tzid = calendar_config_get_timezone (); + client = e_cal_model_get_default_client (cal_view->priv->model); - cal_client_get_timezone (client, default_tzid, &default_zone); + /* FIXME Error checking */ + cal_client_get_timezone (client, default_tzid, &default_zone, NULL); /* check the type of the component */ + /* FIXME An error dialog if we return? */ kind = icalcomponent_isa (icalcomp); - if (kind != ICAL_VCALENDAR_COMPONENT && - kind != ICAL_VEVENT_COMPONENT && - kind != ICAL_VTODO_COMPONENT && - kind != ICAL_VJOURNAL_COMPONENT) { + if (kind != ICAL_VCALENDAR_COMPONENT && kind != ICAL_VEVENT_COMPONENT) return; - } e_cal_view_set_status_message (cal_view, _("Updating objects")); e_cal_view_get_selected_time_range (cal_view, &selected_time_start, &selected_time_end); + /* FIXME Timezone handling */ if (kind == ICAL_VCALENDAR_COMPONENT) { icalcomponent_kind child_kind; icalcomponent *subcomp; @@ -260,69 +355,27 @@ selection_received (GtkWidget *invisible, subcomp = icalcomponent_get_first_component (icalcomp, ICAL_ANY_COMPONENT); while (subcomp) { child_kind = icalcomponent_isa (subcomp); - if (child_kind == ICAL_VEVENT_COMPONENT || - child_kind == ICAL_VTODO_COMPONENT || - child_kind == ICAL_VJOURNAL_COMPONENT) { - tt_start = icaltime_as_timet (icalcomponent_get_dtstart (subcomp)); - tt_end = icaltime_as_timet (icalcomponent_get_dtend (subcomp)); - ic_dur = icaldurationtype_from_int (tt_end - tt_start); - itime = icaltime_from_timet_with_zone (selected_time_start, - FALSE, default_zone); - - icalcomponent_set_dtstart (subcomp, itime); - itime = icaltime_add (itime, ic_dur); - icalcomponent_set_dtend (subcomp, itime); - - uid = cal_component_gen_uid (); - comp = cal_component_new (); - cal_component_set_icalcomponent ( - comp, icalcomponent_new_clone (subcomp)); - cal_component_set_uid (comp, uid); - - cal_client_update_object (client, comp); - if (itip_organizer_is_user (comp, client) && - send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (cal_view)), - client, comp, TRUE)) { - itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, - client, NULL); - } - - free (uid); - g_object_unref (comp); + if (child_kind == ICAL_VEVENT_COMPONENT) + selection_received_add_event (cal_view, client, selected_time_start, + default_zone, subcomp); + else if (child_kind == ICAL_VTIMEZONE_COMPONENT) { + icaltimezone *zone; + + zone = icaltimezone_new (); + icaltimezone_set_component (zone, subcomp); + cal_client_add_timezone (client, zone, NULL); + + icaltimezone_free (zone, 1); } + subcomp = icalcomponent_get_next_component ( icalcomp, ICAL_ANY_COMPONENT); } icalcomponent_free (icalcomp); - } - else { - tt_start = icaltime_as_timet (icalcomponent_get_dtstart (icalcomp)); - tt_end = icaltime_as_timet (icalcomponent_get_dtend (icalcomp)); - ic_dur = icaldurationtype_from_int (tt_end - tt_start); - itime = icaltime_from_timet_with_zone (selected_time_start, FALSE, default_zone); - - icalcomponent_set_dtstart (icalcomp, itime); - itime = icaltime_add (itime, ic_dur); - icalcomponent_set_dtend (icalcomp, itime); - - uid = cal_component_gen_uid (); - comp = cal_component_new (); - cal_component_set_icalcomponent ( - comp, icalcomponent_new_clone (icalcomp)); - cal_component_set_uid (comp, uid); - - cal_client_update_object (client, comp); - if (itip_organizer_is_user (comp, client) && - send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (cal_view)), - client, comp, TRUE)) { - itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, - client, NULL); - } - - free (uid); - g_object_unref (comp); + } else { + selection_received_add_event (cal_view, client, selected_time_start, default_zone, icalcomp); } e_cal_view_set_status_message (cal_view, NULL); @@ -334,6 +387,14 @@ e_cal_view_init (ECalView *cal_view, ECalViewClass *klass) cal_view->priv = g_new0 (ECalViewPrivate, 1); cal_view->priv->model = (ECalModel *) e_cal_model_calendar_new (); + g_signal_connect (G_OBJECT (cal_view->priv->model), "model_changed", + G_CALLBACK (model_changed_cb), cal_view); + g_signal_connect (G_OBJECT (cal_view->priv->model), "model_row_changed", + G_CALLBACK (model_row_changed_cb), cal_view); + g_signal_connect (G_OBJECT (cal_view->priv->model), "model_rows_inserted", + G_CALLBACK (model_rows_changed_cb), cal_view); + g_signal_connect (G_OBJECT (cal_view->priv->model), "model_rows_deleted", + G_CALLBACK (model_rows_changed_cb), cal_view); /* Set up the invisible widget for the clipboard selections */ cal_view->priv->invisible = gtk_invisible_new (); @@ -380,6 +441,11 @@ e_cal_view_destroy (GtkObject *object) cal_view->priv->clipboard_selection = NULL; } + if (cal_view->priv->default_category) { + g_free (cal_view->priv->default_category); + cal_view->priv->default_category = NULL; + } + g_free (cal_view->priv); cal_view->priv = NULL; } @@ -460,11 +526,35 @@ e_cal_view_set_timezone (ECalView *cal_view, icaltimezone *zone) old_zone, cal_view->priv->zone); } +const char * +e_cal_view_get_default_category (ECalView *cal_view) +{ + g_return_val_if_fail (E_IS_CAL_VIEW (cal_view), NULL); + return (const char *) cal_view->priv->default_category; +} + +/** + * e_cal_view_set_default_category + * @cal_view: A calendar view. + * @category: Default category name or NULL for no category. + * + * Sets the default category that will be used when creating new calendar + * components from the given calendar view. + */ void -e_cal_view_set_status_message (ECalView *cal_view, const gchar *message) +e_cal_view_set_default_category (ECalView *cal_view, const char *category) { - extern EvolutionShellClient *global_shell_client; /* ugly */ + g_return_if_fail (E_IS_CAL_VIEW (cal_view)); + + if (cal_view->priv->default_category) + g_free (cal_view->priv->default_category); + + cal_view->priv->default_category = g_strdup (category); +} +void +e_cal_view_set_status_message (ECalView *cal_view, const gchar *message) +{ g_return_if_fail (E_IS_CAL_VIEW (cal_view)); if (!message || !*message) { @@ -473,14 +563,19 @@ e_cal_view_set_status_message (ECalView *cal_view, const gchar *message) cal_view->priv->activity = NULL; } } else if (!cal_view->priv->activity) { +#if 0 int display; +#endif char *client_id = g_strdup_printf ("%p", cal_view); if (progress_icon[0] == NULL) progress_icon[0] = gdk_pixbuf_new_from_file (EVOLUTION_IMAGESDIR "/" EVOLUTION_CALENDAR_PROGRESS_IMAGE, NULL); + +#if 0 cal_view->priv->activity = evolution_activity_client_new ( global_shell_client, client_id, progress_icon, message, TRUE, &display); +#endif g_free (client_id); } else @@ -564,9 +659,9 @@ e_cal_view_cut_clipboard (ECalView *cal_view) e_cal_view_copy_clipboard (cal_view); for (l = selected; l != NULL; l = l->next) { CalComponent *comp; - ECalViewEvent *event = (ECalViewEvent *) l->data; - + GError *error = NULL; + if (!event) continue; @@ -580,9 +675,11 @@ e_cal_view_cut_clipboard (ECalView *cal_view) event->comp_data->client, NULL); cal_component_get_uid (comp, &uid); - delete_error_dialog (cal_client_remove_object (event->comp_data->client, uid), - CAL_COMPONENT_EVENT); + cal_client_remove_object (event->comp_data->client, uid, &error); + delete_error_dialog (error, CAL_COMPONENT_EVENT); + g_clear_error (&error); + g_object_unref (comp); } @@ -657,7 +754,8 @@ delete_event (ECalView *cal_view, ECalViewEvent *event) if (delete_component_dialog (comp, FALSE, 1, vtype, GTK_WIDGET (cal_view))) { const char *uid; - + GError *error = NULL; + if (itip_organizer_is_user (comp, event->comp_data->client) && cancel_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (cal_view)), event->comp_data->client, @@ -670,9 +768,10 @@ delete_event (ECalView *cal_view, ECalViewEvent *event) g_object_unref (comp); return; } - - delete_error_dialog ( - cal_client_remove_object (event->comp_data->client, uid), CAL_COMPONENT_EVENT); + + cal_client_remove_object (event->comp_data->client, uid, &error); + delete_error_dialog (error, CAL_COMPONENT_EVENT); + g_clear_error (&error); } g_object_unref (comp); @@ -719,35 +818,21 @@ e_cal_view_delete_selected_occurrence (ECalView *cal_view) { ECalViewEvent *event; GList *selected; - + const char *uid; + GError *error = NULL; + selected = e_cal_view_get_selected_events (cal_view); if (!selected) return; event = (ECalViewEvent *) selected->data; - if (cal_util_component_is_instance (event->comp_data->icalcomp)) { - const char *uid; - - uid = icalcomponent_get_uid (event->comp_data->icalcomp); - delete_error_dialog ( - cal_client_remove_object_with_mod (event->comp_data->client, uid, CALOBJ_MOD_THIS), - CAL_COMPONENT_EVENT); - } else { - CalComponent *comp; + uid = icalcomponent_get_uid (event->comp_data->icalcomp); + /* FIXME: use 'rid' argument */ + cal_client_remove_object_with_mod (event->comp_data->client, uid, NULL, CALOBJ_MOD_THIS, &error); - /* we must duplicate the CalComponent, or we won't know it has changed - when we get the "update_event" signal */ - comp = cal_component_new (); - cal_component_set_icalcomponent (comp, icalcomponent_new_clone (event->comp_data->icalcomp)); - cal_comp_util_add_exdate (comp, event->start, cal_view->priv->zone); - - if (cal_client_update_object (event->comp_data->client, comp) - != CAL_CLIENT_RESULT_SUCCESS) - g_message ("e_cal_view_delete_selected_occurrence(): Could not update the object!"); - - g_object_unref (comp); - } + delete_error_dialog (error, CAL_COMPONENT_EVENT); + g_clear_error (&error); /* free memory */ g_list_free (selected); @@ -756,11 +841,9 @@ e_cal_view_delete_selected_occurrence (ECalView *cal_view) static void on_new_appointment (GtkWidget *widget, gpointer user_data) { - time_t dtstart, dtend; ECalView *cal_view = (ECalView *) user_data; - e_cal_view_get_selected_time_range (cal_view, &dtstart, &dtend); - gnome_calendar_new_appointment_for (cal_view->priv->calendar, dtstart, dtend, FALSE, FALSE); + e_cal_view_new_appointment (cal_view); } static void @@ -770,7 +853,7 @@ on_new_event (GtkWidget *widget, gpointer user_data) ECalView *cal_view = (ECalView *) user_data; e_cal_view_get_selected_time_range (cal_view, &dtstart, &dtend); - gnome_calendar_new_appointment_for (cal_view->priv->calendar, dtstart, dtend, TRUE, FALSE); + e_cal_view_new_appointment_for (cal_view, dtstart, dtend, TRUE, FALSE); } static void @@ -780,7 +863,7 @@ on_new_meeting (GtkWidget *widget, gpointer user_data) ECalView *cal_view = (ECalView *) user_data; e_cal_view_get_selected_time_range (cal_view, &dtstart, &dtend); - gnome_calendar_new_appointment_for (cal_view->priv->calendar, dtstart, dtend, FALSE, TRUE); + e_cal_view_new_appointment_for (cal_view, dtstart, dtend, FALSE, TRUE); } static void @@ -817,8 +900,8 @@ on_edit_appointment (GtkWidget *widget, gpointer user_data) ECalViewEvent *event = (ECalViewEvent *) selected->data; if (event) - gnome_calendar_edit_object (cal_view->priv->calendar, event->comp_data->client, - event->comp_data->icalcomp, FALSE); + e_cal_view_edit_appointment (cal_view, event->comp_data->client, + event->comp_data->icalcomp, FALSE); g_list_free (selected); } @@ -834,7 +917,7 @@ on_print (GtkWidget *widget, gpointer user_data) cal_view = E_CAL_VIEW (user_data); - gnome_calendar_get_current_time_range (cal_view->priv->calendar, &start, NULL); + e_cal_view_get_visible_time_range (cal_view, &start, NULL); view_type = gnome_calendar_get_view (cal_view->priv->calendar); switch (view_type) { @@ -930,7 +1013,7 @@ on_meeting (GtkWidget *widget, gpointer user_data) selected = e_cal_view_get_selected_events (cal_view); if (selected) { ECalViewEvent *event = (ECalViewEvent *) selected->data; - gnome_calendar_edit_object (cal_view->priv->calendar, event->comp_data->client, event->comp_data->icalcomp, TRUE); + e_cal_view_edit_appointment (cal_view, event->comp_data->client, event->comp_data->icalcomp, TRUE); g_list_free (selected); } @@ -962,7 +1045,7 @@ on_publish (GtkWidget *widget, gpointer user_data) ECalView *cal_view; icaltimezone *utc; time_t start = time (NULL), end; - GList *comp_list, *client_list, *cl; + GList *comp_list = NULL, *client_list, *cl; cal_view = E_CAL_VIEW (user_data); @@ -972,8 +1055,7 @@ on_publish (GtkWidget *widget, gpointer user_data) client_list = e_cal_model_get_client_list (cal_view->priv->model); for (cl = client_list; cl != NULL; cl = cl->next) { - comp_list = cal_client_get_free_busy ((CalClient *) cl->data, NULL, start, end); - if (comp_list) { + if (cal_client_get_free_busy ((CalClient *) cl->data, NULL, start, end, &comp_list, NULL)) { GList *l; for (l = comp_list; l; l = l->next) { @@ -1041,14 +1123,6 @@ on_paste (GtkWidget *widget, gpointer user_data) e_cal_view_paste_clipboard (cal_view); } -static void -on_unrecur_appointment (GtkWidget *widget, gpointer user_data) -{ - ECalView *cal_view = E_CAL_VIEW (user_data); - - gnome_calendar_unrecur_selection (cal_view->priv->calendar); -} - enum { /* * This is used to "flag" events that can not be editted @@ -1142,7 +1216,6 @@ static EPopupMenu child_items [] = { E_POPUP_SEPARATOR, E_POPUP_ITEM (N_("_Delete"), GTK_SIGNAL_FUNC (on_delete_appointment), MASK_EDITABLE | MASK_SINGLE | MASK_EDITING), - E_POPUP_ITEM (N_("Make this Occurrence _Movable"), GTK_SIGNAL_FUNC (on_unrecur_appointment), MASK_RECURRING | MASK_EDITING | MASK_EDITABLE | MASK_INSTANCE), E_POPUP_ITEM (N_("Delete this _Occurrence"), GTK_SIGNAL_FUNC (on_delete_occurrence), MASK_RECURRING | MASK_EDITING | MASK_EDITABLE), E_POPUP_ITEM (N_("Delete _All Occurrences"), GTK_SIGNAL_FUNC (on_delete_appointment), MASK_RECURRING | MASK_EDITING | MASK_EDITABLE), @@ -1209,21 +1282,18 @@ setup_popup_icons (EPopupMenu *context_menu) GtkMenu * e_cal_view_create_popup_menu (ECalView *cal_view) { - gboolean being_edited, have_selection; GList *selected; EPopupMenu *context_menu; guint32 disable_mask = 0, hide_mask = 0; GtkMenu *popup; CalClient *client = NULL; - + gboolean read_only = TRUE; + g_return_val_if_fail (E_IS_CAL_VIEW (cal_view), NULL); /* get the selection */ - being_edited = FALSE; selected = e_cal_view_get_selected_events (cal_view); - have_selection = GTK_WIDGET_HAS_FOCUS (cal_view) && selected != NULL; - if (selected == NULL) { cal_view->priv->view_menu = gnome_calendar_setup_view_popup (cal_view->priv->calendar); main_items[9].submenu = cal_view->priv->view_menu; @@ -1260,15 +1330,158 @@ e_cal_view_create_popup_menu (ECalView *cal_view) client = event->comp_data->client; } - if (cal_client_is_read_only (client)) + cal_client_is_read_only (client, &read_only, NULL); + if (read_only) disable_mask |= MASK_EDITABLE; - if (being_edited) - disable_mask |= MASK_EDITING; - setup_popup_icons (context_menu); popup = e_popup_menu_create (context_menu, disable_mask, hide_mask, cal_view); g_signal_connect (popup, "selection-done", G_CALLBACK (free_view_popup), cal_view); return popup; } + +/** + * e_cal_view_new_appointment_for + * @cal_view: A calendar view. + * @dtstart: A Unix time_t that marks the beginning of the appointment. + * @dtend: A Unix time_t that marks the end of the appointment. + * @all_day: If TRUE, the dtstart and dtend are expanded to cover + * the entire day, and the event is set to TRANSPARENT. + * @meeting: Whether the appointment is a meeting or not. + * + * Opens an event editor dialog for a new appointment. + */ +void +e_cal_view_new_appointment_for (ECalView *cal_view, + time_t dtstart, time_t dtend, + gboolean all_day, + gboolean meeting) +{ + ECalViewPrivate *priv; + struct icaltimetype itt; + CalComponentDateTime dt; + CalComponent *comp; + icalcomponent *icalcomp; + CalComponentTransparency transparency; + + g_return_if_fail (E_IS_CAL_VIEW (cal_view)); + + priv = cal_view->priv; + + dt.value = &itt; + if (all_day) + dt.tzid = NULL; + else + dt.tzid = icaltimezone_get_tzid (priv->zone); + + icalcomp = e_cal_model_create_component_with_defaults (priv->model); + comp = cal_component_new (); + cal_component_set_icalcomponent (comp, icalcomp); + + /* DTSTART, DTEND */ + itt = icaltime_from_timet_with_zone (dtstart, FALSE, priv->zone); + if (all_day) { + itt.hour = itt.minute = itt.second = 0; + itt.is_date = TRUE; + } + cal_component_set_dtstart (comp, &dt); + + itt = icaltime_from_timet_with_zone (dtend, FALSE, priv->zone); + if (all_day) { + /* We round it up to the end of the day, unless it is + already set to midnight */ + if (itt.hour != 0 || itt.minute != 0 || itt.second != 0) { + icaltime_adjust (&itt, 1, 0, 0, 0); + } + itt.hour = itt.minute = itt.second = 0; + itt.is_date = TRUE; + } + cal_component_set_dtend (comp, &dt); + + /* TRANSPARENCY */ + transparency = all_day ? CAL_COMPONENT_TRANSP_TRANSPARENT + : CAL_COMPONENT_TRANSP_OPAQUE; + cal_component_set_transparency (comp, transparency); + + /* CATEGORY */ + cal_component_set_categories (comp, priv->default_category); + + /* edit the object */ + cal_component_commit_sequence (comp); + + e_cal_view_edit_appointment (cal_view, + e_cal_model_get_default_client (priv->model), + icalcomp, meeting); + + g_object_unref (comp); +} + +/** + * e_cal_view_new_appointment + * @cal_view: A calendar view. + * + * Opens an event editor dialog for a new appointment. The appointment's + * start and end times are set to the currently selected time range in + * the calendar view. + */ +void +e_cal_view_new_appointment (ECalView *cal_view) +{ + time_t dtstart, dtend; + + g_return_if_fail (E_IS_CAL_VIEW (cal_view)); + + e_cal_view_get_selected_time_range (cal_view, &dtstart, &dtend); + e_cal_view_new_appointment_for (cal_view, dtstart, dtend, FALSE, FALSE); +} + +/** + * e_cal_view_edit_appointment + * @cal_view: A calendar view. + * @client: Calendar client. + * @icalcomp: The object to be edited. + * @meeting: Whether the appointment is a meeting or not. + * + * Opens an editor window to allow the user to edit the selected + * object. + */ +void +e_cal_view_edit_appointment (ECalView *cal_view, + CalClient *client, + icalcomponent *icalcomp, + gboolean meeting) +{ + ECalViewPrivate *priv; + CompEditor *ce; + const char *uid; + CalComponent *comp; + + g_return_if_fail (E_IS_CAL_VIEW (cal_view)); + g_return_if_fail (IS_CAL_CLIENT (client)); + g_return_if_fail (icalcomp != NULL); + + priv = cal_view->priv; + + uid = icalcomponent_get_uid (icalcomp); + + ce = e_comp_editor_registry_find (comp_editor_registry, uid); + if (!ce) { + EventEditor *ee; + + ee = event_editor_new (client); + ce = COMP_EDITOR (ee); + + comp = cal_component_new (); + cal_component_set_icalcomponent (comp, icalcomponent_new_clone (icalcomp)); + comp_editor_edit_comp (ce, comp); + if (meeting) + event_editor_show_meeting (ee); + + e_comp_editor_registry_add (comp_editor_registry, ce, FALSE); + + g_object_unref (comp); + } + + comp_editor_focus (ce); +} diff --git a/calendar/gui/e-calendar-view.h b/calendar/gui/e-calendar-view.h index ea7c11a00d..9a09a5236a 100644 --- a/calendar/gui/e-calendar-view.h +++ b/calendar/gui/e-calendar-view.h @@ -96,6 +96,8 @@ ECalModel *e_cal_view_get_model (ECalView *cal_view); void e_cal_view_set_model (ECalView *cal_view, ECalModel *model); icaltimezone *e_cal_view_get_timezone (ECalView *cal_view); void e_cal_view_set_timezone (ECalView *cal_view, icaltimezone *zone); +const char *e_cal_view_get_default_category (ECalView *cal_view); +void e_cal_view_set_default_category (ECalView *cal_view, const char *category); void e_cal_view_set_status_message (ECalView *cal_view, const gchar *message); @@ -114,6 +116,17 @@ void e_cal_view_delete_selected_occurrence (ECalView *cal_view); GtkMenu *e_cal_view_create_popup_menu (ECalView *cal_view); +void e_cal_view_new_appointment_for (ECalView *cal_view, + time_t dtstart, + time_t dtend, + gboolean all_day, + gboolean meeting); +void e_cal_view_new_appointment (ECalView *cal_view); +void e_cal_view_edit_appointment (ECalView *cal_view, + CalClient *client, + icalcomponent *icalcomp, + gboolean meeting); + G_END_DECLS #endif diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c index a2a4f09d56..b4ec9faea0 100644 --- a/calendar/gui/e-day-view.c +++ b/calendar/gui/e-day-view.c @@ -65,6 +65,7 @@ #include "calendar-commands.h" #include "calendar-config.h" #include "goto.h" +#include "e-cal-model-calendar.h" #include "e-day-view-time-item.h" #include "e-day-view-top-item.h" #include "e-day-view-layout.h" @@ -592,8 +593,6 @@ e_day_view_init (EDayView *day_view) day_view->auto_scroll_timeout_id = 0; - day_view->default_category = NULL; - day_view->large_font_desc = NULL; /* String to use in 12-hour time format for times in the morning. */ @@ -850,8 +849,11 @@ GtkWidget * e_day_view_new (void) { GtkWidget *day_view; + ECalModel *model; + + model = E_CAL_MODEL (e_cal_model_calendar_new ()); - day_view = GTK_WIDGET (g_object_new (e_day_view_get_type (), NULL)); + day_view = GTK_WIDGET (g_object_new (e_day_view_get_type (), "model", model, NULL)); return day_view; } @@ -881,12 +883,6 @@ e_day_view_destroy (GtkObject *object) day_view->large_font_desc = NULL; } - if (day_view->default_category) { - g_free (day_view->default_category); - day_view->default_category = NULL; - } - - if (day_view->normal_cursor) { gdk_cursor_unref (day_view->normal_cursor); day_view->normal_cursor = NULL; @@ -1429,26 +1425,6 @@ e_day_view_focus_out (GtkWidget *widget, GdkEventFocus *event) return FALSE; } -/** - * e_day_view_set_default_category: - * @day_view: A day view. - * @category: Default category name or NULL for no category. - * - * Sets the default category that will be used when creating new calendar - * components from the day view. - **/ -void -e_day_view_set_default_category (EDayView *day_view, const char *category) -{ - g_return_if_fail (day_view != NULL); - g_return_if_fail (E_IS_DAY_VIEW (day_view)); - - if (day_view->default_category) - g_free (day_view->default_category); - - day_view->default_category = g_strdup (category); -} - static gboolean e_day_view_update_event_cb (EDayView *day_view, gint day, @@ -1794,6 +1770,9 @@ e_day_view_find_event_from_uid (EDayView *day_view, gint day, event_num; const char *u; + if (!uid) + return FALSE; + for (day = 0; day < day_view->days_shown; day++) { for (event_num = 0; event_num < day_view->events[day]->len; event_num++) { @@ -2048,7 +2027,6 @@ e_day_view_find_work_week_start (EDayView *day_view, return icaltime_as_timet_with_zone (tt, e_cal_view_get_timezone (E_CAL_VIEW (day_view))); } - /* Returns the selected time range. */ static void e_day_view_get_selected_time_range (ECalView *cal_view, time_t *start_time, time_t *end_time) @@ -2123,6 +2101,8 @@ e_day_view_recalc_day_starts (EDayView *day_view, day_view->lower = start_time; day_view->upper = day_view->day_starts[day_view->days_shown]; + + e_day_view_update_query (day_view); } @@ -2588,9 +2568,9 @@ e_day_view_on_top_canvas_button_press (GtkWidget *widget, time_t dtstart, dtend; e_day_view_get_selected_time_range ((ECalView *) day_view, &dtstart, &dtend); - gnome_calendar_new_appointment_for (e_cal_view_get_calendar (E_CAL_VIEW (day_view)), - dtstart, dtend, - TRUE, FALSE); + e_cal_view_new_appointment_for (E_CAL_VIEW (day_view), + dtstart, dtend, + TRUE, FALSE); return TRUE; } @@ -2709,9 +2689,9 @@ e_day_view_on_main_canvas_button_press (GtkWidget *widget, time_t dtstart, dtend; e_day_view_get_selected_time_range ((ECalView *) day_view, &dtstart, &dtend); - gnome_calendar_new_appointment_for (e_cal_view_get_calendar (E_CAL_VIEW (day_view)), - dtstart, dtend, - FALSE, FALSE); + e_cal_view_new_appointment_for (E_CAL_VIEW (day_view), + dtstart, dtend, + FALSE, FALSE); return TRUE; } @@ -3101,7 +3081,6 @@ e_day_view_on_event_double_click (EDayView *day_view, gint event_num) { EDayViewEvent *event; - GnomeCalendar *calendar; if (day == -1) event = &g_array_index (day_view->long_events, EDayViewEvent, @@ -3112,11 +3091,9 @@ e_day_view_on_event_double_click (EDayView *day_view, e_day_view_stop_editing_event (day_view); - calendar = e_cal_view_get_calendar (E_CAL_VIEW (day_view)); - if (calendar) - gnome_calendar_edit_object (calendar, event->comp_data->client, event->comp_data->icalcomp, FALSE); - else - g_warning ("Calendar not set"); + e_cal_view_edit_appointment (E_CAL_VIEW (day_view), + event->comp_data->client, + event->comp_data->icalcomp, FALSE); } static void @@ -3207,7 +3184,6 @@ process_component (EDayView *day_view, ECalModelComponent *comp_data) EDayViewEvent, event_num); if (!cal_util_component_has_recurrences (comp_data->icalcomp) - && !cal_component_has_recurrences (event->comp_data->icalcomp) && cal_util_event_dates_match (event->comp_data->icalcomp, comp_data->icalcomp)) { #if 0 g_print ("updated object's dates unchanged\n"); @@ -3228,17 +3204,18 @@ process_component (EDayView *day_view, ECalModelComponent *comp_data) NULL); } - /* Add the occurrences of the event. */ + /* Add the occurrences of the event */ comp = cal_component_new (); cal_component_set_icalcomponent (comp, icalcomponent_new_clone (comp_data->icalcomp)); + add_event_data.day_view = day_view; add_event_data.comp_data = comp_data; cal_recur_generate_instances (comp, day_view->lower, day_view->upper, e_day_view_add_event, &add_event_data, - cal_client_resolve_tzid_cb, - comp_data->client, + cal_client_resolve_tzid_cb, comp_data->client, e_cal_view_get_timezone (E_CAL_VIEW (day_view))); + g_object_unref (comp); e_day_view_queue_layout (day_view); @@ -3258,8 +3235,6 @@ e_day_view_update_query (ECalView *cal_view) e_day_view_free_events (day_view); e_day_view_queue_layout (day_view); - e_cal_view_set_status_message (E_CAL_VIEW (day_view), _("Searching")); - rows = e_table_model_row_count (E_TABLE_MODEL (e_cal_view_get_model (E_CAL_VIEW (day_view)))); for (r = 0; r < rows; r++) { ECalModelComponent *comp_data; @@ -3268,8 +3243,6 @@ e_day_view_update_query (ECalView *cal_view) g_assert (comp_data != NULL); process_component (day_view, comp_data); } - - e_cal_view_set_status_message (E_CAL_VIEW (day_view), NULL); } static void @@ -3282,67 +3255,6 @@ e_day_view_on_event_right_click (EDayView *day_view, day, event_num); } -void -e_day_view_unrecur_appointment (EDayView *day_view) -{ - EDayViewEvent *event; - CalComponent *comp, *new_comp; - CalComponentDateTime date; - struct icaltimetype itt; - - event = e_day_view_get_popup_menu_event (day_view); - if (event == NULL) - return; - - date.value = &itt; - date.tzid = NULL; - - /* For the recurring object, we add an exception to get rid of the - instance. */ - - comp = cal_component_new (); - cal_component_set_icalcomponent (comp, icalcomponent_new_clone (event->comp_data->icalcomp)); - cal_comp_util_add_exdate (comp, event->start, e_cal_view_get_timezone (E_CAL_VIEW (day_view))); - - /* For the unrecurred instance we duplicate the original object, - create a new uid for it, get rid of the recurrence rules, and set - the start & end times to the instances times. */ - new_comp = cal_component_new (); - cal_component_set_icalcomponent (comp, icalcomponent_new_clone (event->comp_data->icalcomp)); - cal_component_set_uid (new_comp, cal_component_gen_uid ()); - cal_component_set_rdate_list (new_comp, NULL); - cal_component_set_rrule_list (new_comp, NULL); - cal_component_set_exdate_list (new_comp, NULL); - cal_component_set_exrule_list (new_comp, NULL); - - date.value = &itt; - date.tzid = icaltimezone_get_tzid (e_cal_view_get_timezone (E_CAL_VIEW (day_view))); - - *date.value = icaltime_from_timet_with_zone (event->start, FALSE, - e_cal_view_get_timezone (E_CAL_VIEW (day_view))); - cal_component_set_dtstart (new_comp, &date); - *date.value = icaltime_from_timet_with_zone (event->end, FALSE, - e_cal_view_get_timezone (E_CAL_VIEW (day_view))); - cal_component_set_dtend (new_comp, &date); - - - /* Now update both CalComponents. Note that we do this last since at - * present the updates happen synchronously so our event may disappear. - */ - if (cal_client_update_object (event->comp_data->client, comp) - != CAL_CLIENT_RESULT_SUCCESS) - g_message ("e_day_view_on_unrecur_appointment(): Could not update the object!"); - - g_object_unref (comp); - - if (cal_client_update_object (event->comp_data->client, new_comp) - != CAL_CLIENT_RESULT_SUCCESS) - g_message ("e_day_view_on_unrecur_appointment(): Could not update the object!"); - - g_object_unref (new_comp); -} - - static EDayViewEvent* e_day_view_get_popup_menu_event (EDayView *day_view) { @@ -3841,7 +3753,9 @@ e_day_view_finish_long_event_resize (EDayView *day_view) struct icaltimetype itt; time_t dt; CalClient *client; - + CalObjModType mod = CALOBJ_MOD_ALL; + GtkWindow *toplevel; + event_num = day_view->resize_event_num; event = &g_array_index (day_view->long_events, EDayViewEvent, event_num); @@ -3870,31 +3784,26 @@ e_day_view_finish_long_event_resize (EDayView *day_view) e_cal_view_get_timezone (E_CAL_VIEW (day_view))); cal_component_set_dtend (comp, &date); } - - if (cal_component_is_instance (comp)) { - CalObjModType mod; - - if (recur_component_dialog (comp, &mod, NULL)) { - if (cal_client_update_object_with_mod (client, comp, mod) == CAL_CLIENT_RESULT_SUCCESS) { - if (itip_organizer_is_user (comp, client) && - send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (day_view)), - client, comp, FALSE)) - itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, client, NULL); - } else { - g_message ("e_day_view_finish_resize(): Could not update the object!"); - } - } else { + + if (cal_component_has_recurrences (comp)) { + if (!recur_component_dialog (comp, &mod, NULL)) { gtk_widget_queue_draw (day_view->top_canvas); - } - } else if (cal_client_update_object (client, comp) == CAL_CLIENT_RESULT_SUCCESS) { - if (itip_organizer_is_user (comp, client) && - send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (day_view)), - client, comp, TRUE)) - itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, client, NULL); - } else { - g_message ("e_day_view_finish_long_event_resize(): Could not update the object!"); - } - + goto out; + } + } + + toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (day_view))); + + if (cal_client_modify_object (client, cal_component_get_icalcomponent (comp), mod, NULL)) { + if (itip_organizer_is_user (comp, client) && + send_component_dialog (toplevel, client, comp, TRUE)) { + itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, client, NULL); + } else { + g_message (G_STRLOC ": Could not update the object!"); + } + } + + out: gnome_canvas_item_hide (day_view->resize_long_event_rect_item); day_view->resize_drag_pos = E_CAL_VIEW_POS_NONE; @@ -3915,6 +3824,8 @@ e_day_view_finish_resize (EDayView *day_view) struct icaltimetype itt; time_t dt; CalClient *client; + CalObjModType mod = CALOBJ_MOD_ALL; + GtkWindow *toplevel; day = day_view->resize_event_day; event_num = day_view->resize_event_num; @@ -3957,29 +3868,26 @@ e_day_view_finish_resize (EDayView *day_view) day_view->resize_drag_pos = E_CAL_VIEW_POS_NONE; - if (cal_component_is_instance (comp)) { - CalObjModType mod; + if (cal_component_has_recurrences (comp)) { + if (!recur_component_dialog (comp, &mod, NULL)) { + gtk_widget_queue_draw (day_view->top_canvas); + goto out; + } + } + + toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (day_view))); - if (recur_component_dialog (comp, &mod, NULL)) { - if (cal_client_update_object_with_mod (client, comp, mod) == CAL_CLIENT_RESULT_SUCCESS) { - if (itip_organizer_is_user (comp, client) && - send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (day_view)), - client, comp, FALSE)) - itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, client, NULL); - } else { - g_message ("e_day_view_finish_resize(): Could not update the object!"); - } - } else { - gtk_widget_queue_draw (day_view->main_canvas); - } - } else if (cal_client_update_object (client, comp) == CAL_CLIENT_RESULT_SUCCESS) { + cal_component_commit_sequence (comp); + if (cal_client_modify_object (client, cal_component_get_icalcomponent (comp), mod, NULL)) { if (itip_organizer_is_user (comp, client) && - send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (day_view)), client, comp, FALSE)) + send_component_dialog (toplevel, client, comp, TRUE)) { itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, client, NULL); - } else { - g_message ("e_day_view_finish_resize(): Could not update the object!"); - } - + } else { + g_message (G_STRLOC ": Could not update the object!"); + } + } + + out: g_object_unref (comp); } @@ -4774,6 +4682,8 @@ e_day_view_do_key_press (GtkWidget *widget, GdkEventKey *event) /* Add a new event covering the selected range */ icalcomp = e_cal_model_create_component_with_defaults (e_cal_view_get_model (E_CAL_VIEW (day_view))); + if (!icalcomp) + return FALSE; uid = icalcomponent_get_uid (icalcomp); comp = cal_component_new (); @@ -4801,7 +4711,8 @@ e_day_view_do_key_press (GtkWidget *widget, GdkEventKey *event) cal_component_set_dtstart (comp, &start_dt); cal_component_set_dtend (comp, &end_dt); - cal_component_set_categories (comp, day_view->default_category); + cal_component_set_categories ( + comp, e_cal_view_get_default_category (E_CAL_VIEW (day_view))); /* We add the event locally and start editing it. We don't send it to the server until the user finishes editing it. */ @@ -5777,7 +5688,8 @@ e_day_view_on_editing_stopped (EDayView *day_view, gchar *text = NULL; CalComponentText summary; CalComponent *comp; - + gboolean on_server; + /* Note: the item we are passed here isn't reliable, so we just stop the edit of whatever item was being edited. We also receive this event twice for some reason. */ @@ -5822,8 +5734,9 @@ e_day_view_on_editing_stopped (EDayView *day_view, comp = cal_component_new (); cal_component_set_icalcomponent (comp, icalcomponent_new_clone (event->comp_data->icalcomp)); - if (string_is_empty (text) && - !cal_comp_is_on_server (comp, event->comp_data->client)) { + on_server = cal_comp_is_on_server (comp, event->comp_data->client); + + if (string_is_empty (text) && !on_server) { const char *uid; cal_component_get_uid (comp, &uid); @@ -5845,34 +5758,34 @@ e_day_view_on_editing_stopped (EDayView *day_view, e_day_view_update_event_label (day_view, day, event_num); } else if (summary.value || !string_is_empty (text)) { + icalcomponent *icalcomp = cal_component_get_icalcomponent (comp); + summary.value = text; summary.altrep = NULL; cal_component_set_summary (comp, &summary); - if (cal_component_is_instance (comp)) { - CalObjModType mod; - - if (recur_component_dialog (comp, &mod, NULL)) { - if (cal_client_update_object_with_mod (event->comp_data->client, comp, mod) - == CAL_CLIENT_RESULT_SUCCESS) { - if (itip_organizer_is_user (comp, event->comp_data->client) - && send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (day_view)), - event->comp_data->client, comp, FALSE)) - itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, - event->comp_data->client, NULL); - } else { - g_message ("e_day_view_on_editing_stopped(): Could not update the object!"); + if (!on_server) { + if (!cal_client_create_object (event->comp_data->client, icalcomp, NULL, NULL)) + g_message (G_STRLOC ": Could not create the object!"); + } else { + CalObjModType mod = CALOBJ_MOD_ALL; + GtkWindow *toplevel; + if (cal_component_has_recurrences (comp)) { + if (!recur_component_dialog (comp, &mod, NULL)) { + goto out; } } - } else if (cal_client_update_object (event->comp_data->client, comp) == CAL_CLIENT_RESULT_SUCCESS) { - if (itip_organizer_is_user (comp, event->comp_data->client) && - send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (day_view)), - event->comp_data->client, comp, FALSE)) - itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, - event->comp_data->client, NULL); - } else { - g_message ("e_day_view_on_editing_stopped(): Could not update the object!"); + + /* FIXME When sending here, what exactly should we send? */ + toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (day_view))); + if (cal_client_modify_object (event->comp_data->client, icalcomp, mod, NULL)) { + if (itip_organizer_is_user (comp, event->comp_data->client) + && send_component_dialog (toplevel, event->comp_data->client, comp, FALSE)) + itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, + event->comp_data->client, NULL); + } } + } out: @@ -6881,7 +6794,10 @@ e_day_view_on_top_canvas_drag_data_received (GtkWidget *widget, x, y, &day, NULL); if (pos != E_CAL_VIEW_POS_OUTSIDE) { + CalObjModType mod = CALOBJ_MOD_ALL; + GtkWindow *toplevel; const char *uid; + num_days = 1; start_offset = 0; end_offset = 0; @@ -6972,33 +6888,20 @@ e_day_view_on_top_canvas_drag_data_received (GtkWidget *widget, if (event->canvas_item) gnome_canvas_item_show (event->canvas_item); - if (cal_component_is_instance (comp)) { - CalObjModType mod; - - if (recur_component_dialog (comp, &mod, NULL)) { - if (cal_client_update_object_with_mod (client, comp, mod) == CAL_CLIENT_RESULT_SUCCESS) { - if (itip_organizer_is_user (comp, client) - && send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (day_view)), - client, comp, FALSE)) - itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, - client, NULL); - } else { - g_message ("e_day_view_on_top_canvas_drag_data_received(): Could " - "not update the object!"); - } - } - } else if (cal_client_update_object (client, comp) - == CAL_CLIENT_RESULT_SUCCESS) { - if (itip_organizer_is_user (comp, client) && - send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (day_view)), - client, comp, FALSE)) - itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, - client, NULL); - } else { - g_message ("e_day_view_on_top_canvas_drag_data_received(): Could " - "not update the object!"); + if (cal_component_has_recurrences (comp)) { + if (!recur_component_dialog (comp, &mod, NULL)) + return; } + toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (day_view))); + + if (cal_client_modify_object (client, cal_component_get_icalcomponent (comp), mod, NULL)) { + if (itip_organizer_is_user (comp, client) + && send_component_dialog (toplevel, client, comp, FALSE)) + itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, + client, NULL); + } + g_object_unref (comp); return; @@ -7044,7 +6947,10 @@ e_day_view_on_main_canvas_drag_data_received (GtkWidget *widget, x, y, &day, &row, NULL); if (pos != E_CAL_VIEW_POS_OUTSIDE) { + CalObjModType mod = CALOBJ_MOD_ALL; + GtkWindow *toplevel; const char *uid; + num_rows = 1; start_offset = 0; end_offset = 0; @@ -7109,30 +7015,20 @@ e_day_view_on_main_canvas_drag_data_received (GtkWidget *widget, if (event->canvas_item) gnome_canvas_item_show (event->canvas_item); - if (cal_component_is_instance (comp)) { - CalObjModType mod; - - if (recur_component_dialog (comp, &mod, NULL)) { - if (cal_client_update_object_with_mod (client, comp, mod) == CAL_CLIENT_RESULT_SUCCESS) { - if (itip_organizer_is_user (comp, client) - && send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (day_view)), - client, comp, FALSE)) - itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, - client, NULL); - } else { - g_message ("e_day_view_on_top_canvas_drag_data_received(): Could " - "not update the object!"); - } + if (cal_component_has_recurrences (comp)) { + if (!recur_component_dialog (comp, &mod, NULL)) { + g_object_unref (comp); + return; } - } else if (cal_client_update_object (client, comp) == CAL_CLIENT_RESULT_SUCCESS) { - if (itip_organizer_is_user (comp, client) && - send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (day_view)), - client, comp, FALSE)) - itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, + } + + toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (day_view))); + + if (cal_client_modify_object (client, cal_component_get_icalcomponent (comp), mod, NULL)) { + if (itip_organizer_is_user (comp, client) + && send_component_dialog (toplevel, client, comp, FALSE)) + itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, client, NULL); - } else { - g_message ("e_day_view_on_main_canvas_drag_data_received(): " - "Could not update the object!"); } g_object_unref (comp); diff --git a/calendar/gui/e-day-view.h b/calendar/gui/e-day-view.h index 1c39fd5844..decd281127 100644 --- a/calendar/gui/e-day-view.h +++ b/calendar/gui/e-day-view.h @@ -453,9 +453,6 @@ struct _EDayView gint am_string_width; gint pm_string_width; - /* The default category for new events */ - char *default_category; - /* The activity client used to show messages on the status bar. */ EvolutionActivityClient *activity; }; @@ -472,9 +469,6 @@ GtkWidget* e_day_view_new (void); void e_day_view_set_query (EDayView *day_view, const char *sexp); -void e_day_view_set_default_category (EDayView *day_view, - const char *category); - /* Whether we are displaying a work-week, in which case the display always starts on the first day of the working week. */ gboolean e_day_view_get_work_week_view (EDayView *day_view); @@ -528,7 +522,6 @@ void e_day_view_set_week_start_day (EDayView *day_view, gint week_start_day); void e_day_view_delete_occurrence (EDayView *day_view); -void e_day_view_unrecur_appointment (EDayView *day_view); /* Returns the number of selected events (0 or 1 at present). */ gint e_day_view_get_num_events_selected (EDayView *day_view); diff --git a/calendar/gui/e-itip-control.c b/calendar/gui/e-itip-control.c index 8b39b82b8c..d5e24c8936 100644 --- a/calendar/gui/e-itip-control.c +++ b/calendar/gui/e-itip-control.c @@ -94,8 +94,6 @@ struct _EItipControlPrivate { #define HTML_BODY_END "</body>" #define HTML_FOOTER "</html>" -extern EvolutionShellClient *global_shell_client; - /* We intentionally use "calendar" instead of "calendar / *" here. We * don't want public calendars. */ @@ -132,63 +130,26 @@ class_init (EItipControlClass *klass) object_class->finalize = finalize; } - -/* Calendar Server routines */ -static void -start_calendar_server_cb (CalClient *cal_client, - CalClientOpenStatus status, - gpointer data) -{ - int *success = data; - int orig = *success; - - if (status == CAL_CLIENT_OPEN_SUCCESS) - *success = 1; - else - *success = 0; - - if (orig != -1) - gtk_main_quit (); /* end the sub event loop */ -} - static CalClient * start_calendar_server (EItipControl *itip, char *uri) { CalClient *client; - int success = -1; - - client = cal_client_new (); - - g_signal_connect (client, "cal_opened", G_CALLBACK (start_calendar_server_cb), &success); - - if (!cal_client_open_calendar (client, uri, TRUE)) - goto error; - - /* run a sub event loop to turn cal-client's async load - notification into a synchronous call */ - if (success == -1 && !itip->priv->destroyed) { - success = 0; - - gtk_signal_connect (GTK_OBJECT (itip), "destroy", - gtk_main_quit, NULL); - - gtk_main (); - - gtk_signal_disconnect_by_func (GTK_OBJECT (itip), - gtk_main_quit, NULL); - } + GError *error = NULL; - if (success == 1) - return client; + client = cal_client_new (uri, CALOBJ_TYPE_EVENT); -error: - g_object_unref (client); + if (!cal_client_open (client, TRUE, &error)) { + g_warning (_("start_calendar_server(): %s"), error->message); + g_error_free (error); + g_object_unref (client); + return NULL; + } - return NULL; + return client; } static gboolean -start_default_server_async (EItipControl *itip, CalClient *client, gboolean tasks) +start_default_server (EItipControl *itip, CalClient *client, gboolean tasks) { if (tasks) return cal_client_open_default_tasks (client, FALSE); @@ -196,6 +157,7 @@ start_default_server_async (EItipControl *itip, CalClient *client, gboolean task return cal_client_open_default_calendar (client, FALSE); } +#if 0 /* EPFIXME, rewrite this */ static GPtrArray * get_servers (EItipControl *itip, EvolutionShellClient *shell_client, const char *possible_types[], gboolean tasks) { @@ -263,6 +225,7 @@ get_servers (EItipControl *itip, EvolutionShellClient *shell_client, const char return servers; } +#endif static CalClient * find_server (GPtrArray *servers, CalComponent *comp) @@ -274,11 +237,9 @@ find_server (GPtrArray *servers, CalComponent *comp) for (i = 0; i < servers->len; i++) { CalClient *client; icalcomponent *icalcomp; - CalClientGetStatus status; client = g_ptr_array_index (servers, i); - status = cal_client_get_object (client, uid, &icalcomp); - if (status == CAL_CLIENT_GET_SUCCESS) { + if (cal_client_get_object (client, uid, NULL, &icalcomp, NULL)) { icalcomponent_free (icalcomp); g_object_ref (client); @@ -540,8 +501,7 @@ find_attendee (icalcomponent *ical_comp, const char *address) for (prop = icalcomponent_get_first_property (ical_comp, ICAL_ATTENDEE_PROPERTY); prop != NULL; - prop = icalcomponent_get_next_property (ical_comp, ICAL_ATTENDEE_PROPERTY)) - { + prop = icalcomponent_get_next_property (ical_comp, ICAL_ATTENDEE_PROPERTY)) { icalvalue *value; const char *attendee; char *text; @@ -762,6 +722,7 @@ write_recurrence_piece (EItipControl *itip, CalComponent *comp, } else if (!icaltime_is_null_time (r->until)) { CalComponentDateTime dt; + /* FIXME This should get the tzid id, not the whole zone */ dt.value = &r->until; dt.tzid = r->until.zone; @@ -1220,7 +1181,7 @@ get_real_item (EItipControl *itip) CalComponent *comp; icalcomponent *icalcomp; CalComponentVType type; - CalClientGetStatus status = CAL_CLIENT_GET_NOT_FOUND; + gboolean found = FALSE; const char *uid; priv = itip->priv; @@ -1231,17 +1192,17 @@ get_real_item (EItipControl *itip) switch (type) { case CAL_COMPONENT_EVENT: if (priv->event_client != NULL) - status = cal_client_get_object (priv->event_client, uid, &icalcomp); + found = cal_client_get_object (priv->event_client, uid, NULL, &icalcomp, NULL); break; case CAL_COMPONENT_TODO: if (priv->task_client != NULL) - status = cal_client_get_object (priv->task_client, uid, &icalcomp); + found = cal_client_get_object (priv->task_client, uid, NULL, &icalcomp, NULL); break; default: - status = CAL_CLIENT_GET_NOT_FOUND; + found = FALSE; } - if (status != CAL_CLIENT_GET_SUCCESS) + if (!found) return NULL; comp = cal_component_new (); @@ -1568,13 +1529,18 @@ show_current (EItipControl *itip) switch (type) { case CAL_COMPONENT_EVENT: - if (!priv->event_clients) - priv->event_clients = get_servers (itip, global_shell_client, calendar_types, FALSE); + if (!priv->event_clients) { + priv->event_clients = g_ptr_array_new (); + /* EPFIXME */ + /* priv->event_clients = get_servers (itip, global_shell_client, calendar_types, FALSE); */ + } show_current_event (itip); break; case CAL_COMPONENT_TODO: - if (!priv->task_clients) - priv->task_clients = get_servers (itip, global_shell_client, tasks_types, TRUE); + if (!priv->task_clients) { + /* EPFIXME */ + /* priv->task_clients = get_servers (itip, global_shell_client, tasks_types, TRUE); */ + } show_current_todo (itip); break; case CAL_COMPONENT_FREEBUSY: @@ -1853,7 +1819,6 @@ update_item (EItipControl *itip) CalClient *client; CalComponentVType type; GtkWidget *dialog; - CalClientResult result; priv = itip->priv; @@ -1881,32 +1846,18 @@ update_item (EItipControl *itip) icalcomponent_add_component (priv->top_level, clone); icalcomponent_set_method (priv->top_level, priv->method); - result = cal_client_update_objects (client, priv->top_level); - switch (result) { - case CAL_CLIENT_RESULT_INVALID_OBJECT : - dialog = gnome_warning_dialog (_("Object is invalid and cannot be updated\n")); - break; - case CAL_CLIENT_RESULT_CORBA_ERROR : - dialog = gnome_warning_dialog (_("There was an error on the CORBA system\n")); - break; - case CAL_CLIENT_RESULT_NOT_FOUND : - dialog = gnome_warning_dialog (_("Object could not be found\n")); - break; - case CAL_CLIENT_RESULT_PERMISSION_DENIED : - dialog = gnome_warning_dialog (_("You do not have the right permissions to update the calendar\n")); - break; - case CAL_CLIENT_RESULT_SUCCESS : - dialog = gnome_ok_dialog (_("Update complete\n")); - break; - default : + /* FIXME Better error dialog */ + if (!cal_client_receive_objects (client, priv->top_level, NULL)) { dialog = gnome_warning_dialog (_("Calendar file could not be updated!\n")); - break; + } else { + dialog = gnome_ok_dialog (_("Update complete\n")); } gnome_dialog_run_and_close (GNOME_DIALOG (dialog)); icalcomponent_remove_component (priv->top_level, clone); } +#if 0 static void update_attendee_status (EItipControl *itip) { @@ -1936,7 +1887,7 @@ update_attendee_status (EItipControl *itip) /* Obtain our version */ cal_component_get_uid (priv->comp, &uid); - status = cal_client_get_object (client, uid, &icalcomp); + status = cal_client_get_object (client, uid, NULL, &icalcomp); if (status == CAL_CLIENT_GET_SUCCESS) { GSList *attendees; @@ -2010,6 +1961,7 @@ update_attendee_status (EItipControl *itip) g_object_unref (comp); gnome_dialog_run_and_close (GNOME_DIALOG (dialog)); } +#endif static void remove_item (EItipControl *itip) @@ -2019,7 +1971,7 @@ remove_item (EItipControl *itip) CalComponentVType type; const char *uid; GtkWidget *dialog; - CalClientResult result; + GError *error = NULL; priv = itip->priv; @@ -2033,13 +1985,15 @@ remove_item (EItipControl *itip) return; cal_component_get_uid (priv->comp, &uid); - result = cal_client_remove_object (client, uid); - if (result == CAL_CLIENT_RESULT_SUCCESS || result == CAL_CLIENT_RESULT_NOT_FOUND) { + cal_client_remove_object (client, uid, &error); + if (!error || error->code == E_CALENDAR_STATUS_OBJECT_NOT_FOUND) { dialog = gnome_ok_dialog (_("Removal Complete")); gnome_dialog_run_and_close (GNOME_DIALOG (dialog)); } else { - delete_error_dialog (result, type); - } + delete_error_dialog (error, type); + } + + g_clear_error (&error); } static void @@ -2081,7 +2035,7 @@ send_freebusy (EItipControl *itip) CalComponentDateTime datetime; time_t start, end; GtkWidget *dialog; - GList *comp_list; + GList *comp_list = NULL; icaltimezone *zone; priv = itip->priv; @@ -2106,9 +2060,7 @@ send_freebusy (EItipControl *itip) end = icaltime_as_timet_with_zone (*datetime.value, zone); cal_component_free_datetime (&datetime); - comp_list = cal_client_get_free_busy (priv->event_client, NULL, start, end); - - if (comp_list) { + if (cal_client_get_free_busy (priv->event_client, NULL, start, end, &comp_list, NULL)) { GList *l; for (l = comp_list; l; l = l->next) { @@ -2210,6 +2162,7 @@ default_server_started_cb (CalClient *client, CalClientOpenStatus status, gpoint vtype = cal_component_get_vtype (priv->comp); switch (vtype) { +#if 0 /* EPFIXME */ case CAL_COMPONENT_EVENT: button = evolution_folder_selector_button_new ( global_shell_client, _("Select Calendar Folder"), @@ -2222,6 +2175,7 @@ default_server_started_cb (CalClient *client, CalClientOpenStatus status, gpoint calendar_config_default_tasks_folder (), tasks_types); break; +#endif default: button = NULL; } @@ -2251,29 +2205,30 @@ object_requested_cb (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data) context = g_new0 (ObjectRequestContext, 1); context->itip = itip; context->eb = eb; - context->client = cal_client_new (); - - g_object_ref (itip); - g_signal_connect (context->client, "cal_opened", - G_CALLBACK (default_server_started_cb), context); + /* FIXME: use the default URIs */ switch (vtype) { case CAL_COMPONENT_EVENT: - success = start_default_server_async (itip, context->client, FALSE); + context->client = cal_client_new ("", CALOBJ_TYPE_EVENT); + success = start_default_server (itip, context->client, FALSE); break; case CAL_COMPONENT_TODO: - success = start_default_server_async (itip, context->client, TRUE); + context->client = cal_client_new ("", CALOBJ_TYPE_TODO); + success = start_default_server (itip, context->client, TRUE); break; default: - success = FALSE; + g_free (context); + return FALSE; } if (!success) { - g_object_unref (itip); g_object_unref (context->client); g_free (context); + return FALSE; } + g_object_ref (itip); + return TRUE; } @@ -2330,7 +2285,8 @@ ok_clicked_cb (GtkHTML *html, const gchar *method, const gchar *url, const gchar send_freebusy (itip); break; case 'R': - update_attendee_status (itip); + /* FIXME Make sure this does the right thing in the backend */ + update_item (itip); break; case 'S': send_item (itip); diff --git a/calendar/gui/e-meeting-list-view.c b/calendar/gui/e-meeting-list-view.c index 7d3a4ce6c6..64463fdcb6 100644 --- a/calendar/gui/e-meeting-list-view.c +++ b/calendar/gui/e-meeting-list-view.c @@ -35,11 +35,7 @@ #include <libgnome/gnome-util.h> #include <libgnomevfs/gnome-vfs.h> #include <ebook/e-book.h> -#include <ebook/e-book-util.h> -#include <ebook/e-card-types.h> -#include <ebook/e-card-cursor.h> -#include <ebook/e-card.h> -#include <ebook/e-card-simple.h> +#include <ebook/e-vcard.h> #include <cal-util/cal-component.h> #include <cal-util/cal-util.h> #include <cal-util/timeutil.h> @@ -47,6 +43,7 @@ #include "calendar-config.h" #include "e-meeting-list-view.h" #include <misc/e-cell-renderer-combo.h> +#include <addressbook/util/eab-destination.h> #include "e-select-names-renderer.h" #define SELECT_NAMES_OAFID "OAFIID:GNOME_Evolution_Addressbook_SelectNames" @@ -56,8 +53,6 @@ struct _EMeetingListViewPrivate EMeetingStore *store; EBook *ebook; - gboolean book_loaded; - gboolean book_load_wait; GNOME_Evolution_Addressbook_SelectNames corba_select_names; }; @@ -78,26 +73,17 @@ static icalparameter_role roles[] = {ICAL_ROLE_CHAIR, static GtkTreeViewClass *parent_class = NULL; static void -book_open_cb (EBook *book, EBookStatus status, gpointer data) -{ - EMeetingListView *view = E_MEETING_LIST_VIEW (data); - - if (status == E_BOOK_STATUS_SUCCESS) - view->priv->book_loaded = TRUE; - else - g_warning ("Book not loaded"); - - if (view->priv->book_load_wait) { - view->priv->book_load_wait = FALSE; - gtk_main_quit (); - } -} - -static void start_addressbook_server (EMeetingListView *view) { + GError *error = NULL; + view->priv->ebook = e_book_new (); - e_book_load_default_book (view->priv->ebook, book_open_cb, view); + if (!e_book_load_local_addressbook (view->priv->ebook, &error)) { + g_warning ("start_addressbook_server(): %s", error->message); + g_error_free (error); + + return; + } } static void @@ -319,49 +305,41 @@ e_meeting_list_view_column_set_visible (EMeetingListView *view, const gchar *col } static void -process_section (EMeetingListView *view, GNOME_Evolution_Addressbook_SimpleCardList *cards, icalparameter_role role) +process_section (EMeetingListView *view, EABDestination **cards, icalparameter_role role) { EMeetingListViewPrivate *priv; int i; priv = view->priv; - for (i = 0; i < cards->_length; i++) { - const char *name, *attendee = NULL, *attr; - GNOME_Evolution_Addressbook_SimpleCard card; - CORBA_Environment ev; + for (i = 0; i < G_N_ELEMENTS (cards); i++) { + const char *name, *attendee = NULL; + char *attr = NULL; - card = cards->_buffer[i]; - - CORBA_exception_init (&ev); - - /* Get the CN */ - name = GNOME_Evolution_Addressbook_SimpleCard_get (card, GNOME_Evolution_Addressbook_SimpleCard_FullName, &ev); - if (BONOBO_EX (&ev)) { - CORBA_exception_free (&ev); - continue; - } + name = eab_destination_get_name (cards[i]); /* Get the field as attendee from the backend */ - attr = cal_client_get_ldap_attribute (e_meeting_store_get_cal_client (priv->store)); - if (attr) { + if (cal_client_get_ldap_attribute (e_meeting_store_get_cal_client (priv->store), + &attr, NULL)) { /* FIXME this should be more general */ - if (!g_ascii_strcasecmp (attr, "icscalendar")) - attendee = GNOME_Evolution_Addressbook_SimpleCard_get (card, GNOME_Evolution_Addressbook_SimpleCard_Icscalendar, &ev); + if (!g_ascii_strcasecmp (attr, "icscalendar")) { + EContact *contact; + + /* FIXME: this does not work, have to use first + eab_destination_use_contact() */ + contact = eab_destination_get_contact (cards[i]); + if (contact) { + attendee = e_contact_get (contact, E_CONTACT_FREEBUSY_URL); + if (!attendee) + attendee = e_contact_get (contact, E_CONTACT_CALENDAR_URI); + } + } } - CORBA_exception_init (&ev); - /* If we couldn't get the attendee prior, get the email address as the default */ if (attendee == NULL || *attendee == '\0') { - attendee = GNOME_Evolution_Addressbook_SimpleCard_get (card, GNOME_Evolution_Addressbook_SimpleCard_Email, &ev); - if (BONOBO_EX (&ev)) { - CORBA_exception_free (&ev); - continue; - } + attendee = eab_destination_get_email (cards[i]); } - CORBA_exception_free (&ev); - if (attendee == NULL || *attendee == '\0') continue; @@ -381,22 +359,21 @@ static void select_names_ok_cb (BonoboListener *listener, const char *event_name, const CORBA_any *arg, CORBA_Environment *ev, gpointer data) { EMeetingListView *view = E_MEETING_LIST_VIEW (data); - BonoboArg *card_arg; int i; for (i = 0; sections[i] != NULL; i++) { + EABDestination **destv; + char *string = NULL; Bonobo_Control corba_control = GNOME_Evolution_Addressbook_SelectNames_getEntryBySection (view->priv->corba_select_names, sections[i], ev); GtkWidget *control_widget = bonobo_widget_new_control_from_objref (corba_control, CORBA_OBJECT_NIL); - BonoboControlFrame *control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (control_widget)); - Bonobo_PropertyBag pb = bonobo_control_frame_get_control_property_bag (control_frame, NULL); - card_arg = bonobo_property_bag_client_get_value_any (pb, "simple_card_list", NULL); - if (card_arg != NULL) { - GNOME_Evolution_Addressbook_SimpleCardList cards; - cards = BONOBO_ARG_GET_GENERAL (card_arg, TC_GNOME_Evolution_Addressbook_SimpleCardList, - GNOME_Evolution_Addressbook_SimpleCardList, NULL); - process_section (view, &cards, roles[i]); - bonobo_arg_release (card_arg); + + bonobo_widget_get_property (BONOBO_WIDGET (control_widget), "destinations", + TC_CORBA_string, &string, NULL); + destv = eab_destination_importv (string); + if (destv) { + process_section (view, destv, roles[i]); + g_free (destv); } } } diff --git a/calendar/gui/e-meeting-model.c b/calendar/gui/e-meeting-model.c new file mode 100644 index 0000000000..4742116cf2 --- /dev/null +++ b/calendar/gui/e-meeting-model.c @@ -0,0 +1,1780 @@ +/* -*- Mod:e C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* itip-model.c + * + * Copyright (C) 2001 Ximian, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: JP Rosevear + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <glib.h> +#include <bonobo/bonobo-control.h> +#include <bonobo/bonobo-widget.h> +#include <bonobo/bonobo-exception.h> +#include <libgnome/gnome-i18n.h> +#include <libgnome/gnome-util.h> +#include <libgnomevfs/gnome-vfs.h> +#include <gal/e-table/e-table-without.h> +#include <gal/e-table/e-cell-text.h> +#include <gal/e-table/e-cell-popup.h> +#include <gal/e-table/e-cell-combo.h> +#include <addressbook/util/eab-destination.h> +#include <ebook/e-book.h> +#include <ebook/e-book-async.h> +#include <ebook/e-contact.h> +#include <cal-util/cal-component.h> +#include <cal-util/cal-util.h> +#include <cal-util/timeutil.h> +#include "Evolution-Addressbook-SelectNames.h" +#include "calendar-config.h" +#include "itip-utils.h" +#include "e-meeting-utils.h" +#include "e-meeting-attendee.h" +#include "e-meeting-model.h" + +#define SELECT_NAMES_OAFID "OAFIID:GNOME_Evolution_Addressbook_SelectNames" + +struct _EMeetingModelPrivate +{ + GPtrArray *attendees; + + GList *tables; + + CalClient *client; + icaltimezone *zone; + + EBook *ebook; + gboolean book_loaded; + gboolean book_load_wait; + + GPtrArray *refresh_queue; + GHashTable *refresh_data; + guint refresh_idle_id; + + /* For invite others dialogs */ + GNOME_Evolution_Addressbook_SelectNames corba_select_names; +}; + +#define BUF_SIZE 1024 + +static char *sections[] = {N_("Chair Persons"), + N_("Required Participants"), + N_("Optional Participants"), + N_("Resources"), + NULL}; +static icalparameter_role roles[] = {ICAL_ROLE_CHAIR, + ICAL_ROLE_REQPARTICIPANT, + ICAL_ROLE_OPTPARTICIPANT, + ICAL_ROLE_NONPARTICIPANT, + ICAL_ROLE_NONE}; + +typedef struct _EMeetingModelQueueData EMeetingModelQueueData; +struct _EMeetingModelQueueData { + EMeetingModel *im; + EMeetingAttendee *ia; + + gboolean refreshing; + + EMeetingTime start; + EMeetingTime end; + + char buffer[BUF_SIZE]; + GString *string; + + GPtrArray *call_backs; + GPtrArray *data; +}; + + +static void class_init (EMeetingModelClass *klass); +static void init (EMeetingModel *model); +static void finalize (GObject *obj); + +static void refresh_queue_add (EMeetingModel *im, int row, + EMeetingTime *start, + EMeetingTime *end, + EMeetingModelRefreshCallback call_back, + gpointer data); +static void refresh_queue_remove (EMeetingModel *im, + EMeetingAttendee *ia); +static gboolean refresh_busy_periods (gpointer data); + +static void attendee_changed_cb (EMeetingAttendee *ia, gpointer data); +static void select_names_ok_cb (BonoboListener *listener, + const char *event_name, + const CORBA_any *arg, + CORBA_Environment *ev, + gpointer data); + +static void table_destroy_state_cb (ETableScrolled *etable, gpointer data); +static void table_destroy_list_cb (ETableScrolled *etable, gpointer data); + +static ETableModelClass *parent_class = NULL; + +E_MAKE_TYPE (e_meeting_model, "EMeetingModel", EMeetingModel, + class_init, init, E_TABLE_MODEL_TYPE); + +static void +book_open_cb (EBook *book, EBookStatus status, gpointer data) +{ + EMeetingModel *im = E_MEETING_MODEL (data); + EMeetingModelPrivate *priv; + + priv = im->priv; + + priv->ebook = book; + + if (status == E_BOOK_ERROR_OK) + priv->book_loaded = TRUE; + else + g_warning ("Book not loaded"); + + if (priv->book_load_wait) { + priv->book_load_wait = FALSE; + gtk_main_quit (); + } +} + +static void +start_addressbook_server (EMeetingModel *im) +{ + e_book_async_get_default_addressbook (book_open_cb, im); +} + +static EMeetingAttendee * +find_match (EMeetingModel *im, const char *address, int *pos) +{ + EMeetingModelPrivate *priv; + EMeetingAttendee *ia; + const gchar *ia_address; + int i; + + priv = im->priv; + + if (address == NULL) + return NULL; + + /* Make sure we can add the new delegatee person */ + for (i = 0; i < priv->attendees->len; i++) { + ia = g_ptr_array_index (priv->attendees, i); + + ia_address = e_meeting_attendee_get_address (ia); + if (ia_address != NULL && !g_strcasecmp (itip_strip_mailto (ia_address), itip_strip_mailto (address))) { + if (pos != NULL) + *pos = i; + return ia; + } + } + + return NULL; +} + +static icalparameter_cutype +text_to_type (const char *type) +{ + if (!g_strcasecmp (type, _("Individual"))) + return ICAL_CUTYPE_INDIVIDUAL; + else if (!g_strcasecmp (type, _("Group"))) + return ICAL_CUTYPE_GROUP; + else if (!g_strcasecmp (type, _("Resource"))) + return ICAL_CUTYPE_RESOURCE; + else if (!g_strcasecmp (type, _("Room"))) + return ICAL_CUTYPE_ROOM; + else + return ICAL_CUTYPE_NONE; +} + +static char * +type_to_text (icalparameter_cutype type) +{ + switch (type) { + case ICAL_CUTYPE_INDIVIDUAL: + return _("Individual"); + case ICAL_CUTYPE_GROUP: + return _("Group"); + case ICAL_CUTYPE_RESOURCE: + return _("Resource"); + case ICAL_CUTYPE_ROOM: + return _("Room"); + default: + return _("Unknown"); + } + + return NULL; + +} + +static icalparameter_role +text_to_role (const char *role) +{ + if (!g_strcasecmp (role, _("Chair"))) + return ICAL_ROLE_CHAIR; + else if (!g_strcasecmp (role, _("Required Participant"))) + return ICAL_ROLE_REQPARTICIPANT; + else if (!g_strcasecmp (role, _("Optional Participant"))) + return ICAL_ROLE_OPTPARTICIPANT; + else if (!g_strcasecmp (role, _("Non-Participant"))) + return ICAL_ROLE_NONPARTICIPANT; + else + return ICAL_ROLE_NONE; +} + +static char * +role_to_text (icalparameter_role role) +{ + switch (role) { + case ICAL_ROLE_CHAIR: + return _("Chair"); + case ICAL_ROLE_REQPARTICIPANT: + return _("Required Participant"); + case ICAL_ROLE_OPTPARTICIPANT: + return _("Optional Participant"); + case ICAL_ROLE_NONPARTICIPANT: + return _("Non-Participant"); + default: + return _("Unknown"); + } + + return NULL; +} + +static gboolean +text_to_boolean (const char *role) +{ + if (!g_strcasecmp (role, _("Yes"))) + return TRUE; + else + return FALSE; +} + +static char * +boolean_to_text (gboolean b) +{ + if (b) + return _("Yes"); + else + return _("No"); +} + +static icalparameter_partstat +text_to_partstat (const char *partstat) +{ + if (!g_strcasecmp (partstat, _("Needs Action"))) + return ICAL_PARTSTAT_NEEDSACTION; + else if (!g_strcasecmp (partstat, _("Accepted"))) + return ICAL_PARTSTAT_ACCEPTED; + else if (!g_strcasecmp (partstat, _("Declined"))) + return ICAL_PARTSTAT_DECLINED; + else if (!g_strcasecmp (partstat, _("Tentative"))) + return ICAL_PARTSTAT_TENTATIVE; + else if (!g_strcasecmp (partstat, _("Delegated"))) + return ICAL_PARTSTAT_DELEGATED; + else if (!g_strcasecmp (partstat, _("Completed"))) + return ICAL_PARTSTAT_COMPLETED; + else if (!g_strcasecmp (partstat, _("In Process"))) + return ICAL_PARTSTAT_INPROCESS; + else + return ICAL_PARTSTAT_NONE; +} + +static char * +partstat_to_text (icalparameter_partstat partstat) +{ + switch (partstat) { + case ICAL_PARTSTAT_NEEDSACTION: + return _("Needs Action"); + case ICAL_PARTSTAT_ACCEPTED: + return _("Accepted"); + case ICAL_PARTSTAT_DECLINED: + return _("Declined"); + case ICAL_PARTSTAT_TENTATIVE: + return _("Tentative"); + case ICAL_PARTSTAT_DELEGATED: + return _("Delegated"); + case ICAL_PARTSTAT_COMPLETED: + return _("Completed"); + case ICAL_PARTSTAT_INPROCESS: + return _("In Process"); + case ICAL_PARTSTAT_NONE: + default: + return _("Unknown"); + } + + return NULL; +} + +static int +column_count (ETableModel *etm) +{ + return E_MEETING_MODEL_COLUMN_COUNT; +} + +static int +row_count (ETableModel *etm) +{ + EMeetingModel *im; + EMeetingModelPrivate *priv; + + im = E_MEETING_MODEL (etm); + priv = im->priv; + + return (priv->attendees->len); +} + +static void +append_row (ETableModel *etm, ETableModel *source, int row) +{ + EMeetingModel *im; + EMeetingModelPrivate *priv; + EMeetingAttendee *ia; + char *address; + + im = E_MEETING_MODEL (etm); + priv = im->priv; + + address = (char *) e_table_model_value_at (source, E_MEETING_MODEL_ADDRESS_COL, row); + if (find_match (im, address, NULL) != NULL) { + return; + } + + ia = E_MEETING_ATTENDEE (e_meeting_attendee_new ()); + + e_meeting_attendee_set_address (ia, g_strdup_printf ("MAILTO:%s", address)); + e_meeting_attendee_set_member (ia, g_strdup (e_table_model_value_at (source, E_MEETING_MODEL_MEMBER_COL, row))); + e_meeting_attendee_set_cutype (ia, text_to_type (e_table_model_value_at (source, E_MEETING_MODEL_TYPE_COL, row))); + e_meeting_attendee_set_role (ia, text_to_role (e_table_model_value_at (source, E_MEETING_MODEL_ROLE_COL, row))); + e_meeting_attendee_set_rsvp (ia, text_to_boolean (e_table_model_value_at (source, E_MEETING_MODEL_RSVP_COL, row))); + e_meeting_attendee_set_delto (ia, g_strdup (e_table_model_value_at (source, E_MEETING_MODEL_DELTO_COL, row))); + e_meeting_attendee_set_delfrom (ia, g_strdup (e_table_model_value_at (source, E_MEETING_MODEL_DELFROM_COL, row))); + e_meeting_attendee_set_status (ia, text_to_partstat (e_table_model_value_at (source, E_MEETING_MODEL_STATUS_COL, row))); + e_meeting_attendee_set_cn (ia, g_strdup (e_table_model_value_at (source, E_MEETING_MODEL_CN_COL, row))); + e_meeting_attendee_set_language (ia, g_strdup (e_table_model_value_at (source, E_MEETING_MODEL_LANGUAGE_COL, row))); + + e_meeting_model_add_attendee (E_MEETING_MODEL (etm), ia); + g_object_unref (ia); +} + +static void * +value_at (ETableModel *etm, int col, int row) +{ + EMeetingModel *im; + EMeetingModelPrivate *priv; + EMeetingAttendee *ia; + + im = E_MEETING_MODEL (etm); + priv = im->priv; + + ia = g_ptr_array_index (priv->attendees, row); + + switch (col) { + case E_MEETING_MODEL_ADDRESS_COL: + return (void *)itip_strip_mailto (e_meeting_attendee_get_address (ia)); + case E_MEETING_MODEL_MEMBER_COL: + return (void *)e_meeting_attendee_get_member (ia); + case E_MEETING_MODEL_TYPE_COL: + return type_to_text (e_meeting_attendee_get_cutype (ia)); + case E_MEETING_MODEL_ROLE_COL: + return role_to_text (e_meeting_attendee_get_role (ia)); + case E_MEETING_MODEL_RSVP_COL: + return boolean_to_text (e_meeting_attendee_get_rsvp (ia)); + case E_MEETING_MODEL_DELTO_COL: + return (void *)itip_strip_mailto (e_meeting_attendee_get_delto (ia)); + case E_MEETING_MODEL_DELFROM_COL: + return (void *)itip_strip_mailto (e_meeting_attendee_get_delfrom (ia)); + case E_MEETING_MODEL_STATUS_COL: + return partstat_to_text (e_meeting_attendee_get_status (ia)); + case E_MEETING_MODEL_CN_COL: + return (void *)e_meeting_attendee_get_cn (ia); + case E_MEETING_MODEL_LANGUAGE_COL: + return (void *)e_meeting_attendee_get_language (ia); + } + + return NULL; +} + +static void +set_value_at (ETableModel *etm, int col, int row, const void *val) +{ + EMeetingModel *im; + EMeetingModelPrivate *priv; + EMeetingAttendee *ia; + icalparameter_cutype type; + + im = E_MEETING_MODEL (etm); + priv = im->priv; + + ia = g_ptr_array_index (priv->attendees, row); + + e_table_model_pre_change (etm); + + switch (col) { + case E_MEETING_MODEL_ADDRESS_COL: + if (val != NULL && *((char *)val)) + e_meeting_attendee_set_address (ia, g_strdup_printf ("MAILTO:%s", (char *) val)); + break; + case E_MEETING_MODEL_MEMBER_COL: + e_meeting_attendee_set_member (ia, g_strdup (val)); + break; + case E_MEETING_MODEL_TYPE_COL: + type = text_to_type (val); + e_meeting_attendee_set_cutype (ia, text_to_type (val)); + if (type == ICAL_CUTYPE_RESOURCE) { + e_meeting_attendee_set_role (ia, ICAL_ROLE_NONPARTICIPANT); + e_table_model_cell_changed (etm, E_MEETING_MODEL_ROLE_COL, row); + } + break; + case E_MEETING_MODEL_ROLE_COL: + e_meeting_attendee_set_role (ia, text_to_role (val)); + break; + case E_MEETING_MODEL_RSVP_COL: + e_meeting_attendee_set_rsvp (ia, text_to_boolean (val)); + break; + case E_MEETING_MODEL_DELTO_COL: + e_meeting_attendee_set_delto (ia, g_strdup (val)); + break; + case E_MEETING_MODEL_DELFROM_COL: + e_meeting_attendee_set_delfrom (ia, g_strdup (val)); + break; + case E_MEETING_MODEL_STATUS_COL: + e_meeting_attendee_set_status (ia, text_to_partstat (val)); + break; + case E_MEETING_MODEL_CN_COL: + e_meeting_attendee_set_cn (ia, g_strdup (val)); + break; + case E_MEETING_MODEL_LANGUAGE_COL: + e_meeting_attendee_set_language (ia, g_strdup (val)); + break; + } + + e_table_model_cell_changed (etm, col, row); +} + +static gboolean +is_cell_editable (ETableModel *etm, int col, int row) +{ + EMeetingModel *im; + EMeetingModelPrivate *priv; + EMeetingAttendee *ia; + EMeetingAttendeeEditLevel level; + + im = E_MEETING_MODEL (etm); + priv = im->priv; + + if (col == E_MEETING_MODEL_DELTO_COL + || col == E_MEETING_MODEL_DELFROM_COL) + return FALSE; + + if (row == -1) + return TRUE; + if (row >= priv->attendees->len) + return TRUE; + + ia = g_ptr_array_index (priv->attendees, row); + level = e_meeting_attendee_get_edit_level (ia); + + switch (level) { + case E_MEETING_ATTENDEE_EDIT_FULL: + return TRUE; + case E_MEETING_ATTENDEE_EDIT_STATUS: + return col == E_MEETING_MODEL_STATUS_COL; + case E_MEETING_ATTENDEE_EDIT_NONE: + return FALSE; + } + + return TRUE; +} + +static void * +duplicate_value (ETableModel *etm, int col, const void *val) +{ + return g_strdup (val); +} + +static void +free_value (ETableModel *etm, int col, void *val) +{ + g_free (val); +} + +static void * +init_value (ETableModel *etm, int col) +{ + switch (col) { + case E_MEETING_MODEL_ADDRESS_COL: + return g_strdup (""); + case E_MEETING_MODEL_MEMBER_COL: + return g_strdup (""); + case E_MEETING_MODEL_TYPE_COL: + return g_strdup (_("Individual")); + case E_MEETING_MODEL_ROLE_COL: + return g_strdup (_("Required Participant")); + case E_MEETING_MODEL_RSVP_COL: + return g_strdup (_("Yes")); + case E_MEETING_MODEL_DELTO_COL: + return g_strdup (""); + case E_MEETING_MODEL_DELFROM_COL: + return g_strdup (""); + case E_MEETING_MODEL_STATUS_COL: + return g_strdup (_("Needs Action")); + case E_MEETING_MODEL_CN_COL: + return g_strdup (""); + case E_MEETING_MODEL_LANGUAGE_COL: + return g_strdup ("en"); + } + + return g_strdup (""); +} + +static gboolean +value_is_empty (ETableModel *etm, int col, const void *val) +{ + + switch (col) { + case E_MEETING_MODEL_ADDRESS_COL: + case E_MEETING_MODEL_MEMBER_COL: + case E_MEETING_MODEL_DELTO_COL: + case E_MEETING_MODEL_DELFROM_COL: + case E_MEETING_MODEL_CN_COL: + if (val && !g_strcasecmp (val, "")) + return TRUE; + else + return FALSE; + default: + ; + } + + return TRUE; +} + +static char * +value_to_string (ETableModel *etm, int col, const void *val) +{ + return g_strdup (val); +} + +static void +class_init (EMeetingModelClass *klass) +{ + GObjectClass *gobject_class; + ETableModelClass *etm_class; + + gobject_class = G_OBJECT_CLASS (klass); + etm_class = E_TABLE_MODEL_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->finalize = finalize; + + etm_class->column_count = column_count; + etm_class->row_count = row_count; + etm_class->value_at = value_at; + etm_class->set_value_at = set_value_at; + etm_class->is_cell_editable = is_cell_editable; + etm_class->append_row = append_row; + etm_class->duplicate_value = duplicate_value; + etm_class->free_value = free_value; + etm_class->initialize_value = init_value; + etm_class->value_is_empty = value_is_empty; + etm_class->value_to_string = value_to_string; +} + + +static void +init (EMeetingModel *im) +{ + EMeetingModelPrivate *priv; + + priv = g_new0 (EMeetingModelPrivate, 1); + + im->priv = priv; + + priv->attendees = g_ptr_array_new (); + + priv->tables = NULL; + + priv->client = NULL; + priv->zone = icaltimezone_get_builtin_timezone (calendar_config_get_timezone ()); + + priv->ebook = NULL; + priv->book_loaded = FALSE; + priv->book_load_wait = FALSE; + + priv->refresh_queue = g_ptr_array_new (); + priv->refresh_data = g_hash_table_new (g_direct_hash, g_direct_equal); + priv->refresh_idle_id = 0; + + priv->corba_select_names = CORBA_OBJECT_NIL; + + start_addressbook_server (im); +} + +static void +finalize (GObject *obj) +{ + EMeetingModel *im = E_MEETING_MODEL (obj); + EMeetingModelPrivate *priv; + GList *l; + int i; + + priv = im->priv; + + for (i = 0; i < priv->attendees->len; i++) + g_object_unref (g_ptr_array_index (priv->attendees, i)); + g_ptr_array_free (priv->attendees, TRUE); + + for (l = priv->tables; l != NULL; l = l->next) + g_signal_handlers_disconnect_matched (G_OBJECT (l->data), G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, im); + g_list_free (priv->tables); + + if (priv->client != NULL) + g_object_unref (priv->client); + + if (priv->ebook != NULL) + g_object_unref (priv->ebook); + + if (priv->corba_select_names != CORBA_OBJECT_NIL) { + CORBA_Environment ev; + CORBA_exception_init (&ev); + bonobo_object_release_unref (priv->corba_select_names, &ev); + CORBA_exception_free (&ev); + } + + while (priv->refresh_queue->len > 0) + refresh_queue_remove (im, g_ptr_array_index (priv->refresh_queue, 0)); + g_ptr_array_free (priv->refresh_queue, TRUE); + g_hash_table_destroy (priv->refresh_data); + + if (priv->refresh_idle_id) + g_source_remove (priv->refresh_idle_id); + + g_free (priv); + + if (G_OBJECT_CLASS (parent_class)->finalize) + (* G_OBJECT_CLASS (parent_class)->finalize) (obj); +} + +GtkObject * +e_meeting_model_new (void) +{ + return g_object_new (E_TYPE_MEETING_MODEL, NULL); +} + + +CalClient * +e_meeting_model_get_cal_client (EMeetingModel *im) +{ + EMeetingModelPrivate *priv; + + priv = im->priv; + + return priv->client; +} + +void +e_meeting_model_set_cal_client (EMeetingModel *im, CalClient *client) +{ + EMeetingModelPrivate *priv; + + priv = im->priv; + + if (priv->client != NULL) + g_object_unref (priv->client); + + if (client != NULL) + g_object_ref (client); + priv->client = client; +} + +icaltimezone * +e_meeting_model_get_zone (EMeetingModel *im) +{ + EMeetingModelPrivate *priv; + + g_return_val_if_fail (im != NULL, NULL); + g_return_val_if_fail (E_IS_MEETING_MODEL (im), NULL); + + priv = im->priv; + + return priv->zone; +} + +void +e_meeting_model_set_zone (EMeetingModel *im, icaltimezone *zone) +{ + EMeetingModelPrivate *priv; + + g_return_if_fail (im != NULL); + g_return_if_fail (E_IS_MEETING_MODEL (im)); + + priv = im->priv; + + priv->zone = zone; +} + +static ETableScrolled * +build_etable (ETableModel *model, const gchar *spec_file, const gchar *state_file) +{ + GtkWidget *etable; + ETable *real_table; + ETableExtras *extras; + GList *strings; + ECell *popup_cell, *cell; + + extras = e_table_extras_new (); + + /* For type */ + cell = e_cell_text_new (NULL, GTK_JUSTIFY_LEFT); + popup_cell = e_cell_combo_new (); + e_cell_popup_set_child (E_CELL_POPUP (popup_cell), cell); + g_object_unref (cell); + + strings = NULL; + strings = g_list_append (strings, (char*) _("Individual")); + strings = g_list_append (strings, (char*) _("Group")); + strings = g_list_append (strings, (char*) _("Resource")); + strings = g_list_append (strings, (char*) _("Room")); + strings = g_list_append (strings, (char*) _("Unknown")); + + e_cell_combo_set_popdown_strings (E_CELL_COMBO (popup_cell), strings); + e_table_extras_add_cell (extras, "typeedit", popup_cell); + + /* For role */ + cell = e_cell_text_new (NULL, GTK_JUSTIFY_LEFT); + popup_cell = e_cell_combo_new (); + e_cell_popup_set_child (E_CELL_POPUP (popup_cell), cell); + g_object_unref (cell); + + strings = NULL; + strings = g_list_append (strings, (char*) _("Chair")); + strings = g_list_append (strings, (char*) _("Required Participant")); + strings = g_list_append (strings, (char*) _("Optional Participant")); + strings = g_list_append (strings, (char*) _("Non-Participant")); + strings = g_list_append (strings, (char*) _("Unknown")); + + e_cell_combo_set_popdown_strings (E_CELL_COMBO (popup_cell), strings); + e_table_extras_add_cell (extras, "roleedit", popup_cell); + + /* For rsvp */ + cell = e_cell_text_new (NULL, GTK_JUSTIFY_LEFT); + popup_cell = e_cell_combo_new (); + e_cell_popup_set_child (E_CELL_POPUP (popup_cell), cell); + g_object_unref (cell); + + strings = NULL; + strings = g_list_append (strings, (char*) _("Yes")); + strings = g_list_append (strings, (char*) _("No")); + + e_cell_combo_set_popdown_strings (E_CELL_COMBO (popup_cell), strings); + e_table_extras_add_cell (extras, "rsvpedit", popup_cell); + + /* For status */ + cell = e_cell_text_new (NULL, GTK_JUSTIFY_LEFT); + popup_cell = e_cell_combo_new (); + e_cell_popup_set_child (E_CELL_POPUP (popup_cell), cell); + g_object_unref (cell); + + strings = NULL; + strings = g_list_append (strings, (char*) _("Needs Action")); + strings = g_list_append (strings, (char*) _("Accepted")); + strings = g_list_append (strings, (char*) _("Declined")); + strings = g_list_append (strings, (char*) _("Tentative")); + strings = g_list_append (strings, (char*) _("Delegated")); + + e_cell_combo_set_popdown_strings (E_CELL_COMBO (popup_cell), strings); + e_table_extras_add_cell (extras, "statusedit", popup_cell); + + etable = e_table_scrolled_new_from_spec_file (model, extras, spec_file, NULL); + real_table = e_table_scrolled_get_table (E_TABLE_SCROLLED (etable)); + g_object_set (G_OBJECT (real_table), "uniform_row_height", TRUE, NULL); + e_table_load_state (real_table, state_file); + +#if 0 + g_signal_connect (real_table, "right_click", G_CALLBACK (right_click_cb), mpage); +#endif + + g_signal_connect (etable, "destroy", G_CALLBACK (table_destroy_state_cb), g_strdup (state_file)); + + g_object_unref (extras); + + return E_TABLE_SCROLLED (etable); +} + +void +e_meeting_model_add_attendee (EMeetingModel *im, EMeetingAttendee *ia) +{ + EMeetingModelPrivate *priv; + + priv = im->priv; + + e_table_model_pre_change (E_TABLE_MODEL (im)); + + g_object_ref (ia); + g_ptr_array_add (priv->attendees, ia); + + g_signal_connect (ia, "changed", G_CALLBACK (attendee_changed_cb), im); + + e_table_model_row_inserted (E_TABLE_MODEL (im), row_count (E_TABLE_MODEL (im)) - 1); +} + +EMeetingAttendee * +e_meeting_model_add_attendee_with_defaults (EMeetingModel *im) +{ + EMeetingAttendee *ia; + char *str; + + ia = E_MEETING_ATTENDEE (e_meeting_attendee_new ()); + + e_meeting_attendee_set_address (ia, init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_ADDRESS_COL)); + e_meeting_attendee_set_member (ia, init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_MEMBER_COL)); + + str = init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_TYPE_COL); + e_meeting_attendee_set_cutype (ia, text_to_type (str)); + g_free (str); + str = init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_ROLE_COL); + e_meeting_attendee_set_role (ia, text_to_role (str)); + g_free (str); + str = init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_RSVP_COL); + e_meeting_attendee_set_rsvp (ia, text_to_boolean (str)); + g_free (str); + + e_meeting_attendee_set_delto (ia, init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_DELTO_COL)); + e_meeting_attendee_set_delfrom (ia, init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_DELFROM_COL)); + + str = init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_STATUS_COL); + e_meeting_attendee_set_status (ia, text_to_partstat (str)); + g_free (str); + + e_meeting_attendee_set_cn (ia, init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_CN_COL)); + e_meeting_attendee_set_language (ia, init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_LANGUAGE_COL)); + + e_meeting_model_add_attendee (im, ia); + + return ia; +} + +void +e_meeting_model_remove_attendee (EMeetingModel *im, EMeetingAttendee *ia) +{ + EMeetingModelPrivate *priv; + gint i, row = -1; + + priv = im->priv; + + for (i = 0; i < priv->attendees->len; i++) { + if (ia == g_ptr_array_index (priv->attendees, i)) { + row = i; + break; + } + } + + if (row != -1) { + e_table_model_pre_change (E_TABLE_MODEL (im)); + + g_ptr_array_remove_index (priv->attendees, row); + g_object_unref (ia); + + e_table_model_row_deleted (E_TABLE_MODEL (im), row); + } +} + +void +e_meeting_model_remove_all_attendees (EMeetingModel *im) +{ + EMeetingModelPrivate *priv; + gint i, len; + + priv = im->priv; + + e_table_model_pre_change (E_TABLE_MODEL (im)); + + len = priv->attendees->len; + + for (i = 0; i < len; i++) { + EMeetingAttendee *ia = g_ptr_array_index (priv->attendees, i); + g_object_unref (ia); + } + g_ptr_array_set_size (priv->attendees, 0); + + e_table_model_rows_deleted (E_TABLE_MODEL (im), 0, len); +} + +EMeetingAttendee * +e_meeting_model_find_attendee (EMeetingModel *im, const gchar *address, gint *row) +{ + EMeetingModelPrivate *priv; + EMeetingAttendee *ia; + int i; + + priv = im->priv; + + if (address == NULL) + return NULL; + + for (i = 0; i < priv->attendees->len; i++) { + const gchar *ia_address; + + ia = g_ptr_array_index (priv->attendees, i); + + ia_address = e_meeting_attendee_get_address (ia); + if (ia_address && !g_strcasecmp (itip_strip_mailto (ia_address), itip_strip_mailto (address))) { + if (row != NULL) + *row = i; + + return ia; + } + } + + return NULL; +} + +EMeetingAttendee * +e_meeting_model_find_attendee_at_row (EMeetingModel *im, gint row) +{ + EMeetingModelPrivate *priv; + + g_return_val_if_fail (im != NULL, NULL); + g_return_val_if_fail (E_IS_MEETING_MODEL (im), NULL); + g_return_val_if_fail (row >= 0, NULL); + + priv = im->priv; + g_return_val_if_fail (row < priv->attendees->len, NULL); + + return g_ptr_array_index (priv->attendees, row); +} + +gint +e_meeting_model_count_actual_attendees (EMeetingModel *im) +{ + EMeetingModelPrivate *priv; + + priv = im->priv; + + return e_table_model_row_count (E_TABLE_MODEL (im)); +} + +const GPtrArray * +e_meeting_model_get_attendees (EMeetingModel *im) +{ + EMeetingModelPrivate *priv; + + priv = im->priv; + + return priv->attendees; +} + +static icaltimezone * +find_zone (icalproperty *ip, icalcomponent *tz_top_level) +{ + icalparameter *param; + icalcomponent *sub_comp; + const char *tzid; + icalcompiter iter; + + if (tz_top_level == NULL) + return NULL; + + param = icalproperty_get_first_parameter (ip, ICAL_TZID_PARAMETER); + if (param == NULL) + return NULL; + tzid = icalparameter_get_tzid (param); + + iter = icalcomponent_begin_component (tz_top_level, ICAL_VTIMEZONE_COMPONENT); + while ((sub_comp = icalcompiter_deref (&iter)) != NULL) { + icalcomponent *clone; + const char *tz_tzid; + + /* FIXME We aren't passing a property here */ + tz_tzid = icalproperty_get_tzid (sub_comp); + if (!strcmp (tzid, tz_tzid)) { + icaltimezone *zone; + + zone = icaltimezone_new (); + clone = icalcomponent_new_clone (sub_comp); + icaltimezone_set_component (zone, clone); + + return zone; + } + + icalcompiter_next (&iter); + } + + return NULL; +} + + +static void +refresh_queue_add (EMeetingModel *im, int row, + EMeetingTime *start, + EMeetingTime *end, + EMeetingModelRefreshCallback call_back, + gpointer data) +{ + EMeetingModelPrivate *priv; + EMeetingAttendee *ia; + EMeetingModelQueueData *qdata; + + priv = im->priv; + + ia = g_ptr_array_index (priv->attendees, row); + if (ia == NULL) + return; + + qdata = g_hash_table_lookup (priv->refresh_data, ia); + if (qdata == NULL) { + qdata = g_new0 (EMeetingModelQueueData, 1); + + qdata->im = im; + qdata->ia = ia; + e_meeting_attendee_clear_busy_periods (ia); + e_meeting_attendee_set_has_calendar_info (ia, FALSE); + + qdata->start = *start; + qdata->end = *end; + qdata->string = g_string_new (NULL); + qdata->call_backs = g_ptr_array_new (); + qdata->data = g_ptr_array_new (); + g_ptr_array_add (qdata->call_backs, call_back); + g_ptr_array_add (qdata->data, data); + + g_hash_table_insert (priv->refresh_data, ia, qdata); + } else { + if (e_meeting_time_compare_times (start, &qdata->start) == -1) + qdata->start = *start; + if (e_meeting_time_compare_times (end, &qdata->end) == 1) + qdata->end = *end; + g_ptr_array_add (qdata->call_backs, call_back); + g_ptr_array_add (qdata->data, data); + } + + g_object_ref (ia); + g_ptr_array_add (priv->refresh_queue, ia); + + if (priv->refresh_idle_id == 0) + priv->refresh_idle_id = g_idle_add (refresh_busy_periods, im); +} + +static void +refresh_queue_remove (EMeetingModel *im, EMeetingAttendee *ia) +{ + EMeetingModelPrivate *priv; + EMeetingModelQueueData *qdata; + + priv = im->priv; + + /* Free the queue data */ + qdata = g_hash_table_lookup (priv->refresh_data, ia); + g_assert (qdata != NULL); + + g_hash_table_remove (priv->refresh_data, ia); + g_ptr_array_free (qdata->call_backs, TRUE); + g_ptr_array_free (qdata->data, TRUE); + g_free (qdata); + + /* Unref the attendee */ + g_ptr_array_remove (priv->refresh_queue, ia); + g_object_unref (ia); +} + +static void +process_callbacks (EMeetingModelQueueData *qdata) +{ + EMeetingModel *im; + int i; + + for (i = 0; i < qdata->call_backs->len; i++) { + EMeetingModelRefreshCallback call_back; + gpointer *data; + + call_back = g_ptr_array_index (qdata->call_backs, i); + data = g_ptr_array_index (qdata->data, i); + + call_back (data); + } + + im = qdata->im; + refresh_queue_remove (qdata->im, qdata->ia); + g_object_unref (im); +} + +static void +process_free_busy_comp (EMeetingAttendee *ia, + icalcomponent *fb_comp, + icaltimezone *zone, + icalcomponent *tz_top_level) +{ + icalproperty *ip; + + ip = icalcomponent_get_first_property (fb_comp, ICAL_DTSTART_PROPERTY); + if (ip != NULL) { + struct icaltimetype dtstart; + icaltimezone *ds_zone; + + dtstart = icalproperty_get_dtstart (ip); + if (!dtstart.is_utc) + ds_zone = find_zone (ip, tz_top_level); + else + ds_zone = icaltimezone_get_utc_timezone (); + icaltimezone_convert_time (&dtstart, ds_zone, zone); + e_meeting_attendee_set_start_busy_range (ia, + dtstart.year, + dtstart.month, + dtstart.day, + dtstart.hour, + dtstart.minute); + } + + ip = icalcomponent_get_first_property (fb_comp, ICAL_DTEND_PROPERTY); + if (ip != NULL) { + struct icaltimetype dtend; + icaltimezone *de_zone; + + dtend = icalproperty_get_dtend (ip); + if (!dtend.is_utc) + de_zone = find_zone (ip, tz_top_level); + else + de_zone = icaltimezone_get_utc_timezone (); + icaltimezone_convert_time (&dtend, de_zone, zone); + e_meeting_attendee_set_end_busy_range (ia, + dtend.year, + dtend.month, + dtend.day, + dtend.hour, + dtend.minute); + } + + ip = icalcomponent_get_first_property (fb_comp, ICAL_FREEBUSY_PROPERTY); + while (ip != NULL) { + icalparameter *param; + struct icalperiodtype fb; + EMeetingFreeBusyType busy_type = E_MEETING_FREE_BUSY_LAST; + icalparameter_fbtype fbtype = ICAL_FBTYPE_BUSY; + + fb = icalproperty_get_freebusy (ip); + param = icalproperty_get_first_parameter (ip, ICAL_FBTYPE_PARAMETER); + if (param != NULL) + fbtype = icalparameter_get_fbtype (param); + + switch (fbtype) { + case ICAL_FBTYPE_BUSY: + busy_type = E_MEETING_FREE_BUSY_BUSY; + break; + + case ICAL_FBTYPE_BUSYUNAVAILABLE: + busy_type = E_MEETING_FREE_BUSY_OUT_OF_OFFICE; + break; + + case ICAL_FBTYPE_BUSYTENTATIVE: + busy_type = E_MEETING_FREE_BUSY_TENTATIVE; + break; + + default: + break; + } + + if (busy_type != E_MEETING_FREE_BUSY_LAST) { + icaltimezone *utc_zone = icaltimezone_get_utc_timezone (); + + icaltimezone_convert_time (&fb.start, utc_zone, zone); + icaltimezone_convert_time (&fb.end, utc_zone, zone); + e_meeting_attendee_add_busy_period (ia, + fb.start.year, + fb.start.month, + fb.start.day, + fb.start.hour, + fb.start.minute, + fb.end.year, + fb.end.month, + fb.end.day, + fb.end.hour, + fb.end.minute, + busy_type); + } + + ip = icalcomponent_get_next_property (fb_comp, ICAL_FREEBUSY_PROPERTY); + } +} + +static void +process_free_busy (EMeetingModelQueueData *qdata, char *text) +{ + EMeetingModel *im = qdata->im; + EMeetingModelPrivate *priv; + EMeetingAttendee *ia = qdata->ia; + icalcomponent *main_comp; + icalcomponent_kind kind = ICAL_NO_COMPONENT; + + priv = im->priv; + + main_comp = icalparser_parse_string (text); + if (main_comp == NULL) { + process_callbacks (qdata); + return; + } + + kind = icalcomponent_isa (main_comp); + if (kind == ICAL_VCALENDAR_COMPONENT) { + icalcompiter iter; + icalcomponent *tz_top_level, *sub_comp; + + tz_top_level = cal_util_new_top_level (); + + iter = icalcomponent_begin_component (main_comp, ICAL_VTIMEZONE_COMPONENT); + while ((sub_comp = icalcompiter_deref (&iter)) != NULL) { + icalcomponent *clone; + + clone = icalcomponent_new_clone (sub_comp); + icalcomponent_add_component (tz_top_level, clone); + + icalcompiter_next (&iter); + } + + iter = icalcomponent_begin_component (main_comp, ICAL_VFREEBUSY_COMPONENT); + while ((sub_comp = icalcompiter_deref (&iter)) != NULL) { + process_free_busy_comp (ia, sub_comp, priv->zone, tz_top_level); + + icalcompiter_next (&iter); + } + icalcomponent_free (tz_top_level); + } else if (kind == ICAL_VFREEBUSY_COMPONENT) { + process_free_busy_comp (ia, main_comp, priv->zone, NULL); + } + + icalcomponent_free (main_comp); + + process_callbacks (qdata); +} + +static void +async_close (GnomeVFSAsyncHandle *handle, + GnomeVFSResult result, + gpointer data) +{ + EMeetingModelQueueData *qdata = data; + + process_free_busy (qdata, qdata->string->str); +} + +static void +async_read (GnomeVFSAsyncHandle *handle, + GnomeVFSResult result, + gpointer buffer, + GnomeVFSFileSize requested, + GnomeVFSFileSize read, + gpointer data) +{ + EMeetingModelQueueData *qdata = data; + GnomeVFSFileSize buf_size = BUF_SIZE - 1; + + if (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_EOF) { + gnome_vfs_async_close (handle, async_close, qdata); + return; + } + + ((char *)buffer)[read] = '\0'; + qdata->string = g_string_append (qdata->string, buffer); + + if (result == GNOME_VFS_ERROR_EOF) { + gnome_vfs_async_close (handle, async_close, qdata); + return; + } + + gnome_vfs_async_read (handle, qdata->buffer, buf_size, async_read, qdata); +} + +static void +async_open (GnomeVFSAsyncHandle *handle, + GnomeVFSResult result, + gpointer data) +{ + EMeetingModelQueueData *qdata = data; + GnomeVFSFileSize buf_size = BUF_SIZE - 1; + + if (result != GNOME_VFS_OK) { + gnome_vfs_async_close (handle, async_close, qdata); + return; + } + + gnome_vfs_async_read (handle, qdata->buffer, buf_size, async_read, qdata); +} + +static void +contacts_cb (EBook *book, EBookStatus status, GList *contacts, gpointer data) +{ + EMeetingModelQueueData *qdata = data; + GList *l; + + if (status != E_BOOK_ERROR_OK) + return; + + for (l = contacts; l; l = l->next) { + GnomeVFSAsyncHandle *handle; + EContact *contact = E_CONTACT (l->data); + const char *fburl = e_contact_get_const (contact, E_CONTACT_FREEBUSY_URL); + + if (!fburl || !*fburl) + continue; + + /* Read in free/busy data from the url */ + gnome_vfs_async_open (&handle, fburl, GNOME_VFS_OPEN_READ, + GNOME_VFS_PRIORITY_DEFAULT, async_open, qdata); + + e_free_object_list (contacts); + return; + } + + process_callbacks (qdata); + e_free_object_list (contacts); +} + +static gboolean +refresh_busy_periods (gpointer data) +{ + EMeetingModel *im = E_MEETING_MODEL (data); + EMeetingModelPrivate *priv; + EMeetingAttendee *ia = NULL; + EMeetingModelQueueData *qdata = NULL; + char *query; + int i; + + priv = im->priv; + + /* Check to see if there are any remaining attendees in the queue */ + for (i = 0; i < priv->refresh_queue->len; i++) { + ia = g_ptr_array_index (priv->refresh_queue, i); + g_assert (ia != NULL); + + qdata = g_hash_table_lookup (priv->refresh_data, ia); + g_assert (qdata != NULL); + + if (!qdata->refreshing) + break; + } + + /* The everything in the queue is being refreshed */ + if (i >= priv->refresh_queue->len) { + priv->refresh_idle_id = 0; + return FALSE; + } + + /* Indicate we are trying to refresh it */ + qdata->refreshing = TRUE; + + /* We take a ref in case we get destroyed in the gui during a callback */ + g_object_ref (qdata->im); + + /* Check the server for free busy data */ + if (priv->client) { + GList *fb_data = NULL, *users = NULL; + struct icaltimetype itt; + time_t startt, endt; + const char *user; + + itt = icaltime_null_time (); + itt.year = g_date_year (&qdata->start.date); + itt.month = g_date_month (&qdata->start.date); + itt.day = g_date_day (&qdata->start.date); + itt.hour = qdata->start.hour; + itt.minute = qdata->start.minute; + startt = icaltime_as_timet_with_zone (itt, priv->zone); + + itt = icaltime_null_time (); + itt.year = g_date_year (&qdata->end.date); + itt.month = g_date_month (&qdata->end.date); + itt.day = g_date_day (&qdata->end.date); + itt.hour = qdata->end.hour; + itt.minute = qdata->end.minute; + endt = icaltime_as_timet_with_zone (itt, priv->zone); + + user = itip_strip_mailto (e_meeting_attendee_get_address (ia)); + users = g_list_append (users, g_strdup (user)); + + /* FIXME Error checking */ + cal_client_get_free_busy (priv->client, users, startt, endt, &fb_data, NULL); + + g_list_foreach (users, (GFunc)g_free, NULL); + g_list_free (users); + + if (fb_data != NULL) { + CalComponent *comp = fb_data->data; + char *comp_str; + + comp_str = cal_component_get_as_string (comp); + process_free_busy (qdata, comp_str); + g_free (comp_str); + return TRUE; + } + } + + /* Look for fburl's of attendee with no free busy info on server */ + if (!priv->book_loaded) { + priv->book_load_wait = TRUE; + gtk_main (); + } + + if (!e_meeting_attendee_is_set_address (ia)) { + process_callbacks (qdata); + return TRUE; + } + + query = g_strdup_printf ("(is \"email\" \"%s\")", + itip_strip_mailto (e_meeting_attendee_get_address (ia))); + if (!e_book_async_get_contacts (priv->ebook, query, contacts_cb, qdata)) + process_callbacks (qdata); + g_free (query); + + return TRUE; +} + +void +e_meeting_model_refresh_all_busy_periods (EMeetingModel *im, + EMeetingTime *start, + EMeetingTime *end, + EMeetingModelRefreshCallback call_back, + gpointer data) +{ + EMeetingModelPrivate *priv; + int i; + + g_return_if_fail (im != NULL); + g_return_if_fail (E_IS_MEETING_MODEL (im)); + + priv = im->priv; + + for (i = 0; i < priv->attendees->len; i++) + refresh_queue_add (im, i, start, end, call_back, data); +} + +void +e_meeting_model_refresh_busy_periods (EMeetingModel *im, + int row, + EMeetingTime *start, + EMeetingTime *end, + EMeetingModelRefreshCallback call_back, + gpointer data) +{ + EMeetingModelPrivate *priv; + + g_return_if_fail (im != NULL); + g_return_if_fail (E_IS_MEETING_MODEL (im)); + + priv = im->priv; + + refresh_queue_add (im, row, start, end, call_back, data); +} + +ETableScrolled * +e_meeting_model_etable_from_model (EMeetingModel *im, const gchar *spec_file, const gchar *state_file) +{ + EMeetingModelPrivate *priv; + ETableScrolled *ets; + + g_return_val_if_fail (im != NULL, NULL); + g_return_val_if_fail (E_IS_MEETING_MODEL (im), NULL); + + priv = im->priv; + + ets = build_etable (E_TABLE_MODEL (im), spec_file, state_file); + + priv->tables = g_list_prepend (priv->tables, ets); + + g_signal_connect (ets, "destroy", G_CALLBACK (table_destroy_list_cb), im); + + return ets; +} + +void +e_meeting_model_etable_click_to_add (EMeetingModel *im, gboolean click_to_add) +{ + EMeetingModelPrivate *priv; + GList *l; + + g_return_if_fail (im != NULL); + g_return_if_fail (E_IS_MEETING_MODEL (im)); + + priv = im->priv; + + for (l = priv->tables; l != NULL; l = l->next) { + ETableScrolled *ets; + ETable *real_table; + + ets = l->data; + real_table = e_table_scrolled_get_table (ets); + + g_object_set (G_OBJECT (real_table), "use_click_to_add", click_to_add, NULL); + } +} + +int +e_meeting_model_etable_model_to_view_row (ETable *et, EMeetingModel *im, int model_row) +{ + EMeetingModelPrivate *priv; + + g_return_val_if_fail (im != NULL, -1); + g_return_val_if_fail (E_IS_MEETING_MODEL (im), -1); + + priv = im->priv; + + return e_table_model_to_view_row (et, model_row); +} + +int +e_meeting_model_etable_view_to_model_row (ETable *et, EMeetingModel *im, int view_row) +{ + EMeetingModelPrivate *priv; + + g_return_val_if_fail (im != NULL, -1); + g_return_val_if_fail (E_IS_MEETING_MODEL (im), -1); + + priv = im->priv; + + return e_table_view_to_model_row (et, view_row); +} + + +static void +add_section (GNOME_Evolution_Addressbook_SelectNames corba_select_names, const char *name) +{ + CORBA_Environment ev; + + CORBA_exception_init (&ev); + + GNOME_Evolution_Addressbook_SelectNames_addSection (corba_select_names, + name, + gettext (name), + &ev); + + CORBA_exception_free (&ev); +} + +static gboolean +get_select_name_dialog (EMeetingModel *im) +{ + EMeetingModelPrivate *priv; + CORBA_Environment ev; + int i; + + priv = im->priv; + + if (priv->corba_select_names != CORBA_OBJECT_NIL) { + Bonobo_Control corba_control; + GtkWidget *control_widget; + int i; + + CORBA_exception_init (&ev); + for (i = 0; sections[i] != NULL; i++) { + corba_control = GNOME_Evolution_Addressbook_SelectNames_getEntryBySection + (priv->corba_select_names, sections[i], &ev); + if (BONOBO_EX (&ev)) { + CORBA_exception_free (&ev); + return FALSE; + } + + control_widget = bonobo_widget_new_control_from_objref (corba_control, CORBA_OBJECT_NIL); + + bonobo_widget_set_property (BONOBO_WIDGET (control_widget), "text", TC_CORBA_string, "", NULL); + } + CORBA_exception_free (&ev); + + return TRUE; + } + + CORBA_exception_init (&ev); + + priv->corba_select_names = bonobo_activation_activate_from_id (SELECT_NAMES_OAFID, 0, NULL, &ev); + + for (i = 0; sections[i] != NULL; i++) + add_section (priv->corba_select_names, sections[i]); + + bonobo_event_source_client_add_listener (priv->corba_select_names, + (BonoboListenerCallbackFn) select_names_ok_cb, + "GNOME/Evolution:ok:dialog", + NULL, im); + + if (BONOBO_EX (&ev)) { + CORBA_exception_free (&ev); + return FALSE; + } + + CORBA_exception_free (&ev); + + return TRUE; +} + +void +e_meeting_model_invite_others_dialog (EMeetingModel *im) +{ + EMeetingModelPrivate *priv; + CORBA_Environment ev; + + priv = im->priv; + + if (!get_select_name_dialog (im)) + return; + + CORBA_exception_init (&ev); + + GNOME_Evolution_Addressbook_SelectNames_activateDialog ( + priv->corba_select_names, _("Required Participants"), &ev); + + CORBA_exception_free (&ev); +} + +static void +process_section (EMeetingModel *im, EABDestination **destv, icalparameter_role role) +{ + EMeetingModelPrivate *priv; + int i; + + if (!destv) + return; + + priv = im->priv; + for (i = 0; destv[i]; i++) { + EMeetingAttendee *ia; + const char *name, *attendee = NULL; + char *attr; + CORBA_Environment ev; + EABDestination *dest = destv[i]; + + CORBA_exception_init (&ev); + + /* Get the CN */ + name = eab_destination_get_name (dest); + + /* Get the field as attendee from the backend */ + if (cal_client_get_ldap_attribute (priv->client, &attr, NULL) && attr) { + /* FIXME this should be more general */ + if (!strcmp (attr, "icscalendar")) { + EContact *contact = eab_destination_get_contact (dest); + if (contact) + attendee = e_contact_get_const (contact, E_CONTACT_ICS_CALENDAR); + } + + g_free (attr); + } + + CORBA_exception_init (&ev); + + /* If we couldn't get the attendee prior, get the email address as the default */ + if (attendee == NULL || *attendee == '\0') { + attendee = eab_destination_get_email (dest); + } + + CORBA_exception_free (&ev); + + if (attendee == NULL || *attendee == '\0') + continue; + + if (e_meeting_model_find_attendee (im, attendee, NULL) == NULL) { + ia = e_meeting_model_add_attendee_with_defaults (im); + + e_meeting_attendee_set_address (ia, g_strdup_printf ("MAILTO:%s", attendee)); + e_meeting_attendee_set_role (ia, role); + if (role == ICAL_ROLE_NONPARTICIPANT) + e_meeting_attendee_set_cutype (ia, ICAL_CUTYPE_RESOURCE); + e_meeting_attendee_set_cn (ia, g_strdup (name)); + } + } +} + +static void +select_names_ok_cb (BonoboListener *listener, + const char *event_name, + const CORBA_any *arg, + CORBA_Environment *ev, + gpointer data) +{ + EMeetingModel *im = data; + EMeetingModelPrivate *priv; + Bonobo_Control corba_control; + GtkWidget *control_widget; + BonoboControlFrame *control_frame; + Bonobo_PropertyBag pb; + char *dest_str; + EABDestination **dest; + int i; + + priv = im->priv; + + for (i = 0; sections[i] != NULL; i++) { + corba_control = GNOME_Evolution_Addressbook_SelectNames_getEntryBySection + (priv->corba_select_names, sections[i], ev); + control_widget = bonobo_widget_new_control_from_objref + (corba_control, CORBA_OBJECT_NIL); + + control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (control_widget)); + pb = bonobo_control_frame_get_control_property_bag (control_frame, NULL); + dest_str = bonobo_pbclient_get_string (pb, "destinations", NULL); + dest = eab_destination_importv (dest_str); + process_section (im, dest, roles[i]); + eab_destination_freev (dest); + } +} + +static void +attendee_changed_cb (EMeetingAttendee *ia, gpointer data) +{ + EMeetingModel *im = E_MEETING_MODEL (data); + EMeetingModelPrivate *priv; + gint row = -1, i; + + priv = im->priv; + + /* FIXME: Ideally I think you are supposed to call pre_change() before + the data structures are changed. */ + e_table_model_pre_change (E_TABLE_MODEL (im)); + + for (i = 0; i < priv->attendees->len; i++) { + if (ia == g_ptr_array_index (priv->attendees, i)) { + row = i; + break; + } + } + + if (row == -1) + e_table_model_no_change (E_TABLE_MODEL (im)); + else + e_table_model_row_changed (E_TABLE_MODEL (im), row); +} + +static void +table_destroy_state_cb (ETableScrolled *etable, gpointer data) +{ + ETable *real_table; + char *filename = data; + + real_table = e_table_scrolled_get_table (etable); + e_table_save_state (real_table, filename); + + g_free (data); +} + +static void +table_destroy_list_cb (ETableScrolled *etable, gpointer data) +{ + EMeetingModel *im = E_MEETING_MODEL (data); + EMeetingModelPrivate *priv; + + priv = im->priv; + + priv->tables = g_list_remove (priv->tables, etable); +} + diff --git a/calendar/gui/e-meeting-model.h b/calendar/gui/e-meeting-model.h new file mode 100644 index 0000000000..50fba6c7a6 --- /dev/null +++ b/calendar/gui/e-meeting-model.h @@ -0,0 +1,116 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-model.h + * + * Copyright (C) 2001 Ximian, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: JP Rosevear + */ + +#ifndef _E_MEETING_MODEL_H_ +#define _E_MEETING_MODEL_H_ + +#include <gtk/gtk.h> +#include <gal/e-table/e-table-scrolled.h> +#include <gal/e-table/e-table-model.h> +#include <cal-client/cal-client.h> +#include "e-meeting-attendee.h" + +G_BEGIN_DECLS + +#define E_TYPE_MEETING_MODEL (e_meeting_model_get_type ()) +#define E_MEETING_MODEL(obj) (GTK_CHECK_CAST ((obj), E_TYPE_MEETING_MODEL, EMeetingModel)) +#define E_MEETING_MODEL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_MEETING_MODEL, EMeetingModelClass)) +#define E_IS_MEETING_MODEL(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_MEETING_MODEL)) +#define E_IS_MEETING_MODEL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_MEETING_MODEL)) + + +typedef struct _EMeetingModel EMeetingModel; +typedef struct _EMeetingModelPrivate EMeetingModelPrivate; +typedef struct _EMeetingModelClass EMeetingModelClass; + +typedef enum { + E_MEETING_MODEL_ADDRESS_COL, + E_MEETING_MODEL_MEMBER_COL, + E_MEETING_MODEL_TYPE_COL, + E_MEETING_MODEL_ROLE_COL, + E_MEETING_MODEL_RSVP_COL, + E_MEETING_MODEL_DELTO_COL, + E_MEETING_MODEL_DELFROM_COL, + E_MEETING_MODEL_STATUS_COL, + E_MEETING_MODEL_CN_COL, + E_MEETING_MODEL_LANGUAGE_COL, + E_MEETING_MODEL_COLUMN_COUNT +} EMeetingModelColumns; + +struct _EMeetingModel { + ETableModel parent; + + EMeetingModelPrivate *priv; +}; + +struct _EMeetingModelClass { + ETableModelClass parent_class; +}; + +typedef void (* EMeetingModelRefreshCallback) (gpointer data); + + +GtkType e_meeting_model_get_type (void); +GtkObject *e_meeting_model_new (void); + +CalClient *e_meeting_model_get_cal_client (EMeetingModel *im); +void e_meeting_model_set_cal_client (EMeetingModel *im, CalClient *client); + +icaltimezone *e_meeting_model_get_zone (EMeetingModel *im); +void e_meeting_model_set_zone (EMeetingModel *im, icaltimezone *zone); + +void e_meeting_model_add_attendee (EMeetingModel *im, EMeetingAttendee *ia); +EMeetingAttendee *e_meeting_model_add_attendee_with_defaults (EMeetingModel *im); + +void e_meeting_model_remove_attendee (EMeetingModel *im, EMeetingAttendee *ia); +void e_meeting_model_remove_all_attendees (EMeetingModel *im); + +EMeetingAttendee *e_meeting_model_find_attendee (EMeetingModel *im, const gchar *address, gint *row); +EMeetingAttendee *e_meeting_model_find_attendee_at_row (EMeetingModel *im, gint row); + +gint e_meeting_model_count_actual_attendees (EMeetingModel *im); +const GPtrArray *e_meeting_model_get_attendees (EMeetingModel *im); + +void e_meeting_model_refresh_all_busy_periods (EMeetingModel *im, + EMeetingTime *start, + EMeetingTime *end, + EMeetingModelRefreshCallback call_back, + gpointer data); +void e_meeting_model_refresh_busy_periods (EMeetingModel *im, + int row, + EMeetingTime *start, + EMeetingTime *end, + EMeetingModelRefreshCallback call_back, + gpointer data); + + +/* Helpful functions */ +ETableScrolled *e_meeting_model_etable_from_model (EMeetingModel *im, const gchar *spec_file, const gchar *state_file); +void e_meeting_model_etable_click_to_add (EMeetingModel *im, gboolean click_to_add); +int e_meeting_model_etable_model_to_view_row (ETable *et, EMeetingModel *im, int model_row); +int e_meeting_model_etable_view_to_model_row (ETable *et, EMeetingModel *im, int view_row); + +void e_meeting_model_invite_others_dialog (EMeetingModel *im); + +G_END_DECLS + +#endif diff --git a/calendar/gui/e-meeting-store.c b/calendar/gui/e-meeting-store.c index 0129756e7c..6064971d9f 100644 --- a/calendar/gui/e-meeting-store.c +++ b/calendar/gui/e-meeting-store.c @@ -30,7 +30,6 @@ #include <libgnome/gnome-util.h> #include <libgnomevfs/gnome-vfs.h> #include <ebook/e-book.h> -#include <ebook/e-book-util.h> #include <cal-util/cal-component.h> #include <cal-util/cal-util.h> #include <cal-util/timeutil.h> @@ -50,8 +49,6 @@ struct _EMeetingStorePrivate { icaltimezone *zone; EBook *ebook; - gboolean book_loaded; - gboolean book_load_wait; GPtrArray *refresh_queue; GHashTable *refresh_data; @@ -81,26 +78,10 @@ struct _EMeetingStoreQueueData { static GObjectClass *parent_class = NULL; static void -book_open_cb (EBook *book, EBookStatus status, gpointer data) -{ - EMeetingStore *store = E_MEETING_STORE (data); - - if (status == E_BOOK_STATUS_SUCCESS) - store->priv->book_loaded = TRUE; - else - g_warning ("Book not loaded"); - - if (store->priv->book_load_wait) { - store->priv->book_load_wait = FALSE; - gtk_main_quit (); - } -} - -static void start_addressbook_server (EMeetingStore *store) { store->priv->ebook = e_book_new (); - e_book_load_default_book (store->priv->ebook, book_open_cb, store); + e_book_load_local_addressbook (store->priv->ebook, NULL); } static icalparameter_cutype @@ -914,9 +895,11 @@ find_zone (icalproperty *ip, icalcomponent *tz_top_level) iter = icalcomponent_begin_component (tz_top_level, ICAL_VTIMEZONE_COMPONENT); while ((sub_comp = icalcompiter_deref (&iter)) != NULL) { icalcomponent *clone; + icalproperty *prop; const char *tz_tzid; - - tz_tzid = icalproperty_get_tzid (sub_comp); + + prop = icalcomponent_get_first_property (sub_comp, ICAL_TZID_PROPERTY); + tz_tzid = icalproperty_get_tzid (prop); if (!strcmp (tzid, tz_tzid)) { icaltimezone *zone; @@ -1141,7 +1124,7 @@ refresh_busy_periods (gpointer data) /* Check the server for free busy data */ if (priv->client) { - GList *fb_data, *users = NULL; + GList *fb_data = NULL, *users = NULL; struct icaltimetype itt; time_t startt, endt; const char *user; @@ -1164,7 +1147,7 @@ refresh_busy_periods (gpointer data) user = itip_strip_mailto (e_meeting_attendee_get_address (attendee)); users = g_list_append (users, g_strdup (user)); - fb_data = cal_client_get_free_busy (priv->client, users, startt, endt); + cal_client_get_free_busy (priv->client, users, startt, endt, &fb_data, NULL); g_list_foreach (users, (GFunc)g_free, NULL); g_list_free (users); @@ -1181,11 +1164,6 @@ refresh_busy_periods (gpointer data) } /* Look for fburl's of attendee with no free busy info on server */ - if (!priv->book_loaded) { - priv->book_load_wait = TRUE; - gtk_main (); - } - if (!e_meeting_attendee_is_set_address (attendee)) { process_callbacks (qdata); return TRUE; diff --git a/calendar/gui/e-meeting-time-sel.c b/calendar/gui/e-meeting-time-sel.c index 157320ef16..91d915a4d7 100644 --- a/calendar/gui/e-meeting-time-sel.c +++ b/calendar/gui/e-meeting-time-sel.c @@ -265,6 +265,7 @@ e_meeting_time_selector_init (EMeetingTimeSelector * mts) void e_meeting_time_selector_construct (EMeetingTimeSelector * mts, EMeetingStore *ems) { + char *filename; GtkWidget *hbox, *vbox, *separator, *button, *label, *table; GtkWidget *alignment, *child_hbox, *arrow, *menuitem; GSList *group; @@ -313,7 +314,12 @@ e_meeting_time_selector_construct (EMeetingTimeSelector * mts, EMeetingStore *em gtk_box_pack_start (GTK_BOX (vbox), mts->attendees_vbox, TRUE, TRUE, 0); gtk_widget_show (mts->attendees_vbox); + + /* build the etable */ + filename = g_build_filename (calendar_component_peek_config_directory (calendar_component_peek ()), + "config", "et-header-meeting-time-sel", NULL); mts->model = ems; + if (mts->model) g_object_ref (mts->model); diff --git a/calendar/gui/e-select-names-editable.c b/calendar/gui/e-select-names-editable.c index 2fcc93397a..29c54c7979 100644 --- a/calendar/gui/e-select-names-editable.c +++ b/calendar/gui/e-select-names-editable.c @@ -25,7 +25,7 @@ #include <gtk/gtkcelleditable.h> #include <bonobo/bonobo-exception.h> #include <bonobo/bonobo-widget.h> -#include <ebook/e-destination.h> +#include <addressbook/util/eab-destination.h> #include "e-select-names-editable.h" #include "Evolution-Addressbook-SelectNames.h" @@ -187,16 +187,16 @@ e_select_names_editable_new () gchar * e_select_names_editable_get_address (ESelectNamesEditable *esne) { - EDestination **dest; + EABDestination **dest; gchar *dest_str; gchar *result; g_return_val_if_fail (E_SELECT_NAMES_EDITABLE (esne), NULL); dest_str = bonobo_pbclient_get_string (esne->priv->bag, "destinations", NULL); - dest = e_destination_importv (dest_str); - result = g_strdup (e_destination_get_email (*dest)); - e_destination_freev (dest); + dest = eab_destination_importv (dest_str); + result = g_strdup (eab_destination_get_email (*dest)); + eab_destination_freev (dest); return result; } @@ -204,16 +204,16 @@ e_select_names_editable_get_address (ESelectNamesEditable *esne) gchar * e_select_names_editable_get_name (ESelectNamesEditable *esne) { - EDestination **dest; + EABDestination **dest; gchar *dest_str; gchar *result; g_return_val_if_fail (E_SELECT_NAMES_EDITABLE (esne), NULL); dest_str = bonobo_pbclient_get_string (esne->priv->bag, "destinations", NULL); - dest = e_destination_importv (dest_str); - result = g_strdup (e_destination_get_name (*dest)); - e_destination_freev (dest); + dest = eab_destination_importv (dest_str); + result = g_strdup (eab_destination_get_name (*dest)); + eab_destination_freev (dest); return result; } diff --git a/calendar/gui/e-tasks.c b/calendar/gui/e-tasks.c index b441aee09d..768b2e587c 100644 --- a/calendar/gui/e-tasks.c +++ b/calendar/gui/e-tasks.c @@ -572,7 +572,6 @@ GtkWidget * e_tasks_construct (ETasks *tasks) { ETasksPrivate *priv; - ECalModel *model; g_return_val_if_fail (tasks != NULL, NULL); g_return_val_if_fail (E_IS_TASKS (tasks), NULL); @@ -581,24 +580,6 @@ e_tasks_construct (ETasks *tasks) setup_widgets (tasks); - priv->client = cal_client_new (); - if (!priv->client) - return NULL; - - g_signal_connect (priv->client, "cal_opened", - G_CALLBACK (cal_opened_cb), tasks); - g_signal_connect (priv->client, "backend_error", - G_CALLBACK (backend_error_cb), tasks); - g_signal_connect (priv->client, "categories_changed", - G_CALLBACK (client_categories_changed_cb), tasks); - g_signal_connect (priv->client, "obj_updated", - G_CALLBACK (client_obj_updated_cb), tasks); - - model = e_calendar_table_get_model (E_CALENDAR_TABLE (priv->tasks_view)); - g_assert (model != NULL); - - e_cal_model_add_client (model, priv->client); - return GTK_WIDGET (tasks); } @@ -685,6 +666,8 @@ e_tasks_open (ETasks *tasks, EUri *uri; char *real_uri; char *urinopwd; + ECalModel *model; + GError *error = NULL; g_return_val_if_fail (tasks != NULL, FALSE); g_return_val_if_fail (E_IS_TASKS (tasks), FALSE); @@ -704,10 +687,30 @@ e_tasks_open (ETasks *tasks, g_free (message); g_free (urinopwd); - if (!cal_client_open_calendar (priv->client, real_uri, FALSE)) { - g_message ("e_tasks_open(): Could not issue the request"); + /* create the CalClient */ + priv->client = cal_client_new (real_uri, CALOBJ_TYPE_TODO); + if (!priv->client) + return NULL; + + g_signal_connect (priv->client, "cal_opened", + G_CALLBACK (cal_opened_cb), tasks); + g_signal_connect (priv->client, "backend_error", + G_CALLBACK (backend_error_cb), tasks); + g_signal_connect (priv->client, "categories_changed", + G_CALLBACK (client_categories_changed_cb), tasks); + g_signal_connect (priv->client, "obj_updated", + G_CALLBACK (client_obj_updated_cb), tasks); + + model = e_calendar_table_get_model (E_CALENDAR_TABLE (priv->tasks_view)); + g_assert (model != NULL); + + e_cal_model_add_client (model, priv->client); + + if (cal_client_open (priv->client, FALSE, &error)) { + g_message ("e_tasks_open(): %s", error->message); g_free (real_uri); e_uri_free (uri); + g_error_free (error); return FALSE; } @@ -787,7 +790,8 @@ cal_opened_cb (CalClient *client, location = calendar_config_get_timezone (); zone = icaltimezone_get_builtin_timezone (location); if (zone) - cal_client_set_default_timezone (client, zone); + /* FIXME Error checking */ + cal_client_set_default_timezone (client, zone, NULL); return; case CAL_CLIENT_OPEN_ERROR: @@ -937,60 +941,6 @@ create_sexp (void) return sexp; } -/* Callback used when a component is updated in the live query */ -static void -query_obj_updated_cb (CalQuery *query, const char *uid, - gboolean query_in_progress, int n_scanned, int total, - gpointer data) -{ - ETasks *tasks; - ETasksPrivate *priv; - - tasks = E_TASKS (data); - priv = tasks->priv; - - delete_error_dialog (cal_client_remove_object (priv->client, uid), CAL_COMPONENT_TODO); -} - -/* Callback used when an evaluation error occurs when running a query */ -static void -query_eval_error_cb (CalQuery *query, const char *error_str, gpointer data) -{ - ETasks *tasks; - ETasksPrivate *priv; - - tasks = E_TASKS (data); - priv = tasks->priv; - - g_warning ("eval error: %s\n", error_str); - - set_status_message (tasks, NULL); - - g_signal_handlers_disconnect_matched (priv->query, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, tasks); - g_object_unref (priv->query); - priv->query = NULL; -} - -static void -query_query_done_cb (CalQuery *query, CalQueryDoneStatus status, const char *error_str, gpointer data) -{ - ETasks *tasks; - ETasksPrivate *priv; - - tasks = E_TASKS (data); - priv = tasks->priv; - - if (status != CAL_QUERY_DONE_SUCCESS) - g_warning ("query done: %s\n", error_str); - - set_status_message (tasks, NULL); - - g_signal_handlers_disconnect_matched (priv->query, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, tasks); - g_object_unref (priv->query); - priv->query = NULL; -} /** * e_tasks_expunge: * @tasks: A tasks control widget @@ -1002,31 +952,32 @@ e_tasks_delete_completed (ETasks *tasks) { ETasksPrivate *priv; char *sexp; + GList *objects, *l; g_return_if_fail (tasks != NULL); g_return_if_fail (E_IS_TASKS (tasks)); priv = tasks->priv; - /* If we have a query, we are already expunging */ - if (priv->query) - return; + /* FIXME Confirm expunge */ sexp = create_sexp (); set_status_message (tasks, _("Expunging")); - priv->query = cal_client_get_query (priv->client, sexp); - g_free (sexp); - - if (!priv->query) { + + if (!cal_client_get_object_list (priv->client, sexp, &objects, NULL)) { set_status_message (tasks, NULL); - g_message ("update_query(): Could not create the query"); + g_warning (G_STRLOC ": Could not get the objects"); + return; } + + for (l = objects; l; l = l->next) { + /* FIXME Better error handling */ + cal_client_remove_object (priv->client, icalcomponent_get_uid (l->data), NULL); + } - g_signal_connect (priv->query, "obj_updated", G_CALLBACK (query_obj_updated_cb), tasks); - g_signal_connect (priv->query, "query_done", G_CALLBACK (query_query_done_cb), tasks); - g_signal_connect (priv->query, "eval_error", G_CALLBACK (query_eval_error_cb), tasks); + set_status_message (tasks, NULL); } /* Callback used from the view collection when we need to display a new view */ @@ -1181,6 +1132,7 @@ e_tasks_update_all_config_settings (void) calendar_config_configure_e_calendar_table (E_CALENDAR_TABLE (priv->tasks_view)); if (zone) - cal_client_set_default_timezone (priv->client, zone); + /* FIXME Error checking */ + cal_client_set_default_timezone (priv->client, zone, NULL); } } diff --git a/calendar/gui/e-week-view-event-item.c b/calendar/gui/e-week-view-event-item.c index 139f28bb13..fd68130bc5 100644 --- a/calendar/gui/e-week-view-event-item.c +++ b/calendar/gui/e-week-view-event-item.c @@ -890,7 +890,6 @@ e_week_view_event_item_double_click (EWeekViewEventItem *wveitem, EWeekView *week_view; EWeekViewEvent *event; GnomeCanvasItem *item; - GnomeCalendar *calendar; item = GNOME_CANVAS_ITEM (wveitem); @@ -902,11 +901,7 @@ e_week_view_event_item_double_click (EWeekViewEventItem *wveitem, e_week_view_stop_editing_event (week_view); - calendar = e_cal_view_get_calendar (E_CAL_VIEW (week_view)); - if (calendar) - gnome_calendar_edit_object (calendar, event->comp_data->client, event->comp_data->icalcomp, FALSE); - else - g_warning ("Calendar not set"); + e_cal_view_edit_appointment (E_CAL_VIEW (week_view), event->comp_data->client, event->comp_data->icalcomp, FALSE); return TRUE; } diff --git a/calendar/gui/e-week-view.c b/calendar/gui/e-week-view.c index 8028bf13e6..1be94fc1de 100644 --- a/calendar/gui/e-week-view.c +++ b/calendar/gui/e-week-view.c @@ -62,6 +62,7 @@ #include "calendar-config.h" #include "print.h" #include "goto.h" +#include "e-cal-model-calendar.h" #include "e-week-view-event-item.h" #include "e-week-view-layout.h" #include "e-week-view-main-item.h" @@ -312,8 +313,6 @@ e_week_view_init (EWeekView *week_view) week_view->main_gc = NULL; - week_view->default_category = NULL; - /* Create the small font. */ week_view->use_small_font = TRUE; @@ -423,8 +422,11 @@ GtkWidget * e_week_view_new (void) { GtkWidget *week_view; + ECalModel *model; + + model = E_CAL_MODEL (e_cal_model_calendar_new ()); - week_view = GTK_WIDGET (g_object_new (e_week_view_get_type (), NULL)); + week_view = GTK_WIDGET (g_object_new (e_week_view_get_type (), "model", model, NULL)); return week_view; } @@ -457,11 +459,6 @@ e_week_view_destroy (GtkObject *object) week_view->small_font_desc = NULL; } - if (week_view->default_category) { - g_free (week_view->default_category); - week_view->default_category = NULL; - } - if (week_view->normal_cursor) { gdk_cursor_unref (week_view->normal_cursor); week_view->normal_cursor = NULL; @@ -1149,7 +1146,7 @@ process_component (EWeekView *week_view, ECalModelComponent *comp_data) g_object_unref (tmp_comp); } - /* Add the occurrences of the event. */ + /* Add the occurrences of the event */ num_days = week_view->multi_week_view ? week_view->weeks_shown * 7 : 7; add_event_data.week_view = week_view; @@ -1158,8 +1155,7 @@ process_component (EWeekView *week_view, ECalModelComponent *comp_data) week_view->day_starts[0], week_view->day_starts[num_days], e_week_view_add_event, &add_event_data, - cal_client_resolve_tzid_cb, - comp_data->client, + cal_client_resolve_tzid_cb, comp_data->client, e_cal_view_get_timezone (E_CAL_VIEW (week_view))); g_object_unref (comp); @@ -1178,8 +1174,6 @@ e_week_view_update_query (ECalView *cal_view) e_week_view_free_events (week_view); e_week_view_queue_layout (week_view); - e_cal_view_set_status_message (E_CAL_VIEW (week_view), _("Searching")); - rows = e_table_model_row_count (E_TABLE_MODEL (e_cal_view_get_model (E_CAL_VIEW (week_view)))); for (r = 0; r < rows; r++) { ECalModelComponent *comp_data; @@ -1188,8 +1182,6 @@ e_week_view_update_query (ECalView *cal_view) g_assert (comp_data != NULL); process_component (week_view, comp_data); } - - e_cal_view_set_status_message (E_CAL_VIEW (week_view), NULL); } static void @@ -1217,27 +1209,6 @@ e_week_view_draw_shadow (EWeekView *week_view) gdk_draw_line (window, light_gc, x1, y2, x2, y2); } -/** - * e_week_view_set_default_category: - * @week_view: A week view. - * @category: Default category name or NULL for no category. - * - * Sets the default category that will be used when creating new calendar - * components from the week view. - **/ -void -e_week_view_set_default_category (EWeekView *week_view, const char *category) -{ - g_return_if_fail (week_view != NULL); - g_return_if_fail (E_IS_WEEK_VIEW (week_view)); - - if (week_view->default_category) - g_free (week_view->default_category); - - week_view->default_category = g_strdup (category); -} - - /* This sets the selected time range. The EWeekView will show the corresponding month and the days between start_time and end_time will be selected. To select a single day, use the same value for start_time & end_time. */ @@ -2015,7 +1986,7 @@ e_week_view_on_button_press (GtkWidget *widget, return FALSE; if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) { - gnome_calendar_new_appointment (e_cal_view_get_calendar (E_CAL_VIEW (week_view))); + e_cal_view_new_appointment (E_CAL_VIEW (week_view)); return TRUE; } @@ -2876,14 +2847,11 @@ e_week_view_on_text_item_event (GnomeCanvasItem *item, { EWeekViewEvent *event; gint event_num, span_num; - GnomeCalendar *calendar; #if 0 g_print ("In e_week_view_on_text_item_event\n"); #endif - calendar = e_cal_view_get_calendar (E_CAL_VIEW (week_view)); - switch (gdkevent->type) { case GDK_KEY_PRESS: if (gdkevent && gdkevent->key.keyval == GDK_Return) { @@ -2912,10 +2880,9 @@ e_week_view_on_text_item_event (GnomeCanvasItem *item, event = &g_array_index (week_view->events, EWeekViewEvent, event_num); - if (calendar) - gnome_calendar_edit_object (calendar, event->comp_data->client, event->comp_data->icalcomp, FALSE); - else - g_warning ("Calendar not set"); + e_cal_view_edit_appointment (E_CAL_VIEW (week_view), + event->comp_data->client, + event->comp_data->icalcomp, FALSE); gtk_signal_emit_stop_by_name (GTK_OBJECT (item), "event"); return TRUE; @@ -3049,7 +3016,8 @@ e_week_view_on_editing_stopped (EWeekView *week_view, CalComponent *comp; CalComponentText summary; const char *uid; - + gboolean on_server; + /* Note: the item we are passed here isn't reliable, so we just stop the edit of whatever item was being edited. We also receive this event twice for some reason. */ @@ -3079,8 +3047,9 @@ e_week_view_on_editing_stopped (EWeekView *week_view, comp = cal_component_new (); cal_component_set_icalcomponent (comp, icalcomponent_new_clone (event->comp_data->icalcomp)); - if (string_is_empty (text) && - !cal_comp_is_on_server (comp, event->comp_data->client)) { + on_server = cal_comp_is_on_server (comp, event->comp_data->client); + + if (string_is_empty (text) && !on_server) { const char *uid; cal_component_get_uid (comp, &uid); @@ -3099,33 +3068,33 @@ e_week_view_on_editing_stopped (EWeekView *week_view, e_week_view_reshape_event_span (week_view, event_num, span_num); } else if (summary.value || !string_is_empty (text)) { + icalcomponent *icalcomp = cal_component_get_icalcomponent (comp); + summary.value = text; summary.altrep = NULL; cal_component_set_summary (comp, &summary); - - if (cal_component_is_instance (comp)) { - CalObjModType mod; - - if (recur_component_dialog (comp, &mod, NULL)) { - if (cal_client_update_object_with_mod (event->comp_data->client, comp, mod) - == CAL_CLIENT_RESULT_SUCCESS) { - if (itip_organizer_is_user (comp, event->comp_data->client) - && send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (week_view)), - event->comp_data->client, comp, FALSE)) - itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, - event->comp_data->client, NULL); - } else { - g_message ("e_week_view_on_editing_stopped(): Could not update the object!"); + + if (!on_server) { + if (!cal_client_create_object (event->comp_data->client, icalcomp, NULL, NULL)) + g_message (G_STRLOC ": Could not create the object!"); + } else { + CalObjModType mod = CALOBJ_MOD_ALL; + GtkWindow *toplevel; + + if (cal_component_has_recurrences (comp)) { + if (!recur_component_dialog (comp, &mod, NULL)) { + goto out; } } - } else if (cal_client_update_object (event->comp_data->client, comp) == CAL_CLIENT_RESULT_SUCCESS) { - if (itip_organizer_is_user (comp, event->comp_data->client) && - send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (week_view)), - event->comp_data->client, comp, FALSE)) - itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, - event->comp_data->client, NULL); - } else { - g_message ("e_week_view_on_editing_stopped(): Could not update the object!"); + + /* FIXME When sending here, what exactly should we send? */ + toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (week_view))); + if (cal_client_modify_object (event->comp_data->client, icalcomp, mod, NULL)) { + if (itip_organizer_is_user (comp, event->comp_data->client) + && send_component_dialog (toplevel, event->comp_data->client, comp, FALSE)) + itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, + event->comp_data->client, NULL); + } } } @@ -3182,6 +3151,10 @@ e_week_view_find_event_from_uid (EWeekView *week_view, EWeekViewEvent *event; gint event_num, num_events; + *event_num_return = -1; + if (!uid) + return FALSE; + num_events = week_view->events->len; for (event_num = 0; event_num < num_events; event_num++) { const char *u; @@ -3291,6 +3264,8 @@ e_week_view_do_key_press (GtkWidget *widget, GdkEventKey *event) /* Add a new event covering the selected range. */ icalcomp = e_cal_model_create_component_with_defaults (e_cal_view_get_model (E_CAL_VIEW (week_view))); + if (!icalcomp) + return FALSE; uid = icalcomponent_get_uid (icalcomp); comp = cal_component_new (); @@ -3313,7 +3288,8 @@ e_week_view_do_key_press (GtkWidget *widget, GdkEventKey *event) e_cal_view_get_timezone (E_CAL_VIEW (week_view))); cal_component_set_dtend (comp, &date); - cal_component_set_categories (comp, week_view->default_category); + cal_component_set_categories ( + comp, e_cal_view_get_default_category (E_CAL_VIEW (week_view))); /* We add the event locally and start editing it. We don't send it to the server until the user finishes editing it. */ @@ -3546,63 +3522,6 @@ e_week_view_popup_menu (GtkWidget *widget) } void -e_week_view_unrecur_appointment (EWeekView *week_view) -{ - EWeekViewEvent *event; - CalComponent *comp, *new_comp; - CalComponentDateTime date; - struct icaltimetype itt; - - if (week_view->popup_event_num == -1) - return; - - event = &g_array_index (week_view->events, EWeekViewEvent, - week_view->popup_event_num); - - /* For the recurring object, we add a exception to get rid of the - instance. */ - comp = cal_component_new (); - cal_component_set_icalcomponent (comp, icalcomponent_new_clone (event->comp_data->icalcomp)); - cal_comp_util_add_exdate (comp, event->start, e_cal_view_get_timezone (E_CAL_VIEW (week_view))); - - /* For the unrecurred instance we duplicate the original object, - create a new uid for it, get rid of the recurrence rules, and set - the start & end times to the instances times. */ - new_comp = cal_component_new (); - cal_component_set_icalcomponent (new_comp, icalcomponent_new_clone (event->comp_data->icalcomp)); - cal_component_set_uid (new_comp, cal_component_gen_uid ()); - cal_component_set_rdate_list (new_comp, NULL); - cal_component_set_rrule_list (new_comp, NULL); - cal_component_set_exdate_list (new_comp, NULL); - cal_component_set_exrule_list (new_comp, NULL); - - date.value = &itt; - date.tzid = icaltimezone_get_tzid (e_cal_view_get_timezone (E_CAL_VIEW (week_view))); - - *date.value = icaltime_from_timet_with_zone (event->start, FALSE, - e_cal_view_get_timezone (E_CAL_VIEW (week_view))); - cal_component_set_dtstart (new_comp, &date); - *date.value = icaltime_from_timet_with_zone (event->end, FALSE, - e_cal_view_get_timezone (E_CAL_VIEW (week_view))); - cal_component_set_dtend (new_comp, &date); - - /* Now update both CalComponents. Note that we do this last since at - present the updates happen synchronously so our event may disappear. - */ - if (cal_client_update_object (event->comp_data->client, comp) - != CAL_CLIENT_RESULT_SUCCESS) - g_message ("e_week_view_on_unrecur_appointment(): Could not update the object!"); - - g_object_unref (comp); - - if (cal_client_update_object (event->comp_data->client, new_comp) - != CAL_CLIENT_RESULT_SUCCESS) - g_message ("e_week_view_on_unrecur_appointment(): Could not update the object!"); - - g_object_unref (new_comp); -} - -void e_week_view_jump_to_button_item (EWeekView *week_view, GnomeCanvasItem *item) { gint day; diff --git a/calendar/gui/e-week-view.h b/calendar/gui/e-week-view.h index c24470155d..0296c19c42 100644 --- a/calendar/gui/e-week-view.h +++ b/calendar/gui/e-week-view.h @@ -331,9 +331,6 @@ struct _EWeekView gchar *pm_string; gint am_string_width; gint pm_string_width; - - /* The default category for new events */ - char *default_category; }; struct _EWeekViewClass @@ -353,9 +350,6 @@ void e_week_view_get_first_day_shown (EWeekView *week_view, void e_week_view_set_first_day_shown (EWeekView *week_view, GDate *date); -void e_week_view_set_default_category (EWeekView *week_view, - const char *category); - /* The selected time range. The EWeekView will show the corresponding month and the days between start_time and end_time will be selected. To select a single day, use the same value for start_time & end_time. */ @@ -396,8 +390,6 @@ void e_week_view_set_24_hour_format (EWeekView *week_view, void e_week_view_delete_occurrence (EWeekView *week_view); -void e_week_view_unrecur_appointment (EWeekView *week_view); - /* Returns the number of selected events (0 or 1 at present). */ gint e_week_view_get_num_events_selected (EWeekView *week_view); diff --git a/calendar/gui/gnome-cal.c b/calendar/gui/gnome-cal.c index c2a0c2c61e..bcefd8eeee 100644 --- a/calendar/gui/gnome-cal.c +++ b/calendar/gui/gnome-cal.c @@ -61,8 +61,6 @@ #include "misc.h" #include "ea-calendar.h" -extern ECompEditorRegistry *comp_editor_registry; - /* Private part of the GnomeCalendar structure */ @@ -71,6 +69,8 @@ struct _GnomeCalendarPrivate { * The Calendar Folder. */ + GHashTable *clients; + /* Set of categories from the calendar client */ GPtrArray *cal_categories; @@ -119,6 +119,7 @@ struct _GnomeCalendarPrivate { /* This is the view currently shown. We use it to keep track of the positions of the panes. range_selected is TRUE if a range of dates was selected in the date navigator to show the view. */ + ECalView *views[GNOME_CAL_LAST_VIEW]; GnomeCalendarViewType current_view_type; gboolean range_selected; @@ -145,10 +146,6 @@ struct _GnomeCalendarPrivate { 'dates-shown-changed' signal.*/ time_t visible_start; time_t visible_end; - - /* Calendar query for purging old events */ - GList *exp_queries; - time_t exp_older_than; }; /* Signal IDs */ @@ -361,97 +358,70 @@ gnome_calendar_class_init (GnomeCalendarClass *class) /* Callback used when the calendar query reports of an updated object */ static void -dn_query_obj_updated_cb (CalQuery *query, const char *uid, - gboolean query_in_progress, int n_scanned, int total, - gpointer data) +dn_query_objects_added_cb (CalQuery *query, GList *objects, gpointer data) { GnomeCalendar *gcal; GnomeCalendarPrivate *priv; - CalComponent *comp = NULL; - icalcomponent *icalcomp; - CalClientGetStatus status; - + GList *l; + gcal = GNOME_CALENDAR (data); priv = gcal->priv; - /* If this is an update that is not part of an ongoing query, we have to - * retag the whole thing: an event may change dates and the - * tag_calendar_by_comp() below would not know how to untag the old - * dates. - */ - if (!query_in_progress) { - update_query (gcal); - return; - } + for (l = objects; l; l = l->next) { + CalComponent *comp = NULL; - status = cal_client_get_object (cal_query_get_client (query), uid, &icalcomp); - - switch (status) { - case CAL_CLIENT_GET_SUCCESS: comp = cal_component_new (); - if (!cal_component_set_icalcomponent (comp, icalcomp)) { + if (!cal_component_set_icalcomponent (comp, icalcomponent_new_clone (l->data))) { g_object_unref (comp); - icalcomponent_free (icalcomp); - return; + + continue; } - break; - - case CAL_CLIENT_GET_SYNTAX_ERROR: - g_message ("dn_query_obj_updated_cb(): Syntax error while getting object `%s'", uid); - return; - - case CAL_CLIENT_GET_NOT_FOUND: - /* The object is no longer in the server, so do nothing */ - return; - default: - g_assert_not_reached (); - return; + tag_calendar_by_comp (priv->date_navigator, comp, cal_query_get_client (query), NULL, + FALSE, TRUE); + g_object_unref (comp); } - - tag_calendar_by_comp (priv->date_navigator, comp, cal_query_get_client (query), NULL, - FALSE, TRUE); - g_object_unref (comp); } -/* Callback used when the calendar query reports of a removed object */ static void -dn_query_obj_removed_cb (CalQuery *query, const char *uid, gpointer data) +dn_query_objects_modified_cb (CalQuery *query, GList *objects, gpointer data) { GnomeCalendar *gcal; + GnomeCalendarPrivate *priv; gcal = GNOME_CALENDAR (data); + priv = gcal->priv; - /* Just retag the whole thing */ + /* We have to retag the whole thing: an event may change dates + * and the tag_calendar_by_comp() below would not know how to + * untag the old dates. + */ update_query (gcal); } -/* Callback used when the calendar query is done */ +/* Callback used when the calendar query reports of a removed object */ static void -dn_query_query_done_cb (CalQuery *query, CalQueryDoneStatus status, const char *error_str, - gpointer data) +dn_query_objects_removed_cb (CalQuery *query, GList *uids, gpointer data) { GnomeCalendar *gcal; gcal = GNOME_CALENDAR (data); - /* FIXME */ - - if (status != CAL_QUERY_DONE_SUCCESS) - fprintf (stderr, "query done: %s\n", error_str); + /* Just retag the whole thing */ + update_query (gcal); } -/* Callback used when the calendar query reports an evaluation error */ +/* Callback used when the calendar query is done */ static void -dn_query_eval_error_cb (CalQuery *query, const char *error_str, gpointer data) +dn_query_done_cb (CalQuery *query, ECalendarStatus status, gpointer data) { GnomeCalendar *gcal; gcal = GNOME_CALENDAR (data); - /* FIXME */ - - fprintf (stderr, "eval error: %s\n", error_str); + /* FIXME Better error reporting */ + if (status != E_CALENDAR_STATUS_OK) + g_warning (G_STRLOC ": Query did not successfully complete"); } /* Returns the current view widget, an EDayView, EWeekView or ECalListView. */ @@ -603,6 +573,7 @@ adjust_query_sexp (GnomeCalendar *gcal, const char *sexp) start, end, sexp); + g_free (start); g_free (end); @@ -649,22 +620,24 @@ update_query (GnomeCalendar *gcal) /* create queries for each loaded client */ client_list = e_cal_model_get_client_list (e_cal_view_get_model (E_CAL_VIEW (priv->day_view))); for (l = client_list; l != NULL; l = l->next) { - old_query = cal_client_get_query ((CalClient *) l->data, real_sexp); - if (!old_query) { - g_message ("update_query(): Could not create the query"); + if (!cal_client_get_query ((CalClient *) l->data, real_sexp, &old_query, NULL)) { + g_warning (G_STRLOC ": Could not create the query"); + continue; } - g_signal_connect (old_query, "obj_updated", - G_CALLBACK (dn_query_obj_updated_cb), gcal); - g_signal_connect (old_query, "obj_removed", - G_CALLBACK (dn_query_obj_removed_cb), gcal); + g_signal_connect (old_query, "objects_added", + G_CALLBACK (dn_query_objects_added_cb), gcal); + g_signal_connect (old_query, "objects_modified", + G_CALLBACK (dn_query_objects_modified_cb), gcal); + g_signal_connect (old_query, "objects_removed", + G_CALLBACK (dn_query_objects_removed_cb), gcal); g_signal_connect (old_query, "query_done", - G_CALLBACK (dn_query_query_done_cb), gcal); - g_signal_connect (old_query, "eval_error", - G_CALLBACK (dn_query_eval_error_cb), gcal); + G_CALLBACK (dn_query_done_cb), gcal); priv->dn_queries = g_list_append (priv->dn_queries, old_query); + + cal_query_start (old_query); } g_list_free (client_list); @@ -673,6 +646,30 @@ update_query (GnomeCalendar *gcal) e_cal_view_set_status_message (E_CAL_VIEW (priv->week_view), NULL); } +static void +adjust_query_for_view (ECalView *cal_view, const char *sexp) +{ + char *real_sexp, *start, *end; + time_t ttstart, ttend; + + e_cal_view_get_visible_time_range (cal_view, &ttstart, &ttend); + + start = isodate_from_time_t (ttstart); + end = isodate_from_time_t (ttend); + + real_sexp = g_strdup_printf ( + "(and (occur-in-time-range? (make-time \"%s\")" + " (make-time \"%s\"))" + " %s)", + start, end, sexp); + + e_cal_model_set_query (e_cal_view_get_model (cal_view), real_sexp); + + g_free (start); + g_free (end); + g_free (real_sexp); +} + /** * gnome_calendar_set_query: * @gcal: A calendar. @@ -685,6 +682,7 @@ gnome_calendar_set_query (GnomeCalendar *gcal, const char *sexp) { GnomeCalendarPrivate *priv; ECalModel *model; + int i; g_return_if_fail (gcal != NULL); g_return_if_fail (GNOME_IS_CALENDAR (gcal)); @@ -701,9 +699,9 @@ gnome_calendar_set_query (GnomeCalendar *gcal, const char *sexp) update_query (gcal); - /* Set the query on the main view */ - model = e_cal_view_get_model (E_CAL_VIEW (gnome_calendar_get_current_view_widget (gcal))); - e_cal_model_set_query (model, sexp); + /* Set the query on the views */ + for (i = 0; i < GNOME_CAL_LAST_VIEW; i++) + adjust_query_for_view (E_CAL_VIEW (priv->views[i]), sexp); /* Set the query on the task pad */ model = e_calendar_table_get_model (E_CALENDAR_TABLE (priv->todo)); @@ -747,14 +745,15 @@ search_bar_category_changed_cb (CalSearchBar *cal_search, const char *category, GnomeCalendar *gcal; GnomeCalendarPrivate *priv; ECalModel *model; + int i; gcal = GNOME_CALENDAR (data); priv = gcal->priv; - e_day_view_set_default_category (E_DAY_VIEW (priv->day_view), category); - e_day_view_set_default_category (E_DAY_VIEW (priv->work_week_view), category); - e_week_view_set_default_category (E_WEEK_VIEW (priv->week_view), category); - e_week_view_set_default_category (E_WEEK_VIEW (priv->month_view), category); + for (i = 0; i < GNOME_CAL_LAST_VIEW; i++) { + e_cal_view_set_default_category (E_CAL_VIEW (priv->views[i]), + category); + } model = e_calendar_table_get_model (E_CALENDAR_TABLE (priv->todo)); e_cal_model_set_default_category (model, category); @@ -853,7 +852,6 @@ setup_widgets (GnomeCalendar *gcal) GtkWidget *w; gchar *filename; ETable *etable; - ECalModel *model; priv = gcal->priv; @@ -915,7 +913,8 @@ setup_widgets (GnomeCalendar *gcal) gtk_paned_pack2 (GTK_PANED (priv->vpane), priv->todo, TRUE, TRUE); gtk_widget_show (priv->todo); - filename = g_strdup_printf ("%s/config/TaskPad", evolution_dir); + filename = g_build_filename (calendar_component_peek_config_directory (calendar_component_peek ()), + "TaskPad", NULL); e_calendar_table_load_state (E_CALENDAR_TABLE (priv->todo), filename); g_free (filename); @@ -977,7 +976,7 @@ setup_widgets (GnomeCalendar *gcal) connect_week_view_focus (gcal, E_WEEK_VIEW (priv->month_view)); /* The List View. */ - filename = g_strdup_printf ("%s/config/CalListView", evolution_dir); + filename = g_strdup_printf (".evolution/config/CalListView"); priv->list_view = e_cal_list_view_new (filename); g_free (filename); @@ -988,14 +987,12 @@ setup_widgets (GnomeCalendar *gcal) connect_list_view_focus (gcal, E_CAL_LIST_VIEW (priv->list_view)); - model = (ECalModel *) e_cal_model_calendar_new (); - e_cal_view_set_model (E_CAL_VIEW (priv->day_view), model); - e_cal_view_set_model (E_CAL_VIEW (priv->work_week_view), model); - e_cal_view_set_model (E_CAL_VIEW (priv->week_view), model); - e_cal_view_set_model (E_CAL_VIEW (priv->month_view), model); - e_cal_view_set_model (E_CAL_VIEW (priv->list_view), model); + priv->views[GNOME_CAL_DAY_VIEW] = E_CAL_VIEW (priv->day_view); + priv->views[GNOME_CAL_WORK_WEEK_VIEW] = E_CAL_VIEW (priv->work_week_view); + priv->views[GNOME_CAL_WEEK_VIEW] = E_CAL_VIEW (priv->week_view); + priv->views[GNOME_CAL_MONTH_VIEW] = E_CAL_VIEW (priv->month_view); + priv->views[GNOME_CAL_LIST_VIEW] = E_CAL_VIEW (priv->list_view); - g_object_unref (model); gnome_calendar_update_config_settings (gcal, TRUE); } @@ -1008,6 +1005,8 @@ gnome_calendar_init (GnomeCalendar *gcal) priv = g_new0 (GnomeCalendarPrivate, 1); gcal->priv = priv; + priv->clients = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + priv->cal_categories = NULL; priv->tasks_categories = NULL; @@ -1027,8 +1026,6 @@ gnome_calendar_init (GnomeCalendar *gcal) priv->visible_start = -1; priv->visible_end = -1; - - priv->exp_queries = NULL; } /* Frees a set of categories */ @@ -1062,6 +1059,8 @@ gnome_calendar_destroy (GtkObject *object) if (priv) { GList *l, *client_list; + g_hash_table_destroy (priv->clients); + free_categories (priv->cal_categories); priv->cal_categories = NULL; @@ -1078,7 +1077,8 @@ gnome_calendar_destroy (GtkObject *object) g_list_free (client_list); /* Save the TaskPad layout. */ - filename = g_strdup_printf ("%s/config/TaskPad", evolution_dir); + filename = g_build_filename (calendar_component_peek_config_directory (calendar_component_peek ()), + "TaskPad", NULL); e_calendar_table_save_state (E_CALENDAR_TABLE (priv->todo), filename); g_free (filename); @@ -1120,19 +1120,6 @@ gnome_calendar_destroy (GtkObject *object) priv->view_menus = NULL; } - if (priv->exp_queries) { - GList *l; - - for (l = priv->exp_queries; l != NULL; l = l->next) { - g_signal_handlers_disconnect_matched ((CalQuery *) l->data, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, gcal); - g_object_unref (l->data); - } - - g_list_free (priv->exp_queries); - priv->exp_queries = NULL; - } - g_free (priv); gcal->priv = NULL; } @@ -1764,7 +1751,8 @@ client_cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer da case CAL_CLIENT_OPEN_SUCCESS: /* Set the client's default timezone, if we have one. */ if (priv->zone) { - cal_client_set_default_timezone (client, priv->zone); + /* FIXME Error checking */ + cal_client_set_default_timezone (client, priv->zone, NULL); } /* add the alarms for this client */ @@ -1996,7 +1984,7 @@ gnome_calendar_construct (GnomeCalendar *gcal) /* * TaskPad Folder Client. */ - priv->task_pad_client = cal_client_new (); + priv->task_pad_client = cal_client_new ("", CALOBJ_TYPE_TODO); /* FIXME: use default tasks */ if (!priv->task_pad_client) return NULL; @@ -2063,7 +2051,8 @@ gnome_calendar_get_calendar_model (GnomeCalendar *gcal) priv = gcal->priv; - return e_cal_view_get_model (E_CAL_VIEW (priv->week_view)); + return e_cal_view_get_model ( + gnome_calendar_get_current_view_widget (gcal)); } /** @@ -2078,6 +2067,28 @@ gnome_calendar_get_default_client (GnomeCalendar *gcal) } /** + * gnome_calendar_set_default_client + * @gcal: A calendar view. + * @client: The client to use as default. + * + * Set the default client on the given calendar view. The default calendar will + * be used as the default when creating events in the view. + */ +void +gnome_calendar_set_default_client (GnomeCalendar *gcal, CalClient *client) +{ + int i; + + g_return_if_fail (GNOME_IS_CALENDAR (gcal)); + + for (i = 0; i < GNOME_CAL_LAST_VIEW; i++) { + e_cal_model_set_default_client ( + e_cal_view_get_model (E_CAL_VIEW (gcal->priv->views[i])), + client); + } +} + +/** * gnome_calendar_get_task_pad_cal_client: * @gcal: A calendar view. * @@ -2145,67 +2156,56 @@ add_alarms (const char *uri) CORBA_exception_free (&ev); } +/** + * gnome_calendar_add_event_uri: + * @gcal: A GnomeCalendar. + * @str_uri: URI to add to the calendar views. + * + * Adds the given calendar URI to the calendar views. + * + * Returns: TRUE if successful, FALSE if error. + */ gboolean -gnome_calendar_open (GnomeCalendar *gcal, const char *str_uri) +gnome_calendar_add_event_uri (GnomeCalendar *gcal, const char *str_uri) { GnomeCalendarPrivate *priv; - gboolean success; - EUri *uri; - char *message; - char *real_uri; - char *urinopwd; CalClient *client; - + int i; + g_return_val_if_fail (gcal != NULL, FALSE); g_return_val_if_fail (GNOME_IS_CALENDAR (gcal), FALSE); g_return_val_if_fail (str_uri != NULL, FALSE); priv = gcal->priv; - g_return_val_if_fail ( - cal_client_get_load_state (priv->task_pad_client) == CAL_CLIENT_LOAD_NOT_LOADED, - FALSE); - - uri = e_uri_new (str_uri); - if (!uri || !g_strncasecmp (uri->protocol, "file", 4)) - real_uri = g_concat_dir_and_file (str_uri, "calendar.ics"); - else - real_uri = g_strdup (str_uri); - - urinopwd = get_uri_without_password (str_uri); - message = g_strdup_printf (_("Opening calendar at %s"), urinopwd); - g_free (urinopwd); - e_cal_view_set_status_message (E_CAL_VIEW (priv->week_view), message); - g_free (message); - - client = cal_client_new (); - g_signal_connect (G_OBJECT (client), "cal_opened", G_CALLBACK (client_cal_opened_cb), gcal); + client = g_hash_table_lookup (priv->clients, str_uri); + if (client) + return TRUE; + + client = cal_client_new (str_uri, CALOBJ_TYPE_EVENT); + g_hash_table_insert (priv->clients, g_strdup (str_uri), g_object_ref (client)); + g_signal_connect (G_OBJECT (client), "backend_error", G_CALLBACK (backend_error_cb), gcal); g_signal_connect (G_OBJECT (client), "categories_changed", G_CALLBACK (client_categories_changed_cb), gcal); g_signal_connect (G_OBJECT (client), "backend_died", G_CALLBACK (backend_died_cb), gcal); - if (!cal_client_open_calendar (client, real_uri, FALSE)) { - g_warning (G_STRLOC ": Could not issue the request to open the calendar folder"); + if (!cal_client_open (client, FALSE, NULL)) { + g_hash_table_remove (priv->clients, str_uri); g_object_unref (client); - e_cal_view_set_status_message (E_CAL_VIEW (priv->week_view), NULL); return FALSE; } - /* Open the appropriate Tasks folder to show in the TaskPad */ - e_calendar_table_set_status_message (E_CALENDAR_TABLE (priv->todo), - _("Opening default tasks folder")); - success = cal_client_open_default_tasks (priv->task_pad_client, FALSE); - - g_free (real_uri); - e_uri_free (uri); - - if (!success) { - g_message ("gnome_calendar_open(): Could not issue the request to open the tasks folder"); - e_calendar_table_set_status_message (E_CALENDAR_TABLE (priv->todo), NULL); - return FALSE; + for (i = 0; i < GNOME_CAL_LAST_VIEW; i++) { + ECalModel *model; + + model = e_cal_view_get_model (priv->views[i]); + e_cal_model_add_client (model, client); } + /* update date navigator query */ + update_query (gcal); + return TRUE; } @@ -2308,7 +2308,8 @@ gnome_calendar_update_config_settings (GnomeCalendar *gcal, CalClient *client = l->data; if (cal_client_get_load_state (client) == CAL_CLIENT_LOAD_LOADED) - cal_client_set_default_timezone (client, priv->zone); + /* FIXME Error checking */ + cal_client_set_default_timezone (client, priv->zone, NULL); } g_list_free (client_list); @@ -2316,8 +2317,9 @@ gnome_calendar_update_config_settings (GnomeCalendar *gcal, if (priv->task_pad_client && cal_client_get_load_state (priv->task_pad_client) == CAL_CLIENT_LOAD_LOADED) { + /* FIXME Error Checking */ cal_client_set_default_timezone (priv->task_pad_client, - priv->zone); + priv->zone, NULL); } e_cal_view_set_timezone (E_CAL_VIEW (priv->day_view), priv->zone); @@ -2383,147 +2385,6 @@ gnome_calendar_get_selected_time_range (GnomeCalendar *gcal, *end_time = priv->selection_end_time; } -void -gnome_calendar_edit_object (GnomeCalendar *gcal, CalClient *client, icalcomponent *icalcomp, gboolean meeting) -{ - GnomeCalendarPrivate *priv; - CompEditor *ce; - const char *uid; - CalComponent *comp; - - g_return_if_fail (GNOME_IS_CALENDAR (gcal)); - g_return_if_fail (IS_CAL_CLIENT (client)); - g_return_if_fail (icalcomp != NULL); - - priv = gcal->priv; - - uid = icalcomponent_get_uid (icalcomp); - - ce = e_comp_editor_registry_find (comp_editor_registry, uid); - if (!ce) { - EventEditor *ee; - - ee = event_editor_new (client); - if (!ee) { - g_message ("gnome_calendar_edit_object(): Could not create the event editor"); - return; - } - ce = COMP_EDITOR (ee); - - comp = cal_component_new (); - cal_component_set_icalcomponent (comp, icalcomponent_new_clone (icalcomp)); - - comp_editor_edit_comp (ce, comp); - if (meeting) - event_editor_show_meeting (ee); - - e_comp_editor_registry_add (comp_editor_registry, ce, FALSE); - - g_object_unref (comp); - } - - comp_editor_focus (ce); -} - -/** - * gnome_calendar_new_appointment_for: - * @gcal: An Evolution calendar. - * @dtstart: a Unix time_t that marks the beginning of the appointment. - * @dtend: a Unix time_t that marks the end of the appointment. - * @all_day: if true, the dtstart and dtend are expanded to cover the entire - * day, and the event is set to TRANSPARENT. - * - * Opens an event editor dialog for a new appointment. - * - **/ -void -gnome_calendar_new_appointment_for (GnomeCalendar *cal, - time_t dtstart, time_t dtend, - gboolean all_day, - gboolean meeting) -{ - GnomeCalendarPrivate *priv; - struct icaltimetype itt; - CalComponentDateTime dt; - CalComponent *comp; - icalcomponent *icalcomp; - CalComponentTransparency transparency; - const char *category; - - g_return_if_fail (cal != NULL); - g_return_if_fail (GNOME_IS_CALENDAR (cal)); - - priv = cal->priv; - - dt.value = &itt; - if (all_day) - dt.tzid = NULL; - else - dt.tzid = icaltimezone_get_tzid (priv->zone); - - icalcomp = e_cal_model_create_component_with_defaults (e_cal_view_get_model (E_CAL_VIEW (priv->week_view))); - comp = cal_component_new (); - cal_component_set_icalcomponent (comp, icalcomp); - - /* DTSTART, DTEND */ - - itt = icaltime_from_timet_with_zone (dtstart, FALSE, priv->zone); - if (all_day) { - itt.hour = itt.minute = itt.second = 0; - itt.is_date = TRUE; - } - cal_component_set_dtstart (comp, &dt); - - itt = icaltime_from_timet_with_zone (dtend, FALSE, priv->zone); - if (all_day) { - /* We round it up to the end of the day, unless it is already - set to midnight. */ - if (itt.hour != 0 || itt.minute != 0 || itt.second != 0) { - icaltime_adjust (&itt, 1, 0, 0, 0); - } - itt.hour = itt.minute = itt.second = 0; - itt.is_date = TRUE; - } - cal_component_set_dtend (comp, &dt); - - transparency = all_day ? CAL_COMPONENT_TRANSP_TRANSPARENT - : CAL_COMPONENT_TRANSP_OPAQUE; - cal_component_set_transparency (comp, transparency); - - - /* Category */ - - category = cal_search_bar_get_category (CAL_SEARCH_BAR (priv->search_bar)); - cal_component_set_categories (comp, category); - - /* Edit! */ - - cal_component_commit_sequence (comp); - - gnome_calendar_edit_object (cal, gnome_calendar_get_default_client (cal), icalcomp, meeting); - g_object_unref (comp); -} - -/** - * gnome_calendar_new_appointment: - * @gcal: An Evolution calendar. - * - * Opens an event editor dialog for a new appointment. The appointment's start - * and end times are set to the currently selected time range in the calendar - * views. - **/ -void -gnome_calendar_new_appointment (GnomeCalendar *gcal) -{ - time_t dtstart, dtend; - - g_return_if_fail (gcal != NULL); - g_return_if_fail (GNOME_IS_CALENDAR (gcal)); - - gnome_calendar_get_current_time_range (gcal, &dtstart, &dtend); - gnome_calendar_new_appointment_for (gcal, dtstart, dtend, FALSE, FALSE); -} - /** * gnome_calendar_new_task: * @gcal: An Evolution calendar. @@ -3020,136 +2881,17 @@ gnome_calendar_delete_selected_occurrence (GnomeCalendar *gcal) } } -void -gnome_calendar_unrecur_selection (GnomeCalendar *gcal) -{ - GnomeCalendarPrivate *priv; - FocusLocation location; - GtkWidget *view; - - g_return_if_fail (GNOME_IS_CALENDAR (gcal)); - - priv = gcal->priv; - - location = get_focus_location (gcal); - - if (location == FOCUS_CALENDAR) { - - view = gnome_calendar_get_current_view_widget (gcal); - - if (E_IS_DAY_VIEW (view)) - e_day_view_unrecur_appointment (E_DAY_VIEW (view)); - else - e_week_view_unrecur_appointment (E_WEEK_VIEW (view)); - } -} - -typedef struct { - gboolean remove; - GnomeCalendar *gcal; -} obj_updated_closure; - static gboolean check_instance_cb (CalComponent *comp, time_t instance_start, time_t instance_end, gpointer data) { - obj_updated_closure *closure = data; - - if (instance_start >= closure->gcal->priv->exp_older_than || - instance_end >= closure->gcal->priv->exp_older_than) { - closure->remove = FALSE; - return FALSE; - } - - closure->remove = TRUE; - return TRUE; -} - -static void -purging_obj_updated_cb (CalQuery *query, const char *uid, - gboolean query_in_progress, int n_scanned, int total, - gpointer data) -{ - GnomeCalendarPrivate *priv; - GnomeCalendar *gcal = data; - CalComponent *comp; - icalcomponent *icalcomp; - obj_updated_closure closure; - gchar *msg; - - priv = gcal->priv; - - if (cal_client_get_object (cal_query_get_client (query), uid, &icalcomp) != CAL_CLIENT_GET_SUCCESS) - return; - - comp = cal_component_new (); - if (!cal_component_set_icalcomponent (comp, icalcomp)) { - g_object_unref (comp); - icalcomponent_free (icalcomp); - return; - } - - msg = g_strdup_printf (_("Purging event %s"), uid); - - /* further filter the event, to check the last recurrence end date */ - if (cal_component_has_recurrences (comp)) { - closure.remove = TRUE; - closure.gcal = gcal; - - cal_recur_generate_instances (comp, priv->exp_older_than, -1, - (CalRecurInstanceFn) check_instance_cb, - &closure, - (CalRecurResolveTimezoneFn) cal_client_resolve_tzid_cb, - cal_query_get_client (query), priv->zone); - - if (closure.remove) { - e_cal_view_set_status_message (E_CAL_VIEW (priv->week_view), msg); - delete_error_dialog (cal_client_remove_object (cal_query_get_client (query), uid), - CAL_COMPONENT_EVENT); - } - } else { - e_cal_view_set_status_message (E_CAL_VIEW (priv->week_view), msg); - delete_error_dialog (cal_client_remove_object (cal_query_get_client (query), uid), CAL_COMPONENT_EVENT); - } - - g_object_unref (comp); - g_free (msg); -} - -static void -purging_eval_error_cb (CalQuery *query, const char *error_str, gpointer data) -{ - GnomeCalendarPrivate *priv; - GnomeCalendar *gcal = data; - - priv = gcal->priv; - - e_cal_view_set_status_message (E_CAL_VIEW (priv->week_view), NULL); - - g_signal_handlers_disconnect_matched (query, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, gcal); - - priv->exp_queries = g_list_remove (priv->exp_queries, query); - g_object_unref (query); -} + gboolean *remove = data; -static void -purging_query_done_cb (CalQuery *query, CalQueryDoneStatus status, const char *error_str, gpointer data) -{ - GnomeCalendarPrivate *priv; - GnomeCalendar *gcal = data; - - priv = gcal->priv; - - e_cal_view_set_status_message (E_CAL_VIEW (priv->week_view), NULL); + *remove = FALSE; - g_signal_handlers_disconnect_matched (query, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, gcal); - - priv->exp_queries = g_list_remove (priv->exp_queries, query); - g_object_unref (query); + return FALSE; } void @@ -3163,11 +2905,6 @@ gnome_calendar_purge (GnomeCalendar *gcal, time_t older_than) priv = gcal->priv; - /* if we have a query, we are already purging */ - if (priv->exp_queries) - return; - - priv->exp_older_than = older_than; start = isodate_from_time_t (0); end = isodate_from_time_t (older_than); sexp = g_strdup_printf ("(and (= (get-vtype) \"VEVENT\")" @@ -3177,27 +2914,47 @@ gnome_calendar_purge (GnomeCalendar *gcal, time_t older_than) e_cal_view_set_status_message (E_CAL_VIEW (priv->week_view), _("Purging")); + /* FIXME Confirm expunge */ + client_list = e_cal_model_get_client_list (e_cal_view_get_model (E_CAL_VIEW (priv->week_view))); for (l = client_list; l != NULL; l = l->next) { - CalQuery *exp_query; - - if (cal_client_is_read_only ((CalClient *) l->data)) + CalClient *client = l->data; + GList *objects, *l; + gboolean read_only = TRUE; + + cal_client_is_read_only (client, &read_only, NULL); + if (!read_only) continue; - - exp_query = cal_client_get_query ((CalClient *) l->data, sexp); - if (!exp_query) { - e_cal_view_set_status_message (E_CAL_VIEW (priv->week_view), NULL); - g_message ("gnome_calendar_purge(): Could not create the query"); + + if (!cal_client_get_object_list (client, sexp, &objects, NULL)) { + g_warning (G_STRLOC ": Could not get the objects"); + continue; } - - g_signal_connect (exp_query, "obj_updated", G_CALLBACK (purging_obj_updated_cb), gcal); - g_signal_connect (exp_query, "query_done", G_CALLBACK (purging_query_done_cb), gcal); - g_signal_connect (exp_query, "eval_error", G_CALLBACK (purging_eval_error_cb), gcal); - - priv->exp_queries = g_list_append (priv->exp_queries, exp_query); + + for (l = objects; l; l = l->next) { + CalComponent *comp; + gboolean remove = TRUE; + + comp = cal_component_new (); + cal_component_set_icalcomponent (comp, icalcomponent_new_clone (l->data)); + + cal_recur_generate_instances (comp, older_than, -1, + (CalRecurInstanceFn) check_instance_cb, + &remove, + (CalRecurResolveTimezoneFn) cal_client_resolve_tzid_cb, + client, priv->zone); + + /* FIXME Better error handling */ + if (remove) + cal_client_remove_object (client, icalcomponent_get_uid (l->data), NULL); + + g_object_unref (comp); + } } + e_cal_view_set_status_message (E_CAL_VIEW (priv->week_view), NULL); + g_list_free (client_list); g_free (sexp); g_free (start); diff --git a/calendar/gui/gnome-cal.h b/calendar/gui/gnome-cal.h index c9bbcbaff4..f56ec69211 100644 --- a/calendar/gui/gnome-cal.h +++ b/calendar/gui/gnome-cal.h @@ -55,7 +55,8 @@ typedef enum { GNOME_CAL_WORK_WEEK_VIEW, GNOME_CAL_WEEK_VIEW, GNOME_CAL_MONTH_VIEW, - GNOME_CAL_LIST_VIEW + GNOME_CAL_LIST_VIEW, + GNOME_CAL_LAST_VIEW } GnomeCalendarViewType; typedef enum @@ -106,9 +107,10 @@ ECalendarTable *gnome_calendar_get_task_pad (GnomeCalendar *gcal); ECalModel *gnome_calendar_get_calendar_model (GnomeCalendar *gcal); CalClient *gnome_calendar_get_default_client (GnomeCalendar *gcal); +void gnome_calendar_set_default_client (GnomeCalendar *gcal, CalClient *client); CalClient *gnome_calendar_get_task_pad_cal_client(GnomeCalendar *gcal); -gboolean gnome_calendar_open (GnomeCalendar *gcal, const char *str_uri); +gboolean gnome_calendar_add_event_uri (GnomeCalendar *gcal, const char *str_uri); void gnome_calendar_set_query (GnomeCalendar *gcal, const char *sexp); @@ -145,17 +147,6 @@ void gnome_calendar_get_selected_time_range (GnomeCalendar *gcal, time_t *start_time, time_t *end_time); -void gnome_calendar_edit_object (GnomeCalendar *gcal, - CalClient *client, - icalcomponent *icalcomp, - gboolean meeting); - -void gnome_calendar_new_appointment (GnomeCalendar *gcal); -void gnome_calendar_new_appointment_for (GnomeCalendar *cal, - time_t dtstart, time_t dtend, - gboolean all_day, - gboolean meeting); - void gnome_calendar_new_task (GnomeCalendar *gcal); /* Returns the selected time range for the current view. Note that this may be @@ -193,7 +184,6 @@ void gnome_calendar_paste_clipboard (GnomeCalendar *gcal); void gnome_calendar_delete_selection (GnomeCalendar *gcal); void gnome_calendar_delete_selected_occurrence (GnomeCalendar *gcal); -void gnome_calendar_unrecur_selection (GnomeCalendar *gcal); void gnome_calendar_purge (GnomeCalendar *gcal, time_t older_than); diff --git a/calendar/gui/itip-utils.c b/calendar/gui/itip-utils.c index f5baa8bb05..e2640f01f4 100644 --- a/calendar/gui/itip-utils.c +++ b/calendar/gui/itip-utils.c @@ -70,8 +70,11 @@ static EAccountList *accounts = NULL; EAccountList * itip_addresses_get (void) { - if (accounts == NULL) - accounts = e_account_list_new(gconf_client_get_default()); + if (accounts == NULL) { + GConfClient *gconf_client = gconf_client_get_default (); + accounts = e_account_list_new (gconf_client); + g_object_unref (gconf_client); + } return accounts; } @@ -98,12 +101,14 @@ itip_organizer_is_user (CalComponent *comp, CalClient *client) strip = itip_strip_mailto (organizer.value); if (cal_client_get_static_capability (client, CAL_STATIC_CAPABILITY_ORGANIZER_NOT_EMAIL_ADDRESS)) { - const char *email; + char *email; - email = cal_client_get_cal_address (client); - if (email && !g_strcasecmp (email, strip)) + if (cal_client_get_cal_address (client, &email, NULL) && !g_strcasecmp (email, strip)) { + g_free (email); + return TRUE; - + } + return FALSE; } @@ -185,8 +190,8 @@ foreach_tzid_callback (icalparameter *param, gpointer data) zone = icalcomponent_get_timezone (tz_data->zones, tzid); if (zone == NULL) zone = icaltimezone_get_builtin_timezone_from_tzid (tzid); - if (zone == NULL && tz_data->client != NULL) - cal_client_get_timezone (tz_data->client, tzid, &zone); + if (zone == NULL && tz_data->client != NULL) + cal_client_get_timezone (tz_data->client, tzid, &zone, NULL); if (zone == NULL) return; @@ -528,28 +533,23 @@ static gboolean comp_server_send (CalComponentItipMethod method, CalComponent *comp, CalClient *client, icalcomponent *zones, GList **users) { - CalClientSendResult result; - icalcomponent *top_level, *new_top_level = NULL; - char *error_msg; + icalcomponent *top_level; gboolean retval = TRUE; + GError *error = NULL; top_level = comp_toplevel_with_zones (method, comp, client, zones); - result = cal_client_send_object (client, top_level, &new_top_level, users, &error_msg); - - if (result == CAL_CLIENT_SEND_SUCCESS) { - icalcomponent *ical_comp; - - ical_comp = icalcomponent_get_inner (new_top_level); - icalcomponent_remove_component (new_top_level, ical_comp); - cal_component_set_icalcomponent (comp, ical_comp); - icalcomponent_free (new_top_level); - } else if (result == CAL_CLIENT_SEND_BUSY) { - e_notice (NULL, GTK_MESSAGE_ERROR, error_msg); - - g_free (error_msg); - retval = FALSE; + if (!cal_client_send_objects (client, top_level, &error)) { + /* FIXME Really need a book problem status code */ + if (error->code != E_CALENDAR_STATUS_OK) { + /* FIXME Better error message */ + e_notice (NULL, GTK_MESSAGE_ERROR, "Unable to book"); + + retval = FALSE; + } } + g_clear_error (&error); + icalcomponent_free (top_level); return retval; @@ -755,7 +755,8 @@ comp_compliant (CalComponentItipMethod method, CalComponent *comp, CalClient *cl if (from_zone == NULL) from_zone = icaltimezone_get_builtin_timezone_from_tzid (dt.tzid); if (from_zone == NULL && client != NULL) - cal_client_get_timezone (client, dt.tzid, &from_zone); + /* FIXME Error checking */ + cal_client_get_timezone (client, dt.tzid, &from_zone, NULL); } to_zone = icaltimezone_get_utc_timezone (); diff --git a/calendar/gui/main.c b/calendar/gui/main.c index a15c0ef846..681417f1df 100644 --- a/calendar/gui/main.c +++ b/calendar/gui/main.c @@ -49,9 +49,9 @@ #include "tasks-control.h" -#define FACTORY_ID "OAFIID:GNOME_Evolution_Calendar_Factory" +#define FACTORY_ID "OAFIID:GNOME_Evolution_Calendar_Factory_2" -#define CALENDAR_COMPONENT_ID "OAFIID:GNOME_Evolution_Calendar_ShellComponent" +#define CALENDAR_COMPONENT_ID "OAFIID:GNOME_Evolution_Calendar_Component" #define CALENDAR_CONTROL_ID "OAFIID:GNOME_Evolution_Calendar_Control" #define TASKS_CONTROL_ID "OAFIID:GNOME_Evolution_Tasks_Control" #define ITIP_CONTROL_ID "OAFIID:GNOME_Evolution_Calendar_iTip_Control" @@ -155,23 +155,19 @@ factory (BonoboGenericFactory *factory, initialized = TRUE; } - if (strcmp (component_id, CALENDAR_COMPONENT_ID) == 0) - return calendar_component_get_object (); - if (strcmp (component_id, CALENDAR_CONTROL_ID) == 0) + if (strcmp (component_id, CALENDAR_COMPONENT_ID) == 0) { + BonoboObject *object = BONOBO_OBJECT (calendar_component_peek ()); + bonobo_object_ref (object); + return object; + } else if (strcmp (component_id, CALENDAR_CONTROL_ID) == 0) return BONOBO_OBJECT (control_factory_new_control ()); - if (strcmp (component_id, TASKS_CONTROL_ID) == 0) + else if (strcmp (component_id, TASKS_CONTROL_ID) == 0) return BONOBO_OBJECT (tasks_control_new ()); - if (strcmp (component_id, ITIP_CONTROL_ID) == 0) + else if (strcmp (component_id, ITIP_CONTROL_ID) == 0) return BONOBO_OBJECT (itip_bonobo_control_new ()); - if (strcmp (component_id, CONFIG_CONTROL_ID) == 0) { - extern EvolutionShellClient *global_shell_client; /* FIXME ugly */ - - if (global_shell_client == NULL) - return NULL; - else - return BONOBO_OBJECT (cal_prefs_dialog_new ()); - } - if (strcmp (component_id, COMP_EDITOR_FACTORY_ID) == 0) + else if (strcmp (component_id, CONFIG_CONTROL_ID) == 0) + return BONOBO_OBJECT (cal_prefs_dialog_new ()); + else if (strcmp (component_id, COMP_EDITOR_FACTORY_ID) == 0) return BONOBO_OBJECT (comp_editor_factory_fn ()); g_warning (FACTORY_ID ": Don't know what to do with %s", component_id); diff --git a/calendar/gui/migration.c b/calendar/gui/migration.c new file mode 100644 index 0000000000..be93309f1f --- /dev/null +++ b/calendar/gui/migration.c @@ -0,0 +1,126 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* calendar-component.c + * + * Copyright (C) 2003 Ximian, Inc + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Rodrigo Moya <rodrigo@ximian.com> + */ + +#include <bonobo/bonobo-i18n.h> +#include <libgnomevfs/gnome-vfs-uri.h> +#include <libgnomevfs/gnome-vfs-xfer.h> +#include <gal/util/e-util.h> +#include "migration.h" + +static gboolean +process_calendar_dir (ESourceGroup *source_group, const char *path, + const char *name, const char *base_uri) +{ + char *s; + GnomeVFSURI *from, *to; + GnomeVFSResult vres; + ESource *source; + GDir *dir; + gboolean retval = TRUE; + + s = g_build_filename (path, "calendar.ics", NULL); + if (!g_file_test (s, G_FILE_TEST_EXISTS)) { + g_free (s); + return FALSE; + } + + /* transfer the old file to its new location */ + from = gnome_vfs_uri_new (s); + g_free (s); + if (!from) + return FALSE; + + s = g_build_filename (e_source_group_peek_base_uri (source_group), base_uri, + "calendar.ics", NULL); + if (e_mkdir_hier (s, 0700) != 0) { + gnome_vfs_uri_unref (from); + g_free (s); + return FALSE; + } + to = gnome_vfs_uri_new (s); + g_free (s); + if (!to) { + gnome_vfs_uri_unref (from); + return FALSE; + } + + vres = gnome_vfs_xfer_uri ((const GnomeVFSURI *) from, + (const GnomeVFSURI *) to, + GNOME_VFS_XFER_DEFAULT, + GNOME_VFS_XFER_ERROR_MODE_ABORT, + GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE, + NULL, NULL); + gnome_vfs_uri_unref (from); + gnome_vfs_uri_unref (to); + + if (vres != GNOME_VFS_OK) + return FALSE; + + /* create the new source */ + source = e_source_new (name, base_uri); + e_source_group_add_source (source_group, source, -1); + + /* process subfolders */ + s = g_build_filename (path, "subfolders", NULL); + dir = g_dir_open (s, 0, NULL); + if (dir) { + const char *name, *tmp_s; + + while ((name = g_dir_read_name (dir))) { + tmp_s = g_build_filename (s, name, NULL); + if (g_file_test (tmp_s, G_FILE_TEST_IS_DIR)) { + retval = process_calendar_dir (source_group, tmp_s, name, name); + } + + g_free (tmp_s); + } + + g_dir_close (dir); + } + + g_free (s); + + return retval; +} + +gboolean +migrate_old_calendars (ESourceGroup *source_group) +{ + char *path; + gboolean retval; + + g_return_val_if_fail (E_IS_SOURCE_GROUP (source_group), FALSE); + + path = g_build_filename (g_get_home_dir (), "evolution", NULL); + if (!g_file_test (path, G_FILE_TEST_IS_DIR)) { + g_free (path); + return FALSE; + } + g_free (path); + + /* look for the top-level calendar */ + path = g_build_filename (g_get_home_dir (), "evolution/local/Calendar", NULL); + retval = process_calendar_dir (source_group, path, _("Personal"), "Personal"); + g_free (path); + + return retval; +} diff --git a/calendar/gui/migration.h b/calendar/gui/migration.h new file mode 100644 index 0000000000..2453d47abd --- /dev/null +++ b/calendar/gui/migration.h @@ -0,0 +1,30 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* calendar-component.c + * + * Copyright (C) 2003 Ximian, Inc + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Rodrigo Moya <rodrigo@ximian.com> + */ + +#ifndef MIGRATION_H +#define MIGRATION_H + +#include <e-util/e-source-group.h> + +gboolean migrate_old_calendars (ESourceGroup *source_group); + +#endif diff --git a/calendar/gui/print.c b/calendar/gui/print.c index 6aeb9f6566..0c0fa44886 100644 --- a/calendar/gui/print.c +++ b/calendar/gui/print.c @@ -522,6 +522,16 @@ format_date(time_t time, int flags, char *buffer, int bufflen) return buffer; } +static gboolean +instance_cb (CalComponent *comp, time_t instance_start, time_t instance_end, gpointer data) +{ + gboolean *found = data; + + *found = TRUE; + + return FALSE; +} + /* print out the month small, embolden any days with events. @@ -625,16 +635,16 @@ print_month_small (GnomePrintContext *pc, GnomeCalendar *gcal, time_t month, day = days[y * 7 + x]; if (day != 0) { - GList *uids; + gboolean found = FALSE; sprintf (buf, "%d", day); /* this is a slow messy way to do this ... but easy ... */ - uids = cal_client_get_objects_in_range (client, - CALOBJ_TYPE_EVENT, - now, time_day_end_with_zone (now, zone)); - font = uids ? font_bold : font_normal; - cal_obj_uid_list_free (uids); + cal_client_generate_instances (client, now, CALOBJ_TYPE_EVENT, + time_day_end_with_zone (now, zone), + instance_cb, &found); + + font = found ? font_bold : font_normal; next = time_add_day_with_zone (now, 1, zone); if ((now >= greystart && now < greyend) @@ -1805,7 +1815,7 @@ print_todo_details (GnomePrintContext *pc, GnomeCalendar *gcal, comp = cal_component_new (); cal_component_set_icalcomponent (comp, icalcomponent_new_clone (comp_data->icalcomp)); - cal_component_get_summary (comp_data->icalcomp, &summary); + cal_component_get_summary (comp, &summary); if (!summary.value) { g_object_unref (comp); continue; @@ -2161,11 +2171,8 @@ get_zone_from_tzid (CalClient *client, const char *tzid) the builtin timezone with the TZID first. */ zone = icaltimezone_get_builtin_timezone_from_tzid (tzid); if (!zone) { - CalClientGetStatus status; - - status = cal_client_get_timezone (client, tzid, &zone); - /* FIXME: Handle error better. */ - if (status != CAL_CLIENT_GET_SUCCESS) + if (!cal_client_get_timezone (client, tzid, &zone, NULL)) + /* FIXME: Handle error better. */ g_warning ("Couldn't get timezone from server: %s", tzid ? tzid : ""); } diff --git a/calendar/gui/tag-calendar.c b/calendar/gui/tag-calendar.c index 03e0b3dee4..147a69f246 100644 --- a/calendar/gui/tag-calendar.c +++ b/calendar/gui/tag-calendar.c @@ -162,7 +162,6 @@ resolve_tzid_cb (const char *tzid, gpointer data) { CalClient *client; icaltimezone *zone = NULL; - CalClientGetStatus status; g_return_val_if_fail (data != NULL, NULL); g_return_val_if_fail (IS_CAL_CLIENT (data), NULL); @@ -174,7 +173,7 @@ resolve_tzid_cb (const char *tzid, gpointer data) if (!zone) { /* FIXME: Handle errors. */ - status = cal_client_get_timezone (client, tzid, &zone); + cal_client_get_timezone (client, tzid, &zone, NULL); } return zone; diff --git a/calendar/gui/tasks-control.c b/calendar/gui/tasks-control.c index 5ed9faa0d6..d97ed2d585 100644 --- a/calendar/gui/tasks-control.c +++ b/calendar/gui/tasks-control.c @@ -235,12 +235,12 @@ static void sensitize_commands (ETasks *tasks, BonoboControl *control, int n_selected) { BonoboUIComponent *uic; - gboolean read_only; + gboolean read_only = TRUE; uic = bonobo_control_get_ui_component (control); g_assert (uic != NULL); - read_only = cal_client_is_read_only (e_tasks_get_cal_client (tasks)); + cal_client_is_read_only (e_tasks_get_cal_client (tasks), &read_only, NULL); bonobo_ui_component_set_prop (uic, "/commands/TasksCut", "sensitive", n_selected == 0 || read_only ? "0" : "1", |