aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--calendar/gui/dialogs/alarm-page.c16
-rw-r--r--calendar/gui/dialogs/comp-editor-util.c1
-rw-r--r--calendar/gui/dialogs/comp-editor.c40
-rw-r--r--calendar/gui/dialogs/delete-error.c25
-rw-r--r--calendar/gui/dialogs/delete-error.h2
-rw-r--r--calendar/gui/dialogs/e-delegate-dialog.c26
-rw-r--r--calendar/gui/dialogs/event-editor.c5
-rw-r--r--calendar/gui/dialogs/event-page.c23
-rw-r--r--calendar/gui/dialogs/meeting-page.c12
-rw-r--r--calendar/gui/dialogs/meeting-page.etspec21
-rw-r--r--calendar/gui/dialogs/new-calendar.c150
-rw-r--r--calendar/gui/dialogs/new-calendar.glade193
-rw-r--r--calendar/gui/dialogs/new-calendar.h (renamed from calendar/pcs/job.h)21
-rw-r--r--calendar/gui/dialogs/recurrence-page.c6
-rw-r--r--calendar/gui/dialogs/schedule-page.c23
-rw-r--r--calendar/gui/dialogs/task-editor.c5
-rw-r--r--calendar/gui/dialogs/task-page.c17
-rw-r--r--calendar/idl/evolution-calendar.idl275
-rw-r--r--calendar/importers/icalendar-importer.c102
-rw-r--r--calendar/pcs/Makefile.am19
-rw-r--r--calendar/pcs/cal-backend-file-events.c145
-rw-r--r--calendar/pcs/cal-backend-file-events.h61
-rw-r--r--calendar/pcs/cal-backend-file-todos.c135
-rw-r--r--calendar/pcs/cal-backend-file-todos.h61
-rw-r--r--calendar/pcs/cal-backend-file.c1644
-rw-r--r--calendar/pcs/cal-backend-file.h12
-rw-r--r--calendar/pcs/cal-backend-object-sexp.c1007
-rw-r--r--calendar/pcs/cal-backend-object-sexp.h67
-rw-r--r--calendar/pcs/cal-backend-sync.c611
-rw-r--r--calendar/pcs/cal-backend-sync.h146
-rw-r--r--calendar/pcs/cal-backend-util.c30
-rw-r--r--calendar/pcs/cal-backend-util.h7
-rw-r--r--calendar/pcs/cal-backend.c956
-rw-r--r--calendar/pcs/cal-backend.h218
-rw-r--r--calendar/pcs/cal-common.h6
-rw-r--r--calendar/pcs/cal-factory.c627
-rw-r--r--calendar/pcs/cal-factory.h12
-rw-r--r--calendar/pcs/cal.c1251
-rw-r--r--calendar/pcs/cal.h42
-rw-r--r--calendar/pcs/job.c98
-rw-r--r--calendar/pcs/query-backend.c361
-rw-r--r--calendar/pcs/query-backend.h55
-rw-r--r--calendar/pcs/query.c1765
-rw-r--r--calendar/pcs/query.h47
-rw-r--r--camel/ChangeLog47
-rw-r--r--camel/camel-arg.c4
-rw-r--r--camel/camel-arg.h1
-rw-r--r--camel/camel-object.c9
-rw-r--r--camel/camel-provider.c4
-rw-r--r--camel/camel-provider.h5
-rw-r--r--camel/camel-store.c23
-rw-r--r--camel/providers/local/camel-local-folder.c24
-rw-r--r--camel/providers/local/camel-local-folder.h2
-rw-r--r--camel/providers/local/camel-local-provider.c10
-rw-r--r--composer/ChangeLog34
-rw-r--r--composer/e-msg-composer-hdrs.c71
-rw-r--r--composer/e-msg-composer-hdrs.h16
-rw-r--r--composer/e-msg-composer.c90
-rw-r--r--composer/e-msg-composer.h14
-rw-r--r--composer/evolution-composer.c20
-rw-r--r--data/evolution.desktop.in4
-rw-r--r--e-util/.cvsignore1
-rw-r--r--e-util/ChangeLog143
-rw-r--r--e-util/Makefile.am14
-rw-r--r--e-util/e-account-list.c3
-rw-r--r--e-util/e-account-list.h1
-rw-r--r--e-util/e-account.c29
-rw-r--r--e-util/e-account.h1
-rw-r--r--e-util/e-source-group.c605
-rw-r--r--e-util/e-source-group.h102
-rw-r--r--e-util/e-source-list.c524
-rw-r--r--e-util/e-source-list.h88
-rw-r--r--e-util/e-source.c458
-rw-r--r--e-util/e-source.h91
-rw-r--r--e-util/e-uid.c61
-rw-r--r--e-util/e-uid.h28
-rw-r--r--e-util/test-source-list.c524
-rw-r--r--filter/ChangeLog19
-rw-r--r--filter/filter-folder.c29
-rw-r--r--filter/libfilter-i18n.h44
-rw-r--r--filter/vfolder-rule.c8
-rw-r--r--help/C/.cvsignore2
-rw-r--r--help/es/apx-authors.sgml2
-rw-r--r--help/es/apx-bugs.sgml2
-rw-r--r--help/es/apx-fdl.sgml2
-rw-r--r--help/es/apx-gloss.sgml2
-rw-r--r--help/es/apx-gpl.sgml2
-rw-r--r--help/es/config-prefs.sgml2
-rw-r--r--help/es/config-sync.sgml2
-rw-r--r--help/es/evolution.sgml2
-rw-r--r--help/es/menuref.sgml2
-rw-r--r--help/es/preface.sgml2
-rw-r--r--help/es/usage-calendar.sgml2
-rw-r--r--help/es/usage-contact.sgml2
-rw-r--r--help/es/usage-exchange.sgml2
-rw-r--r--help/es/usage-exec-summary.sgml2
-rw-r--r--help/es/usage-mail-org.sgml2
-rw-r--r--help/es/usage-mail.sgml2
-rw-r--r--help/es/usage-mainwindow.sgml2
-rw-r--r--help/es/usage-print.sgml2
-rw-r--r--help/es/usage-sync.sgml2
-rw-r--r--libical/ChangeLog6
102 files changed, 8402 insertions, 5141 deletions
diff --git a/calendar/gui/dialogs/alarm-page.c b/calendar/gui/dialogs/alarm-page.c
index 785734ad8c..919ed9a2c8 100644
--- a/calendar/gui/dialogs/alarm-page.c
+++ b/calendar/gui/dialogs/alarm-page.c
@@ -677,10 +677,9 @@ add_clicked_cb (GtkButton *button, gpointer data)
action = e_dialog_option_menu_get (priv->action, action_map);
cal_component_alarm_set_action (alarm, action);
if (action == CAL_ALARM_EMAIL && !cal_component_alarm_has_attendees (alarm)) {
- const char *email;
+ char *email;
- email = cal_client_get_alarm_email_address (COMP_EDITOR_PAGE (apage)->client);
- if (email != NULL) {
+ if (!cal_client_get_alarm_email_address (COMP_EDITOR_PAGE (apage)->client, &email, NULL)) {
CalComponentAttendee *a;
GSList attendee_list;
@@ -689,6 +688,7 @@ add_clicked_cb (GtkButton *button, gpointer data)
attendee_list.data = a;
attendee_list.next = NULL;
cal_component_alarm_set_attendee_list (alarm, &attendee_list);
+ g_free (email);
g_free (a);
}
}
@@ -741,7 +741,7 @@ button_options_clicked_cb (GtkWidget *widget, gpointer data)
AlarmPage *apage;
AlarmPagePrivate *priv;
gboolean repeat;
- const char *email;
+ char *email;
apage = ALARM_PAGE (data);
priv = apage->priv;
@@ -751,9 +751,11 @@ button_options_clicked_cb (GtkWidget *widget, gpointer data)
repeat = !cal_client_get_static_capability (COMP_EDITOR_PAGE (apage)->client,
CAL_STATIC_CAPABILITY_NO_ALARM_REPEAT);
- email = cal_client_get_alarm_email_address (COMP_EDITOR_PAGE (apage)->client);
- if (!alarm_options_dialog_run (priv->alarm, email, repeat))
- g_message ("button_options_clicked_cb(): Could not create the alarm options dialog");
+
+ if (cal_client_get_alarm_email_address (COMP_EDITOR_PAGE (apage)->client, &email, NULL)) {
+ if (!alarm_options_dialog_run (priv->alarm, email, repeat))
+ g_message ("button_options_clicked_cb(): Could not create the alarm options dialog");
+ }
}
/* Hooks the widget signals */
diff --git a/calendar/gui/dialogs/comp-editor-util.c b/calendar/gui/dialogs/comp-editor-util.c
index ce3cbc42f6..d06234edda 100644
--- a/calendar/gui/dialogs/comp-editor-util.c
+++ b/calendar/gui/dialogs/comp-editor-util.c
@@ -31,7 +31,6 @@
#include <bonobo-activation/bonobo-activation.h>
#include <bonobo/bonobo-control.h>
#include <bonobo/bonobo-widget.h>
-#include <ebook/e-destination.h>
#include <e-util/e-time-utils.h>
#include <cal-util/timeutil.h>
#include "../calendar-config.h"
diff --git a/calendar/gui/dialogs/comp-editor.c b/calendar/gui/dialogs/comp-editor.c
index f9c9919338..2bbcf92df3 100644
--- a/calendar/gui/dialogs/comp-editor.c
+++ b/calendar/gui/dialogs/comp-editor.c
@@ -41,6 +41,7 @@
#include <e-util/e-dialog-utils.h>
#include <evolution-shell-component-utils.h>
#include "../print.h"
+#include "../comp-util.h"
#include "save-comp.h"
#include "delete-comp.h"
#include "send-comp.h"
@@ -294,7 +295,8 @@ save_comp (CompEditor *editor)
CompEditorPrivate *priv;
CalComponent *clone;
GList *l;
- CalClientResult result;
+ gboolean result;
+ GError *error = NULL;
priv = editor->priv;
@@ -321,32 +323,24 @@ save_comp (CompEditor *editor)
priv->updating = TRUE;
- if (cal_component_is_instance (priv->comp))
- result = cal_client_update_object_with_mod (priv->client, priv->comp, priv->mod);
- else
- result = cal_client_update_object (priv->client, priv->comp);
- if (result != CAL_CLIENT_RESULT_SUCCESS) {
+ if (!cal_comp_is_on_server (priv->comp, priv->client)) {
+ result = cal_client_create_object (priv->client, cal_component_get_icalcomponent (priv->comp), NULL, &error);
+ } else {
+ result = cal_client_modify_object (priv->client, cal_component_get_icalcomponent (priv->comp), priv->mod, &error);
+ }
+
+ if (!result) {
GtkWidget *dlg;
char *msg;
- switch (result) {
- case CAL_CLIENT_RESULT_INVALID_OBJECT :
- msg = g_strdup (_("Could not update invalid object"));
- break;
- case CAL_CLIENT_RESULT_NOT_FOUND :
- msg = g_strdup (_("Object not found, not updated"));
- break;
- case CAL_CLIENT_RESULT_PERMISSION_DENIED :
- msg = g_strdup (_("You don't have permissions to update this object"));
- break;
- default :
- msg = g_strdup (_("Could not update object"));
- break;
- }
+ msg = g_strdup (error ? error->message : _("Could not update object"));
dlg = gnome_error_dialog (msg);
gnome_dialog_run_and_close (GNOME_DIALOG (dlg));
+
g_free (msg);
+ if (error)
+ g_error_free (error);
return FALSE;
} else {
@@ -391,7 +385,7 @@ delete_comp (CompEditor *editor)
cal_component_get_uid (priv->comp, &uid);
priv->updating = TRUE;
- cal_client_remove_object (priv->client, uid);
+ cal_client_remove_object (priv->client, uid, NULL);
priv->updating = FALSE;
close_dialog (editor);
}
@@ -1442,7 +1436,6 @@ obj_updated_cb (CalClient *client, const char *uid, gpointer data)
CompEditor *editor = COMP_EDITOR (data);
CompEditorPrivate *priv;
CalComponent *comp = NULL;
- CalClientGetStatus status;
const char *edit_uid;
priv = editor->priv;
@@ -1453,8 +1446,7 @@ obj_updated_cb (CalClient *client, const char *uid, gpointer data)
if (changed_component_dialog ((GtkWindow *) editor, priv->comp, FALSE, priv->changed)) {
icalcomponent *icalcomp;
- status = cal_client_get_object (priv->client, uid, &icalcomp);
- if (status == CAL_CLIENT_GET_SUCCESS) {
+ if (!cal_client_get_object (priv->client, uid, NULL, &icalcomp, NULL)) {
comp = cal_component_new ();
if (cal_component_set_icalcomponent (comp, icalcomp))
comp_editor_edit_comp (editor, comp);
diff --git a/calendar/gui/dialogs/delete-error.c b/calendar/gui/dialogs/delete-error.c
index 947aab1e97..edbcaf9880 100644
--- a/calendar/gui/dialogs/delete-error.c
+++ b/calendar/gui/dialogs/delete-error.c
@@ -38,13 +38,16 @@
*
**/
void
-delete_error_dialog (CalClientResult result, CalComponentVType vtype)
+delete_error_dialog (GError *error, CalComponentVType vtype)
{
GtkWidget *dialog;
const char *str;
- switch (result) {
- case CAL_CLIENT_RESULT_CORBA_ERROR:
+ if (!error)
+ return;
+
+ switch (error->code) {
+ case E_CALENDAR_STATUS_CORBA_EXCEPTION:
switch (vtype) {
case CAL_COMPONENT_EVENT:
str = _("The event could not be deleted due to a corba error");
@@ -60,7 +63,7 @@ delete_error_dialog (CalClientResult result, CalComponentVType vtype)
break;
}
break;
- case CAL_CLIENT_RESULT_PERMISSION_DENIED:
+ case E_CALENDAR_STATUS_PERMISSION_DENIED:
switch (vtype) {
case CAL_COMPONENT_EVENT:
str = _("The event could not be deleted because permission was denied");
@@ -76,24 +79,24 @@ delete_error_dialog (CalClientResult result, CalComponentVType vtype)
break;
}
break;
- case CAL_CLIENT_RESULT_INVALID_OBJECT:
+ case E_CALENDAR_STATUS_OTHER_ERROR:
switch (vtype) {
case CAL_COMPONENT_EVENT:
- str = _("The event could not be deleted because it was invalid");
+ str = _("The event could not be deleted due to an error");
break;
case CAL_COMPONENT_TODO:
- str = _("The task could not be deleted because it was invalid");
+ str = _("The task could not be deleted due to an error");
break;
case CAL_COMPONENT_JOURNAL:
- str = _("The journal entry could not be deleted because it was invalid");
+ str = _("The journal entry could not be deleted due to an error");
break;
default:
- str = _("The item could not be deleted because it was invalid");
+ str = _("The item could not be deleted due to an error");
break;
}
break;
- case CAL_CLIENT_RESULT_SUCCESS:
- case CAL_CLIENT_RESULT_NOT_FOUND:
+ case E_CALENDAR_STATUS_OK:
+ case E_CALENDAR_STATUS_OBJECT_NOT_FOUND:
default:
/* If not found, we don't care - its gone anyhow */
return;
diff --git a/calendar/gui/dialogs/delete-error.h b/calendar/gui/dialogs/delete-error.h
index dcef2fa3be..4ac8cf4515 100644
--- a/calendar/gui/dialogs/delete-error.h
+++ b/calendar/gui/dialogs/delete-error.h
@@ -25,6 +25,6 @@
#include <cal-client/cal-client.h>
#include <cal-util/cal-component.h>
-void delete_error_dialog (CalClientResult result, CalComponentVType vtype);
+void delete_error_dialog (GError *error, CalComponentVType vtype);
#endif
diff --git a/calendar/gui/dialogs/e-delegate-dialog.c b/calendar/gui/dialogs/e-delegate-dialog.c
index 85c17bbd4b..709ea41178 100644
--- a/calendar/gui/dialogs/e-delegate-dialog.c
+++ b/calendar/gui/dialogs/e-delegate-dialog.c
@@ -33,7 +33,7 @@
#include <glade/glade.h>
#include <gal/util/e-util.h>
#include <widgets/misc/e-map.h>
-#include <ebook/e-destination.h>
+#include <addressbook/util/eab-destination.h>
#include "Evolution-Addressbook-SelectNames.h"
#include "e-delegate-dialog.h"
@@ -126,8 +126,8 @@ EDelegateDialog *
e_delegate_dialog_construct (EDelegateDialog *edd, const char *name, const char *address)
{
EDelegateDialogPrivate *priv;
- EDestination *dest;
- EDestination *destv[2] = {NULL, NULL};
+ EABDestination *dest;
+ EABDestination *destv[2] = {NULL, NULL};
Bonobo_Control corba_control;
CORBA_Environment ev;
char *str;
@@ -178,13 +178,13 @@ e_delegate_dialog_construct (EDelegateDialog *edd, const char *name, const char
gtk_widget_show (priv->entry);
gtk_box_pack_start (GTK_BOX (priv->hbox), priv->entry, TRUE, TRUE, 6);
- dest = e_destination_new ();
+ dest = eab_destination_new ();
destv[0] = dest;
if (name != NULL && *name)
- e_destination_set_name (dest, name);
+ eab_destination_set_name (dest, name);
if (address != NULL && *address)
- e_destination_set_email (dest, address);
- str = e_destination_exportv(destv);
+ eab_destination_set_email (dest, address);
+ str = eab_destination_exportv(destv);
bonobo_widget_set_property (BONOBO_WIDGET (priv->entry), "destinations", TC_CORBA_string, str, NULL);
g_free(str);
g_object_unref((dest));
@@ -256,7 +256,7 @@ char *
e_delegate_dialog_get_delegate (EDelegateDialog *edd)
{
EDelegateDialogPrivate *priv;
- EDestination **destv;
+ EABDestination **destv;
char *string = NULL;
g_return_val_if_fail (edd != NULL, NULL);
@@ -265,11 +265,11 @@ e_delegate_dialog_get_delegate (EDelegateDialog *edd)
priv = edd->priv;
bonobo_widget_get_property (BONOBO_WIDGET (priv->entry), "destinations", TC_CORBA_string, &string, NULL);
- destv = e_destination_importv (string);
+ destv = eab_destination_importv (string);
if (destv && destv[0] != NULL) {
g_free (priv->address);
- priv->address = g_strdup (e_destination_get_email (destv[0]));
+ priv->address = g_strdup (eab_destination_get_email (destv[0]));
g_free (destv);
}
@@ -283,7 +283,7 @@ char *
e_delegate_dialog_get_delegate_name (EDelegateDialog *edd)
{
EDelegateDialogPrivate *priv;
- EDestination **destv;
+ EABDestination **destv;
char *string = NULL;
g_return_val_if_fail (edd != NULL, NULL);
@@ -292,13 +292,13 @@ e_delegate_dialog_get_delegate_name (EDelegateDialog *edd)
priv = edd->priv;
bonobo_widget_get_property (BONOBO_WIDGET (priv->entry), "destinations", TC_CORBA_string, &string, NULL);
- destv = e_destination_importv (string);
+ destv = eab_destination_importv (string);
g_message ("importv: [%s]", string);
if (destv && destv[0] != NULL) {
g_free (priv->name);
- priv->name = g_strdup (e_destination_get_name (destv[0]));
+ priv->name = g_strdup (eab_destination_get_name (destv[0]));
g_free (destv);
}
diff --git a/calendar/gui/dialogs/event-editor.c b/calendar/gui/dialogs/event-editor.c
index 978a2dbb22..861a52c203 100644
--- a/calendar/gui/dialogs/event-editor.c
+++ b/calendar/gui/dialogs/event-editor.c
@@ -122,13 +122,14 @@ static void
set_menu_sens (EventEditor *ee)
{
EventEditorPrivate *priv;
- gboolean sens, existing, user, read_only;
+ gboolean sens, existing, user, read_only = TRUE;
priv = ee->priv;
existing = comp_editor_get_existing_org (COMP_EDITOR (ee));
user = comp_editor_get_user_org (COMP_EDITOR (ee));
- read_only = cal_client_is_read_only (comp_editor_get_cal_client (COMP_EDITOR (ee)));
+
+ cal_client_is_read_only (comp_editor_get_cal_client (COMP_EDITOR (ee)), &read_only, NULL);
sens = priv->meeting_shown;
comp_editor_set_ui_prop (COMP_EDITOR (ee),
diff --git a/calendar/gui/dialogs/event-page.c b/calendar/gui/dialogs/event-page.c
index b55e67dedd..8813081f4d 100644
--- a/calendar/gui/dialogs/event-page.c
+++ b/calendar/gui/dialogs/event-page.c
@@ -270,7 +270,6 @@ update_time (EventPage *epage, CalComponentDateTime *start_date, CalComponentDat
EventPagePrivate *priv;
struct icaltimetype *start_tt, *end_tt, implied_tt;
icaltimezone *start_zone = NULL, *end_zone = NULL;
- CalClientGetStatus status;
gboolean all_day_event;
priv = epage->priv;
@@ -280,24 +279,22 @@ update_time (EventPage *epage, CalComponentDateTime *start_date, CalComponentDat
first. */
start_zone = icaltimezone_get_builtin_timezone_from_tzid (start_date->tzid);
if (!start_zone) {
- status = cal_client_get_timezone (COMP_EDITOR_PAGE (epage)->client,
- start_date->tzid,
- &start_zone);
/* FIXME: Handle error better. */
- if (status != CAL_CLIENT_GET_SUCCESS)
+ if (!cal_client_get_timezone (COMP_EDITOR_PAGE (epage)->client,
+ start_date->tzid, &start_zone, NULL)) {
g_warning ("Couldn't get timezone from server: %s",
- start_date->tzid ? start_date->tzid : "");
+ start_date->tzid ? start_date->tzid : "");
+ }
}
end_zone = icaltimezone_get_builtin_timezone_from_tzid (end_date->tzid);
if (!end_zone) {
- status = cal_client_get_timezone (COMP_EDITOR_PAGE (epage)->client,
- end_date->tzid,
- &end_zone);
- /* FIXME: Handle error better. */
- if (status != CAL_CLIENT_GET_SUCCESS)
- g_warning ("Couldn't get timezone from server: %s",
- end_date->tzid ? end_date->tzid : "");
+ if (!cal_client_get_timezone (COMP_EDITOR_PAGE (epage)->client,
+ end_date->tzid, &end_zone, NULL)) {
+ /* FIXME: Handle error better. */
+ g_warning ("Couldn't get timezone from server: %s",
+ end_date->tzid ? end_date->tzid : "");
+ }
}
/* If both times are DATE values, we set the 'All Day Event' checkbox.
diff --git a/calendar/gui/dialogs/meeting-page.c b/calendar/gui/dialogs/meeting-page.c
index 6c8212e93c..800b0d56c6 100644
--- a/calendar/gui/dialogs/meeting-page.c
+++ b/calendar/gui/dialogs/meeting-page.c
@@ -35,6 +35,7 @@
#include <glade/glade.h>
#include <libgnomeui/gnome-stock-icons.h>
#include <gal/util/e-util.h>
+#include <gal/e-table/e-table.h>
#include <gal/widgets/e-unicode.h>
#include <gal/widgets/e-popup-menu.h>
#include <gal/widgets/e-gui-utils.h>
@@ -693,7 +694,9 @@ meeting_page_construct (MeetingPage *mpage, EMeetingStore *ems,
CalClient *client)
{
MeetingPagePrivate *priv;
- const char *backend_address;
+ ETable *real_table;
+ gchar *filename;
+ char *backend_address;
EIterator *it;
EAccount *def_account;
GList *address_strings = NULL, *l;
@@ -716,7 +719,8 @@ meeting_page_construct (MeetingPage *mpage, EMeetingStore *ems,
}
/* Address information */
- backend_address = cal_client_get_cal_address (client);
+ if (!cal_client_get_cal_address (client, &backend_address, NULL))
+ return NULL;
priv->accounts = itip_addresses_get ();
def_account = itip_addresses_get_default();
@@ -743,7 +747,8 @@ meeting_page_construct (MeetingPage *mpage, EMeetingStore *ems,
}
}
g_object_unref(it);
-
+ g_free (backend_address);
+
if (address_strings)
gtk_combo_set_popdown_strings (GTK_COMBO (priv->organizer), address_strings);
else
@@ -753,6 +758,7 @@ meeting_page_construct (MeetingPage *mpage, EMeetingStore *ems,
g_free (l->data);
g_list_free (address_strings);
+ /* The etable displaying attendees and their status */
g_object_ref((ems));
priv->model = ems;
diff --git a/calendar/gui/dialogs/meeting-page.etspec b/calendar/gui/dialogs/meeting-page.etspec
new file mode 100644
index 0000000000..96bc480fe9
--- /dev/null
+++ b/calendar/gui/dialogs/meeting-page.etspec
@@ -0,0 +1,21 @@
+<ETableSpecification click-to-add="true" click-to-add-end="true" _click-to-add-message="Click here to add an attendee" draw-grid="true">
+ <ETableColumn model_col= "0" _title="Attendee" expansion="2.0" minimum_width="10" resizable="true" cell="string" compare="string"/>
+ <ETableColumn model_col= "1" _title="Member" expansion="2.0" minimum_width="10" resizable="true" cell="string" compare="string"/>
+ <ETableColumn model_col= "2" _title="Type" expansion="1.0" minimum_width="10" resizable="true" cell="typeedit" compare="string"/>
+ <ETableColumn model_col= "3" _title="Role" expansion="1.0" minimum_width="10" resizable="true" cell="roleedit" compare="string"/>
+ <ETableColumn model_col= "4" _title="RSVP" expansion="1.0" minimum_width="10" resizable="true" cell="rsvpedit" compare="string"/>
+ <ETableColumn model_col= "5" _title="Delegated To" expansion="2.0" minimum_width="10" resizable="true" cell="string" compare="string"/>
+ <ETableColumn model_col= "6" _title="Delegated From" expansion="2.0" minimum_width="10" resizable="true" cell="string" compare="string"/>
+ <ETableColumn model_col= "7" _title="Status" expansion="1.0" minimum_width="10" resizable="true" cell="statusedit" compare="string"/>
+ <ETableColumn model_col= "8" _title="Common Name" expansion="2.0" minimum_width="10" resizable="true" cell="string" compare="string"/>
+ <ETableColumn model_col= "9" _title="Language" expansion="2.0" minimum_width="10" resizable="true" cell="string" compare="string"/>
+
+ <ETableState>
+ <column source="0"/>
+ <column source="2"/>
+ <column source="3"/>
+ <column source="4"/>
+ <column source="7"/>
+ <grouping></grouping>
+ </ETableState>
+</ETableSpecification>
diff --git a/calendar/gui/dialogs/new-calendar.c b/calendar/gui/dialogs/new-calendar.c
new file mode 100644
index 0000000000..aa647b55b2
--- /dev/null
+++ b/calendar/gui/dialogs/new-calendar.c
@@ -0,0 +1,150 @@
+/* Evolution calendar - Send calendar component dialog
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Author: JP Rosevear <jpr@ximian.com>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <bonobo/bonobo-i18n.h>
+#include <gtk/gtkdialog.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtkmenu.h>
+#include <gtk/gtkmenuitem.h>
+#include <gtk/gtkmessagedialog.h>
+#include <gtk/gtkoptionmenu.h>
+#include <glade/glade.h>
+#include <e-util/e-dialog-utils.h>
+#include <e-util/e-source-list.h>
+#include "new-calendar.h"
+
+static gboolean
+create_new_source_with_group (GtkWindow *parent,
+ ESourceGroup *group,
+ const char *source_name)
+{
+ ESource *source;
+ char *new_dir;
+
+ if (e_source_group_peek_source_by_name (group, source_name)) {
+ e_notice (parent, GTK_MESSAGE_ERROR,
+ _("Source with name '%s' already exists in the selected group"),
+ source_name);
+ return FALSE;
+ }
+
+ /* create the new source */
+ new_dir = g_build_filename (e_source_group_peek_base_uri (group),
+ source_name, NULL);
+ if (e_mkdir_hier (new_dir, 0700)) {
+ g_free (new_dir);
+ e_notice (parent, GTK_MESSAGE_ERROR,
+ _("Could not create directory for new calendar"));
+ return FALSE;
+ }
+
+ source = e_source_new (source_name, source_name);
+ e_source_group_add_source (group, source, -1);
+
+ g_free (new_dir);
+
+ return TRUE;
+}
+
+/**
+ * new_calendar_dialog
+ *
+ * Displays a dialog that allows the user to create a new calendar.
+ */
+gboolean
+new_calendar_dialog (GtkWindow *parent)
+{
+ GtkWidget *dialog, *cal_group, *cal_name;
+ GladeXML *xml;
+ ESourceList *source_list;
+ GConfClient *gconf_client;
+ GSList *groups, *sl;
+ gboolean result = FALSE, retry = TRUE;
+
+ /* load the Glade file */
+ xml = glade_xml_new (EVOLUTION_GLADEDIR "/new-calendar.glade", "new-calendar-dialog", NULL);
+ if (!xml) {
+ g_warning ("new_calendar_dialog(): cannot load Glade file");
+ return FALSE;
+ }
+
+ dialog = glade_xml_get_widget (xml, "new-calendar-dialog");
+ cal_group = glade_xml_get_widget (xml, "calendar-group");
+ cal_name = glade_xml_get_widget (xml, "calendar-name");
+
+ /* set up widgets */
+ gconf_client = gconf_client_get_default ();
+ source_list = e_source_list_new_for_gconf (gconf_client, "/apps/evolution/calendar/sources");
+
+ groups = e_source_list_peek_groups (source_list);
+ for (sl = groups; sl != NULL; sl = sl->next) {
+ GtkWidget *menu_item, *menu;
+ ESourceGroup *group = sl->data;
+
+ menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (cal_group));
+ if (!GTK_IS_MENU (menu)) {
+ menu = gtk_menu_new ();
+ gtk_option_menu_set_menu (GTK_OPTION_MENU (cal_group), menu);
+ gtk_widget_show (menu);
+ }
+
+ menu_item = gtk_menu_item_new_with_label (e_source_group_peek_name (group));
+ gtk_widget_show (menu_item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+ }
+
+ if (groups)
+ gtk_option_menu_set_history (GTK_OPTION_MENU (cal_group), 0);
+
+ /* run the dialog */
+ do {
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
+ char *name;
+
+ name = gtk_entry_get_text (GTK_ENTRY (cal_name));
+ sl = g_slist_nth (groups, gtk_option_menu_get_history (GTK_OPTION_MENU (cal_group)));
+ if (sl) {
+ if (create_new_source_with_group (GTK_WINDOW (dialog),
+ sl->data,
+ name))
+ retry = FALSE;
+ } else {
+ e_notice (dialog, GTK_MESSAGE_ERROR,
+ _("A group must be selected"));
+ continue;
+ }
+ } else
+ retry = FALSE; /* user pressed Cancel */
+ } while (retry);
+
+ /* free memory */
+ g_object_unref (gconf_client);
+ g_object_unref (source_list);
+ gtk_widget_destroy (dialog);
+
+ /* free memory */
+ g_object_unref (xml);
+
+ return result;
+}
diff --git a/calendar/gui/dialogs/new-calendar.glade b/calendar/gui/dialogs/new-calendar.glade
new file mode 100644
index 0000000000..42717a87a8
--- /dev/null
+++ b/calendar/gui/dialogs/new-calendar.glade
@@ -0,0 +1,193 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+<requires lib="gnome"/>
+
+<widget class="GtkDialog" id="new-calendar-dialog">
+ <property name="border_width">12</property>
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Add New Calendar</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_CENTER</property>
+ <property name="modal">False</property>
+ <property name="resizable">False</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="has_separator">True</property>
+
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+ <child>
+ <widget class="GtkButton" id="cancelbutton1">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-cancel</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="response_id">-6</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="okbutton1">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-ok</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="response_id">-5</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkTable" id="table1">
+ <property name="visible">True</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">3</property>
+ <property name="homogeneous">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Calendar Group</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_padding">6</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Calendar Name</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_padding">6</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkOptionMenu" id="calendar-group">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="history">-1</property>
+ </widget>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_padding">6</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="calendar-name">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_padding">6</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Calendar options&lt;/b&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="y_padding">6</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+</glade-interface>
diff --git a/calendar/pcs/job.h b/calendar/gui/dialogs/new-calendar.h
index 07e3371f89..9890f9e1f8 100644
--- a/calendar/pcs/job.h
+++ b/calendar/gui/dialogs/new-calendar.h
@@ -1,9 +1,8 @@
-/* GNOME personal calendar server - job manager
+/* Evolution calendar - Send calendar component dialog
*
- * Copyright (C) 2000 Ximian, Inc.
- * Copyright (C) 2000 Ximian, Inc.
+ * Copyright (C) 2001 Ximian, Inc.
*
- * Author: Federico Mena-Quintero <federico@ximian.com>
+ * Author: JP Rosevear <jpr@ximian.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -19,17 +18,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
-#ifndef JOB_H
-#define JOB_H
+#ifndef NEW_CALENDAR_H
+#define NEW_CALENDAR_H
-#include <glib.h>
+#include <gtk/gtkwindow.h>
-
-
-typedef void (* JobFunc) (gpointer data);
-
-void job_add (JobFunc func, gpointer data);
-
-
+gboolean new_calendar_dialog (GtkWindow *parent);
#endif
diff --git a/calendar/gui/dialogs/recurrence-page.c b/calendar/gui/dialogs/recurrence-page.c
index 275ba26c44..4599001c27 100644
--- a/calendar/gui/dialogs/recurrence-page.c
+++ b/calendar/gui/dialogs/recurrence-page.c
@@ -852,7 +852,8 @@ preview_recur (RecurrencePage *rpage)
cal_component_get_dtstart (priv->comp, &cdt);
if (cdt.tzid != NULL) {
- if (cal_client_get_timezone (COMP_EDITOR_PAGE (rpage)->client, cdt.tzid, &zone) != CAL_CLIENT_GET_SUCCESS)
+ /* FIXME Will cal_client_get_timezone really not return builtin zones? */
+ if (!cal_client_get_timezone (COMP_EDITOR_PAGE (rpage)->client, cdt.tzid, &zone, NULL))
zone = icaltimezone_get_builtin_timezone_from_tzid (cdt.tzid);
}
cal_component_set_dtstart (comp, &cdt);
@@ -1448,7 +1449,8 @@ fill_ending_date (RecurrencePage *rpage, struct icalrecurrencetype *r)
else if (dt.tzid == NULL)
to_zone = icaltimezone_get_utc_timezone ();
else
- cal_client_get_timezone (client, dt.tzid, &to_zone);
+ /* FIXME Error checking? */
+ cal_client_get_timezone (client, dt.tzid, &to_zone, NULL);
from_zone = icaltimezone_get_utc_timezone ();
icaltimezone_convert_time (&r->until, from_zone, to_zone);
diff --git a/calendar/gui/dialogs/schedule-page.c b/calendar/gui/dialogs/schedule-page.c
index 8cad77360b..06c2d57131 100644
--- a/calendar/gui/dialogs/schedule-page.c
+++ b/calendar/gui/dialogs/schedule-page.c
@@ -208,7 +208,6 @@ update_time (SchedulePage *spage, CalComponentDateTime *start_date, CalComponent
SchedulePagePrivate *priv;
struct icaltimetype start_tt, end_tt;
icaltimezone *start_zone = NULL, *end_zone = NULL;
- CalClientGetStatus status;
gboolean all_day;
priv = spage->priv;
@@ -218,24 +217,22 @@ update_time (SchedulePage *spage, CalComponentDateTime *start_date, CalComponent
first. */
start_zone = icaltimezone_get_builtin_timezone_from_tzid (start_date->tzid);
if (!start_zone) {
- status = cal_client_get_timezone (COMP_EDITOR_PAGE (spage)->client,
- start_date->tzid,
- &start_zone);
- /* FIXME: Handle error better. */
- if (status != CAL_CLIENT_GET_SUCCESS)
+ if (!cal_client_get_timezone (COMP_EDITOR_PAGE (spage)->client,
+ start_date->tzid, &start_zone, NULL)) {
+ /* FIXME: Handle error better. */
g_warning ("Couldn't get timezone from server: %s",
start_date->tzid ? start_date->tzid : "");
+ }
}
end_zone = icaltimezone_get_builtin_timezone_from_tzid (end_date->tzid);
if (!end_zone) {
- status = cal_client_get_timezone (COMP_EDITOR_PAGE (spage)->client,
- end_date->tzid,
- &end_zone);
- /* FIXME: Handle error better. */
- if (status != CAL_CLIENT_GET_SUCCESS)
- g_warning ("Couldn't get timezone from server: %s",
- end_date->tzid ? end_date->tzid : "");
+ if (!cal_client_get_timezone (COMP_EDITOR_PAGE (spage)->client,
+ end_date->tzid, &end_zone, NULL)) {
+ /* FIXME: Handle error better. */
+ g_warning ("Couldn't get timezone from server: %s",
+ end_date->tzid ? end_date->tzid : "");
+ }
}
start_tt = *start_date->value;
diff --git a/calendar/gui/dialogs/task-editor.c b/calendar/gui/dialogs/task-editor.c
index 4ef971fe85..339fdca80d 100644
--- a/calendar/gui/dialogs/task-editor.c
+++ b/calendar/gui/dialogs/task-editor.c
@@ -112,13 +112,14 @@ static void
set_menu_sens (TaskEditor *te)
{
TaskEditorPrivate *priv;
- gboolean sens, existing, user, read_only;
+ gboolean sens, existing, user, read_only = TRUE;
priv = te->priv;
existing = comp_editor_get_existing_org (COMP_EDITOR (te));
user = comp_editor_get_user_org (COMP_EDITOR (te));
- read_only = cal_client_is_read_only (comp_editor_get_cal_client (COMP_EDITOR (te)));
+
+ cal_client_is_read_only (comp_editor_get_cal_client (COMP_EDITOR (te)), &read_only, NULL);
sens = cal_client_get_static_capability (comp_editor_get_cal_client (COMP_EDITOR (te)),
CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT)
diff --git a/calendar/gui/dialogs/task-page.c b/calendar/gui/dialogs/task-page.c
index 760b3e6f9e..fb7558ce5a 100644
--- a/calendar/gui/dialogs/task-page.c
+++ b/calendar/gui/dialogs/task-page.c
@@ -253,7 +253,6 @@ task_page_fill_widgets (CompEditorPage *page, CalComponent *comp)
CalComponentText text;
CalComponentDateTime d;
CalComponentClassification cl;
- CalClientGetStatus get_tz_status;
GSList *l;
const char *categories;
icaltimezone *zone, *default_zone;
@@ -317,12 +316,10 @@ task_page_fill_widgets (CompEditorPage *page, CalComponent *comp)
if (!zone)
zone = icaltimezone_get_builtin_timezone_from_tzid (d.tzid);
if (!zone) {
- get_tz_status = cal_client_get_timezone (page->client, d.tzid,
- &zone);
- /* FIXME: Handle error better. */
- if (get_tz_status != CAL_CLIENT_GET_SUCCESS)
- g_warning ("Couldn't get timezone from server: %s",
- d.tzid ? d.tzid : "");
+ if (!cal_client_get_timezone (page->client, d.tzid, &zone, NULL))
+ /* FIXME: Handle error better. */
+ g_warning ("Couldn't get timezone from server: %s",
+ d.tzid ? d.tzid : "");
}
e_timezone_entry_set_timezone (E_TIMEZONE_ENTRY (priv->due_timezone),
zone);
@@ -359,10 +356,8 @@ task_page_fill_widgets (CompEditorPage *page, CalComponent *comp)
if (!zone)
zone = icaltimezone_get_builtin_timezone_from_tzid (d.tzid);
if (!zone) {
- get_tz_status = cal_client_get_timezone (page->client, d.tzid,
- &zone);
- /* FIXME: Handle error better. */
- if (get_tz_status != CAL_CLIENT_GET_SUCCESS)
+ if (!cal_client_get_timezone (page->client, d.tzid, &zone, NULL))
+ /* FIXME: Handle error better. */
g_warning ("Couldn't get timezone from server: %s",
d.tzid ? d.tzid : "");
}
diff --git a/calendar/idl/evolution-calendar.idl b/calendar/idl/evolution-calendar.idl
index 15b27e806a..1b139fc6f5 100644
--- a/calendar/idl/evolution-calendar.idl
+++ b/calendar/idl/evolution-calendar.idl
@@ -23,9 +23,14 @@ module Calendar {
typedef string CalObj;
typedef sequence<CalObj> CalObjSeq;
+ typedef sequence<string> stringlist;
+
/* A unique identifier for a calendar component */
typedef string CalObjUID;
+ /* A unique identified for an event recurrence */
+ typedef string CalRecurID;
+
/* Simple sequence of strings */
typedef sequence<string> StringSeq;
@@ -66,14 +71,6 @@ module Calendar {
const CalObjChangeType ADDED = 1 << 0;
const CalObjChangeType MODIFIED = 1 << 1;
const CalObjChangeType DELETED = 1 << 2;
-
- /* Types of alarms */
- enum AlarmType {
- MAIL,
- PROGRAM,
- DISPLAY,
- AUDIO
- };
/* Used to store a time_t */
typedef unsigned long Time_t;
@@ -102,30 +99,39 @@ module Calendar {
/* Used to transfer a list of changed components */
typedef sequence<CalObjChange> CalObjChangeSeq;
- /* An alarm trigger instance */
- struct CalAlarmInstance {
- CalAlarmUID auid;
- Time_t trigger;
- Time_t occur_start;
- Time_t occur_end;
- };
-
- /* Used to represent a list of alarm triggers for a single component */
- typedef sequence<CalAlarmInstance> CalAlarmInstanceSeq;
-
- /* Alarms for a component */
- struct CalComponentAlarms {
- CalObj calobj;
- CalAlarmInstanceSeq alarms;
- };
-
- /* Used to represent a list of components plus their triggers */
- typedef sequence<CalComponentAlarms> CalComponentAlarmsSeq;
-
/* Used to represent users and lists of users */
typedef string User;
typedef sequence<User> UserList;
+ enum CallStatus {
+ Success,
+ RepositoryOffline,
+ PermissionDenied,
+ InvalidRange,
+ ObjectNotFound,
+ InvalidObject,
+ CardIdAlreadyExists,
+ AuthenticationFailed,
+ AuthenticationRequired,
+ UnsupportedField,
+ UnsupportedMethod,
+ UnsupportedAuthenticationMethod,
+ TLSNotAvailable,
+ NoSuchCal,
+
+ /* These can be returned for successful searches, but
+ indicate the result set was truncated */
+ SearchSizeLimitExceeded,
+ SearchTimeLimitExceeded,
+
+ InvalidQuery,
+ QueryRefused,
+
+ CouldNotCancel,
+
+ OtherError
+ };
+
interface Query;
interface Listener;
@@ -136,134 +142,68 @@ module Calendar {
interface Cal : Bonobo::Unknown {
exception NotFound {};
exception InvalidRange {};
- exception InvalidObject {};
- exception CouldNotCreate {};
- exception PermissionDenied {};
- exception Busy {string errorMsg;};
/* A calendar is identified by its URI */
readonly attribute string uri;
+ oneway void open (in boolean only_if_exists);
+ oneway void remove ();
+
/* Check write permissions for calendar */
- boolean isReadOnly ();
+ oneway void isReadOnly ();
/* Information on the backend's capabilities */
- string getStaticCapabilities ();
+ oneway void getStaticCapabilities ();
- /* Return the cal address associated with this calendar,
- if any. */
- string getCalAddress ()
- raises (NotFound);
+ /* Return the cal address associated with this calendar, if any. */
+ oneway void getCalAddress ();
- string getAlarmEmailAddress ()
- raises (NotFound);
+ oneway void getAlarmEmailAddress ();
/* Returns the LDAP attribute to get attendees from */
- string getLdapAttribute ()
- raises (NotFound);
+ oneway void getLdapAttribute ();
/* For going online/offline */
void setMode (in CalMode mode);
-
- /* Gets the number of components of the specified types */
- long countObjects (in CalObjType type);
- /* Get a default object of a given type */
- CalObj getDefaultObject (in CalObjType type);
+ /* Get a default object of the backend's type */
+ oneway void getDefaultObject ();
/* Gets a component based on its URI */
- CalObj getObject (in CalObjUID uid)
- raises (NotFound);
-
- /* Sets the default timezone to be used for resolving DATE
- and floating DATE-TIME values. */
- void setDefaultTimezone (in CalTimezoneObjUID tzid)
- raises (NotFound);
+ oneway void getObject (in CalObjUID uid, in CalRecurID rid);
- /* Gets a VTIMEZONE component based on its TZID */
- CalTimezoneObj getTimezoneObject (in CalTimezoneObjUID tzid)
- raises (NotFound);
+ oneway void getObjectList (in string query);
- /* Gets a list of UIDs based on component type */
- CalObjUIDSeq getUIDs (in CalObjType type);
+ /* Methods for manipulating timezones */
+ oneway void getTimezone (in CalTimezoneObjUID tzid);
+ oneway void addTimezone (in CalTimezoneObj tz);
+ /* The timezone used to resolve DATE and floating DATE-TIME values. */
+ oneway void setDefaultTimezone (in CalTimezoneObjUID tzid);
/* Gets a list of components that changed based on object type */
- CalObjChangeSeq getChanges (in CalObjType type, in string change_id);
-
- /* Gets a list of components that occur or recur in the specified time range */
- CalObjUIDSeq getObjectsInRange (in CalObjType type,
- in Time_t start, in Time_t end)
- raises (InvalidRange);
-
- /* Gets a list of the components that have alarms that trigger
- * in the specified range of time, and the trigger/occurrence
- * structures themselves.
- */
- CalComponentAlarmsSeq getAlarmsInRange (in Time_t start, in Time_t end)
- raises (NotFound, InvalidRange);
+ oneway void getChanges (in CalObjType type, in string change_id);
/* Returns free/busy objects for the given interval */
- CalObjSeq getFreeBusy (in UserList users, in Time_t start, in Time_t end)
- raises (NotFound, InvalidRange);
-
- /* Gets the alarms for the specified component that trigger in
- * the specified time range.
- */
- CalComponentAlarms getAlarmsForObject (in CalObjUID uid,
- in Time_t start, in Time_t end)
- raises (NotFound, InvalidRange);
-
+ oneway void getFreeBusy (in UserList users, in Time_t start, in Time_t end);
/* Discards an alarm from a given component */
- void discardAlarm (in CalObjUID uid, in CalAlarmUID auid)
- raises (NotFound);
-
- /* Adds or updates one or more VEVENT/VTODO/VTIMEZONE
- * components. The calobj should be a string representation of
- * a complete VCALENDAR object (we also support single
- * VEVENT/VTODO strings, but that is deprecated).
- *
- * The VTIMEZONE data will be merged into the calendar,
- * possibly by renaming TZIDs (though not for builtin
- * VTIMEZONEs, which have unique TZIDs), so don't rely on the
- * TZIDs being the same in the new object on the server.
- *
- * The client should probably immediately free its copy of the
- * object after this call, and call getObject to get the
- * updated version.
- */
- void updateObjects (in CalObj calobj, in CalObjModType mod)
- raises (NotFound, InvalidObject, PermissionDenied);
+ oneway void discardAlarm (in CalObjUID uid, in CalAlarmUID auid);
- /* Removes a component */
- void removeObject (in CalObjUID uid, in CalObjModType mod)
- raises (NotFound, PermissionDenied);
+ /* Methods for manipulating iCalendar objects */
+ oneway void createObject (in CalObj calobj);
+ oneway void modifyObject (in CalObj calobj, in CalObjModType mod);
+ oneway void removeObject (in CalObjUID uid, in CalRecurID rid, in CalObjModType mod);
- /* Sends a component */
- CalObj sendObject (in CalObj calobj, out UserList users)
- raises (InvalidObject, PermissionDenied, Busy);
+ /* Methods for getting/sending iCalendar VCALENDARS via iTip/iMip */
+ oneway void receiveObjects (in CalObj calobj);
+ oneway void sendObjects (in CalObj calobj);
- /* Initiates a live query of the calendar. Returns a handle
- * to the live query itself; changes to components that are
- * present in the query are notified to the listener.
- */
- Query getQuery (in string sexp, in QueryListener ql)
- raises (CouldNotCreate);
+ /* Query methods */
+ oneway void getQuery (in string sexp, in QueryListener ql);
};
/* Listener for changes in a calendar */
interface Listener : Bonobo::Unknown {
- /* Return status when opening a calendar */
- enum OpenStatus {
- SUCCESS, /* All OK */
- ERROR, /* Generic error */
- NOT_FOUND, /* Requested opening in only_if_exists mode
- * when the URI did not exist.
- */
- METHOD_NOT_SUPPORTED, /* A method handler is not registered */
- PERMISSION_DENIED
- };
-
/* Return status when setting calendar mode */
enum SetModeStatus {
MODE_SET, /* All OK */
@@ -271,62 +211,58 @@ module Calendar {
MODE_NOT_SUPPORTED /* Mode not supported */
};
- /* Called from a CalFactory when a calendar is initially opened.
- * The listener must remember the cal object.
- */
- void notifyCalOpened (in OpenStatus status, in Cal cal);
+ oneway void notifyReadOnly (in CallStatus status, in boolean read_only);
+ oneway void notifyCalAddress (in CallStatus status, in string address);
+ oneway void notifyAlarmEmailAddress (in CallStatus status, in string address);
+ oneway void notifyLDAPAttribute (in CallStatus status, in string ldap_attribute);
+ oneway void notifyStaticCapabilities (in CallStatus status, in string capabilities);
+
+ oneway void notifyCalOpened (in CallStatus status);
+ oneway void notifyCalRemoved (in CallStatus status);
- /* Called from a Calendar when the mode is changed */
- void notifyCalSetMode (in SetModeStatus status, in CalMode mode);
+ oneway void notifyObjectCreated (in CallStatus status, in string uid);
+ oneway void notifyObjectModified (in CallStatus status);
+ oneway void notifyObjectRemoved (in CallStatus status);
+
+ oneway void notifyAlarmDiscarded (in CallStatus status);
+
+ oneway void notifyObjectsReceived (in CallStatus status);
+ oneway void notifyObjectsSent (in CallStatus status);
- /* Called from a Calendar when a component is added or changed */
- void notifyObjUpdated (in CalObjUID uid);
+ oneway void notifyDefaultObjectRequested (in CallStatus status, in CalObj object);
+ oneway void notifyObjectRequested (in CallStatus status, in CalObj object);
+ oneway void notifyObjectListRequested (in CallStatus status, in stringlist objects);
+ oneway void notifyQuery (in CallStatus status, in Query query);
+
+ oneway void notifyTimezoneRequested (in CallStatus status, in CalTimezoneObj tz);
+ oneway void notifyTimezoneAdded (in CallStatus status, in CalTimezoneObjUID tzid);
+ oneway void notifyDefaultTimezoneSet (in CallStatus status);
- /* Called from a Calendar when a component is removed */
- void notifyObjRemoved (in CalObjUID uid);
+ oneway void notifyChanges (in CallStatus status, in CalObjChangeSeq changes);
+ oneway void notifyFreeBusy (in CallStatus status, in CalObjSeq freebusy);
+
+ /* Called from a Calendar when the mode is changed */
+ oneway void notifyCalSetMode (in SetModeStatus status, in CalMode mode);
/* Called from a Calendar when the list of categories changes */
- void notifyCategoriesChanged (in StringSeq categories);
+ oneway void notifyCategoriesChanged (in StringSeq categories);
/* Called from a Calendar when there is an error not notified otherwise */
- void notifyErrorOccurred (in string message);
+ oneway void notifyErrorOccurred (in string message);
};
/* Handle to a live query on a calendar */
interface Query : Bonobo::Unknown {
+ oneway void start ();
};
/* Listener for changes in a query of a calendar */
interface QueryListener : Bonobo::Unknown {
- /* Called when components are added or changed. If
- * query_in_progress is true, then the initial query results are
- * being populated and the other arguments indicate the
- * percentage of completion Otherwise, the percent value is
- * unspecified. */
- void notifyObjUpdated (in CalObjUIDSeq uids,
- in boolean query_in_progress,
- in long n_scanned,
- in long total);
-
- /* Called when a component is removed */
- void notifyObjRemoved (in CalObjUID uid);
-
- /* Reported when a query ends */
- enum QueryDoneStatus {
- SUCCESS,
- PARSE_ERROR
- };
-
- /* Called when the query finishes populating itself some time
- * after it is created. Before this is called,
- * notifyObjUpdated() may have been called several times to
- * indicate which objects are actually in the query, unless the
- * status result is a parse error.
- */
- void notifyQueryDone (in QueryDoneStatus status, in string error_str);
-
- /* Called when an evaluation error occurs while performing a query */
- void notifyEvalError (in string error_str);
+ oneway void notifyObjectsAdded (in stringlist objects);
+ oneway void notifyObjectsModified (in stringlist objects);
+ oneway void notifyObjectsRemoved (in CalObjUIDSeq uids);
+ oneway void notifyQueryProgress (in string message, in short percent);
+ oneway void notifyQueryDone (in CallStatus status);
};
/* A calendar factory, can load and create calendars */
@@ -334,14 +270,9 @@ module Calendar {
exception NilListener {};
exception InvalidURI {};
exception UnsupportedMethod {};
- exception PermissionDenied {};
-
- /* Open a calendar from an URI */
- void open (in string uri, in boolean only_if_exists, in Listener listener)
- raises (NilListener, InvalidURI, UnsupportedMethod, PermissionDenied);
- /* List of open URI's */
- StringSeq uriList (in CalMode mode);
+ Cal getCal (in string uri, in CalObjType type, in Listener listener)
+ raises (NilListener, InvalidURI, UnsupportedMethod);
};
/* Interface to the alarm notification service */
diff --git a/calendar/importers/icalendar-importer.c b/calendar/importers/icalendar-importer.c
index 28068c11df..f2dcbd7097 100644
--- a/calendar/importers/icalendar-importer.c
+++ b/calendar/importers/icalendar-importer.c
@@ -179,6 +179,60 @@ prepare_tasks (icalcomponent *icalcomp, GList *vtodos)
g_list_free (vtodos);
}
+static CalClientResult
+update_single_object (CalClient *client, icalcomponent *icalcomp)
+{
+ char *uid;
+ icalcomponent *tmp_icalcomp;
+
+ uid = (char *) icalcomponent_get_uid (icalcomp);
+
+ if (cal_client_get_object (client, uid, NULL, &tmp_icalcomp, NULL))
+ return cal_client_modify_object (client, icalcomp, CALOBJ_MOD_ALL, NULL)
+ ? CAL_CLIENT_RESULT_SUCCESS : CAL_CLIENT_RESULT_CORBA_ERROR;
+
+ return cal_client_create_object (client, icalcomp, &uid, NULL)
+ ? CAL_CLIENT_RESULT_SUCCESS : CAL_CLIENT_RESULT_CORBA_ERROR;
+}
+
+static CalClientResult
+update_objects (CalClient *client, icalcomponent *icalcomp)
+{
+ icalcomponent *subcomp;
+ icalcomponent_kind kind;
+ CalClientResult result;
+
+ kind = icalcomponent_isa (icalcomp);
+ if (kind == ICAL_VTODO_COMPONENT || kind == ICAL_VEVENT_COMPONENT)
+ return update_single_object (client, icalcomp);
+ else if (kind != ICAL_VCALENDAR_COMPONENT)
+ return CAL_CLIENT_RESULT_INVALID_OBJECT;
+
+ subcomp = icalcomponent_get_first_component (icalcomp, ICAL_ANY_COMPONENT);
+ while (subcomp) {
+ kind = icalcomponent_isa (subcomp);
+ if (kind == ICAL_VTIMEZONE_COMPONENT) {
+ icaltimezone *zone;
+
+ zone = icaltimezone_new ();
+ icaltimezone_set_component (zone, subcomp);
+
+ result = cal_client_add_timezone (client, zone, NULL);
+ icaltimezone_free (zone, 1);
+ if (result != CAL_CLIENT_RESULT_SUCCESS)
+ return result;
+ } else if (kind == ICAL_VTODO_COMPONENT ||
+ kind == ICAL_VEVENT_COMPONENT) {
+ result = update_single_object (client, subcomp);
+ if (result != CAL_CLIENT_RESULT_SUCCESS)
+ return result;
+ }
+
+ subcomp = icalcomponent_get_next_component (icalcomp, ICAL_ANY_COMPONENT);
+ }
+
+ return CAL_CLIENT_RESULT_SUCCESS;
+}
static void
process_item_fn (EvolutionImporter *importer,
@@ -220,20 +274,20 @@ process_item_fn (EvolutionImporter *importer,
contains just tasks, we strip out the VEVENTs, which do not get
imported at all. */
if (ici->folder_contains_events && ici->folder_contains_tasks) {
- if (cal_client_update_objects (ici->client, ici->icalcomp) != CAL_CLIENT_RESULT_SUCCESS)
+ if (update_objects (ici->client, ici->icalcomp) != CAL_CLIENT_RESULT_SUCCESS)
result = GNOME_Evolution_ImporterListener_BAD_DATA;
} else if (ici->folder_contains_events) {
GList *vtodos = prepare_events (ici->icalcomp);
- if (cal_client_update_objects (ici->client, ici->icalcomp) != CAL_CLIENT_RESULT_SUCCESS)
+ if (update_objects (ici->client, ici->icalcomp) != CAL_CLIENT_RESULT_SUCCESS)
result = GNOME_Evolution_ImporterListener_BAD_DATA;
prepare_tasks (ici->icalcomp, vtodos);
- if (cal_client_update_objects (ici->tasks_client,
+ if (update_objects (ici->tasks_client,
ici->icalcomp) != CAL_CLIENT_RESULT_SUCCESS)
result = GNOME_Evolution_ImporterListener_BAD_DATA;
} else {
prepare_tasks (ici->icalcomp, NULL);
- if (cal_client_update_objects (ici->client, ici->icalcomp) != CAL_CLIENT_RESULT_SUCCESS)
+ if (update_objects (ici->client, ici->icalcomp) != CAL_CLIENT_RESULT_SUCCESS)
result = GNOME_Evolution_ImporterListener_BAD_DATA;
}
@@ -312,8 +366,14 @@ load_file_fn (EvolutionImporter *importer,
} else
real_uri = g_strdup (physical_uri);
- if (cal_client_open_calendar (ici->client, real_uri, TRUE)
- && cal_client_open_default_tasks (ici->tasks_client, FALSE)) {
+ /* create CalClient's */
+ if (!ici->client)
+ ici->client = cal_client_new (real_uri, CALOBJ_TYPE_EVENT);
+ if (!ici->tasks_client)
+ ici->tasks_client = cal_client_new ("", CALOBJ_TYPE_TODO); /* FIXME */
+
+ if (cal_client_open (ici->client, TRUE, NULL)
+ && cal_client_open (ici->tasks_client, FALSE, NULL)) {
ici->icalcomp = icalcomp;
ret = TRUE;
}
@@ -334,8 +394,8 @@ ical_importer_new (void)
ICalImporter *ici;
ici = g_new0 (ICalImporter, 1);
- ici->client = cal_client_new ();
- ici->tasks_client = cal_client_new ();
+ ici->client = NULL;
+ ici->tasks_client = NULL;
ici->icalcomp = NULL;
ici->importer = evolution_importer_new (support_format_fn,
load_file_fn,
@@ -458,8 +518,14 @@ vcal_load_file_fn (EvolutionImporter *importer,
} else
real_uri = g_strdup (physical_uri);
- if (cal_client_open_calendar (ici->client, real_uri, TRUE)
- && cal_client_open_default_tasks (ici->tasks_client, FALSE)) {
+ /* create CalClient's */
+ if (!ici->client)
+ ici->client = cal_client_new (real_uri, CALOBJ_TYPE_EVENT);
+ if (!ici->tasks_client)
+ ici->tasks_client = cal_client_new ("", CALOBJ_TYPE_TODO);
+
+ if (cal_client_open (ici->client, TRUE, NULL)
+ && cal_client_open (ici->tasks_client, FALSE, NULL)) {
ici->icalcomp = icalcomp;
ret = TRUE;
}
@@ -478,8 +544,8 @@ vcal_importer_new (void)
ICalImporter *ici;
ici = g_new0 (ICalImporter, 1);
- ici->client = cal_client_new ();
- ici->tasks_client = cal_client_new ();
+ ici->client = NULL;
+ ici->tasks_client = NULL;
ici->icalcomp = NULL;
ici->importer = evolution_importer_new (vcal_support_format_fn,
vcal_load_file_fn,
@@ -542,14 +608,14 @@ gnome_calendar_import_data_fn (EvolutionIntelligentImporter *ii,
/* Try to open the default calendar & tasks folders. */
if (ici->do_calendar) {
- calendar_client = cal_client_new ();
- if (!cal_client_open_default_calendar (calendar_client, FALSE))
+ calendar_client = cal_client_new ("", CALOBJ_TYPE_EVENT); /* FIXME: use default folder */
+ if (!cal_client_open (calendar_client, FALSE, NULL))
goto out;
}
if (ici->do_tasks) {
- tasks_client = cal_client_new ();
- if (!cal_client_open_default_tasks (tasks_client, FALSE))
+ tasks_client = cal_client_new ("", CALOBJ_TYPE_TODO); /* FIXME: use default folder */
+ if (!cal_client_open (tasks_client, FALSE, NULL))
goto out;
}
@@ -598,7 +664,7 @@ gnome_calendar_import_data_fn (EvolutionIntelligentImporter *ii,
/* Import the calendar events. */
/* FIXME: What do intelligent importers do about errors? */
if (ici->do_calendar)
- cal_client_update_objects (calendar_client, icalcomp);
+ update_objects (calendar_client, icalcomp);
/*
@@ -606,7 +672,7 @@ gnome_calendar_import_data_fn (EvolutionIntelligentImporter *ii,
*/
prepare_tasks (icalcomp, vtodos);
if (ici->do_tasks)
- cal_client_update_objects (tasks_client, icalcomp);
+ update_objects (tasks_client, icalcomp);
out:
if (icalcomp)
diff --git a/calendar/pcs/Makefile.am b/calendar/pcs/Makefile.am
index 19b0b66dac..9287ee6a87 100644
--- a/calendar/pcs/Makefile.am
+++ b/calendar/pcs/Makefile.am
@@ -4,10 +4,17 @@ INCLUDES = \
-I$(top_srcdir)/calendar \
-I$(top_builddir)/calendar \
-I$(top_srcdir)/libical/src \
+ -I$(top_builddir)/libical/src \
-I$(top_srcdir)/libwombat \
-I$(top_builddir)/libwombat \
$(EVOLUTION_CALENDAR_CFLAGS)
+AM_CFLAGS = \
+ -DGTK_DISABLE_DEPRECATED=1 \
+ -DGDK_DISABLE_DEPRECATED=1 \
+ -DG_DISABLE_DEPRECATED=1 \
+ -DGNOME_DISABLE_DEPRECATED=1
+
CORBA_GENERATED_H = \
evolution-calendar.h
@@ -37,11 +44,11 @@ pcsinclude_HEADERS = \
$(CORBA_GENERATED_H) \
cal.h \
cal-backend.h \
+ cal-backend-sync.h \
cal-backend-util.h \
+ cal-backend-object-sexp.h\
cal-common.h \
cal-factory.h \
- job.h \
- query-backend.h \
query.h
libpcs_a_SOURCES = \
@@ -49,13 +56,17 @@ libpcs_a_SOURCES = \
$(CORBA_GENERATED_C) \
cal.c \
cal-backend.c \
+ cal-backend-sync.c \
cal-backend-util.c \
+ cal-backend-object-sexp.c\
cal-factory.c \
- job.c \
- query-backend.c \
query.c
libpcsfile_a_SOURCES = \
+ cal-backend-file-events.c\
+ cal-backend-file-events.h\
+ cal-backend-file-todos.c\
+ cal-backend-file-todos.h\
cal-backend-file.c \
cal-backend-file.h
diff --git a/calendar/pcs/cal-backend-file-events.c b/calendar/pcs/cal-backend-file-events.c
new file mode 100644
index 0000000000..a7cf56fac6
--- /dev/null
+++ b/calendar/pcs/cal-backend-file-events.c
@@ -0,0 +1,145 @@
+/* Evolution calendar - iCalendar file backend
+ *
+ * Copyright (C) 2000 Ximian, Inc.
+ * Copyright (C) 2000 Ximian, Inc.
+ *
+ * Authors: Federico Mena-Quintero <federico@ximian.com>
+ * Rodrigo Moya <rodrigo@ximian.com>
+ *
+ * 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.
+ */
+
+#include <config.h>
+#include <string.h>
+#include <unistd.h>
+#include <bonobo/bonobo-exception.h>
+#include <bonobo/bonobo-moniker-util.h>
+#include <libgnome/gnome-i18n.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include "e-util/e-xml-hash-utils.h"
+#include "cal-util/cal-recur.h"
+#include "cal-util/cal-util.h"
+#include "cal-backend-file-events.h"
+#include "cal-backend-util.h"
+
+
+
+/* Private part of the CalBackendFileEvents structure */
+struct _CalBackendFileEventsPrivate {
+};
+
+
+
+static void cal_backend_file_events_class_init (CalBackendFileEventsClass *class);
+static void cal_backend_file_events_init (CalBackendFileEvents *cbfile, CalBackendFileEventsClass *class);
+static void cal_backend_file_events_dispose (GObject *object);
+static void cal_backend_file_events_finalize (GObject *object);
+
+static GObjectClass *parent_class;
+
+
+
+/**
+ * cal_backend_file_events_get_type:
+ * @void:
+ *
+ * Registers the #CalBackendFileEvents class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the #CalBackendFileEvents class.
+ **/
+GType
+cal_backend_file_events_get_type (void)
+{
+ static GType cal_backend_file_events_type = 0;
+
+ if (!cal_backend_file_events_type) {
+ static GTypeInfo info = {
+ sizeof (CalBackendFileEventsClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) cal_backend_file_events_class_init,
+ NULL, NULL,
+ sizeof (CalBackendFileEvents),
+ 0,
+ (GInstanceInitFunc) cal_backend_file_events_init
+ };
+ cal_backend_file_events_type = g_type_register_static (CAL_BACKEND_FILE_TYPE,
+ "CalBackendFileEvents", &info, 0);
+ }
+
+ return cal_backend_file_events_type;
+}
+
+/* Class initialization function for the file backend */
+static void
+cal_backend_file_events_class_init (CalBackendFileEventsClass *klass)
+{
+ GObjectClass *object_class;
+ CalBackendClass *backend_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ backend_class = CAL_BACKEND_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->dispose = cal_backend_file_events_dispose;
+ object_class->finalize = cal_backend_file_events_finalize;
+
+// backend_class->get_uri = cal_backend_file_events_get_uri;
+}
+
+/* Object initialization function for the file backend */
+static void
+cal_backend_file_events_init (CalBackendFileEvents *cbfile, CalBackendFileEventsClass *class)
+{
+ CalBackendFileEventsPrivate *priv;
+
+ priv = g_new0 (CalBackendFileEventsPrivate, 1);
+ cbfile->priv = priv;
+
+ cal_backend_file_set_file_name (CAL_BACKEND_FILE (cbfile), "calendar.ics");
+}
+
+/* Dispose handler for the file backend */
+static void
+cal_backend_file_events_dispose (GObject *object)
+{
+ CalBackendFileEvents *cbfile;
+ CalBackendFileEventsPrivate *priv;
+
+ cbfile = CAL_BACKEND_FILE_EVENTS (object);
+ priv = cbfile->priv;
+
+ if (G_OBJECT_CLASS (parent_class)->dispose)
+ (* G_OBJECT_CLASS (parent_class)->dispose) (object);
+}
+
+/* Finalize handler for the file backend */
+static void
+cal_backend_file_events_finalize (GObject *object)
+{
+ CalBackendFileEvents *cbfile;
+ CalBackendFileEventsPrivate *priv;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (IS_CAL_BACKEND_FILE_EVENTS (object));
+
+ cbfile = CAL_BACKEND_FILE_EVENTS (object);
+ priv = cbfile->priv;
+
+ if (G_OBJECT_CLASS (parent_class)->finalize)
+ (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+}
+
diff --git a/calendar/pcs/cal-backend-file-events.h b/calendar/pcs/cal-backend-file-events.h
new file mode 100644
index 0000000000..3f812b3e09
--- /dev/null
+++ b/calendar/pcs/cal-backend-file-events.h
@@ -0,0 +1,61 @@
+/* Evolution calendar - iCalendar file backend
+ *
+ * Copyright (C) 2000 Ximian, Inc.
+ * Copyright (C) 2000 Ximian, Inc.
+ *
+ * Author: Federico Mena-Quintero <federico@ximian.com>
+ *
+ * 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.
+ */
+
+#ifndef CAL_BACKEND_FILE_EVENTS_H
+#define CAL_BACKEND_FILE_EVENTS_H
+
+#include "cal-backend-file.h"
+
+G_BEGIN_DECLS
+
+
+
+#define CAL_BACKEND_FILE_EVENTS_TYPE (cal_backend_file_events_get_type ())
+#define CAL_BACKEND_FILE_EVENTS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CAL_BACKEND_FILE_EVENTS_TYPE, \
+ CalBackendFileEvents))
+#define CAL_BACKEND_FILE_EVENTS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CAL_BACKEND_FILE_EVENTS_TYPE, \
+ CalBackendFileEventsClass))
+#define IS_CAL_BACKEND_FILE_EVENTS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CAL_BACKEND_FILE_EVENTS_TYPE))
+#define IS_CAL_BACKEND_FILE_EVENTS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CAL_BACKEND_FILE_EVENTS_TYPE))
+
+typedef struct _CalBackendFileEvents CalBackendFileEvents;
+typedef struct _CalBackendFileEventsClass CalBackendFileEventsClass;
+
+typedef struct _CalBackendFileEventsPrivate CalBackendFileEventsPrivate;
+
+struct _CalBackendFileEvents {
+ CalBackendFile backend;
+
+ /* Private data */
+ CalBackendFileEventsPrivate *priv;
+};
+
+struct _CalBackendFileEventsClass {
+ CalBackendFileClass parent_class;
+};
+
+GType cal_backend_file_events_get_type (void);
+
+
+
+G_END_DECLS
+
+#endif
diff --git a/calendar/pcs/cal-backend-file-todos.c b/calendar/pcs/cal-backend-file-todos.c
new file mode 100644
index 0000000000..6f56dd1776
--- /dev/null
+++ b/calendar/pcs/cal-backend-file-todos.c
@@ -0,0 +1,135 @@
+/* Evolution calendar - iCalendar file backend for tasks
+ *
+ * Copyright (C) 2000 Ximian, Inc.
+ * Copyright (C) 2000 Ximian, Inc.
+ *
+ * Authors: Federico Mena-Quintero <federico@ximian.com>
+ * Rodrigo Moya <rodrigo@ximian.com>
+ *
+ * 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.
+ */
+
+#include <libgnome/gnome-i18n.h>
+#include "cal-backend-file-todos.h"
+
+
+
+/* Private part of the CalBackendFileTodos structure */
+struct _CalBackendFileTodosPrivate {
+};
+
+
+
+static void cal_backend_file_todos_class_init (CalBackendFileTodosClass *class);
+static void cal_backend_file_todos_init (CalBackendFileTodos *cbfile, CalBackendFileTodosClass *class);
+static void cal_backend_file_todos_dispose (GObject *object);
+static void cal_backend_file_todos_finalize (GObject *object);
+
+static CalBackendFileClass *parent_class;
+
+
+
+/**
+ * cal_backend_file_todos_get_type:
+ * @void:
+ *
+ * Registers the #CalBackendFileTodos class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the #CalBackendFileTodos class.
+ **/
+GType
+cal_backend_file_todos_get_type (void)
+{
+ static GType cal_backend_file_todos_type = 0;
+
+ if (!cal_backend_file_todos_type) {
+ static GTypeInfo info = {
+ sizeof (CalBackendFileTodosClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) cal_backend_file_todos_class_init,
+ NULL, NULL,
+ sizeof (CalBackendFileTodos),
+ 0,
+ (GInstanceInitFunc) cal_backend_file_todos_init
+ };
+ cal_backend_file_todos_type = g_type_register_static (CAL_BACKEND_FILE_TYPE,
+ "CalBackendFileTodos", &info, 0);
+ }
+
+ return cal_backend_file_todos_type;
+}
+
+/* Class initialization function for the file backend */
+static void
+cal_backend_file_todos_class_init (CalBackendFileTodosClass *klass)
+{
+ GObjectClass *object_class;
+ CalBackendClass *backend_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ backend_class = CAL_BACKEND_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->dispose = cal_backend_file_todos_dispose;
+ object_class->finalize = cal_backend_file_todos_finalize;
+
+// backend_class->get_uri = cal_backend_file_todos_get_uri;
+}
+
+/* Object initialization function for the file backend */
+static void
+cal_backend_file_todos_init (CalBackendFileTodos *cbfile, CalBackendFileTodosClass *class)
+{
+ CalBackendFileTodosPrivate *priv;
+
+ priv = g_new0 (CalBackendFileTodosPrivate, 1);
+ cbfile->priv = priv;
+
+ cal_backend_file_set_file_name (CAL_BACKEND_FILE (cbfile), "tasks.ics");
+}
+
+/* Dispose handler for the file backend */
+static void
+cal_backend_file_todos_dispose (GObject *object)
+{
+ CalBackendFileTodos *cbfile;
+ CalBackendFileTodosPrivate *priv;
+
+ cbfile = CAL_BACKEND_FILE_TODOS (object);
+ priv = cbfile->priv;
+
+ if (G_OBJECT_CLASS (parent_class)->dispose)
+ (* G_OBJECT_CLASS (parent_class)->dispose) (object);
+}
+
+/* Finalize handler for the file backend */
+static void
+cal_backend_file_todos_finalize (GObject *object)
+{
+ CalBackendFileTodos *cbfile;
+ CalBackendFileTodosPrivate *priv;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (IS_CAL_BACKEND_FILE_TODOS (object));
+
+ cbfile = CAL_BACKEND_FILE_TODOS (object);
+ priv = cbfile->priv;
+
+ if (G_OBJECT_CLASS (parent_class)->finalize)
+ (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+}
+
diff --git a/calendar/pcs/cal-backend-file-todos.h b/calendar/pcs/cal-backend-file-todos.h
new file mode 100644
index 0000000000..7f17122673
--- /dev/null
+++ b/calendar/pcs/cal-backend-file-todos.h
@@ -0,0 +1,61 @@
+/* Evolution calendar - iCalendar file backend
+ *
+ * Copyright (C) 2000 Ximian, Inc.
+ * Copyright (C) 2000 Ximian, Inc.
+ *
+ * Author: Federico Mena-Quintero <federico@ximian.com>
+ *
+ * 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.
+ */
+
+#ifndef CAL_BACKEND_FILE_TODOS_H
+#define CAL_BACKEND_FILE_TODOS_H
+
+#include "cal-backend-file.h"
+
+G_BEGIN_DECLS
+
+
+
+#define CAL_BACKEND_FILE_TODOS_TYPE (cal_backend_file_todos_get_type ())
+#define CAL_BACKEND_FILE_TODOS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CAL_BACKEND_FILE_TODOS_TYPE, \
+ CalBackendFileTodos))
+#define CAL_BACKEND_FILE_TODOS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CAL_BACKEND_FILE_TODOS_TYPE, \
+ CalBackendFileTodosClass))
+#define IS_CAL_BACKEND_FILE_TODOS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CAL_BACKEND_FILE_TODOS_TYPE))
+#define IS_CAL_BACKEND_FILE_TODOS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CAL_BACKEND_FILE_TODOS_TYPE))
+
+typedef struct _CalBackendFileTodos CalBackendFileTodos;
+typedef struct _CalBackendFileTodosClass CalBackendFileTodosClass;
+
+typedef struct _CalBackendFileTodosPrivate CalBackendFileTodosPrivate;
+
+struct _CalBackendFileTodos {
+ CalBackendFile backend;
+
+ /* Private data */
+ CalBackendFileTodosPrivate *priv;
+};
+
+struct _CalBackendFileTodosClass {
+ CalBackendFileClass parent_class;
+};
+
+GType cal_backend_file_todos_get_type (void);
+
+
+
+G_END_DECLS
+
+#endif
diff --git a/calendar/pcs/cal-backend-file.c b/calendar/pcs/cal-backend-file.c
index b26f2fd74c..e5e3abb7c9 100644
--- a/calendar/pcs/cal-backend-file.c
+++ b/calendar/pcs/cal-backend-file.c
@@ -1,7 +1,6 @@
/* Evolution calendar - iCalendar file backend
*
- * Copyright (C) 2000 Ximian, Inc.
- * Copyright (C) 2000 Ximian, Inc.
+ * Copyright (C) 2000-2003 Ximian, Inc.
*
* Authors: Federico Mena-Quintero <federico@ximian.com>
* Rodrigo Moya <rodrigo@ximian.com>
@@ -27,38 +26,41 @@
#include <bonobo/bonobo-moniker-util.h>
#include <libgnome/gnome-i18n.h>
#include <libgnomevfs/gnome-vfs.h>
-#include "e-util/e-dbhash.h"
+#include "e-util/e-xml-hash-utils.h"
#include "cal-util/cal-recur.h"
#include "cal-util/cal-util.h"
-#include "cal-backend-file.h"
+#include "cal-backend-file-events.h"
#include "cal-backend-util.h"
+#include "cal-backend-object-sexp.h"
+/* Placeholder for each component and its recurrences */
+typedef struct {
+ CalComponent *full_object;
+ GHashTable *recurrences;
+} CalBackendFileObject;
+
/* Private part of the CalBackendFile structure */
struct _CalBackendFilePrivate {
/* URI where the calendar data is stored */
char *uri;
+ /* Filename in the dir */
+ char *file_name;
+
/* Toplevel VCALENDAR component */
icalcomponent *icalcomp;
- /* All the CalComponent objects in the calendar, hashed by UID. The
+ /* All the objects in the calendar, hashed by UID. The
* hash key *is* the uid returned by cal_component_get_uid(); it is not
* copied, so don't free it when you remove an object from the hash
- * table.
+ * table. Each item in the hash table is a CalBackendFileObject.
*/
GHashTable *comp_uid_hash;
- /* All event, to-do, and journal components in the calendar; they are
- * here just for easy access (i.e. so that you don't have to iterate
- * over the comp_uid_hash). If you need *all* the components in the
- * calendar, iterate over the hash instead.
- */
- GList *events;
- GList *todos;
- GList *journals;
-
+ GList *comp;
+
/* Config database handle for free/busy organizer information */
EConfigListener *config_listener;
@@ -68,181 +70,29 @@ struct _CalBackendFilePrivate {
/* The calendar's default timezone, used for resolving DATE and
floating DATE-TIME values. */
icaltimezone *default_zone;
+
+ /* The list of live queries */
+ GList *queries;
};
-static void cal_backend_file_class_init (CalBackendFileClass *class);
-static void cal_backend_file_init (CalBackendFile *cbfile, CalBackendFileClass *class);
static void cal_backend_file_dispose (GObject *object);
static void cal_backend_file_finalize (GObject *object);
-static const char *cal_backend_file_get_uri (CalBackend *backend);
-static gboolean cal_backend_file_is_read_only (CalBackend *backend);
-static const char *cal_backend_file_get_cal_address (CalBackend *backend);
-static const char *cal_backend_file_get_alarm_email_address (CalBackend *backend);
-static const char *cal_backend_file_get_ldap_attribute (CalBackend *backend);
-static const char *cal_backend_file_get_static_capabilities (CalBackend *backend);
-static CalBackendOpenStatus cal_backend_file_open (CalBackend *backend,
- const char *uristr,
- gboolean only_if_exists);
-static gboolean cal_backend_file_is_loaded (CalBackend *backend);
-static Query *cal_backend_file_get_query (CalBackend *backend,
- GNOME_Evolution_Calendar_QueryListener ql,
- const char *sexp);
-
-static CalMode cal_backend_file_get_mode (CalBackend *backend);
-static void cal_backend_file_set_mode (CalBackend *backend, CalMode mode);
-
-static int cal_backend_file_get_n_objects (CalBackend *backend, CalObjType type);
-static char *cal_backend_file_get_default_object (CalBackend *backend, CalObjType type);
-static CalComponent *cal_backend_file_get_object_component (CalBackend *backend, const char *uid);
-static char *cal_backend_file_get_timezone_object (CalBackend *backend, const char *tzid);
-static GList *cal_backend_file_get_uids (CalBackend *backend, CalObjType type);
-static GList *cal_backend_file_get_objects_in_range (CalBackend *backend, CalObjType type,
- time_t start, time_t end);
-static GList *cal_backend_file_get_free_busy (CalBackend *backend, GList *users, time_t start, time_t end);
-static GNOME_Evolution_Calendar_CalObjChangeSeq *cal_backend_file_get_changes (
- CalBackend *backend, CalObjType type, const char *change_id);
-
-static GNOME_Evolution_Calendar_CalComponentAlarmsSeq *cal_backend_file_get_alarms_in_range (
- CalBackend *backend, time_t start, time_t end);
-
-static GNOME_Evolution_Calendar_CalComponentAlarms *cal_backend_file_get_alarms_for_object (
- CalBackend *backend, const char *uid,
- time_t start, time_t end, gboolean *object_found);
-
-static CalBackendResult cal_backend_file_discard_alarm (CalBackend *backend,
- const char *uid,
- const char *auid);
-
-static CalBackendResult cal_backend_file_update_objects (CalBackend *backend,
- const char *calobj,
- CalObjModType mod);
-static CalBackendResult cal_backend_file_remove_object (CalBackend *backend, const char *uid, CalObjModType mod);
-
-static CalBackendSendResult cal_backend_file_send_object (CalBackend *backend,
- const char *calobj, gchar **new_calobj,
- GNOME_Evolution_Calendar_UserList **user_list,
- char error_msg[256]);
-
-static icaltimezone* cal_backend_file_get_timezone (CalBackend *backend, const char *tzid);
-static icaltimezone* cal_backend_file_get_default_timezone (CalBackend *backend);
-static gboolean cal_backend_file_set_default_timezone (CalBackend *backend,
- const char *tzid);
-
-static CalBackendClass *parent_class;
+static CalBackendSyncClass *parent_class;
-/**
- * cal_backend_file_get_type:
- * @void:
- *
- * Registers the #CalBackendFile class if necessary, and returns the type ID
- * associated to it.
- *
- * Return value: The type ID of the #CalBackendFile class.
- **/
-GType
-cal_backend_file_get_type (void)
-{
- static GType cal_backend_file_type = 0;
-
- if (!cal_backend_file_type) {
- static GTypeInfo info = {
- sizeof (CalBackendFileClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) cal_backend_file_class_init,
- NULL, NULL,
- sizeof (CalBackendFile),
- 0,
- (GInstanceInitFunc) cal_backend_file_init
- };
- cal_backend_file_type = g_type_register_static (CAL_BACKEND_TYPE,
- "CalBackendFile", &info, 0);
- }
-
- return cal_backend_file_type;
-}
-
-/* Class initialization function for the file backend */
-static void
-cal_backend_file_class_init (CalBackendFileClass *class)
-{
- GObjectClass *object_class;
- CalBackendClass *backend_class;
-
- object_class = (GObjectClass *) class;
- backend_class = (CalBackendClass *) class;
-
- parent_class = (CalBackendClass *) g_type_class_peek_parent (class);
-
- object_class->dispose = cal_backend_file_dispose;
- object_class->finalize = cal_backend_file_finalize;
-
- backend_class->get_uri = cal_backend_file_get_uri;
- backend_class->is_read_only = cal_backend_file_is_read_only;
- backend_class->get_cal_address = cal_backend_file_get_cal_address;
- backend_class->get_alarm_email_address = cal_backend_file_get_alarm_email_address;
- backend_class->get_ldap_attribute = cal_backend_file_get_ldap_attribute;
- backend_class->get_static_capabilities = cal_backend_file_get_static_capabilities;
- backend_class->open = cal_backend_file_open;
- backend_class->is_loaded = cal_backend_file_is_loaded;
- backend_class->get_query = cal_backend_file_get_query;
- backend_class->get_mode = cal_backend_file_get_mode;
- backend_class->set_mode = cal_backend_file_set_mode;
- backend_class->get_n_objects = cal_backend_file_get_n_objects;
- backend_class->get_default_object = cal_backend_file_get_default_object;
- backend_class->get_object_component = cal_backend_file_get_object_component;
- backend_class->get_timezone_object = cal_backend_file_get_timezone_object;
- backend_class->get_uids = cal_backend_file_get_uids;
- backend_class->get_objects_in_range = cal_backend_file_get_objects_in_range;
- backend_class->get_free_busy = cal_backend_file_get_free_busy;
- backend_class->get_changes = cal_backend_file_get_changes;
- backend_class->get_alarms_in_range = cal_backend_file_get_alarms_in_range;
- backend_class->get_alarms_for_object = cal_backend_file_get_alarms_for_object;
- backend_class->discard_alarm = cal_backend_file_discard_alarm;
- backend_class->update_objects = cal_backend_file_update_objects;
- backend_class->remove_object = cal_backend_file_remove_object;
- backend_class->send_object = cal_backend_file_send_object;
-
- backend_class->get_timezone = cal_backend_file_get_timezone;
- backend_class->get_default_timezone = cal_backend_file_get_default_timezone;
- backend_class->set_default_timezone = cal_backend_file_set_default_timezone;
-}
-
-/* Object initialization function for the file backend */
-static void
-cal_backend_file_init (CalBackendFile *cbfile, CalBackendFileClass *class)
-{
- CalBackendFilePrivate *priv;
-
- priv = g_new0 (CalBackendFilePrivate, 1);
- cbfile->priv = priv;
-
- priv->uri = NULL;
- priv->icalcomp = NULL;
- priv->comp_uid_hash = NULL;
- priv->events = NULL;
- priv->todos = NULL;
- priv->journals = NULL;
-
- /* The timezone defaults to UTC. */
- priv->default_zone = icaltimezone_get_utc_timezone ();
-
- priv->config_listener = e_config_listener_new ();
-}
-
/* g_hash_table_foreach() callback to destroy a CalComponent */
static void
-free_cal_component (gpointer key, gpointer value, gpointer data)
+free_object (gpointer key, gpointer value, gpointer data)
{
- CalComponent *comp;
+ CalBackendFileObject *obj_data = value;
- comp = CAL_COMPONENT (value);
- g_object_unref (comp);
+ g_object_unref (obj_data->full_object);
+ g_hash_table_foreach (obj_data->recurrences, (GHFunc) g_object_unref, NULL);
+ g_hash_table_destroy (obj_data->recurrences);
}
/* Saves the calendar data */
@@ -340,18 +190,13 @@ cal_backend_file_dispose (GObject *object)
}
if (priv->comp_uid_hash) {
- g_hash_table_foreach (priv->comp_uid_hash,
- free_cal_component, NULL);
+ g_hash_table_foreach (priv->comp_uid_hash, (GHFunc) free_object, NULL);
g_hash_table_destroy (priv->comp_uid_hash);
priv->comp_uid_hash = NULL;
}
- g_list_free (priv->events);
- g_list_free (priv->todos);
- g_list_free (priv->journals);
- priv->events = NULL;
- priv->todos = NULL;
- priv->journals = NULL;
+ g_list_free (priv->comp);
+ priv->comp = NULL;
if (priv->icalcomp) {
icalcomponent_free (priv->icalcomp);
@@ -401,72 +246,80 @@ static CalComponent *
lookup_component (CalBackendFile *cbfile, const char *uid)
{
CalBackendFilePrivate *priv;
- CalComponent *comp;
+ CalBackendFileObject *obj_data;
priv = cbfile->priv;
- comp = g_hash_table_lookup (priv->comp_uid_hash, uid);
-
- return comp;
+ /* FIXME: search recurrences also */
+ obj_data = g_hash_table_lookup (priv->comp_uid_hash, uid);
+ return obj_data ? obj_data->full_object : NULL;
}
/* Calendar backend methods */
-/* Get_uri handler for the file backend */
-static const char *
-cal_backend_file_get_uri (CalBackend *backend)
-{
- CalBackendFile *cbfile;
- CalBackendFilePrivate *priv;
-
- cbfile = CAL_BACKEND_FILE (backend);
- priv = cbfile->priv;
-
- g_return_val_if_fail (priv->icalcomp != NULL, NULL);
- g_assert (priv->uri != NULL);
-
- return (const char *) priv->uri;
-}
-
/* Is_read_only handler for the file backend */
-static gboolean
-cal_backend_file_is_read_only (CalBackend *backend)
+static CalBackendSyncStatus
+cal_backend_file_is_read_only (CalBackendSync *backend, Cal *cal, gboolean *read_only)
{
/* we just return FALSE, since all calendars are read-write */
- return FALSE;
+ *read_only = FALSE;
+
+ return GNOME_Evolution_Calendar_Success;
}
/* Get_email_address handler for the file backend */
-static const char *
-cal_backend_file_get_cal_address (CalBackend *backend)
+static CalBackendSyncStatus
+cal_backend_file_get_cal_address (CalBackendSync *backend, Cal *cal, char **address)
{
/* A file backend has no particular email address associated
* with it (although that would be a useful feature some day).
*/
- return NULL;
+ *address = NULL;
+
+ return GNOME_Evolution_Calendar_Success;
}
-static const char *
-cal_backend_file_get_ldap_attribute (CalBackend *backend)
+static CalBackendSyncStatus
+cal_backend_file_get_ldap_attribute (CalBackendSync *backend, Cal *cal, char **attribute)
{
- return NULL;
+ *attribute = NULL;
+
+ return GNOME_Evolution_Calendar_Success;
}
-static const char *
-cal_backend_file_get_alarm_email_address (CalBackend *backend)
+static CalBackendSyncStatus
+cal_backend_file_get_alarm_email_address (CalBackendSync *backend, Cal *cal, char **address)
{
/* A file backend has no particular email address associated
* with it (although that would be a useful feature some day).
*/
- return NULL;
+ *address = NULL;
+
+ return GNOME_Evolution_Calendar_Success;
}
-static const char *
-cal_backend_file_get_static_capabilities (CalBackend *backend)
+static CalBackendSyncStatus
+cal_backend_file_get_static_capabilities (CalBackendSync *backend, Cal *cal, char **capabilities)
{
- return CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS;
+ *capabilities = CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS;
+
+ return GNOME_Evolution_Calendar_Success;
+}
+
+/* function to resolve timezones */
+static icaltimezone *
+resolve_tzid (const char *tzid, gpointer user_data)
+{
+ icalcomponent *vcalendar_comp = user_data;
+
+ if (!tzid || !tzid[0])
+ return NULL;
+ else if (!strcmp (tzid, "UTC"))
+ return icaltimezone_get_utc_timezone ();
+
+ return icalcomponent_get_timezone (vcalendar_comp, tzid);
}
/* Idle handler; we save the calendar since it is dirty */
@@ -506,7 +359,7 @@ static void
check_dup_uid (CalBackendFile *cbfile, CalComponent *comp)
{
CalBackendFilePrivate *priv;
- CalComponent *old_comp;
+ CalBackendFileObject *obj_data;
const char *uid;
char *new_uid;
@@ -514,8 +367,8 @@ check_dup_uid (CalBackendFile *cbfile, CalComponent *comp)
cal_component_get_uid (comp, &uid);
- old_comp = g_hash_table_lookup (priv->comp_uid_hash, uid);
- if (!old_comp)
+ obj_data = g_hash_table_lookup (priv->comp_uid_hash, uid);
+ if (!obj_data)
return; /* Everything is fine */
g_message ("check_dup_uid(): Got object with duplicated UID `%s', changing it...", uid);
@@ -531,6 +384,22 @@ check_dup_uid (CalBackendFile *cbfile, CalComponent *comp)
mark_dirty (cbfile);
}
+static char *
+get_rid_string (CalComponent *comp)
+{
+ CalComponentRange range;
+ struct icaltimetype tt;
+
+ cal_component_get_recurid (comp, &range);
+ if (!range.datetime.value)
+ return "0";
+ tt = *range.datetime.value;
+ cal_component_free_range (&range);
+
+ return icaltime_is_valid_time (tt) && !icaltime_is_null_time (tt) ?
+ icaltime_as_ical_string (tt) : "0";
+}
+
/* Tries to add an icalcomponent to the file backend. We only store the objects
* of the types we support; all others just remain in the toplevel component so
* that we don't lose them.
@@ -539,38 +408,27 @@ static void
add_component (CalBackendFile *cbfile, CalComponent *comp, gboolean add_to_toplevel)
{
CalBackendFilePrivate *priv;
- GList **list;
+ CalBackendFileObject *obj_data;
const char *uid;
GSList *categories;
priv = cbfile->priv;
- switch (cal_component_get_vtype (comp)) {
- case CAL_COMPONENT_EVENT:
- list = &priv->events;
- break;
-
- case CAL_COMPONENT_TODO:
- list = &priv->todos;
- break;
-
- case CAL_COMPONENT_JOURNAL:
- list = &priv->journals;
- break;
-
- default:
- g_assert_not_reached ();
- return;
- }
+ /* FIXME: check if it's an instance */
/* Ensure that the UID is unique; some broken implementations spit
* components with duplicated UIDs.
*/
check_dup_uid (cbfile, comp);
cal_component_get_uid (comp, &uid);
- g_hash_table_insert (priv->comp_uid_hash, (char *)uid, comp);
- *list = g_list_prepend (*list, comp);
+ obj_data = g_new0 (CalBackendFileObject, 1);
+ obj_data->full_object = comp;
+ obj_data->recurrences = g_hash_table_new (g_str_hash, g_str_equal);
+
+ g_hash_table_insert (priv->comp_uid_hash, (gpointer) uid, obj_data);
+
+ priv->comp = g_list_prepend (priv->comp, comp);
/* Put the object in the toplevel component if required */
@@ -599,8 +457,9 @@ remove_component (CalBackendFile *cbfile, CalComponent *comp)
CalBackendFilePrivate *priv;
icalcomponent *icalcomp;
const char *uid;
- GList **list, *l;
+ GList *l;
GSList *categories;
+ CalBackendFileObject *obj_data;
priv = cbfile->priv;
@@ -614,39 +473,22 @@ remove_component (CalBackendFile *cbfile, CalComponent *comp)
/* Remove it from our mapping */
cal_component_get_uid (comp, &uid);
+ obj_data = g_hash_table_lookup (priv->comp_uid_hash, uid);
+ if (!obj_data)
+ return;
+
g_hash_table_remove (priv->comp_uid_hash, uid);
-
- switch (cal_component_get_vtype (comp)) {
- case CAL_COMPONENT_EVENT:
- list = &priv->events;
- break;
-
- case CAL_COMPONENT_TODO:
- list = &priv->todos;
- break;
-
- case CAL_COMPONENT_JOURNAL:
- list = &priv->journals;
- break;
-
- default:
- /* Make the compiler shut up. */
- list = NULL;
- g_assert_not_reached ();
- }
- l = g_list_find (*list, comp);
+ l = g_list_find (priv->comp, comp);
g_assert (l != NULL);
-
- *list = g_list_remove_link (*list, l);
- g_list_free_1 (l);
+ priv->comp = g_list_delete_link (priv->comp, l);
/* Update the set of categories */
cal_component_get_categories_list (comp, &categories);
cal_backend_unref_categories (CAL_BACKEND (cbfile), categories);
cal_component_free_categories_list (categories);
- g_object_unref (comp);
+ free_object (uid, obj_data, NULL);
}
/* Scans the toplevel VCALENDAR component and stores the objects it finds */
@@ -686,7 +528,7 @@ scan_vcalendar (CalBackendFile *cbfile)
}
/* Parses an open iCalendar file and loads it into the backend */
-static CalBackendOpenStatus
+static CalBackendSyncStatus
open_cal (CalBackendFile *cbfile, const char *uristr)
{
CalBackendFilePrivate *priv;
@@ -696,7 +538,7 @@ open_cal (CalBackendFile *cbfile, const char *uristr)
icalcomp = cal_util_parse_ics_file (uristr);
if (!icalcomp)
- return CAL_BACKEND_OPEN_ERROR;
+ return GNOME_Evolution_Calendar_OtherError;
/* FIXME: should we try to demangle XROOT components and
* individual components as well?
@@ -704,7 +546,8 @@ open_cal (CalBackendFile *cbfile, const char *uristr)
if (icalcomponent_isa (icalcomp) != ICAL_VCALENDAR_COMPONENT) {
icalcomponent_free (icalcomp);
- return CAL_BACKEND_OPEN_ERROR;
+
+ return GNOME_Evolution_Calendar_OtherError;
}
priv->icalcomp = icalcomp;
@@ -714,10 +557,10 @@ open_cal (CalBackendFile *cbfile, const char *uristr)
priv->uri = g_strdup (uristr);
- return CAL_BACKEND_OPEN_SUCCESS;
+ return GNOME_Evolution_Calendar_Success;
}
-static CalBackendOpenStatus
+static CalBackendSyncStatus
create_cal (CalBackendFile *cbfile, const char *uristr)
{
CalBackendFilePrivate *priv;
@@ -734,36 +577,37 @@ create_cal (CalBackendFile *cbfile, const char *uristr)
mark_dirty (cbfile);
- return CAL_BACKEND_OPEN_SUCCESS;
+ return GNOME_Evolution_Calendar_Success;
}
-/* Open handler for the file backend */
-static CalBackendOpenStatus
-cal_backend_file_open (CalBackend *backend, const char *uristr, gboolean only_if_exists)
+static char *
+get_uri_string (CalBackend *backend)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
- char *str_uri;
+ const char *master_uri;
+ char *full_uri, *str_uri;
GnomeVFSURI *uri;
- CalBackendOpenStatus status;
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
+
+ master_uri = cal_backend_get_uri (backend);
+ g_message (G_STRLOC ": Trying to open %s", master_uri);
+
+ /* FIXME Check the error conditions a little more elegantly here */
+ if (g_strrstr ("tasks.ics", master_uri) || g_strrstr ("calendar.ics", master_uri)) {
+ g_warning (G_STRLOC ": Existing file name %s", master_uri);
- g_return_val_if_fail (priv->icalcomp == NULL, CAL_BACKEND_OPEN_ERROR);
- g_return_val_if_fail (uristr != NULL, CAL_BACKEND_OPEN_ERROR);
-
- g_assert (priv->uri == NULL);
- g_assert (priv->comp_uid_hash == NULL);
-
- uri = gnome_vfs_uri_new (uristr);
- if (!uri)
- return CAL_BACKEND_OPEN_ERROR;
-
- if (!uri->method_string || strcmp (uri->method_string, "file")) {
- gnome_vfs_uri_unref (uri);
- return CAL_BACKEND_OPEN_ERROR;
+ return NULL;
}
+
+ full_uri = g_strdup_printf ("%s%s%s", master_uri, G_DIR_SEPARATOR_S, priv->file_name);
+ uri = gnome_vfs_uri_new (full_uri);
+ g_free (full_uri);
+
+ if (!uri)
+ return NULL;
str_uri = gnome_vfs_uri_to_string (uri,
(GNOME_VFS_URI_HIDE_USER_NAME
@@ -771,51 +615,94 @@ cal_backend_file_open (CalBackend *backend, const char *uristr, gboolean only_if
| GNOME_VFS_URI_HIDE_HOST_NAME
| GNOME_VFS_URI_HIDE_HOST_PORT
| GNOME_VFS_URI_HIDE_TOPLEVEL_METHOD));
+ gnome_vfs_uri_unref (uri);
+
if (!str_uri || !strlen (str_uri)) {
g_free (str_uri);
- gnome_vfs_uri_unref (uri);
- return CAL_BACKEND_OPEN_ERROR;
- }
+ return NULL;
+ }
+
+ return str_uri;
+}
+
+/* Open handler for the file backend */
+static CalBackendSyncStatus
+cal_backend_file_open (CalBackendSync *backend, Cal *cal, gboolean only_if_exists)
+{
+ CalBackendFile *cbfile;
+ CalBackendFilePrivate *priv;
+ char *str_uri;
+ CalBackendSyncStatus status;
+
+ cbfile = CAL_BACKEND_FILE (backend);
+ priv = cbfile->priv;
+
+ /* Claim a succesful open if we are already open */
+ if (priv->uri && priv->comp_uid_hash)
+ return GNOME_Evolution_Calendar_Success;
+
+ str_uri = get_uri_string (CAL_BACKEND (backend));
+ if (!str_uri)
+ return GNOME_Evolution_Calendar_OtherError;
+
if (access (str_uri, R_OK) == 0)
status = open_cal (cbfile, str_uri);
else {
if (only_if_exists)
- status = CAL_BACKEND_OPEN_NOT_FOUND;
+ status = GNOME_Evolution_Calendar_NoSuchCal;
else
status = create_cal (cbfile, str_uri);
}
g_free (str_uri);
- gnome_vfs_uri_unref (uri);
return status;
}
-/* is_loaded handler for the file backend */
-static gboolean
-cal_backend_file_is_loaded (CalBackend *backend)
+static CalBackendSyncStatus
+cal_backend_file_remove (CalBackendSync *backend, Cal *cal)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
-
+ char *str_uri;
+
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
- return (priv->icalcomp != NULL);
+ str_uri = get_uri_string (CAL_BACKEND (backend));
+ if (!str_uri)
+ return GNOME_Evolution_Calendar_OtherError;
+
+ if (access (str_uri, W_OK) != 0) {
+ g_free (str_uri);
+
+ return GNOME_Evolution_Calendar_PermissionDenied;
+ }
+
+ /* FIXME Remove backup file and whole directory too? */
+ if (unlink (str_uri) != 0) {
+ g_free (str_uri);
+
+ return GNOME_Evolution_Calendar_OtherError;
+ }
+
+ g_free (str_uri);
+
+ return GNOME_Evolution_Calendar_Success;
}
-/* get_query handler for the file backend */
-static Query *
-cal_backend_file_get_query (CalBackend *backend,
- GNOME_Evolution_Calendar_QueryListener ql,
- const char *sexp)
+/* is_loaded handler for the file backend */
+static gboolean
+cal_backend_file_is_loaded (CalBackend *backend)
{
CalBackendFile *cbfile;
+ CalBackendFilePrivate *priv;
cbfile = CAL_BACKEND_FILE (backend);
+ priv = cbfile->priv;
- return query_new (backend, ql, sexp);
+ return (priv->icalcomp != NULL);
}
/* is_remote handler for the file backend */
@@ -841,283 +728,252 @@ cal_backend_file_set_mode (CalBackend *backend, CalMode mode)
}
-/* Get_n_objects handler for the file backend */
-static int
-cal_backend_file_get_n_objects (CalBackend *backend, CalObjType type)
+static CalBackendSyncStatus
+cal_backend_file_get_default_object (CalBackendSync *backend, Cal *cal, char **object)
{
- CalBackendFile *cbfile;
- CalBackendFilePrivate *priv;
- int n;
-
- cbfile = CAL_BACKEND_FILE (backend);
- priv = cbfile->priv;
-
- g_return_val_if_fail (priv->icalcomp != NULL, -1);
-
- n = 0;
-
- if (type & CALOBJ_TYPE_EVENT)
- n += g_list_length (priv->events);
-
- if (type & CALOBJ_TYPE_TODO)
- n += g_list_length (priv->todos);
-
- if (type & CALOBJ_TYPE_JOURNAL)
- n += g_list_length (priv->journals);
-
- return n;
-}
-
-static char *
-cal_backend_file_get_default_object (CalBackend *backend, CalObjType type)
-{
- CalBackendFile *cbfile;
- CalBackendFilePrivate *priv;
CalComponent *comp;
- char *calobj;
- cbfile = CAL_BACKEND_FILE (backend);
- priv = cbfile->priv;
-
comp = cal_component_new ();
-
- switch (type) {
- case CALOBJ_TYPE_EVENT:
+
+ switch (cal_backend_get_kind (CAL_BACKEND (backend))) {
+ case ICAL_VEVENT_COMPONENT:
cal_component_set_new_vtype (comp, CAL_COMPONENT_EVENT);
break;
- case CALOBJ_TYPE_TODO:
+ case ICAL_VTODO_COMPONENT:
cal_component_set_new_vtype (comp, CAL_COMPONENT_TODO);
break;
- case CALOBJ_TYPE_JOURNAL:
+ case ICAL_VJOURNAL_COMPONENT:
cal_component_set_new_vtype (comp, CAL_COMPONENT_JOURNAL);
break;
default:
g_object_unref (comp);
- return NULL;
+ return GNOME_Evolution_Calendar_ObjectNotFound;
}
- calobj = cal_component_get_as_string (comp);
+ *object = cal_component_get_as_string (comp);
g_object_unref (comp);
- return calobj;
+ return GNOME_Evolution_Calendar_Success;
}
/* Get_object_component handler for the file backend */
-static CalComponent *
-cal_backend_file_get_object_component (CalBackend *backend, const char *uid)
+static CalBackendSyncStatus
+cal_backend_file_get_object (CalBackendSync *backend, Cal *cal, const char *uid, const char *rid, char **object)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
+ CalComponent *comp;
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
- g_return_val_if_fail (uid != NULL, NULL);
-
- g_return_val_if_fail (priv->icalcomp != NULL, NULL);
+ g_return_val_if_fail (priv->icalcomp != NULL, GNOME_Evolution_Calendar_InvalidObject);
+ g_return_val_if_fail (uid != NULL, GNOME_Evolution_Calendar_ObjectNotFound);
g_assert (priv->comp_uid_hash != NULL);
- return lookup_component (cbfile, uid);
+ comp = lookup_component (cbfile, uid);
+ if (!comp)
+ return GNOME_Evolution_Calendar_ObjectNotFound;
+
+ if (rid && *rid) {
+ /* FIXME How to retrieve instance */
+ }
+
+ *object = cal_component_get_as_string (comp);
+
+ return GNOME_Evolution_Calendar_Success;
}
/* Get_timezone_object handler for the file backend */
-static char *
-cal_backend_file_get_timezone_object (CalBackend *backend, const char *tzid)
+static CalBackendSyncStatus
+cal_backend_file_get_timezone (CalBackendSync *backend, Cal *cal, const char *tzid, char **object)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
icaltimezone *zone;
icalcomponent *icalcomp;
- char *ical_string;
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
- g_return_val_if_fail (tzid != NULL, NULL);
-
- g_return_val_if_fail (priv->icalcomp != NULL, NULL);
- g_assert (priv->comp_uid_hash != NULL);
+ g_return_val_if_fail (priv->icalcomp != NULL, GNOME_Evolution_Calendar_NoSuchCal);
+ g_return_val_if_fail (tzid != NULL, GNOME_Evolution_Calendar_ObjectNotFound);
- zone = icalcomponent_get_timezone (priv->icalcomp, tzid);
- if (!zone) {
- zone = icaltimezone_get_builtin_timezone_from_tzid (tzid);
- if (!zone)
- return NULL;
+ if (!strcmp (tzid, "UTC")) {
+ zone = icaltimezone_get_utc_timezone ();
+ } else {
+ zone = icalcomponent_get_timezone (priv->icalcomp, tzid);
+ if (!zone) {
+ zone = icaltimezone_get_builtin_timezone_from_tzid (tzid);
+ if (!zone)
+ return GNOME_Evolution_Calendar_ObjectNotFound;
+ }
}
-
+
icalcomp = icaltimezone_get_component (zone);
if (!icalcomp)
- return NULL;
+ return GNOME_Evolution_Calendar_InvalidObject;
- ical_string = icalcomponent_as_ical_string (icalcomp);
- /* We dup the string; libical owns that memory. */
- if (ical_string)
- return g_strdup (ical_string);
- else
- return NULL;
-}
-
-/* Builds a list of UIDs from a list of CalComponent objects */
-static void
-build_uids_list (GList **list, GList *components)
-{
- GList *l;
-
- for (l = components; l; l = l->next) {
- CalComponent *comp;
- const char *uid;
+ *object = g_strdup (icalcomponent_as_ical_string (icalcomp));
- comp = CAL_COMPONENT (l->data);
- cal_component_get_uid (comp, &uid);
- *list = g_list_prepend (*list, g_strdup (uid));
- }
+ return GNOME_Evolution_Calendar_Success;
}
-/* Get_uids handler for the file backend */
-static GList *
-cal_backend_file_get_uids (CalBackend *backend, CalObjType type)
+/* Add_timezone handler for the file backend */
+static CalBackendSyncStatus
+cal_backend_file_add_timezone (CalBackendSync *backend, Cal *cal, const char *tzobj)
{
+ icalcomponent *tz_comp;
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
- GList *list;
- cbfile = CAL_BACKEND_FILE (backend);
- priv = cbfile->priv;
-
- g_return_val_if_fail (priv->icalcomp != NULL, NULL);
+ cbfile = (CalBackendFile *) backend;
- list = NULL;
+ g_return_val_if_fail (IS_CAL_BACKEND_FILE (cbfile), GNOME_Evolution_Calendar_OtherError);
+ g_return_val_if_fail (tzobj != NULL, GNOME_Evolution_Calendar_OtherError);
- if (type & CALOBJ_TYPE_EVENT)
- build_uids_list (&list, priv->events);
-
- if (type & CALOBJ_TYPE_TODO)
- build_uids_list (&list, priv->todos);
+ priv = cbfile->priv;
- if (type & CALOBJ_TYPE_JOURNAL)
- build_uids_list (&list, priv->journals);
+ tz_comp = icalparser_parse_string (tzobj);
+ if (!tz_comp)
+ return GNOME_Evolution_Calendar_InvalidObject;
- return list;
-}
+ if (icalcomponent_isa (tz_comp) == ICAL_VTIMEZONE_COMPONENT) {
+ icaltimezone *zone;
-/* function to resolve timezones */
-static icaltimezone *
-resolve_tzid (const char *tzid, gpointer user_data)
-{
- icalcomponent *vcalendar_comp = user_data;
+ zone = icaltimezone_new ();
+ icaltimezone_set_component (zone, tz_comp);
+ if (!icalcomponent_get_timezone (priv->icalcomp, icaltimezone_get_tzid (zone))) {
+ icalcomponent_add_component (priv->icalcomp, tz_comp);
+ mark_dirty (cbfile);
+ }
- if (!tzid || !tzid[0])
- return NULL;
- else if (!strcmp (tzid, "UTC"))
- return icaltimezone_get_utc_timezone ();
+ icaltimezone_free (zone, 1);
+ }
- return icalcomponent_get_timezone (vcalendar_comp, tzid);
+ return GNOME_Evolution_Calendar_Success;
}
-/* Callback used from cal_recur_generate_instances(); adds the component's UID
- * to our hash table.
- */
-static gboolean
-add_instance (CalComponent *comp, time_t start, time_t end, gpointer data)
+
+static CalBackendSyncStatus
+cal_backend_file_set_default_timezone (CalBackendSync *backend, Cal *cal, const char *tzid)
{
- GHashTable *uid_hash;
- const char *uid;
- const char *old_uid;
+ CalBackendFile *cbfile;
+ CalBackendFilePrivate *priv;
+ icaltimezone *zone;
- uid_hash = data;
+ cbfile = CAL_BACKEND_FILE (backend);
+ priv = cbfile->priv;
- /* We only care that the component's UID is listed in the hash table;
- * that's why we only allow generation of one instance (i.e. return
- * FALSE every time).
- */
+ g_return_val_if_fail (priv->icalcomp != NULL, GNOME_Evolution_Calendar_NoSuchCal);
- cal_component_get_uid (comp, &uid);
+ /* Look up the VTIMEZONE in our icalcomponent. */
+ zone = icalcomponent_get_timezone (priv->icalcomp, tzid);
+ if (!zone)
+ return GNOME_Evolution_Calendar_ObjectNotFound;
- old_uid = g_hash_table_lookup (uid_hash, uid);
- if (old_uid)
- return FALSE;
+ /* Set the default timezone to it. */
+ priv->default_zone = zone;
- g_hash_table_insert (uid_hash, (char *) uid, NULL);
- return FALSE;
+ return GNOME_Evolution_Calendar_Success;
}
-/* Populates a hash table with the UIDs of the components that occur or recur
- * within a specific time range.
- */
+typedef struct {
+ GList *obj_list;
+ gboolean search_needed;
+ const char *query;
+ CalBackendObjectSExp *obj_sexp;
+ CalBackend *backend;
+ icaltimezone *default_zone;
+} MatchObjectData;
+
static void
-get_instances_in_range (GHashTable *uid_hash, GList *components, time_t start, time_t end, icaltimezone *default_zone)
+match_object_sexp (gpointer key, gpointer value, gpointer data)
{
- GList *l;
-
- for (l = components; l; l = l->next) {
- CalComponent *comp;
- icalcomponent *icalcomp, *vcalendar_comp;
-
- comp = CAL_COMPONENT (l->data);
+ CalBackendFileObject *obj_data = value;
+ MatchObjectData *match_data = data;
- /* Get the parent VCALENDAR component, so we can resolve
- TZIDs. */
- icalcomp = cal_component_get_icalcomponent (comp);
- vcalendar_comp = icalcomponent_get_parent (icalcomp);
- g_assert (vcalendar_comp != NULL);
-
- cal_recur_generate_instances (comp, start, end, add_instance, uid_hash, resolve_tzid, vcalendar_comp, default_zone);
+ if ((!match_data->search_needed) ||
+ (cal_backend_object_sexp_match_comp (match_data->obj_sexp, obj_data->full_object, match_data->backend))) {
+ match_data->obj_list = g_list_append (match_data->obj_list,
+ cal_component_get_as_string (obj_data->full_object));
}
}
-/* Used from g_hash_table_foreach(), adds a UID from the hash table to our list */
-static void
-add_uid_to_list (gpointer key, gpointer value, gpointer data)
+/* Get_objects_in_range handler for the file backend */
+static CalBackendSyncStatus
+cal_backend_file_get_object_list (CalBackendSync *backend, Cal *cal, const char *sexp, GList **objects)
{
- GList **list;
- const char *uid;
- char *uid_copy;
+ CalBackendFile *cbfile;
+ CalBackendFilePrivate *priv;
+ MatchObjectData match_data;
+
+ cbfile = CAL_BACKEND_FILE (backend);
+ priv = cbfile->priv;
- list = data;
+ g_message (G_STRLOC ": Getting object list (%s)", sexp);
- uid = key;
- uid_copy = g_strdup (uid);
+ match_data.search_needed = TRUE;
+ match_data.query = sexp;
+ match_data.obj_list = NULL;
+ match_data.backend = CAL_BACKEND (backend);
+ match_data.default_zone = priv->default_zone;
- *list = g_list_prepend (*list, uid_copy);
+ if (!strcmp (sexp, "#t"))
+ match_data.search_needed = FALSE;
+
+ match_data.obj_sexp = cal_backend_object_sexp_new (sexp);
+ if (!match_data.obj_sexp)
+ return GNOME_Evolution_Calendar_InvalidQuery;
+
+ g_hash_table_foreach (priv->comp_uid_hash, (GHFunc) match_object_sexp, &match_data);
+
+ *objects = match_data.obj_list;
+
+ return GNOME_Evolution_Calendar_Success;
}
-/* Get_objects_in_range handler for the file backend */
-static GList *
-cal_backend_file_get_objects_in_range (CalBackend *backend, CalObjType type,
- time_t start, time_t end)
+/* get_query handler for the file backend */
+static void
+cal_backend_file_start_query (CalBackend *backend, Query *query)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
- GList *event_list;
- GHashTable *uid_hash;
+ MatchObjectData match_data;
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
- g_return_val_if_fail (priv->icalcomp != NULL, NULL);
+ g_message (G_STRLOC ": Starting query (%s)", query_get_text (query));
- g_return_val_if_fail (start != -1 && end != -1, NULL);
- g_return_val_if_fail (start <= end, NULL);
+ /* try to match all currently existing objects */
+ match_data.search_needed = TRUE;
+ match_data.query = query_get_text (query);
+ match_data.obj_list = NULL;
+ match_data.backend = backend;
+ match_data.default_zone = priv->default_zone;
- uid_hash = g_hash_table_new (g_str_hash, g_str_equal);
+ if (!strcmp (match_data.query, "#t"))
+ match_data.search_needed = FALSE;
- if (type & CALOBJ_TYPE_EVENT)
- get_instances_in_range (uid_hash, priv->events, start, end,
- priv->default_zone);
+ match_data.obj_sexp = query_get_object_sexp (query);
+ if (!match_data.obj_sexp) {
+ query_notify_query_done (query, GNOME_Evolution_Calendar_InvalidQuery);
+ return;
+ }
- if (type & CALOBJ_TYPE_TODO)
- get_instances_in_range (uid_hash, priv->todos, start, end,
- priv->default_zone);
+ g_hash_table_foreach (priv->comp_uid_hash, (GHFunc) match_object_sexp, &match_data);
- if (type & CALOBJ_TYPE_JOURNAL)
- get_instances_in_range (uid_hash, priv->journals, start, end,
- priv->default_zone);
+ /* notify listeners of all objects */
+ if (match_data.obj_list) {
+ query_notify_objects_added (query, (const GList *) match_data.obj_list);
- event_list = NULL;
- g_hash_table_foreach (uid_hash, add_uid_to_list, &event_list);
- g_hash_table_destroy (uid_hash);
+ /* free memory */
+ g_list_foreach (match_data.obj_list, (GFunc) g_free, NULL);
+ g_list_free (match_data.obj_list);
+ }
- return event_list;
+ query_notify_query_done (query, GNOME_Evolution_Calendar_Success);
}
static gboolean
@@ -1155,10 +1011,11 @@ create_user_free_busy (CalBackendFile *cbfile, const char *address, const char *
time_t start, time_t end)
{
CalBackendFilePrivate *priv;
- GList *uids;
GList *l;
icalcomponent *vfb;
icaltimezone *utc_zone;
+ CalBackendObjectSExp *obj_sexp;
+ char *query;
priv = cbfile->priv;
@@ -1181,20 +1038,18 @@ create_user_free_busy (CalBackendFile *cbfile, const char *address, const char *
icalcomponent_set_dtend (vfb, icaltime_from_timet_with_zone (end, FALSE, utc_zone));
/* add all objects in the given interval */
+ query = g_strdup_printf ("occur-in-time-range? %lu %lu", start, end);
+ obj_sexp = cal_backend_object_sexp_new (query);
+ g_free (query);
- uids = cal_backend_get_objects_in_range (CAL_BACKEND (cbfile),
- CALOBJ_TYPE_ANY, start, end);
- for (l = uids; l != NULL; l = l->next) {
- CalComponent *comp;
+ if (!obj_sexp)
+ return vfb;
+
+ for (l = priv->comp; l; l = l->next) {
+ CalComponent *comp = l->data;
icalcomponent *icalcomp, *vcalendar_comp;
icalproperty *prop;
- char *uid = (char *) l->data;
-
- /* get the component from our internal list */
- comp = lookup_component (cbfile, uid);
- if (!comp)
- continue;
-
+
icalcomp = cal_component_get_icalcomponent (comp);
if (!icalcomp)
continue;
@@ -1208,7 +1063,10 @@ create_user_free_busy (CalBackendFile *cbfile, const char *address, const char *
transp_val == ICAL_TRANSP_TRANSPARENTNOCONFLICT)
continue;
}
-
+
+ if (!cal_backend_object_sexp_match_comp (obj_sexp, l->data, CAL_BACKEND (cbfile)))
+ continue;
+
vcalendar_comp = icalcomponent_get_parent (icalcomp);
cal_recur_generate_instances (comp, start, end,
free_busy_instance,
@@ -1216,37 +1074,37 @@ create_user_free_busy (CalBackendFile *cbfile, const char *address, const char *
resolve_tzid,
vcalendar_comp,
priv->default_zone);
-
}
- cal_obj_uid_list_free (uids);
return vfb;
}
/* Get_free_busy handler for the file backend */
-static GList *
-cal_backend_file_get_free_busy (CalBackend *backend, GList *users, time_t start, time_t end)
+static CalBackendSyncStatus
+cal_backend_file_get_free_busy (CalBackendSync *backend, Cal *cal, GList *users,
+ time_t start, time_t end, GList **freebusy)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
gchar *address, *name;
icalcomponent *vfb;
char *calobj;
- GList *obj_list = NULL;
GList *l;
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
- g_return_val_if_fail (priv->icalcomp != NULL, NULL);
- g_return_val_if_fail (start != -1 && end != -1, NULL);
- g_return_val_if_fail (start <= end, NULL);
+ g_return_val_if_fail (priv->icalcomp != NULL, GNOME_Evolution_Calendar_NoSuchCal);
+ g_return_val_if_fail (start != -1 && end != -1, GNOME_Evolution_Calendar_InvalidRange);
+ g_return_val_if_fail (start <= end, GNOME_Evolution_Calendar_InvalidRange);
+ *freebusy = NULL;
+
if (users == NULL) {
if (cal_backend_mail_account_get_default (priv->config_listener, &address, &name)) {
vfb = create_user_free_busy (cbfile, address, name, start, end);
calobj = icalcomponent_as_ical_string (vfb);
- obj_list = g_list_append (obj_list, g_strdup (calobj));
+ *freebusy = g_list_append (*freebusy, g_strdup (calobj));
icalcomponent_free (vfb);
g_free (address);
g_free (name);
@@ -1257,34 +1115,31 @@ cal_backend_file_get_free_busy (CalBackend *backend, GList *users, time_t start,
if (cal_backend_mail_account_is_valid (priv->config_listener, address, &name)) {
vfb = create_user_free_busy (cbfile, address, name, start, end);
calobj = icalcomponent_as_ical_string (vfb);
- obj_list = g_list_append (obj_list, g_strdup (calobj));
+ *freebusy = g_list_append (*freebusy, g_strdup (calobj));
icalcomponent_free (vfb);
g_free (name);
}
}
}
- return obj_list;
+ return GNOME_Evolution_Calendar_Success;
}
typedef struct
{
- CalBackend *backend;
+ CalBackendFile *backend;
CalObjType type;
- GList *changes;
- GList *change_ids;
+ GList *deletes;
+ EXmlHash *ehash;
} CalBackendFileComputeChangesData;
static void
cal_backend_file_compute_changes_foreach_key (const char *key, gpointer data)
{
CalBackendFileComputeChangesData *be_data = data;
- char *calobj = cal_backend_get_object (be_data->backend, key);
- if (calobj == NULL) {
+ if (!lookup_component (be_data->backend, key)) {
CalComponent *comp;
- GNOME_Evolution_Calendar_CalObjChange *coc;
- char *calobj;
comp = cal_component_new ();
if (be_data->type == GNOME_Evolution_Calendar_TYPE_TODO)
@@ -1293,319 +1148,283 @@ cal_backend_file_compute_changes_foreach_key (const char *key, gpointer data)
cal_component_set_new_vtype (comp, CAL_COMPONENT_EVENT);
cal_component_set_uid (comp, key);
- calobj = cal_component_get_as_string (comp);
-
- coc = GNOME_Evolution_Calendar_CalObjChange__alloc ();
- coc->calobj = CORBA_string_dup (calobj);
- coc->type = GNOME_Evolution_Calendar_DELETED;
- be_data->changes = g_list_prepend (be_data->changes, coc);
- be_data->change_ids = g_list_prepend (be_data->change_ids, g_strdup (key));
+ be_data->deletes = g_list_prepend (be_data->deletes, cal_component_get_as_string (comp));
- g_free (calobj);
- g_object_unref (comp);
+ e_xmlhash_remove (be_data->ehash, key);
}
}
-static GNOME_Evolution_Calendar_CalObjChangeSeq *
-cal_backend_file_compute_changes (CalBackend *backend, CalObjType type, const char *change_id)
+static CalBackendSyncStatus
+cal_backend_file_compute_changes (CalBackendFile *cbfile, CalObjType type, const char *change_id,
+ GList **adds, GList **modifies, GList **deletes)
{
+ CalBackendFilePrivate *priv;
char *filename;
- EDbHash *ehash;
+ EXmlHash *ehash;
CalBackendFileComputeChangesData be_data;
- GNOME_Evolution_Calendar_CalObjChangeSeq *seq;
- GList *uids, *changes = NULL, *change_ids = NULL;
- GList *i, *j;
- int n;
-
- /* Find the changed ids - FIX ME, path should not be hard coded */
- if (type == GNOME_Evolution_Calendar_TYPE_TODO)
- filename = g_strdup_printf ("%s/evolution/local/Tasks/%s.db", g_get_home_dir (), change_id);
- else
- filename = g_strdup_printf ("%s/evolution/local/Calendar/%s.db", g_get_home_dir (), change_id);
- ehash = e_dbhash_new (filename);
+ GList *i;
+
+ priv = cbfile->priv;
+
+ /* FIXME Will this always work? */
+ filename = g_strdup_printf ("%s/%s.db", priv->uri, change_id);
+ ehash = e_xmlhash_new (filename);
g_free (filename);
- uids = cal_backend_get_uids (backend, type);
-
/* Calculate adds and modifies */
- for (i = uids; i != NULL; i = i->next) {
- GNOME_Evolution_Calendar_CalObjChange *coc;
- char *uid = i->data;
- char *calobj = cal_backend_get_object (backend, uid);
+ for (i = priv->comp; i != NULL; i = i->next) {
+ const char *uid;
+ char *calobj;
+
+ cal_component_get_uid (i->data, &uid);
+ calobj = cal_component_get_as_string (i->data);
g_assert (calobj != NULL);
/* check what type of change has occurred, if any */
- switch (e_dbhash_compare (ehash, uid, calobj)) {
- case E_DBHASH_STATUS_SAME:
+ switch (e_xmlhash_compare (ehash, uid, calobj)) {
+ case E_XMLHASH_STATUS_SAME:
break;
- case E_DBHASH_STATUS_NOT_FOUND:
- coc = GNOME_Evolution_Calendar_CalObjChange__alloc ();
- coc->calobj = CORBA_string_dup (calobj);
- coc->type = GNOME_Evolution_Calendar_ADDED;
- changes = g_list_prepend (changes, coc);
- change_ids = g_list_prepend (change_ids, g_strdup (uid));
+ case E_XMLHASH_STATUS_NOT_FOUND:
+ *adds = g_list_prepend (*adds, g_strdup (calobj));
+ e_xmlhash_add (ehash, uid, calobj);
break;
- case E_DBHASH_STATUS_DIFFERENT:
- coc = GNOME_Evolution_Calendar_CalObjChange__alloc ();
- coc->calobj = CORBA_string_dup (calobj);
- coc->type = GNOME_Evolution_Calendar_MODIFIED;
- changes = g_list_prepend (changes, coc);
- change_ids = g_list_prepend (change_ids, g_strdup (uid));
+ case E_XMLHASH_STATUS_DIFFERENT:
+ *modifies = g_list_prepend (*modifies, g_strdup (calobj));
+ e_xmlhash_add (ehash, uid, calobj);
break;
}
+
+ g_free (calobj);
}
/* Calculate deletions */
- be_data.backend = backend;
+ be_data.backend = cbfile;
be_data.type = type;
- be_data.changes = changes;
- be_data.change_ids = change_ids;
- e_dbhash_foreach_key (ehash, (EDbHashFunc)cal_backend_file_compute_changes_foreach_key, &be_data);
- changes = be_data.changes;
- change_ids = be_data.change_ids;
-
- /* Build the sequence and update the hash */
- n = g_list_length (changes);
-
- seq = GNOME_Evolution_Calendar_CalObjChangeSeq__alloc ();
- seq->_length = n;
- seq->_buffer = CORBA_sequence_GNOME_Evolution_Calendar_CalObjChange_allocbuf (n);
- CORBA_sequence_set_release (seq, TRUE);
-
- for (i = changes, j = change_ids, n = 0; i != NULL; i = i->next, j = j->next, n++) {
- GNOME_Evolution_Calendar_CalObjChange *coc = i->data;
- GNOME_Evolution_Calendar_CalObjChange *seq_coc;
- char *uid = j->data;
-
- /* sequence building */
- seq_coc = &seq->_buffer[n];
- seq_coc->calobj = CORBA_string_dup (coc->calobj);
- seq_coc->type = coc->type;
-
- /* hash updating */
- if (coc->type == GNOME_Evolution_Calendar_ADDED
- || coc->type == GNOME_Evolution_Calendar_MODIFIED) {
- e_dbhash_add (ehash, uid, coc->calobj);
- } else {
- e_dbhash_remove (ehash, uid);
- }
+ be_data.deletes = NULL;
+ be_data.ehash = ehash;
+ e_xmlhash_foreach_key (ehash, (EXmlHashFunc)cal_backend_file_compute_changes_foreach_key, &be_data);
- CORBA_free (coc);
- g_free (uid);
- }
- e_dbhash_write (ehash);
- e_dbhash_destroy (ehash);
+ *deletes = be_data.deletes;
- cal_obj_uid_list_free (uids);
- g_list_free (change_ids);
- g_list_free (changes);
+ e_xmlhash_write (ehash);
+ e_xmlhash_destroy (ehash);
- return seq;
+ return GNOME_Evolution_Calendar_Success;
}
/* Get_changes handler for the file backend */
-static GNOME_Evolution_Calendar_CalObjChangeSeq *
-cal_backend_file_get_changes (CalBackend *backend, CalObjType type, const char *change_id)
+static CalBackendSyncStatus
+cal_backend_file_get_changes (CalBackendSync *backend, Cal *cal, CalObjType type, const char *change_id,
+ GList **adds, GList **modifies, GList **deletes)
{
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
+ CalBackendFile *cbfile;
+ CalBackendFilePrivate *priv;
+
+ cbfile = CAL_BACKEND_FILE (backend);
+ priv = cbfile->priv;
+
+ g_return_val_if_fail (priv->icalcomp != NULL, GNOME_Evolution_Calendar_NoSuchCal);
+ g_return_val_if_fail (change_id != NULL, GNOME_Evolution_Calendar_ObjectNotFound);
+
+ return cal_backend_file_compute_changes (cbfile, type, change_id, adds, modifies, deletes);
+}
- return cal_backend_file_compute_changes (backend, type, change_id);
+/* Discard_alarm handler for the file backend */
+static CalBackendSyncStatus
+cal_backend_file_discard_alarm (CalBackendSync *backend, Cal *cal, const char *uid, const char *auid)
+{
+ /* we just do nothing with the alarm */
+ return GNOME_Evolution_Calendar_Success;
}
-/* Get_alarms_in_range handler for the file backend */
-static GNOME_Evolution_Calendar_CalComponentAlarmsSeq *
-cal_backend_file_get_alarms_in_range (CalBackend *backend,
- time_t start, time_t end)
+static CalBackendSyncStatus
+cal_backend_file_create_object (CalBackendSync *backend, Cal *cal, const char *calobj, char **uid)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
- int n_comp_alarms;
- GSList *comp_alarms;
- GSList *l;
- int i;
- CalAlarmAction omit[] = {-1};
+ icalcomponent *icalcomp;
+ icalcomponent_kind kind;
+ CalComponent *comp;
+ const char *comp_uid;
+ struct icaltimetype current;
- GNOME_Evolution_Calendar_CalComponentAlarmsSeq *seq;
-
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
- g_return_val_if_fail (priv->icalcomp != NULL, NULL);
-
- g_return_val_if_fail (start != -1 && end != -1, NULL);
- g_return_val_if_fail (start <= end, NULL);
-
- /* Per RFC 2445, only VEVENTs and VTODOs can have alarms */
+ g_return_val_if_fail (priv->icalcomp != NULL, GNOME_Evolution_Calendar_NoSuchCal);
+ g_return_val_if_fail (calobj != NULL, GNOME_Evolution_Calendar_ObjectNotFound);
- n_comp_alarms = 0;
- comp_alarms = NULL;
-
- n_comp_alarms += cal_util_generate_alarms_for_list (priv->events, start, end, omit,
- &comp_alarms, resolve_tzid,
- priv->icalcomp,
- priv->default_zone);
- n_comp_alarms += cal_util_generate_alarms_for_list (priv->todos, start, end, omit,
- &comp_alarms, resolve_tzid,
- priv->icalcomp,
- priv->default_zone);
+ icalcomp = icalparser_parse_string ((char *) calobj);
+ if (!icalcomp)
+ return GNOME_Evolution_Calendar_InvalidObject;
- seq = GNOME_Evolution_Calendar_CalComponentAlarmsSeq__alloc ();
- CORBA_sequence_set_release (seq, TRUE);
- seq->_length = n_comp_alarms;
- seq->_buffer = CORBA_sequence_GNOME_Evolution_Calendar_CalComponentAlarms_allocbuf (
- n_comp_alarms);
+ /* FIXME Check kind with the parent */
+ kind = icalcomponent_isa (icalcomp);
+ if (kind != ICAL_VEVENT_COMPONENT && kind != ICAL_VTODO_COMPONENT) {
+ icalcomponent_free (icalcomp);
+ return GNOME_Evolution_Calendar_InvalidObject;
+ }
- for (l = comp_alarms, i = 0; l; l = l->next, i++) {
- CalComponentAlarms *alarms;
- char *comp_str;
+ /* Get the UID */
+ comp_uid = icalcomponent_get_uid (icalcomp);
+
+ /* check the object is not in our cache */
+ if (lookup_component (cbfile, comp_uid)) {
+ icalcomponent_free (icalcomp);
+ return GNOME_Evolution_Calendar_CardIdAlreadyExists;
+ }
- alarms = l->data;
+ /* Create the cal component */
+ comp = cal_component_new ();
+ cal_component_set_icalcomponent (comp, icalcomp);
- comp_str = cal_component_get_as_string (alarms->comp);
- seq->_buffer[i].calobj = CORBA_string_dup (comp_str);
- g_free (comp_str);
+ /* Set the created and last modified times on the component */
+ current = icaltime_from_timet (time (NULL), 0);
+ cal_component_set_created (comp, &current);
+ cal_component_set_last_modified (comp, &current);
- cal_backend_util_fill_alarm_instances_seq (&seq->_buffer[i].alarms, alarms->alarms);
+ /* Add the object */
+ add_component (cbfile, comp, TRUE);
- cal_component_alarms_free (alarms);
- }
+ /* Mark for saving */
+ mark_dirty (cbfile);
- g_slist_free (comp_alarms);
+ /* Return the UID */
+ if (uid)
+ *uid = g_strdup (comp_uid);
- return seq;
+ return GNOME_Evolution_Calendar_Success;
}
-/* Get_alarms_for_object handler for the file backend */
-static GNOME_Evolution_Calendar_CalComponentAlarms *
-cal_backend_file_get_alarms_for_object (CalBackend *backend, const char *uid,
- time_t start, time_t end,
- gboolean *object_found)
+static CalBackendSyncStatus
+cal_backend_file_modify_object (CalBackendSync *backend, Cal *cal, const char *calobj,
+ CalObjModType mod, char **old_object)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
- CalComponent *comp;
- char *comp_str;
- GNOME_Evolution_Calendar_CalComponentAlarms *corba_alarms;
- CalComponentAlarms *alarms;
- CalAlarmAction omit[] = {-1};
+ icalcomponent *icalcomp;
+ icalcomponent_kind kind;
+ const char *comp_uid;
+ CalComponent *comp, *old_comp;
+ struct icaltimetype current;
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
+
+ g_return_val_if_fail (priv->icalcomp != NULL, GNOME_Evolution_Calendar_NoSuchCal);
+ g_return_val_if_fail (calobj != NULL, GNOME_Evolution_Calendar_ObjectNotFound);
- g_return_val_if_fail (priv->icalcomp != NULL, NULL);
+ icalcomp = icalparser_parse_string ((char *) calobj);
+ if (!icalcomp)
+ return GNOME_Evolution_Calendar_InvalidObject;
- g_return_val_if_fail (uid != NULL, NULL);
- g_return_val_if_fail (start != -1 && end != -1, NULL);
- g_return_val_if_fail (start <= end, NULL);
- g_return_val_if_fail (object_found != NULL, NULL);
+ /* FIXME Check kind with the parent */
+ kind = icalcomponent_isa (icalcomp);
+ if (kind != ICAL_VEVENT_COMPONENT && kind != ICAL_VTODO_COMPONENT) {
+ icalcomponent_free (icalcomp);
+ return GNOME_Evolution_Calendar_InvalidObject;
+ }
- comp = lookup_component (cbfile, uid);
- if (!comp) {
- *object_found = FALSE;
- return NULL;
+ /* Get the uid */
+ comp_uid = icalcomponent_get_uid (icalcomp);
+
+ /* Get the object from our cache */
+ if (!(old_comp = lookup_component (cbfile, comp_uid))) {
+ icalcomponent_free (icalcomp);
+ return GNOME_Evolution_Calendar_ObjectNotFound;
}
- *object_found = TRUE;
+ /* Create the cal component */
+ comp = cal_component_new ();
+ cal_component_set_icalcomponent (comp, icalcomp);
+
+ /* Set the last modified time on the component */
+ current = icaltime_from_timet (time (NULL), 0);
+ cal_component_set_last_modified (comp, &current);
+
+ /* FIXME we need to handle mod types here */
- comp_str = cal_component_get_as_string (comp);
- corba_alarms = GNOME_Evolution_Calendar_CalComponentAlarms__alloc ();
+ /* Remove the old version */
+ remove_component (cbfile, old_comp);
- corba_alarms->calobj = CORBA_string_dup (comp_str);
- g_free (comp_str);
+ /* Add the object */
+ add_component (cbfile, comp, TRUE);
- alarms = cal_util_generate_alarms_for_comp (comp, start, end, omit, resolve_tzid, priv->icalcomp, priv->default_zone);
- if (alarms) {
- cal_backend_util_fill_alarm_instances_seq (&corba_alarms->alarms, alarms->alarms);
- cal_component_alarms_free (alarms);
- } else
- cal_backend_util_fill_alarm_instances_seq (&corba_alarms->alarms, NULL);
+ mark_dirty (cbfile);
- return corba_alarms;
-}
+ if (old_object)
+ *old_object = cal_component_get_as_string (comp);
-/* Discard_alarm handler for the file backend */
-static CalBackendResult
-cal_backend_file_discard_alarm (CalBackend *backend, const char *uid, const char *auid)
-{
- /* we just do nothing with the alarm */
- return CAL_BACKEND_RESULT_SUCCESS;
+ return GNOME_Evolution_Calendar_Success;
}
-/* Creates a CalComponent for the given icalcomponent and adds it to our
- cache. Note that the icalcomponent is not added to the toplevel
- icalcomponent here. That needs to be done elsewhere. It returns the uid
- of the added component, or NULL if it failed. */
-static const char*
-cal_backend_file_update_object (CalBackendFile *cbfile,
- icalcomponent *icalcomp)
+/* Remove_object handler for the file backend */
+static CalBackendSyncStatus
+cal_backend_file_remove_object (CalBackendSync *backend, Cal *cal, const char *uid, const char *rid,
+ CalObjModType mod, char **object)
{
- CalComponent *old_comp;
+ CalBackendFile *cbfile;
+ CalBackendFilePrivate *priv;
CalComponent *comp;
- const char *comp_uid;
- struct icaltimetype last_modified;
- /* Create a CalComponent wrapper for the icalcomponent. */
- comp = cal_component_new ();
- if (!cal_component_set_icalcomponent (comp, icalcomp)) {
- g_object_unref (comp);
- return NULL;
- }
+ cbfile = CAL_BACKEND_FILE (backend);
+ priv = cbfile->priv;
- /* Get the UID, and check it isn't empty. */
- cal_component_get_uid (comp, &comp_uid);
- if (!comp_uid || !comp_uid[0]) {
- g_object_unref (comp);
- return NULL;
- }
+ g_return_val_if_fail (priv->icalcomp != NULL, GNOME_Evolution_Calendar_NoSuchCal);
+ g_return_val_if_fail (uid != NULL, GNOME_Evolution_Calendar_ObjectNotFound);
- /* Set the LAST-MODIFIED time on the component */
- last_modified = icaltime_from_timet (time (NULL), 0);
- cal_component_set_last_modified (comp, &last_modified);
-
- /* Remove any old version of the component. */
- old_comp = lookup_component (cbfile, comp_uid);
- if (old_comp)
- remove_component (cbfile, old_comp);
+ /* FIXME we need to handle mod types here */
- /* Now add the component to our local cache, but we pass FALSE as
- the last argument, since the libical component is assumed to have
- been added already. */
- add_component (cbfile, comp, FALSE);
+ comp = lookup_component (cbfile, uid);
+ if (!comp)
+ return GNOME_Evolution_Calendar_ObjectNotFound;
+
+ *object = cal_component_get_as_string (comp);
+ remove_component (cbfile, comp);
+
+ mark_dirty (cbfile);
- return comp_uid;
+ return GNOME_Evolution_Calendar_Success;
}
-static const char*
-cal_backend_file_cancel_object (CalBackendFile *cbfile,
- icalcomponent *icalcomp)
+static gboolean
+cancel_received_object (CalBackendFile *cbfile, icalcomponent *icalcomp)
{
CalComponent *old_comp;
- icalproperty *uid;
- const char *comp_uid;
-
- /* Get the UID, and check it isn't empty. */
- uid = icalcomponent_get_first_property (icalcomp, ICAL_UID_PROPERTY);
- if (!uid)
- return NULL;
- comp_uid = icalproperty_get_uid (uid);
- if (!comp_uid || !comp_uid[0])
- return NULL;
/* Find the old version of the component. */
- old_comp = lookup_component (cbfile, comp_uid);
+ old_comp = lookup_component (cbfile, icalcomponent_get_uid (icalcomp));
if (!old_comp)
- return NULL;
+ return FALSE;
/* And remove it */
remove_component (cbfile, old_comp);
- return comp_uid;
+
+ return TRUE;
+}
+
+typedef struct {
+ GHashTable *zones;
+
+ gboolean found;
+} CalBackendFileTzidData;
+
+static void
+check_tzids (icalparameter *param, void *data)
+{
+ CalBackendFileTzidData *tzdata = data;
+ const char *tzid;
+
+ tzid = icalparameter_get_tzid (param);
+ if (!tzid || g_hash_table_lookup (tzdata->zones, tzid))
+ tzdata->found = FALSE;
}
/* Update_objects handler for the file backend. */
-static CalBackendResult
-cal_backend_file_update_objects (CalBackend *backend, const char *calobj, CalObjModType mod)
+static CalBackendSyncStatus
+cal_backend_file_receive_objects (CalBackendSync *backend, Cal *cal, const char *calobj,
+ GList **created, GList **modified, GList **removed)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
@@ -1613,143 +1432,153 @@ cal_backend_file_update_objects (CalBackend *backend, const char *calobj, CalObj
icalcomponent_kind kind;
icalproperty_method method;
icalcomponent *subcomp;
- CalBackendResult retval = CAL_BACKEND_RESULT_SUCCESS;
- GList *updated_uids = NULL, *removed_uids = NULL, *elem;
+ GList *comps, *l;
+ CalBackendFileTzidData tzdata;
+ CalBackendSyncStatus status = GNOME_Evolution_Calendar_Success;
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
- g_return_val_if_fail (priv->icalcomp != NULL, CAL_BACKEND_RESULT_INVALID_OBJECT);
-
- g_return_val_if_fail (calobj != NULL, CAL_BACKEND_RESULT_INVALID_OBJECT);
+ g_return_val_if_fail (priv->icalcomp != NULL, GNOME_Evolution_Calendar_InvalidObject);
+ g_return_val_if_fail (calobj != NULL, GNOME_Evolution_Calendar_InvalidObject);
/* Pull the component from the string and ensure that it is sane */
-
toplevel_comp = icalparser_parse_string ((char *) calobj);
-
if (!toplevel_comp)
- return CAL_BACKEND_RESULT_INVALID_OBJECT;
+ return GNOME_Evolution_Calendar_InvalidObject;
kind = icalcomponent_isa (toplevel_comp);
-
- if (kind == ICAL_VEVENT_COMPONENT
- || kind == ICAL_VTODO_COMPONENT
- || kind == ICAL_VJOURNAL_COMPONENT) {
- /* Create a temporary toplevel component and put the VEVENT
- or VTODO in it, to simplify the code below. */
+ if (kind != ICAL_VCALENDAR_COMPONENT) {
+ /* If its not a VCALENDAR, make it one to simplify below */
icalcomp = toplevel_comp;
toplevel_comp = cal_util_new_top_level ();
- icalcomponent_add_component (toplevel_comp, icalcomp);
- } else if (kind != ICAL_VCALENDAR_COMPONENT) {
- /* We don't support this type of component */
- icalcomponent_free (toplevel_comp);
- return CAL_BACKEND_RESULT_INVALID_OBJECT;
+ icalcomponent_add_component (toplevel_comp, icalcomp);
}
method = icalcomponent_get_method (toplevel_comp);
- /* Step throught the VEVENT/VTODOs being added, create CalComponents
- for them, and add them to our cache. */
- subcomp = icalcomponent_get_first_component (toplevel_comp,
- ICAL_ANY_COMPONENT);
+ *created = *modified = *removed = NULL;
+
+ /* Build a list of timezones so we can make sure all the objects have valid info */
+ tzdata.zones = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ subcomp = icalcomponent_get_first_component (toplevel_comp, ICAL_VTIMEZONE_COMPONENT);
+ while (subcomp) {
+ icaltimezone *zone;
+
+ zone = icaltimezone_new ();
+ if (icaltimezone_set_component (zone, subcomp))
+ g_hash_table_insert (tzdata.zones, g_strdup (icaltimezone_get_tzid (zone)), NULL);
+
+ subcomp = icalcomponent_get_next_component (toplevel_comp, ICAL_VTIMEZONE_COMPONENT);
+ }
+
+ /* First we make sure all the components are usuable */
+ comps = NULL;
+ subcomp = icalcomponent_get_first_component (toplevel_comp, ICAL_ANY_COMPONENT);
while (subcomp) {
/* We ignore anything except VEVENT, VTODO and VJOURNAL
components. */
icalcomponent_kind child_kind = icalcomponent_isa (subcomp);
- if (child_kind == ICAL_VEVENT_COMPONENT
- || child_kind == ICAL_VTODO_COMPONENT
- || child_kind == ICAL_VJOURNAL_COMPONENT) {
- const char *comp_uid;
-
- if (method == ICAL_METHOD_CANCEL) {
- comp_uid = cal_backend_file_cancel_object (cbfile, subcomp);
- if (comp_uid) {
- removed_uids = g_list_prepend (removed_uids,
- g_strdup (comp_uid));
- } else
- retval = CAL_BACKEND_RESULT_NOT_FOUND;
- } else {
- comp_uid = cal_backend_file_update_object (cbfile, subcomp);
- if (comp_uid) {
- updated_uids = g_list_prepend (updated_uids,
- g_strdup (comp_uid));
- } else
- retval = CAL_BACKEND_RESULT_INVALID_OBJECT;
+
+ switch (child_kind) {
+ case ICAL_VEVENT_COMPONENT:
+ case ICAL_VTODO_COMPONENT:
+ case ICAL_VJOURNAL_COMPONENT:
+ tzdata.found = TRUE;
+ icalcomponent_foreach_tzid (subcomp, check_tzids, &tzdata);
+
+ if (!tzdata.found) {
+ status = GNOME_Evolution_Calendar_InvalidObject;
+ goto error;
}
+
+ if (!icalcomponent_get_uid (subcomp)) {
+ status = GNOME_Evolution_Calendar_InvalidObject;
+ goto error;
+ }
+
+ comps = g_list_prepend (comps, subcomp);
+ break;
+ default:
+ /* Ignore it */
+ break;
}
- subcomp = icalcomponent_get_next_component (toplevel_comp,
- ICAL_ANY_COMPONENT);
+
+ subcomp = icalcomponent_get_next_component (toplevel_comp, ICAL_ANY_COMPONENT);
}
+ /* Now we manipulate the components we care about */
+ for (l = comps; l; l = l->next) {
+ subcomp = l->data;
+
+ switch (method) {
+ case ICAL_METHOD_PUBLISH:
+ case ICAL_METHOD_REQUEST:
+ /* FIXME Need to see the new create/modify stuff before we set this up */
+ break;
+ case ICAL_METHOD_REPLY:
+ /* FIXME Update the status of the user, if we are the organizer */
+ break;
+ case ICAL_METHOD_ADD:
+ /* FIXME This should be doable once all the recurid stuff is done */
+ break;
+ case ICAL_METHOD_COUNTER:
+ status = GNOME_Evolution_Calendar_UnsupportedMethod;
+ goto error;
+ break;
+ case ICAL_METHOD_DECLINECOUNTER:
+ status = GNOME_Evolution_Calendar_UnsupportedMethod;
+ goto error;
+ break;
+ case ICAL_METHOD_CANCEL:
+ /* FIXME Do we need to remove the subcomp so it isn't merged? */
+ if (cancel_received_object (cbfile, subcomp))
+ *removed = g_list_prepend (*removed, g_strdup (icalcomponent_get_uid (subcomp)));
+ break;
+ default:
+ status = GNOME_Evolution_Calendar_UnsupportedMethod;
+ goto error;
+ }
+ }
+ g_list_free (comps);
+
/* Merge the iCalendar components with our existing VCALENDAR,
resolving any conflicting TZIDs. */
icalcomponent_merge_component (priv->icalcomp, toplevel_comp);
mark_dirty (cbfile);
- /* Now emit notification signals for all of the added components.
- We do this after adding them all to make sure the calendar is in a
- stable state before emitting signals. */
- for (elem = updated_uids; elem; elem = elem->next) {
- char *comp_uid = elem->data;
- cal_backend_notify_update (backend, comp_uid);
- g_free (comp_uid);
- }
- g_list_free (updated_uids);
-
- for (elem = removed_uids; elem; elem = elem->next) {
- char *comp_uid = elem->data;
- cal_backend_notify_remove (backend, comp_uid);
- g_free (comp_uid);
- }
- g_list_free (removed_uids);
-
- return retval;
+ error:
+ g_hash_table_destroy (tzdata.zones);
+
+ return status;
}
+static CalBackendSyncStatus
+cal_backend_file_send_objects (CalBackendSync *backend, Cal *cal, const char *calobj)
+{
+ /* FIXME Put in a util routine to send stuff via email */
+
+ return GNOME_Evolution_Calendar_Success;
+}
-/* Remove_object handler for the file backend */
-static CalBackendResult
-cal_backend_file_remove_object (CalBackend *backend, const char *uid, CalObjModType mod)
+static icaltimezone *
+cal_backend_file_internal_get_default_timezone (CalBackend *backend)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
- CalComponent *comp;
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
- g_return_val_if_fail (priv->icalcomp != NULL, CAL_BACKEND_RESULT_INVALID_OBJECT);
-
- g_return_val_if_fail (uid != NULL, CAL_BACKEND_RESULT_NOT_FOUND);
-
- comp = lookup_component (cbfile, uid);
- if (!comp)
- return CAL_BACKEND_RESULT_NOT_FOUND;
-
- remove_component (cbfile, comp);
-
- mark_dirty (cbfile);
-
- cal_backend_notify_remove (backend, uid);
-
- return CAL_BACKEND_RESULT_SUCCESS;
-}
-
-static CalBackendSendResult
-cal_backend_file_send_object (CalBackend *backend, const char *calobj, char **new_calobj,
- GNOME_Evolution_Calendar_UserList **user_list, char error_msg[256])
-{
- *new_calobj = g_strdup (calobj);
-
- *user_list = GNOME_Evolution_Calendar_UserList__alloc ();
- (*user_list)->_length = 0;
+ g_return_val_if_fail (priv->icalcomp != NULL, NULL);
- return CAL_BACKEND_SEND_SUCCESS;
+ return priv->default_zone;
}
-static icaltimezone*
-cal_backend_file_get_timezone (CalBackend *backend, const char *tzid)
+static icaltimezone *
+cal_backend_file_internal_get_timezone (CalBackend *backend, const char *tzid)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
@@ -1771,43 +1600,134 @@ cal_backend_file_get_timezone (CalBackend *backend, const char *tzid)
return zone;
}
-
-static icaltimezone*
-cal_backend_file_get_default_timezone (CalBackend *backend)
+/* Object initialization function for the file backend */
+static void
+cal_backend_file_init (CalBackendFile *cbfile, CalBackendFileClass *class)
{
- CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
- cbfile = CAL_BACKEND_FILE (backend);
- priv = cbfile->priv;
+ priv = g_new0 (CalBackendFilePrivate, 1);
+ cbfile->priv = priv;
- g_return_val_if_fail (priv->icalcomp != NULL, NULL);
+ priv->uri = NULL;
+ priv->file_name = g_strdup ("calendar.ics");
+ priv->icalcomp = NULL;
+ priv->comp_uid_hash = NULL;
+ priv->comp = NULL;
- return priv->default_zone;
+ /* The timezone defaults to UTC. */
+ priv->default_zone = icaltimezone_get_utc_timezone ();
+
+ priv->config_listener = e_config_listener_new ();
}
+/* Class initialization function for the file backend */
+static void
+cal_backend_file_class_init (CalBackendFileClass *class)
+{
+ GObjectClass *object_class;
+ CalBackendClass *backend_class;
+ CalBackendSyncClass *sync_class;
-static gboolean
-cal_backend_file_set_default_timezone (CalBackend *backend,
- const char *tzid)
+ object_class = (GObjectClass *) class;
+ backend_class = (CalBackendClass *) class;
+ sync_class = (CalBackendSyncClass *) class;
+
+ parent_class = (CalBackendSyncClass *) g_type_class_peek_parent (class);
+
+ object_class->dispose = cal_backend_file_dispose;
+ object_class->finalize = cal_backend_file_finalize;
+
+ sync_class->is_read_only_sync = cal_backend_file_is_read_only;
+ sync_class->get_cal_address_sync = cal_backend_file_get_cal_address;
+ sync_class->get_alarm_email_address_sync = cal_backend_file_get_alarm_email_address;
+ sync_class->get_ldap_attribute_sync = cal_backend_file_get_ldap_attribute;
+ sync_class->get_static_capabilities_sync = cal_backend_file_get_static_capabilities;
+ sync_class->open_sync = cal_backend_file_open;
+ sync_class->remove_sync = cal_backend_file_remove;
+ sync_class->create_object_sync = cal_backend_file_create_object;
+ sync_class->modify_object_sync = cal_backend_file_modify_object;
+ sync_class->remove_object_sync = cal_backend_file_remove_object;
+ sync_class->discard_alarm_sync = cal_backend_file_discard_alarm;
+ sync_class->receive_objects_sync = cal_backend_file_receive_objects;
+ sync_class->send_objects_sync = cal_backend_file_send_objects;
+ sync_class->get_default_object_sync = cal_backend_file_get_default_object;
+ sync_class->get_object_sync = cal_backend_file_get_object;
+ sync_class->get_object_list_sync = cal_backend_file_get_object_list;
+ sync_class->get_timezone_sync = cal_backend_file_get_timezone;
+ sync_class->add_timezone_sync = cal_backend_file_add_timezone;
+ sync_class->set_default_timezone_sync = cal_backend_file_set_default_timezone;
+ sync_class->get_freebusy_sync = cal_backend_file_get_free_busy;
+ sync_class->get_changes_sync = cal_backend_file_get_changes;
+
+ backend_class->is_loaded = cal_backend_file_is_loaded;
+ backend_class->start_query = cal_backend_file_start_query;
+ backend_class->get_mode = cal_backend_file_get_mode;
+ backend_class->set_mode = cal_backend_file_set_mode;
+
+ backend_class->internal_get_default_timezone = cal_backend_file_internal_get_default_timezone;
+ backend_class->internal_get_timezone = cal_backend_file_internal_get_timezone;
+}
+
+
+/**
+ * cal_backend_file_get_type:
+ * @void:
+ *
+ * Registers the #CalBackendFile class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the #CalBackendFile class.
+ **/
+GType
+cal_backend_file_get_type (void)
+{
+ static GType cal_backend_file_type = 0;
+
+ if (!cal_backend_file_type) {
+ static GTypeInfo info = {
+ sizeof (CalBackendFileClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) cal_backend_file_class_init,
+ NULL, NULL,
+ sizeof (CalBackendFile),
+ 0,
+ (GInstanceInitFunc) cal_backend_file_init
+ };
+ cal_backend_file_type = g_type_register_static (CAL_TYPE_BACKEND_SYNC,
+ "CalBackendFile", &info, 0);
+ }
+
+ return cal_backend_file_type;
+}
+
+void
+cal_backend_file_set_file_name (CalBackendFile *cbfile, const char *file_name)
{
- CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
- icaltimezone *zone;
+
+ g_return_if_fail (cbfile != NULL);
+ g_return_if_fail (IS_CAL_BACKEND_FILE (cbfile));
+ g_return_if_fail (file_name != NULL);
- cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
+
+ if (priv->file_name)
+ g_free (priv->file_name);
+
+ priv->file_name = g_strdup (file_name);
+}
- g_return_val_if_fail (priv->icalcomp != NULL, FALSE);
+const char *
+cal_backend_file_get_file_name (CalBackendFile *cbfile)
+{
+ CalBackendFilePrivate *priv;
- /* Look up the VTIMEZONE in our icalcomponent. */
- zone = icalcomponent_get_timezone (priv->icalcomp, tzid);
- if (!zone)
- return FALSE;
+ g_return_val_if_fail (cbfile != NULL, NULL);
+ g_return_val_if_fail (IS_CAL_BACKEND_FILE (cbfile), NULL);
- /* Set the default timezone to it. */
- priv->default_zone = zone;
+ priv = cbfile->priv;
- return TRUE;
+ return priv->file_name;
}
-
diff --git a/calendar/pcs/cal-backend-file.h b/calendar/pcs/cal-backend-file.h
index 4f79da66de..ebe190cb2a 100644
--- a/calendar/pcs/cal-backend-file.h
+++ b/calendar/pcs/cal-backend-file.h
@@ -22,7 +22,7 @@
#ifndef CAL_BACKEND_FILE_H
#define CAL_BACKEND_FILE_H
-#include "pcs/cal-backend.h"
+#include "pcs/cal-backend-sync.h"
G_BEGIN_DECLS
@@ -42,17 +42,21 @@ typedef struct _CalBackendFileClass CalBackendFileClass;
typedef struct _CalBackendFilePrivate CalBackendFilePrivate;
struct _CalBackendFile {
- CalBackend backend;
+ CalBackendSync backend;
/* Private data */
CalBackendFilePrivate *priv;
};
struct _CalBackendFileClass {
- CalBackendClass parent_class;
+ CalBackendSyncClass parent_class;
};
-GType cal_backend_file_get_type (void);
+GType cal_backend_file_get_type (void);
+
+void cal_backend_file_set_file_name (CalBackendFile *cbfile,
+ const char *file_name);
+const char *cal_backend_file_get_file_name (CalBackendFile *cbfile);
diff --git a/calendar/pcs/cal-backend-object-sexp.c b/calendar/pcs/cal-backend-object-sexp.c
new file mode 100644
index 0000000000..4bc6b78ebe
--- /dev/null
+++ b/calendar/pcs/cal-backend-object-sexp.c
@@ -0,0 +1,1007 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * cal-backend-card-sexp.c
+ * Copyright 1999, 2000, 2001, Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <libgnome/gnome-i18n.h>
+#include <e-util/e-sexp.h>
+#include <gal/widgets/e-unicode.h>
+#include <cal-util/timeutil.h>
+
+#include "cal-backend-object-sexp.h"
+
+static GObjectClass *parent_class;
+
+typedef struct _SearchContext SearchContext;
+
+struct _CalBackendObjectSExpPrivate {
+ ESExp *search_sexp;
+ char *text;
+ SearchContext *search_context;
+};
+
+struct _SearchContext {
+ CalComponent *comp;
+ CalBackend *backend;
+};
+
+static ESExpResult *
+func_time_now (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+{
+ ESExpResult *result;
+
+ if (argc != 0) {
+ e_sexp_fatal_error (esexp, _("time-now expects 0 arguments"));
+ return NULL;
+ }
+
+ result = e_sexp_result_new (esexp, ESEXP_RES_TIME);
+ result->value.time = time (NULL);
+
+ return result;
+}
+
+/* (make-time ISODATE)
+ *
+ * ISODATE - string, ISO 8601 date/time representation
+ *
+ * Constructs a time_t value for the specified date.
+ */
+static ESExpResult *
+func_make_time (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+{
+ const char *str;
+ time_t t;
+ ESExpResult *result;
+
+ if (argc != 1) {
+ e_sexp_fatal_error (esexp, _("make-time expects 1 argument"));
+ return NULL;
+ }
+
+ if (argv[0]->type != ESEXP_RES_STRING) {
+ e_sexp_fatal_error (esexp, _("make-time expects argument 1 "
+ "to be a string"));
+ return NULL;
+ }
+ str = argv[0]->value.string;
+
+ t = time_from_isodate (str);
+ if (t == -1) {
+ e_sexp_fatal_error (esexp, _("make-time argument 1 must be an "
+ "ISO 8601 date/time string"));
+ return NULL;
+ }
+
+ result = e_sexp_result_new (esexp, ESEXP_RES_TIME);
+ result->value.time = t;
+
+ return result;
+}
+
+/* (time-add-day TIME N)
+ *
+ * TIME - time_t, base time
+ * N - int, number of days to add
+ *
+ * Adds the specified number of days to a time value.
+ *
+ * FIXME: TIMEZONES - need to use a timezone or daylight saving changes will
+ * make the result incorrect.
+ */
+static ESExpResult *
+func_time_add_day (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+{
+ ESExpResult *result;
+ time_t t;
+ int n;
+
+ if (argc != 2) {
+ e_sexp_fatal_error (esexp, _("time-add-day expects 2 arguments"));
+ return NULL;
+ }
+
+ if (argv[0]->type != ESEXP_RES_TIME) {
+ e_sexp_fatal_error (esexp, _("time-add-day expects argument 1 "
+ "to be a time_t"));
+ return NULL;
+ }
+ t = argv[0]->value.time;
+
+ if (argv[1]->type != ESEXP_RES_INT) {
+ e_sexp_fatal_error (esexp, _("time-add-day expects argument 2 "
+ "to be an integer"));
+ return NULL;
+ }
+ n = argv[1]->value.number;
+
+ result = e_sexp_result_new (esexp, ESEXP_RES_TIME);
+ result->value.time = time_add_day (t, n);
+
+ return result;
+}
+
+/* (time-day-begin TIME)
+ *
+ * TIME - time_t, base time
+ *
+ * Returns the start of the day, according to the local time.
+ *
+ * FIXME: TIMEZONES - this uses the current Unix timezone.
+ */
+static ESExpResult *
+func_time_day_begin (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+{
+ time_t t;
+ ESExpResult *result;
+
+ if (argc != 1) {
+ e_sexp_fatal_error (esexp, _("time-day-begin expects 1 argument"));
+ return NULL;
+ }
+
+ if (argv[0]->type != ESEXP_RES_TIME) {
+ e_sexp_fatal_error (esexp, _("time-day-begin expects argument 1 "
+ "to be a time_t"));
+ return NULL;
+ }
+ t = argv[0]->value.time;
+
+ result = e_sexp_result_new (esexp, ESEXP_RES_TIME);
+ result->value.time = time_day_begin (t);
+
+ return result;
+}
+
+/* (time-day-end TIME)
+ *
+ * TIME - time_t, base time
+ *
+ * Returns the end of the day, according to the local time.
+ *
+ * FIXME: TIMEZONES - this uses the current Unix timezone.
+ */
+static ESExpResult *
+func_time_day_end (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+{
+ time_t t;
+ ESExpResult *result;
+
+ if (argc != 1) {
+ e_sexp_fatal_error (esexp, _("time-day-end expects 1 argument"));
+ return NULL;
+ }
+
+ if (argv[0]->type != ESEXP_RES_TIME) {
+ e_sexp_fatal_error (esexp, _("time-day-end expects argument 1 "
+ "to be a time_t"));
+ return NULL;
+ }
+ t = argv[0]->value.time;
+
+ result = e_sexp_result_new (esexp, ESEXP_RES_TIME);
+ result->value.time = time_day_end (t);
+
+ return result;
+}
+
+/* (get-vtype)
+ *
+ * Returns a string indicating the type of component (VEVENT, VTODO, VJOURNAL,
+ * VFREEBUSY, VTIMEZONE, UNKNOWN).
+ */
+static ESExpResult *
+func_get_vtype (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+{
+ SearchContext *ctx = data;
+ CalComponentVType vtype;
+ char *str;
+ ESExpResult *result;
+
+ /* Check argument types */
+
+ if (argc != 0) {
+ e_sexp_fatal_error (esexp, _("get-vtype expects 0 arguments"));
+ return NULL;
+ }
+
+ /* Get the type */
+
+ vtype = cal_component_get_vtype (ctx->comp);
+
+ switch (vtype) {
+ case CAL_COMPONENT_EVENT:
+ str = g_strdup ("VEVENT");
+ break;
+
+ case CAL_COMPONENT_TODO:
+ str = g_strdup ("VTODO");
+ break;
+
+ case CAL_COMPONENT_JOURNAL:
+ str = g_strdup ("VJOURNAL");
+ break;
+
+ case CAL_COMPONENT_FREEBUSY:
+ str = g_strdup ("VFREEBUSY");
+ break;
+
+ case CAL_COMPONENT_TIMEZONE:
+ str = g_strdup ("VTIMEZONE");
+ break;
+
+ default:
+ str = g_strdup ("UNKNOWN");
+ break;
+ }
+
+ result = e_sexp_result_new (esexp, ESEXP_RES_STRING);
+ result->value.string = str;
+
+ return result;
+}
+
+/* (occur-in-time-range? START END)
+ *
+ * START - time_t, start of the time range
+ * END - time_t, end of the time range
+ *
+ * Returns a boolean indicating whether the component has any occurrences in the
+ * specified time range.
+ */
+static ESExpResult *
+func_occur_in_time_range (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+{
+ SearchContext *ctx = data;
+ time_t start, end, tt;
+ gboolean occurs;
+ ESExpResult *result;
+ CalComponentDateTime dt;
+
+ /* Check argument types */
+
+ if (argc != 2) {
+ e_sexp_fatal_error (esexp, _("occur-in-time-range? expects 2 arguments"));
+ return NULL;
+ }
+
+ if (argv[0]->type != ESEXP_RES_TIME) {
+ e_sexp_fatal_error (esexp, _("occur-in-time-range? expects argument 1 "
+ "to be a time_t"));
+ return NULL;
+ }
+ start = argv[0]->value.time;
+
+ if (argv[1]->type != ESEXP_RES_TIME) {
+ e_sexp_fatal_error (esexp, _("occur-in-time-range? expects argument 2 "
+ "to be a time_t"));
+ return NULL;
+ }
+ end = argv[1]->value.time;
+
+ /* See if the object occurs in the specified time range */
+ occurs = FALSE;
+
+ cal_component_get_dtstart (ctx->comp, &dt);
+ if (dt.value) {
+ icaltimezone *zone;
+
+ if (dt.tzid)
+ zone = cal_backend_internal_get_timezone (ctx->backend, dt.tzid);
+ else
+ zone = cal_backend_internal_get_default_timezone (ctx->backend);
+
+ tt = icaltime_as_timet_with_zone (*dt.value, zone);
+ if (tt >= start && tt <= end)
+ occurs = TRUE;
+ else {
+ cal_component_get_dtend (ctx->comp, &dt);
+ if (dt.value) {
+ if (dt.tzid)
+ zone = cal_backend_internal_get_timezone (ctx->backend, dt.tzid);
+ else
+ zone = cal_backend_internal_get_default_timezone (ctx->backend);
+
+ tt = icaltime_as_timet_with_zone (*dt.value, zone);
+ if (tt >= start && tt <= end)
+ occurs = TRUE;
+ }
+ }
+ }
+
+ result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
+ result->value.bool = occurs;
+
+ return result;
+}
+
+/* Returns whether a list of CalComponentText items matches the specified string */
+static gboolean
+matches_text_list (GSList *text_list, const char *str)
+{
+ GSList *l;
+ gboolean matches;
+
+ matches = FALSE;
+
+ for (l = text_list; l; l = l->next) {
+ CalComponentText *text;
+
+ text = l->data;
+ g_assert (text->value != NULL);
+
+ if (e_utf8_strstrcasedecomp (text->value, str) != NULL) {
+ matches = TRUE;
+ break;
+ }
+ }
+
+ return matches;
+}
+
+/* Returns whether the comments in a component matches the specified string */
+static gboolean
+matches_comment (CalComponent *comp, const char *str)
+{
+ GSList *list;
+ gboolean matches;
+
+ cal_component_get_comment_list (comp, &list);
+ matches = matches_text_list (list, str);
+ cal_component_free_text_list (list);
+
+ return matches;
+}
+
+/* Returns whether the description in a component matches the specified string */
+static gboolean
+matches_description (CalComponent *comp, const char *str)
+{
+ GSList *list;
+ gboolean matches;
+
+ cal_component_get_description_list (comp, &list);
+ matches = matches_text_list (list, str);
+ cal_component_free_text_list (list);
+
+ return matches;
+}
+
+/* Returns whether the summary in a component matches the specified string */
+static gboolean
+matches_summary (CalComponent *comp, const char *str)
+{
+ CalComponentText text;
+
+ cal_component_get_summary (comp, &text);
+
+ if (!text.value)
+ return FALSE;
+
+ return e_utf8_strstrcasedecomp (text.value, str) != NULL;
+}
+
+/* Returns whether any text field in a component matches the specified string */
+static gboolean
+matches_any (CalComponent *comp, const char *str)
+{
+ /* As an optimization, and to make life easier for the individual
+ * predicate functions, see if we are looking for the empty string right
+ * away.
+ */
+ if (strlen (str) == 0)
+ return TRUE;
+
+ return (matches_comment (comp, str)
+ || matches_description (comp, str)
+ || matches_summary (comp, str));
+}
+
+/* (contains? FIELD STR)
+ *
+ * FIELD - string, name of field to match (any, comment, description, summary)
+ * STR - string, match string
+ *
+ * Returns a boolean indicating whether the specified field contains the
+ * specified string.
+ */
+static ESExpResult *
+func_contains (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+{
+ SearchContext *ctx = data;
+ const char *field;
+ const char *str;
+ gboolean matches;
+ ESExpResult *result;
+
+ /* Check argument types */
+
+ if (argc != 2) {
+ e_sexp_fatal_error (esexp, _("contains? expects 2 arguments"));
+ return NULL;
+ }
+
+ if (argv[0]->type != ESEXP_RES_STRING) {
+ e_sexp_fatal_error (esexp, _("contains? expects argument 1 "
+ "to be a string"));
+ return NULL;
+ }
+ field = argv[0]->value.string;
+
+ if (argv[1]->type != ESEXP_RES_STRING) {
+ e_sexp_fatal_error (esexp, _("contains? expects argument 2 "
+ "to be a string"));
+ return NULL;
+ }
+ str = argv[1]->value.string;
+
+ /* See if it matches */
+
+ if (strcmp (field, "any") == 0)
+ matches = matches_any (ctx->comp, str);
+ else if (strcmp (field, "comment") == 0)
+ matches = matches_comment (ctx->comp, str);
+ else if (strcmp (field, "description") == 0)
+ matches = matches_description (ctx->comp, str);
+ else if (strcmp (field, "summary") == 0)
+ matches = matches_summary (ctx->comp, str);
+ else {
+ e_sexp_fatal_error (esexp, _("contains? expects argument 1 to "
+ "be one of \"any\", \"summary\", \"description\""));
+ return NULL;
+ }
+
+ result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
+ result->value.bool = matches;
+
+ return result;
+}
+
+/* (has-alarms? #f|#t)
+ *
+ * A boolean value for components that have/dont have alarms.
+ *
+ * Returns: a boolean indicating whether the component has alarms or not.
+ */
+static ESExpResult *
+func_has_alarms (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+{
+ SearchContext *ctx = data;
+ ESExpResult *result;
+ gboolean has_to_have_alarms;
+
+ /* Check argument types */
+
+ if (argc != 1) {
+ e_sexp_fatal_error (esexp, _("has-alarms? expects at least 1 argument"));
+ return NULL;
+ }
+
+ if (argv[0]->type != ESEXP_RES_BOOL) {
+ e_sexp_fatal_error (esexp, _("has-alarms? excepts argument to be a boolean"));
+ return NULL;
+ }
+
+ has_to_have_alarms = argv[0]->value.bool;
+ result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
+
+ if (has_to_have_alarms && cal_component_has_alarms (ctx->comp))
+ result->value.bool = TRUE;
+ else if (!has_to_have_alarms && !cal_component_has_alarms (ctx->comp))
+ result->value.bool = TRUE;
+ else
+ result->value.bool = FALSE;
+
+ return result;
+}
+
+/* (has-categories? STR+)
+ * (has-categories? #f)
+ *
+ * STR - At least one string specifying a category
+ * Or you can specify a single #f (boolean false) value for components
+ * that have no categories assigned to them ("unfiled").
+ *
+ * Returns a boolean indicating whether the component has all the specified
+ * categories.
+ */
+static ESExpResult *
+func_has_categories (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+{
+ SearchContext *ctx = data;
+ gboolean unfiled;
+ int i;
+ GSList *categories;
+ gboolean matches;
+ ESExpResult *result;
+
+ /* Check argument types */
+
+ if (argc < 1) {
+ e_sexp_fatal_error (esexp, _("has-categories? expects at least 1 argument"));
+ return NULL;
+ }
+
+ if (argc == 1 && argv[0]->type == ESEXP_RES_BOOL)
+ unfiled = TRUE;
+ else
+ unfiled = FALSE;
+
+ if (!unfiled)
+ for (i = 0; i < argc; i++)
+ if (argv[i]->type != ESEXP_RES_STRING) {
+ e_sexp_fatal_error (esexp, _("has-categories? expects all arguments "
+ "to be strings or one and only one "
+ "argument to be a boolean false (#f)"));
+ return NULL;
+ }
+
+ /* Search categories. First, if there are no categories we return
+ * whether unfiled components are supposed to match.
+ */
+
+ cal_component_get_categories_list (ctx->comp, &categories);
+ if (!categories) {
+ result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
+ result->value.bool = unfiled;
+
+ return result;
+ }
+
+ /* Otherwise, we *do* have categories but unfiled components were
+ * requested, so this component does not match.
+ */
+ if (unfiled) {
+ result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
+ result->value.bool = FALSE;
+
+ return result;
+ }
+
+ matches = TRUE;
+
+ for (i = 0; i < argc; i++) {
+ const char *sought;
+ GSList *l;
+ gboolean has_category;
+
+ sought = argv[i]->value.string;
+
+ has_category = FALSE;
+
+ for (l = categories; l; l = l->next) {
+ const char *category;
+
+ category = l->data;
+
+ if (strcmp (category, sought) == 0) {
+ has_category = TRUE;
+ break;
+ }
+ }
+
+ if (!has_category) {
+ matches = FALSE;
+ break;
+ }
+ }
+
+ cal_component_free_categories_list (categories);
+
+ result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
+ result->value.bool = matches;
+
+ return result;
+}
+
+/* (is-completed?)
+ *
+ * Returns a boolean indicating whether the component is completed (i.e. has
+ * a COMPLETED property. This is really only useful for TODO components.
+ */
+static ESExpResult *
+func_is_completed (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+{
+ SearchContext *ctx = data;
+ ESExpResult *result;
+ struct icaltimetype *t;
+ gboolean complete = FALSE;
+
+ /* Check argument types */
+
+ if (argc != 0) {
+ e_sexp_fatal_error (esexp, _("is-completed? expects 0 arguments"));
+ return NULL;
+ }
+
+ cal_component_get_completed (ctx->comp, &t);
+ if (t) {
+ complete = TRUE;
+ cal_component_free_icaltimetype (t);
+ }
+
+ result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
+ result->value.bool = complete;
+
+ return result;
+}
+
+/* (completed-before? TIME)
+ *
+ * TIME - time_t
+ *
+ * Returns a boolean indicating whether the component was completed on or
+ * before the given time (i.e. it checks the COMPLETED property).
+ * This is really only useful for TODO components.
+ */
+static ESExpResult *
+func_completed_before (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+{
+ SearchContext *ctx = data;
+ ESExpResult *result;
+ struct icaltimetype *tt;
+ icaltimezone *zone;
+ gboolean retval = FALSE;
+ time_t before_time, completed_time;
+
+ /* Check argument types */
+
+ if (argc != 1) {
+ e_sexp_fatal_error (esexp, _("completed-before? expects 1 argument"));
+ return NULL;
+ }
+
+ if (argv[0]->type != ESEXP_RES_TIME) {
+ e_sexp_fatal_error (esexp, _("completed-before? expects argument 1 "
+ "to be a time_t"));
+ return NULL;
+ }
+ before_time = argv[0]->value.time;
+
+ cal_component_get_completed (ctx->comp, &tt);
+ if (tt) {
+ /* COMPLETED must be in UTC. */
+ zone = icaltimezone_get_utc_timezone ();
+ completed_time = icaltime_as_timet_with_zone (*tt, zone);
+
+#if 0
+ g_print ("Query Time : %s", ctime (&before_time));
+ g_print ("Completed Time: %s", ctime (&completed_time));
+#endif
+
+ /* We want to return TRUE if before_time is after
+ completed_time. */
+ if (difftime (before_time, completed_time) > 0) {
+#if 0
+ g_print (" Returning TRUE\n");
+#endif
+ retval = TRUE;
+ }
+
+ cal_component_free_icaltimetype (tt);
+ }
+
+ result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
+ result->value.bool = retval;
+
+ return result;
+}
+
+#if 0
+static struct prop_info {
+ ECardSimpleField field_id;
+ const char *query_prop;
+ const char *ecard_prop;
+#define PROP_TYPE_NORMAL 0x01
+#define PROP_TYPE_LIST 0x02
+#define PROP_TYPE_LISTITEM 0x03
+#define PROP_TYPE_ID 0x04
+ int prop_type;
+ gboolean (*list_compare)(ECardSimple *ecard, const char *str,
+ char *(*compare)(const char*, const char*));
+
+} prop_info_table[] = {
+#define NORMAL_PROP(f,q,e) {f, q, e, PROP_TYPE_NORMAL, NULL}
+#define ID_PROP {0, "id", NULL, PROP_TYPE_ID, NULL}
+#define LIST_PROP(q,e,c) {0, q, e, PROP_TYPE_LIST, c}
+
+ /* query prop, ecard prop, type, list compare function */
+ NORMAL_PROP ( E_CARD_SIMPLE_FIELD_FILE_AS, "file_as", "file_as" ),
+ LIST_PROP ( "full_name", "full_name", compare_name), /* not really a list, but we need to compare both full and surname */
+ NORMAL_PROP ( E_CARD_SIMPLE_FIELD_URL, "url", "url" ),
+ NORMAL_PROP ( E_CARD_SIMPLE_FIELD_MAILER, "mailer", "mailer"),
+ NORMAL_PROP ( E_CARD_SIMPLE_FIELD_ORG, "org", "org"),
+ NORMAL_PROP ( E_CARD_SIMPLE_FIELD_ORG_UNIT, "org_unit", "org_unit"),
+ NORMAL_PROP ( E_CARD_SIMPLE_FIELD_OFFICE, "office", "office"),
+ NORMAL_PROP ( E_CARD_SIMPLE_FIELD_TITLE, "title", "title"),
+ NORMAL_PROP ( E_CARD_SIMPLE_FIELD_ROLE, "role", "role"),
+ NORMAL_PROP ( E_CARD_SIMPLE_FIELD_MANAGER, "manager", "manager"),
+ NORMAL_PROP ( E_CARD_SIMPLE_FIELD_ASSISTANT, "assistant", "assistant"),
+ NORMAL_PROP ( E_CARD_SIMPLE_FIELD_NICKNAME, "nickname", "nickname"),
+ NORMAL_PROP ( E_CARD_SIMPLE_FIELD_SPOUSE, "spouse", "spouse" ),
+ NORMAL_PROP ( E_CARD_SIMPLE_FIELD_NOTE, "note", "note"),
+ ID_PROP,
+ LIST_PROP ( "email", "email", compare_email ),
+ LIST_PROP ( "phone", "phone", compare_phone ),
+ LIST_PROP ( "address", "address", compare_address ),
+ LIST_PROP ( "category", "category", compare_category ),
+ LIST_PROP ( "arbitrary", "arbitrary", compare_arbitrary )
+};
+static int num_prop_infos = sizeof(prop_info_table) / sizeof(prop_info_table[0]);
+
+static ESExpResult *
+entry_compare(SearchContext *ctx, struct _ESExp *f,
+ int argc, struct _ESExpResult **argv,
+ char *(*compare)(const char*, const char*))
+{
+ ESExpResult *r;
+ int truth = FALSE;
+
+ if (argc == 2
+ && argv[0]->type == ESEXP_RES_STRING
+ && argv[1]->type == ESEXP_RES_STRING) {
+ char *propname;
+ struct prop_info *info = NULL;
+ int i;
+ gboolean any_field;
+
+ propname = argv[0]->value.string;
+
+ any_field = !strcmp(propname, "x-evolution-any-field");
+ for (i = 0; i < num_prop_infos; i ++) {
+ if (any_field
+ || !strcmp (prop_info_table[i].query_prop, propname)) {
+ info = &prop_info_table[i];
+
+ if (info->prop_type == PROP_TYPE_NORMAL) {
+ char *prop = NULL;
+ /* searches where the query's property
+ maps directly to an ecard property */
+
+ prop = e_card_simple_get (ctx->card, info->field_id);
+
+ if (prop && compare(prop, argv[1]->value.string)) {
+ truth = TRUE;
+ }
+ if ((!prop) && compare("", argv[1]->value.string)) {
+ truth = TRUE;
+ }
+ g_free (prop);
+ } else if (info->prop_type == PROP_TYPE_LIST) {
+ /* the special searches that match any of the list elements */
+ truth = info->list_compare (ctx->card, argv[1]->value.string, compare);
+ } else if (info->prop_type == PROP_TYPE_ID) {
+ const char *prop = NULL;
+ /* searches where the query's property
+ maps directly to an ecard property */
+
+ prop = e_card_get_id (ctx->card->card);
+
+ if (prop && compare(prop, argv[1]->value.string)) {
+ truth = TRUE;
+ }
+ if ((!prop) && compare("", argv[1]->value.string)) {
+ truth = TRUE;
+ }
+ }
+
+ /* if we're looking at all fields and find a match,
+ or if we're just looking at this one field,
+ break. */
+ if ((any_field && truth)
+ || !any_field)
+ break;
+ }
+ }
+
+ }
+ r = e_sexp_result_new(f, ESEXP_RES_BOOL);
+ r->value.bool = truth;
+
+ return r;
+}
+#endif
+
+/* 'builtin' functions */
+static struct {
+ char *name;
+ ESExpFunc *func;
+ int type; /* set to 1 if a function can perform shortcut evaluation, or
+ doesn't execute everything, 0 otherwise */
+} symbols[] = {
+ /* Time-related functions */
+ { "time-now", func_time_now, 0 },
+ { "make-time", func_make_time, 0 },
+ { "time-add-day", func_time_add_day, 0 },
+ { "time-day-begin", func_time_day_begin, 0 },
+ { "time-day-end", func_time_day_end, 0 },
+
+ /* Component-related functions */
+ { "get-vtype", func_get_vtype, 0 },
+ { "occur-in-time-range?", func_occur_in_time_range, 0 },
+ { "contains?", func_contains, 0 },
+ { "has-alarms?", func_has_alarms, 0 },
+ { "has-categories?", func_has_categories, 0 },
+ { "is-completed?", func_is_completed, 0 },
+ { "completed-before?", func_completed_before, 0 }
+};
+
+gboolean
+cal_backend_object_sexp_match_comp (CalBackendObjectSExp *sexp, CalComponent *comp, CalBackend *backend)
+{
+ ESExpResult *r;
+ gboolean retval;
+
+ sexp->priv->search_context->comp = g_object_ref (comp);
+ sexp->priv->search_context->backend = g_object_ref (backend);
+
+ /* if it's not a valid vcard why is it in our db? :) */
+ if (!sexp->priv->search_context->comp)
+ return FALSE;
+
+ r = e_sexp_eval(sexp->priv->search_sexp);
+
+ retval = (r && r->type == ESEXP_RES_BOOL && r->value.bool);
+
+ g_object_unref (sexp->priv->search_context->comp);
+ g_object_unref (sexp->priv->search_context->backend);
+
+ e_sexp_result_free(sexp->priv->search_sexp, r);
+
+ return retval;
+}
+
+gboolean
+cal_backend_object_sexp_match_object (CalBackendObjectSExp *sexp, const char *object, CalBackend *backend)
+{
+ CalComponent *comp;
+ icalcomponent *icalcomp;
+ gboolean retval;
+
+ icalcomp = icalcomponent_new_from_string ((char *) object);
+ if (!icalcomp)
+ return FALSE;
+
+ comp = cal_component_new ();
+ cal_component_set_icalcomponent (comp, icalcomp);
+
+ retval = cal_backend_object_sexp_match_comp (sexp, comp, backend);
+
+ g_object_unref (comp);
+
+ return retval;
+}
+
+
+
+/**
+ * cal_backend_card_sexp_new:
+ */
+CalBackendObjectSExp *
+cal_backend_object_sexp_new (const char *text)
+{
+ CalBackendObjectSExp *sexp = g_object_new (CAL_TYPE_BACKEND_OBJECT_SEXP, NULL);
+ int esexp_error;
+ int i;
+
+ sexp->priv->search_sexp = e_sexp_new();
+ sexp->priv->text = g_strdup (text);
+
+ for(i=0;i<sizeof(symbols)/sizeof(symbols[0]);i++) {
+ if (symbols[i].type == 1) {
+ e_sexp_add_ifunction(sexp->priv->search_sexp, 0, symbols[i].name,
+ (ESExpIFunc *)symbols[i].func, sexp->priv->search_context);
+ } else {
+ e_sexp_add_function(sexp->priv->search_sexp, 0, symbols[i].name,
+ symbols[i].func, sexp->priv->search_context);
+ }
+ }
+
+ e_sexp_input_text(sexp->priv->search_sexp, text, strlen(text));
+ esexp_error = e_sexp_parse(sexp->priv->search_sexp);
+
+ if (esexp_error == -1) {
+ g_object_unref (sexp);
+ sexp = NULL;
+ }
+
+ return sexp;
+}
+
+const char *
+cal_backend_object_sexp_text (CalBackendObjectSExp *sexp)
+{
+ CalBackendObjectSExpPrivate *priv;
+
+ g_return_val_if_fail (sexp != NULL, NULL);
+ g_return_val_if_fail (CAL_IS_BACKEND_OBJECT_SEXP (sexp), NULL);
+
+ priv = sexp->priv;
+
+ return priv->text;
+}
+
+static void
+cal_backend_object_sexp_dispose (GObject *object)
+{
+ CalBackendObjectSExp *sexp = CAL_BACKEND_OBJECT_SEXP (object);
+
+ if (sexp->priv) {
+ e_sexp_unref(sexp->priv->search_sexp);
+
+ g_free (sexp->priv->text);
+
+ g_free (sexp->priv->search_context);
+ g_free (sexp->priv);
+ sexp->priv = NULL;
+ }
+
+ if (G_OBJECT_CLASS (parent_class)->dispose)
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+cal_backend_object_sexp_class_init (CalBackendObjectSExpClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ /* Set the virtual methods. */
+
+ object_class->dispose = cal_backend_object_sexp_dispose;
+}
+
+static void
+cal_backend_object_sexp_init (CalBackendObjectSExp *sexp)
+{
+ CalBackendObjectSExpPrivate *priv;
+
+ priv = g_new0 (CalBackendObjectSExpPrivate, 1);
+
+ sexp->priv = priv;
+ priv->search_context = g_new (SearchContext, 1);
+}
+
+/**
+ * cal_backend_object_sexp_get_type:
+ */
+GType
+cal_backend_object_sexp_get_type (void)
+{
+ static GType type = 0;
+
+ if (! type) {
+ GTypeInfo info = {
+ sizeof (CalBackendObjectSExpClass),
+ NULL, /* base_class_init */
+ NULL, /* base_class_finalize */
+ (GClassInitFunc) cal_backend_object_sexp_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (CalBackendObjectSExp),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) cal_backend_object_sexp_init
+ };
+
+ type = g_type_register_static (G_TYPE_OBJECT, "CalBackendObjectSExp", &info, 0);
+ }
+
+ return type;
+}
diff --git a/calendar/pcs/cal-backend-object-sexp.h b/calendar/pcs/cal-backend-object-sexp.h
new file mode 100644
index 0000000000..dbac3b6abc
--- /dev/null
+++ b/calendar/pcs/cal-backend-object-sexp.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * cal-backend-card-sexp.h
+ * Copyright 2000, 2001, Ximian, Inc.
+ *
+ * Authors:
+ * Chris Lahey <clahey@ximian.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __CAL_BACKEND_OBJECT_SEXP_H__
+#define __CAL_BACKEND_OBJECT_SEXP_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <pcs/cal-backend.h>
+#include <cal-util/cal-component.h>
+
+G_BEGIN_DECLS
+
+#define CAL_TYPE_BACKEND_OBJECT_SEXP (cal_backend_object_sexp_get_type ())
+#define CAL_BACKEND_OBJECT_SEXP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CAL_TYPE_BACKEND_OBJECT_SEXP, CalBackendObjectSExp))
+#define CAL_BACKEND_OBJECT_SEXP_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CAL_BACKEND_TYPE, CalBackendObjectSExpClass))
+#define CAL_IS_BACKEND_OBJECT_SEXP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CAL_TYPE_BACKEND_OBJECT_SEXP))
+#define CAL_IS_BACKEND_OBJECT_SEXP_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CAL_TYPE_BACKEND_OBJECT_SEXP))
+#define CAL_BACKEND_OBJECT_SEXP_GET_CLASS(k) (G_TYPE_INSTANCE_GET_CLASS ((obj), CAL_TYPE_BACKEND_OBJECT_SEXP, CALBackendObjectSExpClass))
+
+typedef struct _CalBackendObjectSExpPrivate CalBackendObjectSExpPrivate;
+
+struct _CalBackendObjectSExp {
+ GObject parent_object;
+
+ CalBackendObjectSExpPrivate *priv;
+};
+
+struct _CalBackendObjectSExpClass {
+ GObjectClass parent_class;
+};
+
+GType cal_backend_object_sexp_get_type (void);
+CalBackendObjectSExp *cal_backend_object_sexp_new (const char *text);
+const char *cal_backend_object_sexp_text (CalBackendObjectSExp *sexp);
+
+
+gboolean cal_backend_object_sexp_match_object (CalBackendObjectSExp *sexp,
+ const char *object,
+ CalBackend *backend);
+gboolean cal_backend_object_sexp_match_comp (CalBackendObjectSExp *sexp,
+ CalComponent *comp,
+ CalBackend *backend);
+
+G_END_DECLS
+
+#endif /* __CAL_BACKEND_OBJECT_SEXP_H__ */
diff --git a/calendar/pcs/cal-backend-sync.c b/calendar/pcs/cal-backend-sync.c
new file mode 100644
index 0000000000..2a807ef689
--- /dev/null
+++ b/calendar/pcs/cal-backend-sync.c
@@ -0,0 +1,611 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Author:
+ * Chris Toshok (toshok@ximian.com)
+ *
+ * Copyright (C) 2003, Ximian, Inc.
+ */
+
+#ifdef CONFIG_H
+#include <config.h>
+#endif
+
+#include "cal-backend-sync.h"
+
+struct _CalBackendSyncPrivate {
+ int mumble;
+};
+
+static GObjectClass *parent_class;
+
+G_LOCK_DEFINE_STATIC (cal_sync_mutex);
+#define SYNC_LOCK() G_LOCK (cal_sync_mutex)
+#define SYNC_UNLOCK() G_UNLOCK (cal_sync_mutex)
+
+CalBackendSyncStatus
+cal_backend_sync_is_read_only (CalBackendSync *backend, Cal *cal, gboolean *read_only)
+{
+ g_return_val_if_fail (backend && CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+ g_return_val_if_fail (read_only, GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->is_read_only_sync);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->is_read_only_sync) (backend, cal, read_only);
+}
+
+CalBackendSyncStatus
+cal_backend_sync_get_cal_address (CalBackendSync *backend, Cal *cal, char **address)
+{
+ g_return_val_if_fail (backend && CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+ g_return_val_if_fail (address, GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->get_cal_address_sync);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->get_cal_address_sync) (backend, cal, address);
+}
+
+CalBackendSyncStatus
+cal_backend_sync_get_alarm_email_address (CalBackendSync *backend, Cal *cal, char **address)
+{
+ g_return_val_if_fail (backend && CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+ g_return_val_if_fail (address, GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->get_alarm_email_address_sync);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->get_alarm_email_address_sync) (backend, cal, address);
+}
+
+CalBackendSyncStatus
+cal_backend_sync_get_ldap_attribute (CalBackendSync *backend, Cal *cal, char **attribute)
+{
+ g_return_val_if_fail (backend && CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+ g_return_val_if_fail (attribute, GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->get_ldap_attribute_sync);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->get_ldap_attribute_sync) (backend, cal, attribute);
+}
+
+CalBackendSyncStatus
+cal_backend_sync_get_static_capabilities (CalBackendSync *backend, Cal *cal, char **capabilities)
+{
+ g_return_val_if_fail (backend && CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+ g_return_val_if_fail (capabilities, GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->get_static_capabilities_sync);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->get_static_capabilities_sync) (backend, cal, capabilities);
+}
+
+CalBackendSyncStatus
+cal_backend_sync_open (CalBackendSync *backend, Cal *cal, gboolean only_if_exists)
+{
+ CalBackendSyncStatus status;
+
+ g_return_val_if_fail (backend && CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->open_sync);
+
+ SYNC_LOCK ();
+
+ status = (* CAL_BACKEND_SYNC_GET_CLASS (backend)->open_sync) (backend, cal, only_if_exists);
+
+ SYNC_UNLOCK ();
+
+ return status;
+}
+
+CalBackendSyncStatus
+cal_backend_sync_remove (CalBackendSync *backend, Cal *cal)
+{
+ g_return_val_if_fail (backend && CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->remove_sync);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->remove_sync) (backend, cal);
+}
+
+CalBackendSyncStatus
+cal_backend_sync_create_object (CalBackendSync *backend, Cal *cal, const char *calobj, char **uid)
+{
+ g_return_val_if_fail (backend && CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->create_object_sync);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->create_object_sync) (backend, cal, calobj, uid);
+}
+
+CalBackendSyncStatus
+cal_backend_sync_modify_object (CalBackendSync *backend, Cal *cal, const char *calobj,
+ CalObjModType mod, char **old_object)
+{
+ g_return_val_if_fail (backend && CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->modify_object_sync);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->modify_object_sync) (backend, cal,
+ calobj, mod, old_object);
+}
+
+CalBackendSyncStatus
+cal_backend_sync_remove_object (CalBackendSync *backend, Cal *cal, const char *uid, const char *rid,
+ CalObjModType mod, char **object)
+{
+ g_return_val_if_fail (backend && CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->remove_object_sync);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->remove_object_sync) (backend, cal, uid, rid, mod, object);
+}
+
+CalBackendSyncStatus
+cal_backend_sync_discard_alarm (CalBackendSync *backend, Cal *cal, const char *uid, const char *auid)
+{
+ g_return_val_if_fail (backend && CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->discard_alarm_sync);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->discard_alarm_sync) (backend, cal, uid, auid);
+}
+
+CalBackendSyncStatus
+cal_backend_sync_receive_objects (CalBackendSync *backend, Cal *cal, const char *calobj,
+ GList **created, GList **modified, GList **removed)
+{
+ g_return_val_if_fail (backend && CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->receive_objects_sync);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->receive_objects_sync) (backend, cal, calobj,
+ created, modified, removed);
+}
+
+CalBackendSyncStatus
+cal_backend_sync_send_objects (CalBackendSync *backend, Cal *cal, const char *calobj)
+{
+ g_return_val_if_fail (backend && CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->send_objects_sync);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->send_objects_sync) (backend, cal, calobj);
+}
+
+CalBackendSyncStatus
+cal_backend_sync_get_default_object (CalBackendSync *backend, Cal *cal, char **object)
+{
+ g_return_val_if_fail (backend && CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+ g_return_val_if_fail (object, GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->get_default_object_sync);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->get_default_object_sync) (backend, cal, object);
+}
+
+CalBackendSyncStatus
+cal_backend_sync_get_object (CalBackendSync *backend, Cal *cal, const char *uid, const char *rid, char **object)
+{
+ g_return_val_if_fail (backend && CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+ g_return_val_if_fail (object, GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->get_object_sync);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->get_object_sync) (backend, cal, uid, rid, object);
+}
+
+CalBackendSyncStatus
+cal_backend_sync_get_object_list (CalBackendSync *backend, Cal *cal, const char *sexp, GList **objects)
+{
+ g_return_val_if_fail (backend && CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+ g_return_val_if_fail (objects, GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->get_object_list_sync);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->get_object_list_sync) (backend, cal, sexp, objects);
+}
+
+CalBackendSyncStatus
+cal_backend_sync_get_timezone (CalBackendSync *backend, Cal *cal, const char *tzid, char **object)
+{
+ g_return_val_if_fail (CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->get_timezone_sync != NULL);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->get_timezone_sync) (backend, cal, tzid, object);
+}
+
+CalBackendSyncStatus
+cal_backend_sync_add_timezone (CalBackendSync *backend, Cal *cal, const char *tzobj)
+{
+ g_return_val_if_fail (CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->add_timezone_sync != NULL);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->add_timezone_sync) (backend, cal, tzobj);
+}
+
+CalBackendSyncStatus
+cal_backend_sync_set_default_timezone (CalBackendSync *backend, Cal *cal, const char *tzid)
+{
+ g_return_val_if_fail (CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->set_default_timezone_sync != NULL);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->set_default_timezone_sync) (backend, cal, tzid);
+}
+
+
+CalBackendSyncStatus
+cal_backend_sync_get_changes (CalBackendSync *backend, Cal *cal, CalObjType type, const char *change_id,
+ GList **adds, GList **modifies, GList **deletes)
+{
+ g_return_val_if_fail (CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->get_changes_sync != NULL);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->get_changes_sync) (backend, cal, type, change_id,
+ adds, modifies, deletes);
+}
+
+CalBackendSyncStatus
+cal_backend_sync_get_free_busy (CalBackendSync *backend, Cal *cal, GList *users,
+ time_t start, time_t end, GList **freebusy)
+{
+ g_return_val_if_fail (CAL_IS_BACKEND_SYNC (backend), GNOME_Evolution_Calendar_OtherError);
+
+ g_assert (CAL_BACKEND_SYNC_GET_CLASS (backend)->get_freebusy_sync != NULL);
+
+ return (* CAL_BACKEND_SYNC_GET_CLASS (backend)->get_freebusy_sync) (backend, cal, users,
+ start, end, freebusy);
+}
+
+
+static void
+_cal_backend_is_read_only (CalBackend *backend, Cal *cal)
+{
+ CalBackendSyncStatus status;
+ gboolean read_only;
+
+ status = cal_backend_sync_is_read_only (CAL_BACKEND_SYNC (backend), cal, &read_only);
+
+ cal_notify_read_only (cal, status, read_only);
+}
+
+static void
+_cal_backend_get_cal_address (CalBackend *backend, Cal *cal)
+{
+ CalBackendSyncStatus status;
+ char *address;
+
+ status = cal_backend_sync_get_cal_address (CAL_BACKEND_SYNC (backend), cal, &address);
+
+ cal_notify_cal_address (cal, status, address);
+
+ g_free (address);
+}
+
+static void
+_cal_backend_get_alarm_email_address (CalBackend *backend, Cal *cal)
+{
+ CalBackendSyncStatus status;
+ char *address;
+
+ status = cal_backend_sync_get_cal_address (CAL_BACKEND_SYNC (backend), cal, &address);
+
+ cal_notify_alarm_email_address (cal, status, address);
+
+ g_free (address);
+}
+
+static void
+_cal_backend_get_ldap_attribute (CalBackend *backend, Cal *cal)
+{
+ CalBackendSyncStatus status;
+ char *attribute;
+
+ status = cal_backend_sync_get_cal_address (CAL_BACKEND_SYNC (backend), cal, &attribute);
+
+ cal_notify_ldap_attribute (cal, status, attribute);
+
+ g_free (attribute);
+}
+
+static void
+_cal_backend_get_static_capabilities (CalBackend *backend, Cal *cal)
+{
+ CalBackendSyncStatus status;
+ char *capabilities;
+
+ status = cal_backend_sync_get_cal_address (CAL_BACKEND_SYNC (backend), cal, &capabilities);
+
+ cal_notify_static_capabilities (cal, status, capabilities);
+
+ g_free (capabilities);
+}
+
+static void
+_cal_backend_open (CalBackend *backend, Cal *cal, gboolean only_if_exists)
+{
+ CalBackendSyncStatus status;
+
+ status = cal_backend_sync_open (CAL_BACKEND_SYNC (backend), cal, only_if_exists);
+
+ cal_notify_open (cal, status);
+}
+
+static void
+_cal_backend_remove (CalBackend *backend, Cal *cal)
+{
+ CalBackendSyncStatus status;
+
+ status = cal_backend_sync_remove (CAL_BACKEND_SYNC (backend), cal);
+
+ cal_notify_remove (cal, status);
+}
+
+static void
+_cal_backend_create_object (CalBackend *backend, Cal *cal, const char *calobj)
+{
+ CalBackendSyncStatus status;
+ char *uid = NULL;
+
+ status = cal_backend_sync_create_object (CAL_BACKEND_SYNC (backend), cal, calobj, &uid);
+
+ cal_notify_object_created (cal, status, uid, calobj);
+
+ if (uid)
+ g_free (uid);
+}
+
+static void
+_cal_backend_modify_object (CalBackend *backend, Cal *cal, const char *calobj, CalObjModType mod)
+{
+ CalBackendSyncStatus status;
+ char *old_object;
+
+ status = cal_backend_sync_modify_object (CAL_BACKEND_SYNC (backend), cal,
+ calobj, mod, &old_object);
+
+ cal_notify_object_modified (cal, status, old_object, calobj);
+}
+
+static void
+_cal_backend_remove_object (CalBackend *backend, Cal *cal, const char *uid, const char *rid, CalObjModType mod)
+{
+ CalBackendSyncStatus status;
+ char *object;
+
+ status = cal_backend_sync_remove_object (CAL_BACKEND_SYNC (backend), cal, uid, rid, mod, &object);
+
+ cal_notify_object_removed (cal, status, uid, object);
+}
+
+static void
+_cal_backend_discard_alarm (CalBackend *backend, Cal *cal, const char *uid, const char *auid)
+{
+ CalBackendSyncStatus status;
+
+ status = cal_backend_sync_discard_alarm (CAL_BACKEND_SYNC (backend), cal, uid, auid);
+
+ cal_notify_alarm_discarded (cal, status);
+}
+
+static void
+_cal_backend_receive_objects (CalBackend *backend, Cal *cal, const char *calobj)
+{
+ CalBackendSyncStatus status;
+ GList *created = NULL, *modified = NULL, *removed = NULL;
+
+ status = cal_backend_sync_receive_objects (CAL_BACKEND_SYNC (backend), cal, calobj,
+ &created, &modified, &removed);
+
+ cal_notify_objects_received (cal, status, created, modified, removed);
+}
+
+static void
+_cal_backend_send_objects (CalBackend *backend, Cal *cal, const char *calobj)
+{
+ CalBackendSyncStatus status;
+
+ status = cal_backend_sync_send_objects (CAL_BACKEND_SYNC (backend), cal, calobj);
+
+ cal_notify_objects_sent (cal, status);
+}
+
+static void
+_cal_backend_get_default_object (CalBackend *backend, Cal *cal)
+{
+ CalBackendSyncStatus status;
+ char *object = NULL;
+
+ status = cal_backend_sync_get_default_object (CAL_BACKEND_SYNC (backend), cal, &object);
+
+ cal_notify_default_object (cal, status, object);
+
+ g_free (object);
+}
+
+static void
+_cal_backend_get_object (CalBackend *backend, Cal *cal, const char *uid, const char *rid)
+{
+ CalBackendSyncStatus status;
+ char *object = NULL;
+
+ status = cal_backend_sync_get_object (CAL_BACKEND_SYNC (backend), cal, uid, rid, &object);
+
+ cal_notify_object (cal, status, object);
+
+ g_free (object);
+}
+
+static void
+_cal_backend_get_object_list (CalBackend *backend, Cal *cal, const char *sexp)
+{
+ CalBackendSyncStatus status;
+ GList *objects, *l;
+
+ status = cal_backend_sync_get_object_list (CAL_BACKEND_SYNC (backend), cal, sexp, &objects);
+
+ cal_notify_object_list (cal, status, objects);
+
+ for (l = objects; l; l = l->next)
+ g_free (l->data);
+ g_list_free (objects);
+}
+
+static void
+_cal_backend_get_timezone (CalBackend *backend, Cal *cal, const char *tzid)
+{
+ CalBackendSyncStatus status;
+ char *object = NULL;
+
+ status = cal_backend_sync_get_timezone (CAL_BACKEND_SYNC (backend), cal, tzid, &object);
+
+ cal_notify_timezone_requested (cal, status, object);
+}
+
+static void
+_cal_backend_add_timezone (CalBackend *backend, Cal *cal, const char *tzobj)
+{
+ CalBackendSyncStatus status;
+
+ status = cal_backend_sync_add_timezone (CAL_BACKEND_SYNC (backend), cal, tzobj);
+
+ cal_notify_timezone_added (cal, status, tzobj);
+}
+
+static void
+_cal_backend_set_default_timezone (CalBackend *backend, Cal *cal, const char *tzid)
+{
+ CalBackendSyncStatus status;
+
+ status = cal_backend_sync_set_default_timezone (CAL_BACKEND_SYNC (backend), cal, tzid);
+
+ cal_notify_default_timezone_set (cal, status);
+}
+
+static void
+_cal_backend_get_changes (CalBackend *backend, Cal *cal, CalObjType type, const char *change_id)
+{
+ CalBackendSyncStatus status;
+ GList *adds = NULL, *modifies = NULL, *deletes = NULL, *l;
+
+ status = cal_backend_sync_get_changes (CAL_BACKEND_SYNC (backend), cal, type, change_id,
+ &adds, &modifies, &deletes);
+
+ cal_notify_changes (cal, status, adds, modifies, deletes);
+
+ for (l = adds; l; l = l->next)
+ g_free (l->data);
+ g_list_free (adds);
+
+ for (l = modifies; l; l = l->next)
+ g_free (l->data);
+ g_list_free (modifies);
+
+ for (l = deletes; l; l = l->next)
+ g_free (l->data);
+ g_list_free (deletes);
+}
+
+static void
+_cal_backend_get_free_busy (CalBackend *backend, Cal *cal, GList *users, time_t start, time_t end)
+{
+ CalBackendSyncStatus status;
+ GList *freebusy = NULL, *l;
+
+ status = cal_backend_sync_get_free_busy (CAL_BACKEND_SYNC (backend), cal, users, start, end, &freebusy);
+
+ cal_notify_free_busy (cal, status, freebusy);
+
+ for (l = freebusy; l; l = l->next)
+ g_free (l->data);
+ g_list_free (freebusy);
+}
+
+static void
+cal_backend_sync_init (CalBackendSync *backend)
+{
+ CalBackendSyncPrivate *priv;
+
+ priv = g_new0 (CalBackendSyncPrivate, 1);
+
+ backend->priv = priv;
+}
+
+static void
+cal_backend_sync_dispose (GObject *object)
+{
+ CalBackendSync *backend;
+
+ backend = CAL_BACKEND_SYNC (object);
+
+ if (backend->priv) {
+ g_free (backend->priv);
+
+ backend->priv = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+cal_backend_sync_class_init (CalBackendSyncClass *klass)
+{
+ GObjectClass *object_class;
+ CalBackendClass *backend_class = CAL_BACKEND_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class = (GObjectClass *) klass;
+
+ backend_class->is_read_only = _cal_backend_is_read_only;
+ backend_class->get_cal_address = _cal_backend_get_cal_address;
+ backend_class->get_alarm_email_address = _cal_backend_get_alarm_email_address;
+ backend_class->get_ldap_attribute = _cal_backend_get_ldap_attribute;
+ backend_class->get_static_capabilities = _cal_backend_get_static_capabilities;
+ backend_class->open = _cal_backend_open;
+ backend_class->remove = _cal_backend_remove;
+ backend_class->create_object = _cal_backend_create_object;
+ backend_class->modify_object = _cal_backend_modify_object;
+ backend_class->remove_object = _cal_backend_remove_object;
+ backend_class->discard_alarm = _cal_backend_discard_alarm;
+ backend_class->receive_objects = _cal_backend_receive_objects;
+ backend_class->send_objects = _cal_backend_send_objects;
+ backend_class->get_default_object = _cal_backend_get_default_object;
+ backend_class->get_object = _cal_backend_get_object;
+ backend_class->get_object_list = _cal_backend_get_object_list;
+ backend_class->get_timezone = _cal_backend_get_timezone;
+ backend_class->add_timezone = _cal_backend_add_timezone;
+ backend_class->set_default_timezone = _cal_backend_set_default_timezone;
+ backend_class->get_changes = _cal_backend_get_changes;
+ backend_class->get_free_busy = _cal_backend_get_free_busy;
+
+ object_class->dispose = cal_backend_sync_dispose;
+}
+
+/**
+ * cal_backend_get_type:
+ */
+GType
+cal_backend_sync_get_type (void)
+{
+ static GType type = 0;
+
+ if (! type) {
+ GTypeInfo info = {
+ sizeof (CalBackendSyncClass),
+ NULL, /* base_class_init */
+ NULL, /* base_class_finalize */
+ (GClassInitFunc) cal_backend_sync_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (CalBackendSync),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) cal_backend_sync_init
+ };
+
+ type = g_type_register_static (CAL_BACKEND_TYPE, "CalBackendSync", &info, 0);
+ }
+
+ return type;
+}
diff --git a/calendar/pcs/cal-backend-sync.h b/calendar/pcs/cal-backend-sync.h
new file mode 100644
index 0000000000..ead49fa4b7
--- /dev/null
+++ b/calendar/pcs/cal-backend-sync.h
@@ -0,0 +1,146 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ */
+
+#ifndef __Cal_BACKEND_SYNC_H__
+#define __Cal_BACKEND_SYNC_H__
+
+#include <glib.h>
+#include <pcs/cal-backend.h>
+#include <pcs/evolution-calendar.h>
+
+G_BEGIN_DECLS
+
+#define CAL_TYPE_BACKEND_SYNC (cal_backend_sync_get_type ())
+#define CAL_BACKEND_SYNC(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CAL_TYPE_BACKEND_SYNC, CalBackendSync))
+#define CAL_BACKEND_SYNC_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CAL_TYPE_BACKEND_SYNC, CalBackendSyncClass))
+#define CAL_IS_BACKEND_SYNC(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CAL_TYPE_BACKEND_SYNC))
+#define CAL_IS_BACKEND_SYNC_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CAL_TYPE_BACKEND_SYNC))
+#define CAL_BACKEND_SYNC_GET_CLASS(k) (G_TYPE_INSTANCE_GET_CLASS ((k), CAL_TYPE_BACKEND_SYNC, CalBackendSyncClass))
+typedef struct _CalBackendSync CalBackendSync;
+typedef struct _CalBackendSyncClass CalBackendSyncClass;
+typedef struct _CalBackendSyncPrivate CalBackendSyncPrivate;
+
+typedef GNOME_Evolution_Calendar_CallStatus CalBackendSyncStatus;
+
+struct _CalBackendSync {
+ CalBackend parent_object;
+
+ CalBackendSyncPrivate *priv;
+};
+
+struct _CalBackendSyncClass {
+ CalBackendClass parent_class;
+
+ /* Virtual methods */
+ CalBackendSyncStatus (*is_read_only_sync) (CalBackendSync *backend, Cal *cal, gboolean *read_only);
+ CalBackendSyncStatus (*get_cal_address_sync) (CalBackendSync *backend, Cal *cal, char **address);
+ CalBackendSyncStatus (*get_alarm_email_address_sync) (CalBackendSync *backend, Cal *cal, char **address);
+ CalBackendSyncStatus (*get_ldap_attribute_sync) (CalBackendSync *backend, Cal *cal, char **attribute);
+ CalBackendSyncStatus (*get_static_capabilities_sync) (CalBackendSync *backend, Cal *cal, char **capabilities);
+
+ CalBackendSyncStatus (*open_sync) (CalBackendSync *backend, Cal *cal, gboolean only_if_exists);
+ CalBackendSyncStatus (*remove_sync) (CalBackendSync *backend, Cal *cal);
+
+ CalBackendSyncStatus (*create_object_sync) (CalBackendSync *backend, Cal *cal, const char *calobj, char **uid);
+ CalBackendSyncStatus (*modify_object_sync) (CalBackendSync *backend, Cal *cal, const char *calobj, CalObjModType mod, char **old_object);
+ CalBackendSyncStatus (*remove_object_sync) (CalBackendSync *backend, Cal *cal, const char *uid, const char *rid, CalObjModType mod, char **object);
+
+ CalBackendSyncStatus (*discard_alarm_sync) (CalBackendSync *backend, Cal *cal, const char *uid, const char *auid);
+
+ CalBackendSyncStatus (*receive_objects_sync) (CalBackendSync *backend, Cal *cal, const char *calobj, GList **created, GList **modified, GList **removed);
+ CalBackendSyncStatus (*send_objects_sync) (CalBackendSync *backend, Cal *cal, const char *calobj);
+
+ CalBackendSyncStatus (*get_default_object_sync) (CalBackendSync *backend, Cal *cal, char **object);
+ CalBackendSyncStatus (*get_object_sync) (CalBackendSync *backend, Cal *cal, const char *uid, const char *rid, char **object);
+ CalBackendSyncStatus (*get_object_list_sync) (CalBackendSync *backend, Cal *cal, const char *sexp, GList **objects);
+
+ CalBackendSyncStatus (*get_timezone_sync) (CalBackendSync *backend, Cal *cal, const char *tzid, char **object);
+ CalBackendSyncStatus (*add_timezone_sync) (CalBackendSync *backend, Cal *cal, const char *tzobj);
+ CalBackendSyncStatus (*set_default_timezone_sync) (CalBackendSync *backend, Cal *cal, const char *tzid);
+
+ CalBackendSyncStatus (*get_changes_sync) (CalBackendSync *backend, Cal *cal, CalObjType type, const char *change_id, GList **adds, GList **modifies, GList **deletes);
+ CalBackendSyncStatus (*get_freebusy_sync) (CalBackendSync *backend, Cal *cal, GList *users, time_t start, time_t end, GList **freebusy);
+
+ /* Padding for future expansion */
+ void (*_cal_reserved0) (void);
+ void (*_cal_reserved1) (void);
+ void (*_cal_reserved2) (void);
+ void (*_cal_reserved3) (void);
+ void (*_cal_reserved4) (void);
+
+};
+
+typedef CalBackendSync * (*CalBackendSyncFactoryFn) (void);
+GType cal_backend_sync_get_type (void);
+CalBackendSyncStatus cal_backend_sync_is_read_only (CalBackendSync *backend,
+ Cal *cal,
+ gboolean *read_only);
+CalBackendSyncStatus cal_backend_sync_get_cal_address (CalBackendSync *backend,
+ Cal *cal,
+ char **address);
+CalBackendSyncStatus cal_backend_sync_get_alarm_email_address (CalBackendSync *backend,
+ Cal *cal,
+ char **address);
+CalBackendSyncStatus cal_backend_sync_get_ldap_attribute (CalBackendSync *backend,
+ Cal *cal,
+ char **attribute);
+CalBackendSyncStatus cal_backend_sync_get_static_capabilities (CalBackendSync *backend,
+ Cal *cal,
+ char **capabiliites);
+CalBackendSyncStatus cal_backend_sync_open (CalBackendSync *backend,
+ Cal *cal,
+ gboolean only_if_exists);
+CalBackendSyncStatus cal_backend_sync_remove (CalBackendSync *backend,
+ Cal *cal);
+CalBackendSyncStatus cal_backend_sync_create_object (CalBackendSync *backend,
+ Cal *cal,
+ const char *calobj,
+ char **uid);
+CalBackendSyncStatus cal_backend_sync_modify_object (CalBackendSync *backend,
+ Cal *cal,
+ const char *calobj,
+ CalObjModType mod,
+ char **old_object);
+CalBackendSyncStatus cal_backend_sync_remove_object (CalBackendSync *backend,
+ Cal *cal,
+ const char *uid,
+ const char *rid,
+ CalObjModType mod,
+ char **object);
+CalBackendSyncStatus cal_backend_sync_discard_alarm (CalBackendSync *backend, Cal *cal, const char *uid, const char *auid);
+
+CalBackendSyncStatus cal_backend_sync_receive_objects (CalBackendSync *backend,
+ Cal *cal,
+ const char *calobj,
+ GList **created,
+ GList **modified,
+ GList **removed);
+CalBackendSyncStatus cal_backend_sync_send_objects (CalBackendSync *backend,
+ Cal *cal,
+ const char *calobj);
+CalBackendSyncStatus cal_backend_sync_get_default_object (CalBackendSync *backend,
+ Cal *cal,
+ char **object);
+
+CalBackendSyncStatus cal_backend_sync_get_object (CalBackendSync *backend,
+ Cal *cal,
+ const char *uid,
+ const char *rid,
+ char **object);
+
+CalBackendSyncStatus cal_backend_sync_get_object_list (CalBackendSync *backend,
+ Cal *cal,
+ const char *sexp,
+ GList **objects);
+
+CalBackendSyncStatus cal_backend_sync_get_timezone (CalBackendSync *backend, Cal *cal, const char *tzid, char **object);
+CalBackendSyncStatus cal_backend_sync_add_timezone (CalBackendSync *backend, Cal *cal, const char *tzobj);
+CalBackendSyncStatus cal_backend_sync_set_default_timezone (CalBackendSync *backend, Cal *cal, const char *tzid);
+
+CalBackendSyncStatus cal_backend_sync_get_changes (CalBackendSync *backend, Cal *cal, CalObjType type, const char *change_id, GList **adds, GList **modifies, GList **deletes);
+CalBackendSyncStatus cal_backend_sync_get_free_busy (CalBackendSync *backend, Cal *cal, GList *users, time_t start, time_t end, GList **freebusy);
+
+G_END_DECLS
+
+#endif /* ! __CAL_BACKEND_SYNC_H__ */
diff --git a/calendar/pcs/cal-backend-util.c b/calendar/pcs/cal-backend-util.c
index ad39bfcc38..86bf761878 100644
--- a/calendar/pcs/cal-backend-util.c
+++ b/calendar/pcs/cal-backend-util.c
@@ -26,36 +26,6 @@
static EAccountList *accounts;
-void
-cal_backend_util_fill_alarm_instances_seq (GNOME_Evolution_Calendar_CalAlarmInstanceSeq *seq,
- GSList *alarms)
-{
- int n_alarms;
- GSList *l;
- int i;
-
- g_return_if_fail (seq != NULL);
-
- n_alarms = g_slist_length (alarms);
-
- CORBA_sequence_set_release (seq, TRUE);
- seq->_length = n_alarms;
- seq->_buffer = CORBA_sequence_GNOME_Evolution_Calendar_CalAlarmInstance_allocbuf (n_alarms);
-
- for (l = alarms, i = 0; l; l = l->next, i++) {
- CalAlarmInstance *instance;
- GNOME_Evolution_Calendar_CalAlarmInstance *corba_instance;
-
- instance = l->data;
- corba_instance = seq->_buffer + i;
-
- corba_instance->auid = CORBA_string_dup (instance->auid);
- corba_instance->trigger = (long) instance->trigger;
- corba_instance->occur_start = (long) instance->occur_start;
- corba_instance->occur_end = (long) instance->occur_end;
- }
-}
-
gboolean
cal_backend_mail_account_get_default (EConfigListener *db,
char **address,
diff --git a/calendar/pcs/cal-backend-util.h b/calendar/pcs/cal-backend-util.h
index 6ce9d59807..228179b8c7 100644
--- a/calendar/pcs/cal-backend-util.h
+++ b/calendar/pcs/cal-backend-util.h
@@ -29,13 +29,6 @@
G_BEGIN_DECLS
/*
- * CORBA utility functions
- */
-
-void cal_backend_util_fill_alarm_instances_seq (
- GNOME_Evolution_Calendar_CalAlarmInstanceSeq *seq, GSList *alarms);
-
-/*
* Functions for accessing mail configuration
*/
diff --git a/calendar/pcs/cal-backend.c b/calendar/pcs/cal-backend.c
index 1d6330346c..ae5be6829e 100644
--- a/calendar/pcs/cal-backend.c
+++ b/calendar/pcs/cal-backend.c
@@ -43,9 +43,19 @@ typedef struct {
/* Private part of the CalBackend structure */
struct _CalBackendPrivate {
- /* List of Cal objects with their listeners */
+ /* The uri for this backend */
+ char *uri;
+
+ /* The kind of components for this backend */
+ icalcomponent_kind kind;
+
+ /* List of Cal objects */
+ GMutex *clients_mutex;
GList *clients;
+ GMutex *queries_mutex;
+ EList *queries;
+
/* Hash table of live categories, temporary hash of
* added/removed categories, and idle handler for sending
* category_changed.
@@ -55,13 +65,18 @@ struct _CalBackendPrivate {
guint category_idle_id;
};
+/* Property IDs */
+enum props {
+ PROP_0,
+ PROP_URI,
+ PROP_KIND
+};
+
/* Signal IDs */
enum {
LAST_CLIENT_GONE,
- CAL_ADDED,
OPENED,
- OBJ_UPDATED,
- OBJ_REMOVED,
+ REMOVED,
LAST_SIGNAL
};
static guint cal_backend_signals[LAST_SIGNAL];
@@ -70,8 +85,6 @@ static void cal_backend_class_init (CalBackendClass *class);
static void cal_backend_init (CalBackend *backend);
static void cal_backend_finalize (GObject *object);
-static char *get_object (CalBackend *backend, const char *uid);
-
static void notify_categories_changed (CalBackend *backend);
#define CLASS(backend) (CAL_BACKEND_CLASS (G_OBJECT_GET_CLASS (backend)))
@@ -111,6 +124,51 @@ cal_backend_get_type (void)
return cal_backend_type;
}
+static void
+cal_backend_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+ CalBackend *backend;
+ CalBackendPrivate *priv;
+
+ backend = CAL_BACKEND (object);
+ priv = backend->priv;
+
+ switch (property_id) {
+ case PROP_URI:
+ g_free (priv->uri);
+ priv->uri = g_value_dup_string (value);
+ break;
+ case PROP_KIND:
+ priv->kind = g_value_get_ulong (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+cal_backend_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+ CalBackend *backend;
+ CalBackendPrivate *priv;
+
+ backend = CAL_BACKEND (object);
+ priv = backend->priv;
+
+ switch (property_id) {
+ case PROP_URI:
+ g_value_set_string (value, cal_backend_get_uri (backend));
+ break;
+ case PROP_KIND:
+ g_value_set_ulong (value, cal_backend_get_kind (backend));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
/* Class initialization function for the calendar backend */
static void
cal_backend_class_init (CalBackendClass *class)
@@ -121,6 +179,21 @@ cal_backend_class_init (CalBackendClass *class)
object_class = (GObjectClass *) class;
+ object_class->set_property = cal_backend_set_property;
+ object_class->get_property = cal_backend_get_property;
+ object_class->finalize = cal_backend_finalize;
+
+ g_object_class_install_property (object_class, PROP_URI,
+ g_param_spec_string ("uri", NULL, NULL, "",
+ G_PARAM_READABLE | G_PARAM_WRITABLE
+ | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class, PROP_KIND,
+ g_param_spec_ulong ("kind", NULL, NULL,
+ ICAL_NO_COMPONENT, ICAL_XLICMIMEPART_COMPONENT,
+ ICAL_NO_COMPONENT,
+ G_PARAM_READABLE | G_PARAM_WRITABLE
+ | G_PARAM_CONSTRUCT_ONLY));
cal_backend_signals[LAST_CLIENT_GONE] =
g_signal_new ("last_client_gone",
G_TYPE_FROM_CLASS (class),
@@ -129,15 +202,6 @@ cal_backend_class_init (CalBackendClass *class)
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
- cal_backend_signals[CAL_ADDED] =
- g_signal_new ("cal_added",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (CalBackendClass, cal_added),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1,
- G_TYPE_POINTER);
cal_backend_signals[OPENED] =
g_signal_new ("opened",
G_TYPE_FROM_CLASS (class),
@@ -147,56 +211,43 @@ cal_backend_class_init (CalBackendClass *class)
g_cclosure_marshal_VOID__ENUM,
G_TYPE_NONE, 1,
G_TYPE_INT);
- cal_backend_signals[OBJ_UPDATED] =
- g_signal_new ("obj_updated",
+ cal_backend_signals[REMOVED] =
+ g_signal_new ("removed",
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (CalBackendClass, obj_updated),
+ G_STRUCT_OFFSET (CalBackendClass, removed),
NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1,
- G_TYPE_STRING);
- cal_backend_signals[OBJ_REMOVED] =
- g_signal_new ("obj_removed",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (CalBackendClass, obj_removed),
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
+ g_cclosure_marshal_VOID__ENUM,
G_TYPE_NONE, 1,
- G_TYPE_STRING);
-
- object_class->finalize = cal_backend_finalize;
+ G_TYPE_INT);
class->last_client_gone = NULL;
class->opened = NULL;
class->obj_updated = NULL;
- class->obj_removed = NULL;
- class->get_uri = NULL;
class->get_cal_address = NULL;
class->get_alarm_email_address = NULL;
class->get_static_capabilities = NULL;
class->open = NULL;
class->is_loaded = NULL;
class->is_read_only = NULL;
- class->get_query = NULL;
+ class->start_query = NULL;
class->get_mode = NULL;
class->set_mode = NULL;
- class->get_n_objects = NULL;
- class->get_object = get_object;
- class->get_object_component = NULL;
- class->get_timezone_object = NULL;
- class->get_uids = NULL;
- class->get_objects_in_range = NULL;
+ class->get_object = NULL;
+ class->get_default_object = NULL;
+ class->get_object_list = NULL;
class->get_free_busy = NULL;
class->get_changes = NULL;
- class->get_alarms_in_range = NULL;
- class->get_alarms_for_object = NULL;
class->discard_alarm = NULL;
- class->update_objects = NULL;
+ class->create_object = NULL;
+ class->modify_object = NULL;
class->remove_object = NULL;
- class->send_object = NULL;
+ class->receive_objects = NULL;
+ class->send_objects = NULL;
+ class->get_timezone = NULL;
+ class->add_timezone = NULL;
+ class->set_default_timezone = NULL;
}
/* Object initialization func for the calendar backend */
@@ -208,6 +259,13 @@ cal_backend_init (CalBackend *backend)
priv = g_new0 (CalBackendPrivate, 1);
backend->priv = priv;
+ priv->clients = NULL;
+ priv->clients_mutex = g_mutex_new ();
+
+ /* FIXME bonobo_object_ref/unref? */
+ priv->queries = e_list_new((EListCopyFunc) g_object_ref, (EListFreeFunc) g_object_unref, NULL);
+ priv->queries_mutex = g_mutex_new ();
+
priv->categories = g_hash_table_new (g_str_hash, g_str_equal);
priv->changed_categories = g_hash_table_new (g_str_hash, g_str_equal);
}
@@ -242,12 +300,17 @@ cal_backend_finalize (GObject *object)
g_assert (priv->clients == NULL);
+ g_object_unref (priv->queries);
+
g_hash_table_foreach_remove (priv->changed_categories, prune_changed_categories, NULL);
g_hash_table_destroy (priv->changed_categories);
g_hash_table_foreach (priv->categories, free_category_cb, NULL);
g_hash_table_destroy (priv->categories);
+ g_mutex_free (priv->clients_mutex);
+ g_mutex_free (priv->queries_mutex);
+
if (priv->category_idle_id)
g_source_remove (priv->category_idle_id);
@@ -270,108 +333,177 @@ cal_backend_finalize (GObject *object)
const char *
cal_backend_get_uri (CalBackend *backend)
{
+ CalBackendPrivate *priv;
+
g_return_val_if_fail (backend != NULL, NULL);
g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
- g_assert (CLASS (backend)->get_uri != NULL);
- return (* CLASS (backend)->get_uri) (backend);
+ priv = backend->priv;
+
+ return priv->uri;
}
-/**
- * cal_backend_get_cal_address:
- * @backend: A calendar backend.
- *
- * Queries the cal address associated with a calendar backend, which
- * must already have an open calendar.
- *
- * Return value: The cal address associated with the calendar.
- **/
-const char *
-cal_backend_get_cal_address (CalBackend *backend)
+icalcomponent_kind
+cal_backend_get_kind (CalBackend *backend)
{
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
+ CalBackendPrivate *priv;
+
+ g_return_val_if_fail (backend != NULL, ICAL_NO_COMPONENT);
+ g_return_val_if_fail (IS_CAL_BACKEND (backend), ICAL_NO_COMPONENT);
- g_assert (CLASS (backend)->get_cal_address != NULL);
- return (* CLASS (backend)->get_cal_address) (backend);
+ priv = backend->priv;
+
+ return priv->kind;
}
-const char *
-cal_backend_get_alarm_email_address (CalBackend *backend)
+static void
+cal_destroy_cb (gpointer data, GObject *where_cal_was)
{
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
+ CalBackend *backend = CAL_BACKEND (data);
- g_assert (CLASS (backend)->get_alarm_email_address != NULL);
- return (* CLASS (backend)->get_alarm_email_address) (backend);
+ cal_backend_remove_client (backend, (Cal *) where_cal_was);
}
-const char *
-cal_backend_get_ldap_attribute (CalBackend *backend)
+static void
+listener_died_cb (gpointer cnx, gpointer data)
{
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
+ Cal *cal = CAL (data);
- g_assert (CLASS (backend)->get_ldap_attribute != NULL);
- return (* CLASS (backend)->get_ldap_attribute) (backend);
+ cal_backend_remove_client (cal_get_backend (cal), cal);
}
-const char *
-cal_backend_get_static_capabilities (CalBackend *backend)
+static void
+last_client_gone (CalBackend *backend)
{
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
+ g_signal_emit (backend, cal_backend_signals[LAST_CLIENT_GONE], 0);
+}
- g_assert (CLASS (backend)->get_static_capabilities != NULL);
- return (* CLASS (backend)->get_static_capabilities) (backend);
+void
+cal_backend_add_client (CalBackend *backend, Cal *cal)
+{
+ CalBackendPrivate *priv;
+
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = backend->priv;
+
+ bonobo_object_set_immortal (BONOBO_OBJECT (cal), TRUE);
+
+ g_object_weak_ref (G_OBJECT (cal), cal_destroy_cb, backend);
+
+ ORBit_small_listen_for_broken (cal_get_listener (cal), G_CALLBACK (listener_died_cb), cal);
+
+ g_mutex_lock (priv->clients_mutex);
+ priv->clients = g_list_append (priv->clients, cal);
+ g_mutex_unlock (priv->clients_mutex);
+
+ /* Tell the new client about the list of categories.
+ * (Ends up telling all the other clients too, but *shrug*.)
+ */
+ /* FIXME This doesn't seem right at all */
+ notify_categories_changed (backend);
}
-/* Callback used when a Cal is destroyed */
-static void
-cal_destroy_cb (gpointer data, GObject *where_cal_was)
+void
+cal_backend_remove_client (CalBackend *backend, Cal *cal)
{
- CalBackend *backend = CAL_BACKEND (data);
- CalBackendPrivate *priv = backend->priv;
+ CalBackendPrivate *priv;
+
+ /* XXX this needs a bit more thinking wrt the mutex - we
+ should be holding it when we check to see if clients is
+ NULL */
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (IS_CAL (cal));
- priv->clients = g_list_remove (priv->clients, where_cal_was);
+ priv = backend->priv;
+
+ /* Disconnect */
+ g_mutex_lock (priv->clients_mutex);
+ priv->clients = g_list_remove (priv->clients, cal);
+ g_mutex_unlock (priv->clients_mutex);
/* When all clients go away, notify the parent factory about it so that
* it may decide whether to kill the backend or not.
*/
if (!priv->clients)
- cal_backend_last_client_gone (backend);
+ last_client_gone (backend);
+}
+
+void
+cal_backend_add_query (CalBackend *backend, Query *query)
+{
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
+
+ g_mutex_lock (backend->priv->queries_mutex);
+
+ e_list_append (backend->priv->queries, query);
+
+ g_mutex_unlock (backend->priv->queries_mutex);
+}
+
+EList *
+cal_backend_get_queries (CalBackend *backend)
+{
+ g_return_val_if_fail (backend != NULL, NULL);
+ g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
+
+ return g_object_ref (backend->priv->queries);
}
+
/**
- * cal_backend_add_cal:
+ * cal_backend_get_cal_address:
* @backend: A calendar backend.
- * @cal: A calendar client interface object.
*
- * Adds a calendar client interface object to a calendar @backend.
- * The calendar backend must already have an open calendar.
+ * Queries the cal address associated with a calendar backend, which
+ * must already have an open calendar.
+ *
+ * Return value: The cal address associated with the calendar.
**/
void
-cal_backend_add_cal (CalBackend *backend, Cal *cal)
+cal_backend_get_cal_address (CalBackend *backend, Cal *cal)
{
- CalBackendPrivate *priv = backend->priv;
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
+ g_assert (CLASS (backend)->get_cal_address != NULL);
+ (* CLASS (backend)->get_cal_address) (backend, cal);
+}
+
+void
+cal_backend_get_alarm_email_address (CalBackend *backend, Cal *cal)
+{
g_return_if_fail (backend != NULL);
g_return_if_fail (IS_CAL_BACKEND (backend));
- g_return_if_fail (IS_CAL (cal));
- /* we do not keep a (strong) reference to the Cal since the
- * Calendar user agent owns it */
- g_object_weak_ref (G_OBJECT (cal), cal_destroy_cb, backend);
+ g_assert (CLASS (backend)->get_alarm_email_address != NULL);
+ (* CLASS (backend)->get_alarm_email_address) (backend, cal);
+}
- priv->clients = g_list_prepend (priv->clients, cal);
+void
+cal_backend_get_ldap_attribute (CalBackend *backend, Cal *cal)
+{
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
- /* Tell the new client about the list of categories.
- * (Ends up telling all the other clients too, but *shrug*.)
- */
- notify_categories_changed (backend);
+ g_assert (CLASS (backend)->get_ldap_attribute != NULL);
+ (* CLASS (backend)->get_ldap_attribute) (backend, cal);
+}
- /* notify backend that a new Cal has been added */
- g_signal_emit (backend, cal_backend_signals[CAL_ADDED], 0, cal);
+void
+cal_backend_get_static_capabilities (CalBackend *backend, Cal *cal)
+{
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
+
+ g_assert (CLASS (backend)->get_static_capabilities != NULL);
+ (* CLASS (backend)->get_static_capabilities) (backend, cal);
}
/**
@@ -387,19 +519,24 @@ cal_backend_add_cal (CalBackend *backend, Cal *cal)
*
* Return value: An operation status code.
**/
-CalBackendOpenStatus
-cal_backend_open (CalBackend *backend, const char *uristr, gboolean only_if_exists)
+void
+cal_backend_open (CalBackend *backend, Cal *cal, gboolean only_if_exists)
{
- CalBackendOpenStatus result;
-
- g_return_val_if_fail (backend != NULL, CAL_BACKEND_OPEN_ERROR);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), CAL_BACKEND_OPEN_ERROR);
- g_return_val_if_fail (uristr != NULL, CAL_BACKEND_OPEN_ERROR);
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
g_assert (CLASS (backend)->open != NULL);
- result = (* CLASS (backend)->open) (backend, uristr, only_if_exists);
+ (* CLASS (backend)->open) (backend, cal, only_if_exists);
+}
- return result;
+void
+cal_backend_remove (CalBackend *backend, Cal *cal)
+{
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
+
+ g_assert (CLASS (backend)->remove != NULL);
+ (* CLASS (backend)->remove) (backend, cal);
}
/**
@@ -433,44 +570,24 @@ cal_backend_is_loaded (CalBackend *backend)
*
* Return value: TRUE if the calendar is read only, FALSE otherwise.
*/
-gboolean
-cal_backend_is_read_only (CalBackend *backend)
+void
+cal_backend_is_read_only (CalBackend *backend, Cal *cal)
{
- gboolean result;
-
- g_return_val_if_fail (backend != NULL, FALSE);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), FALSE);
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
g_assert (CLASS (backend)->is_read_only != NULL);
- result = (* CLASS (backend)->is_read_only) (backend);
-
- return result;
+ (* CLASS (backend)->is_read_only) (backend, cal);
}
-/**
- * cal_backend_get_query:
- * @backend: A calendar backend.
- * @ql: The query listener.
- * @sexp: Search expression.
- *
- * Create a query object for this backend.
- */
-Query *
-cal_backend_get_query (CalBackend *backend,
- GNOME_Evolution_Calendar_QueryListener ql,
- const char *sexp)
+void
+cal_backend_start_query (CalBackend *backend, Query *query)
{
- Query *result;
-
- g_return_val_if_fail (backend != NULL, FALSE);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), FALSE);
-
- if (CLASS (backend)->get_query != NULL)
- result = (* CLASS (backend)->get_query) (backend, ql, sexp);
- else
- result = query_new (backend, ql, sexp);
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
- return result;
+ g_assert (CLASS (backend)->start_query != NULL);
+ (* CLASS (backend)->start_query) (backend, query);
}
/**
@@ -514,206 +631,56 @@ cal_backend_set_mode (CalBackend *backend, CalMode mode)
(* CLASS (backend)->set_mode) (backend, mode);
}
-/**
- * cal_backend_get_n_objects:
- * @backend: A calendar backend.
- * @type: Types of objects that will be included in the count.
- *
- * Queries the number of calendar objects of a particular type.
- *
- * Return value: Number of objects of the specified @type.
- **/
-int
-cal_backend_get_n_objects (CalBackend *backend, CalObjType type)
-{
- g_return_val_if_fail (backend != NULL, -1);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), -1);
-
- g_assert (CLASS (backend)->get_n_objects != NULL);
- return (* CLASS (backend)->get_n_objects) (backend, type);
-}
-
-/* Default cal_backend_get_object implementation */
-static char *
-get_object (CalBackend *backend, const char *uid)
-{
- CalComponent *comp;
-
- comp = cal_backend_get_object_component (backend, uid);
- if (!comp)
- return NULL;
-
- return cal_component_get_as_string (comp);
-}
-
-char *
-cal_backend_get_default_object (CalBackend *backend, CalObjType type)
+void
+cal_backend_get_default_object (CalBackend *backend, Cal *cal)
{
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
g_assert (CLASS (backend)->get_default_object != NULL);
- return (* CLASS (backend)->get_default_object) (backend, type);
+ (* CLASS (backend)->get_default_object) (backend, cal);
}
/**
* cal_backend_get_object:
* @backend: A calendar backend.
* @uid: Unique identifier for a calendar object.
+ * @rid: ID for the object's recurrence to get.
*
* Queries a calendar backend for a calendar object based on its unique
- * identifier.
+ * identifier and its recurrence ID (if a recurrent appointment).
*
* Return value: The string representation of a complete calendar wrapping the
* the sought object, or NULL if no object had the specified UID.
**/
-char *
-cal_backend_get_object (CalBackend *backend, const char *uid)
+void
+cal_backend_get_object (CalBackend *backend, Cal *cal, const char *uid, const char *rid)
{
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
- g_return_val_if_fail (uid != NULL, NULL);
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
+ g_return_if_fail (uid != NULL);
g_assert (CLASS (backend)->get_object != NULL);
- return (* CLASS (backend)->get_object) (backend, uid);
+ (* CLASS (backend)->get_object) (backend, cal, uid, rid);
}
/**
- * cal_backend_get_object_component:
- * @backend: A calendar backend.
- * @uid: Unique identifier for a calendar object.
- *
- * Queries a calendar backend for a calendar object based on its unique
- * identifier. It returns the CalComponent rather than the string
- * representation.
- *
- * Return value: The CalComponent of the sought object, or NULL if no object
- * had the specified UID.
- **/
-CalComponent *
-cal_backend_get_object_component (CalBackend *backend, const char *uid)
-{
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
- g_return_val_if_fail (uid != NULL, NULL);
-
- g_assert (CLASS (backend)->get_object_component != NULL);
- return (* CLASS (backend)->get_object_component) (backend, uid);
-}
-
-/**
- * cal_backend_get_timezone_object:
- * @backend: A calendar backend.
- * @tzid: Unique identifier for a calendar VTIMEZONE object.
- *
- * Queries a calendar backend for a VTIMEZONE calendar object based on its
- * unique TZID identifier.
- *
- * Return value: The string representation of a VTIMEZONE component, or NULL
- * if no VTIMEZONE object had the specified TZID.
- **/
-char *
-cal_backend_get_timezone_object (CalBackend *backend, const char *tzid)
-{
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
- g_return_val_if_fail (tzid != NULL, NULL);
-
- g_assert (CLASS (backend)->get_timezone_object != NULL);
- return (* CLASS (backend)->get_timezone_object) (backend, tzid);
-}
-
-/**
- * cal_backend_get_type_by_uid
- * @backend: A calendar backend.
- * @uid: Unique identifier for a Calendar object.
- *
- * Returns the type of the object identified by the @uid argument
- */
-CalObjType
-cal_backend_get_type_by_uid (CalBackend *backend, const char *uid)
-{
- icalcomponent *icalcomp;
- char *comp_str;
- CalObjType type = CAL_COMPONENT_NO_TYPE;
-
- g_return_val_if_fail (IS_CAL_BACKEND (backend), CAL_COMPONENT_NO_TYPE);
- g_return_val_if_fail (uid != NULL, CAL_COMPONENT_NO_TYPE);
-
- comp_str = cal_backend_get_object (backend, uid);
- if (!comp_str)
- return CAL_COMPONENT_NO_TYPE;
-
- icalcomp = icalparser_parse_string (comp_str);
- if (icalcomp) {
- switch (icalcomponent_isa (icalcomp)) {
- case ICAL_VEVENT_COMPONENT :
- type = CALOBJ_TYPE_EVENT;
- break;
- case ICAL_VTODO_COMPONENT :
- type = CALOBJ_TYPE_TODO;
- break;
- case ICAL_VJOURNAL_COMPONENT :
- type = CALOBJ_TYPE_JOURNAL;
- break;
- default :
- type = CAL_COMPONENT_NO_TYPE;
- }
-
- icalcomponent_free (icalcomp);
- }
-
- g_free (comp_str);
-
- return type;
-}
-
-/**
- * cal_backend_get_uids:
- * @backend: A calendar backend.
- * @type: Bitmask with types of objects to return.
- *
- * Builds 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. The list should be
- * freed using the cal_obj_uid_list_free() function.
- **/
-GList *
-cal_backend_get_uids (CalBackend *backend, CalObjType type)
-{
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
-
- g_assert (CLASS (backend)->get_uids != NULL);
- return (* CLASS (backend)->get_uids) (backend, type);
-}
-
-
-/**
- * cal_backend_get_objects_in_range:
- * @backend: A calendar backend.
- * @type: Bitmask with types of objects to return.
- * @start: Start time for query.
- * @end: End time for query.
+ * cal_backend_get_object_list:
+ * @backend:
+ * @type:
+ *
*
- * Builds a list of unique identifiers corresponding to calendar objects of the
- * specified type that occur or recur within the specified time range.
*
- * Return value: A list of UID strings. The list should be freed using the
- * cal_obj_uid_list_free() function.
+ * Return value:
**/
-GList *
-cal_backend_get_objects_in_range (CalBackend *backend, CalObjType type,
- time_t start, time_t end)
+void
+cal_backend_get_object_list (CalBackend *backend, Cal *cal, const char *sexp)
{
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
- g_return_val_if_fail (start != -1 && end != -1, NULL);
- g_return_val_if_fail (start <= end, NULL);
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
- g_assert (CLASS (backend)->get_objects_in_range != NULL);
- return (* CLASS (backend)->get_objects_in_range) (backend, type, start, end);
+ g_assert (CLASS (backend)->get_object_list != NULL);
+ return (* CLASS (backend)->get_object_list) (backend, cal, sexp);
}
/**
@@ -727,16 +694,16 @@ cal_backend_get_objects_in_range (CalBackend *backend, CalObjType type,
*
* Return value: a list of CalObj's
**/
-GList *
-cal_backend_get_free_busy (CalBackend *backend, GList *users, time_t start, time_t end)
+void
+cal_backend_get_free_busy (CalBackend *backend, Cal *cal, GList *users, time_t start, time_t end)
{
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
- g_return_val_if_fail (start != -1 && end != -1, NULL);
- g_return_val_if_fail (start <= end, NULL);
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
+ g_return_if_fail (start != -1 && end != -1);
+ g_return_if_fail (start <= end);
g_assert (CLASS (backend)->get_free_busy != NULL);
- return (* CLASS (backend)->get_free_busy) (backend, users, start, end);
+ (* CLASS (backend)->get_free_busy) (backend, cal, users, start, end);
}
/**
@@ -750,91 +717,15 @@ cal_backend_get_free_busy (CalBackend *backend, GList *users, time_t start, time
*
* Return value: A list of the objects that changed and the type of change
**/
-GNOME_Evolution_Calendar_CalObjChangeSeq *
-cal_backend_get_changes (CalBackend *backend, CalObjType type, const char *change_id)
+void
+cal_backend_get_changes (CalBackend *backend, Cal *cal, CalObjType type, const char *change_id)
{
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
- g_return_val_if_fail (change_id != NULL, NULL);
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
+ g_return_if_fail (change_id != NULL);
g_assert (CLASS (backend)->get_changes != NULL);
- return (* CLASS (backend)->get_changes) (backend, type, change_id);
-}
-
-/**
- * cal_backend_get_alarms_in_range:
- * @backend: A calendar backend.
- * @start: Start time for query.
- * @end: End time for query.
- * @valid_range: Return value that says whether the range is valid or not.
- *
- * Builds a sorted list of the alarms that trigger in the specified time range.
- *
- * Return value: A sequence of component alarm instances structures, or NULL
- * if @valid_range returns FALSE.
- **/
-GNOME_Evolution_Calendar_CalComponentAlarmsSeq *
-cal_backend_get_alarms_in_range (CalBackend *backend, time_t start, time_t end,
- gboolean *valid_range)
-{
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
- g_return_val_if_fail (valid_range != NULL, NULL);
-
- g_assert (CLASS (backend)->get_alarms_in_range != NULL);
-
- if (!(start != -1 && end != -1 && start <= end)) {
- *valid_range = FALSE;
- return NULL;
- } else {
- *valid_range = TRUE;
- return (* CLASS (backend)->get_alarms_in_range) (backend, start, end);
- }
-}
-
-/**
- * cal_backend_get_alarms_for_object:
- * @backend: A calendar backend.
- * @uid: Unique identifier for a calendar object.
- * @start: Start time for query.
- * @end: End time for query.
- * @result: Return value for the result code for the operation.
- *
- * Builds a sorted list of the alarms of the specified event that trigger in a
- * particular time range.
- *
- * Return value: A structure of the component's alarm instances, or NULL if @result
- * returns something other than #CAL_BACKEND_GET_ALARMS_SUCCESS.
- **/
-GNOME_Evolution_Calendar_CalComponentAlarms *
-cal_backend_get_alarms_for_object (CalBackend *backend, const char *uid,
- time_t start, time_t end,
- CalBackendGetAlarmsForObjectResult *result)
-{
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
- g_return_val_if_fail (uid != NULL, NULL);
- g_return_val_if_fail (result != NULL, NULL);
-
- g_assert (CLASS (backend)->get_alarms_for_object != NULL);
-
- if (!(start != -1 && end != -1 && start <= end)) {
- *result = CAL_BACKEND_GET_ALARMS_INVALID_RANGE;
- return NULL;
- } else {
- gboolean object_found;
- GNOME_Evolution_Calendar_CalComponentAlarms *alarms;
-
- alarms = (* CLASS (backend)->get_alarms_for_object) (backend, uid, start, end,
- &object_found);
-
- if (object_found)
- *result = CAL_BACKEND_GET_ALARMS_SUCCESS;
- else
- *result = CAL_BACKEND_GET_ALARMS_NOT_FOUND;
-
- return alarms;
- }
+ (* CLASS (backend)->get_changes) (backend, cal, type, change_id);
}
/**
@@ -846,92 +737,82 @@ cal_backend_get_alarms_for_object (CalBackend *backend, const char *uid,
* Discards an alarm from the given component. This allows the specific backend
* to do whatever is needed to really discard the alarm.
*
- * Return value: a #CalBackendResult value, which indicates the
- * result of the operation.
**/
-CalBackendResult
-cal_backend_discard_alarm (CalBackend *backend, const char *uid, const char *auid)
+void
+cal_backend_discard_alarm (CalBackend *backend, Cal *cal, const char *uid, const char *auid)
{
- g_return_val_if_fail (backend != NULL, CAL_BACKEND_RESULT_NOT_FOUND);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), CAL_BACKEND_RESULT_NOT_FOUND);
- g_return_val_if_fail (uid != NULL, CAL_BACKEND_RESULT_NOT_FOUND);
- g_return_val_if_fail (auid != NULL, CAL_BACKEND_RESULT_NOT_FOUND);
- g_return_val_if_fail (CLASS (backend)->discard_alarm != NULL, CAL_BACKEND_RESULT_NOT_FOUND);
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
+ g_return_if_fail (uid != NULL);
+ g_return_if_fail (auid != NULL);
- return (* CLASS (backend)->discard_alarm) (backend, uid, auid);
+ g_assert (CLASS (backend)->discard_alarm != NULL);
+ (* CLASS (backend)->discard_alarm) (backend, cal, uid, auid);
}
-/**
- * cal_backend_update_objects:
- * @backend: A calendar backend.
- * @calobj: String representation of the new calendar object(s).
- *
- * Updates an object in a calendar backend. It will replace any existing
- * object that has the same UID as the specified one. The backend will in
- * turn notify all of its clients about the change.
- *
- * Return value: a #CalBackendResult value, which indicates the
- * result of the operation.
- **/
-CalBackendResult
-cal_backend_update_objects (CalBackend *backend, const char *calobj, CalObjModType mod)
+void
+cal_backend_create_object (CalBackend *backend, Cal *cal, const char *calobj)
+{
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
+ g_return_if_fail (calobj != NULL);
+
+ g_assert (CLASS (backend)->create_object != NULL);
+ (* CLASS (backend)->create_object) (backend, cal, calobj);
+}
+
+void
+cal_backend_modify_object (CalBackend *backend, Cal *cal, const char *calobj, CalObjModType mod)
{
- g_return_val_if_fail (backend != NULL, CAL_BACKEND_RESULT_NOT_FOUND);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), CAL_BACKEND_RESULT_NOT_FOUND);
- g_return_val_if_fail (calobj != NULL, CAL_BACKEND_RESULT_NOT_FOUND);
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
+ g_return_if_fail (calobj != NULL);
- g_assert (CLASS (backend)->update_objects != NULL);
- return (* CLASS (backend)->update_objects) (backend, calobj, mod);
+ g_assert (CLASS (backend)->modify_object != NULL);
+ (* CLASS (backend)->modify_object) (backend, cal, calobj, mod);
}
/**
* cal_backend_remove_object:
* @backend: A calendar backend.
* @uid: Unique identifier of the object to remove.
+ * @rid: A recurrence ID.
*
* Removes an object in a calendar backend. The backend will notify all of its
* clients about the change.
*
- * Return value: a #CalBackendResult value, which indicates the
- * result of the operation.
**/
-CalBackendResult
-cal_backend_remove_object (CalBackend *backend, const char *uid, CalObjModType mod)
+void
+cal_backend_remove_object (CalBackend *backend, Cal *cal, const char *uid, const char *rid, CalObjModType mod)
{
- g_return_val_if_fail (backend != NULL, CAL_BACKEND_RESULT_NOT_FOUND);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), CAL_BACKEND_RESULT_NOT_FOUND);
- g_return_val_if_fail (uid != NULL, CAL_BACKEND_RESULT_NOT_FOUND);
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
+ g_return_if_fail (uid != NULL);
g_assert (CLASS (backend)->remove_object != NULL);
- return (* CLASS (backend)->remove_object) (backend, uid, mod);
+ (* CLASS (backend)->remove_object) (backend, cal, uid, rid, mod);
}
-CalBackendSendResult
-cal_backend_send_object (CalBackend *backend, const char *calobj, char **new_calobj,
- GNOME_Evolution_Calendar_UserList **user_list, char error_msg[256])
+void
+cal_backend_receive_objects (CalBackend *backend, Cal *cal, const char *calobj)
{
- g_return_val_if_fail (backend != NULL, CAL_BACKEND_SEND_INVALID_OBJECT);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), CAL_BACKEND_SEND_INVALID_OBJECT);
- g_return_val_if_fail (calobj != NULL, CAL_BACKEND_SEND_INVALID_OBJECT);
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
+ g_return_if_fail (calobj != NULL);
- g_assert (CLASS (backend)->send_object != NULL);
- return (* CLASS (backend)->send_object) (backend, calobj, new_calobj, user_list, error_msg);
+ g_assert (CLASS (backend)->receive_objects != NULL);
+ return (* CLASS (backend)->receive_objects) (backend, cal, calobj);
}
-/**
- * cal_backend_last_client_gone:
- * @backend: A calendar backend.
- *
- * Emits the "last_client_gone" signal of a calendar backend. This function is
- * to be used only by backend implementations.
- **/
void
-cal_backend_last_client_gone (CalBackend *backend)
+cal_backend_send_objects (CalBackend *backend, Cal *cal, const char *calobj)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (IS_CAL_BACKEND (backend));
+ g_return_if_fail (calobj != NULL);
- g_signal_emit (G_OBJECT (backend), cal_backend_signals[LAST_CLIENT_GONE], 0);
+ g_assert (CLASS (backend)->send_objects != NULL);
+ return (* CLASS (backend)->send_objects) (backend, cal, calobj);
}
/**
@@ -943,7 +824,7 @@ cal_backend_last_client_gone (CalBackend *backend)
* only by backend implementations.
**/
void
-cal_backend_opened (CalBackend *backend, CalBackendOpenStatus status)
+cal_backend_opened (CalBackend *backend, int status)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (IS_CAL_BACKEND (backend));
@@ -952,45 +833,16 @@ cal_backend_opened (CalBackend *backend, CalBackendOpenStatus status)
0, status);
}
-/**
- * cal_backend_obj_updated:
- * @backend: A calendar backend.
- * @uid: Unique identifier of the component that was updated.
- *
- * Emits the "obj_updated" signal of a calendar backend. This function is to be
- * used only by backend implementations.
- **/
void
-cal_backend_obj_updated (CalBackend *backend, const char *uid)
+cal_backend_removed (CalBackend *backend, int status)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (IS_CAL_BACKEND (backend));
- g_return_if_fail (uid != NULL);
-
- g_signal_emit (G_OBJECT (backend), cal_backend_signals[OBJ_UPDATED],
- 0, uid);
-}
-/**
- * cal_backend_obj_removed:
- * @backend: A calendar backend.
- * @uid: Unique identifier of the component that was removed.
- *
- * Emits the "obj_removed" signal of a calendar backend. This function is to be
- * used only by backend implementations.
- **/
-void
-cal_backend_obj_removed (CalBackend *backend, const char *uid)
-{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (IS_CAL_BACKEND (backend));
- g_return_if_fail (uid != NULL);
-
- g_signal_emit (G_OBJECT (backend), cal_backend_signals[OBJ_REMOVED],
- 0, uid);
+ g_signal_emit (G_OBJECT (backend), cal_backend_signals[REMOVED],
+ 0, status);
}
-
/**
* cal_backend_get_timezone:
* @backend: A calendar backend.
@@ -1002,38 +854,17 @@ cal_backend_obj_removed (CalBackend *backend, const char *uid)
*
* Returns: The icaltimezone* corresponding to the given TZID, or NULL.
**/
-icaltimezone*
-cal_backend_get_timezone (CalBackend *backend, const char *tzid)
+void
+cal_backend_get_timezone (CalBackend *backend, Cal *cal, const char *tzid)
{
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
- g_return_val_if_fail (tzid != NULL, NULL);
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
+ g_return_if_fail (tzid != NULL);
g_assert (CLASS (backend)->get_timezone != NULL);
- return (* CLASS (backend)->get_timezone) (backend, tzid);
+ (* CLASS (backend)->get_timezone) (backend, cal, tzid);
}
-
-/**
- * cal_backend_get_default_timezone:
- * @backend: A calendar backend.
- *
- * Returns the default timezone for the calendar, which is used to resolve
- * DATE and floating DATE-TIME values.
- *
- * Returns: The default icaltimezone* for the calendar.
- **/
-icaltimezone*
-cal_backend_get_default_timezone (CalBackend *backend)
-{
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
-
- g_assert (CLASS (backend)->get_default_timezone != NULL);
- return (* CLASS (backend)->get_default_timezone) (backend);
-}
-
-
/**
* cal_backend_set_default_timezone:
* @backend: A calendar backend.
@@ -1045,75 +876,74 @@ cal_backend_get_default_timezone (CalBackend *backend)
* Returns: TRUE if the VTIMEZONE data for the timezone was found, or FALSE if
* not.
**/
-gboolean
-cal_backend_set_default_timezone (CalBackend *backend, const char *tzid)
+void
+cal_backend_set_default_timezone (CalBackend *backend, Cal *cal, const char *tzid)
{
- g_return_val_if_fail (backend != NULL, FALSE);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), FALSE);
- g_return_val_if_fail (tzid != NULL, FALSE);
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (IS_CAL_BACKEND (backend));
+ g_return_if_fail (tzid != NULL);
g_assert (CLASS (backend)->set_default_timezone != NULL);
- return (* CLASS (backend)->set_default_timezone) (backend, tzid);
+ (* CLASS (backend)->set_default_timezone) (backend, cal, tzid);
}
-
/**
- * cal_backend_notify_mode:
+ * cal_backend_add_timezone
* @backend: A calendar backend.
- * @status: Status of the mode set
- * @mode: the current mode
+ * @tzobj: The timezone object, in a string.
*
- * Notifies each of the backend's listeners about the results of a
- * setMode call.
- **/
+ * Add a timezone object to the given backend.
+ *
+ * Returns: TRUE if successful, or FALSE if not.
+ */
void
-cal_backend_notify_mode (CalBackend *backend,
- GNOME_Evolution_Calendar_Listener_SetModeStatus status,
- GNOME_Evolution_Calendar_CalMode mode)
+cal_backend_add_timezone (CalBackend *backend, Cal *cal, const char *tzobj)
{
- CalBackendPrivate *priv = backend->priv;
- GList *l;
+ g_return_if_fail (IS_CAL_BACKEND (backend));
+ g_return_if_fail (tzobj != NULL);
+ g_return_if_fail (CLASS (backend)->add_timezone != NULL);
- for (l = priv->clients; l; l = l->next)
- cal_notify_mode (l->data, status, mode);
+ (* CLASS (backend)->add_timezone) (backend, cal, tzobj);
}
-/**
- * cal_backend_notify_update:
- * @backend: A calendar backend.
- * @uid: UID of object that was updated.
- *
- * Notifies each of the backend's listeners about an update to a
- * calendar object.
- **/
-void
-cal_backend_notify_update (CalBackend *backend, const char *uid)
+icaltimezone *
+cal_backend_internal_get_default_timezone (CalBackend *backend)
{
- CalBackendPrivate *priv = backend->priv;
- GList *l;
+ g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
+ g_return_val_if_fail (CLASS (backend)->internal_get_default_timezone != NULL, NULL);
- cal_backend_obj_updated (backend, uid);
- for (l = priv->clients; l; l = l->next)
- cal_notify_update (l->data, uid);
+ return (* CLASS (backend)->internal_get_default_timezone) (backend);
+}
+
+icaltimezone *
+cal_backend_internal_get_timezone (CalBackend *backend, const char *tzid)
+{
+ g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
+ g_return_val_if_fail (tzid != NULL, NULL);
+ g_return_val_if_fail (CLASS (backend)->internal_get_timezone != NULL, NULL);
+
+ return (* CLASS (backend)->internal_get_timezone) (backend, tzid);
}
/**
- * cal_backend_notify_remove:
+ * cal_backend_notify_mode:
* @backend: A calendar backend.
- * @uid: UID of object that was removed.
- *
- * Notifies each of the backend's listeners about a calendar object
- * that was removed.
+ * @status: Status of the mode set
+ * @mode: the current mode
+ *
+ * Notifies each of the backend's listeners about the results of a
+ * setMode call.
**/
void
-cal_backend_notify_remove (CalBackend *backend, const char *uid)
+cal_backend_notify_mode (CalBackend *backend,
+ GNOME_Evolution_Calendar_Listener_SetModeStatus status,
+ GNOME_Evolution_Calendar_CalMode mode)
{
CalBackendPrivate *priv = backend->priv;
GList *l;
- cal_backend_obj_removed (backend, uid);
for (l = priv->clients; l; l = l->next)
- cal_notify_remove (l->data, uid);
+ cal_notify_mode (l->data, status, mode);
}
/**
diff --git a/calendar/pcs/cal-backend.h b/calendar/pcs/cal-backend.h
index 49d8b2d76e..793622cadc 100644
--- a/calendar/pcs/cal-backend.h
+++ b/calendar/pcs/cal-backend.h
@@ -24,6 +24,7 @@
#ifndef CAL_BACKEND_H
#define CAL_BACKEND_H
+#include <e-util/e-list.h>
#include <cal-util/cal-util.h>
#include <cal-util/cal-component.h>
#include "pcs/evolution-calendar.h"
@@ -42,37 +43,6 @@ G_BEGIN_DECLS
#define IS_CAL_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CAL_BACKEND_TYPE))
#define IS_CAL_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CAL_BACKEND_TYPE))
-/* Open status values */
-typedef enum {
- CAL_BACKEND_OPEN_SUCCESS, /* Loading OK */
- CAL_BACKEND_OPEN_ERROR, /* We need better error reporting in libversit */
- CAL_BACKEND_OPEN_NOT_FOUND,
- CAL_BACKEND_OPEN_PERMISSION_DENIED,
-} CalBackendOpenStatus;
-
-/* Update and Remove result values */
-typedef enum {
- CAL_BACKEND_RESULT_SUCCESS,
- CAL_BACKEND_RESULT_INVALID_OBJECT,
- CAL_BACKEND_RESULT_NOT_FOUND,
- CAL_BACKEND_RESULT_PERMISSION_DENIED
-} CalBackendResult;
-
-/* Send result values */
-typedef enum {
- CAL_BACKEND_SEND_SUCCESS,
- CAL_BACKEND_SEND_INVALID_OBJECT,
- CAL_BACKEND_SEND_BUSY,
- CAL_BACKEND_SEND_PERMISSION_DENIED,
-} CalBackendSendResult;
-
-/* Result codes for ::get_alarms_in_range() */
-typedef enum {
- CAL_BACKEND_GET_ALARMS_SUCCESS,
- CAL_BACKEND_GET_ALARMS_NOT_FOUND,
- CAL_BACKEND_GET_ALARMS_INVALID_RANGE
-} CalBackendGetAlarmsForObjectResult;
-
typedef struct _CalBackendPrivate CalBackendPrivate;
struct _CalBackend {
@@ -88,153 +58,115 @@ struct _CalBackendClass {
void (* last_client_gone) (CalBackend *backend);
void (* cal_added) (CalBackend *backend, Cal *cal);
- void (* opened) (CalBackend *backend, CalBackendOpenStatus status);
+ gboolean (* is_loaded) (CalBackend *backend);
+
+ /* FIXME What to pass back here */
+ void (* opened) (CalBackend *backend, int status);
+ void (* removed) (CalBackend *backend, int status);
void (* obj_updated) (CalBackend *backend, const char *uid);
- void (* obj_removed) (CalBackend *backend, const char *uid);
/* Virtual methods */
- const char *(* get_uri) (CalBackend *backend);
-
- const char *(* get_cal_address) (CalBackend *backend);
- const char *(* get_alarm_email_address) (CalBackend *backend);
- const char *(* get_ldap_attribute) (CalBackend *backend);
-
- const char *(* get_static_capabilities) (CalBackend *backend);
+ void (* is_read_only) (CalBackend *backend, Cal *cal);
+ void (* get_cal_address) (CalBackend *backend, Cal *cal);
+ void (* get_alarm_email_address) (CalBackend *backend, Cal *cal);
+ void (* get_ldap_attribute) (CalBackend *backend, Cal *cal);
+ void (* get_static_capabilities) (CalBackend *backend, Cal *cal);
- CalBackendOpenStatus (* open) (CalBackend *backend, const char *uristr,
- gboolean only_if_exists);
+ void (* open) (CalBackend *backend, Cal *cal, gboolean only_if_exists);
+ void (* remove) (CalBackend *backend, Cal *cal);
- gboolean (* is_loaded) (CalBackend *backend);
- gboolean (* is_read_only) (CalBackend *backend);
-
- Query *(* get_query) (CalBackend *backend,
- GNOME_Evolution_Calendar_QueryListener ql,
- const char *sexp);
-
- /* Mode relate virtual methods */
- CalMode (* get_mode) (CalBackend *backend);
- void (* set_mode) (CalBackend *backend, CalMode mode);
-
- /* General object acquirement and information related virtual methods */
- int (* get_n_objects) (CalBackend *backend, CalObjType type);
- char *(* get_default_object) (CalBackend *backend, CalObjType type);
- char *(* get_object) (CalBackend *backend, const char *uid);
- CalComponent *(* get_object_component) (CalBackend *backend, const char *uid);
- char *(* get_timezone_object) (CalBackend *backend, const char *tzid);
- GList *(* get_uids) (CalBackend *backend, CalObjType type);
-
- GList *(* get_objects_in_range) (CalBackend *backend, CalObjType type,
- time_t start, time_t end);
- GList *(* get_free_busy) (CalBackend *backend, GList *users, time_t start, time_t end);
-
- /* Change related virtual methods */
- GNOME_Evolution_Calendar_CalObjChangeSeq * (* get_changes) (
- CalBackend *backend, CalObjType type, const char *change_id);
-
- /* Alarm related virtual methods */
- GNOME_Evolution_Calendar_CalComponentAlarmsSeq *(* get_alarms_in_range) (
- CalBackend *backend, time_t start, time_t end);
- GNOME_Evolution_Calendar_CalComponentAlarms *(* get_alarms_for_object) (
- CalBackend *backend, const char *uid,
- time_t start, time_t end, gboolean *object_found);
- CalBackendResult (* discard_alarm) (CalBackend *backend, const char *uid, const char *auid);
-
- /* Object manipulation virtual methods */
- CalBackendResult (* update_objects) (CalBackend *backend, const char *calobj, CalObjModType mod);
- CalBackendResult (* remove_object) (CalBackend *backend, const char *uid, CalObjModType mod);
-
- CalBackendSendResult (* send_object) (CalBackend *backend, const char *calobj, char **new_calobj,
- GNOME_Evolution_Calendar_UserList **user_list,
- char error_msg[256]);
-
- /* Timezone related virtual methods */
- icaltimezone *(* get_timezone) (CalBackend *backend, const char *tzid);
- icaltimezone *(* get_default_timezone) (CalBackend *backend);
- gboolean (* set_default_timezone) (CalBackend *backend, const char *tzid);
-};
-
-GType cal_backend_get_type (void);
-
-const char *cal_backend_get_uri (CalBackend *backend);
+ /* Object related virtual methods */
+ void (* create_object) (CalBackend *backend, Cal *cal, const char *calobj);
+ void (* modify_object) (CalBackend *backend, Cal *cal, const char *calobj, CalObjModType mod);
+ void (* remove_object) (CalBackend *backend, Cal *cal, const char *uid, const char *rid, CalObjModType mod);
-const char *cal_backend_get_cal_address (CalBackend *backend);
-const char *cal_backend_get_alarm_email_address (CalBackend *backend);
-const char *cal_backend_get_ldap_attribute (CalBackend *backend);
+ void (* discard_alarm) (CalBackend *backend, Cal *cal, const char *uid, const char *auid);
-const char *cal_backend_get_static_capabilities (CalBackend *backend);
+ void (* receive_objects) (CalBackend *backend, Cal *cal, const char *calobj);
+ void (* send_objects) (CalBackend *backend, Cal *cal, const char *calobj);
-void cal_backend_add_cal (CalBackend *backend, Cal *cal);
+ void (* get_default_object) (CalBackend *backend, Cal *cal);
+ void (* get_object) (CalBackend *backend, Cal *cal, const char *uid, const char *rid);
+ void (* get_object_list) (CalBackend *backend, Cal *cal, const char *sexp);
-CalBackendOpenStatus cal_backend_open (CalBackend *backend, const char *uristr,
- gboolean only_if_exists);
-
-gboolean cal_backend_is_loaded (CalBackend *backend);
-
-gboolean cal_backend_is_read_only (CalBackend *backend);
-
-Query *cal_backend_get_query (CalBackend *backend,
- GNOME_Evolution_Calendar_QueryListener ql,
- const char *sexp);
+ /* Timezone related virtual methods */
+ void (* get_timezone) (CalBackend *backend, Cal *cal, const char *tzid);
+ void (* add_timezone) (CalBackend *backend, Cal *cal, const char *object);
+ void (* set_default_timezone) (CalBackend *backend, Cal *cal, const char *tzid);
-CalMode cal_backend_get_mode (CalBackend *backend);
-void cal_backend_set_mode (CalBackend *backend, CalMode mode);
+ void (* start_query) (CalBackend *backend, Query *query);
-int cal_backend_get_n_objects (CalBackend *backend, CalObjType type);
+ /* Mode relate virtual methods */
+ CalMode (* get_mode) (CalBackend *backend);
+ void (* set_mode) (CalBackend *backend, CalMode mode);
-char *cal_backend_get_default_object (CalBackend *backend, CalObjType type);
+ void (* get_free_busy) (CalBackend *backend, Cal *cal, GList *users, time_t start, time_t end);
+ void (* get_changes) (CalBackend *backend, Cal *cal, CalObjType type, const char *change_id);
-char *cal_backend_get_object (CalBackend *backend, const char *uid);
+ /* Internal methods for use only in the pcs */
+ icaltimezone *(* internal_get_default_timezone) (CalBackend *backend);
+ icaltimezone *(* internal_get_timezone) (CalBackend *backend, const char *tzid);
+};
-CalComponent *cal_backend_get_object_component (CalBackend *backend, const char *uid);
+GType cal_backend_get_type (void);
-gboolean cal_backend_set_default_timezone (CalBackend *backend, const char *tzid);
+const char *cal_backend_get_uri (CalBackend *backend);
+icalcomponent_kind cal_backend_get_kind (CalBackend *backend);
-char *cal_backend_get_timezone_object (CalBackend *backend, const char *tzid);
+void cal_backend_add_client (CalBackend *backend, Cal *cal);
+void cal_backend_remove_client (CalBackend *backend, Cal *cal);
-CalObjType cal_backend_get_type_by_uid (CalBackend *backend, const char *uid);
+void cal_backend_add_query (CalBackend *backend, Query *query);
+EList *cal_backend_get_queries (CalBackend *backend);
-GList *cal_backend_get_uids (CalBackend *backend, CalObjType type);
+void cal_backend_is_read_only (CalBackend *backend, Cal *cal);
+void cal_backend_get_cal_address (CalBackend *backend, Cal *cal);
+void cal_backend_get_alarm_email_address (CalBackend *backend, Cal *cal);
+void cal_backend_get_ldap_attribute (CalBackend *backend, Cal *cal);
+void cal_backend_get_static_capabilities (CalBackend *backend, Cal *cal);
-GList *cal_backend_get_objects_in_range (CalBackend *backend, CalObjType type,
- time_t start, time_t end);
+void cal_backend_open (CalBackend *backend, Cal *cal, gboolean only_if_exists);
+void cal_backend_remove (CalBackend *backend, Cal *cal);
-GList *cal_backend_get_free_busy (CalBackend *backend, GList *users, time_t start, time_t end);
+void cal_backend_create_object (CalBackend *backend, Cal *cal, const char *calobj);
+void cal_backend_modify_object (CalBackend *backend, Cal *cal, const char *calobj, CalObjModType mod);
+void cal_backend_remove_object (CalBackend *backend, Cal *cal, const char *uid, const char *rid, CalObjModType mod);
-GNOME_Evolution_Calendar_CalObjChangeSeq * cal_backend_get_changes (
- CalBackend *backend, CalObjType type, const char *change_id);
+void cal_backend_discard_alarm (CalBackend *backend, Cal *cal, const char *uid, const char *auid);
-GNOME_Evolution_Calendar_CalComponentAlarmsSeq *cal_backend_get_alarms_in_range (
- CalBackend *backend, time_t start, time_t end, gboolean *valid_range);
+void cal_backend_receive_objects (CalBackend *backend, Cal *cal, const char *calobj);
+void cal_backend_send_objects (CalBackend *backend, Cal *cal, const char *calobj);
-GNOME_Evolution_Calendar_CalComponentAlarms *cal_backend_get_alarms_for_object (
- CalBackend *backend, const char *uid,
- time_t start, time_t end,
- CalBackendGetAlarmsForObjectResult *result);
+void cal_backend_get_default_object (CalBackend *backend, Cal *cal);
+void cal_backend_get_object (CalBackend *backend, Cal *cal, const char *uid, const char *rid);
+void cal_backend_get_object_list (CalBackend *backend, Cal *cal, const char *sexp);
-CalBackendResult cal_backend_discard_alarm (CalBackend *backend, const char *uid, const char *auid);
+gboolean cal_backend_is_loaded (CalBackend *backend);
+void cal_backend_start_query (CalBackend *backend, Query *query);
-CalBackendResult cal_backend_update_objects (CalBackend *backend, const char *calobj, CalObjModType mod);
+CalMode cal_backend_get_mode (CalBackend *backend);
+void cal_backend_set_mode (CalBackend *backend, CalMode mode);
-CalBackendResult cal_backend_remove_object (CalBackend *backend, const char *uid, CalObjModType mod);
+void cal_backend_get_timezone (CalBackend *backend, Cal *cal, const char *tzid);
+void cal_backend_add_timezone (CalBackend *backend, Cal *cal, const char *object);
+void cal_backend_set_default_timezone (CalBackend *backend, Cal *cal, const char *tzid);
-CalBackendSendResult cal_backend_send_object (CalBackend *backend, const char *calobj, char **new_calobj,
- GNOME_Evolution_Calendar_UserList **user_list,
- char error_msg[256]);
+void cal_backend_get_changes (CalBackend *backend, Cal *cal, CalObjType type, const char *change_id);
+void cal_backend_get_free_busy (CalBackend *backend, Cal *cal, GList *users, time_t start, time_t end);
-icaltimezone* cal_backend_get_timezone (CalBackend *backend, const char *tzid);
-icaltimezone* cal_backend_get_default_timezone (CalBackend *backend);
+icaltimezone* cal_backend_internal_get_default_timezone (CalBackend *backend);
+icaltimezone* cal_backend_internal_get_timezone (CalBackend *backend, const char *tzid);
void cal_backend_last_client_gone (CalBackend *backend);
-void cal_backend_opened (CalBackend *backend, CalBackendOpenStatus status);
-void cal_backend_obj_updated (CalBackend *backend, const char *uid);
-void cal_backend_obj_removed (CalBackend *backend, const char *uid);
+
+/* FIXME what to do about status */
+void cal_backend_opened (CalBackend *backend, int status);
+void cal_backend_removed (CalBackend *backend, int status);
void cal_backend_notify_mode (CalBackend *backend,
GNOME_Evolution_Calendar_Listener_SetModeStatus status,
GNOME_Evolution_Calendar_CalMode mode);
-void cal_backend_notify_update (CalBackend *backend, const char *uid);
-void cal_backend_notify_remove (CalBackend *backend, const char *uid);
void cal_backend_notify_error (CalBackend *backend, const char *message);
void cal_backend_ref_categories (CalBackend *backend, GSList *categories);
void cal_backend_unref_categories (CalBackend *backend, GSList *categories);
diff --git a/calendar/pcs/cal-common.h b/calendar/pcs/cal-common.h
index 3bf229ee8f..5a588c93c8 100644
--- a/calendar/pcs/cal-common.h
+++ b/calendar/pcs/cal-common.h
@@ -34,6 +34,12 @@ typedef struct _CalBackendClass CalBackendClass;
typedef struct _Cal Cal;
typedef struct _CalClass CalClass;
+typedef struct _Query Query;
+typedef struct _QueryClass QueryClass;
+
+typedef struct _CalBackendObjectSExp CalBackendObjectSExp;
+typedef struct _CalBackendObjectSExpClass CalBackendObjectSExpClass;
+
G_END_DECLS
diff --git a/calendar/pcs/cal-factory.c b/calendar/pcs/cal-factory.c
index 48df951544..2f72ec5911 100644
--- a/calendar/pcs/cal-factory.c
+++ b/calendar/pcs/cal-factory.c
@@ -1,9 +1,10 @@
/* Evolution calendar factory
*
- * Copyright (C) 2000 Ximian, Inc.
- * Copyright (C) 2000 Ximian, Inc.
+ * Copyright (C) 2000-2003 Ximian, Inc.
*
- * Author: Federico Mena-Quintero <federico@ximian.com>
+ * Authors:
+ * Federico Mena-Quintero <federico@ximian.com>
+ * JP Rosevear <jpr@ximian.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -19,16 +20,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
-#include <config.h>
-#include <ctype.h>
-#include <stdio.h>
#include <bonobo-activation/bonobo-activation.h>
+#include <bonobo/bonobo-exception.h>
+#include <bonobo/bonobo-main.h>
#include "e-util/e-url.h"
#include "evolution-calendar.h"
-#include "cal.h"
#include "cal-backend.h"
+#include "cal.h"
#include "cal-factory.h"
-#include "job.h"
#define PARENT_TYPE BONOBO_TYPE_OBJECT
#define DEFAULT_CAL_FACTORY_OAF_ID "OAFIID:GNOME_Evolution_Wombat_CalendarFactory"
@@ -50,13 +49,6 @@ struct _CalFactoryPrivate {
guint registered : 1;
};
-typedef struct
-{
- CalFactory *factory;
- GNOME_Evolution_Calendar_CalMode mode;
- GNOME_Evolution_Calendar_StringSeq *list;
-} CalFactoryUriData;
-
/* Signal IDs */
enum SIGNALS {
LAST_CALENDAR_GONE,
@@ -65,76 +57,61 @@ enum SIGNALS {
static guint signals[LAST_SIGNAL];
-/* Frees a method/GType * pair from the methods hash table */
-static void
-free_method (gpointer key, gpointer value, gpointer data)
+/* Opening calendars */
+static icalcomponent_kind
+calobjtype_to_icalkind (const GNOME_Evolution_Calendar_CalObjType type)
{
- char *method;
- GType *type;
-
- method = key;
- type = value;
-
- g_free (method);
- g_free (type);
+ switch (type){
+ case GNOME_Evolution_Calendar_TYPE_EVENT:
+ return ICAL_VEVENT_COMPONENT;
+ case GNOME_Evolution_Calendar_TYPE_TODO:
+ return ICAL_VTODO_COMPONENT;
+ case GNOME_Evolution_Calendar_TYPE_JOURNAL:
+ return ICAL_VJOURNAL_COMPONENT;
+ }
+
+ return ICAL_NO_COMPONENT;
}
-/* Frees a uri/backend pair from the backends hash table */
-static void
-free_backend (gpointer key, gpointer value, gpointer data)
+static GType
+get_backend_type (GHashTable *methods, const char *method, icalcomponent_kind kind)
{
- char *uri;
- CalBackend *backend;
+ GHashTable *kinds;
+ GType type;
+
+ kinds = g_hash_table_lookup (methods, method);
+ if (!kinds)
+ return 0;
- uri = key;
- backend = value;
+ type = GPOINTER_TO_INT (g_hash_table_lookup (kinds, GINT_TO_POINTER (kind)));
- g_free (uri);
- g_object_unref (backend);
+ return type;
}
-/* Opening calendars */
-
/* Looks up a calendar backend in a factory's hash table of uri->cal. If
* *non-NULL, orig_uri_return will be set to point to the original key in the
* *hash table.
*/
static CalBackend *
-lookup_backend (CalFactory *factory, const char *uristr, char **orig_uri_return)
+lookup_backend (CalFactory *factory, const char *uristr)
{
CalFactoryPrivate *priv;
EUri *uri;
+ CalBackend *backend;
char *tmp;
- gboolean found;
- gpointer orig_key;
- gpointer data;
priv = factory->priv;
uri = e_uri_new (uristr);
- if (!uri) {
- if (orig_uri_return)
- *orig_uri_return = NULL;
-
+ if (!uri)
return NULL;
- }
tmp = e_uri_to_string (uri, FALSE);
- found = g_hash_table_lookup_extended (priv->backends, tmp, &orig_key, &data);
+ backend = g_hash_table_lookup (priv->backends, tmp);
g_free (tmp);
e_uri_free (uri);
- if (found) {
- if (orig_uri_return)
- *orig_uri_return = orig_key;
-
- return CAL_BACKEND (data);
- } else {
- if (orig_uri_return)
- *orig_uri_return = NULL;
-
- return NULL;
- }
+ return backend;
}
/* Callback used when a backend loses its last connected client */
@@ -145,7 +122,6 @@ backend_last_client_gone_cb (CalBackend *backend, gpointer data)
CalFactoryPrivate *priv;
CalBackend *ret_backend;
const char *uristr;
- char *orig_uristr;
fprintf (stderr, "backend_last_client_gone_cb() called!\n");
@@ -157,14 +133,11 @@ backend_last_client_gone_cb (CalBackend *backend, gpointer data)
uristr = cal_backend_get_uri (backend);
g_assert (uristr != NULL);
- ret_backend = lookup_backend (factory, uristr, &orig_uristr);
+ ret_backend = lookup_backend (factory, uristr);
g_assert (ret_backend != NULL);
g_assert (ret_backend == backend);
- g_hash_table_remove (priv->backends, orig_uristr);
- g_free (orig_uristr);
-
- g_object_unref (backend);
+ g_hash_table_remove (priv->backends, uristr);
/* Notify upstream if there are no more backends */
@@ -172,405 +145,92 @@ backend_last_client_gone_cb (CalBackend *backend, gpointer data)
g_signal_emit (G_OBJECT (factory), signals[LAST_CALENDAR_GONE], 0);
}
-/* Adds a backend to the calendar factory's hash table */
-static void
-add_backend (CalFactory *factory, const char *uristr, CalBackend *backend)
-{
- CalFactoryPrivate *priv;
- EUri *uri;
- char *tmp;
-
- priv = factory->priv;
-
- uri = e_uri_new (uristr);
- if (!uri)
- return;
-
- tmp = e_uri_to_string (uri, FALSE);
- g_hash_table_insert (priv->backends, tmp, backend);
- e_uri_free (uri);
-
- g_signal_connect (G_OBJECT (backend), "last_client_gone",
- G_CALLBACK (backend_last_client_gone_cb),
- factory);
-}
-
-/* Tries to launch a backend for the method of the specified URI. If there is
- * no such method registered in the factory, it sends the listener the
- * MethodNotSupported error code.
- */
-static CalBackend *
-launch_backend_for_uri (CalFactory *factory,
- const char *uristr,
- GNOME_Evolution_Calendar_Listener listener)
-{
- CalFactoryPrivate *priv;
- const char *method;
- GType *type;
- CalBackend *backend;
- EUri *uri;
-
- priv = factory->priv;
-
- uri = e_uri_new (uristr);
- if (!uri)
- return NULL;
-
- method = uri->protocol;
- type = g_hash_table_lookup (priv->methods, method);
- e_uri_free (uri);
-
- if (!type) {
- CORBA_Environment ev;
-
- CORBA_exception_init (&ev);
- GNOME_Evolution_Calendar_Listener_notifyCalOpened (
- listener,
- GNOME_Evolution_Calendar_Listener_METHOD_NOT_SUPPORTED,
- CORBA_OBJECT_NIL,
- &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION)
- g_message ("launch_backend_for_uri(): could not notify the listener");
-
- CORBA_exception_free (&ev);
- return NULL;
- }
-
- backend = g_object_new (*type, NULL);
- if (!backend)
- g_message ("launch_backend_for_uri(): could not launch the backend");
-
- return backend;
-}
-
-/* Opens a calendar backend and puts it in the factory's backend hash table */
-static CalBackend *
-open_backend (CalFactory *factory, const char *uristr, gboolean only_if_exists,
- GNOME_Evolution_Calendar_Listener listener)
-{
- CalFactoryPrivate *priv;
- CalBackend *backend;
- CalBackendOpenStatus status;
- CORBA_Environment ev;
-
- priv = factory->priv;
-
- backend = launch_backend_for_uri (factory, uristr, listener);
- if (!backend)
- return NULL;
-
- status = cal_backend_open (backend, uristr, only_if_exists);
-
- switch (status) {
- case CAL_BACKEND_OPEN_SUCCESS:
- add_backend (factory, uristr, backend);
- return backend;
-
- case CAL_BACKEND_OPEN_ERROR:
- g_object_unref (backend);
-
- CORBA_exception_init (&ev);
- GNOME_Evolution_Calendar_Listener_notifyCalOpened (
- listener,
- GNOME_Evolution_Calendar_Listener_ERROR,
- CORBA_OBJECT_NIL,
- &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION)
- g_message ("open_backend(): could not notify the listener");
-
- CORBA_exception_free (&ev);
- return NULL;
-
- case CAL_BACKEND_OPEN_NOT_FOUND:
- g_object_unref (backend);
-
- CORBA_exception_init (&ev);
- GNOME_Evolution_Calendar_Listener_notifyCalOpened (
- listener,
- GNOME_Evolution_Calendar_Listener_NOT_FOUND,
- CORBA_OBJECT_NIL,
- &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION)
- g_message ("open_backend(): could not notify the listener");
-
- CORBA_exception_free (&ev);
- return NULL;
-
- case CAL_BACKEND_OPEN_PERMISSION_DENIED :
- g_object_unref (backend);
-
- CORBA_exception_init (&ev);
- GNOME_Evolution_Calendar_Listener_notifyCalOpened (
- listener,
- GNOME_Evolution_Calendar_Listener_PERMISSION_DENIED,
- CORBA_OBJECT_NIL,
- &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION)
- g_message ("open_backend(): could not notify the listener");
-
- CORBA_exception_free (&ev);
- return NULL;
-
- default:
- g_assert_not_reached ();
- return NULL;
- }
-}
-
-/* Adds a listener to a calendar backend by creating a calendar client interface
- * object.
- */
-static void
-add_calendar_client (CalFactory *factory,
- CalBackend *backend,
- GNOME_Evolution_Calendar_Listener listener)
-{
- Cal *cal;
- CORBA_Environment ev;
-
- cal = cal_new (backend, listener);
- if (!cal) {
- g_message ("add_calendar_client(): could not create the calendar client interface");
-
- CORBA_exception_init (&ev);
- GNOME_Evolution_Calendar_Listener_notifyCalOpened (
- listener,
- GNOME_Evolution_Calendar_Listener_ERROR,
- CORBA_OBJECT_NIL,
- &ev);
- if (ev._major != CORBA_NO_EXCEPTION)
- g_message ("add_calendar_client(): could not notify the listener");
-
- CORBA_exception_free (&ev);
- return;
- }
-
- cal_backend_add_cal (backend, cal);
-
- CORBA_exception_init (&ev);
- GNOME_Evolution_Calendar_Listener_notifyCalOpened (
- listener,
- GNOME_Evolution_Calendar_Listener_SUCCESS,
- BONOBO_OBJREF (cal),
- &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_message ("add_calendar_client(): could not notify the listener");
- bonobo_object_unref (BONOBO_OBJECT (cal));
- }
-
- CORBA_exception_free (&ev);
-}
-
-/* Add a uri to a string list */
-static void
-add_uri (gpointer key, gpointer value, gpointer data)
-{
- CalFactoryUriData *cfud = data;
- CalFactory *factory = cfud->factory;
- GNOME_Evolution_Calendar_StringSeq *list = cfud->list;
- GNOME_Evolution_Calendar_CalMode mode = cfud->mode;
- char *uri_string = key;
- CalBackend *backend;
-
- switch (mode) {
- case GNOME_Evolution_Calendar_MODE_LOCAL:
- backend = lookup_backend (factory, uri_string, NULL);
- if (backend == NULL || cal_backend_get_mode (backend) != CAL_MODE_LOCAL)
- return;
- break;
- case GNOME_Evolution_Calendar_MODE_REMOTE:
- backend = lookup_backend (factory, uri_string, NULL);
- if (backend == NULL || cal_backend_get_mode (backend) != CAL_MODE_REMOTE)
- return;
- break;
- case GNOME_Evolution_Calendar_MODE_ANY:
- break;
- }
-
- list->_buffer[list->_length] = CORBA_string_dup (uri_string);
- list->_length++;
-}
-
-/* Job data */
-typedef struct {
- CalFactory *factory;
- char *uri;
- gboolean only_if_exists;
- GNOME_Evolution_Calendar_Listener listener;
-} OpenJobData;
-
-/* Job handler for the open calendar command */
-static void
-open_fn (gpointer data)
-{
- OpenJobData *jd;
- CalFactory *factory;
- gboolean only_if_exists;
- GNOME_Evolution_Calendar_Listener listener;
- CalBackend *backend;
- CORBA_Environment ev;
- char *uri_string;
-
- jd = data;
- g_assert (jd->uri != NULL);
-
- /* Check the URI */
- uri_string = g_strdup (jd->uri);
- g_free (jd->uri);
-
- only_if_exists = jd->only_if_exists;
- factory = jd->factory;
- listener = jd->listener;
- g_free (jd);
-
- if (!uri_string) {
- CORBA_exception_init (&ev);
- GNOME_Evolution_Calendar_Listener_notifyCalOpened (
- listener,
- GNOME_Evolution_Calendar_Listener_ERROR,
- CORBA_OBJECT_NIL,
- &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION)
- g_message ("open_fn(): Could not notify the listener!");
-
- CORBA_exception_free (&ev);
- goto out;
- }
-
- /* Look up the backend and create it if needed */
-
- backend = lookup_backend (factory, uri_string, NULL);
-
- if (!backend)
- backend = open_backend (factory, uri_string, only_if_exists, listener);
-
- g_free (uri_string);
-
- if (backend)
- add_calendar_client (factory, backend, listener);
-
- out:
-
- CORBA_exception_init (&ev);
- CORBA_Object_release (listener, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION)
- g_message ("open_fn(): could not release the listener");
-
- CORBA_exception_free (&ev);
-}
-
-static void
-impl_CalFactory_open (PortableServer_Servant servant,
- const CORBA_char *str_uri,
- CORBA_boolean only_if_exists,
- GNOME_Evolution_Calendar_Listener listener,
- CORBA_Environment *ev)
+static GNOME_Evolution_Calendar_Cal
+impl_CalFactory_getCal (PortableServer_Servant servant,
+ const CORBA_char *str_uri,
+ const GNOME_Evolution_Calendar_CalObjType type,
+ const GNOME_Evolution_Calendar_Listener listener,
+ CORBA_Environment *ev)
{
CalFactory *factory;
CalFactoryPrivate *priv;
+ Cal *cal = CORBA_OBJECT_NIL;
+ CalBackend *backend;
CORBA_Environment ev2;
- gboolean result;
- OpenJobData *jd;
GNOME_Evolution_Calendar_Listener listener_copy;
- GType *type;
+ GType backend_type;
EUri *uri;
-
+ char *uri_string;
+
factory = CAL_FACTORY (bonobo_object_from_servant (servant));
priv = factory->priv;
- /* check URI to see if we support it */
-
+ /* Parse the uri */
uri = e_uri_new (str_uri);
if (!uri) {
- CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
- ex_GNOME_Evolution_Calendar_CalFactory_InvalidURI,
- NULL);
- return;
- }
-
- type = g_hash_table_lookup (priv->methods, uri->protocol);
+ bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_CalFactory_InvalidURI);
- e_uri_free (uri);
- if (!type) {
- CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
- ex_GNOME_Evolution_Calendar_CalFactory_UnsupportedMethod,
- NULL);
- return;
+ return CORBA_OBJECT_NIL;
}
-
- /* duplicate the listener object */
- CORBA_exception_init (&ev2);
- result = CORBA_Object_is_nil (listener, &ev2);
-
- if (ev2._major != CORBA_NO_EXCEPTION || result) {
- CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
- ex_GNOME_Evolution_Calendar_CalFactory_NilListener,
- NULL);
-
- CORBA_exception_free (&ev2);
- return;
+ uri_string = e_uri_to_string (uri, FALSE);
+
+ /* Find the associated backend type (if any) */
+ backend_type = get_backend_type (priv->methods, uri->protocol, calobjtype_to_icalkind (type));
+ if (!backend_type) {
+ /* FIXME Distinguish between method and kind failures? */
+ bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_CalFactory_UnsupportedMethod);
+ goto cleanup;
}
- CORBA_exception_free (&ev2);
-
+
+ /* Duplicate the listener object */
CORBA_exception_init (&ev2);
listener_copy = CORBA_Object_duplicate (listener, &ev2);
- if (ev2._major != CORBA_NO_EXCEPTION) {
- g_message ("CalFactory_open(): could not duplicate the listener");
+ if (BONOBO_EX (&ev2)) {
+ g_warning (G_STRLOC ": could not duplicate the listener");
+ bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_CalFactory_NilListener);
CORBA_exception_free (&ev2);
- CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
- ex_GNOME_Evolution_Calendar_CalFactory_NilListener,
- NULL);
- return;
+ goto cleanup;
}
-
CORBA_exception_free (&ev2);
- /* add new asynchronous job */
- jd = g_new (OpenJobData, 1);
- jd->factory = factory;
- jd->uri = g_strdup (str_uri);
- jd->only_if_exists = only_if_exists;
- jd->listener = listener_copy;
-
- job_add (open_fn, jd);
-}
-
-static GNOME_Evolution_Calendar_StringSeq *
-impl_CalFactory_uriList (PortableServer_Servant servant,
- GNOME_Evolution_Calendar_CalMode mode,
- CORBA_Environment *ev)
-{
- CalFactory *factory;
- CalFactoryPrivate *priv;
- CalFactoryUriData cfud;
- GNOME_Evolution_Calendar_StringSeq *list;
-
- factory = CAL_FACTORY (bonobo_object_from_servant (servant));
- priv = factory->priv;
-
- list = GNOME_Evolution_Calendar_StringSeq__alloc ();
- CORBA_sequence_set_release (list, TRUE);
- list->_length = 0;
- list->_maximum = g_hash_table_size (priv->backends);
- list->_buffer = CORBA_sequence_CORBA_string_allocbuf (list->_maximum);
+ /* Look for an existing backend */
+ backend = lookup_backend (factory, uri_string);
+ if (!backend) {
+ /* There was no existing backend, create a new one */
+ backend = g_object_new (backend_type, "uri", uri_string, "kind", calobjtype_to_icalkind (type), NULL);
+ if (!backend) {
+ g_warning (G_STRLOC ": could not instantiate backend");
+ bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_CalFactory_UnsupportedMethod);
+ goto cleanup;
+ }
+
+ /* Track the backend */
+ g_hash_table_insert (priv->backends, g_strdup (uri_string), backend);
+
+ g_signal_connect (G_OBJECT (backend), "last_client_gone",
+ G_CALLBACK (backend_last_client_gone_cb),
+ factory);
+ }
+
+ /* Create the corba calendar */
+ cal = cal_new (backend, uri_string, listener);
+ if (!cal) {
+ g_warning (G_STRLOC ": could not create the corba calendar");
+ bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_CalFactory_UnsupportedMethod);
+ goto cleanup;
+ }
- cfud.factory = factory;
- cfud.mode = mode;
- cfud.list = list;
- g_hash_table_foreach (priv->backends, add_uri, &cfud);
+ /* Let the backend know about its clients corba clients */
+ cal_backend_add_client (backend, cal);
- return list;
+ cleanup:
+ e_uri_free (uri);
+ g_free (uri_string);
+ return CORBA_Object_duplicate (BONOBO_OBJREF (cal), ev);
}
@@ -589,7 +249,9 @@ cal_factory_new (void)
{
CalFactory *factory;
- factory = g_object_new (CAL_FACTORY_TYPE, NULL);
+ factory = g_object_new (CAL_FACTORY_TYPE,
+ "poa", bonobo_poa_get_threaded (ORBIT_THREAD_HINT_PER_REQUEST, NULL),
+ NULL);
return factory;
}
@@ -607,13 +269,10 @@ cal_factory_finalize (GObject *object)
factory = CAL_FACTORY (object);
priv = factory->priv;
- g_hash_table_foreach (priv->methods, free_method, NULL);
g_hash_table_destroy (priv->methods);
priv->methods = NULL;
/* Should we assert that there are no more backends? */
-
- g_hash_table_foreach (priv->backends, free_backend, NULL);
g_hash_table_destroy (priv->backends);
priv->backends = NULL;
@@ -652,8 +311,7 @@ cal_factory_class_init (CalFactoryClass *klass)
object_class->finalize = cal_factory_finalize;
/* Epv methods */
- epv->open = impl_CalFactory_open;
- epv->uriList = impl_CalFactory_uriList;
+ epv->getCal = impl_CalFactory_getCal;
}
/* Object initialization function for the calendar factory */
@@ -665,8 +323,10 @@ cal_factory_init (CalFactory *factory, CalFactoryClass *klass)
priv = g_new0 (CalFactoryPrivate, 1);
factory->priv = priv;
- priv->methods = g_hash_table_new (g_str_hash, g_str_equal);
- priv->backends = g_hash_table_new (g_str_hash, g_str_equal);
+ priv->methods = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free, (GDestroyNotify) g_hash_table_destroy);
+ priv->backends = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free, (GDestroyNotify) g_object_unref);
priv->registered = FALSE;
}
@@ -675,23 +335,8 @@ BONOBO_TYPE_FUNC_FULL (CalFactory,
PARENT_TYPE,
cal_factory);
-/* Returns the lowercase version of a string */
-static char *
-str_tolower (const char *s)
-{
- char *str;
- unsigned char *p;
-
- str = g_strdup (s);
- for (p = str; *p; p++)
- if (isalpha (*p))
- *p = tolower (*p);
-
- return str;
-}
-
/**
- * cal_factory_oaf_register:
+ * cal_factory_register_storage:
* @factory: A calendar factory.
* @iid: OAFIID for the factory to be registered.
*
@@ -701,7 +346,7 @@ str_tolower (const char *s)
* Return value: TRUE on success, FALSE otherwise.
**/
gboolean
-cal_factory_oaf_register (CalFactory *factory, const char *iid)
+cal_factory_register_storage (CalFactory *factory, const char *iid)
{
CalFactoryPrivate *priv;
Bonobo_RegistrationResult result;
@@ -729,19 +374,16 @@ cal_factory_oaf_register (CalFactory *factory, const char *iid)
return TRUE;
case Bonobo_ACTIVATION_REG_NOT_LISTED:
- g_message ("cal_factory_oaf_register(): Cannot register the calendar factory: "
- "not listed");
+ g_warning (G_STRLOC ": cannot register the calendar factory (not listed)");
break;
case Bonobo_ACTIVATION_REG_ALREADY_ACTIVE:
- g_message ("cal_factory_oaf_register(): Cannot register the calendar factory: "
- "already active");
+ g_warning (G_STRLOC ": cannot register the calendar factory (already active)");
break;
case Bonobo_ACTIVATION_REG_ERROR:
default:
- g_message ("cal_factory_oaf_register(): Cannot register the calendar factory: "
- "generic error");
+ g_warning (G_STRLOC ": cannot register the calendar factory (generic error)");
break;
}
@@ -762,12 +404,13 @@ cal_factory_oaf_register (CalFactory *factory, const char *iid)
* the appropriate type.
**/
void
-cal_factory_register_method (CalFactory *factory, const char *method, GType backend_type)
+cal_factory_register_method (CalFactory *factory, const char *method, icalcomponent_kind kind, GType backend_type)
{
CalFactoryPrivate *priv;
- GType *type;
char *method_str;
-
+ GHashTable *kinds;
+ GType type;
+
g_return_if_fail (factory != NULL);
g_return_if_fail (IS_CAL_FACTORY (factory));
g_return_if_fail (method != NULL);
@@ -776,37 +419,39 @@ cal_factory_register_method (CalFactory *factory, const char *method, GType back
priv = factory->priv;
- method_str = str_tolower (method);
-
- type = g_hash_table_lookup (priv->methods, method_str);
- if (type) {
- g_message ("cal_factory_register_method(): Method `%s' already registered!",
- method_str);
- g_free (method_str);
- return;
- }
+ method_str = g_ascii_strdown (method, -1);
- type = g_new (GType, 1);
- *type = backend_type;
+ kinds = g_hash_table_lookup (priv->methods, method_str);
+ if (kinds) {
+ type = GPOINTER_TO_INT (g_hash_table_lookup (kinds, GINT_TO_POINTER (kind)));
+ if (type) {
+ g_warning (G_STRLOC ": method `%s' already registered", method_str);
+ g_free (method_str);
- g_hash_table_insert (priv->methods, method_str, type);
+ return;
+ }
+ } else {
+ kinds = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
+ g_hash_table_insert (priv->methods, method_str, kinds);
+ }
+
+ g_hash_table_insert (kinds, GINT_TO_POINTER (kind), GINT_TO_POINTER (backend_type));
}
/**
- * cal_factory_get_n_backends:
+ * cal_factory_get_n_backends
* @factory: A calendar factory.
- *
- * Queries the number of running calendar backends in a calendar factory.
- *
- * Return value: Number of running backends.
- **/
+ *
+ * Get the number of backends currently active in the given factory.
+ *
+ * Returns: the number of backends.
+ */
int
cal_factory_get_n_backends (CalFactory *factory)
{
CalFactoryPrivate *priv;
- g_return_val_if_fail (factory != NULL, -1);
- g_return_val_if_fail (IS_CAL_FACTORY (factory), -1);
+ g_return_val_if_fail (IS_CAL_FACTORY (factory), 0);
priv = factory->priv;
return g_hash_table_size (priv->backends);
diff --git a/calendar/pcs/cal-factory.h b/calendar/pcs/cal-factory.h
index b7c370066b..d6d2b895ed 100644
--- a/calendar/pcs/cal-factory.h
+++ b/calendar/pcs/cal-factory.h
@@ -22,6 +22,7 @@
#define CAL_FACTORY_H
#include <bonobo/bonobo-object.h>
+#include <libical/ical.h>
#include "pcs/evolution-calendar.h"
@@ -60,11 +61,12 @@ struct _CalFactoryClass {
GType cal_factory_get_type (void);
CalFactory *cal_factory_new (void);
-gboolean cal_factory_oaf_register (CalFactory *factory, const char *iid);
-void cal_factory_register_method (CalFactory *factory,
- const char *method,
- GType backend_type);
-int cal_factory_get_n_backends (CalFactory *factory);
+gboolean cal_factory_register_storage (CalFactory *factory, const char *iid);
+void cal_factory_register_method (CalFactory *factory,
+ const char *method,
+ icalcomponent_kind kind,
+ GType backend_type);
+int cal_factory_get_n_backends (CalFactory *factory);
void cal_factory_dump_active_backends (CalFactory *factory);
G_END_DECLS
diff --git a/calendar/pcs/cal.c b/calendar/pcs/cal.c
index 0f20d88186..a88e9a146c 100644
--- a/calendar/pcs/cal.c
+++ b/calendar/pcs/cal.c
@@ -25,10 +25,10 @@
#endif
#include <libical/ical.h>
+#include <bonobo/bonobo-main.h>
#include <bonobo/bonobo-exception.h>
-#include "cal.h"
#include "cal-backend.h"
-#include "query.h"
+#include "cal.h"
#define PARENT_TYPE BONOBO_TYPE_OBJECT
@@ -43,7 +43,6 @@ struct _CalPrivate {
GNOME_Evolution_Calendar_Listener listener;
};
-
/* Cal::get_uri method */
static CORBA_char *
impl_Cal_get_uri (PortableServer_Servant servant,
@@ -63,8 +62,35 @@ impl_Cal_get_uri (PortableServer_Servant servant,
return str_uri_copy;
}
+static void
+impl_Cal_open (PortableServer_Servant servant,
+ CORBA_boolean only_if_exists,
+ CORBA_Environment *ev)
+{
+ Cal *cal;
+ CalPrivate *priv;
+
+ cal = CAL (bonobo_object_from_servant (servant));
+ priv = cal->priv;
+
+ cal_backend_open (priv->backend, cal, only_if_exists);
+}
+
+static void
+impl_Cal_remove (PortableServer_Servant servant,
+ CORBA_Environment *ev)
+{
+ Cal *cal;
+ CalPrivate *priv;
+
+ cal = CAL (bonobo_object_from_servant (servant));
+ priv = cal->priv;
+
+ cal_backend_remove (priv->backend, cal);
+}
+
/* Cal::isReadOnly method */
-static CORBA_boolean
+static void
impl_Cal_isReadOnly (PortableServer_Servant servant,
CORBA_Environment *ev)
{
@@ -74,109 +100,63 @@ impl_Cal_isReadOnly (PortableServer_Servant servant,
cal = CAL (bonobo_object_from_servant (servant));
priv = cal->priv;
- return cal_backend_is_read_only (priv->backend);
+ cal_backend_is_read_only (priv->backend, cal);
}
/* Cal::getEmailAddress method */
-static CORBA_char *
+static void
impl_Cal_getCalAddress (PortableServer_Servant servant,
- CORBA_Environment *ev)
+ CORBA_Environment *ev)
{
Cal *cal;
CalPrivate *priv;
- const char *str_cal_address;
- CORBA_char *str_cal_address_copy;
cal = CAL (bonobo_object_from_servant (servant));
priv = cal->priv;
- str_cal_address = cal_backend_get_cal_address (priv->backend);
- if (str_cal_address == NULL) {
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_NotFound);
- return CORBA_OBJECT_NIL;
- }
-
- str_cal_address_copy = CORBA_string_dup (str_cal_address);
-
- return str_cal_address_copy;
+ cal_backend_get_cal_address (priv->backend, cal);
}
/* Cal::get_alarm_email_address method */
-static CORBA_char *
+static void
impl_Cal_getAlarmEmailAddress (PortableServer_Servant servant,
CORBA_Environment *ev)
{
Cal *cal;
CalPrivate *priv;
- const char *str_email_address;
- CORBA_char *str_email_address_copy;
-
+
cal = CAL (bonobo_object_from_servant (servant));
priv = cal->priv;
-
- str_email_address = cal_backend_get_alarm_email_address (priv->backend);
- if (str_email_address == NULL) {
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_NotFound);
- return CORBA_OBJECT_NIL;
- }
-
- str_email_address_copy = CORBA_string_dup (str_email_address);
- return str_email_address_copy;
+ cal_backend_get_alarm_email_address (priv->backend, cal);
}
/* Cal::get_ldap_attribute method */
-static CORBA_char *
+static void
impl_Cal_getLdapAttribute (PortableServer_Servant servant,
CORBA_Environment *ev)
{
Cal *cal;
CalPrivate *priv;
- const char *str_ldap_attr;
- CORBA_char *str_ldap_attr_copy;
cal = CAL (bonobo_object_from_servant (servant));
priv = cal->priv;
- str_ldap_attr = cal_backend_get_ldap_attribute (priv->backend);
- if (str_ldap_attr == NULL) {
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_NotFound);
- return CORBA_OBJECT_NIL;
- }
-
- str_ldap_attr_copy = CORBA_string_dup (str_ldap_attr);
-
- return str_ldap_attr_copy;
+ cal_backend_get_ldap_attribute (priv->backend, cal);
}
/* Cal::getSchedulingInformation method */
-static CORBA_char *
+static void
impl_Cal_getStaticCapabilities (PortableServer_Servant servant,
CORBA_Environment *ev)
{
Cal *cal;
CalPrivate *priv;
- const char *cap;
- CORBA_char *cap_copy;
cal = CAL (bonobo_object_from_servant (servant));
priv = cal->priv;
- cap = cal_backend_get_static_capabilities (priv->backend);
- cap_copy = CORBA_string_dup (cap == NULL ? "" : cap);
-
- return cap_copy;
-}
-
-/* Converts a calendar object type from its CORBA representation to our own
- * representation.
- */
-static CalObjType
-uncorba_obj_type (GNOME_Evolution_Calendar_CalObjType type)
-{
- return (((type & GNOME_Evolution_Calendar_TYPE_EVENT) ? CALOBJ_TYPE_EVENT : 0)
- | ((type & GNOME_Evolution_Calendar_TYPE_TODO) ? CALOBJ_TYPE_TODO : 0)
- | ((type & GNOME_Evolution_Calendar_TYPE_JOURNAL) ? CALOBJ_TYPE_JOURNAL : 0));
+ cal_backend_get_static_capabilities (priv->backend, cal);
}
/* Cal::setMode method */
@@ -194,208 +174,68 @@ impl_Cal_setMode (PortableServer_Servant servant,
cal_backend_set_mode (priv->backend, mode);
}
-/* Cal::countObjects method */
-static CORBA_long
-impl_Cal_countObjects (PortableServer_Servant servant,
- GNOME_Evolution_Calendar_CalObjType type,
- CORBA_Environment *ev)
-{
- Cal *cal;
- CalPrivate *priv;
- int t;
- int n;
-
- cal = CAL (bonobo_object_from_servant (servant));
- priv = cal->priv;
-
- t = uncorba_obj_type (type);
- n = cal_backend_get_n_objects (priv->backend, t);
- return n;
-}
-
-static GNOME_Evolution_Calendar_CalObj
+static void
impl_Cal_getDefaultObject (PortableServer_Servant servant,
- GNOME_Evolution_Calendar_CalObjType type,
- CORBA_Environment *ev)
+ CORBA_Environment *ev)
{
Cal *cal;
CalPrivate *priv;
- GNOME_Evolution_Calendar_CalObj calobj_copy;
- char *calobj;
-
cal = CAL (bonobo_object_from_servant (servant));
priv = cal->priv;
- calobj = cal_backend_get_default_object (priv->backend, type);
- calobj_copy = CORBA_string_dup (calobj);
- g_free (calobj);
-
- return calobj_copy;
+ cal_backend_get_default_object (priv->backend, cal);
}
/* Cal::getObject method */
-static GNOME_Evolution_Calendar_CalObj
+static void
impl_Cal_getObject (PortableServer_Servant servant,
const CORBA_char *uid,
+ const CORBA_char *rid,
CORBA_Environment *ev)
{
Cal *cal;
CalPrivate *priv;
- char *calobj;
cal = CAL (bonobo_object_from_servant (servant));
priv = cal->priv;
- calobj = cal_backend_get_object (priv->backend, uid);
-
- if (calobj) {
- CORBA_char *calobj_copy;
-
- calobj_copy = CORBA_string_dup (calobj);
- g_free (calobj);
- return calobj_copy;
- } else {
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_NotFound);
-
- return NULL;
- }
-}
-
-static GNOME_Evolution_Calendar_CalObjUIDSeq *
-build_uid_seq (GList *uids)
-{
- GNOME_Evolution_Calendar_CalObjUIDSeq *seq;
- GList *l;
- int n, i;
-
- n = g_list_length (uids);
-
- seq = GNOME_Evolution_Calendar_CalObjUIDSeq__alloc ();
- CORBA_sequence_set_release (seq, TRUE);
- seq->_length = n;
- seq->_buffer = CORBA_sequence_GNOME_Evolution_Calendar_CalObjUID_allocbuf (n);
-
- /* Fill the sequence */
-
- for (i = 0, l = uids; l; i++, l = l->next) {
- char *uid;
-
- uid = l->data;
- seq->_buffer[i] = CORBA_string_dup (uid);
- }
-
- return seq;
+ cal_backend_get_object (priv->backend, cal, uid, rid);
}
-/* Cal::getUIDs method */
-static GNOME_Evolution_Calendar_CalObjUIDSeq *
-impl_Cal_getUIDs (PortableServer_Servant servant,
- GNOME_Evolution_Calendar_CalObjType type,
- CORBA_Environment *ev)
+/* Cal::getObjectsInRange method */
+static void
+impl_Cal_getObjectList (PortableServer_Servant servant,
+ const CORBA_char *query,
+ CORBA_Environment *ev)
{
Cal *cal;
CalPrivate *priv;
- GList *uids;
- GNOME_Evolution_Calendar_CalObjUIDSeq *seq;
- int t;
-
+
cal = CAL (bonobo_object_from_servant (servant));
priv = cal->priv;
- t = uncorba_obj_type (type);
-
- uids = cal_backend_get_uids (priv->backend, t);
- seq = build_uid_seq (uids);
-
- cal_obj_uid_list_free (uids);
-
- return seq;
+ cal_backend_get_object_list (priv->backend, cal, query);
}
/* Cal::getChanges method */
-static GNOME_Evolution_Calendar_CalObjChangeSeq *
+static void
impl_Cal_getChanges (PortableServer_Servant servant,
GNOME_Evolution_Calendar_CalObjType type,
const CORBA_char *change_id,
CORBA_Environment *ev)
{
- Cal *cal;
- CalPrivate *priv;
- int t;
-
- cal = CAL (bonobo_object_from_servant (servant));
- priv = cal->priv;
-
- t = uncorba_obj_type (type);
-
- return cal_backend_get_changes (priv->backend, t, change_id);
-}
-
-/* Cal::getObjectsInRange method */
-static GNOME_Evolution_Calendar_CalObjUIDSeq *
-impl_Cal_getObjectsInRange (PortableServer_Servant servant,
- GNOME_Evolution_Calendar_CalObjType type,
- GNOME_Evolution_Calendar_Time_t start,
- GNOME_Evolution_Calendar_Time_t end,
- CORBA_Environment *ev)
-{
- Cal *cal;
- CalPrivate *priv;
- int t;
- time_t t_start, t_end;
- GNOME_Evolution_Calendar_CalObjUIDSeq *seq;
- GList *uids;
-
- cal = CAL (bonobo_object_from_servant (servant));
- priv = cal->priv;
-
- t = uncorba_obj_type (type);
- t_start = (time_t) start;
- t_end = (time_t) end;
-
- if (t_start > t_end || t_start == -1 || t_end == -1) {
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_InvalidRange);
- return NULL;
- }
-
- uids = cal_backend_get_objects_in_range (priv->backend, t, t_start, t_end);
- seq = build_uid_seq (uids);
-
- cal_obj_uid_list_free (uids);
-
- return seq;
-}
-
-static GNOME_Evolution_Calendar_CalObjSeq *
-build_fb_seq (GList *obj_list)
-{
- GNOME_Evolution_Calendar_CalObjSeq *seq;
- GList *l;
- int n, i;
-
- n = g_list_length (obj_list);
-
- seq = GNOME_Evolution_Calendar_CalObjSeq__alloc ();
- CORBA_sequence_set_release (seq, TRUE);
- seq->_maximum = n;
- seq->_length = n;
- seq->_buffer = CORBA_sequence_GNOME_Evolution_Calendar_CalObj_allocbuf (n);
+ Cal *cal;
+ CalPrivate *priv;
- /* Fill the sequence */
+ cal = CAL (bonobo_object_from_servant (servant));
+ priv = cal->priv;
- for (i = 0, l = obj_list; l; i++, l = l->next) {
- char *calobj;
-
- calobj = l->data;
- seq->_buffer[i] = CORBA_string_dup (calobj);
- }
-
- return seq;
+ cal_backend_get_changes (priv->backend, cal, type, change_id);
}
/* Cal::getFreeBusy method */
-static GNOME_Evolution_Calendar_CalObjSeq *
+static void
impl_Cal_getFreeBusy (PortableServer_Servant servant,
const GNOME_Evolution_Calendar_UserList *user_list,
const GNOME_Evolution_Calendar_Time_t start,
@@ -404,22 +244,11 @@ impl_Cal_getFreeBusy (PortableServer_Servant servant,
{
Cal *cal;
CalPrivate *priv;
- time_t t_start, t_end;
GList *users = NULL;
- GList *obj_list;
- GNOME_Evolution_Calendar_CalObjSeq *seq;
cal = CAL (bonobo_object_from_servant (servant));
priv = cal->priv;
- t_start = (time_t) start;
- t_end = (time_t) end;
-
- if (t_start > t_end || t_start == -1 || t_end == -1) {
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_InvalidRange);
- return build_fb_seq (NULL);
- }
-
/* convert the CORBA user list to a GList */
if (user_list) {
int i;
@@ -429,297 +258,181 @@ impl_Cal_getFreeBusy (PortableServer_Servant servant,
}
/* call the backend's get_free_busy method */
- obj_list = cal_backend_get_free_busy (priv->backend, users, t_start, t_end);
- seq = build_fb_seq (obj_list);
- g_list_free (users);
-
- if (obj_list == NULL)
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_NotFound);
-
- return seq;
+ cal_backend_get_free_busy (priv->backend, cal, users, start, end);
}
-/* Cal::getAlarmsInRange method */
-static GNOME_Evolution_Calendar_CalComponentAlarmsSeq *
-impl_Cal_getAlarmsInRange (PortableServer_Servant servant,
- GNOME_Evolution_Calendar_Time_t start,
- GNOME_Evolution_Calendar_Time_t end,
- CORBA_Environment *ev)
+/* Cal::discardAlarm method */
+static void
+impl_Cal_discardAlarm (PortableServer_Servant servant,
+ const CORBA_char *uid,
+ const CORBA_char *auid,
+ CORBA_Environment *ev)
{
Cal *cal;
CalPrivate *priv;
- time_t t_start, t_end;
- gboolean valid_range;
- GNOME_Evolution_Calendar_CalComponentAlarmsSeq *seq;
cal = CAL (bonobo_object_from_servant (servant));
priv = cal->priv;
- t_start = (time_t) start;
- t_end = (time_t) end;
-
- seq = cal_backend_get_alarms_in_range (priv->backend, t_start, t_end, &valid_range);
- if (!valid_range) {
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_InvalidRange);
- return NULL;
- }
-
- if (!seq) {
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_NotFound);
- return NULL;
- }
-
- return seq;
+ cal_backend_discard_alarm (priv->backend, cal, uid, auid);
}
-/* Cal::getAlarmsForObject method */
-static GNOME_Evolution_Calendar_CalComponentAlarms *
-impl_Cal_getAlarmsForObject (PortableServer_Servant servant,
- const CORBA_char *uid,
- GNOME_Evolution_Calendar_Time_t start,
- GNOME_Evolution_Calendar_Time_t end,
- CORBA_Environment * ev)
+static void
+impl_Cal_createObject (PortableServer_Servant servant,
+ const CORBA_char *calobj,
+ CORBA_Environment *ev)
{
Cal *cal;
CalPrivate *priv;
- time_t t_start, t_end;
- GNOME_Evolution_Calendar_CalComponentAlarms *alarms;
- CalBackendGetAlarmsForObjectResult result;
cal = CAL (bonobo_object_from_servant (servant));
priv = cal->priv;
- t_start = (time_t) start;
- t_end = (time_t) end;
-
- alarms = cal_backend_get_alarms_for_object (priv->backend, uid, t_start, t_end, &result);
-
- switch (result) {
- case CAL_BACKEND_GET_ALARMS_SUCCESS:
- return alarms;
-
- case CAL_BACKEND_GET_ALARMS_NOT_FOUND:
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_NotFound);
- return NULL;
-
- case CAL_BACKEND_GET_ALARMS_INVALID_RANGE:
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_InvalidRange);
- return NULL;
-
- default:
- g_assert_not_reached ();
- return NULL;
- }
+ cal_backend_create_object (priv->backend, cal, calobj);
}
-/* Cal::discardAlarm method */
static void
-impl_Cal_discardAlarm (PortableServer_Servant servant,
- const CORBA_char *uid,
- const CORBA_char *auid,
+impl_Cal_modifyObject (PortableServer_Servant servant,
+ const CORBA_char *calobj,
+ const GNOME_Evolution_Calendar_CalObjModType mod,
CORBA_Environment *ev)
{
Cal *cal;
CalPrivate *priv;
- CalBackendResult result;
cal = CAL (bonobo_object_from_servant (servant));
priv = cal->priv;
- result = cal_backend_discard_alarm (priv->backend, uid, auid);
- if (result == CAL_BACKEND_RESULT_NOT_FOUND)
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_NotFound);
+ cal_backend_modify_object (priv->backend, cal, calobj, mod);
}
-/* Cal::updateObjects method */
+/* Cal::removeObject method */
static void
-impl_Cal_updateObjects (PortableServer_Servant servant,
- const CORBA_char *calobj,
- const GNOME_Evolution_Calendar_CalObjModType mod,
- CORBA_Environment *ev)
+impl_Cal_removeObject (PortableServer_Servant servant,
+ const CORBA_char *uid,
+ const CORBA_char *rid,
+ const GNOME_Evolution_Calendar_CalObjModType mod,
+ CORBA_Environment *ev)
{
Cal *cal;
CalPrivate *priv;
- CalBackendResult result;
cal = CAL (bonobo_object_from_servant (servant));
priv = cal->priv;
- result = cal_backend_update_objects (priv->backend, calobj, mod);
- switch (result) {
- case CAL_BACKEND_RESULT_INVALID_OBJECT :
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_InvalidObject);
- break;
- case CAL_BACKEND_RESULT_NOT_FOUND :
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_NotFound);
- break;
- case CAL_BACKEND_RESULT_PERMISSION_DENIED :
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_PermissionDenied);
- break;
- default :
- break;
- }
+ cal_backend_remove_object (priv->backend, cal, uid, rid, mod);
}
-/* Cal::removeObject method */
static void
-impl_Cal_removeObject (PortableServer_Servant servant,
- const CORBA_char *uid,
- const GNOME_Evolution_Calendar_CalObjModType mod,
- CORBA_Environment *ev)
+impl_Cal_receiveObjects (PortableServer_Servant servant, const CORBA_char *calobj, CORBA_Environment *ev)
{
Cal *cal;
CalPrivate *priv;
- CalBackendResult result;
cal = CAL (bonobo_object_from_servant (servant));
priv = cal->priv;
- result = cal_backend_remove_object (priv->backend, uid, mod);
- switch (result) {
- case CAL_BACKEND_RESULT_INVALID_OBJECT :
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_InvalidObject);
- break;
- case CAL_BACKEND_RESULT_NOT_FOUND :
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_NotFound);
- break;
- case CAL_BACKEND_RESULT_PERMISSION_DENIED :
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_PermissionDenied);
- break;
- default :
- break;
- }
+ cal_backend_receive_objects (priv->backend, cal, calobj);
}
-/* Cal::sendObject method */
-static GNOME_Evolution_Calendar_CalObj
-impl_Cal_sendObject (PortableServer_Servant servant,
- const CORBA_char *calobj,
- GNOME_Evolution_Calendar_UserList **user_list,
- CORBA_Environment *ev)
+static void
+impl_Cal_sendObjects (PortableServer_Servant servant, const CORBA_char *calobj, CORBA_Environment *ev)
{
Cal *cal;
CalPrivate *priv;
- CORBA_char *calobj_copy;
- char *new_calobj;
- GNOME_Evolution_Calendar_Cal_Busy *err;
- CalBackendSendResult result;
- char error_msg[256];
-
+
cal = CAL (bonobo_object_from_servant (servant));
priv = cal->priv;
- result = cal_backend_send_object (priv->backend, calobj, &new_calobj, user_list, error_msg);
- switch (result) {
- case CAL_BACKEND_SEND_SUCCESS:
- calobj_copy = CORBA_string_dup (new_calobj);
- g_free (new_calobj);
-
- return calobj_copy;
-
- case CAL_BACKEND_SEND_INVALID_OBJECT:
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_InvalidObject);
- break;
-
- case CAL_BACKEND_SEND_BUSY:
- err = GNOME_Evolution_Calendar_Cal_Busy__alloc ();
- err->errorMsg = CORBA_string_dup (error_msg);
- CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_GNOME_Evolution_Calendar_Cal_Busy, err);
- break;
-
- case CAL_BACKEND_SEND_PERMISSION_DENIED:
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_PermissionDenied);
- break;
-
- default :
- g_assert_not_reached ();
- }
-
- return NULL;
+ cal_backend_send_objects (priv->backend, cal, calobj);
}
/* Cal::getQuery implementation */
-static GNOME_Evolution_Calendar_Query
+static void
impl_Cal_getQuery (PortableServer_Servant servant,
const CORBA_char *sexp,
GNOME_Evolution_Calendar_QueryListener ql,
CORBA_Environment *ev)
{
+
Cal *cal;
CalPrivate *priv;
Query *query;
- CORBA_Environment ev2;
- GNOME_Evolution_Calendar_Query query_copy;
-
+ CalBackendObjectSExp *obj_sexp;
+
cal = CAL (bonobo_object_from_servant (servant));
priv = cal->priv;
- query = cal_backend_get_query (priv->backend, ql, sexp);
- if (!query) {
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_CouldNotCreate);
- return CORBA_OBJECT_NIL;
+ /* we handle this entirely here, since it doesn't require any
+ backend involvement now that we have pas_book_view_start to
+ actually kick off the search. */
+
+ obj_sexp = cal_backend_object_sexp_new (sexp);
+ if (!obj_sexp) {
+ cal_notify_query (cal, GNOME_Evolution_Calendar_InvalidQuery, NULL);
+
+ return;
}
- CORBA_exception_init (&ev2);
- query_copy = CORBA_Object_duplicate (BONOBO_OBJREF (query), &ev2);
- if (BONOBO_EX (&ev2)) {
- bonobo_object_unref (query);
- CORBA_exception_free (&ev2);
- g_message ("Cal_get_query(): Could not duplicate the query reference");
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_CouldNotCreate);
- return CORBA_OBJECT_NIL;
+ query = query_new (priv->backend, ql, obj_sexp);
+ if (!query) {
+ g_object_unref (obj_sexp);
+ cal_notify_query (cal, GNOME_Evolution_Calendar_OtherError, NULL);
+
+ return;
}
- CORBA_exception_free (&ev2);
+ cal_backend_add_query (priv->backend, query);
+
+ cal_notify_query (cal, GNOME_Evolution_Calendar_Success, query);
- return query_copy;
+ g_object_unref (query);
}
-/* Cal::setDefaultTimezone method */
+
+/* Cal::getTimezone method */
static void
-impl_Cal_setDefaultTimezone (PortableServer_Servant servant,
- const CORBA_char *tzid,
- CORBA_Environment *ev)
+impl_Cal_getTimezone (PortableServer_Servant servant,
+ const CORBA_char *tzid,
+ CORBA_Environment *ev)
{
Cal *cal;
CalPrivate *priv;
- gboolean zone_set;
cal = CAL (bonobo_object_from_servant (servant));
priv = cal->priv;
- zone_set = cal_backend_set_default_timezone (priv->backend, tzid);
-
- if (!zone_set) {
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_NotFound);
- }
+ cal_backend_get_timezone (priv->backend, cal, tzid);
}
-/* Cal::getTimezoneObject method */
-static GNOME_Evolution_Calendar_CalObj
-impl_Cal_getTimezoneObject (PortableServer_Servant servant,
- const CORBA_char *tzid,
- CORBA_Environment *ev)
+/* Cal::addTimezone method */
+static void
+impl_Cal_addTimezone (PortableServer_Servant servant,
+ const CORBA_char *tz,
+ CORBA_Environment *ev)
{
Cal *cal;
CalPrivate *priv;
- char *calobj;
cal = CAL (bonobo_object_from_servant (servant));
priv = cal->priv;
- calobj = cal_backend_get_timezone_object (priv->backend, tzid);
+ cal_backend_add_timezone (priv->backend, cal, tz);
+}
- if (calobj) {
- CORBA_char *calobj_copy;
+/* Cal::setDefaultTimezone method */
+static void
+impl_Cal_setDefaultTimezone (PortableServer_Servant servant,
+ const CORBA_char *tzid,
+ CORBA_Environment *ev)
+{
+ Cal *cal;
+ CalPrivate *priv;
- calobj_copy = CORBA_string_dup (calobj);
- g_free (calobj);
- return calobj_copy;
- } else {
- bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_Cal_NotFound);
- return NULL;
- }
+ cal = CAL (bonobo_object_from_servant (servant));
+ priv = cal->priv;
+
+ cal_backend_set_default_timezone (priv->backend, cal, tzid);
}
/**
@@ -762,7 +475,7 @@ cal_construct (Cal *cal,
CORBA_exception_free (&ev);
priv->backend = backend;
-
+
return cal;
}
@@ -778,18 +491,20 @@ cal_construct (Cal *cal,
* if its corresponding CORBA object could not be created.
**/
Cal *
-cal_new (CalBackend *backend, GNOME_Evolution_Calendar_Listener listener)
+cal_new (CalBackend *backend, const char *uri, GNOME_Evolution_Calendar_Listener listener)
{
Cal *cal, *retval;
g_return_val_if_fail (backend != NULL, NULL);
g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
- cal = CAL (g_object_new (CAL_TYPE, NULL));
+ cal = CAL (g_object_new (CAL_TYPE,
+ "poa", bonobo_poa_get_threaded (ORBIT_THREAD_HINT_PER_REQUEST, NULL),
+ NULL));
retval = cal_construct (cal, backend, listener);
if (!retval) {
- g_message ("cal_new(): could not construct the calendar client interface");
+ g_message (G_STRLOC ": could not construct the calendar client interface");
bonobo_object_unref (BONOBO_OBJECT (cal));
return NULL;
}
@@ -797,6 +512,24 @@ cal_new (CalBackend *backend, GNOME_Evolution_Calendar_Listener listener)
return retval;
}
+CalBackend *
+cal_get_backend (Cal *cal)
+{
+ g_return_val_if_fail (cal != NULL, NULL);
+ g_return_val_if_fail (IS_CAL (cal), NULL);
+
+ return cal->priv->backend;
+}
+
+GNOME_Evolution_Calendar_Listener
+cal_get_listener (Cal *cal)
+{
+ g_return_val_if_fail (cal != NULL, NULL);
+ g_return_val_if_fail (IS_CAL (cal), NULL);
+
+ return cal->priv->listener;
+}
+
/* Destroy handler for the calendar */
static void
cal_finalize (GObject *object)
@@ -812,11 +545,11 @@ cal_finalize (GObject *object)
priv = cal->priv;
priv->backend = NULL;
-
+
CORBA_exception_init (&ev);
bonobo_object_release_unref (priv->listener, &ev);
if (BONOBO_EX (&ev))
- g_message ("cal_destroy(): could not release the listener");
+ g_message (G_STRLOC ": could not release the listener");
priv->listener = NULL;
CORBA_exception_free (&ev);
@@ -843,27 +576,28 @@ cal_class_init (CalClass *klass)
/* Epv methods */
epv->_get_uri = impl_Cal_get_uri;
+ epv->open = impl_Cal_open;
+ epv->remove = impl_Cal_remove;
epv->isReadOnly = impl_Cal_isReadOnly;
epv->getCalAddress = impl_Cal_getCalAddress;
epv->getAlarmEmailAddress = impl_Cal_getAlarmEmailAddress;
epv->getLdapAttribute = impl_Cal_getLdapAttribute;
epv->getStaticCapabilities = impl_Cal_getStaticCapabilities;
epv->setMode = impl_Cal_setMode;
- epv->countObjects = impl_Cal_countObjects;
epv->getDefaultObject = impl_Cal_getDefaultObject;
epv->getObject = impl_Cal_getObject;
+ epv->getTimezone = impl_Cal_getTimezone;
+ epv->addTimezone = impl_Cal_addTimezone;
epv->setDefaultTimezone = impl_Cal_setDefaultTimezone;
- epv->getTimezoneObject = impl_Cal_getTimezoneObject;
- epv->getUIDs = impl_Cal_getUIDs;
+ epv->getObjectList = impl_Cal_getObjectList;
epv->getChanges = impl_Cal_getChanges;
- epv->getObjectsInRange = impl_Cal_getObjectsInRange;
epv->getFreeBusy = impl_Cal_getFreeBusy;
- epv->getAlarmsInRange = impl_Cal_getAlarmsInRange;
- epv->getAlarmsForObject = impl_Cal_getAlarmsForObject;
epv->discardAlarm = impl_Cal_discardAlarm;
- epv->updateObjects = impl_Cal_updateObjects;
+ epv->createObject = impl_Cal_createObject;
+ epv->modifyObject = impl_Cal_modifyObject;
epv->removeObject = impl_Cal_removeObject;
- epv->sendObject = impl_Cal_sendObject;
+ epv->receiveObjects = impl_Cal_receiveObjects;
+ epv->sendObjects = impl_Cal_sendObjects;
epv->getQuery = impl_Cal_getQuery;
}
@@ -882,18 +616,50 @@ cal_init (Cal *cal, CalClass *klass)
BONOBO_TYPE_FUNC_FULL (Cal, GNOME_Evolution_Calendar_Cal, PARENT_TYPE, cal);
-/**
- * cal_notify_mode:
- * @cal: A calendar client interface.
- * @status: Status of the mode set.
- * @mode: The current mode.
- *
- * Notifys the listener of the results of a setMode call.
- **/
+void
+cal_notify_read_only (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, gboolean read_only)
+{
+ CalPrivate *priv;
+ CORBA_Environment ev;
+
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_Calendar_Listener_notifyReadOnly (priv->listener, status, read_only, &ev);
+
+ if (BONOBO_EX (&ev))
+ g_message (G_STRLOC ": could not notify the listener of read only");
+
+ CORBA_exception_free (&ev);
+}
+
+void
+cal_notify_cal_address (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, const char *address)
+{
+ CalPrivate *priv;
+ CORBA_Environment ev;
+
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_Calendar_Listener_notifyCalAddress (priv->listener, status, address ? address : "", &ev);
+
+ if (BONOBO_EX (&ev))
+ g_message (G_STRLOC ": could not notify the listener of cal address");
+
+ CORBA_exception_free (&ev);
+}
+
void
-cal_notify_mode (Cal *cal,
- GNOME_Evolution_Calendar_Listener_SetModeStatus status,
- GNOME_Evolution_Calendar_CalMode mode)
+cal_notify_alarm_email_address (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, const char *address)
{
CalPrivate *priv;
CORBA_Environment ev;
@@ -905,75 +671,606 @@ cal_notify_mode (Cal *cal,
g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
CORBA_exception_init (&ev);
- GNOME_Evolution_Calendar_Listener_notifyCalSetMode (priv->listener, status, mode, &ev);
+ GNOME_Evolution_Calendar_Listener_notifyAlarmEmailAddress (priv->listener, status, address ? address : "", &ev);
if (BONOBO_EX (&ev))
- g_message ("cal_notify_mode(): could not notify the listener "
- "about a mode change");
+ g_message (G_STRLOC ": could not notify the listener of alarm address");
+
+ CORBA_exception_free (&ev);
+}
+
+void
+cal_notify_ldap_attribute (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, const char *attribute)
+{
+ CalPrivate *priv;
+ CORBA_Environment ev;
+
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_Calendar_Listener_notifyLDAPAttribute (priv->listener, status, attribute ? attribute : "", &ev);
+
+ if (BONOBO_EX (&ev))
+ g_message (G_STRLOC ": could not notify the listener of ldap attribute");
+
+ CORBA_exception_free (&ev);
+}
+
+void
+cal_notify_static_capabilities (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, const char *capabilities)
+{
+ CalPrivate *priv;
+ CORBA_Environment ev;
+
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_Calendar_Listener_notifyStaticCapabilities (priv->listener, status,
+ capabilities ? capabilities : "", &ev);
+
+ if (BONOBO_EX (&ev))
+ g_message (G_STRLOC ": could not notify the listener of static capabilities");
+
+ CORBA_exception_free (&ev);
+}
+
+void
+cal_notify_open (Cal *cal, GNOME_Evolution_Calendar_CallStatus status)
+{
+ CalPrivate *priv;
+ CORBA_Environment ev;
+
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_Calendar_Listener_notifyCalOpened (priv->listener, status, &ev);
+
+ if (BONOBO_EX (&ev))
+ g_message (G_STRLOC ": could not notify the listener of open");
+
+ CORBA_exception_free (&ev);
+}
+
+void
+cal_notify_remove (Cal *cal, GNOME_Evolution_Calendar_CallStatus status)
+{
+ CalPrivate *priv;
+ CORBA_Environment ev;
+
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_Calendar_Listener_notifyCalRemoved (priv->listener, status, &ev);
+
+ if (BONOBO_EX (&ev))
+ g_message (G_STRLOC ": could not notify the listener of remove");
+
+ CORBA_exception_free (&ev);
+}
+
+void
+cal_notify_object_created (Cal *cal, GNOME_Evolution_Calendar_CallStatus status,
+ const char *uid, const char *object)
+{
+ CalPrivate *priv;
+ EList *queries;
+ EIterator *iter;
+ CORBA_Environment ev;
+
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ queries = cal_backend_get_queries (priv->backend);
+ iter = e_list_get_iterator (queries);
+
+ while (e_iterator_is_valid (iter)) {
+ Query *query = QUERY (e_iterator_get (iter));
+
+ bonobo_object_dup_ref (BONOBO_OBJREF (query), NULL);
+
+ if (!query_object_matches (query, object))
+ continue;
+
+ query_notify_objects_added_1 (query, object);
+
+ bonobo_object_release_unref (BONOBO_OBJREF (query), NULL);
+
+ e_iterator_next (iter);
+ }
+ g_object_unref (iter);
+ g_object_unref (queries);
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_Calendar_Listener_notifyObjectCreated (priv->listener, status, uid ? uid : "", &ev);
+
+ if (BONOBO_EX (&ev))
+ g_message (G_STRLOC ": could not notify the listener of object creation");
+
+ CORBA_exception_free (&ev);
+}
+
+void
+cal_notify_object_modified (Cal *cal, GNOME_Evolution_Calendar_CallStatus status,
+ const char *old_object, const char *object)
+{
+ CalPrivate *priv;
+ EList *queries;
+ EIterator *iter;
+ CORBA_Environment ev;
+
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ queries = cal_backend_get_queries (priv->backend);
+ iter = e_list_get_iterator (queries);
+
+ while (e_iterator_is_valid (iter)) {
+ Query *query = QUERY (e_iterator_get (iter));
+ gboolean old_match, new_match;
+
+ bonobo_object_dup_ref (BONOBO_OBJREF (query), NULL);
+
+ old_match = query_object_matches (query, old_object);
+ new_match = query_object_matches (query, object);
+ if (old_match && new_match)
+ query_notify_objects_modified_1 (query, object);
+ else if (new_match)
+ query_notify_objects_added_1 (query, object);
+ else /* if (old_match) */ {
+ icalcomponent *comp;
+
+ comp = icalcomponent_new_from_string ((char *)old_object);
+ query_notify_objects_removed_1 (query, icalcomponent_get_uid (comp));
+ icalcomponent_free (comp);
+ }
+ query_notify_query_done (query, GNOME_Evolution_Calendar_Success);
+
+ bonobo_object_release_unref (BONOBO_OBJREF (query), NULL);
+
+ e_iterator_next (iter);
+ }
+ g_object_unref (iter);
+ g_object_unref (queries);
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_Calendar_Listener_notifyObjectModified (priv->listener, status, &ev);
+
+ if (BONOBO_EX (&ev))
+ g_message (G_STRLOC ": could not notify the listener of object creation");
+
+ CORBA_exception_free (&ev);
+}
+
+void
+cal_notify_object_removed (Cal *cal, GNOME_Evolution_Calendar_CallStatus status,
+ const char *uid, const char *object)
+{
+ CalPrivate *priv;
+ EList *queries;
+ EIterator *iter;
+ CORBA_Environment ev;
+
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ queries = cal_backend_get_queries (priv->backend);
+ iter = e_list_get_iterator (queries);
+
+ while (e_iterator_is_valid (iter)) {
+ Query *query = QUERY (e_iterator_get (iter));
+
+ bonobo_object_dup_ref (BONOBO_OBJREF (query), NULL);
+
+ if (!query_object_matches (query, object))
+ continue;
+
+ query_notify_objects_removed_1 (query, uid);
+
+ bonobo_object_release_unref (BONOBO_OBJREF (query), NULL);
+
+ e_iterator_next (iter);
+ }
+ g_object_unref (iter);
+ g_object_unref (queries);
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_Calendar_Listener_notifyObjectRemoved (priv->listener, status, &ev);
+
+ if (BONOBO_EX (&ev))
+ g_message (G_STRLOC ": could not notify the listener of object removal");
+
+ CORBA_exception_free (&ev);
+}
+
+void
+cal_notify_objects_received (Cal *cal, GNOME_Evolution_Calendar_CallStatus status,
+ GList *created, GList *modified, GList *removed)
+{
+ CalPrivate *priv;
+ EList *queries;
+ EIterator *iter;
+ CORBA_Environment ev;
+
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ queries = cal_backend_get_queries (priv->backend);
+ iter = e_list_get_iterator (queries);
+
+ while (e_iterator_is_valid (iter)) {
+ Query *query = QUERY (e_iterator_get (iter));
+
+ bonobo_object_dup_ref (BONOBO_OBJREF (query), NULL);
+
+ query_notify_objects_added (query, created);
+ query_notify_objects_modified (query, modified);
+ query_notify_objects_removed (query, removed);
+
+ bonobo_object_release_unref (BONOBO_OBJREF (query), NULL);
+
+ e_iterator_next (iter);
+ }
+ g_object_unref (iter);
+ g_object_unref (queries);
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_Calendar_Listener_notifyObjectsReceived (priv->listener, status, &ev);
+
+ if (BONOBO_EX (&ev))
+ g_message (G_STRLOC ": could not notify the listener of objects received");
+
+ CORBA_exception_free (&ev);
+}
+
+void
+cal_notify_alarm_discarded (Cal *cal, GNOME_Evolution_Calendar_CallStatus status)
+{
+ CalPrivate *priv;
+ CORBA_Environment ev;
+
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_Calendar_Listener_notifyAlarmDiscarded (priv->listener, status, &ev);
+
+ if (BONOBO_EX (&ev))
+ g_message (G_STRLOC ": could not notify the listener of alarm discarded");
CORBA_exception_free (&ev);
}
-/**
- * cal_notify_update:
- * @cal: A calendar client interface.
- * @uid: UID of object that was updated.
- *
- * Notifies a listener attached to a calendar client interface object about an
- * update to a calendar object.
- **/
void
-cal_notify_update (Cal *cal, const char *uid)
+cal_notify_objects_sent (Cal *cal, GNOME_Evolution_Calendar_CallStatus status)
{
CalPrivate *priv;
CORBA_Environment ev;
g_return_if_fail (cal != NULL);
g_return_if_fail (IS_CAL (cal));
- g_return_if_fail (uid != NULL);
priv = cal->priv;
g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
CORBA_exception_init (&ev);
- GNOME_Evolution_Calendar_Listener_notifyObjUpdated (priv->listener, (char *) uid, &ev);
+ GNOME_Evolution_Calendar_Listener_notifyObjectsSent (priv->listener, status, &ev);
if (BONOBO_EX (&ev))
- g_message ("cal_notify_update(): could not notify the listener "
- "about an updated object");
+ g_message (G_STRLOC ": could not notify the listener of objects sent");
+
+ CORBA_exception_free (&ev);
+}
+
+void
+cal_notify_default_object (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, char *object)
+{
+ CalPrivate *priv;
+ CORBA_Environment ev;
+
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
+
+ GNOME_Evolution_Calendar_Listener_notifyDefaultObjectRequested (priv->listener, status,
+ object ? object : "", &ev);
+
+ if (BONOBO_EX (&ev))
+ g_message (G_STRLOC ": could not notify the listener of default object");
+
+ CORBA_exception_free (&ev);
+}
+
+void
+cal_notify_object (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, char *object)
+{
+ CalPrivate *priv;
+ CORBA_Environment ev;
+
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
+
+ GNOME_Evolution_Calendar_Listener_notifyObjectRequested (priv->listener, status,
+ object ? object : "", &ev);
+
+ if (BONOBO_EX (&ev))
+ g_message (G_STRLOC ": could not notify the listener of object");
+
+ CORBA_exception_free (&ev);
+}
+
+void
+cal_notify_object_list (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, GList *objects)
+{
+ CalPrivate *priv;
+ CORBA_Environment ev;
+ GNOME_Evolution_Calendar_stringlist seq;
+ GList *l;
+ int i;
+
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
+
+ seq._maximum = g_list_length (objects);
+ seq._length = 0;
+ seq._buffer = GNOME_Evolution_Calendar_stringlist_allocbuf (seq._maximum);
+
+ for (l = objects, i = 0; l; l = l->next, i++) {
+ seq._buffer[i] = CORBA_string_dup (l->data);
+ seq._length++;
+ }
+
+ GNOME_Evolution_Calendar_Listener_notifyObjectListRequested (priv->listener, status, &seq, &ev);
+
+ if (BONOBO_EX (&ev))
+ g_message (G_STRLOC ": could not notify the listener of object list");
+
+ CORBA_exception_free (&ev);
+
+ CORBA_free(seq._buffer);
+}
+
+void
+cal_notify_query (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, Query *query)
+{
+ CalPrivate *priv;
+ CORBA_Environment ev;
+
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_Calendar_Listener_notifyQuery (priv->listener, status, BONOBO_OBJREF (query), &ev);
+
+ if (BONOBO_EX (&ev))
+ g_message (G_STRLOC ": could not notify the listener of query");
+
+ CORBA_exception_free (&ev);
+}
+
+void
+cal_notify_timezone_requested (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, const char *object)
+{
+ CalPrivate *priv;
+ CORBA_Environment ev;
+
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_Calendar_Listener_notifyTimezoneRequested (priv->listener, status, object ? object : "", &ev);
+
+ if (BONOBO_EX (&ev))
+ g_warning (G_STRLOC ": could not notify the listener of timezone requested");
+
+ CORBA_exception_free (&ev);
+}
+
+void
+cal_notify_timezone_added (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, const char *tzid)
+{
+ CalPrivate *priv;
+ CORBA_Environment ev;
+
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_Calendar_Listener_notifyTimezoneAdded (priv->listener, status, tzid, &ev);
+
+ if (BONOBO_EX (&ev))
+ g_warning (G_STRLOC ": could not notify the listener of timezone added");
+
+ CORBA_exception_free (&ev);
+}
+
+void
+cal_notify_default_timezone_set (Cal *cal, GNOME_Evolution_Calendar_CallStatus status)
+{
+ CalPrivate *priv;
+ CORBA_Environment ev;
+
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_Calendar_Listener_notifyDefaultTimezoneSet (priv->listener, status, &ev);
+
+ if (BONOBO_EX (&ev))
+ g_warning (G_STRLOC ": could not notify the listener of default timezone set");
+
+ CORBA_exception_free (&ev);
+}
+
+void
+cal_notify_changes (Cal *cal, GNOME_Evolution_Calendar_CallStatus status,
+ GList *adds, GList *modifies, GList *deletes)
+{
+ CalPrivate *priv;
+ CORBA_Environment ev;
+ GNOME_Evolution_Calendar_CalObjChangeSeq seq;
+ GList *l;
+ int n, i;
+
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ n = g_list_length (adds) + g_list_length (modifies) + g_list_length (deletes);
+ seq._maximum = n;
+ seq._length = n;
+ seq._buffer = CORBA_sequence_GNOME_Evolution_Calendar_CalObjChange_allocbuf (n);
+
+ i = 0;
+ for (l = adds; l; i++, l = l->next) {
+ GNOME_Evolution_Calendar_CalObjChange *change = &seq._buffer[i];
+
+ change->calobj = CORBA_string_dup (l->data);
+ change->type = GNOME_Evolution_Calendar_ADDED;
+ }
+
+ for (l = modifies; l; i++, l = l->next) {
+ GNOME_Evolution_Calendar_CalObjChange *change = &seq._buffer[i];
+
+ change->calobj = CORBA_string_dup (l->data);
+ change->type = GNOME_Evolution_Calendar_MODIFIED;
+ }
+
+ for (l = deletes; l; i++, l = l->next) {
+ GNOME_Evolution_Calendar_CalObjChange *change = &seq._buffer[i];
+
+ change->calobj = CORBA_string_dup (l->data);
+ change->type = GNOME_Evolution_Calendar_DELETED;
+ }
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_Calendar_Listener_notifyDefaultTimezoneSet (priv->listener, status, &ev);
+
+ CORBA_free (seq._buffer);
+
+ if (BONOBO_EX (&ev))
+ g_warning (G_STRLOC ": could not notify the listener of default timezone set");
+
+ CORBA_exception_free (&ev);
+}
+
+void
+cal_notify_free_busy (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, GList *freebusy)
+{
+ CalPrivate *priv;
+ CORBA_Environment ev;
+ GNOME_Evolution_Calendar_CalObjSeq seq;
+ GList *l;
+ int n, i;
+
+ g_return_if_fail (IS_CAL (cal));
+
+ priv = cal->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ n = g_list_length (freebusy);
+ seq._maximum = n;
+ seq._length = n;
+ seq._buffer = CORBA_sequence_GNOME_Evolution_Calendar_CalObj_allocbuf (n);
+
+ for (i = 0, l = freebusy; l; i++, l = l->next)
+ seq._buffer[i] = CORBA_string_dup (l->data);
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_Calendar_Listener_notifyDefaultTimezoneSet (priv->listener, status, &ev);
+
+ CORBA_free (seq._buffer);
+
+ if (BONOBO_EX (&ev))
+ g_warning (G_STRLOC ": could not notify the listener of freebusy");
CORBA_exception_free (&ev);
}
/**
- * cal_notify_remove:
+ * cal_notify_mode:
* @cal: A calendar client interface.
- * @uid: UID of object that was removed.
+ * @status: Status of the mode set.
+ * @mode: The current mode.
*
- * Notifies a listener attached to a calendar client interface object about a
- * calendar object that was removed.
+ * Notifys the listener of the results of a setMode call.
**/
void
-cal_notify_remove (Cal *cal, const char *uid)
+cal_notify_mode (Cal *cal,
+ GNOME_Evolution_Calendar_Listener_SetModeStatus status,
+ GNOME_Evolution_Calendar_CalMode mode)
{
CalPrivate *priv;
CORBA_Environment ev;
g_return_if_fail (cal != NULL);
g_return_if_fail (IS_CAL (cal));
- g_return_if_fail (uid != NULL);
priv = cal->priv;
g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
CORBA_exception_init (&ev);
- GNOME_Evolution_Calendar_Listener_notifyObjRemoved (priv->listener, (char *) uid, &ev);
+ GNOME_Evolution_Calendar_Listener_notifyCalSetMode (priv->listener, status, mode, &ev);
if (BONOBO_EX (&ev))
- g_message ("cal_notify_remove(): could not notify the listener "
- "about a removed object");
+ g_message ("cal_notify_mode(): could not notify the listener "
+ "about a mode change");
- CORBA_exception_free (&ev);
+ CORBA_exception_free (&ev);
}
/**
diff --git a/calendar/pcs/cal.h b/calendar/pcs/cal.h
index 35f64f278f..52d8589ab2 100644
--- a/calendar/pcs/cal.h
+++ b/calendar/pcs/cal.h
@@ -26,6 +26,7 @@
#include <bonobo/bonobo-object.h>
#include "pcs/evolution-calendar.h"
#include "pcs/cal-common.h"
+#include "pcs/query.h"
G_BEGIN_DECLS
@@ -58,13 +59,48 @@ Cal *cal_construct (Cal *cal,
CalBackend *backend,
GNOME_Evolution_Calendar_Listener listener);
-Cal *cal_new (CalBackend *backend, GNOME_Evolution_Calendar_Listener listener);
+Cal *cal_new (CalBackend *backend, const char *uri, GNOME_Evolution_Calendar_Listener listener);
+
+CalBackend *cal_get_backend (Cal *cal);
+GNOME_Evolution_Calendar_Listener cal_get_listener (Cal *cal);
+
+void cal_notify_read_only (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, gboolean read_only);
+void cal_notify_cal_address (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, const char *address);
+void cal_notify_alarm_email_address (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, const char *address);
+void cal_notify_ldap_attribute (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, const char *attribute);
+void cal_notify_static_capabilities (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, const char *capabilities);
+
+void cal_notify_open (Cal *cal, GNOME_Evolution_Calendar_CallStatus status);
+void cal_notify_remove (Cal *cal, GNOME_Evolution_Calendar_CallStatus status);
+
+void cal_notify_object_created (Cal *cal, GNOME_Evolution_Calendar_CallStatus status,
+ const char *uid, const char *object);
+void cal_notify_object_modified (Cal *cal, GNOME_Evolution_Calendar_CallStatus status,
+ const char *old_object, const char *object);
+void cal_notify_object_removed (Cal *cal, GNOME_Evolution_Calendar_CallStatus status,
+ const char *uid, const char *object);
+void cal_notify_alarm_discarded (Cal *cal, GNOME_Evolution_Calendar_CallStatus status);
+
+void cal_notify_objects_received (Cal *cal, GNOME_Evolution_Calendar_CallStatus status,
+ GList *created, GList *modified, GList *removed);
+void cal_notify_objects_sent (Cal *cal, GNOME_Evolution_Calendar_CallStatus status);
+
+void cal_notify_default_object (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, char *object);
+void cal_notify_object (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, char *object);
+void cal_notify_object_list (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, GList *objects);
+
+void cal_notify_query (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, Query *query);
+
+void cal_notify_timezone_requested (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, const char *object);
+void cal_notify_timezone_added (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, const char *tzid);
+void cal_notify_default_timezone_set (Cal *cal, GNOME_Evolution_Calendar_CallStatus status);
+
+void cal_notify_changes (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, GList *adds, GList *modifies, GList *deletes);
+void cal_notify_free_busy (Cal *cal, GNOME_Evolution_Calendar_CallStatus status, GList *freebusy);
void cal_notify_mode (Cal *cal,
GNOME_Evolution_Calendar_Listener_SetModeStatus status,
GNOME_Evolution_Calendar_CalMode mode);
-void cal_notify_update (Cal *cal, const char *uid);
-void cal_notify_remove (Cal *cal, const char *uid);
void cal_notify_error (Cal *cal, const char *message);
void cal_notify_categories_changed (Cal *cal, GNOME_Evolution_Calendar_StringSeq *categories);
diff --git a/calendar/pcs/job.c b/calendar/pcs/job.c
deleted file mode 100644
index 584f1a6f38..0000000000
--- a/calendar/pcs/job.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/* GNOME personal calendar server - job manager
- *
- * Copyright (C) 2000 Ximian, Inc.
- * Copyright (C) 2000 Ximian, Inc.
- *
- * Author: Federico Mena-Quintero <federico@ximian.com>
- *
- * 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.
- */
-
-#include <config.h>
-#include "job.h"
-
-
-
-/* The job list */
-
-typedef struct {
- JobFunc func;
- gpointer data;
-} Job;
-
-static GSList *jobs_head;
-static GSList *jobs_tail;
-
-static guint jobs_idle_id;
-
-
-
-/* Runs a job and dequeues it */
-static gboolean
-run_job (gpointer data)
-{
- Job *job;
- GSList *l;
-
- g_assert (jobs_head != NULL);
-
- job = jobs_head->data;
- (* job->func) (job->data);
- g_free (job);
-
- l = jobs_head;
- jobs_head = g_slist_remove_link (jobs_head, jobs_head);
- g_slist_free_1 (l);
-
- if (!jobs_head) {
- jobs_tail = NULL;
- jobs_idle_id = 0;
- return FALSE;
- } else
- return TRUE;
-}
-
-/**
- * job_add:
- * @func: Function to run the job.
- * @data: Data to pass to @function.
- *
- * Adds a job to the queue. The job will automatically be run asynchronously.
- **/
-void
-job_add (JobFunc func, gpointer data)
-{
- Job *job;
-
- g_return_if_fail (func != NULL);
-
- job = g_new (Job, 1);
- job->func = func;
- job->data = data;
-
- if (!jobs_head) {
- g_assert (jobs_tail == NULL);
- g_assert (jobs_idle_id == 0);
-
- jobs_head = g_slist_append (NULL, job);
- jobs_tail = jobs_head;
-
- jobs_idle_id = g_idle_add (run_job, NULL);
- } else {
- g_assert (jobs_tail != NULL);
- g_assert (jobs_idle_id != 0);
-
- jobs_tail = g_slist_append (jobs_tail, job)->next;
- }
-}
diff --git a/calendar/pcs/query-backend.c b/calendar/pcs/query-backend.c
deleted file mode 100644
index 7d6cca041a..0000000000
--- a/calendar/pcs/query-backend.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/* Evolution calendar - Backend cache for calendar queries.
- *
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Author: Rodrigo Moya <rodrigo@ximian.com>
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib.h>
-#include <libgnome/gnome-i18n.h>
-#include <cal-util/cal-component.h>
-#include "query.h"
-#include "query-backend.h"
-
-static void query_backend_class_init (QueryBackendClass *klass);
-static void query_backend_init (QueryBackend *qb, QueryBackendClass *klass);
-static void query_backend_finalize (GObject *object);
-
-typedef struct {
- CalComponent *comp;
-} QueryBackendComponent;
-
-/* Private part of the QueryBackend structure */
-struct _QueryBackendPrivate {
- char *uri;
- CalBackend *backend;
- GHashTable *components;
- GList *queries;
-};
-
-static GHashTable *loaded_backends = NULL;
-static GObjectClass *parent_class = NULL;
-
-/* Class initialization function for the backend cache */
-static void
-query_backend_class_init (QueryBackendClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- parent_class = g_type_class_peek_parent (klass);
-
- object_class->finalize = query_backend_finalize;
-}
-
-/* Object initialization function for the backend cache */
-static void
-query_backend_init (QueryBackend *qb, QueryBackendClass *klass)
-{
- QueryBackendPrivate *priv;
-
- priv = g_new0 (QueryBackendPrivate, 1);
- qb->priv = priv;
-
- priv->uri = NULL;
- priv->backend = NULL;
- priv->components = g_hash_table_new (g_str_hash, g_str_equal);
- priv->queries = NULL;
-}
-
-static void
-free_hash_comp_cb (gpointer key, gpointer value, gpointer user_data)
-{
- g_free (key);
- g_object_unref (value);
-}
-
-/* Finalize handler for the backend cache */
-static void
-query_backend_finalize (GObject *object)
-{
- QueryBackend *qb = (QueryBackend *) object;
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (IS_QUERY_BACKEND (qb));
-
- /* remove the QueryBackend from the internal hash table */
- g_hash_table_remove (loaded_backends, qb->priv->uri);
- if (g_hash_table_size (loaded_backends) == 0) {
- g_hash_table_destroy (loaded_backends);
- loaded_backends = NULL;
- }
-
- /* free memory */
- qb->priv->backend = NULL;
-
- g_free (qb->priv->uri);
- qb->priv->uri = NULL;
-
- g_hash_table_foreach (qb->priv->components, (GHFunc) free_hash_comp_cb, NULL);
- g_hash_table_destroy (qb->priv->components);
- qb->priv->components = NULL;
-
- g_list_free (qb->priv->queries);
- qb->priv->queries = NULL;
-
- g_free (qb->priv);
- qb->priv = NULL;
-
- if (G_OBJECT_CLASS (parent_class)->finalize)
- (* G_OBJECT_CLASS (parent_class)->finalize) (object);
-}
-
-/**
- * query_backend_get_type:
- * @void:
- *
- * Registers the #QueryBackend class if necessary, and returns the type ID
- * associated to it.
- *
- * Return value: The type ID of the #QueryBackend class.
- **/
-GType
-query_backend_get_type (void)
-{
- static GType type = 0;
-
- if (!type) {
- static GTypeInfo info = {
- sizeof (QueryBackendClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) query_backend_class_init,
- NULL, NULL,
- sizeof (QueryBackend),
- 0,
- (GInstanceInitFunc) query_backend_init
- };
- type = g_type_register_static (G_TYPE_OBJECT, "QueryBackend", &info, 0);
- }
-
- return type;
-}
-
-static void
-backend_destroyed_cb (gpointer user_data, GObject *where_backend_was)
-{
- QueryBackend *qb = (QueryBackend *) user_data;
-
- g_return_if_fail (IS_QUERY_BACKEND (qb));
-
- g_object_unref (qb);
-}
-
-static void
-object_updated_cb (CalBackend *backend, const char *uid, gpointer user_data)
-{
- gpointer orig_key, orig_value;
- const char *tmp_uid;
- CalComponent *comp;
- icalcomponent *icalcomp;
- char *comp_str;
- QueryBackend *qb = (QueryBackend *) user_data;
-
- g_return_if_fail (IS_QUERY_BACKEND (qb));
-
- if (g_hash_table_lookup_extended (qb->priv->components, uid, &orig_key, &orig_value)) {
- g_hash_table_remove (qb->priv->components, uid);
- g_free (orig_key);
- g_object_unref (orig_value);
- }
-
- comp_str = cal_backend_get_object (qb->priv->backend, uid);
- if (!comp_str)
- return;
-
- icalcomp = icalparser_parse_string (comp_str);
- g_free (comp_str);
- if (icalcomp) {
- comp = cal_component_new ();
- if (!cal_component_set_icalcomponent (comp, icalcomp)) {
- icalcomponent_free (icalcomp);
- g_object_unref (comp);
- return;
- }
-
- cal_component_get_uid (comp, &tmp_uid);
- if (!uid || !*uid) {
- g_object_unref (comp);
- } else
- g_hash_table_insert (qb->priv->components, g_strdup (tmp_uid), comp);
- }
-}
-
-static void
-object_removed_cb (CalBackend *backend, const char *uid, gpointer user_data)
-{
- gpointer orig_key, orig_value;
- QueryBackend *qb = (QueryBackend *) user_data;
-
- g_return_if_fail (IS_QUERY_BACKEND (qb));
-
- if (g_hash_table_lookup_extended (qb->priv->components, uid, &orig_key, &orig_value)) {
- g_hash_table_remove (qb->priv->components, uid);
- g_free (orig_key);
- g_object_unref (orig_value);
- }
-}
-
-static void
-query_destroyed_cb (gpointer user_data, GObject *where_the_object_was)
-{
- Query *query = (Query *) where_the_object_was;
- QueryBackend *qb = (QueryBackend *) user_data;
-
- g_return_if_fail (IS_QUERY (query));
- g_return_if_fail (IS_QUERY_BACKEND (qb));
-
- qb->priv->queries = g_list_remove (qb->priv->queries, query);
-}
-
-static void
-foreach_uid_cb (gpointer data, gpointer user_data)
-{
- QueryBackend *qb = (QueryBackend *) user_data;
-
- g_return_if_fail (data != NULL);
- g_return_if_fail (IS_QUERY_BACKEND (qb));
-
- object_updated_cb (qb->priv->backend, (const char *) data, qb);
-}
-
-/**
- * query_backend_new
- * @query: The #Query object that issues the query.
- * @backend: A #CalBackend object.
- *
- * Create a new #QueryBackend instance, which is a class to
- * have a cache of objects for the calendar queries, so that
- * we don't have to ask the calendar backend to get the objects
- * everytime.
- *
- * Returns: the newly-created object.
- */
-QueryBackend *
-query_backend_new (Query *query, CalBackend *backend)
-{
- QueryBackend *qb = NULL;
-
- g_return_val_if_fail (IS_QUERY (query), NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
-
- if (!loaded_backends)
- loaded_backends = g_hash_table_new (g_str_hash, g_str_equal);
-
- /* see if we already have the backend loaded */
- qb = g_hash_table_lookup (loaded_backends,
- cal_backend_get_uri (backend));
- if (!qb) {
- GList *uidlist;
-
- qb = g_object_new (QUERY_BACKEND_TYPE, NULL);
-
- qb->priv->uri = g_strdup (cal_backend_get_uri (backend));
- qb->priv->backend = backend;
-
- /* load all UIDs */
- uidlist = cal_backend_get_uids (backend, CALOBJ_TYPE_ANY);
- g_list_foreach (uidlist, foreach_uid_cb, qb);
- cal_obj_uid_list_free (uidlist);
-
- g_object_weak_ref (G_OBJECT (backend), backend_destroyed_cb, qb);
- g_signal_connect (G_OBJECT (backend), "obj_updated",
- G_CALLBACK (object_updated_cb), qb);
- g_signal_connect (G_OBJECT (backend), "obj_removed",
- G_CALLBACK (object_removed_cb), qb);
-
- g_hash_table_insert (loaded_backends, qb->priv->uri, qb);
- }
-
- qb->priv->queries = g_list_append (qb->priv->queries, query);
- g_object_weak_ref (G_OBJECT (query), query_destroyed_cb, qb);
-
- return qb;
-}
-
-typedef struct {
- GList *uidlist;
- CalObjType type;
-} GetUidsData;
-
-static void
-uid_hash_cb (gpointer key, gpointer value, gpointer user_data)
-{
- CalComponentVType vtype;
- char *uid = (char *) key;
- CalComponent *comp = (CalComponent *) value;
- GetUidsData *uids_data = (GetUidsData *) user_data;
-
- g_return_if_fail (uid != NULL);
- g_return_if_fail (IS_CAL_COMPONENT (comp));
- g_return_if_fail (uids_data != NULL);
-
- vtype = cal_component_get_vtype (comp);
- if (vtype == CAL_COMPONENT_EVENT && uids_data->type == CALOBJ_TYPE_EVENT)
- uids_data->uidlist = g_list_append (uids_data->uidlist, g_strdup (uid));
- else if (vtype == CAL_COMPONENT_TODO && uids_data->type == CALOBJ_TYPE_TODO)
- uids_data->uidlist = g_list_append (uids_data->uidlist, g_strdup (uid));
- else if (vtype == CAL_COMPONENT_JOURNAL && uids_data->type == CALOBJ_TYPE_JOURNAL)
- uids_data->uidlist = g_list_append (uids_data->uidlist, g_strdup (uid));
- else if (uids_data->type == CALOBJ_TYPE_ANY)
- uids_data->uidlist = g_list_append (uids_data->uidlist, g_strdup (uid));
-}
-
-/**
- * query_backend_get_uids
- * @qb: A #QueryBackend type.
- * @type: Type of objects to get the UIDs for.
- *
- * Get a list of all UIDs for objects of the given type out from
- * the specified #QueryBackend object.
- *
- * Returns: a GList of UIDs, which should be freed, when no longer needed,
- * via a call to cal_obj_uid_list_free.
- */
-GList *
-query_backend_get_uids (QueryBackend *qb, CalObjType type)
-{
- GetUidsData uids_data;
-
- g_return_val_if_fail (IS_QUERY_BACKEND (qb), NULL);
-
- uids_data.uidlist = NULL;
- uids_data.type = type;
- g_hash_table_foreach (qb->priv->components, (GHFunc) uid_hash_cb, &uids_data);
-
- return uids_data.uidlist;
-}
-
-/**
- * query_backend_get_object_component
- * @qb: A #QueryBackend object.
- * @uid: UID of the object to retrieve.
- *
- * Get a #CalComponent from the given #QueryBackend.
- *
- * Returns: the component if found, NULL otherwise.
- */
-CalComponent *
-query_backend_get_object_component (QueryBackend *qb, const char *uid)
-{
- g_return_val_if_fail (IS_QUERY_BACKEND (qb), NULL);
- g_return_val_if_fail (uid != NULL, NULL);
-
- return g_hash_table_lookup (qb->priv->components, uid);
-}
diff --git a/calendar/pcs/query-backend.h b/calendar/pcs/query-backend.h
deleted file mode 100644
index a6d9b5d8aa..0000000000
--- a/calendar/pcs/query-backend.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Evolution calendar - Backend cache for calendar queries.
- *
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Author: Rodrigo Moya <rodrigo@ximian.com>
- *
- * 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.
- */
-
-#ifndef QUERY_BACKEND_H
-#define QUERY_BACKEND_H
-
-#include "cal-backend.h"
-#include "query.h"
-
-G_BEGIN_DECLS
-
-#define QUERY_BACKEND_TYPE (query_backend_get_type ())
-#define QUERY_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), QUERY_BACKEND_TYPE, QueryBackend))
-#define QUERY_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), QUERY_BACKEND_TYPE, QueryBackendClass))
-#define IS_QUERY_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), QUERY_BACKEND_TYPE))
-#define IS_QUERY_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), QUERY_BACKEND_TYPE))
-
-typedef struct _QueryBackendPrivate QueryBackendPrivate;
-
-typedef struct {
- GObject object;
-
- /* Private data */
- QueryBackendPrivate *priv;
-} QueryBackend;
-
-typedef struct {
- GObjectClass parent;
-} QueryBackendClass;
-
-GType query_backend_get_type (void);
-QueryBackend *query_backend_new (Query *query, CalBackend *backend);
-GList *query_backend_get_uids (QueryBackend *qb, CalObjType type);
-CalComponent *query_backend_get_object_component (QueryBackend *qb, const char *uid);
-
-G_END_DECLS
-
-#endif
diff --git a/calendar/pcs/query.c b/calendar/pcs/query.c
index 41853c1a47..6f3d417a32 100644
--- a/calendar/pcs/query.c
+++ b/calendar/pcs/query.c
@@ -30,68 +30,28 @@
#include <gal/widgets/e-unicode.h>
#include <e-util/e-component-listener.h>
#include <e-util/e-sexp.h>
+#include <pcs/cal-backend-object-sexp.h>
#include <cal-util/cal-recur.h>
#include <cal-util/timeutil.h>
#include "cal-backend.h"
#include "query.h"
-#include "query-backend.h"
-typedef struct {
- Query *query;
- GNOME_Evolution_Calendar_QueryListener ql;
- guint tid;
-} StartCachedQueryInfo;
-
-/* States of a query */
-typedef enum {
- QUERY_WAIT_FOR_BACKEND, /* the query is not populated and the backend is not loaded */
- QUERY_START_PENDING, /* the query is not populated yet, but the backend is loaded */
- QUERY_IN_PROGRESS, /* the query is populated; components are still being processed */
- QUERY_DONE, /* the query is done, but still accepts object changes */
- QUERY_PARSE_ERROR /* a parse error occurred when initially creating the ESexp */
-} QueryState;
-
/* Private part of the Query structure */
struct _QueryPrivate {
/* The backend we are monitoring */
CalBackend *backend;
- /* The cache backend */
- QueryBackend *qb;
-
- /* The default timezone for the calendar. */
- icaltimezone *default_zone;
-
- /* Listeners to which we report changes in the live query */
- GList *listeners;
- GList *component_listeners;
+ /* The listener we report to */
+ GNOME_Evolution_Calendar_QueryListener listener;
+ EComponentListener *component_listener;
/* Sexp that defines the query */
- char *sexp;
- ESExp *esexp;
-
- /* Timeout handler ID for asynchronous queries and current state of the query */
- guint timeout_id;
- QueryState state;
-
- GList *cached_timeouts;
-
- /* List of UIDs that we still have to process */
- GList *pending_uids;
- int n_pending;
- int pending_total;
-
- /* Table of the UIDs we know do match the query */
- GHashTable *uids;
-
- /* The next component that will be handled in e_sexp_eval(); put here
- * just because the query object itself is the esexp context.
- */
- CalComponent *next_comp;
+ CalBackendObjectSExp *sexp;
};
+
static void query_class_init (QueryClass *class);
@@ -99,7 +59,6 @@ static void query_init (Query *query, QueryClass *class);
static void query_finalize (GObject *object);
static BonoboObjectClass *parent_class;
-static GList *cached_queries = NULL;
@@ -108,1626 +67,434 @@ BONOBO_TYPE_FUNC_FULL (Query,
BONOBO_TYPE_OBJECT,
query);
-/* Class initialization function for the live search query */
-static void
-query_class_init (QueryClass *class)
-{
- GObjectClass *object_class;
-
- object_class = (GObjectClass *) class;
-
- parent_class = g_type_class_peek_parent (class);
-
- object_class->finalize = query_finalize;
+/* Property IDs */
+enum props {
+ PROP_0,
+ PROP_BACKEND,
+ PROP_LISTENER,
+ PROP_SEXP
+};
- /* The Query interface (ha ha! query interface!) has no methods, so we
- * don't need to fiddle with the epv.
- */
-}
-/* Object initialization function for the live search query */
static void
-query_init (Query *query, QueryClass *class)
+listener_died_cb (EComponentListener *cl, gpointer data)
{
+ Query *query = QUERY (data);
QueryPrivate *priv;
- priv = g_new0 (QueryPrivate, 1);
- query->priv = priv;
-
- priv->backend = NULL;
- priv->qb = NULL;
- priv->default_zone = NULL;
- priv->listeners = NULL;
- priv->component_listeners = NULL;
- priv->sexp = NULL;
-
- priv->timeout_id = 0;
- priv->state = QUERY_WAIT_FOR_BACKEND;
-
- priv->cached_timeouts = NULL;
-
- priv->pending_uids = NULL;
- priv->uids = g_hash_table_new (g_str_hash, g_str_equal);
-
- priv->next_comp = NULL;
-}
-
-/* Used from g_hash_table_foreach(); frees a UID */
-static void
-free_uid_cb (gpointer key, gpointer value, gpointer data)
-{
- char *uid;
+ priv = query->priv;
- uid = key;
- g_free (uid);
+ g_object_unref (priv->component_listener);
+ priv->component_listener = NULL;
+
+ bonobo_object_release_unref (priv->listener, NULL);
+ priv->listener = NULL;
}
-/* Finalize handler for the live search query */
static void
-query_finalize (GObject *object)
+impl_Query_start (PortableServer_Servant servant, CORBA_Environment *ev)
{
Query *query;
QueryPrivate *priv;
- g_return_if_fail (object != NULL);
- g_return_if_fail (IS_QUERY (object));
-
- query = QUERY (object);
+ query = QUERY (bonobo_object_from_servant (servant));
priv = query->priv;
- if (priv->backend) {
- /* If we are waiting for the backend to be opened, we'll be
- * connected to its "opened" signal. If we are in the middle of
- * a query or if we are just waiting for object update
- * notifications, we'll have the "obj_removed" and "obj_updated"
- * connections. Otherwise, we are either in a parse error state
- * or waiting for the query to be populated, and in both cases
- * we have no signal connections.
- */
- if (priv->state == QUERY_WAIT_FOR_BACKEND
- || priv->state == QUERY_IN_PROGRESS || priv->state == QUERY_DONE)
- g_signal_handlers_disconnect_matched (G_OBJECT (priv->backend),
- G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, NULL, query);
-
- g_object_unref (priv->backend);
- priv->backend = NULL;
- }
-
- priv->qb = NULL;
-
- if (priv->listeners != NULL) {
- CORBA_Environment ev;
- GList *l;
-
- CORBA_exception_init (&ev);
- for (l = priv->listeners; l != NULL; l = l->next) {
- bonobo_object_release_unref (l->data, &ev);
-
- if (BONOBO_EX (&ev))
- g_message ("query_destroy(): Could not unref the listener\n");
- }
-
- CORBA_exception_free (&ev);
-
- g_list_free (priv->listeners);
- priv->listeners = NULL;
- }
-
- if (priv->component_listeners != NULL) {
- g_list_foreach (priv->component_listeners, (GFunc) g_object_unref, NULL);
- g_list_free (priv->component_listeners);
- priv->component_listeners = NULL;
- }
-
- if (priv->sexp) {
- g_free (priv->sexp);
- priv->sexp = NULL;
- }
-
- if (priv->esexp) {
- e_sexp_unref (priv->esexp);
- priv->esexp = NULL;
- }
-
- if (priv->timeout_id) {
- g_source_remove (priv->timeout_id);
- priv->timeout_id = 0;
- }
-
- if (priv->cached_timeouts) {
- GList *l;
-
- for (l = priv->cached_timeouts; l != NULL; l = l->next)
- g_source_remove (GPOINTER_TO_INT (l->data));
-
- g_list_free (priv->cached_timeouts);
- priv->cached_timeouts = NULL;
- }
-
- if (priv->pending_uids) {
- GList *l;
-
- for (l = priv->pending_uids; l; l = l->next) {
- char *uid;
-
- uid = l->data;
- g_assert (uid != NULL);
- g_free (uid);
- }
-
- g_list_free (priv->pending_uids);
- priv->pending_uids = NULL;
- priv->n_pending = 0;
- }
-
- g_hash_table_foreach (priv->uids, free_uid_cb, NULL);
- g_hash_table_destroy (priv->uids);
- priv->uids = NULL;
-
- g_free (priv);
- query->priv = NULL;
-
- if (G_OBJECT_CLASS (parent_class)->finalize)
- (* G_OBJECT_CLASS (parent_class)->finalize) (object);
-}
-
-
-
-/* E-Sexp functions */
-
-/* (time-now)
- *
- * Returns a time_t of time (NULL).
- */
-static ESExpResult *
-func_time_now (ESExp *esexp, int argc, ESExpResult **argv, void *data)
-{
- ESExpResult *result;
-
- if (argc != 0) {
- e_sexp_fatal_error (esexp, _("time-now expects 0 arguments"));
- return NULL;
- }
-
- result = e_sexp_result_new (esexp, ESEXP_RES_TIME);
- result->value.time = time (NULL);
-
- return result;
-}
-
-/* (make-time ISODATE)
- *
- * ISODATE - string, ISO 8601 date/time representation
- *
- * Constructs a time_t value for the specified date.
- */
-static ESExpResult *
-func_make_time (ESExp *esexp, int argc, ESExpResult **argv, void *data)
-{
- const char *str;
- time_t t;
- ESExpResult *result;
-
- if (argc != 1) {
- e_sexp_fatal_error (esexp, _("make-time expects 1 argument"));
- return NULL;
- }
-
- if (argv[0]->type != ESEXP_RES_STRING) {
- e_sexp_fatal_error (esexp, _("make-time expects argument 1 "
- "to be a string"));
- return NULL;
- }
- str = argv[0]->value.string;
-
- t = time_from_isodate (str);
- if (t == -1) {
- e_sexp_fatal_error (esexp, _("make-time argument 1 must be an "
- "ISO 8601 date/time string"));
- return NULL;
- }
-
- result = e_sexp_result_new (esexp, ESEXP_RES_TIME);
- result->value.time = t;
-
- return result;
+ cal_backend_start_query (priv->backend, query);
}
-/* (time-add-day TIME N)
- *
- * TIME - time_t, base time
- * N - int, number of days to add
- *
- * Adds the specified number of days to a time value.
- *
- * FIXME: TIMEZONES - need to use a timezone or daylight saving changes will
- * make the result incorrect.
- */
-static ESExpResult *
-func_time_add_day (ESExp *esexp, int argc, ESExpResult **argv, void *data)
-{
- ESExpResult *result;
- time_t t;
- int n;
-
- if (argc != 2) {
- e_sexp_fatal_error (esexp, _("time-add-day expects 2 arguments"));
- return NULL;
- }
-
- if (argv[0]->type != ESEXP_RES_TIME) {
- e_sexp_fatal_error (esexp, _("time-add-day expects argument 1 "
- "to be a time_t"));
- return NULL;
- }
- t = argv[0]->value.time;
-
- if (argv[1]->type != ESEXP_RES_INT) {
- e_sexp_fatal_error (esexp, _("time-add-day expects argument 2 "
- "to be an integer"));
- return NULL;
- }
- n = argv[1]->value.number;
-
- result = e_sexp_result_new (esexp, ESEXP_RES_TIME);
- result->value.time = time_add_day (t, n);
-
- return result;
-}
-
-/* (time-day-begin TIME)
- *
- * TIME - time_t, base time
- *
- * Returns the start of the day, according to the local time.
- *
- * FIXME: TIMEZONES - this uses the current Unix timezone.
- */
-static ESExpResult *
-func_time_day_begin (ESExp *esexp, int argc, ESExpResult **argv, void *data)
-{
- time_t t;
- ESExpResult *result;
-
- if (argc != 1) {
- e_sexp_fatal_error (esexp, _("time-day-begin expects 1 argument"));
- return NULL;
- }
-
- if (argv[0]->type != ESEXP_RES_TIME) {
- e_sexp_fatal_error (esexp, _("time-day-begin expects argument 1 "
- "to be a time_t"));
- return NULL;
- }
- t = argv[0]->value.time;
-
- result = e_sexp_result_new (esexp, ESEXP_RES_TIME);
- result->value.time = time_day_begin (t);
-
- return result;
-}
-
-/* (time-day-end TIME)
- *
- * TIME - time_t, base time
- *
- * Returns the end of the day, according to the local time.
- *
- * FIXME: TIMEZONES - this uses the current Unix timezone.
- */
-static ESExpResult *
-func_time_day_end (ESExp *esexp, int argc, ESExpResult **argv, void *data)
-{
- time_t t;
- ESExpResult *result;
-
- if (argc != 1) {
- e_sexp_fatal_error (esexp, _("time-day-end expects 1 argument"));
- return NULL;
- }
-
- if (argv[0]->type != ESEXP_RES_TIME) {
- e_sexp_fatal_error (esexp, _("time-day-end expects argument 1 "
- "to be a time_t"));
- return NULL;
- }
- t = argv[0]->value.time;
-
- result = e_sexp_result_new (esexp, ESEXP_RES_TIME);
- result->value.time = time_day_end (t);
-
- return result;
-}
-
-/* (get-vtype)
- *
- * Returns a string indicating the type of component (VEVENT, VTODO, VJOURNAL,
- * VFREEBUSY, VTIMEZONE, UNKNOWN).
- */
-static ESExpResult *
-func_get_vtype (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+static void
+query_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
{
Query *query;
QueryPrivate *priv;
- CalComponent *comp;
- CalComponentVType vtype;
- char *str;
- ESExpResult *result;
+ CORBA_Environment ev;
- query = QUERY (data);
+ query = QUERY (object);
priv = query->priv;
-
- g_assert (priv->next_comp != NULL);
- comp = priv->next_comp;
-
- /* Check argument types */
-
- if (argc != 0) {
- e_sexp_fatal_error (esexp, _("get-vtype expects 0 arguments"));
- return NULL;
- }
-
- /* Get the type */
-
- vtype = cal_component_get_vtype (comp);
-
- switch (vtype) {
- case CAL_COMPONENT_EVENT:
- str = g_strdup ("VEVENT");
- break;
-
- case CAL_COMPONENT_TODO:
- str = g_strdup ("VTODO");
+
+ switch (property_id) {
+ case PROP_BACKEND:
+ priv->backend = CAL_BACKEND (g_value_dup_object (value));
break;
+ case PROP_LISTENER:
+ CORBA_exception_init (&ev);
+ priv->listener = CORBA_Object_duplicate (g_value_get_pointer (value), &ev);
+ CORBA_exception_free (&ev);
- case CAL_COMPONENT_JOURNAL:
- str = g_strdup ("VJOURNAL");
+ priv->component_listener = e_component_listener_new (priv->listener);
+ g_signal_connect (G_OBJECT (priv->component_listener), "component_died",
+ G_CALLBACK (listener_died_cb), query);
break;
-
- case CAL_COMPONENT_FREEBUSY:
- str = g_strdup ("VFREEBUSY");
+ case PROP_SEXP:
+ priv->sexp = CAL_BACKEND_OBJECT_SEXP (g_value_dup_object (value));
break;
-
- case CAL_COMPONENT_TIMEZONE:
- str = g_strdup ("VTIMEZONE");
- break;
-
default:
- str = g_strdup ("UNKNOWN");
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
-
- result = e_sexp_result_new (esexp, ESEXP_RES_STRING);
- result->value.string = str;
-
- return result;
}
-/* Sets a boolean value in the data to TRUE; called from
- * cal_recur_generate_instances() to indicate that at least one instance occurs
- * in the sought time range. We always return FALSE because we want the
- * recurrence engine to finish as soon as possible.
- */
-static gboolean
-instance_occur_cb (CalComponent *comp, time_t start, time_t end, gpointer data)
-{
- gboolean *occurs;
-
- occurs = data;
- *occurs = TRUE;
-
- return FALSE;
-}
-
-/* Call the backend function to get a timezone from a TZID. */
-static icaltimezone*
-resolve_tzid (const char *tzid, gpointer data)
-{
- Query *query = data;
-
- if (!tzid || !tzid[0])
- return NULL;
- else
- return cal_backend_get_timezone (query->priv->backend, tzid);
-}
-
-
-/* (occur-in-time-range? START END)
- *
- * START - time_t, start of the time range
- * END - time_t, end of the time range
- *
- * Returns a boolean indicating whether the component has any occurrences in the
- * specified time range.
- */
-static ESExpResult *
-func_occur_in_time_range (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+static void
+query_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
{
Query *query;
QueryPrivate *priv;
- CalComponent *comp;
- time_t start, end;
- gboolean occurs;
- ESExpResult *result;
-
- query = QUERY (data);
+
+ query = QUERY (object);
priv = query->priv;
- g_assert (priv->next_comp != NULL);
- comp = priv->next_comp;
-
- /* Check argument types */
-
- if (argc != 2) {
- e_sexp_fatal_error (esexp, _("occur-in-time-range? expects 2 arguments"));
- return NULL;
- }
-
- if (argv[0]->type != ESEXP_RES_TIME) {
- e_sexp_fatal_error (esexp, _("occur-in-time-range? expects argument 1 "
- "to be a time_t"));
- return NULL;
- }
- start = argv[0]->value.time;
-
- if (argv[1]->type != ESEXP_RES_TIME) {
- e_sexp_fatal_error (esexp, _("occur-in-time-range? expects argument 2 "
- "to be a time_t"));
- return NULL;
- }
- end = argv[1]->value.time;
-
- /* See if there is at least one instance in that range */
-
- occurs = FALSE;
-
- cal_recur_generate_instances (comp, start, end,
- instance_occur_cb, &occurs,
- resolve_tzid, query, priv->default_zone);
-
- result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
- result->value.bool = occurs;
-
- return result;
-}
-
-/* Returns whether a list of CalComponentText items matches the specified string */
-static gboolean
-matches_text_list (GSList *text_list, const char *str)
-{
- GSList *l;
- gboolean matches;
-
- matches = FALSE;
-
- for (l = text_list; l; l = l->next) {
- CalComponentText *text;
-
- text = l->data;
- g_assert (text->value != NULL);
-
- if (e_utf8_strstrcasedecomp (text->value, str) != NULL) {
- matches = TRUE;
- break;
- }
+ switch (property_id) {
+ case PROP_BACKEND:
+ g_value_set_object (value, priv->backend);
+ case PROP_LISTENER:
+ g_value_set_pointer (value, priv->listener);
+ break;
+ case PROP_SEXP:
+ g_value_set_object (value, priv->sexp);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
}
-
- return matches;
-}
-
-/* Returns whether the comments in a component matches the specified string */
-static gboolean
-matches_comment (CalComponent *comp, const char *str)
-{
- GSList *list;
- gboolean matches;
-
- cal_component_get_comment_list (comp, &list);
- matches = matches_text_list (list, str);
- cal_component_free_text_list (list);
-
- return matches;
}
-/* Returns whether the description in a component matches the specified string */
-static gboolean
-matches_description (CalComponent *comp, const char *str)
-{
- GSList *list;
- gboolean matches;
-
- cal_component_get_description_list (comp, &list);
- matches = matches_text_list (list, str);
- cal_component_free_text_list (list);
-
- return matches;
-}
-
-/* Returns whether the summary in a component matches the specified string */
-static gboolean
-matches_summary (CalComponent *comp, const char *str)
+/* Class initialization function for the live search query */
+static void
+query_class_init (QueryClass *klass)
{
- CalComponentText text;
+ GObjectClass *object_class;
+ POA_GNOME_Evolution_Calendar_Query__epv *epv = &klass->epv;
+ GParamSpec *param;
+
+ object_class = (GObjectClass *) klass;
- cal_component_get_summary (comp, &text);
+ parent_class = g_type_class_peek_parent (klass);
- if (!text.value)
- return FALSE;
+ object_class->set_property = query_set_property;
+ object_class->get_property = query_get_property;
+ object_class->finalize = query_finalize;
- return e_utf8_strstrcasedecomp (text.value, str) != NULL;
-}
+ epv->start = impl_Query_start;
-/* Returns whether any text field in a component matches the specified string */
-static gboolean
-matches_any (CalComponent *comp, const char *str)
-{
- /* As an optimization, and to make life easier for the individual
- * predicate functions, see if we are looking for the empty string right
- * away.
- */
- if (strlen (str) == 0)
- return TRUE;
-
- return (matches_comment (comp, str)
- || matches_description (comp, str)
- || matches_summary (comp, str));
+ param = g_param_spec_object ("backend", NULL, NULL, CAL_BACKEND_TYPE,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (object_class, PROP_BACKEND, 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 ("sexp", NULL, NULL, CAL_TYPE_BACKEND_OBJECT_SEXP,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (object_class, PROP_SEXP, param);
}
-/* (contains? FIELD STR)
- *
- * FIELD - string, name of field to match (any, comment, description, summary)
- * STR - string, match string
- *
- * Returns a boolean indicating whether the specified field contains the
- * specified string.
- */
-static ESExpResult *
-func_contains (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+/* Object initialization function for the live search query */
+static void
+query_init (Query *query, QueryClass *class)
{
- Query *query;
QueryPrivate *priv;
- CalComponent *comp;
- const char *field;
- const char *str;
- gboolean matches;
- ESExpResult *result;
-
- query = QUERY (data);
- priv = query->priv;
-
- g_assert (priv->next_comp != NULL);
- comp = priv->next_comp;
-
- /* Check argument types */
-
- if (argc != 2) {
- e_sexp_fatal_error (esexp, _("contains? expects 2 arguments"));
- return NULL;
- }
-
- if (argv[0]->type != ESEXP_RES_STRING) {
- e_sexp_fatal_error (esexp, _("contains? expects argument 1 "
- "to be a string"));
- return NULL;
- }
- field = argv[0]->value.string;
- if (argv[1]->type != ESEXP_RES_STRING) {
- e_sexp_fatal_error (esexp, _("contains? expects argument 2 "
- "to be a string"));
- return NULL;
- }
- str = argv[1]->value.string;
-
- /* See if it matches */
-
- if (strcmp (field, "any") == 0)
- matches = matches_any (comp, str);
- else if (strcmp (field, "comment") == 0)
- matches = matches_comment (comp, str);
- else if (strcmp (field, "description") == 0)
- matches = matches_description (comp, str);
- else if (strcmp (field, "summary") == 0)
- matches = matches_summary (comp, str);
- else {
- e_sexp_fatal_error (esexp, _("contains? expects argument 1 to "
- "be one of \"any\", \"summary\", \"description\""));
- return NULL;
- }
-
- result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
- result->value.bool = matches;
+ priv = g_new0 (QueryPrivate, 1);
+ query->priv = priv;
- return result;
+ priv->backend = NULL;
+ priv->listener = NULL;
+ priv->component_listener = NULL;
+ priv->sexp = NULL;
}
-/* (has-categories? STR+)
- * (has-categories? #f)
- *
- * STR - At least one string specifying a category
- * Or you can specify a single #f (boolean false) value for components
- * that have no categories assigned to them ("unfiled").
- *
- * Returns a boolean indicating whether the component has all the specified
- * categories.
- */
-static ESExpResult *
-func_has_categories (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+/* Finalize handler for the live search query */
+static void
+query_finalize (GObject *object)
{
Query *query;
QueryPrivate *priv;
- CalComponent *comp;
- gboolean unfiled;
- int i;
- GSList *categories;
- gboolean matches;
- ESExpResult *result;
-
- query = QUERY (data);
- priv = query->priv;
-
- g_assert (priv->next_comp != NULL);
- comp = priv->next_comp;
-
- /* Check argument types */
-
- if (argc < 1) {
- e_sexp_fatal_error (esexp, _("has-categories? expects at least 1 argument"));
- return NULL;
- }
-
- if (argc == 1 && argv[0]->type == ESEXP_RES_BOOL)
- unfiled = TRUE;
- else
- unfiled = FALSE;
-
- if (!unfiled)
- for (i = 0; i < argc; i++)
- if (argv[i]->type != ESEXP_RES_STRING) {
- e_sexp_fatal_error (esexp, _("has-categories? expects all arguments "
- "to be strings or one and only one "
- "argument to be a boolean false (#f)"));
- return NULL;
- }
-
- /* Search categories. First, if there are no categories we return
- * whether unfiled components are supposed to match.
- */
-
- cal_component_get_categories_list (comp, &categories);
- if (!categories) {
- result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
- result->value.bool = unfiled;
-
- return result;
- }
-
- /* Otherwise, we *do* have categories but unfiled components were
- * requested, so this component does not match.
- */
- if (unfiled) {
- result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
- result->value.bool = FALSE;
-
- return result;
- }
-
- matches = TRUE;
- for (i = 0; i < argc; i++) {
- const char *sought;
- GSList *l;
- gboolean has_category;
-
- sought = argv[i]->value.string;
-
- has_category = FALSE;
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (IS_QUERY (object));
- for (l = categories; l; l = l->next) {
- const char *category;
+ query = QUERY (object);
+ priv = query->priv;
- category = l->data;
+ if (priv->backend)
+ g_object_unref (priv->backend);
- if (strcmp (category, sought) == 0) {
- has_category = TRUE;
- break;
- }
- }
+ if (priv->listener != NULL)
+ bonobo_object_release_unref (priv->listener, NULL);
- if (!has_category) {
- matches = FALSE;
- break;
- }
- }
+ if (priv->component_listener != NULL)
+ g_object_unref (priv->component_listener);
- cal_component_free_categories_list (categories);
+ if (priv->sexp)
+ g_object_unref (priv->sexp);
- result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
- result->value.bool = matches;
+ g_free (priv);
- return result;
+ if (G_OBJECT_CLASS (parent_class)->finalize)
+ (* G_OBJECT_CLASS (parent_class)->finalize) (object);
}
-/* (is-completed?)
- *
- * Returns a boolean indicating whether the component is completed (i.e. has
- * a COMPLETED property. This is really only useful for TODO components.
- */
-static ESExpResult *
-func_is_completed (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+/**
+ * query_new:
+ * @backend: Calendar backend that the query object will monitor.
+ * @ql: Listener for query results.
+ * @sexp: Sexp that defines the query.
+ *
+ * Creates a new query engine object that monitors a calendar backend.
+ *
+ * Return value: A newly-created query object, or NULL on failure.
+ **/
+Query *
+query_new (CalBackend *backend,
+ GNOME_Evolution_Calendar_QueryListener ql,
+ CalBackendObjectSExp *sexp)
{
Query *query;
- QueryPrivate *priv;
- CalComponent *comp;
- ESExpResult *result;
- struct icaltimetype *t;
- gboolean complete = FALSE;
-
- query = QUERY (data);
- priv = query->priv;
-
- g_assert (priv->next_comp != NULL);
- comp = priv->next_comp;
-
- /* Check argument types */
-
- if (argc != 0) {
- e_sexp_fatal_error (esexp, _("is-completed? expects 0 arguments"));
- return NULL;
- }
-
- cal_component_get_completed (comp, &t);
- if (t) {
- complete = TRUE;
- cal_component_free_icaltimetype (t);
- }
- result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
- result->value.bool = complete;
+ query = g_object_new (QUERY_TYPE, "backend", backend, "listener", ql,
+ "sexp", sexp, NULL);
- return result;
+ return query;
}
-/* (completed-before? TIME)
+/**
+ * query_get_sexp
+ * @query: A #Query object.
*
- * TIME - time_t
+ * Get the expression used for the given query.
*
- * Returns a boolean indicating whether the component was completed on or
- * before the given time (i.e. it checks the COMPLETED property).
- * This is really only useful for TODO components.
+ * Returns: the query expression used to search.
*/
-static ESExpResult *
-func_completed_before (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+const char *
+query_get_text (Query *query)
{
- Query *query;
- QueryPrivate *priv;
- CalComponent *comp;
- ESExpResult *result;
- struct icaltimetype *tt;
- icaltimezone *zone;
- gboolean retval = FALSE;
- time_t before_time, completed_time;
-
- query = QUERY (data);
- priv = query->priv;
-
- g_assert (priv->next_comp != NULL);
- comp = priv->next_comp;
-
- /* Check argument types */
-
- if (argc != 1) {
- e_sexp_fatal_error (esexp, _("completed-before? expects 1 argument"));
- return NULL;
- }
-
- if (argv[0]->type != ESEXP_RES_TIME) {
- e_sexp_fatal_error (esexp, _("completed-before? expects argument 1 "
- "to be a time_t"));
- return NULL;
- }
- before_time = argv[0]->value.time;
-
- cal_component_get_completed (comp, &tt);
- if (tt) {
- /* COMPLETED must be in UTC. */
- zone = icaltimezone_get_utc_timezone ();
- completed_time = icaltime_as_timet_with_zone (*tt, zone);
-
-#if 0
- g_print ("Query Time : %s", ctime (&before_time));
- g_print ("Completed Time: %s", ctime (&completed_time));
-#endif
-
- /* We want to return TRUE if before_time is after
- completed_time. */
- if (difftime (before_time, completed_time) > 0) {
-#if 0
- g_print (" Returning TRUE\n");
-#endif
- retval = TRUE;
- }
-
- cal_component_free_icaltimetype (tt);
- }
-
- result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
- result->value.bool = retval;
-
- return result;
-}
-
-
-
-/* Adds a component to our the UIDs hash table and notifies the client */
-static void
-add_component (Query *query, const char *uid, gboolean query_in_progress, int n_scanned, int total)
-{
- QueryPrivate *priv;
- char *old_uid;
- CORBA_Environment ev;
- GList *l;
-
- if (query_in_progress)
- g_assert (n_scanned > 0 || n_scanned <= total);
-
- priv = query->priv;
-
- if (g_hash_table_lookup_extended (priv->uids, uid, (gpointer *) &old_uid, NULL)) {
- g_hash_table_remove (priv->uids, old_uid);
- g_free (old_uid);
- }
-
- g_hash_table_insert (priv->uids, g_strdup (uid), NULL);
-
- CORBA_exception_init (&ev);
- for (l = priv->listeners; l != NULL; l = l->next) {
- GNOME_Evolution_Calendar_CalObjUIDSeq *corba_uids;
-
- corba_uids = GNOME_Evolution_Calendar_CalObjUIDSeq__alloc ();
- CORBA_sequence_set_release (corba_uids, TRUE);
- corba_uids->_buffer = CORBA_sequence_GNOME_Evolution_Calendar_CalObjUID_allocbuf (1);
- corba_uids->_length = 1;
- corba_uids->_buffer[0] = CORBA_string_dup (uid);
-
- GNOME_Evolution_Calendar_QueryListener_notifyObjUpdated (
- l->data,
- corba_uids,
- query_in_progress,
- n_scanned,
- total,
- &ev);
-
- if (BONOBO_EX (&ev))
- g_message ("add_component(): Could not notify the listener of an "
- "updated component");
-
- CORBA_free (corba_uids);
- }
+ g_return_val_if_fail (IS_QUERY (query), NULL);
- CORBA_exception_free (&ev);
+ return cal_backend_object_sexp_text (query->priv->sexp);
}
-/* Removes a component from our the UIDs hash table and notifies the client */
-static void
-remove_component (Query *query, const char *uid)
+CalBackendObjectSExp *
+query_get_object_sexp (Query *query)
{
- QueryPrivate *priv;
- char *old_uid;
- CORBA_Environment ev;
- GList *l;
-
- priv = query->priv;
-
- if (!g_hash_table_lookup_extended (priv->uids, uid, (gpointer *) &old_uid, NULL))
- return;
-
- /* The component did match the query before but it no longer does, so we
- * have to notify the client.
- */
-
- g_hash_table_remove (priv->uids, old_uid);
- g_free (old_uid);
-
- CORBA_exception_init (&ev);
- for (l = priv->listeners; l != NULL; l = l->next) {
- GNOME_Evolution_Calendar_QueryListener_notifyObjRemoved (
- l->data,
- (char *) uid,
- &ev);
-
- if (BONOBO_EX (&ev))
- g_message ("remove_component(): Could not notify the listener of a "
- "removed component");
- }
+ g_return_val_if_fail (IS_QUERY (query), NULL);
- CORBA_exception_free (&ev);
+ return query->priv->sexp;
}
-/* Removes a component from the list of pending UIDs */
-static void
-remove_from_pending (Query *query, const char *remove_uid)
+gboolean
+query_object_matches (Query *query, const char *object)
{
QueryPrivate *priv;
- GList *l;
+
+ g_return_val_if_fail (query != NULL, FALSE);
+ g_return_val_if_fail (IS_QUERY (query), FALSE);
+ g_return_val_if_fail (object != NULL, FALSE);
priv = query->priv;
-
- for (l = priv->pending_uids; l; l = l->next) {
- char *uid;
-
- g_assert (priv->n_pending > 0);
-
- uid = l->data;
- if (strcmp (remove_uid, uid))
- continue;
-
- g_free (uid);
-
- priv->pending_uids = g_list_remove_link (priv->pending_uids, l);
- g_list_free_1 (l);
- priv->n_pending--;
-
- g_assert ((priv->pending_uids && priv->n_pending != 0)
- || (!priv->pending_uids && priv->n_pending == 0));
-
- break;
- }
-}
-
-static struct {
- char *name;
- ESExpFunc *func;
-} functions[] = {
- /* Time-related functions */
- { "time-now", func_time_now },
- { "make-time", func_make_time },
- { "time-add-day", func_time_add_day },
- { "time-day-begin", func_time_day_begin },
- { "time-day-end", func_time_day_end },
-
- /* Component-related functions */
- { "get-vtype", func_get_vtype },
- { "occur-in-time-range?", func_occur_in_time_range },
- { "contains?", func_contains },
- { "has-categories?", func_has_categories },
- { "is-completed?", func_is_completed },
- { "completed-before?", func_completed_before }
-};
-
-/* Initializes a sexp by interning our own symbols */
-static ESExp *
-create_sexp (Query *query)
-{
- ESExp *esexp;
- int i;
-
- esexp = e_sexp_new ();
-
- for (i = 0; i < (sizeof (functions) / sizeof (functions[0])); i++)
- e_sexp_add_function (esexp, 0, functions[i].name, functions[i].func, query);
-
- return esexp;
+
+ return cal_backend_object_sexp_match_object (priv->sexp, object, priv->backend);
}
-/* Creates the ESexp and parses the esexp. If a parse error occurs, it sets the
- * query state to QUERY_PARSE_ERROR and returns FALSE.
- */
-static gboolean
-parse_sexp (Query *query)
+void
+query_notify_objects_added (Query *query, const GList *objects)
{
QueryPrivate *priv;
+ GNOME_Evolution_Calendar_stringlist obj_list;
+ CORBA_Environment ev;
+ const GList *l;
+ int num_objs, i;
+
+ g_return_if_fail (query != NULL);
+ g_return_if_fail (IS_QUERY (query));
priv = query->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
- /* Compile the query string */
-
- priv->esexp = create_sexp (query);
-
- g_assert (priv->sexp != NULL);
- e_sexp_input_text (priv->esexp, priv->sexp, strlen (priv->sexp));
-
- if (e_sexp_parse (priv->esexp) == -1) {
- const char *error_str;
- CORBA_Environment ev;
- GList *l;
-
- priv->state = QUERY_PARSE_ERROR;
-
- /* Report the error to the listeners */
+ num_objs = g_list_length ((GList*)objects);
+ obj_list._buffer = GNOME_Evolution_Calendar_stringlist_allocbuf (num_objs);
+ obj_list._maximum = num_objs;
+ obj_list._length = num_objs;
- error_str = e_sexp_error (priv->esexp);
- g_assert (error_str != NULL);
+ for (l = objects, i = 0; l; l = l->next, i++)
+ obj_list._buffer[i] = CORBA_string_dup (l->data);
- CORBA_exception_init (&ev);
- for (l = priv->listeners; l != NULL; l = l->next) {
- GNOME_Evolution_Calendar_QueryListener_notifyQueryDone (
- l->data,
- GNOME_Evolution_Calendar_QueryListener_PARSE_ERROR,
- error_str,
- &ev);
-
- if (BONOBO_EX (&ev))
- g_message ("parse_sexp(): Could not notify the listener of "
- "a parse error");
- }
-
- CORBA_exception_free (&ev);
+ GNOME_Evolution_Calendar_QueryListener_notifyObjectsAdded (priv->listener, &obj_list, &ev);
- e_sexp_unref (priv->esexp);
- priv->esexp = NULL;
+ CORBA_free (obj_list._buffer);
- /* remove the query from the list of cached queries */
- cached_queries = g_list_remove (cached_queries, query);
- bonobo_object_unref (BONOBO_OBJECT (query));
-
- return FALSE;
- }
+ if (BONOBO_EX (&ev))
+ g_warning (G_STRLOC ": could not notify the listener of object addition");
- return TRUE;
+ CORBA_exception_free (&ev);
}
-/* Evaluates the query sexp on the specified component and notifies the listener
- * as appropriate.
- */
-static void
-match_component (Query *query, const char *uid,
- gboolean query_in_progress, int n_scanned, int total)
+void
+query_notify_objects_added_1 (Query *query, const char *object)
{
QueryPrivate *priv;
- CalComponent *comp;
- ESExpResult *result;
+ GList objects;
+
+ g_return_if_fail (query != NULL);
+ g_return_if_fail (IS_QUERY (query));
priv = query->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
- g_assert (priv->state == QUERY_IN_PROGRESS || priv->state == QUERY_DONE);
- g_assert (priv->esexp != NULL);
-
- comp = query_backend_get_object_component (priv->qb, uid);
- if (!comp)
- return;
-
- /* Eval the sexp */
-
- g_assert (priv->next_comp == NULL);
-
- priv->next_comp = comp;
- result = e_sexp_eval (priv->esexp);
- priv->next_comp = NULL;
-
- if (!result) {
- const char *error_str;
- CORBA_Environment ev;
- GList *l;
-
- error_str = e_sexp_error (priv->esexp);
- g_assert (error_str != NULL);
-
- CORBA_exception_init (&ev);
- for (l = priv->listeners; l != NULL; l = l->next) {
- GNOME_Evolution_Calendar_QueryListener_notifyEvalError (
- l->data,
- error_str,
- &ev);
-
- if (BONOBO_EX (&ev))
- g_message ("match_component(): Could not notify the listener of "
- "an evaluation error");
- }
-
- CORBA_exception_free (&ev);
- return;
- } else if (result->type != ESEXP_RES_BOOL) {
- CORBA_Environment ev;
- GList *l;
-
- CORBA_exception_init (&ev);
- for (l = priv->listeners; l != NULL; l = l->next) {
- GNOME_Evolution_Calendar_QueryListener_notifyEvalError (
- l->data,
- _("Evaluation of the search expression did not yield a boolean value"),
- &ev);
-
- if (BONOBO_EX (&ev))
- g_message ("match_component(): Could not notify the listener of "
- "an unexpected result value type when evaluating the "
- "search expression");
- }
-
- CORBA_exception_free (&ev);
- } else {
- /* Success; process the component accordingly */
+ objects.next = objects.prev = NULL;
+ objects.data = (gpointer)object;
- if (result->value.bool)
- add_component (query, uid, query_in_progress, n_scanned, total);
- else
- remove_component (query, uid);
- }
-
- e_sexp_result_free (priv->esexp, result);
+ query_notify_objects_added (query, &objects);
}
-/* Processes all components that are queued in the list */
-static gboolean
-process_components_cb (gpointer data)
+void
+query_notify_objects_modified (Query *query, const GList *objects)
{
- Query *query;
QueryPrivate *priv;
- char *uid;
- GList *l;
+ GNOME_Evolution_Calendar_CalObjUIDSeq obj_list;
CORBA_Environment ev;
+ const GList *l;
+ int num_objs, i;
+
+ g_return_if_fail (query != NULL);
+ g_return_if_fail (IS_QUERY (query));
- query = QUERY (data);
priv = query->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
- g_source_remove (priv->timeout_id);
- priv->timeout_id = 0;
-
- bonobo_object_ref (BONOBO_OBJECT (query));
-
- while (priv->pending_uids) {
- g_assert (priv->n_pending > 0);
-
- /* Fetch the component */
-
- l = priv->pending_uids;
- priv->pending_uids = g_list_remove_link (priv->pending_uids, l);
- priv->n_pending--;
-
- g_assert ((priv->pending_uids && priv->n_pending != 0)
- || (!priv->pending_uids && priv->n_pending == 0));
-
- uid = l->data;
- g_assert (uid != NULL);
-
- g_list_free_1 (l);
-
- match_component (query, uid,
- TRUE,
- priv->pending_total - priv->n_pending,
- priv->pending_total);
-
- g_free (uid);
+ num_objs = g_list_length ((GList*)objects);
+ obj_list._buffer = GNOME_Evolution_Calendar_stringlist_allocbuf (num_objs);
+ obj_list._maximum = num_objs;
+ obj_list._length = num_objs;
- /* run the main loop, for not blocking */
- if (gtk_events_pending ())
- gtk_main_iteration ();
- }
+ for (l = objects, i = 0; l; l = l->next, i++)
+ obj_list._buffer[i] = CORBA_string_dup (l->data);
- bonobo_object_unref (BONOBO_OBJECT (query));
- if (!priv || !priv->listeners)
- return FALSE;
+ GNOME_Evolution_Calendar_QueryListener_notifyObjectsModified (priv->listener, &obj_list, &ev);
- /* notify listeners that the query ended */
- priv->state = QUERY_DONE;
+ CORBA_free (obj_list._buffer);
- CORBA_exception_init (&ev);
- for (l = priv->listeners; l != NULL; l = l->next) {
- GNOME_Evolution_Calendar_QueryListener_notifyQueryDone (
- l->data,
- GNOME_Evolution_Calendar_QueryListener_SUCCESS,
- "",
- &ev);
-
- if (BONOBO_EX (&ev))
- g_message ("start_query(): Could not notify the listener of "
- "a finished query");
- }
+ if (BONOBO_EX (&ev))
+ g_warning (G_STRLOC ": could not notify the listener of object modification");
CORBA_exception_free (&ev);
-
- return FALSE;
}
-/* Callback used when a component changes in the backend */
-static void
-backend_obj_updated_cb (CalBackend *backend, const char *uid, gpointer data)
+void
+query_notify_objects_modified_1 (Query *query, const char *object)
{
- Query *query;
QueryPrivate *priv;
+ GList objects;
+
+ g_return_if_fail (query != NULL);
+ g_return_if_fail (IS_QUERY (query));
- query = QUERY (data);
priv = query->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
- g_assert (priv->state == QUERY_IN_PROGRESS || priv->state == QUERY_DONE);
-
- bonobo_object_ref (BONOBO_OBJECT (query));
-
- match_component (query, uid, FALSE, 0, 0);
- remove_from_pending (query, uid);
-
- bonobo_object_unref (BONOBO_OBJECT (query));
+ objects.next = objects.prev = NULL;
+ objects.data = (gpointer)object;
+
+ query_notify_objects_modified (query, &objects);
}
-/* Callback used when a component is removed from the backend */
-static void
-backend_obj_removed_cb (CalBackend *backend, const char *uid, gpointer data)
+void
+query_notify_objects_removed (Query *query, const GList *uids)
{
- Query *query;
QueryPrivate *priv;
+ GNOME_Evolution_Calendar_CalObjUIDSeq uid_list;
+ CORBA_Environment ev;
+ const GList *l;
+ int num_uids, i;
+
+ g_return_if_fail (query != NULL);
+ g_return_if_fail (IS_QUERY (query));
- query = QUERY (data);
priv = query->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
- g_assert (priv->state == QUERY_IN_PROGRESS || priv->state == QUERY_DONE);
-
- bonobo_object_ref (BONOBO_OBJECT (query));
-
- remove_component (query, uid);
- remove_from_pending (query, uid);
-
- bonobo_object_unref (BONOBO_OBJECT (query));
-}
-
-/* Actually starts the query */
-static void
-start_query (Query *query)
-{
- QueryPrivate *priv;
+ num_uids = g_list_length ((GList*)uids);
+ uid_list._buffer = GNOME_Evolution_Calendar_CalObjUIDSeq_allocbuf (num_uids);
+ uid_list._maximum = num_uids;
+ uid_list._length = num_uids;
- priv = query->priv;
+ for (l = uids, i = 0; l; l = l->next, i ++)
+ uid_list._buffer[i] = CORBA_string_dup (l->data);
- if (!parse_sexp (query))
- return;
+ GNOME_Evolution_Calendar_QueryListener_notifyObjectsRemoved (priv->listener, &uid_list, &ev);
- /* Populate the query with UIDs so that we can process them asynchronously */
+ CORBA_free (uid_list._buffer);
- priv->state = QUERY_IN_PROGRESS;
- priv->pending_uids = query_backend_get_uids (priv->qb, CALOBJ_TYPE_ANY);
- priv->pending_total = g_list_length (priv->pending_uids);
- priv->n_pending = priv->pending_total;
+ if (BONOBO_EX (&ev))
+ g_warning (G_STRLOC ": could not notify the listener of object removal");
- g_signal_connect (G_OBJECT (priv->backend), "obj_updated",
- G_CALLBACK (backend_obj_updated_cb),
- query);
- g_signal_connect (G_OBJECT (priv->backend), "obj_removed",
- G_CALLBACK (backend_obj_removed_cb),
- query);
- priv->timeout_id = g_timeout_add (100, (GSourceFunc) process_components_cb, query);
+ CORBA_exception_free (&ev);
}
-/* Idle handler for starting a query */
-static gboolean
-start_query_cb (gpointer data)
+void
+query_notify_objects_removed_1 (Query *query, const char *uid)
{
- Query *query;
QueryPrivate *priv;
+ GList uids;
+
+ g_return_if_fail (query != NULL);
+ g_return_if_fail (IS_QUERY (query));
- query = QUERY (data);
priv = query->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
- g_source_remove (priv->timeout_id);
- priv->timeout_id = 0;
-
- if (priv->state == QUERY_START_PENDING) {
- priv->state = QUERY_IN_PROGRESS;
- start_query (query);
- }
-
- return FALSE;
+ uids.next = uids.prev = NULL;
+ uids.data = (gpointer)uid;
+
+ query_notify_objects_modified (query, &uids);
}
-static void
-listener_died_cb (EComponentListener *cl, gpointer data)
+void
+query_notify_query_progress (Query *query, const char *message, int percent)
{
- QueryPrivate *priv;
- Query *query = QUERY (data);
- GNOME_Evolution_Calendar_QueryListener ql;
+ QueryPrivate *priv;
CORBA_Environment ev;
- priv = query->priv;
-
- ql = e_component_listener_get_component (cl);
- priv->listeners = g_list_remove (priv->listeners, ql);
-
- priv->component_listeners = g_list_remove (priv->component_listeners, cl);
- g_object_unref (cl);
+ g_return_if_fail (query != NULL);
+ g_return_if_fail (IS_QUERY (query));
+ priv = query->priv;
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
CORBA_exception_init (&ev);
- bonobo_object_release_unref (ql, &ev);
+
+ GNOME_Evolution_Calendar_QueryListener_notifyQueryProgress (priv->listener, message, percent, &ev);
if (BONOBO_EX (&ev))
- g_message ("query_destroy(): Could not unref the listener\n");
+ g_warning (G_STRLOC ": could not notify the listener of query progress");
CORBA_exception_free (&ev);
}
-static void
-add_uid_cb (gpointer key, gpointer value, gpointer data)
-{
- char *uid = (char *) key;
- GList **uidlist = (GList **) data;
-
- *uidlist = g_list_append (*uidlist, uid);
-}
-
-/* Idle handler for starting a cached query */
-static gboolean
-start_cached_query_cb (gpointer data)
-{
- CORBA_Environment ev;
- QueryPrivate *priv;
- EComponentListener *cl;
- StartCachedQueryInfo *info = (StartCachedQueryInfo *) data;
-
- priv = info->query->priv;
-
- g_source_remove (info->tid);
- priv->cached_timeouts = g_list_remove (priv->cached_timeouts,
- GINT_TO_POINTER (info->tid));
-
- /* if the query hasn't started yet, we add the listener */
- if (priv->state == QUERY_START_PENDING ||
- priv->state == QUERY_WAIT_FOR_BACKEND) {
- priv->listeners = g_list_append (priv->listeners, info->ql);
-
- cl = e_component_listener_new (info->ql);
- priv->component_listeners = g_list_append (priv->component_listeners, cl);
- g_signal_connect (G_OBJECT (cl), "component_died",
- G_CALLBACK (listener_died_cb), info->query);
- } else if (priv->state == QUERY_IN_PROGRESS) {
- /* if it's in progress, we re-add the timeout */
- info->tid = g_timeout_add (100, (GSourceFunc) start_cached_query_cb, info);
- priv->cached_timeouts = g_list_append (priv->cached_timeouts,
- GINT_TO_POINTER (info->tid));
-
- return FALSE;
- } else if (priv->state == QUERY_PARSE_ERROR) {
- /* notify listener of error */
- CORBA_exception_init (&ev);
- GNOME_Evolution_Calendar_QueryListener_notifyQueryDone (
- info->ql,
- GNOME_Evolution_Calendar_QueryListener_PARSE_ERROR,
- _("Parse error"),
- &ev);
-
- if (BONOBO_EX (&ev))
- g_message ("start_cached_query_cb(): Could not notify the listener of "
- "a parse error");
-
- CORBA_exception_free (&ev);
-
- /* remove all traces of this query */
- cached_queries = g_list_remove (cached_queries, info->query);
- bonobo_object_unref (BONOBO_OBJECT (info->query));
- } else if (priv->state == QUERY_DONE) {
- int len;
- GList *uid_list = NULL, *l;
-
- CORBA_exception_init (&ev);
-
- /* if the query is done, then we just notify the listener of all the
- * UIDS we've got so far, all at once */
- g_hash_table_foreach (priv->uids, (GHFunc) add_uid_cb, &uid_list);
-
- len = g_list_length (uid_list);
- if (len > 0) {
- int n;
- GNOME_Evolution_Calendar_CalObjUIDSeq *corba_uids;
-
- corba_uids = GNOME_Evolution_Calendar_CalObjUIDSeq__alloc ();
- corba_uids->_length = len;
- corba_uids->_maximum = len;
- corba_uids->_buffer = CORBA_sequence_GNOME_Evolution_Calendar_CalObjUID_allocbuf (len);
- CORBA_sequence_set_release (corba_uids, TRUE);
-
- for (l = uid_list, n = 0; l != NULL; l = l->next, n++)
- corba_uids->_buffer[n] = CORBA_string_dup ((CORBA_char *) l->data);
-
- GNOME_Evolution_Calendar_QueryListener_notifyObjUpdated (
- info->ql,
- corba_uids,
- TRUE,
- len,
- len, &ev);
-
- if (BONOBO_EX (&ev))
- g_message ("start_cached_query_cb(): Could not notify the listener of all "
- "cached components");
-
- CORBA_free (corba_uids);
- g_list_free (uid_list);
- }
-
- /* setup private data and notify listener that the query ended */
- priv->listeners = g_list_append (priv->listeners, info->ql);
-
- cl = e_component_listener_new (info->ql);
- priv->component_listeners = g_list_append (priv->component_listeners, cl);
- g_signal_connect (G_OBJECT (cl), "component_died",
- G_CALLBACK (listener_died_cb), info->query);
-
- GNOME_Evolution_Calendar_QueryListener_notifyQueryDone (
- info->ql,
- GNOME_Evolution_Calendar_QueryListener_SUCCESS,
- "",
- &ev);
- if (BONOBO_EX (&ev))
- g_message ("start_cached_query_cb(): Could not notify the listener of "
- "a finished query");
-
- CORBA_exception_free (&ev);
- }
-
- g_free (info);
-
- return FALSE;
-}
-
-/* Callback used when the backend gets loaded; we just queue the query to be
- * started later.
- */
-static void
-backend_opened_cb (CalBackend *backend, CalBackendOpenStatus status, gpointer data)
-{
- Query *query;
- QueryPrivate *priv;
-
- query = QUERY (data);
- priv = query->priv;
-
- g_assert (priv->state == QUERY_WAIT_FOR_BACKEND);
-
- g_signal_handlers_disconnect_matched (G_OBJECT (priv->backend),
- G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, NULL, query);
- priv->state = QUERY_START_PENDING;
-
- if (status == CAL_BACKEND_OPEN_SUCCESS) {
- g_assert (cal_backend_is_loaded (backend));
-
- priv->timeout_id = g_timeout_add (100, (GSourceFunc) start_query_cb, query);
- }
-}
-
-/* Callback used when the backend for a cached query is destroyed */
-static void
-backend_destroyed_cb (gpointer data, GObject *where_backend_was)
-{
- Query *query;
-
- query = QUERY (data);
-
- cached_queries = g_list_remove (cached_queries, query);
- bonobo_object_unref (BONOBO_OBJECT (query));
-}
-
-/**
- * query_construct:
- * @query: A live search query.
- * @backend: Calendar backend that the query object will monitor.
- * @ql: Listener for query results.
- * @sexp: Sexp that defines the query.
- *
- * Constructs a #Query object by binding it to a calendar backend and a query
- * listener. The @query object will start to populate itself asynchronously and
- * call the listener as appropriate.
- *
- * Return value: The same value as @query, or NULL if the query could not
- * be constructed.
- **/
-Query *
-query_construct (Query *query,
- CalBackend *backend,
- GNOME_Evolution_Calendar_QueryListener ql,
- const char *sexp)
+void
+query_notify_query_done (Query *query, GNOME_Evolution_Calendar_CallStatus status)
{
- QueryPrivate *priv;
+ QueryPrivate *priv;
CORBA_Environment ev;
- EComponentListener *cl;
- g_return_val_if_fail (query != NULL, NULL);
- g_return_val_if_fail (IS_QUERY (query), NULL);
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
- g_return_val_if_fail (ql != CORBA_OBJECT_NIL, NULL);
- g_return_val_if_fail (sexp != NULL, NULL);
+ g_return_if_fail (query != NULL);
+ g_return_if_fail (IS_QUERY (query));
priv = query->priv;
-
+ g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
+
CORBA_exception_init (&ev);
- priv->listeners = g_list_append (NULL, CORBA_Object_duplicate (ql, &ev));
- if (BONOBO_EX (&ev)) {
- g_message ("query_construct(): Could not duplicate the listener");
- priv->listeners = NULL;
- CORBA_exception_free (&ev);
- return NULL;
- }
- CORBA_exception_free (&ev);
-
- cl = e_component_listener_new (ql);
- priv->component_listeners = g_list_append (priv->component_listeners, cl);
- g_signal_connect (G_OBJECT (cl), "component_died",
- G_CALLBACK (listener_died_cb), query);
-
- priv->backend = backend;
- g_object_ref (priv->backend);
-
- priv->qb = query_backend_new (query, backend);
- priv->default_zone = cal_backend_get_default_timezone (backend);
-
- priv->sexp = g_strdup (sexp);
-
- /* Queue the query to be started asynchronously */
- if (cal_backend_is_loaded (priv->backend)) {
- priv->state = QUERY_START_PENDING;
+ GNOME_Evolution_Calendar_QueryListener_notifyQueryDone (priv->listener, status, &ev);
- priv->timeout_id = g_timeout_add (100, (GSourceFunc) start_query_cb, query);
- } else
- g_signal_connect (G_OBJECT (priv->backend), "opened",
- G_CALLBACK (backend_opened_cb),
- query);
-
- return query;
-}
-
-/**
- * query_new:
- * @backend: Calendar backend that the query object will monitor.
- * @ql: Listener for query results.
- * @sexp: Sexp that defines the query.
- *
- * Creates a new query engine object that monitors a calendar backend.
- *
- * Return value: A newly-created query object, or NULL on failure.
- **/
-Query *
-query_new (CalBackend *backend,
- GNOME_Evolution_Calendar_QueryListener ql,
- const char *sexp)
-{
- Query *query;
- GList *l;
-
- /* first, see if we've got this query in our cache */
- for (l = cached_queries; l != NULL; l = l->next) {
- query = QUERY (l->data);
-
- g_assert (query != NULL);
-
- if (query->priv->backend == backend &&
- !strcmp (query->priv->sexp, sexp)) {
- StartCachedQueryInfo *info;
- CORBA_Environment ev;
-
- info = g_new0 (StartCachedQueryInfo, 1);
- info->query = query;
-
- CORBA_exception_init (&ev);
- info->ql = CORBA_Object_duplicate (ql, &ev);
- if (BONOBO_EX (&ev)) {
- g_message ("query_new(): Could not duplicate listener object");
- g_free (info);
-
- return NULL;
- }
- CORBA_exception_free (&ev);
-
- info->tid = g_timeout_add (100, (GSourceFunc) start_cached_query_cb, info);
- query->priv->cached_timeouts = g_list_append (query->priv->cached_timeouts,
- GINT_TO_POINTER (info->tid));
-
- bonobo_object_ref (BONOBO_OBJECT (query));
- return query;
- }
- }
-
- /* not found, so create a new one */
- query = QUERY (g_object_new (QUERY_TYPE, NULL));
- if (!query_construct (query, backend, ql, sexp)) {
- bonobo_object_unref (BONOBO_OBJECT (query));
- return NULL;
- }
-
- /* add the new query to our cache */
- g_object_weak_ref (G_OBJECT (query->priv->backend),
- backend_destroyed_cb, query);
-
- bonobo_object_ref (BONOBO_OBJECT (query));
- cached_queries = g_list_append (cached_queries, query);
+ if (BONOBO_EX (&ev))
+ g_warning (G_STRLOC ": could not notify the listener of query completion");
- return query;
+ CORBA_exception_free (&ev);
}
diff --git a/calendar/pcs/query.h b/calendar/pcs/query.h
index 752c29eb40..9c03aa2661 100644
--- a/calendar/pcs/query.h
+++ b/calendar/pcs/query.h
@@ -24,6 +24,7 @@
#include <bonobo/bonobo-object.h>
#include "pcs/cal-common.h"
#include "pcs/evolution-calendar.h"
+#include "cal-backend-object-sexp.h"
G_BEGIN_DECLS
@@ -37,31 +38,43 @@ G_BEGIN_DECLS
typedef struct _QueryPrivate QueryPrivate;
-typedef struct {
+struct _Query {
BonoboObject xobject;
/* Private data */
QueryPrivate *priv;
-} Query;
+};
-typedef struct {
+struct _QueryClass {
BonoboObjectClass parent_class;
POA_GNOME_Evolution_Calendar_Query__epv epv;
-} QueryClass;
-
-GType query_get_type (void);
-
-Query *query_construct (Query *query,
- CalBackend *backend,
- GNOME_Evolution_Calendar_QueryListener ql,
- const char *sexp);
-
-Query *query_new (CalBackend *backend,
- GNOME_Evolution_Calendar_QueryListener ql,
- const char *sexp);
-
-
+};
+
+GType query_get_type (void);
+Query *query_new (CalBackend *backend,
+ GNOME_Evolution_Calendar_QueryListener ql,
+ CalBackendObjectSExp *sexp);
+const char *query_get_text (Query *query);
+CalBackendObjectSExp *query_get_object_sexp (Query *query);
+gboolean query_object_matches (Query *query, const char *object);
+void query_notify_objects_added (Query *query,
+ const GList *objects);
+void query_notify_objects_added_1 (Query *query,
+ const char *object);
+void query_notify_objects_modified (Query *query,
+ const GList *objects);
+void query_notify_objects_modified_1 (Query *query,
+ const char *object);
+void query_notify_objects_removed (Query *query,
+ const GList *uids);
+void query_notify_objects_removed_1 (Query *query,
+ const char *uid);
+void query_notify_query_progress (Query *query,
+ const char *message,
+ int percent);
+void query_notify_query_done (Query *query,
+ GNOME_Evolution_Calendar_CallStatus status);
G_END_DECLS
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 286058dc8e..343bbf3afb 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,7 +1,43 @@
+2003-10-21 Not Zed <NotZed@Ximian.com>
+
+ * providers/local/camel-local-folder.c (local_getv, local_setv):
+ use the right tag name for the index_body arg.
+ (local_sync): write any persistent metadata - to make it
+ persistent.
+ (camel_local_folder_construct): turn off indexing, for now, it
+ should be done in local_setv.
+
+ * providers/local/camel-local-folder.h: change body_index to a bool
+ type.
+
+ * camel-object.c (cobject_state_read, cobject_state_write): handle
+ bool types
+ (cobject_state_write): make sure we free all arg types.
+
+ * camel-arg.c (camel_argv_build):
+ (camel_arggetv_build): handle bool type.
+
+ * camel-arg.h: Added BOO (bool) type.
+
+2003-10-15 Not Zed <NotZed@Ximian.com>
+
+ * camel-store.c (camel_folder_info_build): Fix so we output the
+ tree in sorted depth-first order, rather in reverse.
+
2003-10-16 Jeffrey Stedfast <fejj@ximian.com>
* camel-sasl-kerberos4.c: Fixed a #include.
+2003-10-10 Not Zed <NotZed@Ximian.com>
+
+ * providers/local/camel-local-provider.c: set the url fragment
+ flag for local providers.
+
+ * camel-provider.h: Move the URL_PART_NEED bits to the high 16
+ bits, to allow for easier changes in the future. Added a
+ URL_PART_FRAGMENT flag for providers that use fragment = folder
+ path.
+
2003-10-09 Jeffrey Stedfast <fejj@ximian.com>
* camel-mime-utils.c (header_decode_date): Allow timezone offsets
@@ -20,6 +56,12 @@
localhost lookup results in a numeric IPv6 host, use the form
"[IPv6:<addr>]" as specified in rfc2821. Fixes bug #46006.
+2003-09-23 Ettore Perazzoli <ettore@ximian.com>
+
+ * providers/local/camel-local-provider.c: Set the IS_STORAGE bit
+ in the mbox provider, since it can now contain a hierarchy of
+ folders.
+
2003-09-23 Jeffrey Stedfast <fejj@ximian.com>
* providers/local/camel-mbox-store.c (get_folder): If the CREATE
@@ -687,6 +729,11 @@
addr->str to make sure that it is valid UTF-8, if not convert it
to UTF-8. Fixes bug #42170.
+2003-07-23 Ettore Perazzoli <ettore@ximian.com>
+
+ * camel-provider.c (camel_provider_init): Print the provider
+ directory as well, for debugging.
+
2003-07-23 Jeffrey Stedfast <fejj@ximian.com>
* camel-mime-message.c (find_best_encoding): Revert my previous
diff --git a/camel/camel-arg.c b/camel/camel-arg.c
index f8cd048f0a..bcd79bab59 100644
--- a/camel/camel-arg.c
+++ b/camel/camel-arg.c
@@ -60,6 +60,9 @@ int camel_argv_build(CamelArgV *tv)
case CAMEL_ARG_PTR:
a->ca_ptr = va_arg(tv->ap, void *);
break;
+ case CAMEL_ARG_BOO:
+ a->ca_int = va_arg(tv->ap, int) != 0;
+ break;
default:
printf("Error, unknown type, truncating result\n");
more = FALSE;
@@ -96,6 +99,7 @@ int camel_arggetv_build(CamelArgGetV *tv)
*a->ca_object = NULL;
break;
case CAMEL_ARG_INT:
+ case CAMEL_ARG_BOO:
a->ca_int = va_arg(tv->ap, int *);
*a->ca_int = 0;
break;
diff --git a/camel/camel-arg.h b/camel/camel-arg.h
index 1213596457..ebecc0f217 100644
--- a/camel/camel-arg.h
+++ b/camel/camel-arg.h
@@ -45,6 +45,7 @@ enum camel_arg_t {
CAMEL_ARG_DBL = 0x20000000, /* double */
CAMEL_ARG_STR = 0x30000000, /* c string */
CAMEL_ARG_PTR = 0x40000000, /* ptr */
+ CAMEL_ARG_BOO = 0x50000000, /* bool */
};
typedef struct _CamelArg CamelArg;
diff --git a/camel/camel-object.c b/camel/camel-object.c
index 31d458a59d..744e9f7566 100644
--- a/camel/camel-object.c
+++ b/camel/camel-object.c
@@ -439,6 +439,7 @@ cobject_state_read(CamelObject *obj, FILE *fp)
switch(argv->argv[argv->argc].tag & CAMEL_ARG_TYPE) {
case CAMEL_ARG_INT:
+ case CAMEL_ARG_BOO:
if (camel_file_util_decode_uint32(fp, &argv->argv[argv->argc].ca_int) == -1)
goto cleanup;
break;
@@ -535,6 +536,7 @@ cobject_state_write(CamelObject *obj, FILE *fp)
switch (arg->tag & CAMEL_ARG_TYPE) {
case CAMEL_ARG_INT:
+ case CAMEL_ARG_BOO:
if (camel_file_util_encode_uint32(fp, arg->ca_int) == -1)
goto abort;
break;
@@ -547,6 +549,13 @@ cobject_state_write(CamelObject *obj, FILE *fp)
res = 0;
abort:
+ for (i=0;i<argv->argc;i++) {
+ CamelArg *arg = &argv->argv[i];
+
+ if ((argv->argv[i].tag & CAMEL_ARG_TYPE) == CAMEL_ARG_STR)
+ camel_object_free(obj, arg->tag, arg->ca_str);
+ }
+
g_free(argv);
g_free(arggetv);
diff --git a/camel/camel-provider.c b/camel/camel-provider.c
index 9beacc02f0..321b3077cd 100644
--- a/camel/camel-provider.c
+++ b/camel/camel-provider.c
@@ -70,8 +70,8 @@ camel_provider_init (void)
dir = opendir (CAMEL_PROVIDERDIR);
if (!dir) {
- g_error ("Could not open camel provider directory: %s",
- g_strerror (errno));
+ g_error ("Could not open camel provider directory (%s): %s",
+ CAMEL_PROVIDERDIR, g_strerror (errno));
return NULL;
}
diff --git a/camel/camel-provider.h b/camel/camel-provider.h
index edfb424181..98c5a3ed6a 100644
--- a/camel/camel-provider.h
+++ b/camel/camel-provider.h
@@ -81,7 +81,7 @@ extern char *camel_provider_type_name[CAMEL_NUM_PROVIDER_TYPES];
#define CAMEL_URL_PART_PORT (1 << 4)
#define CAMEL_URL_PART_PATH (1 << 5)
-#define CAMEL_URL_PART_NEED 6
+#define CAMEL_URL_PART_NEED 8
/* Use these macros to test a provider's url_flags */
#define CAMEL_PROVIDER_ALLOWS(prov, flags) (prov->url_flags & (flags | (flags << CAMEL_URL_PART_NEED)))
@@ -102,7 +102,8 @@ extern char *camel_provider_type_name[CAMEL_NUM_PROVIDER_TYPES];
#define CAMEL_URL_NEED_PORT (CAMEL_URL_PART_PORT << CAMEL_URL_PART_NEED)
#define CAMEL_URL_NEED_PATH (CAMEL_URL_PART_PATH << CAMEL_URL_PART_NEED)
-#define CAMEL_URL_PATH_IS_ABSOLUTE (1 << 12)
+#define CAMEL_URL_FRAGMENT_IS_PATH (1 << 30) /* url uses fragment for folder name path, not path */
+#define CAMEL_URL_PATH_IS_ABSOLUTE (1 << 31)
#define CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT(prov) (prov->object_types[CAMEL_PROVIDER_STORE] && prov->object_types[CAMEL_PROVIDER_TRANSPORT])
diff --git a/camel/camel-store.c b/camel/camel-store.c
index eedc9dfa2a..3c49f312ec 100644
--- a/camel/camel-store.c
+++ b/camel/camel-store.c
@@ -776,7 +776,7 @@ CamelFolderInfo *
camel_folder_info_build (GPtrArray *folders, const char *namespace,
char separator, gboolean short_names)
{
- CamelFolderInfo *fi, *pfi, *top = NULL;
+ CamelFolderInfo *fi, *pfi, *top = NULL, *tail = NULL;
GHashTable *hash;
char *name, *p, *pname;
int i, nlen;
@@ -854,9 +854,15 @@ camel_folder_info_build (GPtrArray *folders, const char *namespace,
g_hash_table_insert (hash, pname, pfi);
g_ptr_array_add (folders, pfi);
}
- fi->sibling = pfi->child;
+ tail = pfi->child;
+ if (tail == NULL) {
+ pfi->child = fi;
+ } else {
+ while (tail->sibling)
+ tail = tail->sibling;
+ tail->sibling = fi;
+ }
fi->parent = pfi;
- pfi->child = fi;
} else if (!top)
top = fi;
}
@@ -864,13 +870,18 @@ camel_folder_info_build (GPtrArray *folders, const char *namespace,
g_hash_table_destroy (hash);
/* Link together the top-level folders */
+ tail = top;
for (i = 0; i < folders->len; i++) {
fi = folders->pdata[i];
if (fi->parent || fi == top)
continue;
- if (top)
- fi->sibling = top;
- top = fi;
+ if (tail == NULL) {
+ tail = fi;
+ top = fi;
+ } else {
+ tail->sibling = fi;
+ tail = fi;
+ }
}
return top;
diff --git a/camel/providers/local/camel-local-folder.c b/camel/providers/local/camel-local-folder.c
index 608954af94..b774c8b5f6 100644
--- a/camel/providers/local/camel-local-folder.c
+++ b/camel/providers/local/camel-local-folder.c
@@ -251,7 +251,9 @@ camel_local_folder_construct(CamelLocalFolder *lf, CamelStore *parent_store, con
}
camel_object_set(lf, NULL, CAMEL_OBJECT_STATE_FILE, statepath, NULL);
g_free (statepath);
-
+
+ lf->flags = flags;
+
if (camel_object_state_read(lf) == -1) {
/* FIXME: load defaults? */
}
@@ -269,7 +271,8 @@ camel_local_folder_construct(CamelLocalFolder *lf, CamelStore *parent_store, con
the old-format 'ibex' files that might be lying around */
unlink(lf->index_path);
-#if 0
+ /* FIXME: Need to run indexing off of the setv method */
+#if 1
forceindex = FALSE;
#else
/* if we have no/invalid index file, force it */
@@ -292,8 +295,8 @@ camel_local_folder_construct(CamelLocalFolder *lf, CamelStore *parent_store, con
camel_text_index_remove(lf->index_path);
forceindex = FALSE;
}
-#endif
lf->flags = flags;
+#endif
folder->summary = (CamelFolderSummary *)CLOCALF_CLASS(lf)->create_summary(lf->summary_path, lf->folder_path, lf->index);
if (camel_local_summary_load((CamelLocalSummary *)folder->summary, forceindex, ex) == -1) {
@@ -404,7 +407,9 @@ local_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args)
break; }
- case CAMEL_LOCAL_FOLDER_INDEX_BODY:
+ case CAMEL_LOCAL_FOLDER_ARG_INDEX_BODY:
+ printf("getv:'%s' flags %08x\n", ((CamelFolder *)object)->full_name, ((CamelLocalFolder *)object)->flags);
+
/* FIXME: remove this from sotre flags */
*arg->ca_int = (((CamelLocalFolder *)folder)->flags & CAMEL_STORE_FOLDER_BODY_INDEX) != 0;
break;
@@ -431,9 +436,16 @@ local_setv(CamelObject *object, CamelException *ex, CamelArgV *args)
tag = arg->tag;
switch (tag & CAMEL_ARG_TAG) {
- case CAMEL_LOCAL_FOLDER_INDEX_BODY:
+ case CAMEL_LOCAL_FOLDER_ARG_INDEX_BODY:
/* FIXME: implement */
+ /* TODO: When turning on (off?) the index, we want to launch a task for it,
+ and make sure we dont have multiple tasks doing the same job */
printf("setting folder indexing %s\n", arg->ca_int?"on":"off");
+ if (arg->ca_int)
+ ((CamelLocalFolder *)object)->flags |= CAMEL_STORE_FOLDER_BODY_INDEX;
+ else
+ ((CamelLocalFolder *)object)->flags &= ~CAMEL_STORE_FOLDER_BODY_INDEX;
+ printf("setv:'%s' flags %08x\n", ((CamelFolder *)object)->full_name, ((CamelLocalFolder *)object)->flags);
break;
default:
continue;
@@ -494,6 +506,8 @@ local_sync(CamelFolder *folder, gboolean expunge, CamelException *ex)
if (camel_local_folder_lock(lf, CAMEL_LOCK_WRITE, ex) == -1)
return;
+ camel_object_state_write(lf);
+
/* if sync fails, we'll pass it up on exit through ex */
camel_local_summary_sync((CamelLocalSummary *)folder->summary, expunge, lf->changes, ex);
camel_local_folder_unlock(lf);
diff --git a/camel/providers/local/camel-local-folder.h b/camel/providers/local/camel-local-folder.h
index 4fb5980a07..73059f03b3 100644
--- a/camel/providers/local/camel-local-folder.h
+++ b/camel/providers/local/camel-local-folder.h
@@ -47,7 +47,7 @@ enum {
};
enum {
- CAMEL_LOCAL_FOLDER_INDEX_BODY = CAMEL_LOCAL_FOLDER_ARG_INDEX_BODY | CAMEL_ARG_INT,
+ CAMEL_LOCAL_FOLDER_INDEX_BODY = CAMEL_LOCAL_FOLDER_ARG_INDEX_BODY | CAMEL_ARG_BOO,
};
typedef struct {
diff --git a/camel/providers/local/camel-local-provider.c b/camel/providers/local/camel-local-provider.c
index 077bc45b5f..a52dfbde5f 100644
--- a/camel/providers/local/camel-local-provider.c
+++ b/camel/providers/local/camel-local-provider.c
@@ -50,7 +50,7 @@ static CamelProvider mh_provider = {
N_("For storing local mail in MH-like mail directories."),
"mail",
CAMEL_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_IS_LOCAL,
- CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE,
+ CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE | CAMEL_URL_FRAGMENT_IS_PATH,
mh_conf_entries,
/* ... */
};
@@ -65,8 +65,8 @@ static CamelProvider mbox_provider = {
N_("Local delivery"),
N_("For retrieving (moving) local mail from standard mbox formated spools into folders managed by Evolution."),
"mail",
- CAMEL_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_LOCAL,
- CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE,
+ CAMEL_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_IS_LOCAL,
+ CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE | CAMEL_URL_FRAGMENT_IS_PATH,
mbox_conf_entries,
/* ... */
};
@@ -84,7 +84,7 @@ static CamelProvider maildir_provider = {
N_("For storing local mail in maildir directories."),
"mail",
CAMEL_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_IS_LOCAL,
- CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE,
+ CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE | CAMEL_URL_FRAGMENT_IS_PATH,
maildir_conf_entries,
/* ... */
};
@@ -102,7 +102,7 @@ static CamelProvider spool_provider = {
N_("For reading and storing local mail in external standard mbox spool files.\nMay also be used to read a tree of Elm, Pine, or Mutt style folders."),
"mail",
CAMEL_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_STORAGE,
- CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE,
+ CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE | CAMEL_URL_FRAGMENT_IS_PATH,
spool_conf_entries,
/* ... */
};
diff --git a/composer/ChangeLog b/composer/ChangeLog
index b698c2cf57..1bc29bb5df 100644
--- a/composer/ChangeLog
+++ b/composer/ChangeLog
@@ -1,3 +1,37 @@
+2003-10-08 Chris Toshok <toshok@ximian.com>
+
+ * evolution-composer.c (corba_recipientlist_to_destv): EDestination =>
+ EABDestination, and e_destination => eab_destination.
+ (impl_Composer_set_headers): same.
+
+ * e-msg-composer.c (update_auto_recipients): EDestination =>
+ EABDestination, and e_destination => eab_destination.
+ (e_msg_composer_new_with_message): same.
+ (add_recipients): same.
+ (handle_mailto): same.
+ (e_msg_composer_set_headers): same.
+ (e_msg_composer_get_recipients): same.
+ (e_msg_composer_get_to): same.
+ (e_msg_composer_get_cc): same.
+ (e_msg_composer_get_bcc): same.
+
+ * e-msg-composer.h: EDestination => EABDestination, and
+ e_destination => eab_destination.
+
+ * e-msg-composer-hdrs.c (set_recipients_from_destv): EDestination
+ => EABDestination, and e_destination => eab_destination.
+ (e_msg_composer_hdrs_to_message_internal): same.
+ (e_msg_composer_hdrs_set_to): same.
+ (e_msg_composer_hdrs_set_cc): same.
+ (e_msg_composer_hdrs_set_bcc): same.
+ (e_msg_composer_hdrs_get_to): same.
+ (e_msg_composer_hdrs_get_cc): same.
+ (e_msg_composer_hdrs_get_bcc): same.
+ (e_msg_composer_hdrs_get_recipients): same.
+
+ * e-msg-composer-hdrs.h: EDestination => EABDestination, and
+ e_destination => eab_destination.
+
2003-09-26 Jeffrey Stedfast <fejj@ximian.com>
* e-msg-composer.c (save): Don't blindly claim that the file
diff --git a/composer/e-msg-composer-hdrs.c b/composer/e-msg-composer-hdrs.c
index e6d4bebe17..23c24a339a 100644
--- a/composer/e-msg-composer-hdrs.c
+++ b/composer/e-msg-composer-hdrs.c
@@ -51,7 +51,6 @@
#include "evolution-folder-selector-button.h"
#include "e-msg-composer-hdrs.h"
#include "mail/mail-config.h"
-#include "addressbook/backend/ebook/e-book-util.h"
extern EvolutionShellClient *global_shell_client;
@@ -837,9 +836,9 @@ e_msg_composer_hdrs_new (BonoboUIComponent *uic, int visible_mask, int visible_f
static void
set_recipients_from_destv (CamelMimeMessage *msg,
- EDestination **to_destv,
- EDestination **cc_destv,
- EDestination **bcc_destv,
+ EABDestination **to_destv,
+ EABDestination **cc_destv,
+ EABDestination **bcc_destv,
gboolean redirect)
{
CamelInternetAddress *to_addr;
@@ -856,12 +855,12 @@ set_recipients_from_destv (CamelMimeMessage *msg,
if (to_destv) {
for (i = 0; to_destv[i] != NULL; ++i) {
- text_addr = e_destination_get_address (to_destv[i]);
+ text_addr = eab_destination_get_address (to_destv[i]);
if (text_addr && *text_addr) {
target = to_addr;
- if (e_destination_is_evolution_list (to_destv[i])
- && !e_destination_list_show_addresses (to_destv[i])) {
+ if (eab_destination_is_evolution_list (to_destv[i])
+ && !eab_destination_list_show_addresses (to_destv[i])) {
target = bcc_addr;
seen_hidden_list = TRUE;
}
@@ -873,11 +872,11 @@ set_recipients_from_destv (CamelMimeMessage *msg,
if (cc_destv) {
for (i = 0; cc_destv[i] != NULL; ++i) {
- text_addr = e_destination_get_address (cc_destv[i]);
+ text_addr = eab_destination_get_address (cc_destv[i]);
if (text_addr && *text_addr) {
target = cc_addr;
- if (e_destination_is_evolution_list (cc_destv[i])
- && !e_destination_list_show_addresses (cc_destv[i])) {
+ if (eab_destination_is_evolution_list (cc_destv[i])
+ && !eab_destination_list_show_addresses (cc_destv[i])) {
target = bcc_addr;
seen_hidden_list = TRUE;
}
@@ -889,7 +888,7 @@ set_recipients_from_destv (CamelMimeMessage *msg,
if (bcc_destv) {
for (i = 0; bcc_destv[i] != NULL; ++i) {
- text_addr = e_destination_get_address (bcc_destv[i]);
+ text_addr = eab_destination_get_address (bcc_destv[i]);
if (text_addr && *text_addr) {
camel_address_decode (CAMEL_ADDRESS (bcc_addr), text_addr);
}
@@ -923,7 +922,7 @@ e_msg_composer_hdrs_to_message_internal (EMsgComposerHdrs *hdrs,
CamelMimeMessage *msg,
gboolean redirect)
{
- EDestination **to_destv, **cc_destv, **bcc_destv;
+ EABDestination **to_destv, **cc_destv, **bcc_destv;
CamelInternetAddress *addr;
const char *subject;
char *header;
@@ -959,9 +958,9 @@ e_msg_composer_hdrs_to_message_internal (EMsgComposerHdrs *hdrs,
set_recipients_from_destv (msg, to_destv, cc_destv, bcc_destv, redirect);
- e_destination_freev (to_destv);
- e_destination_freev (cc_destv);
- e_destination_freev (bcc_destv);
+ eab_destination_freev (to_destv);
+ eab_destination_freev (cc_destv);
+ eab_destination_freev (bcc_destv);
}
if (hdrs->visible_mask & E_MSG_COMPOSER_VISIBLE_POSTTO) {
@@ -1056,26 +1055,26 @@ e_msg_composer_hdrs_set_reply_to (EMsgComposerHdrs *hdrs,
void
e_msg_composer_hdrs_set_to (EMsgComposerHdrs *hdrs,
- EDestination **to_destv)
+ EABDestination **to_destv)
{
char *str;
g_return_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs));
- str = e_destination_exportv (to_destv);
+ str = eab_destination_exportv (to_destv);
bonobo_widget_set_property (BONOBO_WIDGET (hdrs->priv->to.entry), "destinations", TC_CORBA_string, str ? str : "", NULL);
g_free (str);
}
void
e_msg_composer_hdrs_set_cc (EMsgComposerHdrs *hdrs,
- EDestination **cc_destv)
+ EABDestination **cc_destv)
{
char *str;
g_return_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs));
- str = e_destination_exportv (cc_destv);
+ str = eab_destination_exportv (cc_destv);
bonobo_widget_set_property (BONOBO_WIDGET (hdrs->priv->cc.entry), "destinations", TC_CORBA_string, str ? str :"", NULL);
if (str && *str)
set_pair_visibility (hdrs, &hdrs->priv->cc, TRUE);
@@ -1084,13 +1083,13 @@ e_msg_composer_hdrs_set_cc (EMsgComposerHdrs *hdrs,
void
e_msg_composer_hdrs_set_bcc (EMsgComposerHdrs *hdrs,
- EDestination **bcc_destv)
+ EABDestination **bcc_destv)
{
char *str;
g_return_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs));
- str = e_destination_exportv (bcc_destv);
+ str = eab_destination_exportv (bcc_destv);
bonobo_widget_set_property (BONOBO_WIDGET (hdrs->priv->bcc.entry), "destinations", TC_CORBA_string, str ? str : "", NULL);
if (str && *str)
set_pair_visibility (hdrs, &hdrs->priv->bcc, TRUE);
@@ -1159,67 +1158,67 @@ e_msg_composer_hdrs_get_reply_to (EMsgComposerHdrs *hdrs)
return addr;
}
-EDestination **
+EABDestination **
e_msg_composer_hdrs_get_to (EMsgComposerHdrs *hdrs)
{
char *str = NULL;
- EDestination **destv = NULL;
+ EABDestination **destv = NULL;
g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL);
bonobo_widget_get_property (BONOBO_WIDGET (hdrs->priv->to.entry), "destinations", TC_CORBA_string, &str, NULL);
if (str != NULL) {
- destv = e_destination_importv (str);
+ destv = eab_destination_importv (str);
g_free (str);
}
return destv;
}
-EDestination **
+EABDestination **
e_msg_composer_hdrs_get_cc (EMsgComposerHdrs *hdrs)
{
char *str = NULL;
- EDestination **destv = NULL;
+ EABDestination **destv = NULL;
g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL);
bonobo_widget_get_property (BONOBO_WIDGET (hdrs->priv->cc.entry), "destinations", TC_CORBA_string, &str, NULL);
if (str != NULL) {
- destv = e_destination_importv (str);
+ destv = eab_destination_importv (str);
g_free (str);
}
return destv;
}
-EDestination **
+EABDestination **
e_msg_composer_hdrs_get_bcc (EMsgComposerHdrs *hdrs)
{
char *str = NULL;
- EDestination **destv = NULL;
+ EABDestination **destv = NULL;
g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL);
bonobo_widget_get_property (BONOBO_WIDGET (hdrs->priv->bcc.entry), "destinations", TC_CORBA_string, &str, NULL);
if (str != NULL) {
- destv = e_destination_importv (str);
+ destv = eab_destination_importv (str);
g_free (str);
}
return destv;
}
-EDestination **
+EABDestination **
e_msg_composer_hdrs_get_recipients (EMsgComposerHdrs *hdrs)
{
- EDestination **to_destv;
- EDestination **cc_destv;
- EDestination **bcc_destv;
- EDestination **recip_destv;
+ EABDestination **to_destv;
+ EABDestination **cc_destv;
+ EABDestination **bcc_destv;
+ EABDestination **recip_destv;
int i, j, n;
g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL);
@@ -1237,7 +1236,7 @@ e_msg_composer_hdrs_get_recipients (EMsgComposerHdrs *hdrs)
if (n == 0)
return NULL;
- recip_destv = g_new (EDestination *, n + 1);
+ recip_destv = g_new (EABDestination *, n + 1);
j = 0;
diff --git a/composer/e-msg-composer-hdrs.h b/composer/e-msg-composer-hdrs.h
index eae32c6ef6..ff39062f19 100644
--- a/composer/e-msg-composer-hdrs.h
+++ b/composer/e-msg-composer-hdrs.h
@@ -31,7 +31,7 @@
#include <e-util/e-account.h>
#include <camel/camel-mime-message.h>
-#include <addressbook/backend/ebook/e-destination.h>
+#include <addressbook/util/eab-destination.h>
#ifdef __cplusplus
extern "C" {
@@ -110,11 +110,11 @@ void e_msg_composer_hdrs_set_from_account (EMsgComposerHdrs *hdrs,
void e_msg_composer_hdrs_set_reply_to (EMsgComposerHdrs *hdrs,
const char *reply_to);
void e_msg_composer_hdrs_set_to (EMsgComposerHdrs *hdrs,
- EDestination **to_destv);
+ EABDestination **to_destv);
void e_msg_composer_hdrs_set_cc (EMsgComposerHdrs *hdrs,
- EDestination **cc_destv);
+ EABDestination **cc_destv);
void e_msg_composer_hdrs_set_bcc (EMsgComposerHdrs *hdrs,
- EDestination **bcc_destv);
+ EABDestination **bcc_destv);
void e_msg_composer_hdrs_set_post_to (EMsgComposerHdrs *hdrs,
const char *post_to);
void e_msg_composer_hdrs_set_subject (EMsgComposerHdrs *hdrs,
@@ -123,10 +123,10 @@ void e_msg_composer_hdrs_set_subject (EMsgComposerHdrs *hdrs,
CamelInternetAddress *e_msg_composer_hdrs_get_from (EMsgComposerHdrs *hdrs);
CamelInternetAddress *e_msg_composer_hdrs_get_reply_to (EMsgComposerHdrs *hdrs);
-EDestination **e_msg_composer_hdrs_get_to (EMsgComposerHdrs *hdrs);
-EDestination **e_msg_composer_hdrs_get_cc (EMsgComposerHdrs *hdrs);
-EDestination **e_msg_composer_hdrs_get_bcc (EMsgComposerHdrs *hdrs);
-EDestination **e_msg_composer_hdrs_get_recipients (EMsgComposerHdrs *hdrs);
+EABDestination **e_msg_composer_hdrs_get_to (EMsgComposerHdrs *hdrs);
+EABDestination **e_msg_composer_hdrs_get_cc (EMsgComposerHdrs *hdrs);
+EABDestination **e_msg_composer_hdrs_get_bcc (EMsgComposerHdrs *hdrs);
+EABDestination **e_msg_composer_hdrs_get_recipients (EMsgComposerHdrs *hdrs);
char *e_msg_composer_hdrs_get_post_to (EMsgComposerHdrs *hdrs);
const char *e_msg_composer_hdrs_get_subject (EMsgComposerHdrs *hdrs);
diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c
index f446229889..d4b06cb2b7 100644
--- a/composer/e-msg-composer.c
+++ b/composer/e-msg-composer.c
@@ -2294,7 +2294,7 @@ enum {
static void
update_auto_recipients (EMsgComposerHdrs *hdrs, int mode, const char *auto_addrs)
{
- EDestination *dest, **destv = NULL;
+ EABDestination *dest, **destv = NULL;
CamelInternetAddress *iaddr;
GList *list, *tail, *node;
int i, n = 0;
@@ -2310,14 +2310,14 @@ update_auto_recipients (EMsgComposerHdrs *hdrs, int mode, const char *auto_addrs
if (!camel_internet_address_get (iaddr, i, &name, &addr))
continue;
- dest = e_destination_new ();
- e_destination_set_auto_recipient (dest, TRUE);
+ dest = eab_destination_new ();
+ eab_destination_set_auto_recipient (dest, TRUE);
if (name)
- e_destination_set_name (dest, name);
+ eab_destination_set_name (dest, name);
if (addr)
- e_destination_set_email (dest, addr);
+ eab_destination_set_email (dest, addr);
node = g_list_alloc ();
node->data = dest;
@@ -2352,9 +2352,9 @@ update_auto_recipients (EMsgComposerHdrs *hdrs, int mode, const char *auto_addrs
if (destv) {
for (i = 0; destv[i]; i++) {
- if (!e_destination_is_auto_recipient (destv[i])) {
+ if (!eab_destination_is_auto_recipient (destv[i])) {
node = g_list_alloc ();
- node->data = e_destination_copy (destv[i]);
+ node->data = eab_destination_copy (destv[i]);
node->next = NULL;
if (tail) {
@@ -2370,10 +2370,10 @@ update_auto_recipients (EMsgComposerHdrs *hdrs, int mode, const char *auto_addrs
}
}
- e_destination_freev (destv);
+ eab_destination_freev (destv);
}
- destv = e_destination_list_to_vector_sized (list, n);
+ destv = eab_destination_list_to_vector_sized (list, n);
g_list_free (list);
switch (mode) {
@@ -2387,7 +2387,7 @@ update_auto_recipients (EMsgComposerHdrs *hdrs, int mode, const char *auto_addrs
g_assert_not_reached ();
}
- e_destination_freev (destv);
+ eab_destination_freev (destv);
}
static void
@@ -3580,7 +3580,7 @@ e_msg_composer_new_with_message (CamelMimeMessage *message)
const CamelInternetAddress *to, *cc, *bcc;
GList *To = NULL, *Cc = NULL, *Bcc = NULL;
const char *format, *subject, *postto;
- EDestination **Tov, **Ccv, **Bccv;
+ EABDestination **Tov, **Ccv, **Bccv;
GHashTable *auto_cc, *auto_bcc;
CamelContentType *content_type;
struct _camel_header_raw *headers;
@@ -3657,13 +3657,13 @@ e_msg_composer_new_with_message (CamelMimeMessage *message)
const char *name, *addr;
if (camel_internet_address_get (to, i, &name, &addr)) {
- EDestination *dest = e_destination_new ();
- e_destination_set_name (dest, name);
- e_destination_set_email (dest, addr);
+ EABDestination *dest = eab_destination_new ();
+ eab_destination_set_name (dest, name);
+ eab_destination_set_email (dest, addr);
To = g_list_append (To, dest);
}
}
- Tov = e_destination_list_to_vector (To);
+ Tov = eab_destination_list_to_vector (To);
g_list_free (To);
len = CAMEL_ADDRESS (cc)->addresses->len;
@@ -3671,18 +3671,18 @@ e_msg_composer_new_with_message (CamelMimeMessage *message)
const char *name, *addr;
if (camel_internet_address_get (cc, i, &name, &addr)) {
- EDestination *dest = e_destination_new ();
- e_destination_set_name (dest, name);
- e_destination_set_email (dest, addr);
+ EABDestination *dest = eab_destination_new ();
+ eab_destination_set_name (dest, name);
+ eab_destination_set_email (dest, addr);
if (g_hash_table_lookup (auto_cc, addr))
- e_destination_set_auto_recipient (dest, TRUE);
+ eab_destination_set_auto_recipient (dest, TRUE);
Cc = g_list_append (Cc, dest);
}
}
- Ccv = e_destination_list_to_vector (Cc);
+ Ccv = eab_destination_list_to_vector (Cc);
g_hash_table_foreach (auto_cc, auto_recip_free, NULL);
g_hash_table_destroy (auto_cc);
g_list_free (Cc);
@@ -3692,18 +3692,18 @@ e_msg_composer_new_with_message (CamelMimeMessage *message)
const char *name, *addr;
if (camel_internet_address_get (bcc, i, &name, &addr)) {
- EDestination *dest = e_destination_new ();
- e_destination_set_name (dest, name);
- e_destination_set_email (dest, addr);
+ EABDestination *dest = eab_destination_new ();
+ eab_destination_set_name (dest, name);
+ eab_destination_set_email (dest, addr);
if (g_hash_table_lookup (auto_bcc, addr))
- e_destination_set_auto_recipient (dest, TRUE);
+ eab_destination_set_auto_recipient (dest, TRUE);
Bcc = g_list_append (Bcc, dest);
}
}
- Bccv = e_destination_list_to_vector (Bcc);
+ Bccv = eab_destination_list_to_vector (Bcc);
g_hash_table_foreach (auto_bcc, auto_recip_free, NULL);
g_hash_table_destroy (auto_bcc);
g_list_free (Bcc);
@@ -3719,9 +3719,9 @@ e_msg_composer_new_with_message (CamelMimeMessage *message)
g_free (account_name);
- e_destination_freev (Tov);
- e_destination_freev (Ccv);
- e_destination_freev (Bccv);
+ eab_destination_freev (Tov);
+ eab_destination_freev (Ccv);
+ eab_destination_freev (Bccv);
/* Restore the format editing preference */
format = camel_medium_get_header (CAMEL_MEDIUM (message), "X-Evolution-Format");
@@ -3843,9 +3843,9 @@ add_recipients (GList *list, const char *recips, gboolean decode)
for (i = 0; i < num; i++) {
if (camel_internet_address_get (cia, i, &name, &addr)) {
- EDestination *dest = e_destination_new ();
- e_destination_set_name (dest, name);
- e_destination_set_email (dest, addr);
+ EABDestination *dest = eab_destination_new ();
+ eab_destination_set_name (dest, name);
+ eab_destination_set_email (dest, addr);
list = g_list_append (list, dest);
}
@@ -3859,7 +3859,7 @@ handle_mailto (EMsgComposer *composer, const char *mailto)
{
EMsgComposerHdrs *hdrs;
GList *to = NULL, *cc = NULL, *bcc = NULL;
- EDestination **tov, **ccv, **bccv;
+ EABDestination **tov, **ccv, **bccv;
char *subject = NULL, *body = NULL;
char *header, *content, *buf;
size_t nread, nwritten;
@@ -3964,9 +3964,9 @@ handle_mailto (EMsgComposer *composer, const char *mailto)
g_free (buf);
- tov = e_destination_list_to_vector (to);
- ccv = e_destination_list_to_vector (cc);
- bccv = e_destination_list_to_vector (bcc);
+ tov = eab_destination_list_to_vector (to);
+ ccv = eab_destination_list_to_vector (cc);
+ bccv = eab_destination_list_to_vector (bcc);
g_list_free (to);
g_list_free (cc);
@@ -3978,9 +3978,9 @@ handle_mailto (EMsgComposer *composer, const char *mailto)
e_msg_composer_hdrs_set_cc (hdrs, ccv);
e_msg_composer_hdrs_set_bcc (hdrs, bccv);
- e_destination_freev (tov);
- e_destination_freev (ccv);
- e_destination_freev (bccv);
+ eab_destination_freev (tov);
+ eab_destination_freev (ccv);
+ eab_destination_freev (bccv);
if (subject) {
e_msg_composer_hdrs_set_subject (hdrs, subject);
@@ -4053,9 +4053,9 @@ e_msg_composer_show_attachments (EMsgComposer *composer,
void
e_msg_composer_set_headers (EMsgComposer *composer,
const char *from,
- EDestination **to,
- EDestination **cc,
- EDestination **bcc,
+ EABDestination **to,
+ EABDestination **cc,
+ EABDestination **bcc,
const char *subject)
{
EMsgComposerHdrs *hdrs;
@@ -4829,7 +4829,7 @@ e_msg_composer_set_view_bcc (EMsgComposer *composer, gboolean view_bcc)
}
-EDestination **
+EABDestination **
e_msg_composer_get_recipients (EMsgComposer *composer)
{
g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
@@ -4837,7 +4837,7 @@ e_msg_composer_get_recipients (EMsgComposer *composer)
return composer->hdrs ? e_msg_composer_hdrs_get_recipients (E_MSG_COMPOSER_HDRS (composer->hdrs)) : NULL;
}
-EDestination **
+EABDestination **
e_msg_composer_get_to (EMsgComposer *composer)
{
g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
@@ -4845,7 +4845,7 @@ e_msg_composer_get_to (EMsgComposer *composer)
return composer->hdrs ? e_msg_composer_hdrs_get_to (E_MSG_COMPOSER_HDRS (composer->hdrs)) : NULL;
}
-EDestination **
+EABDestination **
e_msg_composer_get_cc (EMsgComposer *composer)
{
g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
@@ -4853,7 +4853,7 @@ e_msg_composer_get_cc (EMsgComposer *composer)
return composer->hdrs ? e_msg_composer_hdrs_get_cc (E_MSG_COMPOSER_HDRS (composer->hdrs)) : NULL;
}
-EDestination **
+EABDestination **
e_msg_composer_get_bcc (EMsgComposer *composer)
{
g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
diff --git a/composer/e-msg-composer.h b/composer/e-msg-composer.h
index e28d8981d5..734b4c8760 100644
--- a/composer/e-msg-composer.h
+++ b/composer/e-msg-composer.h
@@ -134,9 +134,9 @@ void e_msg_composer_show_attachments (EMsgCo
gboolean show);
void e_msg_composer_set_headers (EMsgComposer *composer,
const char *from,
- EDestination **to,
- EDestination **cc,
- EDestination **bcc,
+ EABDestination **to,
+ EABDestination **cc,
+ EABDestination **bcc,
const char *subject);
void e_msg_composer_set_body_text (EMsgComposer *composer,
const char *text);
@@ -173,10 +173,10 @@ gboolean e_msg_composer_get_view_bcc (EMsgCo
void e_msg_composer_set_view_bcc (EMsgComposer *composer,
gboolean view_bcc);
-EDestination **e_msg_composer_get_recipients (EMsgComposer *composer);
-EDestination **e_msg_composer_get_to (EMsgComposer *composer);
-EDestination **e_msg_composer_get_cc (EMsgComposer *composer);
-EDestination **e_msg_composer_get_bcc (EMsgComposer *composer);
+EABDestination **e_msg_composer_get_recipients (EMsgComposer *composer);
+EABDestination **e_msg_composer_get_to (EMsgComposer *composer);
+EABDestination **e_msg_composer_get_cc (EMsgComposer *composer);
+EABDestination **e_msg_composer_get_bcc (EMsgComposer *composer);
const char *e_msg_composer_get_subject (EMsgComposer *composer);
EAccount *e_msg_composer_get_preferred_account (EMsgComposer *composer);
diff --git a/composer/evolution-composer.c b/composer/evolution-composer.c
index b5c7630de8..31da13c342 100644
--- a/composer/evolution-composer.c
+++ b/composer/evolution-composer.c
@@ -47,26 +47,26 @@ struct _EvolutionComposerPrivate {
};
/* CORBA interface implementation. */
-static EDestination **
+static EABDestination **
corba_recipientlist_to_destv (const GNOME_Evolution_Composer_RecipientList *cl)
{
GNOME_Evolution_Composer_Recipient *recip;
- EDestination **destv;
+ EABDestination **destv;
int i;
if (cl->_length == 0)
return NULL;
- destv = g_new (EDestination *, cl->_length+1);
+ destv = g_new (EABDestination *, cl->_length+1);
for (i = 0; i < cl->_length; ++i) {
recip = &(cl->_buffer[i]);
- destv[i] = e_destination_new ();
+ destv[i] = eab_destination_new ();
if (*recip->name)
- e_destination_set_name (destv[i], recip->name);
- e_destination_set_email (destv[i], recip->address);
+ eab_destination_set_name (destv[i], recip->name);
+ eab_destination_set_email (destv[i], recip->address);
}
destv[cl->_length] = NULL;
@@ -85,7 +85,7 @@ impl_Composer_set_headers (PortableServer_Servant servant,
{
BonoboObject *bonobo_object;
EvolutionComposer *composer;
- EDestination **tov, **ccv, **bccv;
+ EABDestination **tov, **ccv, **bccv;
EAccountList *accounts;
EAccount *account;
EIterator *iter;
@@ -122,9 +122,9 @@ impl_Composer_set_headers (PortableServer_Servant servant,
e_msg_composer_set_headers (composer->composer, account->name,
tov, ccv, bccv, subject);
- e_destination_freev (tov);
- e_destination_freev (ccv);
- e_destination_freev (bccv);
+ eab_destination_freev (tov);
+ eab_destination_freev (ccv);
+ eab_destination_freev (bccv);
}
static void
diff --git a/data/evolution.desktop.in b/data/evolution.desktop.in
index 2fc62f6993..d8fada2802 100644
--- a/data/evolution.desktop.in
+++ b/data/evolution.desktop.in
@@ -1,8 +1,8 @@
[Desktop Entry]
_Name=Ximian Evolution
_Comment=The Evolution groupware suite
-Exec=evolution-1.4
-Icon=evolution-1.4.png
+Exec=evolution-1.5
+Icon=evolution-1.5.png
Terminal=false
Type=Application
Categories=GNOME;Application;Office;X-Red-Hat-Base;
diff --git a/e-util/.cvsignore b/e-util/.cvsignore
index ea3b8c5ad4..cfb049f0e3 100644
--- a/e-util/.cvsignore
+++ b/e-util/.cvsignore
@@ -6,3 +6,4 @@ Makefile.in
*.la
e-util-marshal.c
e-util-marshal.h
+test-source-list \ No newline at end of file
diff --git a/e-util/ChangeLog b/e-util/ChangeLog
index fb28623bee..b6bdedd004 100644
--- a/e-util/ChangeLog
+++ b/e-util/ChangeLog
@@ -3,6 +3,21 @@
* Makefile.am (pilot_compile) [! ENABLE_PILOT_CONDUITS]: Add
md5-utils.c so it compiles even if you have no Pilot support.
+2003-10-16 Rodrigo Moya <rodrigo@ximian.com>
+
+ * e-source-list.c (e_source_list_sync): use gconf_client_notify_remove
+ instead of g_source_remove for GConf notification IDs.
+ (impl_finalize): remove the GConf notification also here.
+
+2003-10-13 Rodrigo Moya <rodrigo@ximian.com>
+
+ * e-source-group.[ch] (e_source_group_peek_source_by_name): added
+ new function.
+
+2003-10-10 Not Zed <NotZed@Ximian.com>
+
+ * e-account-list.c (e_account_list_find): add FIND_UID find type.
+
2003-09-26 Jeffrey Stedfast <fejj@ximian.com>
* e-host-utils.c (e_gethostbyaddr_r): IPv6 implementation
@@ -21,6 +36,11 @@
* e-host-utils.c (e_gethostbyaddr_r): Work around a bug in glibc
2.3.2's gethostbyaddr_r() implementation.
+2003-09-15 Larry Ewing <lewing@ximian.com>
+
+ * e-source.c (e_source_dump_to_xml_node): make sure declarations
+ precede the body.
+
2003-09-11 Dan Winship <danw@ximian.com>
* Makefile.am (noinst_LTLIBRARIES): Remove libeutil-static.la and
@@ -47,6 +67,129 @@
Editor always gives time validation error for apptmnts in non
UTF-8/non ASCII locales.
+2003-08-17 Ettore Perazzoli <ettore@ximian.com>
+
+ * test-source-list.c: No short letter for --key.
+
+2003-08-15 Ettore Perazzoli <ettore@ximian.com>
+
+ * e-uid.c: #include <glib/gstrfuncs.h>
+
+ * test-source-list.c: Add options to display, set and unset the
+ color as well.
+
+ * e-source.c: New members has_color, color in struct
+ ESourcePrivate.
+ (e_source_update_from_xml_node): Parse a color property from the
+ XML node. Protect from NULL name and relative_uri members as
+ well.
+ (e_source_dump_to_xml_node): Set a color property on the XML node.
+ (e_source_get_color): New.
+ (e_source_set_color): New.
+ (e_source_unset_color): New.
+ (e_source_new_from_xml_node): Use e_source_update_from_xml_node()
+ instead of getting the data from the XML yourself.
+
+2003-08-14 Ettore Perazzoli <ettore@ximian.com>
+
+ Add UIDs to ESource* items so we can distinguish renames from
+ removals/additions.
+
+ * test-source-list.c: Made --source and --group get UIDs instead
+ of names.
+ (on_idle_do_stuff): Updated behavior accordingly.
+ (dump_list): Print "(No items)" if there are no groups.
+ (dump_group): Print the UID of the group.
+ (dump_source): Print the UID of the source.
+
+ * e-source-list.c (load_from_gconf): Match with group UIDs instead
+ of group names.
+ (e_source_list_peek_source_by_uid): New.
+ (e_source_list_peek_source_by_name): Removed.
+ (e_source_list_peek_group_by_uid): New.
+ (e_source_list_peek_group_by_name): Removed.
+ (e_source_list_remove_group_by_uid): New.
+ (e_source_list_remove_group_by_name): Removed.
+ (e_source_list_remove_source_by_uid): New.
+ (e_source_list_remove_source_by_name): Removed.
+
+ * e-source-group.c: New member uid in struct ESourceGroupPrivate.
+ (impl_finalize): Free it.
+ (e_source_group_new): Set the uid member using e_uid_new().
+ (e_source_group_peek_source_by_uid): New.
+ (e_source_group_peek_source_by_name): Removed.
+ (e_source_group_add_source): Check that the UID is unique, instead
+ of the name.
+ (e_source_group_remove_source_by_uid): New.
+ (e_source_group_remove_source_by_name): Removed.
+ (e_source_group_update_from_xmldoc): Use the UID to figure out
+ which source has changed, instead of the name.
+ (e_source_group_uid_from_xmldoc): New.
+ (e_source_group_name_from_xmldoc): Removed.
+ (e_source_group_new_from_xmldoc): Set the UID in the new group
+ from the XML.
+ (e_source_group_to_xml): Set a UID property in the XML.
+
+ * e-source.c: New member uid in struct ESourcePrivate.
+ (e_source_new): Initialize using e_uid_new().
+ (impl_finalize): Free.
+ (e_source_peek_uid): New.
+ (e_source_new_from_xml_node): Set the UID from the XML node.
+ (e_source_name_from_xml_node): Removed.
+ (e_source_uid_from_xml_node): New.
+ (e_source_dump_to_xml_node): Set the "uid" property on the XML
+ node.
+
+ * e-account.c (e_account_gen_uid): Removed.
+ (e_account_new): Use e_uid_new() instead of e_account_gen_uid().
+
+ * e-uid.c (e_uid_new): New file, new function.
+
+2003-08-13 Ettore Perazzoli <ettore@ximian.com>
+
+ Fix up the semantics of "changed" signals on GConf changes.
+
+ * e-source-group.c (e_source_group_update_from_xmldoc): Added new
+ member ignore_source_changed in struct _ESourceGroupPrivate.
+ (e_source_group_update_from_xmldoc): Increment
+ ignore_source_changed before calling
+ e_source_update_from_xml_node(), decrement afterwards.
+ (source_changed_callback): Only emit "changed" if
+ ignore_source_changed is zero.
+ (e_source_group_update_from_xmldoc): Properly emit the "changed"
+ signal when the base_uri or the name change.
+
+ * e-source-list.c: Changed type of sync_idle_id from gboolean (!)
+ to int and added new member ignore_group_changed in struct
+ _ESourceListPrivate.
+ (load_from_gconf): Increment ignore_group_changed before calling
+ e_source_group_update_from_xmldoc() and decrement it afterwards.
+ (group_changed_callback): Only emit the signal if
+ ignore_group_changed is zero.
+
+ * e-source.c (e_source_update_from_xml_node): Removed arg
+ emit_signals. Always emit signals.
+
+ * e-source-group.c (e_source_group_update_from_xmldoc): Removed
+ arg emit_signals. Always emit signals.
+ (e_source_group_update_from_xml): Likewise.
+
+2003-08-11 Ettore Perazzoli <ettore@ximian.com>
+
+ * e-source.c (e_source_set_group): Weak_unref the current group if
+ not NULL and properly handle the case where a NULL group is being
+ passed in.
+
+2003-08-11 Ettore Perazzoli <ettore@ximian.com>
+
+ * e-source-group.c: New file.
+ * e-source-group.h: New file.
+ * e-source-list.h: New file.
+ * e-source-list.c: New file.
+ * e-source.c: New file.
+ * e-source.h: New file.
+ * test-source-list.c: New file to test the above.
+
2003-08-11 Not Zed <NotZed@Ximian.com>
* e-msgport.c (e_thread_put): check pthread_create return code
diff --git a/e-util/Makefile.am b/e-util/Makefile.am
index 2a134e14ed..f80e321f0e 100644
--- a/e-util/Makefile.am
+++ b/e-util/Makefile.am
@@ -44,8 +44,12 @@ eutilinclude_HEADERS = \
e-proxy.h \
e-request.h \
e-sexp.h \
+ e-source-group.h \
+ e-source-list.h \
+ e-source.h \
e-time-utils.h \
e-trie.h \
+ e-uid.h \
e-url.h \
e-xml-hash-utils.h \
md5-utils.h
@@ -78,8 +82,12 @@ libeutil_la_SOURCES = \
e-proxy.c \
e-request.c \
e-sexp.c \
+ e-source-group.c \
+ e-source-list.c \
+ e-source.c \
e-time-utils.c \
e-trie.c \
+ e-uid.c \
e-url.c \
e-util-marshal.c \
e-xml-hash-utils.c \
@@ -87,6 +95,12 @@ libeutil_la_SOURCES = \
eggtrayicon.h \
md5-utils.c
+noinst_PROGRAMS = \
+ test-source-list
+
+test_source_list_SOURCES = test-source-list.c
+test_source_list_LDADD = libeutil.la
+
MARSHAL_GENERATED = e-util-marshal.c e-util-marshal.h
@EVO_MARSHAL_RULE@
diff --git a/e-util/e-account-list.c b/e-util/e-account-list.c
index acb9093cb4..d0463a810b 100644
--- a/e-util/e-account-list.c
+++ b/e-util/e-account-list.c
@@ -447,6 +447,9 @@ e_account_list_find(EAccountList *accounts, e_account_find_t type, const char *k
case E_ACCOUNT_FIND_NAME:
found = strcmp(account->name, key) == 0;
break;
+ case E_ACCOUNT_FIND_UID:
+ found = strcmp(account->uid, key) == 0;
+ break;
case E_ACCOUNT_FIND_ID_NAME:
if (account->id)
found = strcmp(account->id->name, key) == 0;
diff --git a/e-util/e-account-list.h b/e-util/e-account-list.h
index 2ad0896307..b47efb42ae 100644
--- a/e-util/e-account-list.h
+++ b/e-util/e-account-list.h
@@ -35,6 +35,7 @@ typedef struct EAccountListPrivate EAccountListPrivate;
/* search options for the find command */
typedef enum _e_account_find_t {
E_ACCOUNT_FIND_NAME,
+ E_ACCOUNT_FIND_UID,
E_ACCOUNT_FIND_ID_NAME,
E_ACCOUNT_FIND_ID_ADDRESS,
} e_account_find_t;
diff --git a/e-util/e-account.c b/e-util/e-account.c
index 510200b723..b6e3cdc57f 100644
--- a/e-util/e-account.c
+++ b/e-util/e-account.c
@@ -23,9 +23,9 @@
#include "e-account.h"
+#include "e-uid.h"
+
#include <string.h>
-#include <time.h>
-#include <unistd.h>
#include <gal/util/e-util.h>
#include <libxml/parser.h>
@@ -106,29 +106,6 @@ finalize (GObject *object)
E_MAKE_TYPE (e_account, "EAccount", EAccount, class_init, init, PARENT_TYPE)
-char *
-e_account_gen_uid (void)
-{
- static char *hostname;
- static int serial;
-
- if (!hostname) {
- static char buffer [512];
-
- if ((gethostname (buffer, sizeof (buffer) - 1) == 0) &&
- (buffer [0] != 0))
- hostname = buffer;
- else
- hostname = "localhost";
- }
-
- return g_strdup_printf ("%lu.%lu.%d@%s",
- (unsigned long) time (NULL),
- (unsigned long) getpid (),
- serial++,
- hostname);
-}
-
/**
* e_account_new:
*
@@ -141,7 +118,7 @@ e_account_new (void)
EAccount *account;
account = g_object_new (E_TYPE_ACCOUNT, NULL);
- account->uid = e_account_gen_uid ();
+ account->uid = e_uid_new ();
return account;
}
diff --git a/e-util/e-account.h b/e-util/e-account.h
index 78eb70b7a8..ff937b3905 100644
--- a/e-util/e-account.h
+++ b/e-util/e-account.h
@@ -100,6 +100,5 @@ char *e_account_to_xml (EAccount *account);
char *e_account_uid_from_xml (const char *xml);
-char *e_account_gen_uid (void);
#endif /* __E_ACCOUNT__ */
diff --git a/e-util/e-source-group.c b/e-util/e-source-group.c
new file mode 100644
index 0000000000..5fb5a97b23
--- /dev/null
+++ b/e-util/e-source-group.c
@@ -0,0 +1,605 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-source-group.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: Ettore Perazzoli <ettore@ximian.com>
+ */
+
+#include <config.h>
+
+#include "e-source-group.h"
+
+#include "e-uid.h"
+#include "e-util-marshal.h"
+
+#include <gal/util/e-util.h>
+
+#include <string.h>
+
+#define PARENT_TYPE G_TYPE_OBJECT
+static GObjectClass *parent_class = NULL;
+
+
+/* Private members. */
+
+struct _ESourceGroupPrivate {
+ char *uid;
+ char *name;
+ char *base_uri;
+
+ GSList *sources;
+
+ gboolean ignore_source_changed;
+};
+
+
+/* Signals. */
+
+enum {
+ CHANGED,
+ SOURCE_REMOVED,
+ SOURCE_ADDED,
+ LAST_SIGNAL
+};
+static unsigned int signals[LAST_SIGNAL] = { 0 };
+
+
+/* Callbacks. */
+
+static void
+source_changed_callback (ESource *source,
+ ESourceGroup *group)
+{
+ if (! group->priv->ignore_source_changed)
+ g_signal_emit (group, signals[CHANGED], 0);
+}
+
+
+/* GObject methods. */
+
+static void
+impl_dispose (GObject *object)
+{
+ ESourceGroupPrivate *priv = E_SOURCE_GROUP (object)->priv;
+
+ if (priv->sources != NULL) {
+ GSList *p;
+
+ for (p = priv->sources; p != NULL; p = p->next) {
+ ESource *source = E_SOURCE (p->data);
+
+ g_signal_handlers_disconnect_by_func (source,
+ G_CALLBACK (source_changed_callback),
+ object);
+ g_object_unref (source);
+ }
+
+ g_slist_free (priv->sources);
+ priv->sources = NULL;
+ }
+
+ (* G_OBJECT_CLASS (parent_class)->dispose) (object);
+}
+
+static void
+impl_finalize (GObject *object)
+{
+ ESourceGroupPrivate *priv = E_SOURCE_GROUP (object)->priv;
+
+ g_free (priv->uid);
+ g_free (priv->name);
+ g_free (priv->base_uri);
+ g_free (priv);
+
+ (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+}
+
+
+/* Initialization. */
+
+static void
+class_init (ESourceGroupClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->dispose = impl_dispose;
+ object_class->finalize = impl_finalize;
+
+ parent_class = g_type_class_peek_parent (class);
+
+ signals[CHANGED] =
+ g_signal_new ("changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ESourceGroupClass, changed),
+ NULL, NULL,
+ e_util_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[SOURCE_ADDED] =
+ g_signal_new ("source_added",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ESourceGroupClass, source_added),
+ NULL, NULL,
+ e_util_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ G_TYPE_OBJECT);
+ signals[SOURCE_REMOVED] =
+ g_signal_new ("source_removed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ESourceGroupClass, source_removed),
+ NULL, NULL,
+ e_util_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ G_TYPE_OBJECT);
+}
+
+static void
+init (ESourceGroup *source_group)
+{
+ ESourceGroupPrivate *priv;
+
+ priv = g_new0 (ESourceGroupPrivate, 1);
+ source_group->priv = priv;
+}
+
+
+/* Public methods. */
+
+ESourceGroup *
+e_source_group_new (const char *name,
+ const char *base_uri)
+{
+ ESourceGroup *new;
+
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (base_uri != NULL, NULL);
+
+ new = g_object_new (e_source_group_get_type (), NULL);
+ new->priv->uid = e_uid_new ();
+
+ e_source_group_set_name (new, name);
+ e_source_group_set_base_uri (new, base_uri);
+
+ return new;
+}
+
+ESourceGroup *
+e_source_group_new_from_xml (const char *xml)
+{
+ xmlDocPtr doc;
+ ESourceGroup *group;
+
+ doc = xmlParseDoc ((char *) xml);
+ if (doc == NULL)
+ return NULL;
+
+ group = e_source_group_new_from_xmldoc (doc);
+ xmlFreeDoc (doc);
+
+ return group;
+}
+
+ESourceGroup *
+e_source_group_new_from_xmldoc (xmlDocPtr doc)
+{
+ xmlNodePtr root, p;
+ xmlChar *uid;
+ xmlChar *name;
+ xmlChar *base_uri;
+ ESourceGroup *new = NULL;
+
+ g_return_val_if_fail (doc != NULL, NULL);
+
+ root = doc->children;
+ if (strcmp (root->name, "group") != 0)
+ return NULL;
+
+ uid = xmlGetProp (root, "uid");
+ name = xmlGetProp (root, "name");
+ base_uri = xmlGetProp (root, "base_uri");
+
+ if (uid == NULL || name == NULL || base_uri == NULL)
+ goto done;
+
+ new = g_object_new (e_source_group_get_type (), NULL);
+ new->priv->uid = g_strdup (uid);
+
+ e_source_group_set_name (new, name);
+ e_source_group_set_base_uri (new, base_uri);
+
+ for (p = root->children; p != NULL; p = p->next) {
+ ESource *new_source = e_source_new_from_xml_node (p);
+ e_source_group_add_source (new, new_source, -1);
+ }
+
+ done:
+ if (name != NULL)
+ xmlFree (name);
+ if (base_uri != NULL)
+ xmlFree (base_uri);
+ return new;
+}
+
+gboolean
+e_source_group_update_from_xml (ESourceGroup *group,
+ const char *xml,
+ gboolean *changed_return)
+{
+ xmlDocPtr xmldoc;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_SOURCE_GROUP (group), FALSE);
+ g_return_val_if_fail (xml != NULL, FALSE);
+
+ xmldoc = xmlParseDoc ((char *) xml);
+
+ success = e_source_group_update_from_xmldoc (group, xmldoc, changed_return);
+
+ xmlFreeDoc (xmldoc);
+
+ return success;
+}
+
+gboolean
+e_source_group_update_from_xmldoc (ESourceGroup *group,
+ xmlDocPtr doc,
+ gboolean *changed_return)
+{
+ GHashTable *new_sources_hash;
+ GSList *new_sources_list = NULL;
+ xmlNodePtr root, nodep;
+ xmlChar *name, *base_uri;
+ gboolean changed = FALSE;
+ GSList *p, *q;
+
+ g_return_val_if_fail (E_IS_SOURCE_GROUP (group), FALSE);
+ g_return_val_if_fail (doc != NULL, FALSE);
+
+ *changed_return = FALSE;
+
+ root = doc->children;
+ if (strcmp (root->name, "group") != 0)
+ return FALSE;
+
+ name = xmlGetProp (root, "name");
+ if (name == NULL)
+ return FALSE;
+
+ base_uri = xmlGetProp (root, "base_uri");
+ if (base_uri == NULL) {
+ xmlFree (name);
+ return FALSE;
+ }
+
+ if (strcmp (group->priv->name, name) != 0) {
+ g_free (group->priv->name);
+ group->priv->name = g_strdup (name);
+ changed = TRUE;
+ }
+ xmlFree (name);
+
+ if (strcmp (group->priv->base_uri, base_uri) != 0) {
+ g_free (group->priv->base_uri);
+ group->priv->base_uri = g_strdup (base_uri);
+ changed = TRUE;
+ }
+ xmlFree (base_uri);
+
+ new_sources_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ for (nodep = root->children; nodep != NULL; nodep = nodep->next) {
+ ESource *existing_source;
+ char *uid = e_source_uid_from_xml_node (nodep);
+
+ if (uid == NULL)
+ continue;
+
+ existing_source = e_source_group_peek_source_by_uid (group, uid);
+ if (g_hash_table_lookup (new_sources_hash, existing_source) != NULL)
+ continue;
+
+ if (existing_source == NULL) {
+ ESource *new_source = e_source_new_from_xml_node (nodep);
+
+ if (new_source != NULL) {
+ e_source_set_group (new_source, group);
+ g_signal_connect (new_source, "changed", G_CALLBACK (source_changed_callback), group);
+ new_sources_list = g_slist_prepend (new_sources_list, new_source);
+
+ g_hash_table_insert (new_sources_hash, new_source, new_source);
+
+ g_signal_emit (group, signals[SOURCE_ADDED], 0, new_source);
+ changed = TRUE;
+ }
+ } else {
+ gboolean source_changed;
+
+ group->priv->ignore_source_changed ++;
+
+ if (e_source_update_from_xml_node (existing_source, nodep, &source_changed)) {
+ new_sources_list = g_slist_prepend (new_sources_list, existing_source);
+ g_object_ref (existing_source);
+ g_hash_table_insert (new_sources_hash, existing_source, existing_source);
+
+ if (source_changed)
+ changed = TRUE;
+ }
+
+ group->priv->ignore_source_changed --;
+ }
+
+ g_free (uid);
+ }
+
+ new_sources_list = g_slist_reverse (new_sources_list);
+
+ /* Emit "group_removed" and disconnect the "changed" signal for all the
+ groups that we haven't found in the new list. */
+ q = new_sources_list;
+ for (p = group->priv->sources; p != NULL; p = p->next) {
+ ESource *source = E_SOURCE (p->data);
+
+ if (g_hash_table_lookup (new_sources_hash, source) == NULL) {
+ changed = TRUE;
+
+ g_signal_emit (group, signals[SOURCE_REMOVED], 0, source);
+ g_signal_handlers_disconnect_by_func (source, source_changed_callback, group);
+ }
+
+ if (! changed && q != NULL) {
+ if (q->data != p->data)
+ changed = TRUE;
+ q = q->next;
+ }
+ }
+
+ g_hash_table_destroy (new_sources_hash);
+
+ /* Replace the original group list with the new one. */
+ g_slist_foreach (group->priv->sources, (GFunc) g_object_unref, NULL);
+ g_slist_free (group->priv->sources);
+
+ group->priv->sources = new_sources_list;
+
+ /* FIXME if the order changes, the function doesn't notice. */
+
+ if (changed) {
+ g_signal_emit (group, signals[CHANGED], 0);
+ *changed_return = TRUE;
+ }
+
+ return TRUE; /* Success. */
+}
+
+char *
+e_source_group_uid_from_xmldoc (xmlDocPtr doc)
+{
+ xmlNodePtr root = doc->children;
+ xmlChar *name;
+ char *retval;
+
+ if (strcmp (root->name, "group") != 0)
+ return NULL;
+
+ name = xmlGetProp (root, "uid");
+ if (name == NULL)
+ return NULL;
+
+ retval = g_strdup (name);
+ xmlFree (name);
+ return retval;
+}
+
+void
+e_source_group_set_name (ESourceGroup *group,
+ const char *name)
+{
+ g_return_if_fail (E_IS_SOURCE_GROUP (group));
+ g_return_if_fail (name != NULL);
+
+ if (group->priv->name == name)
+ return;
+
+ g_free (group->priv->name);
+ group->priv->name = g_strdup (name);
+
+ g_signal_emit (group, signals[CHANGED], 0);
+}
+
+void e_source_group_set_base_uri (ESourceGroup *group,
+ const char *base_uri)
+{
+ g_return_if_fail (E_IS_SOURCE_GROUP (group));
+ g_return_if_fail (base_uri != NULL);
+
+ if (group->priv->base_uri == base_uri)
+ return;
+
+ g_free (group->priv->base_uri);
+ group->priv->base_uri = g_strdup (base_uri);
+
+ g_signal_emit (group, signals[CHANGED], 0);
+}
+
+
+const char *
+e_source_group_peek_uid (ESourceGroup *group)
+{
+ g_return_val_if_fail (E_IS_SOURCE_GROUP (group), NULL);
+
+ return group->priv->uid;
+}
+
+const char *
+e_source_group_peek_name (ESourceGroup *group)
+{
+ g_return_val_if_fail (E_IS_SOURCE_GROUP (group), NULL);
+
+ return group->priv->name;
+}
+
+const char *
+e_source_group_peek_base_uri (ESourceGroup *group)
+{
+ g_return_val_if_fail (E_IS_SOURCE_GROUP (group), NULL);
+
+ return group->priv->base_uri;
+}
+
+
+GSList *
+e_source_group_peek_sources (ESourceGroup *group)
+{
+ g_return_val_if_fail (E_IS_SOURCE_GROUP (group), NULL);
+
+ return group->priv->sources;
+}
+
+ESource *
+e_source_group_peek_source_by_uid (ESourceGroup *group,
+ const char *uid)
+{
+ GSList *p;
+
+ for (p = group->priv->sources; p != NULL; p = p->next) {
+ if (strcmp (e_source_peek_uid (E_SOURCE (p->data)), uid) == 0)
+ return E_SOURCE (p->data);
+ }
+
+ return NULL;
+}
+
+ESource *
+e_source_group_peek_source_by_name (ESourceGroup *group,
+ const char *name)
+{
+ GSList *p;
+
+ for (p = group->priv->sources; p != NULL; p = p->next) {
+ if (strcmp (e_source_peek_name (E_SOURCE (p->data)), name) == 0)
+ return E_SOURCE (p->data);
+ }
+
+ return NULL;
+}
+
+gboolean
+e_source_group_add_source (ESourceGroup *group,
+ ESource *source,
+ int position)
+{
+ g_return_val_if_fail (E_IS_SOURCE_GROUP (group), FALSE);
+
+ if (e_source_group_peek_source_by_uid (group, e_source_peek_uid (source)) != NULL)
+ return FALSE;
+
+ e_source_set_group (source, group);
+ g_object_ref (source);
+
+ g_signal_connect (source, "changed", G_CALLBACK (source_changed_callback), group);
+
+ group->priv->sources = g_slist_insert (group->priv->sources, source, position);
+ g_signal_emit (group, signals[SOURCE_ADDED], 0, source);
+ g_signal_emit (group, signals[CHANGED], 0);
+
+ return TRUE;
+}
+
+gboolean
+e_source_group_remove_source (ESourceGroup *group,
+ ESource *source)
+{
+ GSList *p;
+
+ g_return_val_if_fail (E_IS_SOURCE_GROUP (group), FALSE);
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+
+ for (p = group->priv->sources; p != NULL; p = p->next) {
+ if (E_SOURCE (p->data) == source) {
+ group->priv->sources = g_slist_remove_link (group->priv->sources, p);
+ g_signal_emit (group, signals[SOURCE_REMOVED], 0, source);
+ g_signal_emit (group, signals[CHANGED], 0);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+gboolean
+e_source_group_remove_source_by_uid (ESourceGroup *group,
+ const char *uid)
+{
+ GSList *p;
+
+ g_return_val_if_fail (E_IS_SOURCE_GROUP (group), FALSE);
+ g_return_val_if_fail (uid != NULL, FALSE);
+
+ for (p = group->priv->sources; p != NULL; p = p->next) {
+ ESource *source = E_SOURCE (p->data);
+
+ if (strcmp (e_source_peek_uid (source), uid) == 0) {
+ group->priv->sources = g_slist_remove_link (group->priv->sources, p);
+ g_signal_emit (group, signals[SOURCE_REMOVED], 0, source);
+ g_signal_emit (group, signals[CHANGED], 0);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+char *
+e_source_group_to_xml (ESourceGroup *group)
+{
+ xmlDocPtr doc;
+ xmlNodePtr root;
+ xmlChar *xml_buffer;
+ char *returned_buffer;
+ int xml_buffer_size;
+ GSList *p;
+
+ doc = xmlNewDoc ("1.0");
+
+ root = xmlNewDocNode (doc, NULL, "group", NULL);
+ xmlSetProp (root, "uid", e_source_group_peek_uid (group));
+ xmlSetProp (root, "name", e_source_group_peek_name (group));
+ xmlSetProp (root, "base_uri", e_source_group_peek_base_uri (group));
+
+ xmlDocSetRootElement (doc, root);
+
+ for (p = group->priv->sources; p != NULL; p = p->next)
+ e_source_dump_to_xml_node (E_SOURCE (p->data), root);
+
+ xmlDocDumpMemory (doc, &xml_buffer, &xml_buffer_size);
+ xmlFreeDoc (doc);
+
+ returned_buffer = g_malloc (xml_buffer_size + 1);
+ memcpy (returned_buffer, xml_buffer, xml_buffer_size);
+ returned_buffer [xml_buffer_size] = '\0';
+ xmlFree (xml_buffer);
+
+ return returned_buffer;
+}
+
+
+E_MAKE_TYPE (e_source_group, "ESourceGroup", ESourceGroup, class_init, init, PARENT_TYPE)
diff --git a/e-util/e-source-group.h b/e-util/e-source-group.h
new file mode 100644
index 0000000000..bebecba58f
--- /dev/null
+++ b/e-util/e-source-group.h
@@ -0,0 +1,102 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-source-group.h
+ *
+ * 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: Ettore Perazzoli <ettore@ximian.com>
+ */
+
+#ifndef _E_SOURCE_GROUP_H_
+#define _E_SOURCE_GROUP_H_
+
+#include <glib-object.h>
+#include <libxml/tree.h>
+
+#define E_TYPE_SOURCE_GROUP (e_source_group_get_type ())
+#define E_SOURCE_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_SOURCE_GROUP, ESourceGroup))
+#define E_SOURCE_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_SOURCE_GROUP, ESourceGroupClass))
+#define E_IS_SOURCE_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_SOURCE_GROUP))
+#define E_IS_SOURCE_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_SOURCE_GROUP))
+
+
+typedef struct _ESourceGroup ESourceGroup;
+typedef struct _ESourceGroupPrivate ESourceGroupPrivate;
+typedef struct _ESourceGroupClass ESourceGroupClass;
+
+#include "e-source.h"
+
+struct _ESourceGroup {
+ GObject parent;
+
+ ESourceGroupPrivate *priv;
+};
+
+struct _ESourceGroupClass {
+ GObjectClass parent_class;
+
+ /* Signals. */
+
+ void (* changed) (ESourceGroup *group);
+
+ void (* source_removed) (ESourceGroup *source_list, ESource *source);
+ void (* source_added) (ESourceGroup *source_list, ESource *source);
+};
+
+
+GType e_source_group_get_type (void);
+
+ESourceGroup *e_source_group_new (const char *name,
+ const char *base_uri);
+ESourceGroup *e_source_group_new_from_xml (const char *xml);
+ESourceGroup *e_source_group_new_from_xmldoc (xmlDocPtr doc);
+
+gboolean e_source_group_update_from_xml (ESourceGroup *group,
+ const char *xml,
+ gboolean *changed_return);
+gboolean e_source_group_update_from_xmldoc (ESourceGroup *group,
+ xmlDocPtr doc,
+ gboolean *changed_return);
+
+char *e_source_group_uid_from_xmldoc (xmlDocPtr doc);
+
+void e_source_group_set_name (ESourceGroup *group,
+ const char *name);
+void e_source_group_set_base_uri (ESourceGroup *group,
+ const char *base_uri);
+
+const char *e_source_group_peek_uid (ESourceGroup *group);
+const char *e_source_group_peek_name (ESourceGroup *group);
+const char *e_source_group_peek_base_uri (ESourceGroup *group);
+
+GSList *e_source_group_peek_sources (ESourceGroup *group);
+ESource *e_source_group_peek_source_by_uid (ESourceGroup *group,
+ const char *source_uid);
+ESource *e_source_group_peek_source_by_name (ESourceGroup *group,
+ const char *source_name);
+
+gboolean e_source_group_add_source (ESourceGroup *group,
+ ESource *source,
+ int position);
+gboolean e_source_group_remove_source (ESourceGroup *group,
+ ESource *source);
+gboolean e_source_group_remove_source_by_uid (ESourceGroup *group,
+ const char *uid);
+
+char *e_source_group_to_xml (ESourceGroup *group);
+
+
+#endif /* _E_SOURCE_GROUP_H_ */
diff --git a/e-util/e-source-list.c b/e-util/e-source-list.c
new file mode 100644
index 0000000000..565df8977e
--- /dev/null
+++ b/e-util/e-source-list.c
@@ -0,0 +1,524 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-source-list.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: Ettore Perazzoli <ettore@ximian.com>
+ */
+
+#include <config.h>
+
+#include "e-source-list.h"
+
+#include "e-util-marshal.h"
+
+#include <string.h>
+#include <gal/util/e-util.h>
+
+
+#define PARENT_TYPE G_TYPE_OBJECT
+static GObjectClass *parent_class = NULL;
+
+struct _ESourceListPrivate {
+ GConfClient *gconf_client;
+ char *gconf_path;
+
+ int gconf_notify_id;
+
+ GSList *groups;
+
+ gboolean ignore_group_changed;
+ int sync_idle_id;
+};
+
+
+/* Signals. */
+
+enum {
+ CHANGED,
+ GROUP_REMOVED,
+ GROUP_ADDED,
+ LAST_SIGNAL
+};
+static unsigned int signals[LAST_SIGNAL] = { 0 };
+
+
+/* Forward declarations. */
+
+static gboolean sync_idle_callback (ESourceList *list);
+static void group_changed_callback (ESourceGroup *group,
+ ESourceList *list);
+static void conf_changed_callback (GConfClient *client,
+ unsigned int connection_id,
+ GConfEntry *entry,
+ ESourceList *list);
+
+
+/* Utility functions. */
+
+static void
+load_from_gconf (ESourceList *list)
+{
+ GSList *conf_list, *p, *q;
+ GSList *new_groups_list;
+ GHashTable *new_groups_hash;
+ gboolean changed = FALSE;
+ int pos;
+
+ conf_list = gconf_client_get_list (list->priv->gconf_client,
+ list->priv->gconf_path,
+ GCONF_VALUE_STRING, NULL);
+
+ new_groups_list = NULL;
+ new_groups_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ for (p = conf_list, pos = 0; p != NULL; p = p->next, pos++) {
+ const char *xml = p->data;
+ xmlDocPtr xmldoc = xmlParseDoc ((char *) xml);
+ char *group_uid = e_source_group_uid_from_xmldoc (xmldoc);
+ ESourceGroup *existing_group;
+
+ if (group_uid == NULL)
+ continue;
+
+ existing_group = e_source_list_peek_group_by_uid (list, group_uid);
+ if (g_hash_table_lookup (new_groups_hash, existing_group) != NULL)
+ continue;
+
+ if (existing_group == NULL) {
+ ESourceGroup *new_group = e_source_group_new_from_xmldoc (xmldoc);
+
+ if (new_group != NULL) {
+ g_signal_connect (new_group, "changed", G_CALLBACK (group_changed_callback), list);
+ new_groups_list = g_slist_prepend (new_groups_list, new_group);
+
+ g_hash_table_insert (new_groups_hash, new_group, new_group);
+ g_signal_emit (list, signals[GROUP_ADDED], 0, new_group);
+ changed = TRUE;
+ }
+ } else {
+ gboolean group_changed;
+
+ list->priv->ignore_group_changed ++;
+
+ if (e_source_group_update_from_xmldoc (existing_group, xmldoc, &group_changed)) {
+ new_groups_list = g_slist_prepend (new_groups_list, existing_group);
+ g_object_ref (existing_group);
+ g_hash_table_insert (new_groups_hash, existing_group, existing_group);
+
+ if (group_changed)
+ changed = TRUE;
+ }
+
+ list->priv->ignore_group_changed --;
+ }
+
+ g_free (group_uid);
+ }
+
+ new_groups_list = g_slist_reverse (new_groups_list);
+
+ g_slist_foreach (conf_list, (GFunc) g_free, NULL);
+ g_slist_free (conf_list);
+
+ /* Emit "group_removed" and disconnect the "changed" signal for all the
+ groups that we haven't found in the new list. Also, check if the
+ order has changed. */
+ q = new_groups_list;
+ for (p = list->priv->groups; p != NULL; p = p->next) {
+ ESourceGroup *group = E_SOURCE_GROUP (p->data);
+
+ if (g_hash_table_lookup (new_groups_hash, group) == NULL) {
+ changed = TRUE;
+ g_signal_emit (list, signals[GROUP_REMOVED], 0, group);
+ g_signal_handlers_disconnect_by_func (group, group_changed_callback, list);
+ }
+
+ if (! changed && q != NULL) {
+ if (q->data != p->data)
+ changed = TRUE;
+ q = q->next;
+ }
+ }
+
+ g_hash_table_destroy (new_groups_hash);
+
+ /* Replace the original group list with the new one. */
+
+ g_slist_foreach (list->priv->groups, (GFunc) g_object_unref, NULL);
+ g_slist_free (list->priv->groups);
+
+ list->priv->groups = new_groups_list;
+
+ /* FIXME if the order changes, the function doesn't notice. */
+
+ if (changed)
+ g_signal_emit (list, signals[CHANGED], 0);
+}
+
+static void
+remove_group (ESourceList *list,
+ ESourceGroup *group)
+{
+ list->priv->groups = g_slist_remove (list->priv->groups, group);
+
+ g_signal_emit (list, signals[GROUP_REMOVED], 0, group);
+ g_object_unref (group);
+
+ g_signal_emit (list, signals[CHANGED], 0);
+}
+
+
+/* Callbacks. */
+
+static gboolean
+sync_idle_callback (ESourceList *list)
+{
+ GError *error = NULL;
+
+ if (! e_source_list_sync (list, &error)) {
+ g_warning ("Cannot update \"%s\": %s", list->priv->gconf_path, error->message);
+ g_error_free (error);
+ }
+
+ return FALSE;
+}
+
+static void
+group_changed_callback (ESourceGroup *group,
+ ESourceList *list)
+{
+ if (! list->priv->ignore_group_changed)
+ g_signal_emit (list, signals[CHANGED], 0);
+
+ if (list->priv->sync_idle_id == 0)
+ list->priv->sync_idle_id = g_idle_add ((GSourceFunc) sync_idle_callback, list);
+}
+
+static void
+conf_changed_callback (GConfClient *client,
+ unsigned int connection_id,
+ GConfEntry *entry,
+ ESourceList *list)
+{
+ load_from_gconf (list);
+}
+
+
+/* GObject methods. */
+
+static void
+impl_dispose (GObject *object)
+{
+ ESourceListPrivate *priv = E_SOURCE_LIST (object)->priv;
+
+ if (priv->sync_idle_id != 0) {
+ GError *error = NULL;
+
+ g_source_remove (priv->sync_idle_id);
+ priv->sync_idle_id = 0;
+
+ if (! e_source_list_sync (E_SOURCE_LIST (object), &error))
+ g_warning ("Could not update \"%s\": %s",
+ priv->gconf_path, error->message);
+ }
+
+ if (priv->groups != NULL) {
+ GSList *p;
+
+ for (p = priv->groups; p != NULL; p = p->next)
+ g_object_unref (p->data);
+
+ g_slist_free (priv->groups);
+ priv->groups = NULL;
+ }
+
+ if (priv->gconf_client != NULL) {
+ if (priv->gconf_notify_id != 0) {
+ gconf_client_notify_remove (priv->gconf_client,
+ priv->gconf_notify_id);
+ priv->gconf_notify_id = 0;
+ }
+
+ g_object_unref (priv->gconf_client);
+ priv->gconf_client = NULL;
+ }
+
+ (* G_OBJECT_CLASS (parent_class)->dispose) (object);
+}
+
+static void
+impl_finalize (GObject *object)
+{
+ ESourceListPrivate *priv = E_SOURCE_LIST (object)->priv;
+
+ if (priv->gconf_notify_id != 0) {
+ gconf_client_notify_remove (priv->gconf_client,
+ priv->gconf_notify_id);
+ priv->gconf_notify_id = 0;
+ }
+
+ g_free (priv->gconf_path);
+ g_free (priv);
+
+ (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+}
+
+
+/* Initialization. */
+
+static void
+class_init (ESourceListClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->dispose = impl_dispose;
+ object_class->finalize = impl_finalize;
+
+ parent_class = g_type_class_peek_parent (class);
+
+ signals[CHANGED] =
+ g_signal_new ("changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ESourceListClass, changed),
+ NULL, NULL,
+ e_util_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[GROUP_REMOVED] =
+ g_signal_new ("group_removed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ESourceListClass, group_removed),
+ NULL, NULL,
+ e_util_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ G_TYPE_POINTER);
+
+ signals[GROUP_ADDED] =
+ g_signal_new ("group_added",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ESourceListClass, group_added),
+ NULL, NULL,
+ e_util_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ G_TYPE_POINTER);
+}
+
+static void
+init (ESourceList *source_list)
+{
+ ESourceListPrivate *priv;
+
+ priv = g_new0 (ESourceListPrivate, 1);
+
+ source_list->priv = priv;
+}
+
+
+/* Public methods. */
+
+ESourceList *
+e_source_list_new (void)
+{
+ ESourceList *list = g_object_new (e_source_list_get_type (), NULL);
+
+ return list;
+}
+
+ESourceList *
+e_source_list_new_for_gconf (GConfClient *client,
+ const char *path)
+{
+ ESourceList *list;
+
+ g_return_val_if_fail (GCONF_IS_CLIENT (client), NULL);
+ g_return_val_if_fail (path != NULL, NULL);
+
+ list = g_object_new (e_source_list_get_type (), NULL);
+
+ list->priv->gconf_path = g_strdup (path);
+ list->priv->gconf_client = client;
+ g_object_ref (client);
+
+ gconf_client_add_dir (client, path, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+
+ list->priv->gconf_notify_id
+ = gconf_client_notify_add (client, path,
+ (GConfClientNotifyFunc) conf_changed_callback, list,
+ NULL, NULL);
+ load_from_gconf (list);
+
+ return list;
+}
+
+
+GSList *
+e_source_list_peek_groups (ESourceList *list)
+{
+ g_return_val_if_fail (E_IS_SOURCE_LIST (list), NULL);
+
+ return list->priv->groups;
+}
+
+ESourceGroup *
+e_source_list_peek_group_by_uid (ESourceList *list,
+ const char *uid)
+{
+ GSList *p;
+
+ g_return_val_if_fail (E_IS_SOURCE_LIST (list), NULL);
+ g_return_val_if_fail (uid != NULL, NULL);
+
+ for (p = list->priv->groups; p != NULL; p = p->next) {
+ ESourceGroup *group = E_SOURCE_GROUP (p->data);
+
+ if (strcmp (e_source_group_peek_uid (group), uid) == 0)
+ return group;
+ }
+
+ return NULL;
+}
+
+ESource *
+e_source_list_peek_source_by_uid (ESourceList *list,
+ const char *group_uid,
+ const char *source_uid)
+{
+ ESourceGroup *group;
+
+ g_return_val_if_fail (E_IS_SOURCE_LIST (list), NULL);
+ g_return_val_if_fail (group_uid != NULL, NULL);
+ g_return_val_if_fail (source_uid != NULL, NULL);
+
+ group = e_source_list_peek_group_by_uid (list, group_uid);
+ if (group == NULL)
+ return NULL;
+
+ return e_source_group_peek_source_by_uid (group, source_uid);
+}
+
+
+gboolean
+e_source_list_add_group (ESourceList *list,
+ ESourceGroup *group,
+ int position)
+{
+ g_return_val_if_fail (E_IS_SOURCE_LIST (list), FALSE);
+ g_return_val_if_fail (E_IS_SOURCE_GROUP (group), FALSE);
+
+ if (e_source_list_peek_group_by_uid (list, e_source_group_peek_uid (group)) != NULL)
+ return FALSE;
+
+ list->priv->groups = g_slist_insert (list->priv->groups, group, position);
+ g_object_ref (group);
+
+ g_signal_connect (group, "changed", G_CALLBACK (group_changed_callback), list);
+
+ g_signal_emit (list, signals[GROUP_ADDED], 0, group);
+ g_signal_emit (list, signals[CHANGED], 0);
+
+ return TRUE;
+}
+
+gboolean
+e_source_list_remove_group (ESourceList *list,
+ ESourceGroup *group)
+{
+ g_return_val_if_fail (E_IS_SOURCE_LIST (list), FALSE);
+ g_return_val_if_fail (E_IS_SOURCE_GROUP (group), FALSE);
+
+ if (e_source_list_peek_group_by_uid (list, e_source_group_peek_uid (group)) == NULL)
+ return FALSE;
+
+ remove_group (list, group);
+ return TRUE;
+}
+
+gboolean
+e_source_list_remove_group_by_uid (ESourceList *list,
+ const char *uid)
+{
+ ESourceGroup *group;
+
+ g_return_val_if_fail (E_IS_SOURCE_LIST (list), FALSE);
+ g_return_val_if_fail (uid != NULL, FALSE);
+
+ group = e_source_list_peek_group_by_uid (list, uid);
+ if (group== NULL)
+ return FALSE;
+
+ remove_group (list, group);
+ return TRUE;
+}
+
+gboolean
+e_source_list_remove_source_by_uid (ESourceList *list,
+ const char *group_uid,
+ const char *source_uid)
+{
+ ESourceGroup *group;
+
+ g_return_val_if_fail (E_IS_SOURCE_LIST (list), FALSE);
+ g_return_val_if_fail (group_uid != NULL, FALSE);
+ g_return_val_if_fail (source_uid != NULL, FALSE);
+
+ group = e_source_list_peek_group_by_uid (list, group_uid);
+ if (group== NULL)
+ return FALSE;
+
+ return e_source_group_remove_source_by_uid (group, source_uid);
+}
+
+
+gboolean
+e_source_list_sync (ESourceList *list,
+ GError **error)
+{
+ GSList *conf_list;
+ GSList *p;
+ gboolean retval;
+
+ g_return_val_if_fail (E_IS_SOURCE_LIST (list), FALSE);
+
+ conf_list = NULL;
+ for (p = list->priv->groups; p != NULL; p = p->next)
+ conf_list = g_slist_prepend (conf_list, e_source_group_to_xml (E_SOURCE_GROUP (p->data)));
+ conf_list = g_slist_reverse (conf_list);
+
+ retval = gconf_client_set_list (list->priv->gconf_client,
+ list->priv->gconf_path,
+ GCONF_VALUE_STRING,
+ conf_list,
+ error);
+
+ g_slist_foreach (conf_list, (GFunc) g_free, NULL);
+ g_slist_free (conf_list);
+
+ if (list->priv->gconf_notify_id != 0) {
+ gconf_client_notify_remove (list->priv->gconf_client,
+ list->priv->gconf_notify_id);
+ list->priv->gconf_notify_id = 0;
+ }
+
+ return retval;
+}
+
+
+E_MAKE_TYPE (e_source_list, "ESourceList", ESourceList, class_init, init, PARENT_TYPE)
diff --git a/e-util/e-source-list.h b/e-util/e-source-list.h
new file mode 100644
index 0000000000..1985b35d73
--- /dev/null
+++ b/e-util/e-source-list.h
@@ -0,0 +1,88 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-source-list.h
+ *
+ * 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: Ettore Perazzoli <ettore@ximian.com>
+ */
+
+#ifndef _E_SOURCE_LIST_H_
+#define _E_SOURCE_LIST_H_
+
+#include <libxml/tree.h>
+#include <gconf/gconf-client.h>
+
+#include "e-source-group.h"
+
+#define E_TYPE_SOURCE_LIST (e_source_list_get_type ())
+#define E_SOURCE_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_SOURCE_LIST, ESourceList))
+#define E_SOURCE_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_SOURCE_LIST, ESourceListClass))
+#define E_IS_SOURCE_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_SOURCE_LIST))
+#define E_IS_SOURCE_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_SOURCE_LIST))
+
+
+typedef struct _ESourceList ESourceList;
+typedef struct _ESourceListPrivate ESourceListPrivate;
+typedef struct _ESourceListClass ESourceListClass;
+
+struct _ESourceList {
+ GObject parent;
+
+ ESourceListPrivate *priv;
+};
+
+struct _ESourceListClass {
+ GObjectClass parent_class;
+
+ /* Signals. */
+
+ void (* changed) (ESourceList *source_list);
+
+ void (* group_removed) (ESourceList *source_list, ESourceGroup *group);
+ void (* group_added) (ESourceList *source_list, ESourceGroup *group);
+};
+
+
+GType e_source_list_get_type (void);
+
+ESourceList *e_source_list_new (void);
+ESourceList *e_source_list_new_for_gconf (GConfClient *client,
+ const char *path);
+
+GSList *e_source_list_peek_groups (ESourceList *list);
+ESourceGroup *e_source_list_peek_group_by_uid (ESourceList *list,
+ const char *source_group);
+ESource *e_source_list_peek_source_by_uid (ESourceList *list,
+ const char *group_name,
+ const char *source_name);
+
+gboolean e_source_list_add_group (ESourceList *list,
+ ESourceGroup *group,
+ int position);
+gboolean e_source_list_remove_group (ESourceList *list,
+ ESourceGroup *group);
+gboolean e_source_list_remove_group_by_uid (ESourceList *list,
+ const char *name);
+gboolean e_source_list_remove_source_by_uid (ESourceList *list,
+ const char *group_name,
+ const char *source_name);
+
+gboolean e_source_list_sync (ESourceList *list,
+ GError **error);
+
+
+#endif /* _E_SOURCE_LIST_H_ */
diff --git a/e-util/e-source.c b/e-util/e-source.c
new file mode 100644
index 0000000000..cc7742d924
--- /dev/null
+++ b/e-util/e-source.c
@@ -0,0 +1,458 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-source.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: Ettore Perazzoli <ettore@ximian.com>
+ */
+
+#include <config.h>
+
+#include "e-source.h"
+
+#include "e-util-marshal.h"
+#include "e-uid.h"
+
+#include <string.h>
+#include <gal/util/e-util.h>
+
+
+#define PARENT_TYPE G_TYPE_OBJECT
+static GObjectClass *parent_class = NULL;
+
+#define ES_CLASS(obj) E_SOURCE_CLASS (G_OBJECT_GET_CLASS (obj))
+
+
+/* String used to put the color in the XML. */
+#define COLOR_FORMAT_STRING "%06x"
+
+
+/* Private members. */
+
+struct _ESourcePrivate {
+ ESourceGroup *group;
+
+ char *uid;
+ char *name;
+ char *relative_uri;
+
+ gboolean has_color;
+ guint32 color;
+};
+
+
+/* Signals. */
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+static unsigned int signals[LAST_SIGNAL] = { 0 };
+
+
+/* Callbacks. */
+
+static void
+group_weak_notify (ESource *source,
+ GObject **where_the_object_was)
+{
+ source->priv->group = NULL;
+
+ g_signal_emit (source, signals[CHANGED], 0);
+}
+
+
+/* GObject methods. */
+
+static void
+impl_finalize (GObject *object)
+{
+ ESourcePrivate *priv = E_SOURCE (object)->priv;
+
+ g_free (priv->uid);
+ g_free (priv->name);
+ g_free (priv->relative_uri);
+ g_free (priv);
+
+ (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+}
+
+static void
+impl_dispose (GObject *object)
+{
+ ESourcePrivate *priv = E_SOURCE (object)->priv;
+
+ if (priv->group != NULL) {
+ g_object_weak_unref (G_OBJECT (priv->group), (GWeakNotify) group_weak_notify, object);
+ priv->group = NULL;
+ }
+
+ (* G_OBJECT_CLASS (parent_class)->dispose) (object);
+}
+
+
+/* Initialization. */
+
+static void
+class_init (ESourceClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->dispose = impl_dispose;
+ object_class->finalize = impl_finalize;
+
+ parent_class = g_type_class_peek_parent (class);
+
+ signals[CHANGED] =
+ g_signal_new ("changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ESourceClass, changed),
+ NULL, NULL,
+ e_util_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+init (ESource *source)
+{
+ ESourcePrivate *priv;
+
+ priv = g_new0 (ESourcePrivate, 1);
+ source->priv = priv;
+}
+
+
+/* Public methods. */
+
+ESource *
+e_source_new (const char *name,
+ const char *relative_uri)
+{
+ ESource *source;
+
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (relative_uri != NULL, NULL);
+
+ source = g_object_new (e_source_get_type (), NULL);
+ source->priv->uid = e_uid_new ();
+
+ e_source_set_name (source, name);
+ e_source_set_relative_uri (source, relative_uri);
+ return source;
+}
+
+ESource *
+e_source_new_from_xml_node (xmlNodePtr node)
+{
+ ESource *source;
+ xmlChar *uid;
+
+ uid = xmlGetProp (node, "uid");
+ if (uid == NULL)
+ return NULL;
+
+ source = g_object_new (e_source_get_type (), NULL);
+
+ source->priv->uid = g_strdup (uid);
+ xmlFree (uid);
+
+ if (e_source_update_from_xml_node (source, node, NULL))
+ return source;
+
+ g_object_unref (source);
+ return NULL;
+}
+
+/**
+ * e_source_update_from_xml_node:
+ * @source: An ESource.
+ * @node: A pointer to the node to parse.
+ *
+ * Update the ESource properties from @node.
+ *
+ * Return value: %TRUE if the data in @node was recognized and parsed into
+ * acceptable values for @source, %FALSE otherwise.
+ **/
+gboolean
+e_source_update_from_xml_node (ESource *source,
+ xmlNodePtr node,
+ gboolean *changed_return)
+{
+ xmlChar *name;
+ xmlChar *relative_uri;
+ xmlChar *color_string;
+ gboolean retval;
+ gboolean changed = FALSE;
+
+ name = xmlGetProp (node, "name");
+ relative_uri = xmlGetProp (node, "relative_uri");
+ color_string = xmlGetProp (node, "color");
+
+ if (name == NULL || relative_uri == NULL) {
+ retval = FALSE;
+ goto done;
+ }
+
+ if (source->priv->name == NULL
+ || strcmp (name, source->priv->name) != 0
+ || source->priv->relative_uri == NULL
+ || strcmp (relative_uri, source->priv->relative_uri) != 0) {
+ g_free (source->priv->name);
+ source->priv->name = g_strdup (name);
+
+ g_free (source->priv->relative_uri);
+ source->priv->relative_uri = g_strdup (relative_uri);
+
+ changed = TRUE;
+ }
+
+ if (color_string == NULL) {
+ if (source->priv->has_color) {
+ source->priv->has_color = FALSE;
+ changed = TRUE;
+ }
+ } else {
+ guint32 color = 0;
+
+ sscanf (color_string, COLOR_FORMAT_STRING, &color);
+ if (! source->priv->has_color || source->priv->color != color) {
+ source->priv->has_color = TRUE;
+ source->priv->color = color;
+ changed = TRUE;
+ }
+ }
+
+ retval = TRUE;
+
+ done:
+ if (changed)
+ g_signal_emit (source, signals[CHANGED], 0);
+
+ if (changed_return != NULL)
+ *changed_return = changed;
+
+ if (name != NULL)
+ xmlFree (name);
+ if (relative_uri != NULL)
+ xmlFree (relative_uri);
+ if (color_string != NULL)
+ xmlFree (color_string);
+
+ return retval;
+}
+
+/**
+ * e_source_name_from_xml_node:
+ * @node: A pointer to an XML node.
+ *
+ * Assuming that @node is a valid ESource specification, retrieve the name of
+ * the source from it.
+ *
+ * Return value: Name of the source in the specified @node. The caller must
+ * free the string.
+ **/
+char *
+e_source_uid_from_xml_node (xmlNodePtr node)
+{
+ xmlChar *uid = xmlGetProp (node, "uid");
+ char *retval;
+
+ if (uid == NULL)
+ return NULL;
+
+ retval = g_strdup (uid);
+ xmlFree (uid);
+ return retval;
+}
+
+void
+e_source_set_group (ESource *source,
+ ESourceGroup *group)
+{
+ g_return_if_fail (E_IS_SOURCE (source));
+ g_return_if_fail (group == NULL || E_IS_SOURCE_GROUP (group));
+
+ if (source->priv->group == group)
+ return;
+
+ if (source->priv->group != NULL)
+ g_object_weak_unref (G_OBJECT (source->priv->group), (GWeakNotify) group_weak_notify, source);
+
+ source->priv->group = group;
+ if (group != NULL)
+ g_object_weak_ref (G_OBJECT (group), (GWeakNotify) group_weak_notify, source);
+
+ g_signal_emit (source, signals[CHANGED], 0);
+}
+
+void
+e_source_set_name (ESource *source,
+ const char *name)
+{
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ if (source->priv->name == name)
+ return;
+
+ g_free (source->priv->name);
+ source->priv->name = g_strdup (name);
+
+ g_signal_emit (source, signals[CHANGED], 0);
+}
+
+void
+e_source_set_relative_uri (ESource *source,
+ const char *relative_uri)
+{
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ if (source->priv->relative_uri == relative_uri)
+ return;
+
+ g_free (source->priv->relative_uri);
+ source->priv->relative_uri = g_strdup (relative_uri);
+
+ g_signal_emit (source, signals[CHANGED], 0);
+}
+
+void
+e_source_set_color (ESource *source,
+ guint32 color)
+{
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ if (source->priv->has_color && source->priv->color == color)
+ return;
+
+ source->priv->has_color = TRUE;
+ source->priv->color = color;
+
+ g_signal_emit (source, signals[CHANGED], 0);
+}
+
+void
+e_source_unset_color (ESource *source)
+{
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ if (! source->priv->has_color)
+ return;
+
+ source->priv->has_color = FALSE;
+ g_signal_emit (source, signals[CHANGED], 0);
+}
+
+
+ESourceGroup *
+e_source_peek_group (ESource *source)
+{
+ g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+
+ return source->priv->group;
+}
+
+const char *
+e_source_peek_uid (ESource *source)
+{
+ g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+
+ return source->priv->uid;
+}
+
+const char *
+e_source_peek_name (ESource *source)
+{
+ g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+
+ return source->priv->name;
+}
+
+const char *
+e_source_peek_relative_uri (ESource *source)
+{
+ g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+
+ return source->priv->relative_uri;
+}
+
+/**
+ * e_source_get_color:
+ * @source: An ESource
+ * @color_return: Pointer to a variable where the returned color will be
+ * stored.
+ *
+ * If @source has an associated color, return it in *@color_return.
+ *
+ * Return value: %TRUE if the @source has a defined color (and hence
+ * *@color_return was set), %FALSE otherwise.
+ **/
+gboolean
+e_source_get_color (ESource *source,
+ guint32 *color_return)
+{
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+
+ if (! source->priv->has_color)
+ return FALSE;
+
+ if (color_return != NULL)
+ *color_return = source->priv->color;
+
+ return TRUE;
+}
+
+
+char *
+e_source_get_uri (ESource *source)
+{
+ g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+
+ if (source->priv->group == NULL)
+ return NULL;
+
+ return g_build_filename (e_source_group_peek_base_uri (source->priv->group),
+ source->priv->relative_uri,
+ NULL);
+}
+
+
+void
+e_source_dump_to_xml_node (ESource *source,
+ xmlNodePtr parent_node)
+{
+ gboolean has_color;
+ guint32 color;
+ xmlNodePtr node = xmlNewChild (parent_node, NULL, "source", NULL);
+
+ g_return_if_fail (E_IS_SOURCE (source));
+
+
+ xmlSetProp (node, "uid", e_source_peek_uid (source));
+ xmlSetProp (node, "name", e_source_peek_name (source));
+ xmlSetProp (node, "relative_uri", e_source_peek_relative_uri (source));
+
+ has_color = e_source_get_color (source, &color);
+ if (has_color) {
+ char *color_string = g_strdup_printf (COLOR_FORMAT_STRING, color);
+ xmlSetProp (node, "color", color_string);
+ g_free (color_string);
+ }
+}
+
+
+E_MAKE_TYPE (e_source, "ESource", ESource, class_init, init, PARENT_TYPE)
diff --git a/e-util/e-source.h b/e-util/e-source.h
new file mode 100644
index 0000000000..6060b8b588
--- /dev/null
+++ b/e-util/e-source.h
@@ -0,0 +1,91 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-source.h
+ *
+ * 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: Ettore Perazzoli <ettore@ximian.com>
+ */
+
+#ifndef _E_SOURCE_H_
+#define _E_SOURCE_H_
+
+#include <glib-object.h>
+#include <libxml/tree.h>
+
+#define E_TYPE_SOURCE (e_source_get_type ())
+#define E_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_SOURCE, ESource))
+#define E_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_SOURCE, ESourceClass))
+#define E_IS_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_SOURCE))
+#define E_IS_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_SOURCE))
+
+
+typedef struct _ESource ESource;
+typedef struct _ESourcePrivate ESourcePrivate;
+typedef struct _ESourceClass ESourceClass;
+
+#include "e-source-group.h"
+
+struct _ESource {
+ GObject parent;
+
+ ESourcePrivate *priv;
+};
+
+struct _ESourceClass {
+ GObjectClass parent_class;
+
+ /* Signals. */
+ void (* changed) (ESource *source);
+};
+
+
+GType e_source_get_type (void);
+
+ESource *e_source_new (const char *name,
+ const char *relative_uri);
+ESource *e_source_new_from_xml_node (xmlNodePtr node);
+
+gboolean e_source_update_from_xml_node (ESource *source,
+ xmlNodePtr node,
+ gboolean *changed_return);
+
+char *e_source_uid_from_xml_node (xmlNodePtr node);
+
+void e_source_set_group (ESource *source,
+ ESourceGroup *group);
+void e_source_set_name (ESource *source,
+ const char *name);
+void e_source_set_relative_uri (ESource *source,
+ const char *relative_uri);
+void e_source_set_color (ESource *source,
+ guint32 color);
+void e_source_unset_color (ESource *source);
+
+ESourceGroup *e_source_peek_group (ESource *source);
+const char *e_source_peek_uid (ESource *source);
+const char *e_source_peek_name (ESource *source);
+const char *e_source_peek_relative_uri (ESource *source);
+gboolean e_source_get_color (ESource *source,
+ guint32 *color_return);
+
+char *e_source_get_uri (ESource *source);
+
+void e_source_dump_to_xml_node (ESource *source,
+ xmlNodePtr parent_node);
+
+
+#endif /* _E_SOURCE_H_ */
diff --git a/e-util/e-uid.c b/e-util/e-uid.c
new file mode 100644
index 0000000000..90c036e0c1
--- /dev/null
+++ b/e-util/e-uid.c
@@ -0,0 +1,61 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-uid.c - Unique ID generator.
+ *
+ * Copyright (C) 2002 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: Dan Winship <danw@ximian.com>
+ */
+
+#include "e-uid.h"
+
+#include <glib/gstrfuncs.h>
+
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+
+/**
+ * e_uid_new:
+ *
+ * Generate a new unique string for use e.g. in account lists.
+ *
+ * Return value: the newly generated UID. The caller should free the string
+ * when it's done with it.
+ **/
+char *
+e_uid_new (void)
+{
+ static char *hostname;
+ static int serial;
+
+ if (!hostname) {
+ static char buffer [512];
+
+ if ((gethostname (buffer, sizeof (buffer) - 1) == 0) &&
+ (buffer [0] != 0))
+ hostname = buffer;
+ else
+ hostname = "localhost";
+ }
+
+ return g_strdup_printf ("%lu.%lu.%d@%s",
+ (unsigned long) time (NULL),
+ (unsigned long) getpid (),
+ serial++,
+ hostname);
+}
diff --git a/e-util/e-uid.h b/e-util/e-uid.h
new file mode 100644
index 0000000000..44ec8c0dd9
--- /dev/null
+++ b/e-util/e-uid.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-uid.h - Unique ID generator.
+ *
+ * Copyright (C) 2002 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: Dan Winship <danw@ximian.com>
+ */
+
+#ifndef E_UID_H
+#define E_UID_H
+
+char *e_uid_new (void);
+
+#endif /* E_UID_H */
diff --git a/e-util/test-source-list.c b/e-util/test-source-list.c
new file mode 100644
index 0000000000..7c38436326
--- /dev/null
+++ b/e-util/test-source-list.c
@@ -0,0 +1,524 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* test-source-list.c - Test for the ESourceList class.
+ *
+ * Copyright (C) 2002 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: Ettore Perazzoli <ettore@ximian.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-source-list.h"
+
+#include <libgnomeui/gnome-ui-init.h>
+#include <glib/gmain.h>
+
+
+/* Globals. */
+
+static GMainLoop *main_loop = NULL;
+static ESourceList *list = NULL;
+static int idle_dump_id = 0;
+
+
+/* Options. */
+
+static gboolean listen = FALSE;
+static gboolean dump = FALSE;
+static char *key_arg = "/apps/evolution/test/source_list";
+static char *source_arg = NULL;
+static char *group_arg = NULL;
+static char *add_group_arg = NULL;
+static char *add_source_arg = NULL;
+static char *remove_group_arg = NULL;
+static char *remove_source_arg = NULL;
+static char *set_name_arg = NULL;
+static char *set_base_uri_arg = NULL;
+static char *set_relative_uri_arg = NULL;
+static char *set_color_arg = NULL;
+static gboolean unset_color = FALSE;
+
+static struct poptOption options[] = {
+ { "key", '\0', POPT_ARG_STRING, &key_arg, 0,
+ "Name of the GConf key to use", "PATH" },
+ { "source", '\0', POPT_ARG_STRING, &source_arg, 0,
+ "UID of source to apply operation to", "UID" },
+ { "group", '\0', POPT_ARG_STRING, &group_arg, 0,
+ "UID of group to apply operation to", "UID" },
+ { "add-group", '\0', POPT_ARG_STRING, &add_group_arg, 0,
+ "Add group of specified name", "NAME" },
+ { "add-source", '\0', POPT_ARG_STRING, &add_source_arg, 0,
+ "Add source of specified name", "NAME" },
+ { "remove-group", '\0', POPT_ARG_STRING, &remove_group_arg, 0,
+ "Remove group of specified name", "NAME" },
+ { "remove-source", '\0', POPT_ARG_STRING, &remove_source_arg, 0,
+ "Remove source of specified name", "NAME" },
+ { "set-name", '\0', POPT_ARG_STRING, &set_name_arg, 0,
+ "Set name of source or group. When used with --group, it sets the name of a group. "
+ "When used with both --group and --source, it sets the name of a source.", "NAME" },
+ { "set-relative-uri", '\0', POPT_ARG_STRING, &set_relative_uri_arg, 0,
+ "Set relative URI of a source. Use with --source or --add-source.", "NAME" },
+ { "set-base-uri", '\0', POPT_ARG_STRING, &set_base_uri_arg, 0,
+ "Set base URI of a group. Use with --group or --add-group.", "NAME" },
+ { "set-color", '\0', POPT_ARG_STRING, &set_color_arg, 0,
+ "Set the color of a source. Use with --source or --add-source.", "COLOR (rrggbb)" },
+ { "unset-color", '\0', POPT_ARG_NONE, &unset_color, 0,
+ "Unset the color of a source. Use with --source or --add-source.", NULL },
+ { "listen", '\0', POPT_ARG_NONE, &listen, 0,
+ "Wait and listen for changes.", "" },
+ { "dump", '\0', POPT_ARG_NONE, &dump, 0,
+ "List the current configured sources.", "" },
+ POPT_AUTOHELP
+ { NULL }
+};
+
+
+/* Forward decls. */
+static void group_added_callback (ESourceList *list, ESourceGroup *group);
+static void group_removed_callback (ESourceList *list, ESourceGroup *group);
+static void source_added_callback (ESourceGroup *group, ESource *source);
+static void source_removed_callback (ESourceGroup *group, ESource *source);
+
+
+static void
+dump_source (ESource *source)
+{
+ char *uri = e_source_get_uri (source);
+ gboolean has_color;
+ guint32 color;
+
+ g_print ("\tSource %s\n", e_source_peek_uid (source));
+ g_print ("\t\tname: %s\n", e_source_peek_name (source));
+ g_print ("\t\trelative_uri: %s\n", e_source_peek_relative_uri (source));
+ g_print ("\t\tabsolute_uri: %s\n", uri);
+
+ has_color = e_source_get_color (source, &color);
+ if (has_color)
+ g_print ("\t\tcolor: %06x\n", color);
+
+ g_free (uri);
+}
+
+static void
+dump_group (ESourceGroup *group)
+{
+ GSList *sources, *p;
+
+ g_print ("Group %s\n", e_source_group_peek_uid (group));
+ g_print ("\tname: %s\n", e_source_group_peek_name (group));
+ g_print ("\tbase_uri: %s\n", e_source_group_peek_base_uri (group));
+
+ sources = e_source_group_peek_sources (group);
+ for (p = sources; p != NULL; p = p->next) {
+ ESource *source = E_SOURCE (p->data);
+
+ dump_source (source);
+
+ if (e_source_peek_group (source) != group)
+ g_warning ("\t\t** ERROR ** parent pointer is %p, should be %p",
+ e_source_peek_group (source), group);
+ }
+}
+
+static void
+dump_list (void)
+{
+ GSList *groups, *p;
+
+ groups = e_source_list_peek_groups (list);
+ if (groups == NULL) {
+ g_print ("(No items)\n");
+ return;
+ }
+
+ for (p = groups; p != NULL; p = p->next)
+ dump_group (E_SOURCE_GROUP (p->data));
+}
+
+
+static int
+idle_dump_callback (void *unused_data)
+{
+ dump_list ();
+ idle_dump_id = 0;
+
+ return FALSE;
+}
+
+static void
+dump_on_idle (void)
+{
+ if (idle_dump_id == 0)
+ idle_dump_id = g_idle_add (idle_dump_callback, NULL);
+}
+
+
+static void
+source_changed_callback (ESource *source)
+{
+ static int count = 0;
+
+ g_print ("** Event: source \"%s\" changed (%d)\n", e_source_peek_name (source), ++count);
+
+ dump_on_idle ();
+}
+
+static void
+group_changed_callback (ESourceGroup *group)
+{
+ static int count = 0;
+
+ g_print ("** Event: group \"%s\" changed (%d)\n", e_source_group_peek_name (group), ++count);
+
+ dump_on_idle ();
+}
+
+static void
+list_changed_callback (ESourceGroup *group)
+{
+ static int count = 0;
+
+ g_print ("** Event: list changed (%d)\n", ++count);
+
+ dump_on_idle ();
+}
+
+
+static void
+connect_source (ESource *source)
+{
+ g_object_ref (source);
+ g_signal_connect (source, "changed", G_CALLBACK (source_changed_callback), NULL);
+}
+
+static void
+connect_group (ESourceGroup *group)
+{
+ GSList *sources, *p;
+
+ g_object_ref (group);
+ g_signal_connect (group, "changed", G_CALLBACK (group_changed_callback), NULL);
+ g_signal_connect (group, "source_added", G_CALLBACK (source_added_callback), NULL);
+ g_signal_connect (group, "source_removed", G_CALLBACK (source_removed_callback), NULL);
+
+ sources = e_source_group_peek_sources (group);
+ for (p = sources; p != NULL; p = p->next)
+ connect_source (E_SOURCE (p->data));
+}
+
+static void
+connect_list (void)
+{
+ GSList *groups, *p;
+
+ g_signal_connect (list, "changed", G_CALLBACK (list_changed_callback), NULL);
+ g_signal_connect (list, "group_added", G_CALLBACK (group_added_callback), NULL);
+ g_signal_connect (list, "group_removed", G_CALLBACK (group_removed_callback), NULL);
+
+ groups = e_source_list_peek_groups (list);
+ for (p = groups; p != NULL; p = p->next)
+ connect_group (E_SOURCE_GROUP (p->data));
+}
+
+static void
+disconnect_group (ESourceGroup *group)
+{
+ g_signal_handlers_disconnect_by_func (group, G_CALLBACK (group_changed_callback), NULL);
+ g_signal_handlers_disconnect_by_func (group, G_CALLBACK (source_added_callback), NULL);
+
+ g_object_unref (group);
+}
+
+static void
+disconnect_source (ESource *source)
+{
+ g_signal_handlers_disconnect_by_func (source, G_CALLBACK (source_changed_callback), NULL);
+
+ g_object_unref (source);
+}
+
+
+static void
+source_added_callback (ESourceGroup *group,
+ ESource *source)
+{
+ static int count = 0;
+
+ g_print ("** Event: source \"%s\" added (%d)\n", e_source_peek_name (source), ++count);
+
+ connect_source (source);
+ dump_on_idle ();
+}
+
+static void
+source_removed_callback (ESourceGroup *group,
+ ESource *source)
+{
+ static int count = 0;
+
+ g_print ("** Event: source \"%s\" removed (%d)\n", e_source_peek_name (source), ++count);
+
+ disconnect_source (source);
+ dump_on_idle ();
+}
+
+static void
+group_added_callback (ESourceList *list,
+ ESourceGroup *group)
+{
+ static int count = 0;
+
+ g_print ("** Event: group \"%s\" added (%d)\n", e_source_group_peek_name (group), ++count);
+
+ connect_group (group);
+ dump_on_idle ();
+}
+
+static void
+group_removed_callback (ESourceList *list,
+ ESourceGroup *group)
+{
+ static int count = 0;
+
+ g_print ("** Event: group \"%s\" removed (%d)\n", e_source_group_peek_name (group), ++count);
+
+ disconnect_group (group);
+ dump_on_idle ();
+}
+
+
+static int
+on_idle_do_stuff (void *unused_data)
+{
+ GConfClient *client = gconf_client_get_default ();
+ ESourceGroup *new_group = NULL;
+ ESource *new_source = NULL;
+
+ list = e_source_list_new_for_gconf (client, key_arg);
+ g_object_unref (client);
+
+ if (add_group_arg != NULL) {
+ if (group_arg != NULL) {
+ fprintf (stderr, "--add-group and --group cannot be used at the same time.\n");
+ exit (1);
+ }
+ if (set_base_uri_arg == NULL) {
+ fprintf (stderr, "When using --add-group, you need to specify a base URI using --set-base-uri.\n");
+ exit (1);
+ }
+
+ new_group = e_source_group_new (add_group_arg, set_base_uri_arg);
+ e_source_list_add_group (list, new_group, -1);
+ g_object_unref (new_group);
+
+ e_source_list_sync (list, NULL);
+ }
+
+ if (remove_group_arg != NULL) {
+ ESourceGroup *group;
+
+ group = e_source_list_peek_group_by_uid (list, remove_group_arg);
+ if (group == NULL) {
+ fprintf (stderr, "No such group \"%s\".\n", remove_group_arg);
+ exit (1);
+ }
+
+ e_source_list_remove_group (list, group);
+ e_source_list_sync (list, NULL);
+ }
+
+ if (add_source_arg != NULL) {
+ ESourceGroup *group;
+
+ if (group_arg == NULL && new_group == NULL) {
+ fprintf (stderr,
+ "When using --add-source, you need to specify a group using either --group\n"
+ "or --add-group.\n");
+ exit (1);
+ }
+ if (set_relative_uri_arg == NULL) {
+ fprintf (stderr,
+ "When using --add-source, you need to specify a relative URI using\n"
+ "--set-relative-uri.\n");
+ exit (1);
+ }
+
+ if (group_arg == NULL) {
+ group = new_group;
+ } else {
+ group = e_source_list_peek_group_by_uid (list, group_arg);
+ if (group == NULL) {
+ fprintf (stderr, "No such group \"%s\".\n", group_arg == NULL ? add_group_arg : group_arg);
+ exit (1);
+ }
+ }
+
+ new_source = e_source_new (add_source_arg, set_relative_uri_arg);
+ e_source_group_add_source (group, new_source, -1);
+ e_source_list_sync (list, NULL);
+ }
+
+ if (remove_source_arg != NULL) {
+ ESource *source;
+
+ if (group_arg == NULL) {
+ fprintf (stderr, "When using --remove-source, you need to specify a group using --group.\n");
+ exit (1);
+ }
+
+ source = e_source_list_peek_source_by_uid (list, group_arg, remove_source_arg);
+ if (source == NULL) {
+ fprintf (stderr, "No such source \"%s\" in group \"%s\".\n", remove_source_arg, group_arg);
+ exit (1);
+ }
+
+ e_source_list_remove_source_by_uid (list, group_arg, remove_source_arg);
+ e_source_list_sync (list, NULL);
+ }
+
+ if (set_name_arg != NULL) {
+ if (group_arg == NULL) {
+ fprintf (stderr,
+ "When using --set-name, you need to specify a source (using --group and\n"
+ "--source) or a group (using --group alone).\n");
+ exit (1);
+ }
+
+ if (source_arg != NULL) {
+ ESource *source = e_source_list_peek_source_by_uid (list, group_arg, source_arg);
+
+ if (source != NULL) {
+ e_source_set_name (source, set_name_arg);
+ } else {
+ fprintf (stderr, "No such source \"%s\" in group \"%s\".\n", source_arg, group_arg);
+ exit (1);
+ }
+ } else {
+ ESourceGroup *group = e_source_list_peek_group_by_uid (list, group_arg);
+
+ if (group != NULL) {
+ e_source_group_set_name (group, set_name_arg);
+ } else {
+ fprintf (stderr, "No such group \"%s\".\n", group_arg);
+ exit (1);
+ }
+ }
+
+ e_source_list_sync (list, NULL);
+ }
+
+ if (set_relative_uri_arg != NULL && add_source_arg == NULL) {
+ ESource *source;
+
+ if (source_arg == NULL || group_arg == NULL) {
+ fprintf (stderr,
+ "When using --set-relative-uri, you need to specify a source using --group\n"
+ "and --source.\n");
+ exit (1);
+ }
+
+ source = e_source_list_peek_source_by_uid (list, group_arg, source_arg);
+ e_source_set_relative_uri (source, set_relative_uri_arg);
+ e_source_list_sync (list, NULL);
+ }
+
+ if (set_color_arg != NULL) {
+ ESource *source;
+ guint32 color;
+
+ if (add_source_arg == NULL && (source_arg == NULL || group_arg == NULL)) {
+ fprintf (stderr,
+ "When using --set-color, you need to specify a source using --group\n"
+ "and --source.\n");
+ exit (1);
+ }
+
+ if (add_source_arg != NULL)
+ source = new_source;
+ else
+ source = e_source_list_peek_source_by_uid (list, group_arg, source_arg);
+
+ sscanf (set_color_arg, "%06x", &color);
+ e_source_set_color (source, color);
+ e_source_list_sync (list, NULL);
+ }
+
+ if (unset_color) {
+ ESource *source;
+
+ if (add_source_arg == NULL && (source_arg == NULL || group_arg == NULL)) {
+ fprintf (stderr,
+ "When using --unset-color, you need to specify a source using --group\n"
+ "and --source.\n");
+ exit (1);
+ }
+
+ if (add_source_arg != NULL)
+ source = new_source;
+ else
+ source = e_source_list_peek_source_by_uid (list, group_arg, source_arg);
+
+ e_source_unset_color (source);
+ e_source_list_sync (list, NULL);
+ }
+
+ if (set_base_uri_arg != NULL && add_group_arg == NULL) {
+ ESourceGroup *group;
+
+ if (group_arg == NULL) {
+ fprintf (stderr,
+ "When using --set-base-uri, you need to specify a group using --group.\n");
+ exit (1);
+ }
+
+ group = e_source_list_peek_group_by_uid (list, group_arg);
+ e_source_group_set_base_uri (group, set_base_uri_arg);
+ e_source_list_sync (list, NULL);
+ }
+
+ connect_list ();
+
+ if (dump)
+ dump_list ();
+
+ if (! listen)
+ g_main_loop_quit (main_loop);
+
+ return FALSE;
+}
+
+
+int
+main (int argc,
+ char **argv)
+{
+ GnomeProgram *program;
+
+ program = gnome_program_init ("test-source-list", "0.0",
+ LIBGNOMEUI_MODULE, argc, argv,
+ GNOME_PARAM_POPT_TABLE, options,
+ NULL);
+
+ g_idle_add (on_idle_do_stuff, NULL);
+
+ main_loop = g_main_loop_new (NULL, TRUE);
+ g_main_loop_run (main_loop);
+
+ return 0;
+}
diff --git a/filter/ChangeLog b/filter/ChangeLog
index abcaad596c..0506227e66 100644
--- a/filter/ChangeLog
+++ b/filter/ChangeLog
@@ -1,3 +1,13 @@
+2003-10-10 Not Zed <NotZed@Ximian.com>
+
+ * filter-folder.c (folder_selected): change for
+ emfolderselectionbutton fixes.
+ (get_widget): same.
+
+2003-09-29 Ettore Perazzoli <ettore@ximian.com>
+
+ * filter-folder.c (get_widget): Use an EMFolderSelectionButton.
+
2003-09-22 Jeffrey Stedfast <fejj@ximian.com>
* filter-int.c (get_widget): Listen to the "value-changed" signal
@@ -24,6 +34,15 @@
* searchtypes.xml: Added a search-specific types folder. Also
contains system searches that cannot be deleted.
+2003-08-18 Ettore Perazzoli <ettore@ximian.com>
+
+ * vfolder-rule.c (source_add): As a temporary measure, don't call
+ evolution_shell_client_user_select_folder() since this is not done
+ by the shell anymore.
+
+ * filter-folder.c (get_widget): Return NULL for now, since we
+ can't get the folder selector button from the shell anymore.
+
2003-08-05 Not Zed <NotZed@Ximian.com>
** See bug #42636.
diff --git a/filter/filter-folder.c b/filter/filter-folder.c
index e074c31f6c..c19584484d 100644
--- a/filter/filter-folder.c
+++ b/filter/filter-folder.c
@@ -31,7 +31,8 @@
#include <libgnome/gnome-i18n.h>
#include "filter-folder.h"
-#include "shell/evolution-folder-selector-button.h"
+#include "mail/em-folder-selection-button.h"
+#include "mail/mail-component.h"
#include "e-util/e-sexp.h"
#define d(x)
@@ -53,9 +54,6 @@ static void filter_folder_finalise (GObject *obj);
static FilterElementClass *parent_class = NULL;
-extern EvolutionShellClient *global_shell_client;
-
-
GType
filter_folder_get_type (void)
{
@@ -222,12 +220,13 @@ xml_decode (FilterElement *fe, xmlNodePtr node)
}
static void
-folder_selected (EvolutionFolderSelectorButton *button,
- GNOME_Evolution_Folder *folder,
- FilterFolder *ff)
+folder_selected(EMFolderSelectionButton *button, FilterFolder *ff)
{
- g_free (ff->uri);
- ff->uri = g_strdup (folder->physicalUri);
+ const char *uri;
+
+ uri = em_folder_selection_button_get_selection(button);
+ g_free(ff->uri);
+ ff->uri = uri!=NULL?em_uri_from_camel(uri):NULL;
gdk_window_raise (GTK_WIDGET (gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_WINDOW))->window);
}
@@ -235,14 +234,14 @@ folder_selected (EvolutionFolderSelectorButton *button,
static GtkWidget *
get_widget (FilterElement *fe)
{
- static const char *allowed_types[] = { "mail/*", NULL };
FilterFolder *ff = (FilterFolder *)fe;
GtkWidget *button;
-
- button = evolution_folder_selector_button_new (global_shell_client,
- _("Select Folder"),
- ff->uri,
- allowed_types);
+ char *uri;
+
+ uri = em_uri_to_camel(ff->uri);
+ button = em_folder_selection_button_new (_("Select Folder"), NULL);
+ em_folder_selection_button_set_selection(EM_FOLDER_SELECTION_BUTTON(button), uri);
+ g_free(uri);
gtk_widget_show (button);
g_signal_connect (button, "selected", G_CALLBACK (folder_selected), ff);
diff --git a/filter/libfilter-i18n.h b/filter/libfilter-i18n.h
index d965e03184..ea7ff03b0e 100644
--- a/filter/libfilter-i18n.h
+++ b/filter/libfilter-i18n.h
@@ -4,34 +4,17 @@ char *s = N_("Assign Color");
char *s = N_("Assign Score");
char *s = N_("Attachments");
char *s = N_("Beep");
-char *s = N_("contains");
char *s = N_("Copy to Folder");
char *s = N_("Date received");
char *s = N_("Date sent");
char *s = N_("Delete");
char *s = N_("Deleted");
-char *s = N_("does not contain");
-char *s = N_("does not end with");
-char *s = N_("does not exist");
-char *s = N_("does not return");
-char *s = N_("does not sound like");
-char *s = N_("does not start with");
char *s = N_("Do Not Exist");
char *s = N_("Draft");
-char *s = N_("ends with");
char *s = N_("Exist");
-char *s = N_("exists");
char *s = N_("Expression");
char *s = N_("Follow Up");
char *s = N_("Important");
-char *s = N_("is");
-char *s = N_("is after");
-char *s = N_("is before");
-char *s = N_("is Flagged");
-char *s = N_("is greater than");
-char *s = N_("is less than");
-char *s = N_("is not");
-char *s = N_("is not Flagged");
char *s = N_("Label");
char *s = N_("Mailing list");
char *s = N_("Message Body");
@@ -43,19 +26,36 @@ char *s = N_("Read");
char *s = N_("Recipients");
char *s = N_("Regex Match");
char *s = N_("Replied to");
-char *s = N_("returns");
-char *s = N_("returns greater than");
-char *s = N_("returns less than");
char *s = N_("Score");
char *s = N_("Sender");
char *s = N_("Set Status");
char *s = N_("Shell Command");
char *s = N_("Size (kB)");
-char *s = N_("sounds like");
char *s = N_("Source Account");
char *s = N_("Specific header");
-char *s = N_("starts with");
char *s = N_("Status");
char *s = N_("Stop Processing");
char *s = N_("Subject");
char *s = N_("Unset Status");
+char *s = N_("contains");
+char *s = N_("does not contain");
+char *s = N_("does not end with");
+char *s = N_("does not exist");
+char *s = N_("does not return");
+char *s = N_("does not sound like");
+char *s = N_("does not start with");
+char *s = N_("ends with");
+char *s = N_("exists");
+char *s = N_("is Flagged");
+char *s = N_("is after");
+char *s = N_("is before");
+char *s = N_("is greater than");
+char *s = N_("is less than");
+char *s = N_("is not Flagged");
+char *s = N_("is not");
+char *s = N_("is");
+char *s = N_("returns greater than");
+char *s = N_("returns less than");
+char *s = N_("returns");
+char *s = N_("sounds like");
+char *s = N_("starts with");
diff --git a/filter/vfolder-rule.c b/filter/vfolder-rule.c
index 26d024c525..91ad0b151c 100644
--- a/filter/vfolder-rule.c
+++ b/filter/vfolder-rule.c
@@ -46,8 +46,6 @@ static void rule_copy (FilterRule *dest, FilterRule *src);
/*static void build_code(FilterRule *, GString *out);*/
static GtkWidget *get_widget(FilterRule *fr, RuleContext *f);
-extern EvolutionShellClient *global_shell_client;
-
static void vfolder_rule_class_init (VfolderRuleClass *klass);
static void vfolder_rule_init (VfolderRule *vr);
static void vfolder_rule_finalise (GObject *obj);
@@ -433,9 +431,13 @@ source_add (GtkWidget *widget, struct _source_data *data)
window = gtk_widget_get_toplevel (widget);
gtk_widget_set_sensitive (window, FALSE);
-
+
+#if 0 /* EPFIXME */
evolution_shell_client_user_select_folder (global_shell_client, GTK_WINDOW (window),
_("Select Folder"), "", allowed_types, &folder);
+#else
+ folder = NULL;
+#endif
gtk_widget_set_sensitive (window, TRUE);
diff --git a/help/C/.cvsignore b/help/C/.cvsignore
index 282522db03..c35e90b546 100644
--- a/help/C/.cvsignore
+++ b/help/C/.cvsignore
@@ -1,2 +1,4 @@
Makefile
Makefile.in
+evolution-*-C.omf.out
+omf_timestamp
diff --git a/help/es/apx-authors.sgml b/help/es/apx-authors.sgml
index a1069ee6cb..eeda6754fe 100644
--- a/help/es/apx-authors.sgml
+++ b/help/es/apx-authors.sgml
@@ -1,6 +1,6 @@
-<!-- $Id: apx-authors.sgml,v 1.2 2003/08/08 21:57:42 olea Exp $ -->
+<!-- $Id: apx-authors.sgml,v 1.3 2003/10/21 18:51:25 ettore Exp $ -->
<!-- Traducción: Ismael -->
<!-- Revisión: irm 030504/final 030428/rápida -->
diff --git a/help/es/apx-bugs.sgml b/help/es/apx-bugs.sgml
index 7062bd442e..d0fc39ef65 100644
--- a/help/es/apx-bugs.sgml
+++ b/help/es/apx-bugs.sgml
@@ -1,6 +1,6 @@
-<!-- $Id: apx-bugs.sgml,v 1.2 2003/08/08 21:57:42 olea Exp $ -->
+<!-- $Id: apx-bugs.sgml,v 1.3 2003/10/21 18:51:25 ettore Exp $ -->
<!-- Traducción: Ismael -->
<!-- Revisión: irm 030504/final 030428/rápida -->
diff --git a/help/es/apx-fdl.sgml b/help/es/apx-fdl.sgml
index b7dcfe14a9..46814a06cb 100644
--- a/help/es/apx-fdl.sgml
+++ b/help/es/apx-fdl.sgml
@@ -1,4 +1,4 @@
-<!-- $Id: apx-fdl.sgml,v 1.2 2003/08/08 21:57:42 olea Exp $ -->
+<!-- $Id: apx-fdl.sgml,v 1.3 2003/10/21 18:51:25 ettore Exp $ -->
<!-- Este fichero no se traduce -->
<!--
diff --git a/help/es/apx-gloss.sgml b/help/es/apx-gloss.sgml
index ae3f537713..fff6a85ec7 100644
--- a/help/es/apx-gloss.sgml
+++ b/help/es/apx-gloss.sgml
@@ -1,6 +1,6 @@
-<!-- $Id: apx-gloss.sgml,v 1.2 2003/08/08 21:57:43 olea Exp $ -->
+<!-- $Id: apx-gloss.sgml,v 1.3 2003/10/21 18:51:25 ettore Exp $ -->
<!-- Traducción: Ismael -->
<!-- Revisión: irm 030504/final 030428/rápida -->
diff --git a/help/es/apx-gpl.sgml b/help/es/apx-gpl.sgml
index e824478de7..bec3c1dbcf 100644
--- a/help/es/apx-gpl.sgml
+++ b/help/es/apx-gpl.sgml
@@ -1,4 +1,4 @@
-<!-- $Id: apx-gpl.sgml,v 1.2 2003/08/08 21:57:43 olea Exp $ -->
+<!-- $Id: apx-gpl.sgml,v 1.3 2003/10/21 18:51:25 ettore Exp $ -->
<!-- Este fichero no se traduce -->
<appendix id="apx-gpl" lang="en">
diff --git a/help/es/config-prefs.sgml b/help/es/config-prefs.sgml
index 76bb8c3426..051a3a63b6 100644
--- a/help/es/config-prefs.sgml
+++ b/help/es/config-prefs.sgml
@@ -1,5 +1,5 @@
-<!-- $Id: config-prefs.sgml,v 1.2 2003/08/08 21:57:43 olea Exp $ -->
+<!-- $Id: config-prefs.sgml,v 1.3 2003/10/21 18:51:25 ettore Exp $ -->
<!-- Traducción: Ismael -->
<!-- Revisión: -->
<chapter id="config-prefs">
diff --git a/help/es/config-sync.sgml b/help/es/config-sync.sgml
index 59304b2ba2..21ccde614f 100644
--- a/help/es/config-sync.sgml
+++ b/help/es/config-sync.sgml
@@ -1,4 +1,4 @@
-<!-- $Id: config-sync.sgml,v 1.2 2003/08/08 21:57:43 olea Exp $ -->
+<!-- $Id: config-sync.sgml,v 1.3 2003/10/21 18:51:25 ettore Exp $ -->
<!-- Traducción: irm 030501 -->
<!-- Revisión: ismael 030505 -->
diff --git a/help/es/evolution.sgml b/help/es/evolution.sgml
index 8e6253924c..382134c0df 100644
--- a/help/es/evolution.sgml
+++ b/help/es/evolution.sgml
@@ -1,6 +1,6 @@
-<!-- $Id: evolution.sgml,v 1.3 2003/08/08 21:57:43 olea Exp $ -->
+<!-- $Id: evolution.sgml,v 1.4 2003/10/21 18:51:25 ettore Exp $ -->
<!-- Traducción: Ismael -->
<!-- Revisión: irm 030504/final 030428/rápida -->
diff --git a/help/es/menuref.sgml b/help/es/menuref.sgml
index 1964887159..5d372fed2b 100644
--- a/help/es/menuref.sgml
+++ b/help/es/menuref.sgml
@@ -1,6 +1,6 @@
-<!-- $Id: menuref.sgml,v 1.2 2003/08/08 21:57:43 olea Exp $ -->
+<!-- $Id: menuref.sgml,v 1.3 2003/10/21 18:51:25 ettore Exp $ -->
<!-- Traducción: Ismael -->
<!-- Revisión: irm 030504/final 030428/rápida -->
diff --git a/help/es/preface.sgml b/help/es/preface.sgml
index fbb958d346..585a058581 100644
--- a/help/es/preface.sgml
+++ b/help/es/preface.sgml
@@ -1,6 +1,6 @@
-<!-- $Id: preface.sgml,v 1.3 2003/08/08 21:57:43 olea Exp $ -->
+<!-- $Id: preface.sgml,v 1.4 2003/10/21 18:51:25 ettore Exp $ -->
<!-- Traducción: Ismael -->
<!-- Revisión: irm 030504/final 030428/rápida -->
diff --git a/help/es/usage-calendar.sgml b/help/es/usage-calendar.sgml
index c1680973f0..72a772e65b 100644
--- a/help/es/usage-calendar.sgml
+++ b/help/es/usage-calendar.sgml
@@ -1,6 +1,6 @@
-<!-- $Id: usage-calendar.sgml,v 1.2 2003/08/08 21:57:43 olea Exp $ -->
+<!-- $Id: usage-calendar.sgml,v 1.3 2003/10/21 18:51:25 ettore Exp $ -->
<!-- Traducción: Ismael -->
<!-- Revisión: irm 030504/final 030428/rápida -->
diff --git a/help/es/usage-contact.sgml b/help/es/usage-contact.sgml
index 014323bc0a..c54d9f57c0 100644
--- a/help/es/usage-contact.sgml
+++ b/help/es/usage-contact.sgml
@@ -1,4 +1,4 @@
-<!-- $Id: usage-contact.sgml,v 1.2 2003/08/08 21:57:43 olea Exp $ -->
+<!-- $Id: usage-contact.sgml,v 1.3 2003/10/21 18:51:25 ettore Exp $ -->
<!-- Traducción: irm 030501 -->
<!-- Revisión: ismael 030501 -->
diff --git a/help/es/usage-exchange.sgml b/help/es/usage-exchange.sgml
index 79fd24eb1e..ac92bbf93f 100644
--- a/help/es/usage-exchange.sgml
+++ b/help/es/usage-exchange.sgml
@@ -1,4 +1,4 @@
-<!-- $Id: usage-exchange.sgml,v 1.2 2003/08/08 21:57:43 olea Exp $ -->
+<!-- $Id: usage-exchange.sgml,v 1.3 2003/10/21 18:51:25 ettore Exp $ -->
<!-- Traducción: irm 030501 -->
<!-- Revisión: ismael 030501 -->
diff --git a/help/es/usage-exec-summary.sgml b/help/es/usage-exec-summary.sgml
index 390b4da695..1aa771dd5e 100644
--- a/help/es/usage-exec-summary.sgml
+++ b/help/es/usage-exec-summary.sgml
@@ -1,6 +1,6 @@
-<!-- $Id: usage-exec-summary.sgml,v 1.2 2003/08/08 21:57:43 olea Exp $ -->
+<!-- $Id: usage-exec-summary.sgml,v 1.3 2003/10/21 18:51:26 ettore Exp $ -->
<!-- Traducción: Ismael -->
<!-- Revisión: irm 030504/final 030428/rápida -->
diff --git a/help/es/usage-mail-org.sgml b/help/es/usage-mail-org.sgml
index 9072eab5e4..55d5b078d0 100644
--- a/help/es/usage-mail-org.sgml
+++ b/help/es/usage-mail-org.sgml
@@ -1,4 +1,4 @@
-<!-- $Id: usage-mail-org.sgml,v 1.2 2003/08/08 21:57:43 olea Exp $ -->
+<!-- $Id: usage-mail-org.sgml,v 1.3 2003/10/21 18:51:26 ettore Exp $ -->
<!-- Traducción: irm -->
<!-- Revisión: -->
diff --git a/help/es/usage-mail.sgml b/help/es/usage-mail.sgml
index f4ec2068b3..7ad36e4eee 100644
--- a/help/es/usage-mail.sgml
+++ b/help/es/usage-mail.sgml
@@ -1,4 +1,4 @@
-<!-- $Id: usage-mail.sgml,v 1.2 2003/08/08 21:57:43 olea Exp $ -->
+<!-- $Id: usage-mail.sgml,v 1.3 2003/10/21 18:51:26 ettore Exp $ -->
<!-- Traducción: irm 030501 -->
<!-- Revisión: -->
diff --git a/help/es/usage-mainwindow.sgml b/help/es/usage-mainwindow.sgml
index d7bf49819c..35b582632c 100644
--- a/help/es/usage-mainwindow.sgml
+++ b/help/es/usage-mainwindow.sgml
@@ -1,6 +1,6 @@
-<!-- $Id: usage-mainwindow.sgml,v 1.2 2003/08/08 21:57:43 olea Exp $ -->
+<!-- $Id: usage-mainwindow.sgml,v 1.3 2003/10/21 18:51:26 ettore Exp $ -->
<!-- Traducción: Ismael -->
<!-- Revisión: irm 030504/final 030428/rápida -->
diff --git a/help/es/usage-print.sgml b/help/es/usage-print.sgml
index 8c6b04e35d..28e67b9551 100644
--- a/help/es/usage-print.sgml
+++ b/help/es/usage-print.sgml
@@ -1,4 +1,4 @@
-<!-- $Id: usage-print.sgml,v 1.2 2003/08/08 21:57:43 olea Exp $ -->
+<!-- $Id: usage-print.sgml,v 1.3 2003/10/21 18:51:26 ettore Exp $ -->
<!-- Traducción: ismael-->
<!-- Revisión: irm 030504/final 030428/rápida -->
diff --git a/help/es/usage-sync.sgml b/help/es/usage-sync.sgml
index 50c01ca875..de9da3dbcc 100644
--- a/help/es/usage-sync.sgml
+++ b/help/es/usage-sync.sgml
@@ -1,4 +1,4 @@
-<!-- $Id: usage-sync.sgml,v 1.2 2003/08/08 21:57:43 olea Exp $ -->
+<!-- $Id: usage-sync.sgml,v 1.3 2003/10/21 18:51:26 ettore Exp $ -->
<!-- Traducción: ismael -->
<!-- Revisión: -->
<chapter id="usage-sync">
diff --git a/libical/ChangeLog b/libical/ChangeLog
index c6d5919adc..d8655dd243 100644
--- a/libical/ChangeLog
+++ b/libical/ChangeLog
@@ -1,3 +1,9 @@
+2003-10-15 Rodrigo Moya <rodrigo@ximian.com>
+
+ * src/libicalss/icalssyacc.y: re-added missing header.
+
+ * src/libical/ical.h: added from HEAD.
+
2003-10-09 Jeffrey Stedfast <fejj@ximian.com>
* src/libical/Makefile.am: Fixed INCLUDES and don't autogenerate