aboutsummaryrefslogtreecommitdiffstats
path: root/calendar
diff options
context:
space:
mode:
authorMike Kestner <mkestner@ximian.com>2003-10-01 06:39:04 +0800
committerMike Kestner <mkestner@src.gnome.org>2003-10-01 06:39:04 +0800
commit54869d90bd04f0a816b1786530d3555ac2b034cc (patch)
tree3b2859280d478fa6b57227a419125eadd455a615 /calendar
parent642e0e5abd8486793e95fab56e9fd9f3dd0394f8 (diff)
downloadgsoc2013-evolution-54869d90bd04f0a816b1786530d3555ac2b034cc.tar
gsoc2013-evolution-54869d90bd04f0a816b1786530d3555ac2b034cc.tar.gz
gsoc2013-evolution-54869d90bd04f0a816b1786530d3555ac2b034cc.tar.bz2
gsoc2013-evolution-54869d90bd04f0a816b1786530d3555ac2b034cc.tar.lz
gsoc2013-evolution-54869d90bd04f0a816b1786530d3555ac2b034cc.tar.xz
gsoc2013-evolution-54869d90bd04f0a816b1786530d3555ac2b034cc.tar.zst
gsoc2013-evolution-54869d90bd04f0a816b1786530d3555ac2b034cc.zip
new VOID:STRING,STRING,STRING build the new view/store/renderer/editable
2003-09-30 Mike Kestner <mkestner@ximian.com> * cal-util/cal-util-marshal.list : new VOID:STRING,STRING,STRING * gui/Makefile.am : build the new view/store/renderer/editable * gui/e-select-names-renderer.* : new completion cell renderer * gui/e-select-names-editable.* : new completion cell editable * gui/e-meeting-model.* : killed. code reused in list-view/store * gui/e-meeting-store.* : port of EMeetingModel to GtkTreeModel * gui/e-meeting-list-view.* : GtkTreeView subclass for attendee lists * gui/e-meeting-time-sel.c : Use the new store/view * gui/e-meeting-time-sel-item.c : Use the new store/view * gui/dialogs/Makefile.am : don't install the etspec anymore. * gui/dialogs/event-editor.c : Use the new store/view. * gui/dialogs/meeting-page.c : Use the new store/view. * gui/dialogs/shedule-page.c : Use the new store/view. * gui/dialogs/task-editor.c : Use the new store/view. svn path=/trunk/; revision=22774
Diffstat (limited to 'calendar')
-rw-r--r--calendar/ChangeLog17
-rw-r--r--calendar/cal-util/cal-util-marshal.list1
-rw-r--r--calendar/gui/Makefile.am10
-rw-r--r--calendar/gui/dialogs/Makefile.am5
-rw-r--r--calendar/gui/dialogs/event-editor.c62
-rw-r--r--calendar/gui/dialogs/meeting-page.c182
-rw-r--r--calendar/gui/dialogs/meeting-page.etspec21
-rw-r--r--calendar/gui/dialogs/meeting-page.h6
-rw-r--r--calendar/gui/dialogs/schedule-page.c18
-rw-r--r--calendar/gui/dialogs/schedule-page.h6
-rw-r--r--calendar/gui/dialogs/task-editor.c58
-rw-r--r--calendar/gui/e-meeting-list-view.c483
-rw-r--r--calendar/gui/e-meeting-list-view.h62
-rw-r--r--calendar/gui/e-meeting-model.c1788
-rw-r--r--calendar/gui/e-meeting-model.h116
-rw-r--r--calendar/gui/e-meeting-store.c1317
-rw-r--r--calendar/gui/e-meeting-store.h108
-rw-r--r--calendar/gui/e-meeting-time-sel-item.c42
-rw-r--r--calendar/gui/e-meeting-time-sel.c149
-rw-r--r--calendar/gui/e-meeting-time-sel.h20
-rw-r--r--calendar/gui/e-select-names-editable.c228
-rw-r--r--calendar/gui/e-select-names-editable.h64
-rw-r--r--calendar/gui/e-select-names-renderer.c176
-rw-r--r--calendar/gui/e-select-names-renderer.h63
24 files changed, 2712 insertions, 2290 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index 567639adda..20ac5c32b1 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,3 +1,20 @@
+2003-09-30 Mike Kestner <mkestner@ximian.com>
+
+ * cal-util/cal-util-marshal.list : new VOID:STRING,STRING,STRING
+ * gui/Makefile.am : build the new view/store/renderer/editable
+ * gui/e-select-names-renderer.* : new completion cell renderer
+ * gui/e-select-names-editable.* : new completion cell editable
+ * gui/e-meeting-model.* : killed. code reused in list-view/store
+ * gui/e-meeting-store.* : port of EMeetingModel to GtkTreeModel
+ * gui/e-meeting-list-view.* : GtkTreeView subclass for attendee lists
+ * gui/e-meeting-time-sel.c : Use the new store/view
+ * gui/e-meeting-time-sel-item.c : Use the new store/view
+ * gui/dialogs/Makefile.am : don't install the etspec anymore.
+ * gui/dialogs/event-editor.c : Use the new store/view.
+ * gui/dialogs/meeting-page.c : Use the new store/view.
+ * gui/dialogs/shedule-page.c : Use the new store/view.
+ * gui/dialogs/task-editor.c : Use the new store/view.
+
2003-09-29 JP Rosevear <jpr@ximian.com>
* conduits/todo/Makefile.am: link to libical-evolution
diff --git a/calendar/cal-util/cal-util-marshal.list b/calendar/cal-util/cal-util-marshal.list
index 7c58793852..77509b1c50 100644
--- a/calendar/cal-util/cal-util-marshal.list
+++ b/calendar/cal-util/cal-util-marshal.list
@@ -3,6 +3,7 @@ NONE:ENUM,ENUM
NONE:ENUM,STRING
NONE:STRING,BOOL,INT,INT
NONE:STRING,STRING
+NONE:STRING,STRING,STRING
NONE:POINTER,ENUM
NONE:POINTER,STRING
NONE:POINTER,POINTER
diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am
index 5cee4ae0e3..553186d85c 100644
--- a/calendar/gui/Makefile.am
+++ b/calendar/gui/Makefile.am
@@ -127,8 +127,10 @@ libevolution_calendar_la_SOURCES = \
e-itip-control.c \
e-meeting-attendee.c \
e-meeting-attendee.h \
- e-meeting-model.c \
- e-meeting-model.h \
+ e-meeting-list-view.c \
+ e-meeting-list-view.h \
+ e-meeting-store.c \
+ e-meeting-store.h \
e-meeting-time-sel.c \
e-meeting-time-sel.h \
e-meeting-time-sel-item.c \
@@ -136,6 +138,10 @@ libevolution_calendar_la_SOURCES = \
e-meeting-types.h \
e-meeting-utils.c \
e-meeting-utils.h \
+ e-select-names-editable.c \
+ e-select-names-editable.h \
+ e-select-names-renderer.c \
+ e-select-names-renderer.h \
e-week-view-event-item.c \
e-week-view-event-item.h \
e-week-view-layout.c \
diff --git a/calendar/gui/dialogs/Makefile.am b/calendar/gui/dialogs/Makefile.am
index 4bbdd90ca5..e6067d4d23 100644
--- a/calendar/gui/dialogs/Makefile.am
+++ b/calendar/gui/dialogs/Makefile.am
@@ -26,7 +26,6 @@ INCLUDES = \
-DEVOLUTION_DATADIR=\""$(datadir)"\" \
-DEVOLUTION_GLADEDIR=\""$(gladedir)"\" \
-DEVOLUTION_IMAGESDIR=\""$(imagesdir)"\" \
- -DEVOLUTION_ETSPECDIR=\""$(etspecdir)"\" \
-DEVOLUTION_UIDIR=\""$(evolutionuidir)"\" \
-DPREFIX=\""$(prefix)"\" \
$(EVOLUTION_CALENDAR_CFLAGS)
@@ -92,7 +91,6 @@ glade_DATA = \
task-details-page.glade \
task-page.glade
-etspec_DATA = meeting-page.etspec
CLEANFILES = $(BUILT_SOURCES)
@@ -100,5 +98,4 @@ dist-hook:
cd $(distdir); rm -f $(BUILT_SOURCES)
EXTRA_DIST = \
- $(glade_DATA) \
- $(etspec_DATA)
+ $(glade_DATA)
diff --git a/calendar/gui/dialogs/event-editor.c b/calendar/gui/dialogs/event-editor.c
index a67f2b14f9..978a2dbb22 100644
--- a/calendar/gui/dialogs/event-editor.c
+++ b/calendar/gui/dialogs/event-editor.c
@@ -26,6 +26,7 @@
#include <config.h>
#include <string.h>
#include <glade/glade.h>
+#include <gal/util/e-util.h>
#include <gal/widgets/e-unicode.h>
#include <libgnome/gnome-i18n.h>
#include <widgets/misc/e-dateedit.h>
@@ -45,7 +46,7 @@ struct _EventEditorPrivate {
MeetingPage *meet_page;
SchedulePage *sched_page;
- EMeetingModel *model;
+ EMeetingStore *model;
gboolean meeting_shown;
gboolean updating;
@@ -65,8 +66,8 @@ static void refresh_meeting_cmd (GtkWidget *widget, gpointer data);
static void cancel_meeting_cmd (GtkWidget *widget, gpointer data);
static void forward_cmd (GtkWidget *widget, gpointer data);
-static void model_row_changed_cb (ETableModel *etm, int row, gpointer data);
-static void row_count_changed_cb (ETableModel *etm, int row, int count, gpointer data);
+static void model_row_change_insert_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data);
+static void model_row_delete_cb (GtkTreeModel *model, GtkTreePath *path, gpointer data);
static EPixmap pixmaps [] = {
E_PIXMAP ("/Toolbar/Actions/ActionScheduleMeeting", "schedule-meeting-24.png"),
@@ -162,12 +163,12 @@ init_widgets (EventEditor *ee)
priv = ee->priv;
- g_signal_connect((priv->model), "model_row_changed",
- G_CALLBACK (model_row_changed_cb), ee);
- g_signal_connect((priv->model), "model_rows_inserted",
- G_CALLBACK (row_count_changed_cb), ee);
- g_signal_connect((priv->model), "model_rows_deleted",
- G_CALLBACK (row_count_changed_cb), ee);
+ g_signal_connect((priv->model), "row_changed",
+ G_CALLBACK (model_row_change_insert_cb), ee);
+ g_signal_connect((priv->model), "row_inserted",
+ G_CALLBACK (model_row_change_insert_cb), ee);
+ g_signal_connect((priv->model), "row_deleted",
+ G_CALLBACK (model_row_delete_cb), ee);
}
/* Object initialization function for the event editor */
@@ -179,7 +180,7 @@ event_editor_init (EventEditor *ee)
priv = g_new0 (EventEditorPrivate, 1);
ee->priv = priv;
- priv->model = E_MEETING_MODEL (e_meeting_model_new ());
+ priv->model = E_MEETING_STORE (e_meeting_store_new ());
priv->meeting_shown = TRUE;
priv->updating = FALSE;
}
@@ -232,6 +233,7 @@ event_editor_construct (EventEditor *ee, CalClient *client)
init_widgets (ee);
set_menu_sens (ee);
+ gtk_window_set_default_size (GTK_WINDOW (ee), 300, 225);
return ee;
}
@@ -245,7 +247,7 @@ event_editor_set_cal_client (CompEditor *editor, CalClient *client)
ee = EVENT_EDITOR (editor);
priv = ee->priv;
- e_meeting_model_set_cal_client (priv->model, client);
+ e_meeting_store_set_cal_client (priv->model, client);
if (parent_class->set_cal_client)
parent_class->set_cal_client (editor, client);
@@ -275,7 +277,7 @@ event_editor_edit_comp (CompEditor *editor, CalComponent *comp)
cal_component_get_attendee_list (comp, &attendees);
/* Clear things up */
- e_meeting_model_remove_all_attendees (priv->model);
+ e_meeting_store_remove_all_attendees (priv->model);
/* Set up the attendees */
if (attendees == NULL) {
@@ -304,7 +306,7 @@ event_editor_edit_comp (CompEditor *editor, CalComponent *comp)
/* If we aren't the organizer or the attendee is just delegating, don't allow editing */
if (!comp_editor_get_user_org (editor) || e_meeting_attendee_is_set_delto (ia))
e_meeting_attendee_set_edit_level (ia, E_MEETING_ATTENDEE_EDIT_NONE);
- e_meeting_model_add_attendee (priv->model, ia);
+ e_meeting_store_add_attendee (priv->model, ia);
g_object_unref(ia);
}
@@ -321,7 +323,7 @@ event_editor_edit_comp (CompEditor *editor, CalComponent *comp)
account = (EAccount*)e_iterator_get(it);
- ia = e_meeting_model_find_attendee (priv->model, account->id->address, &row);
+ ia = e_meeting_store_find_attendee (priv->model, account->id->address, &row);
if (ia != NULL)
e_meeting_attendee_set_edit_level (ia, E_MEETING_ATTENDEE_EDIT_STATUS);
}
@@ -329,7 +331,7 @@ event_editor_edit_comp (CompEditor *editor, CalComponent *comp)
} else if (cal_client_get_organizer_must_attend (client)) {
EMeetingAttendee *ia;
- ia = e_meeting_model_find_attendee (priv->model, organizer.value, &row);
+ ia = e_meeting_store_find_attendee (priv->model, organizer.value, &row);
if (ia != NULL)
e_meeting_attendee_set_edit_level (ia, E_MEETING_ATTENDEE_EDIT_NONE);
}
@@ -363,7 +365,7 @@ event_editor_send_comp (CompEditor *editor, CalComponentItipMethod method)
CalClient *client;
gboolean result;
- client = e_meeting_model_get_cal_client (priv->model);
+ client = e_meeting_store_get_cal_client (priv->model);
result = itip_send_comp (CAL_COMPONENT_METHOD_CANCEL, comp, client, NULL);
g_object_unref((comp));
@@ -498,29 +500,23 @@ forward_cmd (GtkWidget *widget, gpointer data)
}
static void
-model_row_changed_cb (ETableModel *etm, int row, gpointer data)
+model_changed (EventEditor *ee)
{
- EventEditor *ee = EVENT_EDITOR (data);
- EventEditorPrivate *priv;
-
- priv = ee->priv;
-
- if (!priv->updating) {
+ if (!ee->priv->updating) {
comp_editor_set_changed (COMP_EDITOR (ee), TRUE);
comp_editor_set_needs_send (COMP_EDITOR (ee), TRUE);
}
}
static void
-row_count_changed_cb (ETableModel *etm, int row, int count, gpointer data)
+model_row_change_insert_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
{
- EventEditor *ee = EVENT_EDITOR (data);
- EventEditorPrivate *priv;
-
- priv = ee->priv;
-
- if (!priv->updating) {
- comp_editor_set_changed (COMP_EDITOR (ee), TRUE);
- comp_editor_set_needs_send (COMP_EDITOR (ee), TRUE);
- }
+ model_changed (EVENT_EDITOR (data));
}
+
+static void
+model_row_delete_cb (GtkTreeModel *model, GtkTreePath *path, gpointer data)
+{
+ model_changed (EVENT_EDITOR (data));
+}
+
diff --git a/calendar/gui/dialogs/meeting-page.c b/calendar/gui/dialogs/meeting-page.c
index e603978520..6c8212e93c 100644
--- a/calendar/gui/dialogs/meeting-page.c
+++ b/calendar/gui/dialogs/meeting-page.c
@@ -34,10 +34,7 @@
#include <libgnome/gnome-i18n.h>
#include <glade/glade.h>
#include <libgnomeui/gnome-stock-icons.h>
-#include <gal/e-table/e-cell-combo.h>
-#include <gal/e-table/e-cell-text.h>
-#include <gal/e-table/e-table-simple.h>
-#include <gal/e-table/e-table-scrolled.h>
+#include <gal/util/e-util.h>
#include <gal/widgets/e-unicode.h>
#include <gal/widgets/e-popup-menu.h>
#include <gal/widgets/e-gui-utils.h>
@@ -47,27 +44,13 @@
#include "../calendar-component.h"
#include "../e-meeting-attendee.h"
-#include "../e-meeting-model.h"
+#include "../e-meeting-store.h"
+#include "../e-meeting-list-view.h"
#include "../itip-utils.h"
#include "comp-editor-util.h"
#include "e-delegate-dialog.h"
#include "meeting-page.h"
-
-
-enum columns {
- MEETING_ATTENDEE_COL,
- MEETING_MEMBER_COL,
- MEETING_TYPE_COL,
- MEETING_ROLE_COL,
- MEETING_RSVP_COL,
- MEETING_DELTO_COL,
- MEETING_DELFROM_COL,
- MEETING_STATUS_COL,
- MEETING_CN_COL,
- MEETING_LANG_COL,
- MEETING_COLUMN_COUNT
-};
/* Private part of the MeetingPage structure */
struct _MeetingPagePrivate {
@@ -94,9 +77,9 @@ struct _MeetingPagePrivate {
GtkWidget *existing_organizer_btn;
GtkWidget *invite;
- /* E Table stuff */
- EMeetingModel *model;
- ETableScrolled *etable;
+ /* ListView stuff */
+ EMeetingStore *model;
+ EMeetingListView *list_view;
gint row;
/* For handling who the organizer is */
@@ -116,8 +99,6 @@ static void meeting_page_focus_main_widget (CompEditorPage *page);
static void meeting_page_fill_widgets (CompEditorPage *page, CalComponent *comp);
static gboolean meeting_page_fill_component (CompEditorPage *page, CalComponent *comp);
-static gint right_click_cb (ETable *etable, gint row, gint col, GdkEvent *event, gpointer data);
-
static CompEditorPageClass *parent_class = NULL;
@@ -178,7 +159,7 @@ meeting_page_init (MeetingPage *mpage)
priv->invite = NULL;
priv->model = NULL;
- priv->etable = NULL;
+ priv->list_view = NULL;
priv->updating = FALSE;
}
@@ -377,14 +358,12 @@ meeting_page_fill_widgets (CompEditorPage *page, CalComponent *comp)
page->client,
CAL_STATIC_CAPABILITY_ORGANIZER_NOT_EMAIL_ADDRESS))
gtk_widget_hide (priv->existing_organizer_btn);
- e_meeting_model_etable_click_to_add (priv->model, TRUE);
} else {
if (cal_client_get_static_capability (
page->client,
CAL_STATIC_CAPABILITY_ORGANIZER_NOT_EMAIL_ADDRESS))
gtk_widget_hide (priv->existing_organizer_btn);
gtk_widget_hide (priv->invite);
- e_meeting_model_etable_click_to_add (priv->model, FALSE);
}
if (organizer.cn != NULL)
@@ -401,7 +380,7 @@ meeting_page_fill_widgets (CompEditorPage *page, CalComponent *comp)
a = get_current_account (mpage);
if (a != NULL) {
- priv->ia = e_meeting_model_add_attendee_with_defaults (priv->model);
+ priv->ia = e_meeting_store_add_attendee_with_defaults (priv->model);
g_object_ref (priv->ia);
e_meeting_attendee_set_address (priv->ia, g_strdup_printf ("MAILTO:%s", a->id->address));
@@ -453,12 +432,12 @@ meeting_page_fill_component (CompEditorPage *page, CalComponent *comp)
g_free (addr);
}
- if (e_meeting_model_count_actual_attendees (priv->model) < 1) {
+ if (e_meeting_store_count_actual_attendees (priv->model) < 1) {
e_notice (page, GTK_MESSAGE_ERROR,
_("At least one attendee is required."));
return FALSE;
}
- set_attendees (comp, e_meeting_model_get_attendees (priv->model));
+ set_attendees (comp, e_meeting_store_get_attendees (priv->model));
return TRUE;
}
@@ -535,10 +514,10 @@ org_changed_cb (GtkWidget *widget, gpointer data)
e_meeting_attendee_set_address (priv->ia, g_strdup_printf ("MAILTO:%s", a->id->address));
e_meeting_attendee_set_cn (priv->ia, g_strdup (a->id->name));
- if (!e_meeting_model_find_attendee (priv->model, e_meeting_attendee_get_address (priv->ia), NULL))
- e_meeting_model_add_attendee (priv->model, priv->ia);
+ if (!e_meeting_store_find_attendee (priv->model, e_meeting_attendee_get_address (priv->ia), NULL))
+ e_meeting_store_add_attendee (priv->model, priv->ia);
} else {
- e_meeting_model_remove_attendee (priv->model, priv->ia);
+ e_meeting_store_remove_attendee (priv->model, priv->ia);
}
}
@@ -558,7 +537,6 @@ change_clicked_cb (GtkWidget *widget, gpointer data)
gtk_widget_show (priv->organizer_table);
gtk_widget_hide (priv->existing_organizer_table);
gtk_widget_show (priv->invite);
- e_meeting_model_etable_click_to_add (priv->model, TRUE);
comp_editor_page_notify_needs_send (COMP_EDITOR_PAGE (mpage));
@@ -575,7 +553,7 @@ invite_cb (GtkWidget *widget, gpointer data)
mpage = MEETING_PAGE (data);
priv = mpage->priv;
- e_meeting_model_invite_others_dialog (priv->model);
+ e_meeting_list_view_invite_others_dialog (priv->list_view);
}
/* Hooks the widget signals */
@@ -598,67 +576,6 @@ init_widgets (MeetingPage *mpage)
G_CALLBACK (invite_cb), mpage);
}
-#if 0
-static void
-popup_delegate_cb (GtkWidget *widget, gpointer data)
-{
- MeetingPage *mpage = MEETING_PAGE (data);
- MeetingPagePrivate *priv;
- EDelegateDialog *edd;
- GtkWidget *dialog;
- EMeetingAttendee *ia;
- char *address = NULL, *name = NULL;
-
- priv = mpage->priv;
-
- ia = e_meeting_model_find_attendee_at_row (priv->model, priv->row);
-
- /* Show dialog. */
- edd = e_delegate_dialog_new (NULL, itip_strip_mailto (e_meeting_attendee_get_delto (ia)));
- dialog = e_delegate_dialog_get_toplevel (edd);
-
- if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK){
- EMeetingAttendee *ic;
-
- name = e_delegate_dialog_get_delegate_name (edd);
- address = e_delegate_dialog_get_delegate (edd);
-
- /* Make sure we can add the new delegatee person */
- if (e_meeting_model_find_attendee (priv->model, address, NULL) != NULL) {
- e_notice (mpage, GTK_MESSAGE_ERROR,
- _("That person is already attending the meeting!"));
- goto cleanup;
- }
-
- /* Update information for attendee */
- if (e_meeting_attendee_is_set_delto (ia)) {
- EMeetingAttendee *ib;
-
- ib = e_meeting_model_find_attendee (priv->model, itip_strip_mailto (e_meeting_attendee_get_delto (ia)), NULL);
- if (ib != NULL) {
- g_object_ref((ib));
- g_ptr_array_add (priv->deleted_attendees, ib);
-
- e_meeting_model_remove_attendee (priv->model, ib);
- }
- }
- e_meeting_attendee_set_delto (ia, g_strdup_printf ("MAILTO:%s", address));
-
- /* Construct delegatee information */
- ic = e_meeting_model_add_attendee_with_defaults (priv->model);
-
- e_meeting_attendee_set_address (ic, g_strdup_printf ("MAILTO:%s", address));
- e_meeting_attendee_set_delfrom (ic, g_strdup (e_meeting_attendee_get_address (ia)));
- e_meeting_attendee_set_cn (ic, g_strdup (name));
- }
-
- cleanup:
- g_free (name);
- g_free (address);
- g_object_unref((edd));
-}
-#endif
-
static void
popup_delete_cb (GtkWidget *widget, gpointer data)
{
@@ -669,7 +586,7 @@ popup_delete_cb (GtkWidget *widget, gpointer data)
priv = mpage->priv;
- ia = e_meeting_model_find_attendee_at_row (priv->model, priv->row);
+ ia = e_meeting_store_find_attendee_at_row (priv->model, priv->row);
/* If the user deletes the attendee explicitly, assume they no
longer want the organizer showing up */
@@ -682,7 +599,7 @@ popup_delete_cb (GtkWidget *widget, gpointer data)
if (e_meeting_attendee_is_set_delfrom (ia)) {
EMeetingAttendee *ib;
- ib = e_meeting_model_find_attendee (priv->model, e_meeting_attendee_get_delfrom (ia), &pos);
+ ib = e_meeting_store_find_attendee (priv->model, e_meeting_attendee_get_delfrom (ia), &pos);
if (ib != NULL) {
e_meeting_attendee_set_delto (ib, NULL);
e_meeting_attendee_set_edit_level (ib, E_MEETING_ATTENDEE_EDIT_FULL);
@@ -695,10 +612,10 @@ popup_delete_cb (GtkWidget *widget, gpointer data)
g_object_ref((ia));
g_ptr_array_add (priv->deleted_attendees, ia);
- e_meeting_model_remove_attendee (priv->model, ia);
+ e_meeting_store_remove_attendee (priv->model, ia);
if (e_meeting_attendee_get_delto (ia) != NULL)
- ib = e_meeting_model_find_attendee (priv->model, e_meeting_attendee_get_delto (ia), NULL);
+ ib = e_meeting_store_find_attendee (priv->model, e_meeting_attendee_get_delto (ia), NULL);
ia = ib;
}
}
@@ -719,6 +636,8 @@ static EPopupMenu context_menu[] = {
E_POPUP_TERMINATOR
};
+#if 0
+/* FIXME: handle context menu for treeview */
/* handle context menu over message-list */
static gint
right_click_cb (ETable *etable, gint row, gint col, GdkEvent *event, gpointer data)
@@ -752,26 +671,12 @@ right_click_cb (ETable *etable, gint row, gint col, GdkEvent *event, gpointer da
return TRUE;
}
-
+#endif
-
-/* Callback used when the ETable gets a focus-out event. We have to commit any
- * pending click-to-add state for if the event editor is being destroyed.
- */
-static gint
-table_canvas_focus_out_cb (GtkWidget *widget, GdkEventFocus *event, gpointer data)
+static void
+add_btn_clicked_cb (GtkButton *btn, MeetingPage *mpage)
{
- MeetingPage *mpage;
- MeetingPagePrivate *priv;
- ETable *etable;
-
- mpage = MEETING_PAGE (data);
- priv = mpage->priv;
-
- etable = e_table_scrolled_get_table (priv->etable);
-
- e_table_commit_click_to_add (etable);
- return TRUE;
+ e_meeting_store_add_attendee_with_defaults (mpage->priv->model);
}
/**
@@ -784,16 +689,15 @@ table_canvas_focus_out_cb (GtkWidget *widget, GdkEventFocus *event, gpointer dat
* be created.
**/
MeetingPage *
-meeting_page_construct (MeetingPage *mpage, EMeetingModel *emm,
+meeting_page_construct (MeetingPage *mpage, EMeetingStore *ems,
CalClient *client)
{
MeetingPagePrivate *priv;
- ETable *real_table;
- gchar *filename;
const char *backend_address;
EIterator *it;
EAccount *def_account;
GList *address_strings = NULL, *l;
+ GtkWidget *sw, *btn;
priv = mpage->priv;
@@ -849,25 +753,27 @@ meeting_page_construct (MeetingPage *mpage, EMeetingModel *emm,
g_free (l->data);
g_list_free (address_strings);
- /* The etable displaying attendees and their status */
- g_object_ref((emm));
- priv->model = emm;
+ g_object_ref((ems));
+ priv->model = ems;
+
+ btn = gtk_button_new_with_label ("Add Attendee");
+ g_signal_connect(btn, "clicked", G_CALLBACK (add_btn_clicked_cb), mpage);
+ gtk_widget_show (btn);
+ gtk_box_pack_start (GTK_BOX (priv->main), btn, FALSE, FALSE, 6);
- filename = g_strdup_printf ("%s/config/et-header-meeting-page", evolution_dir);
- priv->etable = e_meeting_model_etable_from_model (priv->model,
- EVOLUTION_ETSPECDIR "/meeting-page.etspec",
- filename);
- g_free (filename);
+ priv->list_view = e_meeting_list_view_new (priv->model);
- real_table = e_table_scrolled_get_table (priv->etable);
+#if 0
+ /* FIXME: handle context menu for treeview */
g_signal_connect((real_table),
"right_click", G_CALLBACK (right_click_cb), mpage);
+#endif
- g_signal_connect((real_table->table_canvas), "focus_out_event",
- G_CALLBACK (table_canvas_focus_out_cb), mpage);
-
- gtk_widget_show (GTK_WIDGET (priv->etable));
- gtk_box_pack_start (GTK_BOX (priv->main), GTK_WIDGET (priv->etable), TRUE, TRUE, 6);
+ gtk_widget_show (GTK_WIDGET (priv->list_view));
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_show (sw);
+ gtk_container_add (GTK_CONTAINER (sw), GTK_WIDGET (priv->list_view));
+ gtk_box_pack_start (GTK_BOX (priv->main), sw, TRUE, TRUE, 6);
/* Init the widget signals */
init_widgets (mpage);
@@ -884,12 +790,12 @@ meeting_page_construct (MeetingPage *mpage, EMeetingModel *emm,
* not be created.
**/
MeetingPage *
-meeting_page_new (EMeetingModel *emm, CalClient *client)
+meeting_page_new (EMeetingStore *ems, CalClient *client)
{
MeetingPage *mpage;
mpage = g_object_new (TYPE_MEETING_PAGE, NULL);
- if (!meeting_page_construct (mpage, emm, client)) {
+ if (!meeting_page_construct (mpage, ems, client)) {
g_object_unref((mpage));
return NULL;
}
diff --git a/calendar/gui/dialogs/meeting-page.etspec b/calendar/gui/dialogs/meeting-page.etspec
deleted file mode 100644
index 96bc480fe9..0000000000
--- a/calendar/gui/dialogs/meeting-page.etspec
+++ /dev/null
@@ -1,21 +0,0 @@
-<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/meeting-page.h b/calendar/gui/dialogs/meeting-page.h
index 2a209b586b..5891189810 100644
--- a/calendar/gui/dialogs/meeting-page.h
+++ b/calendar/gui/dialogs/meeting-page.h
@@ -24,7 +24,7 @@
#ifndef MEETING_PAGE_H
#define MEETING_PAGE_H
-#include "../e-meeting-model.h"
+#include "../e-meeting-store.h"
#include "../itip-utils.h"
#include "comp-editor-page.h"
@@ -54,9 +54,9 @@ typedef struct {
GtkType meeting_page_get_type (void);
MeetingPage *meeting_page_construct (MeetingPage *mpage,
- EMeetingModel *emm,
+ EMeetingStore *ems,
CalClient *client);
-MeetingPage *meeting_page_new (EMeetingModel *emm,
+MeetingPage *meeting_page_new (EMeetingStore *ems,
CalClient *client);
CalComponent *meeting_page_get_cancel_comp (MeetingPage *mpage);
diff --git a/calendar/gui/dialogs/schedule-page.c b/calendar/gui/dialogs/schedule-page.c
index 2163d51f1e..8cad77360b 100644
--- a/calendar/gui/dialogs/schedule-page.c
+++ b/calendar/gui/dialogs/schedule-page.c
@@ -60,7 +60,7 @@ struct _SchedulePagePrivate {
GtkWidget *main;
/* Model */
- EMeetingModel *model;
+ EMeetingStore *model;
/* Selector */
EMeetingTimeSelector *sel;
@@ -164,7 +164,7 @@ schedule_page_finalize (GObject *object)
priv->xml = NULL;
}
- g_object_unref((priv->model));
+ g_object_unref(priv->model);
g_free (priv);
spage->priv = NULL;
@@ -251,7 +251,7 @@ update_time (SchedulePage *spage, CalComponentDateTime *start_date, CalComponent
if (start_zone != end_zone) {
icaltimezone_convert_time (&end_tt, end_zone, start_zone);
}
- e_meeting_model_set_zone (priv->model, priv->zone);
+ e_meeting_store_set_zone (priv->model, priv->zone);
all_day = (start_tt.is_date && end_tt.is_date) ? TRUE : FALSE;
@@ -405,7 +405,7 @@ init_widgets (SchedulePage *spage)
* be created.
**/
SchedulePage *
-schedule_page_construct (SchedulePage *spage, EMeetingModel *emm)
+schedule_page_construct (SchedulePage *spage, EMeetingStore *ems)
{
SchedulePagePrivate *priv;
@@ -426,11 +426,11 @@ schedule_page_construct (SchedulePage *spage, EMeetingModel *emm)
}
/* Model */
- g_object_ref((emm));
- priv->model = emm;
+ g_object_ref (ems);
+ priv->model = ems;
/* Selector */
- priv->sel = E_MEETING_TIME_SELECTOR (e_meeting_time_selector_new (emm));
+ priv->sel = E_MEETING_TIME_SELECTOR (e_meeting_time_selector_new (ems));
e_meeting_time_selector_set_working_hours (priv->sel,
calendar_config_get_day_start_hour (),
calendar_config_get_day_start_minute (),
@@ -457,12 +457,12 @@ schedule_page_construct (SchedulePage *spage, EMeetingModel *emm)
* not be created.
**/
SchedulePage *
-schedule_page_new (EMeetingModel *emm)
+schedule_page_new (EMeetingStore *ems)
{
SchedulePage *spage;
spage = g_object_new (TYPE_SCHEDULE_PAGE, NULL);
- if (!schedule_page_construct (spage, emm)) {
+ if (!schedule_page_construct (spage, ems)) {
g_object_unref((spage));
return NULL;
}
diff --git a/calendar/gui/dialogs/schedule-page.h b/calendar/gui/dialogs/schedule-page.h
index 42745962cd..d4c7eafbdd 100644
--- a/calendar/gui/dialogs/schedule-page.h
+++ b/calendar/gui/dialogs/schedule-page.h
@@ -21,7 +21,7 @@
#ifndef SCHEDULE_PAGE_H
#define SCHEDULE_PAGE_H
-#include "../e-meeting-model.h"
+#include "../e-meeting-store.h"
#include "comp-editor-page.h"
G_BEGIN_DECLS
@@ -49,8 +49,8 @@ typedef struct {
GtkType schedule_page_get_type (void);
-SchedulePage *schedule_page_construct (SchedulePage *mpage, EMeetingModel *emm);
-SchedulePage *schedule_page_new (EMeetingModel *emm);
+SchedulePage *schedule_page_construct (SchedulePage *mpage, EMeetingStore *ems);
+SchedulePage *schedule_page_new (EMeetingStore *ems);
diff --git a/calendar/gui/dialogs/task-editor.c b/calendar/gui/dialogs/task-editor.c
index eaf4c2eaca..4ef971fe85 100644
--- a/calendar/gui/dialogs/task-editor.c
+++ b/calendar/gui/dialogs/task-editor.c
@@ -26,6 +26,7 @@
#include <config.h>
#include <string.h>
#include <glade/glade.h>
+#include <gal/util/e-util.h>
#include <gal/widgets/e-unicode.h>
#include <libgnome/gnome-i18n.h>
@@ -40,7 +41,7 @@ struct _TaskEditorPrivate {
TaskDetailsPage *task_details_page;
MeetingPage *meet_page;
- EMeetingModel *model;
+ EMeetingStore *model;
gboolean assignment_shown;
gboolean updating;
@@ -60,8 +61,8 @@ static void refresh_task_cmd (GtkWidget *widget, gpointer data);
static void cancel_task_cmd (GtkWidget *widget, gpointer data);
static void forward_cmd (GtkWidget *widget, gpointer data);
-static void model_row_changed_cb (ETableModel *etm, int row, gpointer data);
-static void row_count_changed_cb (ETableModel *etm, int row, int count, gpointer data);
+static void model_row_change_insert_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data);
+static void model_row_delete_cb (GtkTreeModel *model, GtkTreePath *path, gpointer data);
static BonoboUIVerb verbs [] = {
BONOBO_UI_UNSAFE_VERB ("ActionAssignTask", assign_task_cmd),
@@ -154,12 +155,12 @@ init_widgets (TaskEditor *te)
priv = te->priv;
- g_signal_connect((priv->model), "model_row_changed",
- G_CALLBACK (model_row_changed_cb), te);
- g_signal_connect((priv->model), "model_rows_inserted",
- G_CALLBACK (row_count_changed_cb), te);
- g_signal_connect((priv->model), "model_rows_deleted",
- G_CALLBACK (row_count_changed_cb), te);
+ g_signal_connect((priv->model), "row_changed",
+ G_CALLBACK (model_row_change_insert_cb), te);
+ g_signal_connect((priv->model), "row_inserted",
+ G_CALLBACK (model_row_change_insert_cb), te);
+ g_signal_connect((priv->model), "row_deleted",
+ G_CALLBACK (model_row_delete_cb), te);
}
/* Object initialization function for the task editor */
@@ -171,7 +172,7 @@ task_editor_init (TaskEditor *te)
priv = g_new0 (TaskEditorPrivate, 1);
te->priv = priv;
- priv->model = E_MEETING_MODEL (e_meeting_model_new ());
+ priv->model = E_MEETING_STORE (e_meeting_store_new ());
priv->assignment_shown = TRUE;
priv->updating = FALSE;
@@ -224,7 +225,7 @@ task_editor_set_cal_client (CompEditor *editor, CalClient *client)
te = TASK_EDITOR (editor);
priv = te->priv;
- e_meeting_model_set_cal_client (priv->model, client);
+ e_meeting_store_set_cal_client (priv->model, client);
if (parent_class->set_cal_client)
parent_class->set_cal_client (editor, client);
@@ -254,7 +255,7 @@ task_editor_edit_comp (CompEditor *editor, CalComponent *comp)
cal_component_get_attendee_list (comp, &attendees);
/* Clear things up */
- e_meeting_model_remove_all_attendees (priv->model);
+ e_meeting_store_remove_all_attendees (priv->model);
if (attendees == NULL) {
comp_editor_remove_page (editor, COMP_EDITOR_PAGE (priv->meet_page));
@@ -276,7 +277,7 @@ task_editor_edit_comp (CompEditor *editor, CalComponent *comp)
/* If we aren't the organizer or the attendee is just delegating, don't allow editing */
if (!comp_editor_get_user_org (editor) || e_meeting_attendee_is_set_delto (ia))
e_meeting_attendee_set_edit_level (ia, E_MEETING_ATTENDEE_EDIT_NONE);
- e_meeting_model_add_attendee (priv->model, ia);
+ e_meeting_store_add_attendee (priv->model, ia);
g_object_unref(ia);
}
@@ -293,7 +294,7 @@ task_editor_edit_comp (CompEditor *editor, CalComponent *comp)
account = (EAccount*)e_iterator_get(it);
- ia = e_meeting_model_find_attendee (priv->model, account->id->address, &row);
+ ia = e_meeting_store_find_attendee (priv->model, account->id->address, &row);
if (ia != NULL)
e_meeting_attendee_set_edit_level (ia, E_MEETING_ATTENDEE_EDIT_STATUS);
}
@@ -301,7 +302,7 @@ task_editor_edit_comp (CompEditor *editor, CalComponent *comp)
} else if (cal_client_get_organizer_must_attend (client)) {
EMeetingAttendee *ia;
- ia = e_meeting_model_find_attendee (priv->model, organizer.value, &row);
+ ia = e_meeting_store_find_attendee (priv->model, organizer.value, &row);
if (ia != NULL)
e_meeting_attendee_set_edit_level (ia, E_MEETING_ATTENDEE_EDIT_NONE);
}
@@ -335,7 +336,7 @@ task_editor_send_comp (CompEditor *editor, CalComponentItipMethod method)
CalClient *client;
gboolean result;
- client = e_meeting_model_get_cal_client (priv->model);
+ client = e_meeting_store_get_cal_client (priv->model);
result = itip_send_comp (CAL_COMPONENT_METHOD_CANCEL, comp, client, NULL);
g_object_unref((comp));
@@ -464,29 +465,22 @@ forward_cmd (GtkWidget *widget, gpointer data)
}
static void
-model_row_changed_cb (ETableModel *etm, int row, gpointer data)
+model_changed (TaskEditor *te)
{
- TaskEditor *te = TASK_EDITOR (data);
- TaskEditorPrivate *priv;
-
- priv = te->priv;
-
- if (!priv->updating) {
+ if (!te->priv->updating) {
comp_editor_set_changed (COMP_EDITOR (te), TRUE);
comp_editor_set_needs_send (COMP_EDITOR (te), TRUE);
}
}
static void
-row_count_changed_cb (ETableModel *etm, int row, int count, gpointer data)
+model_row_change_insert_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
{
- TaskEditor *te = TASK_EDITOR (data);
- TaskEditorPrivate *priv;
-
- priv = te->priv;
+ model_changed (TASK_EDITOR (data));
+}
- if (!priv->updating) {
- comp_editor_set_changed (COMP_EDITOR (te), TRUE);
- comp_editor_set_needs_send (COMP_EDITOR (te), TRUE);
- }
+static void
+model_row_delete_cb (GtkTreeModel *model, GtkTreePath *path, gpointer data)
+{
+ model_changed (TASK_EDITOR (data));
}
diff --git a/calendar/gui/e-meeting-list-view.c b/calendar/gui/e-meeting-list-view.c
new file mode 100644
index 0000000000..7d3a4ce6c6
--- /dev/null
+++ b/calendar/gui/e-meeting-list-view.c
@@ -0,0 +1,483 @@
+/*
+ * e-meeting-list-view.c
+ *
+ * Authors: Mike Kestner <mkestner@ximian.com>
+ * JP Rosevear <jpr@ximian.com>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <gtk/gtktreemodel.h>
+#include <bonobo/bonobo-control.h>
+#include <bonobo/bonobo-widget.h>
+#include <bonobo/bonobo-exception.h>
+#include <libgnome/gnome-i18n.h>
+#include <libgnome/gnome-util.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <ebook/e-book.h>
+#include <ebook/e-book-util.h>
+#include <ebook/e-card-types.h>
+#include <ebook/e-card-cursor.h>
+#include <ebook/e-card.h>
+#include <ebook/e-card-simple.h>
+#include <cal-util/cal-component.h>
+#include <cal-util/cal-util.h>
+#include <cal-util/timeutil.h>
+#include "Evolution-Addressbook-SelectNames.h"
+#include "calendar-config.h"
+#include "e-meeting-list-view.h"
+#include <misc/e-cell-renderer-combo.h>
+#include "e-select-names-renderer.h"
+
+#define SELECT_NAMES_OAFID "OAFIID:GNOME_Evolution_Addressbook_SelectNames"
+
+struct _EMeetingListViewPrivate
+{
+ EMeetingStore *store;
+
+ EBook *ebook;
+ gboolean book_loaded;
+ gboolean book_load_wait;
+
+ GNOME_Evolution_Addressbook_SelectNames corba_select_names;
+};
+
+#define BUF_SIZE 1024
+
+static char *sections[] = {N_("Chair Persons"),
+ N_("Required Participants"),
+ N_("Optional Participants"),
+ N_("Resources"),
+ NULL};
+static icalparameter_role roles[] = {ICAL_ROLE_CHAIR,
+ ICAL_ROLE_REQPARTICIPANT,
+ ICAL_ROLE_OPTPARTICIPANT,
+ ICAL_ROLE_NONPARTICIPANT,
+ ICAL_ROLE_NONE};
+
+static GtkTreeViewClass *parent_class = NULL;
+
+static void
+book_open_cb (EBook *book, EBookStatus status, gpointer data)
+{
+ EMeetingListView *view = E_MEETING_LIST_VIEW (data);
+
+ if (status == E_BOOK_STATUS_SUCCESS)
+ view->priv->book_loaded = TRUE;
+ else
+ g_warning ("Book not loaded");
+
+ if (view->priv->book_load_wait) {
+ view->priv->book_load_wait = FALSE;
+ gtk_main_quit ();
+ }
+}
+
+static void
+start_addressbook_server (EMeetingListView *view)
+{
+ view->priv->ebook = e_book_new ();
+ e_book_load_default_book (view->priv->ebook, book_open_cb, view);
+}
+
+static void
+emlv_finalize (GObject *obj)
+{
+ EMeetingListView *view = E_MEETING_LIST_VIEW (obj);
+ EMeetingListViewPrivate *priv = view->priv;
+
+ if (priv->ebook != NULL)
+ g_object_unref (priv->ebook);
+
+ if (priv->corba_select_names != CORBA_OBJECT_NIL) {
+ CORBA_Environment ev;
+ CORBA_exception_init (&ev);
+ bonobo_object_release_unref (priv->corba_select_names, &ev);
+ CORBA_exception_free (&ev);
+ }
+
+ g_free (priv);
+
+ if (G_OBJECT_CLASS (parent_class)->finalize)
+ (* G_OBJECT_CLASS (parent_class)->finalize) (obj);
+}
+
+static void
+emlv_class_init (GObjectClass *klass)
+{
+ parent_class = g_type_class_peek_parent (klass);
+
+ klass->finalize = emlv_finalize;
+}
+
+
+static void
+emlv_init (EMeetingListView *view)
+{
+ EMeetingListViewPrivate *priv;
+
+ priv = g_new0 (EMeetingListViewPrivate, 1);
+
+ view->priv = priv;
+
+ priv->corba_select_names = CORBA_OBJECT_NIL;
+
+ start_addressbook_server (view);
+}
+
+E_MAKE_TYPE (e_meeting_list_view, "EMeetingListView", EMeetingListView, emlv_class_init, emlv_init, GTK_TYPE_TREE_VIEW);
+static GList *
+get_type_strings ()
+{
+ GList *strings = NULL;
+
+ strings = g_list_append (strings, (char*) _("Individual"));
+ strings = g_list_append (strings, (char*) _("Group"));
+ strings = g_list_append (strings, (char*) _("Resource"));
+ strings = g_list_append (strings, (char*) _("Room"));
+ strings = g_list_append (strings, (char*) _("Unknown"));
+
+ return strings;
+}
+
+static GList *
+get_role_strings ()
+{
+ GList *strings = NULL;
+
+ strings = g_list_append (strings, (char*) _("Chair"));
+ strings = g_list_append (strings, (char*) _("Required Participant"));
+ strings = g_list_append (strings, (char*) _("Optional Participant"));
+ strings = g_list_append (strings, (char*) _("Non-Participant"));
+ strings = g_list_append (strings, (char*) _("Unknown"));
+
+ return strings;
+}
+
+static GList *
+get_rsvp_strings ()
+{
+ GList *strings = NULL;
+
+ strings = g_list_append (strings, (char*) _("Yes"));
+ strings = g_list_append (strings, (char*) _("No"));
+
+ return strings;
+}
+
+static GList *
+get_status_strings ()
+{
+ GList *strings = NULL;
+
+ strings = g_list_append (strings, (char*) _("Needs Action"));
+ strings = g_list_append (strings, (char*) _("Accepted"));
+ strings = g_list_append (strings, (char*) _("Declined"));
+ strings = g_list_append (strings, (char*) _("Tentative"));
+ strings = g_list_append (strings, (char*) _("Delegated"));
+
+ return strings;
+}
+
+static void
+value_edited (GtkTreeView *view, gint col, const gchar *path, const gchar *text)
+{
+ EMeetingStore *model = E_MEETING_STORE (gtk_tree_view_get_model (view));
+ GtkTreePath *treepath = gtk_tree_path_new_from_string (path);
+ int row = gtk_tree_path_get_indices (treepath)[0];
+
+ e_meeting_store_set_value (model, row, col, text);
+ gtk_tree_path_free (treepath);
+}
+
+static void
+attendee_edited_cb (GtkCellRenderer *renderer, const gchar *path, const gchar *address, const gchar *name, GtkTreeView *view)
+{
+ value_edited (view, E_MEETING_STORE_ADDRESS_COL, path, address);
+ value_edited (view, E_MEETING_STORE_CN_COL, path, name);
+}
+
+static void
+type_edited_cb (GtkCellRenderer *renderer, const gchar *path, const gchar *text, GtkTreeView *view)
+{
+ value_edited (view, E_MEETING_STORE_TYPE_COL, path, text);
+}
+
+static void
+role_edited_cb (GtkCellRenderer *renderer, const gchar *path, const gchar *text, GtkTreeView *view)
+{
+ value_edited (view, E_MEETING_STORE_ROLE_COL, path, text);
+}
+
+static void
+rsvp_edited_cb (GtkCellRenderer *renderer, const gchar *path, const gchar *text, GtkTreeView *view)
+{
+ value_edited (view, E_MEETING_STORE_RSVP_COL, path, text);
+}
+
+static void
+status_edited_cb (GtkCellRenderer *renderer, const gchar *path, const gchar *text, GtkTreeView *view)
+{
+ value_edited (view, E_MEETING_STORE_STATUS_COL, path, text);
+}
+
+static void
+build_table (GtkTreeView *view)
+{
+ GtkCellRenderer *renderer;
+
+ gtk_tree_view_set_headers_visible (view, TRUE);
+ gtk_tree_view_set_rules_hint (view, TRUE);
+
+ renderer = e_select_names_renderer_new ();
+ g_object_set (G_OBJECT (renderer), "editable", TRUE, NULL);
+ gtk_tree_view_insert_column_with_attributes (view, -1, _("Attendee"), renderer,
+ "text", E_MEETING_STORE_ATTENDEE_COL,
+ "address", E_MEETING_STORE_ADDRESS_COL,
+ "underline", E_MEETING_STORE_ATTENDEE_UNDERLINE_COL,
+ NULL);
+ g_signal_connect (renderer, "cell_edited", G_CALLBACK (attendee_edited_cb), view);
+
+ renderer = e_cell_renderer_combo_new ();
+ g_object_set (G_OBJECT (renderer), "list", get_type_strings (), "editable", TRUE, NULL);
+ gtk_tree_view_insert_column_with_attributes (view, -1, _("Type"), renderer,
+ "text", E_MEETING_STORE_TYPE_COL,
+ NULL);
+ g_signal_connect (renderer, "edited", G_CALLBACK (type_edited_cb), view);
+
+ renderer = e_cell_renderer_combo_new ();
+ g_object_set (G_OBJECT (renderer), "list", get_role_strings (), "editable", TRUE, NULL);
+ gtk_tree_view_insert_column_with_attributes (view, -1, _("Role"), renderer,
+ "text", E_MEETING_STORE_ROLE_COL,
+ NULL);
+ g_signal_connect (renderer, "edited", G_CALLBACK (role_edited_cb), view);
+
+ renderer = e_cell_renderer_combo_new ();
+ g_object_set (G_OBJECT (renderer), "list", get_rsvp_strings (), "editable", TRUE, NULL);
+ gtk_tree_view_insert_column_with_attributes (view, -1, _("RSVP"), renderer,
+ "text", E_MEETING_STORE_RSVP_COL,
+ NULL);
+ g_signal_connect (renderer, "edited", G_CALLBACK (rsvp_edited_cb), view);
+
+ renderer = e_cell_renderer_combo_new ();
+ g_object_set (G_OBJECT (renderer), "list", get_status_strings (), "editable", TRUE, NULL);
+ gtk_tree_view_insert_column_with_attributes (view, -1, _("Status"), renderer,
+ "text", E_MEETING_STORE_STATUS_COL,
+ NULL);
+ g_signal_connect (renderer, "edited", G_CALLBACK (status_edited_cb), view);
+}
+
+EMeetingListView *
+e_meeting_list_view_new (EMeetingStore *store)
+{
+ EMeetingListView *view = g_object_new (E_TYPE_MEETING_LIST_VIEW, NULL);
+
+ if (view) {
+ view->priv->store = store;
+ gtk_tree_view_set_model (GTK_TREE_VIEW (view), GTK_TREE_MODEL (store));
+ build_table (GTK_TREE_VIEW (view));
+ }
+
+ return view;
+}
+
+void
+e_meeting_list_view_column_set_visible (EMeetingListView *view, const gchar *col_name, gboolean visible)
+{
+ GList *cols, *l;
+
+ cols = gtk_tree_view_get_columns (GTK_TREE_VIEW (view));
+
+ for (l = cols; l; l = l->next) {
+ GtkTreeViewColumn *col = (GtkTreeViewColumn *) l->data;
+
+ if (strcmp (gtk_tree_view_column_get_title (col), col_name) == 0) {
+ gtk_tree_view_column_set_visible (col, visible);
+ break;
+ }
+ }
+}
+
+static void
+process_section (EMeetingListView *view, GNOME_Evolution_Addressbook_SimpleCardList *cards, icalparameter_role role)
+{
+ EMeetingListViewPrivate *priv;
+ int i;
+
+ priv = view->priv;
+ for (i = 0; i < cards->_length; i++) {
+ const char *name, *attendee = NULL, *attr;
+ GNOME_Evolution_Addressbook_SimpleCard card;
+ CORBA_Environment ev;
+
+ card = cards->_buffer[i];
+
+ CORBA_exception_init (&ev);
+
+ /* Get the CN */
+ name = GNOME_Evolution_Addressbook_SimpleCard_get (card, GNOME_Evolution_Addressbook_SimpleCard_FullName, &ev);
+ if (BONOBO_EX (&ev)) {
+ CORBA_exception_free (&ev);
+ continue;
+ }
+
+ /* Get the field as attendee from the backend */
+ attr = cal_client_get_ldap_attribute (e_meeting_store_get_cal_client (priv->store));
+ if (attr) {
+ /* FIXME this should be more general */
+ if (!g_ascii_strcasecmp (attr, "icscalendar"))
+ attendee = GNOME_Evolution_Addressbook_SimpleCard_get (card, GNOME_Evolution_Addressbook_SimpleCard_Icscalendar, &ev);
+ }
+
+ CORBA_exception_init (&ev);
+
+ /* If we couldn't get the attendee prior, get the email address as the default */
+ if (attendee == NULL || *attendee == '\0') {
+ attendee = GNOME_Evolution_Addressbook_SimpleCard_get (card, GNOME_Evolution_Addressbook_SimpleCard_Email, &ev);
+ if (BONOBO_EX (&ev)) {
+ CORBA_exception_free (&ev);
+ continue;
+ }
+ }
+
+ CORBA_exception_free (&ev);
+
+ if (attendee == NULL || *attendee == '\0')
+ continue;
+
+ if (e_meeting_store_find_attendee (priv->store, attendee, NULL) == NULL) {
+ EMeetingAttendee *ia = e_meeting_store_add_attendee_with_defaults (priv->store);
+
+ e_meeting_attendee_set_address (ia, g_strdup_printf ("MAILTO:%s", attendee));
+ e_meeting_attendee_set_role (ia, role);
+ if (role == ICAL_ROLE_NONPARTICIPANT)
+ e_meeting_attendee_set_cutype (ia, ICAL_CUTYPE_RESOURCE);
+ e_meeting_attendee_set_cn (ia, g_strdup (name));
+ }
+ }
+}
+
+static void
+select_names_ok_cb (BonoboListener *listener, const char *event_name, const CORBA_any *arg, CORBA_Environment *ev, gpointer data)
+{
+ EMeetingListView *view = E_MEETING_LIST_VIEW (data);
+ BonoboArg *card_arg;
+ int i;
+
+ for (i = 0; sections[i] != NULL; i++) {
+ Bonobo_Control corba_control = GNOME_Evolution_Addressbook_SelectNames_getEntryBySection
+ (view->priv->corba_select_names, sections[i], ev);
+ GtkWidget *control_widget = bonobo_widget_new_control_from_objref (corba_control, CORBA_OBJECT_NIL);
+ BonoboControlFrame *control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (control_widget));
+ Bonobo_PropertyBag pb = bonobo_control_frame_get_control_property_bag (control_frame, NULL);
+ card_arg = bonobo_property_bag_client_get_value_any (pb, "simple_card_list", NULL);
+ if (card_arg != NULL) {
+ GNOME_Evolution_Addressbook_SimpleCardList cards;
+ cards = BONOBO_ARG_GET_GENERAL (card_arg, TC_GNOME_Evolution_Addressbook_SimpleCardList,
+ GNOME_Evolution_Addressbook_SimpleCardList, NULL);
+ process_section (view, &cards, roles[i]);
+ bonobo_arg_release (card_arg);
+ }
+ }
+}
+
+static void
+add_section (GNOME_Evolution_Addressbook_SelectNames corba_select_names, const char *name)
+{
+ CORBA_Environment ev;
+
+ CORBA_exception_init (&ev);
+
+ GNOME_Evolution_Addressbook_SelectNames_addSection (
+ corba_select_names, name, gettext (name), &ev);
+
+ CORBA_exception_free (&ev);
+}
+
+static gboolean
+get_select_name_dialog (EMeetingListView *view)
+{
+ EMeetingListViewPrivate *priv;
+ CORBA_Environment ev;
+ int i;
+
+ priv = view->priv;
+
+ CORBA_exception_init (&ev);
+
+ if (priv->corba_select_names != CORBA_OBJECT_NIL) {
+ int i;
+
+ for (i = 0; sections[i] != NULL; i++) {
+ GtkWidget *control_widget;
+ Bonobo_Control corba_control = GNOME_Evolution_Addressbook_SelectNames_getEntryBySection
+ (priv->corba_select_names, sections[i], &ev);
+ if (BONOBO_EX (&ev)) {
+ CORBA_exception_free (&ev);
+ return FALSE;
+ }
+
+ control_widget = bonobo_widget_new_control_from_objref (corba_control, CORBA_OBJECT_NIL);
+
+ bonobo_widget_set_property (BONOBO_WIDGET (control_widget), "text", TC_CORBA_string, "", NULL);
+ }
+ CORBA_exception_free (&ev);
+
+ return TRUE;
+ }
+
+ priv->corba_select_names = bonobo_activation_activate_from_id (SELECT_NAMES_OAFID, 0, NULL, &ev);
+
+ for (i = 0; sections[i] != NULL; i++)
+ add_section (priv->corba_select_names, sections[i]);
+
+ bonobo_event_source_client_add_listener (priv->corba_select_names,
+ (BonoboListenerCallbackFn) select_names_ok_cb,
+ "GNOME/Evolution:ok:dialog", NULL, view);
+
+ if (BONOBO_EX (&ev)) {
+ CORBA_exception_free (&ev);
+ return FALSE;
+ }
+
+ CORBA_exception_free (&ev);
+
+ return TRUE;
+}
+
+void
+e_meeting_list_view_invite_others_dialog (EMeetingListView *view)
+{
+ CORBA_Environment ev;
+
+ if (!get_select_name_dialog (view))
+ return;
+
+ CORBA_exception_init (&ev);
+
+ GNOME_Evolution_Addressbook_SelectNames_activateDialog (
+ view->priv->corba_select_names, _("Required Participants"), &ev);
+
+ CORBA_exception_free (&ev);
+}
+
diff --git a/calendar/gui/e-meeting-list-view.h b/calendar/gui/e-meeting-list-view.h
new file mode 100644
index 0000000000..dd539b9652
--- /dev/null
+++ b/calendar/gui/e-meeting-list-view.h
@@ -0,0 +1,62 @@
+/*
+ * e-meeting-list-view.h
+ *
+ * Author: Mike Kestner <mkestner@ximian.com>
+ *
+ * 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.
+ */
+
+#ifndef _E_MEETING_LIST_VIEW_H_
+#define _E_MEETING_LIST_VIEW_H_
+
+#include <gtk/gtktreeview.h>
+#include "e-meeting-store.h"
+
+G_BEGIN_DECLS
+
+#define E_TYPE_MEETING_LIST_VIEW (e_meeting_list_view_get_type ())
+#define E_MEETING_LIST_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_MEETING_LIST_VIEW, EMeetingListView))
+#define E_MEETING_LIST_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_MEETING_LIST_VIEW, EMeetingListViewClass))
+#define E_IS_MEETING_LIST_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_MEETING_LIST_VIEW))
+#define E_IS_MEETING_LIST_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_MEETING_LIST_VIEW))
+
+
+typedef struct _EMeetingListView EMeetingListView;
+typedef struct _EMeetingListViewPrivate EMeetingListViewPrivate;
+typedef struct _EMeetingListViewClass EMeetingListViewClass;
+
+struct _EMeetingListView {
+ GtkTreeView parent;
+
+ EMeetingListViewPrivate *priv;
+};
+
+struct _EMeetingListViewClass {
+ GtkTreeViewClass parent_class;
+};
+
+GType e_meeting_list_view_get_type (void);
+
+EMeetingListView *e_meeting_list_view_new (EMeetingStore *store);
+
+void e_meeting_list_view_column_set_visible (EMeetingListView *emlv, const gchar *col_name, gboolean visible);
+
+void e_meeting_list_view_invite_others_dialog (EMeetingListView *emlv);
+
+G_END_DECLS
+
+#endif
diff --git a/calendar/gui/e-meeting-model.c b/calendar/gui/e-meeting-model.c
deleted file mode 100644
index a7cd54fd85..0000000000
--- a/calendar/gui/e-meeting-model.c
+++ /dev/null
@@ -1,1788 +0,0 @@
-/* -*- Mod:e C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* itip-model.c
- *
- * Copyright (C) 2001 Ximian, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: JP Rosevear
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib.h>
-#include <bonobo/bonobo-control.h>
-#include <bonobo/bonobo-widget.h>
-#include <bonobo/bonobo-exception.h>
-#include <libgnome/gnome-i18n.h>
-#include <libgnome/gnome-util.h>
-#include <libgnomevfs/gnome-vfs.h>
-#include <gal/e-table/e-table-without.h>
-#include <gal/e-table/e-cell-text.h>
-#include <gal/e-table/e-cell-popup.h>
-#include <gal/e-table/e-cell-combo.h>
-#include <ebook/e-book.h>
-#include <ebook/e-book-util.h>
-#include <ebook/e-card-types.h>
-#include <ebook/e-card-cursor.h>
-#include <ebook/e-card.h>
-#include <ebook/e-card-simple.h>
-#include <cal-util/cal-component.h>
-#include <cal-util/cal-util.h>
-#include <cal-util/timeutil.h>
-#include "Evolution-Addressbook-SelectNames.h"
-#include "calendar-config.h"
-#include "itip-utils.h"
-#include "e-meeting-utils.h"
-#include "e-meeting-attendee.h"
-#include "e-meeting-model.h"
-
-#define SELECT_NAMES_OAFID "OAFIID:GNOME_Evolution_Addressbook_SelectNames"
-
-struct _EMeetingModelPrivate
-{
- GPtrArray *attendees;
-
- GList *tables;
-
- CalClient *client;
- icaltimezone *zone;
-
- EBook *ebook;
- gboolean book_loaded;
- gboolean book_load_wait;
-
- GPtrArray *refresh_queue;
- GHashTable *refresh_data;
- guint refresh_idle_id;
-
- /* For invite others dialogs */
- GNOME_Evolution_Addressbook_SelectNames corba_select_names;
-};
-
-#define BUF_SIZE 1024
-
-static char *sections[] = {N_("Chair Persons"),
- N_("Required Participants"),
- N_("Optional Participants"),
- N_("Resources"),
- NULL};
-static icalparameter_role roles[] = {ICAL_ROLE_CHAIR,
- ICAL_ROLE_REQPARTICIPANT,
- ICAL_ROLE_OPTPARTICIPANT,
- ICAL_ROLE_NONPARTICIPANT,
- ICAL_ROLE_NONE};
-
-typedef struct _EMeetingModelQueueData EMeetingModelQueueData;
-struct _EMeetingModelQueueData {
- EMeetingModel *im;
- EMeetingAttendee *ia;
-
- gboolean refreshing;
-
- EMeetingTime start;
- EMeetingTime end;
-
- char buffer[BUF_SIZE];
- GString *string;
-
- GPtrArray *call_backs;
- GPtrArray *data;
-};
-
-
-static void class_init (EMeetingModelClass *klass);
-static void init (EMeetingModel *model);
-static void finalize (GObject *obj);
-
-static void refresh_queue_add (EMeetingModel *im, int row,
- EMeetingTime *start,
- EMeetingTime *end,
- EMeetingModelRefreshCallback call_back,
- gpointer data);
-static void refresh_queue_remove (EMeetingModel *im,
- EMeetingAttendee *ia);
-static gboolean refresh_busy_periods (gpointer data);
-
-static void attendee_changed_cb (EMeetingAttendee *ia, gpointer data);
-static void select_names_ok_cb (BonoboListener *listener,
- const char *event_name,
- const CORBA_any *arg,
- CORBA_Environment *ev,
- gpointer data);
-
-static void table_destroy_state_cb (ETableScrolled *etable, gpointer data);
-static void table_destroy_list_cb (ETableScrolled *etable, gpointer data);
-
-static ETableModelClass *parent_class = NULL;
-
-E_MAKE_TYPE (e_meeting_model, "EMeetingModel", EMeetingModel,
- class_init, init, E_TABLE_MODEL_TYPE);
-
-static void
-book_open_cb (EBook *book, EBookStatus status, gpointer data)
-{
- EMeetingModel *im = E_MEETING_MODEL (data);
- EMeetingModelPrivate *priv;
-
- priv = im->priv;
-
- if (status == E_BOOK_STATUS_SUCCESS)
- priv->book_loaded = TRUE;
- else
- g_warning ("Book not loaded");
-
- if (priv->book_load_wait) {
- priv->book_load_wait = FALSE;
- gtk_main_quit ();
- }
-}
-
-static void
-start_addressbook_server (EMeetingModel *im)
-{
- EMeetingModelPrivate *priv;
-
- priv = im->priv;
-
- priv->ebook = e_book_new ();
- e_book_load_default_book (priv->ebook, book_open_cb, im);
-}
-
-static EMeetingAttendee *
-find_match (EMeetingModel *im, const char *address, int *pos)
-{
- EMeetingModelPrivate *priv;
- EMeetingAttendee *ia;
- const gchar *ia_address;
- int i;
-
- priv = im->priv;
-
- if (address == NULL)
- return NULL;
-
- /* Make sure we can add the new delegatee person */
- for (i = 0; i < priv->attendees->len; i++) {
- ia = g_ptr_array_index (priv->attendees, i);
-
- ia_address = e_meeting_attendee_get_address (ia);
- if (ia_address != NULL && !g_strcasecmp (itip_strip_mailto (ia_address), itip_strip_mailto (address))) {
- if (pos != NULL)
- *pos = i;
- return ia;
- }
- }
-
- return NULL;
-}
-
-static icalparameter_cutype
-text_to_type (const char *type)
-{
- if (!g_strcasecmp (type, _("Individual")))
- return ICAL_CUTYPE_INDIVIDUAL;
- else if (!g_strcasecmp (type, _("Group")))
- return ICAL_CUTYPE_GROUP;
- else if (!g_strcasecmp (type, _("Resource")))
- return ICAL_CUTYPE_RESOURCE;
- else if (!g_strcasecmp (type, _("Room")))
- return ICAL_CUTYPE_ROOM;
- else
- return ICAL_CUTYPE_NONE;
-}
-
-static char *
-type_to_text (icalparameter_cutype type)
-{
- switch (type) {
- case ICAL_CUTYPE_INDIVIDUAL:
- return _("Individual");
- case ICAL_CUTYPE_GROUP:
- return _("Group");
- case ICAL_CUTYPE_RESOURCE:
- return _("Resource");
- case ICAL_CUTYPE_ROOM:
- return _("Room");
- default:
- return _("Unknown");
- }
-
- return NULL;
-
-}
-
-static icalparameter_role
-text_to_role (const char *role)
-{
- if (!g_strcasecmp (role, _("Chair")))
- return ICAL_ROLE_CHAIR;
- else if (!g_strcasecmp (role, _("Required Participant")))
- return ICAL_ROLE_REQPARTICIPANT;
- else if (!g_strcasecmp (role, _("Optional Participant")))
- return ICAL_ROLE_OPTPARTICIPANT;
- else if (!g_strcasecmp (role, _("Non-Participant")))
- return ICAL_ROLE_NONPARTICIPANT;
- else
- return ICAL_ROLE_NONE;
-}
-
-static char *
-role_to_text (icalparameter_role role)
-{
- switch (role) {
- case ICAL_ROLE_CHAIR:
- return _("Chair");
- case ICAL_ROLE_REQPARTICIPANT:
- return _("Required Participant");
- case ICAL_ROLE_OPTPARTICIPANT:
- return _("Optional Participant");
- case ICAL_ROLE_NONPARTICIPANT:
- return _("Non-Participant");
- default:
- return _("Unknown");
- }
-
- return NULL;
-}
-
-static gboolean
-text_to_boolean (const char *role)
-{
- if (!g_strcasecmp (role, _("Yes")))
- return TRUE;
- else
- return FALSE;
-}
-
-static char *
-boolean_to_text (gboolean b)
-{
- if (b)
- return _("Yes");
- else
- return _("No");
-}
-
-static icalparameter_partstat
-text_to_partstat (const char *partstat)
-{
- if (!g_strcasecmp (partstat, _("Needs Action")))
- return ICAL_PARTSTAT_NEEDSACTION;
- else if (!g_strcasecmp (partstat, _("Accepted")))
- return ICAL_PARTSTAT_ACCEPTED;
- else if (!g_strcasecmp (partstat, _("Declined")))
- return ICAL_PARTSTAT_DECLINED;
- else if (!g_strcasecmp (partstat, _("Tentative")))
- return ICAL_PARTSTAT_TENTATIVE;
- else if (!g_strcasecmp (partstat, _("Delegated")))
- return ICAL_PARTSTAT_DELEGATED;
- else if (!g_strcasecmp (partstat, _("Completed")))
- return ICAL_PARTSTAT_COMPLETED;
- else if (!g_strcasecmp (partstat, _("In Process")))
- return ICAL_PARTSTAT_INPROCESS;
- else
- return ICAL_PARTSTAT_NONE;
-}
-
-static char *
-partstat_to_text (icalparameter_partstat partstat)
-{
- switch (partstat) {
- case ICAL_PARTSTAT_NEEDSACTION:
- return _("Needs Action");
- case ICAL_PARTSTAT_ACCEPTED:
- return _("Accepted");
- case ICAL_PARTSTAT_DECLINED:
- return _("Declined");
- case ICAL_PARTSTAT_TENTATIVE:
- return _("Tentative");
- case ICAL_PARTSTAT_DELEGATED:
- return _("Delegated");
- case ICAL_PARTSTAT_COMPLETED:
- return _("Completed");
- case ICAL_PARTSTAT_INPROCESS:
- return _("In Process");
- case ICAL_PARTSTAT_NONE:
- default:
- return _("Unknown");
- }
-
- return NULL;
-}
-
-static int
-column_count (ETableModel *etm)
-{
- return E_MEETING_MODEL_COLUMN_COUNT;
-}
-
-static int
-row_count (ETableModel *etm)
-{
- EMeetingModel *im;
- EMeetingModelPrivate *priv;
-
- im = E_MEETING_MODEL (etm);
- priv = im->priv;
-
- return (priv->attendees->len);
-}
-
-static void
-append_row (ETableModel *etm, ETableModel *source, int row)
-{
- EMeetingModel *im;
- EMeetingModelPrivate *priv;
- EMeetingAttendee *ia;
- char *address;
-
- im = E_MEETING_MODEL (etm);
- priv = im->priv;
-
- address = (char *) e_table_model_value_at (source, E_MEETING_MODEL_ADDRESS_COL, row);
- if (find_match (im, address, NULL) != NULL) {
- return;
- }
-
- ia = E_MEETING_ATTENDEE (e_meeting_attendee_new ());
-
- e_meeting_attendee_set_address (ia, g_strdup_printf ("MAILTO:%s", address));
- e_meeting_attendee_set_member (ia, g_strdup (e_table_model_value_at (source, E_MEETING_MODEL_MEMBER_COL, row)));
- e_meeting_attendee_set_cutype (ia, text_to_type (e_table_model_value_at (source, E_MEETING_MODEL_TYPE_COL, row)));
- e_meeting_attendee_set_role (ia, text_to_role (e_table_model_value_at (source, E_MEETING_MODEL_ROLE_COL, row)));
- e_meeting_attendee_set_rsvp (ia, text_to_boolean (e_table_model_value_at (source, E_MEETING_MODEL_RSVP_COL, row)));
- e_meeting_attendee_set_delto (ia, g_strdup (e_table_model_value_at (source, E_MEETING_MODEL_DELTO_COL, row)));
- e_meeting_attendee_set_delfrom (ia, g_strdup (e_table_model_value_at (source, E_MEETING_MODEL_DELFROM_COL, row)));
- e_meeting_attendee_set_status (ia, text_to_partstat (e_table_model_value_at (source, E_MEETING_MODEL_STATUS_COL, row)));
- e_meeting_attendee_set_cn (ia, g_strdup (e_table_model_value_at (source, E_MEETING_MODEL_CN_COL, row)));
- e_meeting_attendee_set_language (ia, g_strdup (e_table_model_value_at (source, E_MEETING_MODEL_LANGUAGE_COL, row)));
-
- e_meeting_model_add_attendee (E_MEETING_MODEL (etm), ia);
- g_object_unref (ia);
-}
-
-static void *
-value_at (ETableModel *etm, int col, int row)
-{
- EMeetingModel *im;
- EMeetingModelPrivate *priv;
- EMeetingAttendee *ia;
-
- im = E_MEETING_MODEL (etm);
- priv = im->priv;
-
- ia = g_ptr_array_index (priv->attendees, row);
-
- switch (col) {
- case E_MEETING_MODEL_ADDRESS_COL:
- return (void *)itip_strip_mailto (e_meeting_attendee_get_address (ia));
- case E_MEETING_MODEL_MEMBER_COL:
- return (void *)e_meeting_attendee_get_member (ia);
- case E_MEETING_MODEL_TYPE_COL:
- return type_to_text (e_meeting_attendee_get_cutype (ia));
- case E_MEETING_MODEL_ROLE_COL:
- return role_to_text (e_meeting_attendee_get_role (ia));
- case E_MEETING_MODEL_RSVP_COL:
- return boolean_to_text (e_meeting_attendee_get_rsvp (ia));
- case E_MEETING_MODEL_DELTO_COL:
- return (void *)itip_strip_mailto (e_meeting_attendee_get_delto (ia));
- case E_MEETING_MODEL_DELFROM_COL:
- return (void *)itip_strip_mailto (e_meeting_attendee_get_delfrom (ia));
- case E_MEETING_MODEL_STATUS_COL:
- return partstat_to_text (e_meeting_attendee_get_status (ia));
- case E_MEETING_MODEL_CN_COL:
- return (void *)e_meeting_attendee_get_cn (ia);
- case E_MEETING_MODEL_LANGUAGE_COL:
- return (void *)e_meeting_attendee_get_language (ia);
- }
-
- return NULL;
-}
-
-static void
-set_value_at (ETableModel *etm, int col, int row, const void *val)
-{
- EMeetingModel *im;
- EMeetingModelPrivate *priv;
- EMeetingAttendee *ia;
- icalparameter_cutype type;
-
- im = E_MEETING_MODEL (etm);
- priv = im->priv;
-
- ia = g_ptr_array_index (priv->attendees, row);
-
- e_table_model_pre_change (etm);
-
- switch (col) {
- case E_MEETING_MODEL_ADDRESS_COL:
- if (val != NULL && *((char *)val))
- e_meeting_attendee_set_address (ia, g_strdup_printf ("MAILTO:%s", (char *) val));
- break;
- case E_MEETING_MODEL_MEMBER_COL:
- e_meeting_attendee_set_member (ia, g_strdup (val));
- break;
- case E_MEETING_MODEL_TYPE_COL:
- type = text_to_type (val);
- e_meeting_attendee_set_cutype (ia, text_to_type (val));
- if (type == ICAL_CUTYPE_RESOURCE) {
- e_meeting_attendee_set_role (ia, ICAL_ROLE_NONPARTICIPANT);
- e_table_model_cell_changed (etm, E_MEETING_MODEL_ROLE_COL, row);
- }
- break;
- case E_MEETING_MODEL_ROLE_COL:
- e_meeting_attendee_set_role (ia, text_to_role (val));
- break;
- case E_MEETING_MODEL_RSVP_COL:
- e_meeting_attendee_set_rsvp (ia, text_to_boolean (val));
- break;
- case E_MEETING_MODEL_DELTO_COL:
- e_meeting_attendee_set_delto (ia, g_strdup (val));
- break;
- case E_MEETING_MODEL_DELFROM_COL:
- e_meeting_attendee_set_delfrom (ia, g_strdup (val));
- break;
- case E_MEETING_MODEL_STATUS_COL:
- e_meeting_attendee_set_status (ia, text_to_partstat (val));
- break;
- case E_MEETING_MODEL_CN_COL:
- e_meeting_attendee_set_cn (ia, g_strdup (val));
- break;
- case E_MEETING_MODEL_LANGUAGE_COL:
- e_meeting_attendee_set_language (ia, g_strdup (val));
- break;
- }
-
- e_table_model_cell_changed (etm, col, row);
-}
-
-static gboolean
-is_cell_editable (ETableModel *etm, int col, int row)
-{
- EMeetingModel *im;
- EMeetingModelPrivate *priv;
- EMeetingAttendee *ia;
- EMeetingAttendeeEditLevel level;
-
- im = E_MEETING_MODEL (etm);
- priv = im->priv;
-
- if (col == E_MEETING_MODEL_DELTO_COL
- || col == E_MEETING_MODEL_DELFROM_COL)
- return FALSE;
-
- if (row == -1)
- return TRUE;
- if (row >= priv->attendees->len)
- return TRUE;
-
- ia = g_ptr_array_index (priv->attendees, row);
- level = e_meeting_attendee_get_edit_level (ia);
-
- switch (level) {
- case E_MEETING_ATTENDEE_EDIT_FULL:
- return TRUE;
- case E_MEETING_ATTENDEE_EDIT_STATUS:
- return col == E_MEETING_MODEL_STATUS_COL;
- case E_MEETING_ATTENDEE_EDIT_NONE:
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void *
-duplicate_value (ETableModel *etm, int col, const void *val)
-{
- return g_strdup (val);
-}
-
-static void
-free_value (ETableModel *etm, int col, void *val)
-{
- g_free (val);
-}
-
-static void *
-init_value (ETableModel *etm, int col)
-{
- switch (col) {
- case E_MEETING_MODEL_ADDRESS_COL:
- return g_strdup ("");
- case E_MEETING_MODEL_MEMBER_COL:
- return g_strdup ("");
- case E_MEETING_MODEL_TYPE_COL:
- return g_strdup (_("Individual"));
- case E_MEETING_MODEL_ROLE_COL:
- return g_strdup (_("Required Participant"));
- case E_MEETING_MODEL_RSVP_COL:
- return g_strdup (_("Yes"));
- case E_MEETING_MODEL_DELTO_COL:
- return g_strdup ("");
- case E_MEETING_MODEL_DELFROM_COL:
- return g_strdup ("");
- case E_MEETING_MODEL_STATUS_COL:
- return g_strdup (_("Needs Action"));
- case E_MEETING_MODEL_CN_COL:
- return g_strdup ("");
- case E_MEETING_MODEL_LANGUAGE_COL:
- return g_strdup ("en");
- }
-
- return g_strdup ("");
-}
-
-static gboolean
-value_is_empty (ETableModel *etm, int col, const void *val)
-{
-
- switch (col) {
- case E_MEETING_MODEL_ADDRESS_COL:
- case E_MEETING_MODEL_MEMBER_COL:
- case E_MEETING_MODEL_DELTO_COL:
- case E_MEETING_MODEL_DELFROM_COL:
- case E_MEETING_MODEL_CN_COL:
- if (val && !g_strcasecmp (val, ""))
- return TRUE;
- else
- return FALSE;
- default:
- ;
- }
-
- return TRUE;
-}
-
-static char *
-value_to_string (ETableModel *etm, int col, const void *val)
-{
- return g_strdup (val);
-}
-
-static void
-class_init (EMeetingModelClass *klass)
-{
- GObjectClass *gobject_class;
- ETableModelClass *etm_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
- etm_class = E_TABLE_MODEL_CLASS (klass);
-
- parent_class = g_type_class_peek_parent (klass);
-
- gobject_class->finalize = finalize;
-
- etm_class->column_count = column_count;
- etm_class->row_count = row_count;
- etm_class->value_at = value_at;
- etm_class->set_value_at = set_value_at;
- etm_class->is_cell_editable = is_cell_editable;
- etm_class->append_row = append_row;
- etm_class->duplicate_value = duplicate_value;
- etm_class->free_value = free_value;
- etm_class->initialize_value = init_value;
- etm_class->value_is_empty = value_is_empty;
- etm_class->value_to_string = value_to_string;
-}
-
-
-static void
-init (EMeetingModel *im)
-{
- EMeetingModelPrivate *priv;
-
- priv = g_new0 (EMeetingModelPrivate, 1);
-
- im->priv = priv;
-
- priv->attendees = g_ptr_array_new ();
-
- priv->tables = NULL;
-
- priv->client = NULL;
- priv->zone = icaltimezone_get_builtin_timezone (calendar_config_get_timezone ());
-
- priv->ebook = NULL;
- priv->book_loaded = FALSE;
- priv->book_load_wait = FALSE;
-
- priv->refresh_queue = g_ptr_array_new ();
- priv->refresh_data = g_hash_table_new (g_direct_hash, g_direct_equal);
- priv->refresh_idle_id = 0;
-
- priv->corba_select_names = CORBA_OBJECT_NIL;
-
- start_addressbook_server (im);
-}
-
-static void
-finalize (GObject *obj)
-{
- EMeetingModel *im = E_MEETING_MODEL (obj);
- EMeetingModelPrivate *priv;
- GList *l;
- int i;
-
- priv = im->priv;
-
- for (i = 0; i < priv->attendees->len; i++)
- g_object_unref (g_ptr_array_index (priv->attendees, i));
- g_ptr_array_free (priv->attendees, TRUE);
-
- for (l = priv->tables; l != NULL; l = l->next)
- g_signal_handlers_disconnect_matched (G_OBJECT (l->data), G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, NULL, im);
- g_list_free (priv->tables);
-
- if (priv->client != NULL)
- g_object_unref (priv->client);
-
- if (priv->ebook != NULL)
- g_object_unref (priv->ebook);
-
- if (priv->corba_select_names != CORBA_OBJECT_NIL) {
- CORBA_Environment ev;
- CORBA_exception_init (&ev);
- bonobo_object_release_unref (priv->corba_select_names, &ev);
- CORBA_exception_free (&ev);
- }
-
- while (priv->refresh_queue->len > 0)
- refresh_queue_remove (im, g_ptr_array_index (priv->refresh_queue, 0));
- g_ptr_array_free (priv->refresh_queue, TRUE);
- g_hash_table_destroy (priv->refresh_data);
-
- if (priv->refresh_idle_id)
- g_source_remove (priv->refresh_idle_id);
-
- g_free (priv);
-
- if (G_OBJECT_CLASS (parent_class)->finalize)
- (* G_OBJECT_CLASS (parent_class)->finalize) (obj);
-}
-
-GtkObject *
-e_meeting_model_new (void)
-{
- return g_object_new (E_TYPE_MEETING_MODEL, NULL);
-}
-
-
-CalClient *
-e_meeting_model_get_cal_client (EMeetingModel *im)
-{
- EMeetingModelPrivate *priv;
-
- priv = im->priv;
-
- return priv->client;
-}
-
-void
-e_meeting_model_set_cal_client (EMeetingModel *im, CalClient *client)
-{
- EMeetingModelPrivate *priv;
-
- priv = im->priv;
-
- if (priv->client != NULL)
- g_object_unref (priv->client);
-
- if (client != NULL)
- g_object_ref (client);
- priv->client = client;
-}
-
-icaltimezone *
-e_meeting_model_get_zone (EMeetingModel *im)
-{
- EMeetingModelPrivate *priv;
-
- g_return_val_if_fail (im != NULL, NULL);
- g_return_val_if_fail (E_IS_MEETING_MODEL (im), NULL);
-
- priv = im->priv;
-
- return priv->zone;
-}
-
-void
-e_meeting_model_set_zone (EMeetingModel *im, icaltimezone *zone)
-{
- EMeetingModelPrivate *priv;
-
- g_return_if_fail (im != NULL);
- g_return_if_fail (E_IS_MEETING_MODEL (im));
-
- priv = im->priv;
-
- priv->zone = zone;
-}
-
-static ETableScrolled *
-build_etable (ETableModel *model, const gchar *spec_file, const gchar *state_file)
-{
- GtkWidget *etable;
- ETable *real_table;
- ETableExtras *extras;
- GList *strings;
- ECell *popup_cell, *cell;
-
- extras = e_table_extras_new ();
-
- /* For type */
- cell = e_cell_text_new (NULL, GTK_JUSTIFY_LEFT);
- popup_cell = e_cell_combo_new ();
- e_cell_popup_set_child (E_CELL_POPUP (popup_cell), cell);
- g_object_unref (cell);
-
- strings = NULL;
- strings = g_list_append (strings, (char*) _("Individual"));
- strings = g_list_append (strings, (char*) _("Group"));
- strings = g_list_append (strings, (char*) _("Resource"));
- strings = g_list_append (strings, (char*) _("Room"));
- strings = g_list_append (strings, (char*) _("Unknown"));
-
- e_cell_combo_set_popdown_strings (E_CELL_COMBO (popup_cell), strings);
- e_table_extras_add_cell (extras, "typeedit", popup_cell);
-
- /* For role */
- cell = e_cell_text_new (NULL, GTK_JUSTIFY_LEFT);
- popup_cell = e_cell_combo_new ();
- e_cell_popup_set_child (E_CELL_POPUP (popup_cell), cell);
- g_object_unref (cell);
-
- strings = NULL;
- strings = g_list_append (strings, (char*) _("Chair"));
- strings = g_list_append (strings, (char*) _("Required Participant"));
- strings = g_list_append (strings, (char*) _("Optional Participant"));
- strings = g_list_append (strings, (char*) _("Non-Participant"));
- strings = g_list_append (strings, (char*) _("Unknown"));
-
- e_cell_combo_set_popdown_strings (E_CELL_COMBO (popup_cell), strings);
- e_table_extras_add_cell (extras, "roleedit", popup_cell);
-
- /* For rsvp */
- cell = e_cell_text_new (NULL, GTK_JUSTIFY_LEFT);
- popup_cell = e_cell_combo_new ();
- e_cell_popup_set_child (E_CELL_POPUP (popup_cell), cell);
- g_object_unref (cell);
-
- strings = NULL;
- strings = g_list_append (strings, (char*) _("Yes"));
- strings = g_list_append (strings, (char*) _("No"));
-
- e_cell_combo_set_popdown_strings (E_CELL_COMBO (popup_cell), strings);
- e_table_extras_add_cell (extras, "rsvpedit", popup_cell);
-
- /* For status */
- cell = e_cell_text_new (NULL, GTK_JUSTIFY_LEFT);
- popup_cell = e_cell_combo_new ();
- e_cell_popup_set_child (E_CELL_POPUP (popup_cell), cell);
- g_object_unref (cell);
-
- strings = NULL;
- strings = g_list_append (strings, (char*) _("Needs Action"));
- strings = g_list_append (strings, (char*) _("Accepted"));
- strings = g_list_append (strings, (char*) _("Declined"));
- strings = g_list_append (strings, (char*) _("Tentative"));
- strings = g_list_append (strings, (char*) _("Delegated"));
-
- e_cell_combo_set_popdown_strings (E_CELL_COMBO (popup_cell), strings);
- e_table_extras_add_cell (extras, "statusedit", popup_cell);
-
- etable = e_table_scrolled_new_from_spec_file (model, extras, spec_file, NULL);
- real_table = e_table_scrolled_get_table (E_TABLE_SCROLLED (etable));
- g_object_set (G_OBJECT (real_table), "uniform_row_height", TRUE, NULL);
- e_table_load_state (real_table, state_file);
-
-#if 0
- g_signal_connect (real_table, "right_click", G_CALLBACK (right_click_cb), mpage);
-#endif
-
- g_signal_connect (etable, "destroy", G_CALLBACK (table_destroy_state_cb), g_strdup (state_file));
-
- g_object_unref (extras);
-
- return E_TABLE_SCROLLED (etable);
-}
-
-void
-e_meeting_model_add_attendee (EMeetingModel *im, EMeetingAttendee *ia)
-{
- EMeetingModelPrivate *priv;
-
- priv = im->priv;
-
- e_table_model_pre_change (E_TABLE_MODEL (im));
-
- g_object_ref (ia);
- g_ptr_array_add (priv->attendees, ia);
-
- g_signal_connect (ia, "changed", G_CALLBACK (attendee_changed_cb), im);
-
- e_table_model_row_inserted (E_TABLE_MODEL (im), row_count (E_TABLE_MODEL (im)) - 1);
-}
-
-EMeetingAttendee *
-e_meeting_model_add_attendee_with_defaults (EMeetingModel *im)
-{
- EMeetingAttendee *ia;
- char *str;
-
- ia = E_MEETING_ATTENDEE (e_meeting_attendee_new ());
-
- e_meeting_attendee_set_address (ia, init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_ADDRESS_COL));
- e_meeting_attendee_set_member (ia, init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_MEMBER_COL));
-
- str = init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_TYPE_COL);
- e_meeting_attendee_set_cutype (ia, text_to_type (str));
- g_free (str);
- str = init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_ROLE_COL);
- e_meeting_attendee_set_role (ia, text_to_role (str));
- g_free (str);
- str = init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_RSVP_COL);
- e_meeting_attendee_set_rsvp (ia, text_to_boolean (str));
- g_free (str);
-
- e_meeting_attendee_set_delto (ia, init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_DELTO_COL));
- e_meeting_attendee_set_delfrom (ia, init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_DELFROM_COL));
-
- str = init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_STATUS_COL);
- e_meeting_attendee_set_status (ia, text_to_partstat (str));
- g_free (str);
-
- e_meeting_attendee_set_cn (ia, init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_CN_COL));
- e_meeting_attendee_set_language (ia, init_value (E_TABLE_MODEL (im), E_MEETING_MODEL_LANGUAGE_COL));
-
- e_meeting_model_add_attendee (im, ia);
-
- return ia;
-}
-
-void
-e_meeting_model_remove_attendee (EMeetingModel *im, EMeetingAttendee *ia)
-{
- EMeetingModelPrivate *priv;
- gint i, row = -1;
-
- priv = im->priv;
-
- for (i = 0; i < priv->attendees->len; i++) {
- if (ia == g_ptr_array_index (priv->attendees, i)) {
- row = i;
- break;
- }
- }
-
- if (row != -1) {
- e_table_model_pre_change (E_TABLE_MODEL (im));
-
- g_ptr_array_remove_index (priv->attendees, row);
- g_object_unref (ia);
-
- e_table_model_row_deleted (E_TABLE_MODEL (im), row);
- }
-}
-
-void
-e_meeting_model_remove_all_attendees (EMeetingModel *im)
-{
- EMeetingModelPrivate *priv;
- gint i, len;
-
- priv = im->priv;
-
- e_table_model_pre_change (E_TABLE_MODEL (im));
-
- len = priv->attendees->len;
-
- for (i = 0; i < len; i++) {
- EMeetingAttendee *ia = g_ptr_array_index (priv->attendees, i);
- g_object_unref (ia);
- }
- g_ptr_array_set_size (priv->attendees, 0);
-
- e_table_model_rows_deleted (E_TABLE_MODEL (im), 0, len);
-}
-
-EMeetingAttendee *
-e_meeting_model_find_attendee (EMeetingModel *im, const gchar *address, gint *row)
-{
- EMeetingModelPrivate *priv;
- EMeetingAttendee *ia;
- int i;
-
- priv = im->priv;
-
- if (address == NULL)
- return NULL;
-
- for (i = 0; i < priv->attendees->len; i++) {
- const gchar *ia_address;
-
- ia = g_ptr_array_index (priv->attendees, i);
-
- ia_address = e_meeting_attendee_get_address (ia);
- if (ia_address && !g_strcasecmp (itip_strip_mailto (ia_address), itip_strip_mailto (address))) {
- if (row != NULL)
- *row = i;
-
- return ia;
- }
- }
-
- return NULL;
-}
-
-EMeetingAttendee *
-e_meeting_model_find_attendee_at_row (EMeetingModel *im, gint row)
-{
- EMeetingModelPrivate *priv;
-
- g_return_val_if_fail (im != NULL, NULL);
- g_return_val_if_fail (E_IS_MEETING_MODEL (im), NULL);
- g_return_val_if_fail (row >= 0, NULL);
-
- priv = im->priv;
- g_return_val_if_fail (row < priv->attendees->len, NULL);
-
- return g_ptr_array_index (priv->attendees, row);
-}
-
-gint
-e_meeting_model_count_actual_attendees (EMeetingModel *im)
-{
- EMeetingModelPrivate *priv;
-
- priv = im->priv;
-
- return e_table_model_row_count (E_TABLE_MODEL (im));
-}
-
-const GPtrArray *
-e_meeting_model_get_attendees (EMeetingModel *im)
-{
- EMeetingModelPrivate *priv;
-
- priv = im->priv;
-
- return priv->attendees;
-}
-
-static icaltimezone *
-find_zone (icalproperty *ip, icalcomponent *tz_top_level)
-{
- icalparameter *param;
- icalcomponent *sub_comp;
- const char *tzid;
- icalcompiter iter;
-
- if (tz_top_level == NULL)
- return NULL;
-
- param = icalproperty_get_first_parameter (ip, ICAL_TZID_PARAMETER);
- if (param == NULL)
- return NULL;
- tzid = icalparameter_get_tzid (param);
-
- iter = icalcomponent_begin_component (tz_top_level, ICAL_VTIMEZONE_COMPONENT);
- while ((sub_comp = icalcompiter_deref (&iter)) != NULL) {
- icalcomponent *clone;
- const char *tz_tzid;
-
- tz_tzid = icalproperty_get_tzid (sub_comp);
- if (!strcmp (tzid, tz_tzid)) {
- icaltimezone *zone;
-
- zone = icaltimezone_new ();
- clone = icalcomponent_new_clone (sub_comp);
- icaltimezone_set_component (zone, clone);
-
- return zone;
- }
-
- icalcompiter_next (&iter);
- }
-
- return NULL;
-}
-
-
-static void
-refresh_queue_add (EMeetingModel *im, int row,
- EMeetingTime *start,
- EMeetingTime *end,
- EMeetingModelRefreshCallback call_back,
- gpointer data)
-{
- EMeetingModelPrivate *priv;
- EMeetingAttendee *ia;
- EMeetingModelQueueData *qdata;
-
- priv = im->priv;
-
- ia = g_ptr_array_index (priv->attendees, row);
- if (ia == NULL)
- return;
-
- qdata = g_hash_table_lookup (priv->refresh_data, ia);
- if (qdata == NULL) {
- qdata = g_new0 (EMeetingModelQueueData, 1);
-
- qdata->im = im;
- qdata->ia = ia;
- e_meeting_attendee_clear_busy_periods (ia);
- e_meeting_attendee_set_has_calendar_info (ia, FALSE);
-
- qdata->start = *start;
- qdata->end = *end;
- qdata->string = g_string_new (NULL);
- qdata->call_backs = g_ptr_array_new ();
- qdata->data = g_ptr_array_new ();
- g_ptr_array_add (qdata->call_backs, call_back);
- g_ptr_array_add (qdata->data, data);
-
- g_hash_table_insert (priv->refresh_data, ia, qdata);
- } else {
- if (e_meeting_time_compare_times (start, &qdata->start) == -1)
- qdata->start = *start;
- if (e_meeting_time_compare_times (end, &qdata->end) == 1)
- qdata->end = *end;
- g_ptr_array_add (qdata->call_backs, call_back);
- g_ptr_array_add (qdata->data, data);
- }
-
- g_object_ref (ia);
- g_ptr_array_add (priv->refresh_queue, ia);
-
- if (priv->refresh_idle_id == 0)
- priv->refresh_idle_id = g_idle_add (refresh_busy_periods, im);
-}
-
-static void
-refresh_queue_remove (EMeetingModel *im, EMeetingAttendee *ia)
-{
- EMeetingModelPrivate *priv;
- EMeetingModelQueueData *qdata;
-
- priv = im->priv;
-
- /* Free the queue data */
- qdata = g_hash_table_lookup (priv->refresh_data, ia);
- g_assert (qdata != NULL);
-
- g_hash_table_remove (priv->refresh_data, ia);
- g_ptr_array_free (qdata->call_backs, TRUE);
- g_ptr_array_free (qdata->data, TRUE);
- g_free (qdata);
-
- /* Unref the attendee */
- g_ptr_array_remove (priv->refresh_queue, ia);
- g_object_unref (ia);
-}
-
-static void
-process_callbacks (EMeetingModelQueueData *qdata)
-{
- EMeetingModel *im;
- int i;
-
- for (i = 0; i < qdata->call_backs->len; i++) {
- EMeetingModelRefreshCallback call_back;
- gpointer *data;
-
- call_back = g_ptr_array_index (qdata->call_backs, i);
- data = g_ptr_array_index (qdata->data, i);
-
- call_back (data);
- }
-
- im = qdata->im;
- refresh_queue_remove (qdata->im, qdata->ia);
- g_object_unref (im);
-}
-
-static void
-process_free_busy_comp (EMeetingAttendee *ia,
- icalcomponent *fb_comp,
- icaltimezone *zone,
- icalcomponent *tz_top_level)
-{
- icalproperty *ip;
-
- ip = icalcomponent_get_first_property (fb_comp, ICAL_DTSTART_PROPERTY);
- if (ip != NULL) {
- struct icaltimetype dtstart;
- icaltimezone *ds_zone;
-
- dtstart = icalproperty_get_dtstart (ip);
- if (!dtstart.is_utc)
- ds_zone = find_zone (ip, tz_top_level);
- else
- ds_zone = icaltimezone_get_utc_timezone ();
- icaltimezone_convert_time (&dtstart, ds_zone, zone);
- e_meeting_attendee_set_start_busy_range (ia,
- dtstart.year,
- dtstart.month,
- dtstart.day,
- dtstart.hour,
- dtstart.minute);
- }
-
- ip = icalcomponent_get_first_property (fb_comp, ICAL_DTEND_PROPERTY);
- if (ip != NULL) {
- struct icaltimetype dtend;
- icaltimezone *de_zone;
-
- dtend = icalproperty_get_dtend (ip);
- if (!dtend.is_utc)
- de_zone = find_zone (ip, tz_top_level);
- else
- de_zone = icaltimezone_get_utc_timezone ();
- icaltimezone_convert_time (&dtend, de_zone, zone);
- e_meeting_attendee_set_end_busy_range (ia,
- dtend.year,
- dtend.month,
- dtend.day,
- dtend.hour,
- dtend.minute);
- }
-
- ip = icalcomponent_get_first_property (fb_comp, ICAL_FREEBUSY_PROPERTY);
- while (ip != NULL) {
- icalparameter *param;
- struct icalperiodtype fb;
- EMeetingFreeBusyType busy_type = E_MEETING_FREE_BUSY_LAST;
- icalparameter_fbtype fbtype = ICAL_FBTYPE_BUSY;
-
- fb = icalproperty_get_freebusy (ip);
- param = icalproperty_get_first_parameter (ip, ICAL_FBTYPE_PARAMETER);
- if (param != NULL)
- fbtype = icalparameter_get_fbtype (param);
-
- switch (fbtype) {
- case ICAL_FBTYPE_BUSY:
- busy_type = E_MEETING_FREE_BUSY_BUSY;
- break;
-
- case ICAL_FBTYPE_BUSYUNAVAILABLE:
- busy_type = E_MEETING_FREE_BUSY_OUT_OF_OFFICE;
- break;
-
- case ICAL_FBTYPE_BUSYTENTATIVE:
- busy_type = E_MEETING_FREE_BUSY_TENTATIVE;
- break;
-
- default:
- break;
- }
-
- if (busy_type != E_MEETING_FREE_BUSY_LAST) {
- icaltimezone *utc_zone = icaltimezone_get_utc_timezone ();
-
- icaltimezone_convert_time (&fb.start, utc_zone, zone);
- icaltimezone_convert_time (&fb.end, utc_zone, zone);
- e_meeting_attendee_add_busy_period (ia,
- fb.start.year,
- fb.start.month,
- fb.start.day,
- fb.start.hour,
- fb.start.minute,
- fb.end.year,
- fb.end.month,
- fb.end.day,
- fb.end.hour,
- fb.end.minute,
- busy_type);
- }
-
- ip = icalcomponent_get_next_property (fb_comp, ICAL_FREEBUSY_PROPERTY);
- }
-}
-
-static void
-process_free_busy (EMeetingModelQueueData *qdata, char *text)
-{
- EMeetingModel *im = qdata->im;
- EMeetingModelPrivate *priv;
- EMeetingAttendee *ia = qdata->ia;
- icalcomponent *main_comp;
- icalcomponent_kind kind = ICAL_NO_COMPONENT;
-
- priv = im->priv;
-
- main_comp = icalparser_parse_string (text);
- if (main_comp == NULL) {
- process_callbacks (qdata);
- return;
- }
-
- kind = icalcomponent_isa (main_comp);
- if (kind == ICAL_VCALENDAR_COMPONENT) {
- icalcompiter iter;
- icalcomponent *tz_top_level, *sub_comp;
-
- tz_top_level = cal_util_new_top_level ();
-
- iter = icalcomponent_begin_component (main_comp, ICAL_VTIMEZONE_COMPONENT);
- while ((sub_comp = icalcompiter_deref (&iter)) != NULL) {
- icalcomponent *clone;
-
- clone = icalcomponent_new_clone (sub_comp);
- icalcomponent_add_component (tz_top_level, clone);
-
- icalcompiter_next (&iter);
- }
-
- iter = icalcomponent_begin_component (main_comp, ICAL_VFREEBUSY_COMPONENT);
- while ((sub_comp = icalcompiter_deref (&iter)) != NULL) {
- process_free_busy_comp (ia, sub_comp, priv->zone, tz_top_level);
-
- icalcompiter_next (&iter);
- }
- icalcomponent_free (tz_top_level);
- } else if (kind == ICAL_VFREEBUSY_COMPONENT) {
- process_free_busy_comp (ia, main_comp, priv->zone, NULL);
- }
-
- icalcomponent_free (main_comp);
-
- process_callbacks (qdata);
-}
-
-static void
-async_close (GnomeVFSAsyncHandle *handle,
- GnomeVFSResult result,
- gpointer data)
-{
- EMeetingModelQueueData *qdata = data;
-
- process_free_busy (qdata, qdata->string->str);
-}
-
-static void
-async_read (GnomeVFSAsyncHandle *handle,
- GnomeVFSResult result,
- gpointer buffer,
- GnomeVFSFileSize requested,
- GnomeVFSFileSize read,
- gpointer data)
-{
- EMeetingModelQueueData *qdata = data;
- GnomeVFSFileSize buf_size = BUF_SIZE - 1;
-
- if (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_EOF) {
- gnome_vfs_async_close (handle, async_close, qdata);
- return;
- }
-
- ((char *)buffer)[read] = '\0';
- qdata->string = g_string_append (qdata->string, buffer);
-
- if (result == GNOME_VFS_ERROR_EOF) {
- gnome_vfs_async_close (handle, async_close, qdata);
- return;
- }
-
- gnome_vfs_async_read (handle, qdata->buffer, buf_size, async_read, qdata);
-}
-
-static void
-async_open (GnomeVFSAsyncHandle *handle,
- GnomeVFSResult result,
- gpointer data)
-{
- EMeetingModelQueueData *qdata = data;
- GnomeVFSFileSize buf_size = BUF_SIZE - 1;
-
- if (result != GNOME_VFS_OK) {
- gnome_vfs_async_close (handle, async_close, qdata);
- return;
- }
-
- gnome_vfs_async_read (handle, qdata->buffer, buf_size, async_read, qdata);
-}
-
-static void
-cursor_cb (EBook *book, EBookStatus status, ECardCursor *cursor, gpointer data)
-{
- EMeetingModelQueueData *qdata = data;
- int length, i;
-
- if (status != E_BOOK_STATUS_SUCCESS)
- return;
-
- length = e_card_cursor_get_length (cursor);
- for (i = 0; i < length; i ++) {
- GnomeVFSAsyncHandle *handle;
- ECard *card = e_card_cursor_get_nth (cursor, i);
- const char *addr;
-
- if (card->fburl == NULL)
- continue;
-
- addr = itip_strip_mailto (e_meeting_attendee_get_address (qdata->ia));
- if (!e_card_email_match_string (card, addr))
- continue;
-
- /* Read in free/busy data from the url */
- gnome_vfs_async_open (&handle, card->fburl, GNOME_VFS_OPEN_READ,
- GNOME_VFS_PRIORITY_DEFAULT, async_open, qdata);
- return;
- }
-
- process_callbacks (qdata);
-}
-
-static gboolean
-refresh_busy_periods (gpointer data)
-{
- EMeetingModel *im = E_MEETING_MODEL (data);
- EMeetingModelPrivate *priv;
- EMeetingAttendee *ia = NULL;
- EMeetingModelQueueData *qdata = NULL;
- char *query;
- int i;
-
- priv = im->priv;
-
- /* Check to see if there are any remaining attendees in the queue */
- for (i = 0; i < priv->refresh_queue->len; i++) {
- ia = g_ptr_array_index (priv->refresh_queue, i);
- g_assert (ia != NULL);
-
- qdata = g_hash_table_lookup (priv->refresh_data, ia);
- g_assert (qdata != NULL);
-
- if (!qdata->refreshing)
- break;
- }
-
- /* The everything in the queue is being refreshed */
- if (i >= priv->refresh_queue->len) {
- priv->refresh_idle_id = 0;
- return FALSE;
- }
-
- /* Indicate we are trying to refresh it */
- qdata->refreshing = TRUE;
-
- /* We take a ref in case we get destroyed in the gui during a callback */
- g_object_ref (qdata->im);
-
- /* Check the server for free busy data */
- if (priv->client) {
- GList *fb_data, *users = NULL;
- struct icaltimetype itt;
- time_t startt, endt;
- const char *user;
-
- itt = icaltime_null_time ();
- itt.year = g_date_year (&qdata->start.date);
- itt.month = g_date_month (&qdata->start.date);
- itt.day = g_date_day (&qdata->start.date);
- itt.hour = qdata->start.hour;
- itt.minute = qdata->start.minute;
- startt = icaltime_as_timet_with_zone (itt, priv->zone);
-
- itt = icaltime_null_time ();
- itt.year = g_date_year (&qdata->end.date);
- itt.month = g_date_month (&qdata->end.date);
- itt.day = g_date_day (&qdata->end.date);
- itt.hour = qdata->end.hour;
- itt.minute = qdata->end.minute;
- endt = icaltime_as_timet_with_zone (itt, priv->zone);
-
- user = itip_strip_mailto (e_meeting_attendee_get_address (ia));
- users = g_list_append (users, g_strdup (user));
- fb_data = cal_client_get_free_busy (priv->client, users, startt, endt);
-
- g_list_foreach (users, (GFunc)g_free, NULL);
- g_list_free (users);
-
- if (fb_data != NULL) {
- CalComponent *comp = fb_data->data;
- char *comp_str;
-
- comp_str = cal_component_get_as_string (comp);
- process_free_busy (qdata, comp_str);
- g_free (comp_str);
- return TRUE;
- }
- }
-
- /* Look for fburl's of attendee with no free busy info on server */
- if (!priv->book_loaded) {
- priv->book_load_wait = TRUE;
- gtk_main ();
- }
-
- if (!e_meeting_attendee_is_set_address (ia)) {
- process_callbacks (qdata);
- return TRUE;
- }
-
- query = g_strdup_printf ("(contains \"email\" \"%s\")",
- itip_strip_mailto (e_meeting_attendee_get_address (ia)));
- if (!e_book_get_cursor (priv->ebook, query, cursor_cb, qdata))
- process_callbacks (qdata);
- g_free (query);
-
- return TRUE;
-}
-
-void
-e_meeting_model_refresh_all_busy_periods (EMeetingModel *im,
- EMeetingTime *start,
- EMeetingTime *end,
- EMeetingModelRefreshCallback call_back,
- gpointer data)
-{
- EMeetingModelPrivate *priv;
- int i;
-
- g_return_if_fail (im != NULL);
- g_return_if_fail (E_IS_MEETING_MODEL (im));
-
- priv = im->priv;
-
- for (i = 0; i < priv->attendees->len; i++)
- refresh_queue_add (im, i, start, end, call_back, data);
-}
-
-void
-e_meeting_model_refresh_busy_periods (EMeetingModel *im,
- int row,
- EMeetingTime *start,
- EMeetingTime *end,
- EMeetingModelRefreshCallback call_back,
- gpointer data)
-{
- EMeetingModelPrivate *priv;
-
- g_return_if_fail (im != NULL);
- g_return_if_fail (E_IS_MEETING_MODEL (im));
-
- priv = im->priv;
-
- refresh_queue_add (im, row, start, end, call_back, data);
-}
-
-ETableScrolled *
-e_meeting_model_etable_from_model (EMeetingModel *im, const gchar *spec_file, const gchar *state_file)
-{
- EMeetingModelPrivate *priv;
- ETableScrolled *ets;
-
- g_return_val_if_fail (im != NULL, NULL);
- g_return_val_if_fail (E_IS_MEETING_MODEL (im), NULL);
-
- priv = im->priv;
-
- ets = build_etable (E_TABLE_MODEL (im), spec_file, state_file);
-
- priv->tables = g_list_prepend (priv->tables, ets);
-
- g_signal_connect (ets, "destroy", G_CALLBACK (table_destroy_list_cb), im);
-
- return ets;
-}
-
-void
-e_meeting_model_etable_click_to_add (EMeetingModel *im, gboolean click_to_add)
-{
- EMeetingModelPrivate *priv;
- GList *l;
-
- g_return_if_fail (im != NULL);
- g_return_if_fail (E_IS_MEETING_MODEL (im));
-
- priv = im->priv;
-
- for (l = priv->tables; l != NULL; l = l->next) {
- ETableScrolled *ets;
- ETable *real_table;
-
- ets = l->data;
- real_table = e_table_scrolled_get_table (ets);
-
- g_object_set (G_OBJECT (real_table), "use_click_to_add", click_to_add, NULL);
- }
-}
-
-int
-e_meeting_model_etable_model_to_view_row (ETable *et, EMeetingModel *im, int model_row)
-{
- EMeetingModelPrivate *priv;
-
- g_return_val_if_fail (im != NULL, -1);
- g_return_val_if_fail (E_IS_MEETING_MODEL (im), -1);
-
- priv = im->priv;
-
- return e_table_model_to_view_row (et, model_row);
-}
-
-int
-e_meeting_model_etable_view_to_model_row (ETable *et, EMeetingModel *im, int view_row)
-{
- EMeetingModelPrivate *priv;
-
- g_return_val_if_fail (im != NULL, -1);
- g_return_val_if_fail (E_IS_MEETING_MODEL (im), -1);
-
- priv = im->priv;
-
- return e_table_view_to_model_row (et, view_row);
-}
-
-
-static void
-add_section (GNOME_Evolution_Addressbook_SelectNames corba_select_names, const char *name)
-{
- CORBA_Environment ev;
-
- CORBA_exception_init (&ev);
-
- GNOME_Evolution_Addressbook_SelectNames_addSection (corba_select_names,
- name,
- gettext (name),
- &ev);
-
- CORBA_exception_free (&ev);
-}
-
-static gboolean
-get_select_name_dialog (EMeetingModel *im)
-{
- EMeetingModelPrivate *priv;
- CORBA_Environment ev;
- int i;
-
- priv = im->priv;
-
- if (priv->corba_select_names != CORBA_OBJECT_NIL) {
- Bonobo_Control corba_control;
- GtkWidget *control_widget;
- int i;
-
- CORBA_exception_init (&ev);
- for (i = 0; sections[i] != NULL; i++) {
- corba_control = GNOME_Evolution_Addressbook_SelectNames_getEntryBySection
- (priv->corba_select_names, sections[i], &ev);
- if (BONOBO_EX (&ev)) {
- CORBA_exception_free (&ev);
- return FALSE;
- }
-
- control_widget = bonobo_widget_new_control_from_objref (corba_control, CORBA_OBJECT_NIL);
-
- bonobo_widget_set_property (BONOBO_WIDGET (control_widget), "text", TC_CORBA_string, "", NULL);
- }
- CORBA_exception_free (&ev);
-
- return TRUE;
- }
-
- CORBA_exception_init (&ev);
-
- priv->corba_select_names = bonobo_activation_activate_from_id (SELECT_NAMES_OAFID, 0, NULL, &ev);
-
- for (i = 0; sections[i] != NULL; i++)
- add_section (priv->corba_select_names, sections[i]);
-
- bonobo_event_source_client_add_listener (priv->corba_select_names,
- (BonoboListenerCallbackFn) select_names_ok_cb,
- "GNOME/Evolution:ok:dialog",
- NULL, im);
-
- if (BONOBO_EX (&ev)) {
- CORBA_exception_free (&ev);
- return FALSE;
- }
-
- CORBA_exception_free (&ev);
-
- return TRUE;
-}
-
-void
-e_meeting_model_invite_others_dialog (EMeetingModel *im)
-{
- EMeetingModelPrivate *priv;
- CORBA_Environment ev;
-
- priv = im->priv;
-
- if (!get_select_name_dialog (im))
- return;
-
- CORBA_exception_init (&ev);
-
- GNOME_Evolution_Addressbook_SelectNames_activateDialog (
- priv->corba_select_names, _("Required Participants"), &ev);
-
- CORBA_exception_free (&ev);
-}
-
-static void
-process_section (EMeetingModel *im, GNOME_Evolution_Addressbook_SimpleCardList *cards, icalparameter_role role)
-{
- EMeetingModelPrivate *priv;
- int i;
-
- priv = im->priv;
- for (i = 0; i < cards->_length; i++) {
- EMeetingAttendee *ia;
- const char *name, *attendee = NULL, *attr;
- GNOME_Evolution_Addressbook_SimpleCard card;
- CORBA_Environment ev;
-
- card = cards->_buffer[i];
-
- CORBA_exception_init (&ev);
-
- /* Get the CN */
- name = GNOME_Evolution_Addressbook_SimpleCard_get (card, GNOME_Evolution_Addressbook_SimpleCard_FullName, &ev);
- if (BONOBO_EX (&ev)) {
- CORBA_exception_free (&ev);
- continue;
- }
-
- /* Get the field as attendee from the backend */
- attr = cal_client_get_ldap_attribute (priv->client);
- if (attr) {
- /* FIXME this should be more general */
- if (!strcmp (attr, "icscalendar"))
- attendee = GNOME_Evolution_Addressbook_SimpleCard_get (card, GNOME_Evolution_Addressbook_SimpleCard_Icscalendar, &ev);
- }
-
- CORBA_exception_init (&ev);
-
- /* If we couldn't get the attendee prior, get the email address as the default */
- if (attendee == NULL || *attendee == '\0') {
- attendee = GNOME_Evolution_Addressbook_SimpleCard_get (card, GNOME_Evolution_Addressbook_SimpleCard_Email, &ev);
- if (BONOBO_EX (&ev)) {
- CORBA_exception_free (&ev);
- continue;
- }
- }
-
- CORBA_exception_free (&ev);
-
- if (attendee == NULL || *attendee == '\0')
- continue;
-
- if (e_meeting_model_find_attendee (im, attendee, NULL) == NULL) {
- ia = e_meeting_model_add_attendee_with_defaults (im);
-
- e_meeting_attendee_set_address (ia, g_strdup_printf ("MAILTO:%s", attendee));
- e_meeting_attendee_set_role (ia, role);
- if (role == ICAL_ROLE_NONPARTICIPANT)
- e_meeting_attendee_set_cutype (ia, ICAL_CUTYPE_RESOURCE);
- e_meeting_attendee_set_cn (ia, g_strdup (name));
- }
- }
-}
-
-static void
-select_names_ok_cb (BonoboListener *listener,
- const char *event_name,
- const CORBA_any *arg,
- CORBA_Environment *ev,
- gpointer data)
-{
- EMeetingModel *im = data;
- EMeetingModelPrivate *priv;
- Bonobo_Control corba_control;
- GtkWidget *control_widget;
- BonoboControlFrame *control_frame;
- Bonobo_PropertyBag pb;
- BonoboArg *card_arg;
- GNOME_Evolution_Addressbook_SimpleCardList cards;
- int i;
-
- priv = im->priv;
-
- for (i = 0; sections[i] != NULL; i++) {
- corba_control = GNOME_Evolution_Addressbook_SelectNames_getEntryBySection
- (priv->corba_select_names, sections[i], ev);
- control_widget = bonobo_widget_new_control_from_objref
- (corba_control, CORBA_OBJECT_NIL);
-
- control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (control_widget));
- pb = bonobo_control_frame_get_control_property_bag (control_frame, NULL);
- card_arg = bonobo_property_bag_client_get_value_any (pb, "simple_card_list", NULL);
- if (card_arg != NULL) {
- cards = BONOBO_ARG_GET_GENERAL (card_arg, TC_GNOME_Evolution_Addressbook_SimpleCardList, GNOME_Evolution_Addressbook_SimpleCardList, NULL);
- process_section (im, &cards, roles[i]);
- bonobo_arg_release (card_arg);
- }
- }
-}
-
-static void
-attendee_changed_cb (EMeetingAttendee *ia, gpointer data)
-{
- EMeetingModel *im = E_MEETING_MODEL (data);
- EMeetingModelPrivate *priv;
- gint row = -1, i;
-
- priv = im->priv;
-
- /* FIXME: Ideally I think you are supposed to call pre_change() before
- the data structures are changed. */
- e_table_model_pre_change (E_TABLE_MODEL (im));
-
- for (i = 0; i < priv->attendees->len; i++) {
- if (ia == g_ptr_array_index (priv->attendees, i)) {
- row = i;
- break;
- }
- }
-
- if (row == -1)
- e_table_model_no_change (E_TABLE_MODEL (im));
- else
- e_table_model_row_changed (E_TABLE_MODEL (im), row);
-}
-
-static void
-table_destroy_state_cb (ETableScrolled *etable, gpointer data)
-{
- ETable *real_table;
- char *filename = data;
-
- real_table = e_table_scrolled_get_table (etable);
- e_table_save_state (real_table, filename);
-
- g_free (data);
-}
-
-static void
-table_destroy_list_cb (ETableScrolled *etable, gpointer data)
-{
- EMeetingModel *im = E_MEETING_MODEL (data);
- EMeetingModelPrivate *priv;
-
- priv = im->priv;
-
- priv->tables = g_list_remove (priv->tables, etable);
-}
-
diff --git a/calendar/gui/e-meeting-model.h b/calendar/gui/e-meeting-model.h
deleted file mode 100644
index 50fba6c7a6..0000000000
--- a/calendar/gui/e-meeting-model.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-model.h
- *
- * Copyright (C) 2001 Ximian, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: JP Rosevear
- */
-
-#ifndef _E_MEETING_MODEL_H_
-#define _E_MEETING_MODEL_H_
-
-#include <gtk/gtk.h>
-#include <gal/e-table/e-table-scrolled.h>
-#include <gal/e-table/e-table-model.h>
-#include <cal-client/cal-client.h>
-#include "e-meeting-attendee.h"
-
-G_BEGIN_DECLS
-
-#define E_TYPE_MEETING_MODEL (e_meeting_model_get_type ())
-#define E_MEETING_MODEL(obj) (GTK_CHECK_CAST ((obj), E_TYPE_MEETING_MODEL, EMeetingModel))
-#define E_MEETING_MODEL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_MEETING_MODEL, EMeetingModelClass))
-#define E_IS_MEETING_MODEL(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_MEETING_MODEL))
-#define E_IS_MEETING_MODEL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_MEETING_MODEL))
-
-
-typedef struct _EMeetingModel EMeetingModel;
-typedef struct _EMeetingModelPrivate EMeetingModelPrivate;
-typedef struct _EMeetingModelClass EMeetingModelClass;
-
-typedef enum {
- E_MEETING_MODEL_ADDRESS_COL,
- E_MEETING_MODEL_MEMBER_COL,
- E_MEETING_MODEL_TYPE_COL,
- E_MEETING_MODEL_ROLE_COL,
- E_MEETING_MODEL_RSVP_COL,
- E_MEETING_MODEL_DELTO_COL,
- E_MEETING_MODEL_DELFROM_COL,
- E_MEETING_MODEL_STATUS_COL,
- E_MEETING_MODEL_CN_COL,
- E_MEETING_MODEL_LANGUAGE_COL,
- E_MEETING_MODEL_COLUMN_COUNT
-} EMeetingModelColumns;
-
-struct _EMeetingModel {
- ETableModel parent;
-
- EMeetingModelPrivate *priv;
-};
-
-struct _EMeetingModelClass {
- ETableModelClass parent_class;
-};
-
-typedef void (* EMeetingModelRefreshCallback) (gpointer data);
-
-
-GtkType e_meeting_model_get_type (void);
-GtkObject *e_meeting_model_new (void);
-
-CalClient *e_meeting_model_get_cal_client (EMeetingModel *im);
-void e_meeting_model_set_cal_client (EMeetingModel *im, CalClient *client);
-
-icaltimezone *e_meeting_model_get_zone (EMeetingModel *im);
-void e_meeting_model_set_zone (EMeetingModel *im, icaltimezone *zone);
-
-void e_meeting_model_add_attendee (EMeetingModel *im, EMeetingAttendee *ia);
-EMeetingAttendee *e_meeting_model_add_attendee_with_defaults (EMeetingModel *im);
-
-void e_meeting_model_remove_attendee (EMeetingModel *im, EMeetingAttendee *ia);
-void e_meeting_model_remove_all_attendees (EMeetingModel *im);
-
-EMeetingAttendee *e_meeting_model_find_attendee (EMeetingModel *im, const gchar *address, gint *row);
-EMeetingAttendee *e_meeting_model_find_attendee_at_row (EMeetingModel *im, gint row);
-
-gint e_meeting_model_count_actual_attendees (EMeetingModel *im);
-const GPtrArray *e_meeting_model_get_attendees (EMeetingModel *im);
-
-void e_meeting_model_refresh_all_busy_periods (EMeetingModel *im,
- EMeetingTime *start,
- EMeetingTime *end,
- EMeetingModelRefreshCallback call_back,
- gpointer data);
-void e_meeting_model_refresh_busy_periods (EMeetingModel *im,
- int row,
- EMeetingTime *start,
- EMeetingTime *end,
- EMeetingModelRefreshCallback call_back,
- gpointer data);
-
-
-/* Helpful functions */
-ETableScrolled *e_meeting_model_etable_from_model (EMeetingModel *im, const gchar *spec_file, const gchar *state_file);
-void e_meeting_model_etable_click_to_add (EMeetingModel *im, gboolean click_to_add);
-int e_meeting_model_etable_model_to_view_row (ETable *et, EMeetingModel *im, int model_row);
-int e_meeting_model_etable_view_to_model_row (ETable *et, EMeetingModel *im, int view_row);
-
-void e_meeting_model_invite_others_dialog (EMeetingModel *im);
-
-G_END_DECLS
-
-#endif
diff --git a/calendar/gui/e-meeting-store.c b/calendar/gui/e-meeting-store.c
new file mode 100644
index 0000000000..0129756e7c
--- /dev/null
+++ b/calendar/gui/e-meeting-store.c
@@ -0,0 +1,1317 @@
+/*
+ * e-meeting-store.c
+ *
+ * Copyright (C) 2001-2003 Ximian, Inc.
+ *
+ * Authors: JP Rosevear <jpr@ximian.com>
+ * Mike Kestner <mkestner@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 <libgnome/gnome-util.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <ebook/e-book.h>
+#include <ebook/e-book-util.h>
+#include <cal-util/cal-component.h>
+#include <cal-util/cal-util.h>
+#include <cal-util/timeutil.h>
+#include "calendar-config.h"
+#include "itip-utils.h"
+#include "e-meeting-utils.h"
+#include "e-meeting-attendee.h"
+#include "e-meeting-store.h"
+
+#define ROW_VALID(store, row) (row >= 0 && row < store->priv->attendees->len)
+
+struct _EMeetingStorePrivate {
+ GPtrArray *attendees;
+ gint stamp;
+
+ CalClient *client;
+ icaltimezone *zone;
+
+ EBook *ebook;
+ gboolean book_loaded;
+ gboolean book_load_wait;
+
+ GPtrArray *refresh_queue;
+ GHashTable *refresh_data;
+ guint refresh_idle_id;
+};
+
+#define BUF_SIZE 1024
+
+typedef struct _EMeetingStoreQueueData EMeetingStoreQueueData;
+struct _EMeetingStoreQueueData {
+ EMeetingStore *store;
+ EMeetingAttendee *attendee;
+
+ gboolean refreshing;
+
+ EMeetingTime start;
+ EMeetingTime end;
+
+ char buffer[BUF_SIZE];
+ GString *string;
+
+ GPtrArray *call_backs;
+ GPtrArray *data;
+};
+
+
+static GObjectClass *parent_class = NULL;
+
+static void
+book_open_cb (EBook *book, EBookStatus status, gpointer data)
+{
+ EMeetingStore *store = E_MEETING_STORE (data);
+
+ if (status == E_BOOK_STATUS_SUCCESS)
+ store->priv->book_loaded = TRUE;
+ else
+ g_warning ("Book not loaded");
+
+ if (store->priv->book_load_wait) {
+ store->priv->book_load_wait = FALSE;
+ gtk_main_quit ();
+ }
+}
+
+static void
+start_addressbook_server (EMeetingStore *store)
+{
+ store->priv->ebook = e_book_new ();
+ e_book_load_default_book (store->priv->ebook, book_open_cb, store);
+}
+
+static icalparameter_cutype
+text_to_type (const char *type)
+{
+ if (!g_strcasecmp (type, _("Individual")))
+ return ICAL_CUTYPE_INDIVIDUAL;
+ else if (!g_strcasecmp (type, _("Group")))
+ return ICAL_CUTYPE_GROUP;
+ else if (!g_strcasecmp (type, _("Resource")))
+ return ICAL_CUTYPE_RESOURCE;
+ else if (!g_strcasecmp (type, _("Room")))
+ return ICAL_CUTYPE_ROOM;
+ else
+ return ICAL_CUTYPE_NONE;
+}
+
+static char *
+type_to_text (icalparameter_cutype type)
+{
+ switch (type) {
+ case ICAL_CUTYPE_INDIVIDUAL:
+ return _("Individual");
+ case ICAL_CUTYPE_GROUP:
+ return _("Group");
+ case ICAL_CUTYPE_RESOURCE:
+ return _("Resource");
+ case ICAL_CUTYPE_ROOM:
+ return _("Room");
+ default:
+ return _("Unknown");
+ }
+
+ return NULL;
+
+}
+
+static icalparameter_role
+text_to_role (const char *role)
+{
+ if (!g_strcasecmp (role, _("Chair")))
+ return ICAL_ROLE_CHAIR;
+ else if (!g_strcasecmp (role, _("Required Participant")))
+ return ICAL_ROLE_REQPARTICIPANT;
+ else if (!g_strcasecmp (role, _("Optional Participant")))
+ return ICAL_ROLE_OPTPARTICIPANT;
+ else if (!g_strcasecmp (role, _("Non-Participant")))
+ return ICAL_ROLE_NONPARTICIPANT;
+ else
+ return ICAL_ROLE_NONE;
+}
+
+static char *
+role_to_text (icalparameter_role role)
+{
+ switch (role) {
+ case ICAL_ROLE_CHAIR:
+ return _("Chair");
+ case ICAL_ROLE_REQPARTICIPANT:
+ return _("Required Participant");
+ case ICAL_ROLE_OPTPARTICIPANT:
+ return _("Optional Participant");
+ case ICAL_ROLE_NONPARTICIPANT:
+ return _("Non-Participant");
+ default:
+ return _("Unknown");
+ }
+
+ return NULL;
+}
+
+static gboolean
+text_to_boolean (const char *role)
+{
+ if (!g_strcasecmp (role, _("Yes")))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static char *
+boolean_to_text (gboolean b)
+{
+ if (b)
+ return _("Yes");
+ else
+ return _("No");
+}
+
+static icalparameter_partstat
+text_to_partstat (const char *partstat)
+{
+ if (!g_strcasecmp (partstat, _("Needs Action")))
+ return ICAL_PARTSTAT_NEEDSACTION;
+ else if (!g_strcasecmp (partstat, _("Accepted")))
+ return ICAL_PARTSTAT_ACCEPTED;
+ else if (!g_strcasecmp (partstat, _("Declined")))
+ return ICAL_PARTSTAT_DECLINED;
+ else if (!g_strcasecmp (partstat, _("Tentative")))
+ return ICAL_PARTSTAT_TENTATIVE;
+ else if (!g_strcasecmp (partstat, _("Delegated")))
+ return ICAL_PARTSTAT_DELEGATED;
+ else if (!g_strcasecmp (partstat, _("Completed")))
+ return ICAL_PARTSTAT_COMPLETED;
+ else if (!g_strcasecmp (partstat, _("In Process")))
+ return ICAL_PARTSTAT_INPROCESS;
+ else
+ return ICAL_PARTSTAT_NONE;
+}
+
+static char *
+partstat_to_text (icalparameter_partstat partstat)
+{
+ switch (partstat) {
+ case ICAL_PARTSTAT_NEEDSACTION:
+ return _("Needs Action");
+ case ICAL_PARTSTAT_ACCEPTED:
+ return _("Accepted");
+ case ICAL_PARTSTAT_DECLINED:
+ return _("Declined");
+ case ICAL_PARTSTAT_TENTATIVE:
+ return _("Tentative");
+ case ICAL_PARTSTAT_DELEGATED:
+ return _("Delegated");
+ case ICAL_PARTSTAT_COMPLETED:
+ return _("Completed");
+ case ICAL_PARTSTAT_INPROCESS:
+ return _("In Process");
+ case ICAL_PARTSTAT_NONE:
+ default:
+ return _("Unknown");
+ }
+
+ return NULL;
+}
+
+static GtkTreeModelFlags
+get_flags (GtkTreeModel *model)
+{
+ g_return_val_if_fail (E_IS_MEETING_STORE (model), 0);
+
+ return GTK_TREE_MODEL_ITERS_PERSIST | GTK_TREE_MODEL_LIST_ONLY;
+}
+
+static int
+get_n_columns (GtkTreeModel *model)
+{
+ g_return_val_if_fail (E_IS_MEETING_STORE (model), 0);
+
+ return E_MEETING_STORE_COLUMN_COUNT;
+}
+
+static GType
+get_column_type (GtkTreeModel *model, int col)
+{
+ g_return_val_if_fail (E_IS_MEETING_STORE (model), G_TYPE_INVALID);
+
+ switch (col) {
+ case E_MEETING_STORE_ADDRESS_COL:
+ case E_MEETING_STORE_MEMBER_COL:
+ case E_MEETING_STORE_TYPE_COL:
+ case E_MEETING_STORE_ROLE_COL:
+ case E_MEETING_STORE_RSVP_COL:
+ case E_MEETING_STORE_DELTO_COL:
+ case E_MEETING_STORE_DELFROM_COL:
+ case E_MEETING_STORE_STATUS_COL:
+ case E_MEETING_STORE_CN_COL:
+ case E_MEETING_STORE_LANGUAGE_COL:
+ case E_MEETING_STORE_ATTENDEE_COL:
+ return G_TYPE_STRING;
+ case E_MEETING_STORE_ATTENDEE_UNDERLINE_COL:
+ return PANGO_TYPE_UNDERLINE;
+ default:
+ return G_TYPE_INVALID;
+ }
+}
+
+static gboolean
+get_iter (GtkTreeModel *model, GtkTreeIter *iter, GtkTreePath *path)
+{
+ int row;
+
+ g_return_val_if_fail (E_IS_MEETING_STORE (model), FALSE);
+ g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
+
+ row = gtk_tree_path_get_indices (path) [0];
+
+ if (!ROW_VALID (E_MEETING_STORE (model), row))
+ return FALSE;
+
+ iter->stamp = E_MEETING_STORE (model)->priv->stamp;
+ iter->user_data = GINT_TO_POINTER (row);
+
+ return TRUE;
+}
+
+static GtkTreePath *
+get_path (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ int row;
+ GtkTreePath *result;
+
+ g_return_val_if_fail (E_IS_MEETING_STORE (model), NULL);
+ g_return_val_if_fail (iter->stamp == E_MEETING_STORE (model)->priv->stamp, NULL);
+
+ row = GPOINTER_TO_INT (iter->user_data);
+
+ g_return_val_if_fail (ROW_VALID (E_MEETING_STORE (model), row), NULL);
+
+ result = gtk_tree_path_new ();
+ gtk_tree_path_append_index (result, row);
+ return result;
+}
+
+static void
+get_value (GtkTreeModel *model, GtkTreeIter *iter, int col, GValue *value)
+{
+ EMeetingStore *store;
+ EMeetingAttendee *attendee;
+ const gchar *cn;
+ int row;
+
+ g_return_if_fail (E_IS_MEETING_STORE (model));
+ g_return_if_fail (col >= 0 && col < E_MEETING_STORE_COLUMN_COUNT);
+
+ row = GPOINTER_TO_INT (iter->user_data);
+ store = E_MEETING_STORE (model);
+
+ g_return_if_fail (iter->stamp == store->priv->stamp);
+ g_return_if_fail (ROW_VALID (E_MEETING_STORE (model), row));
+
+ attendee = g_ptr_array_index (store->priv->attendees, row);
+
+ switch (col) {
+ case E_MEETING_STORE_ADDRESS_COL:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, itip_strip_mailto (e_meeting_attendee_get_address (attendee)));
+ break;
+ case E_MEETING_STORE_MEMBER_COL:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, e_meeting_attendee_get_member (attendee));
+ break;
+ case E_MEETING_STORE_TYPE_COL:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, type_to_text (e_meeting_attendee_get_cutype (attendee)));
+ break;
+ case E_MEETING_STORE_ROLE_COL:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, role_to_text (e_meeting_attendee_get_role (attendee)));
+ break;
+ case E_MEETING_STORE_RSVP_COL:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, boolean_to_text (e_meeting_attendee_get_rsvp (attendee)));
+ break;
+ case E_MEETING_STORE_DELTO_COL:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, itip_strip_mailto (e_meeting_attendee_get_delto (attendee)));
+ break;
+ case E_MEETING_STORE_DELFROM_COL:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, itip_strip_mailto (e_meeting_attendee_get_delfrom (attendee)));
+ break;
+ case E_MEETING_STORE_STATUS_COL:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, partstat_to_text (e_meeting_attendee_get_status (attendee)));
+ break;
+ case E_MEETING_STORE_CN_COL:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, e_meeting_attendee_get_cn (attendee));
+ break;
+ case E_MEETING_STORE_LANGUAGE_COL:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, e_meeting_attendee_get_language (attendee));
+ break;
+ case E_MEETING_STORE_ATTENDEE_COL:
+ g_value_init (value, G_TYPE_STRING);
+ cn = e_meeting_attendee_get_cn (attendee);
+ if (strcmp (cn, ""))
+ g_value_set_string (value, cn);
+ else
+ g_value_set_string (value, itip_strip_mailto (e_meeting_attendee_get_address (attendee)));
+ break;
+ case E_MEETING_STORE_ATTENDEE_UNDERLINE_COL:
+ cn = e_meeting_attendee_get_cn (attendee);
+ g_value_init (value, PANGO_TYPE_UNDERLINE);
+ g_value_set_enum (value, strcmp ("", cn) == 0 ? PANGO_UNDERLINE_NONE : PANGO_UNDERLINE_SINGLE);
+ }
+}
+
+static gboolean
+iter_next (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ int row;
+
+ g_return_val_if_fail (E_IS_MEETING_STORE (model), FALSE);
+ g_return_val_if_fail (iter->stamp == E_MEETING_STORE (model)->priv->stamp, FALSE);
+
+ row = GPOINTER_TO_INT (iter->user_data) + 1;
+ iter->user_data = GINT_TO_POINTER (row);
+
+ return ROW_VALID (E_MEETING_STORE (model), row);
+}
+
+static gboolean
+iter_children (GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *parent)
+{
+ EMeetingStore *store;
+
+ g_return_val_if_fail (E_IS_MEETING_STORE (model), FALSE);
+
+ store = E_MEETING_STORE (model);
+
+ if (parent || store->priv->attendees->len <= 0)
+ return FALSE;
+
+ iter->stamp = store->priv->stamp;
+ iter->user_data = GINT_TO_POINTER (0);
+
+ return TRUE;
+}
+
+static gboolean
+iter_has_child (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ return FALSE;
+}
+
+static int
+iter_n_children (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ g_return_val_if_fail (E_IS_MEETING_STORE (model), -1);
+
+ if (!iter)
+ return E_MEETING_STORE (model)->priv->attendees->len;
+
+ g_return_val_if_fail (iter->stamp == E_MEETING_STORE (model)->priv->stamp, -1);
+
+ return 0;
+}
+
+static gboolean
+iter_nth_child (GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *parent, int n)
+{
+ EMeetingStore *store;
+
+ g_return_val_if_fail (E_IS_MEETING_STORE (model), FALSE);
+
+ store = E_MEETING_STORE (model);
+
+ if (parent || !ROW_VALID (store, n))
+ return FALSE;
+
+ iter->stamp = store->priv->stamp;
+ iter->user_data = GINT_TO_POINTER (n);
+
+ return TRUE;
+}
+
+static gboolean
+iter_parent (GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *child)
+{
+ return FALSE;
+}
+
+static void
+ems_tree_model_init (GtkTreeModelIface *iface)
+{
+ iface->get_flags = get_flags;
+ iface->get_n_columns = get_n_columns;
+ iface->get_column_type = get_column_type;
+ iface->get_iter = get_iter;
+ iface->get_path = get_path;
+ iface->get_value = get_value;
+ iface->iter_next = iter_next;
+ iface->iter_children = iter_children;
+ iface->iter_has_child = iter_has_child;
+ iface->iter_n_children = iter_n_children;
+ iface->iter_nth_child = iter_nth_child;
+ iface->iter_parent = iter_parent;
+}
+
+void
+e_meeting_store_set_value (EMeetingStore *store, int row, int col, const gchar *val)
+{
+ icalparameter_cutype type;
+ EMeetingAttendee *attendee = g_ptr_array_index (store->priv->attendees, row);
+
+ switch (col) {
+ case E_MEETING_STORE_ADDRESS_COL:
+ if (val != NULL && *((char *)val))
+ e_meeting_attendee_set_address (attendee, g_strdup_printf ("MAILTO:%s", (char *) val));
+ break;
+ case E_MEETING_STORE_MEMBER_COL:
+ e_meeting_attendee_set_member (attendee, g_strdup (val));
+ break;
+ case E_MEETING_STORE_TYPE_COL:
+ type = text_to_type (val);
+ e_meeting_attendee_set_cutype (attendee, text_to_type (val));
+ if (type == ICAL_CUTYPE_RESOURCE) {
+ e_meeting_attendee_set_role (attendee, ICAL_ROLE_NONPARTICIPANT);
+ }
+ break;
+ case E_MEETING_STORE_ROLE_COL:
+ e_meeting_attendee_set_role (attendee, text_to_role (val));
+ break;
+ case E_MEETING_STORE_RSVP_COL:
+ e_meeting_attendee_set_rsvp (attendee, text_to_boolean (val));
+ break;
+ case E_MEETING_STORE_DELTO_COL:
+ e_meeting_attendee_set_delto (attendee, g_strdup (val));
+ break;
+ case E_MEETING_STORE_DELFROM_COL:
+ e_meeting_attendee_set_delfrom (attendee, g_strdup (val));
+ break;
+ case E_MEETING_STORE_STATUS_COL:
+ e_meeting_attendee_set_status (attendee, text_to_partstat (val));
+ break;
+ case E_MEETING_STORE_CN_COL:
+ e_meeting_attendee_set_cn (attendee, g_strdup (val));
+ break;
+ case E_MEETING_STORE_LANGUAGE_COL:
+ e_meeting_attendee_set_language (attendee, g_strdup (val));
+ break;
+ }
+}
+
+static gboolean
+is_cell_editable (EMeetingStore *etm, int col, int row)
+{
+ EMeetingStore *store;
+ EMeetingStorePrivate *priv;
+ EMeetingAttendee *attendee;
+ EMeetingAttendeeEditLevel level;
+
+ store = E_MEETING_STORE (etm);
+ priv = store->priv;
+
+ if (col == E_MEETING_STORE_DELTO_COL
+ || col == E_MEETING_STORE_DELFROM_COL)
+ return FALSE;
+
+ if (row == -1)
+ return TRUE;
+ if (row >= priv->attendees->len)
+ return TRUE;
+
+ attendee = g_ptr_array_index (priv->attendees, row);
+ level = e_meeting_attendee_get_edit_level (attendee);
+
+ switch (level) {
+ case E_MEETING_ATTENDEE_EDIT_FULL:
+ return TRUE;
+ case E_MEETING_ATTENDEE_EDIT_STATUS:
+ return col == E_MEETING_STORE_STATUS_COL;
+ case E_MEETING_ATTENDEE_EDIT_NONE:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+refresh_queue_remove (EMeetingStore *store, EMeetingAttendee *attendee)
+{
+ EMeetingStorePrivate *priv;
+ EMeetingStoreQueueData *qdata;
+
+ priv = store->priv;
+
+ /* Free the queue data */
+ qdata = g_hash_table_lookup (priv->refresh_data, attendee);
+ if (qdata) {
+ g_hash_table_remove (priv->refresh_data, attendee);
+ g_ptr_array_free (qdata->call_backs, TRUE);
+ g_ptr_array_free (qdata->data, TRUE);
+ g_free (qdata);
+ }
+
+ /* Unref the attendee */
+ g_ptr_array_remove (priv->refresh_queue, attendee);
+ g_object_unref (attendee);
+}
+
+static void
+ems_finalize (GObject *obj)
+{
+ EMeetingStore *store = E_MEETING_STORE (obj);
+ EMeetingStorePrivate *priv;
+ int i;
+
+ priv = store->priv;
+
+ for (i = 0; i < priv->attendees->len; i++)
+ g_object_unref (g_ptr_array_index (priv->attendees, i));
+ g_ptr_array_free (priv->attendees, TRUE);
+
+ if (priv->client != NULL)
+ g_object_unref (priv->client);
+
+ if (priv->ebook != NULL)
+ g_object_unref (priv->ebook);
+
+ while (priv->refresh_queue->len > 0)
+ refresh_queue_remove (store, g_ptr_array_index (priv->refresh_queue, 0));
+ g_ptr_array_free (priv->refresh_queue, TRUE);
+ g_hash_table_destroy (priv->refresh_data);
+
+ if (priv->refresh_idle_id)
+ g_source_remove (priv->refresh_idle_id);
+
+ g_free (priv);
+
+ if (G_OBJECT_CLASS (parent_class)->finalize)
+ (* G_OBJECT_CLASS (parent_class)->finalize) (obj);
+}
+
+static void
+ems_class_init (GObjectClass *klass)
+{
+ parent_class = g_type_class_peek_parent (klass);
+
+ klass->finalize = ems_finalize;
+}
+
+
+static void
+ems_init (EMeetingStore *store)
+{
+ EMeetingStorePrivate *priv;
+
+ priv = g_new0 (EMeetingStorePrivate, 1);
+
+ store->priv = priv;
+
+ priv->attendees = g_ptr_array_new ();
+
+ priv->zone = icaltimezone_get_builtin_timezone (calendar_config_get_timezone ());
+
+ priv->refresh_queue = g_ptr_array_new ();
+ priv->refresh_data = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ start_addressbook_server (store);
+}
+
+GType
+e_meeting_store_get_type (void)
+{
+ static GType ems_type = 0;
+
+ if (!ems_type) {
+ static const GTypeInfo ems_info = {
+ sizeof (GtkListStoreClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) ems_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (GtkListStore),
+ 0,
+ (GInstanceInitFunc) ems_init };
+
+ static const GInterfaceInfo tree_model_info = {
+ (GInterfaceInitFunc) ems_tree_model_init,
+ NULL,
+ NULL };
+
+ ems_type = g_type_register_static (G_TYPE_OBJECT,
+ "EMeetingStore",
+ &ems_info, 0);
+
+ g_type_add_interface_static (ems_type,
+ GTK_TYPE_TREE_MODEL,
+ &tree_model_info);
+ }
+
+ return ems_type;
+}
+
+GObject *
+e_meeting_store_new (void)
+{
+ return g_object_new (E_TYPE_MEETING_STORE, NULL);
+}
+
+
+CalClient *
+e_meeting_store_get_cal_client (EMeetingStore *store)
+{
+ return store->priv->client;
+}
+
+void
+e_meeting_store_set_cal_client (EMeetingStore *store, CalClient *client)
+{
+ if (store->priv->client != NULL)
+ g_object_unref (store->priv->client);
+
+ if (client != NULL)
+ g_object_ref (client);
+ store->priv->client = client;
+}
+
+icaltimezone *
+e_meeting_store_get_zone (EMeetingStore *store)
+{
+ g_return_val_if_fail (E_IS_MEETING_STORE (store), NULL);
+
+ return store->priv->zone;
+}
+
+void
+e_meeting_store_set_zone (EMeetingStore *store, icaltimezone *zone)
+{
+ g_return_if_fail (E_IS_MEETING_STORE (store));
+
+ store->priv->zone = zone;
+}
+
+static void
+attendee_changed_cb (EMeetingAttendee *attendee, gpointer data)
+{
+ EMeetingStore *store = E_MEETING_STORE (data);
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ gint row = -1, i;
+
+ for (i = 0; i < store->priv->attendees->len; i++) {
+ if (attendee == g_ptr_array_index (store->priv->attendees, i)) {
+ row = i;
+ break;
+ }
+ }
+
+ if (row == -1)
+ return;
+
+ path = gtk_tree_path_new ();
+ gtk_tree_path_append_index (path, row);
+ get_iter (GTK_TREE_MODEL (store), &iter, path);
+ gtk_tree_model_row_changed (GTK_TREE_MODEL (store), path, &iter);
+ gtk_tree_path_free (path);
+}
+
+void
+e_meeting_store_add_attendee (EMeetingStore *store, EMeetingAttendee *attendee)
+{
+ GtkTreePath *path;
+ GtkTreeIter iter;
+
+ g_return_if_fail (E_IS_MEETING_STORE (store));
+
+ g_object_ref (attendee);
+ g_ptr_array_add (store->priv->attendees, attendee);
+
+ g_signal_connect (attendee, "changed", G_CALLBACK (attendee_changed_cb), store);
+
+ path = gtk_tree_path_new ();
+ gtk_tree_path_append_index (path, store->priv->attendees->len - 1);
+ get_iter (GTK_TREE_MODEL (store), &iter, path);
+ gtk_tree_model_row_inserted (GTK_TREE_MODEL (store), path, &iter);
+ gtk_tree_path_free (path);
+}
+
+EMeetingAttendee *
+e_meeting_store_add_attendee_with_defaults (EMeetingStore *store)
+{
+ EMeetingAttendee *attendee;
+ char *str;
+
+ attendee = E_MEETING_ATTENDEE (e_meeting_attendee_new ());
+
+ e_meeting_attendee_set_address (attendee, g_strdup (""));
+ e_meeting_attendee_set_member (attendee, g_strdup (""));
+
+ str = g_strdup (_("Individual"));
+ e_meeting_attendee_set_cutype (attendee, text_to_type (str));
+ g_free (str);
+ str = g_strdup (_("Required Participant"));
+ e_meeting_attendee_set_role (attendee, text_to_role (str));
+ g_free (str);
+ str = g_strdup (_("Yes"));
+ e_meeting_attendee_set_rsvp (attendee, text_to_boolean (str));
+ g_free (str);
+
+ e_meeting_attendee_set_delto (attendee, g_strdup (""));
+ e_meeting_attendee_set_delfrom (attendee, g_strdup (""));
+
+ str = g_strdup (_("Needs Action"));
+ e_meeting_attendee_set_status (attendee, text_to_partstat (str));
+ g_free (str);
+
+ e_meeting_attendee_set_cn (attendee, g_strdup (""));
+ e_meeting_attendee_set_language (attendee, g_strdup ("en"));
+
+ e_meeting_store_add_attendee (store, attendee);
+
+ return attendee;
+}
+
+void
+e_meeting_store_remove_attendee (EMeetingStore *store, EMeetingAttendee *attendee)
+{
+ gint i, row = -1;
+ GtkTreePath *path;
+
+ for (i = 0; i < store->priv->attendees->len; i++) {
+ if (attendee == g_ptr_array_index (store->priv->attendees, i)) {
+ row = i;
+ break;
+ }
+ }
+
+ if (row != -1) {
+ g_ptr_array_remove_index (store->priv->attendees, row);
+ g_object_unref (attendee);
+
+ path = gtk_tree_path_new ();
+ gtk_tree_path_append_index (path, row);
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (store), path);
+ gtk_tree_path_free (path);
+ }
+}
+
+void
+e_meeting_store_remove_all_attendees (EMeetingStore *store)
+{
+ gint i;
+ GtkTreePath *path = gtk_tree_path_new ();
+
+ gtk_tree_path_append_index (path, 0);
+
+ for (i = 0; i < store->priv->attendees->len; i++) {
+ EMeetingAttendee *attendee = g_ptr_array_index (store->priv->attendees, i);
+ g_object_unref (attendee);
+
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (store), path);
+ gtk_tree_path_next (path);
+ }
+
+ g_ptr_array_set_size (store->priv->attendees, 0);
+ gtk_tree_path_free (path);
+}
+
+EMeetingAttendee *
+e_meeting_store_find_attendee (EMeetingStore *store, const gchar *address, gint *row)
+{
+ EMeetingAttendee *attendee;
+ int i;
+
+ if (address == NULL)
+ return NULL;
+
+ for (i = 0; i < store->priv->attendees->len; i++) {
+ const gchar *attendee_address;
+
+ attendee = g_ptr_array_index (store->priv->attendees, i);
+
+ attendee_address = e_meeting_attendee_get_address (attendee);
+ if (attendee_address && !g_strcasecmp (itip_strip_mailto (attendee_address), itip_strip_mailto (address))) {
+ if (row != NULL)
+ *row = i;
+
+ return attendee;
+ }
+ }
+
+ return NULL;
+}
+
+EMeetingAttendee *
+e_meeting_store_find_attendee_at_row (EMeetingStore *store, gint row)
+{
+ g_return_val_if_fail (E_IS_MEETING_STORE (store), NULL);
+ g_return_val_if_fail (ROW_VALID (store, row), NULL);
+
+ return g_ptr_array_index (store->priv->attendees, row);
+}
+
+gint
+e_meeting_store_count_actual_attendees (EMeetingStore *store)
+{
+ g_return_val_if_fail (E_IS_MEETING_STORE (store), 0);
+
+ return store->priv->attendees->len;
+}
+
+const GPtrArray *
+e_meeting_store_get_attendees (EMeetingStore *store)
+{
+ g_return_val_if_fail (E_IS_MEETING_STORE (store), NULL);
+
+ return store->priv->attendees;
+}
+
+static icaltimezone *
+find_zone (icalproperty *ip, icalcomponent *tz_top_level)
+{
+ icalparameter *param;
+ icalcomponent *sub_comp;
+ const char *tzid;
+ icalcompiter iter;
+
+ if (tz_top_level == NULL)
+ return NULL;
+
+ param = icalproperty_get_first_parameter (ip, ICAL_TZID_PARAMETER);
+ if (param == NULL)
+ return NULL;
+ tzid = icalparameter_get_tzid (param);
+
+ iter = icalcomponent_begin_component (tz_top_level, ICAL_VTIMEZONE_COMPONENT);
+ while ((sub_comp = icalcompiter_deref (&iter)) != NULL) {
+ icalcomponent *clone;
+ const char *tz_tzid;
+
+ tz_tzid = icalproperty_get_tzid (sub_comp);
+ if (!strcmp (tzid, tz_tzid)) {
+ icaltimezone *zone;
+
+ zone = icaltimezone_new ();
+ clone = icalcomponent_new_clone (sub_comp);
+ icaltimezone_set_component (zone, clone);
+
+ return zone;
+ }
+
+ icalcompiter_next (&iter);
+ }
+
+ return NULL;
+}
+
+static void
+process_callbacks (EMeetingStoreQueueData *qdata)
+{
+ EMeetingStore *store;
+ int i;
+
+ for (i = 0; i < qdata->call_backs->len; i++) {
+ EMeetingStoreRefreshCallback call_back;
+ gpointer *data;
+
+ call_back = g_ptr_array_index (qdata->call_backs, i);
+ data = g_ptr_array_index (qdata->data, i);
+
+ call_back (data);
+ }
+
+ store = qdata->store;
+ refresh_queue_remove (qdata->store, qdata->attendee);
+ g_object_unref (store);
+}
+
+static void
+process_free_busy_comp (EMeetingAttendee *attendee,
+ icalcomponent *fb_comp,
+ icaltimezone *zone,
+ icalcomponent *tz_top_level)
+{
+ icalproperty *ip;
+
+ ip = icalcomponent_get_first_property (fb_comp, ICAL_DTSTART_PROPERTY);
+ if (ip != NULL) {
+ struct icaltimetype dtstart;
+ icaltimezone *ds_zone;
+
+ dtstart = icalproperty_get_dtstart (ip);
+ if (!dtstart.is_utc)
+ ds_zone = find_zone (ip, tz_top_level);
+ else
+ ds_zone = icaltimezone_get_utc_timezone ();
+ icaltimezone_convert_time (&dtstart, ds_zone, zone);
+ e_meeting_attendee_set_start_busy_range (attendee,
+ dtstart.year,
+ dtstart.month,
+ dtstart.day,
+ dtstart.hour,
+ dtstart.minute);
+ }
+
+ ip = icalcomponent_get_first_property (fb_comp, ICAL_DTEND_PROPERTY);
+ if (ip != NULL) {
+ struct icaltimetype dtend;
+ icaltimezone *de_zone;
+
+ dtend = icalproperty_get_dtend (ip);
+ if (!dtend.is_utc)
+ de_zone = find_zone (ip, tz_top_level);
+ else
+ de_zone = icaltimezone_get_utc_timezone ();
+ icaltimezone_convert_time (&dtend, de_zone, zone);
+ e_meeting_attendee_set_end_busy_range (attendee,
+ dtend.year,
+ dtend.month,
+ dtend.day,
+ dtend.hour,
+ dtend.minute);
+ }
+
+ ip = icalcomponent_get_first_property (fb_comp, ICAL_FREEBUSY_PROPERTY);
+ while (ip != NULL) {
+ icalparameter *param;
+ struct icalperiodtype fb;
+ EMeetingFreeBusyType busy_type = E_MEETING_FREE_BUSY_LAST;
+ icalparameter_fbtype fbtype = ICAL_FBTYPE_BUSY;
+
+ fb = icalproperty_get_freebusy (ip);
+ param = icalproperty_get_first_parameter (ip, ICAL_FBTYPE_PARAMETER);
+ if (param != NULL)
+ fbtype = icalparameter_get_fbtype (param);
+
+ switch (fbtype) {
+ case ICAL_FBTYPE_BUSY:
+ busy_type = E_MEETING_FREE_BUSY_BUSY;
+ break;
+
+ case ICAL_FBTYPE_BUSYUNAVAILABLE:
+ busy_type = E_MEETING_FREE_BUSY_OUT_OF_OFFICE;
+ break;
+
+ case ICAL_FBTYPE_BUSYTENTATIVE:
+ busy_type = E_MEETING_FREE_BUSY_TENTATIVE;
+ break;
+
+ default:
+ break;
+ }
+
+ if (busy_type != E_MEETING_FREE_BUSY_LAST) {
+ icaltimezone *utc_zone = icaltimezone_get_utc_timezone ();
+
+ icaltimezone_convert_time (&fb.start, utc_zone, zone);
+ icaltimezone_convert_time (&fb.end, utc_zone, zone);
+ e_meeting_attendee_add_busy_period (attendee,
+ fb.start.year,
+ fb.start.month,
+ fb.start.day,
+ fb.start.hour,
+ fb.start.minute,
+ fb.end.year,
+ fb.end.month,
+ fb.end.day,
+ fb.end.hour,
+ fb.end.minute,
+ busy_type);
+ }
+
+ ip = icalcomponent_get_next_property (fb_comp, ICAL_FREEBUSY_PROPERTY);
+ }
+}
+
+static void
+process_free_busy (EMeetingStoreQueueData *qdata, char *text)
+{
+ EMeetingStore *store = qdata->store;
+ EMeetingStorePrivate *priv;
+ EMeetingAttendee *attendee = qdata->attendee;
+ icalcomponent *main_comp;
+ icalcomponent_kind kind = ICAL_NO_COMPONENT;
+
+ priv = store->priv;
+
+ main_comp = icalparser_parse_string (text);
+ if (main_comp == NULL) {
+ process_callbacks (qdata);
+ return;
+ }
+
+ kind = icalcomponent_isa (main_comp);
+ if (kind == ICAL_VCALENDAR_COMPONENT) {
+ icalcompiter iter;
+ icalcomponent *tz_top_level, *sub_comp;
+
+ tz_top_level = cal_util_new_top_level ();
+
+ iter = icalcomponent_begin_component (main_comp, ICAL_VTIMEZONE_COMPONENT);
+ while ((sub_comp = icalcompiter_deref (&iter)) != NULL) {
+ icalcomponent *clone;
+
+ clone = icalcomponent_new_clone (sub_comp);
+ icalcomponent_add_component (tz_top_level, clone);
+
+ icalcompiter_next (&iter);
+ }
+
+ iter = icalcomponent_begin_component (main_comp, ICAL_VFREEBUSY_COMPONENT);
+ while ((sub_comp = icalcompiter_deref (&iter)) != NULL) {
+ process_free_busy_comp (attendee, sub_comp, priv->zone, tz_top_level);
+
+ icalcompiter_next (&iter);
+ }
+ icalcomponent_free (tz_top_level);
+ } else if (kind == ICAL_VFREEBUSY_COMPONENT) {
+ process_free_busy_comp (attendee, main_comp, priv->zone, NULL);
+ }
+
+ icalcomponent_free (main_comp);
+
+ process_callbacks (qdata);
+}
+
+static gboolean
+refresh_busy_periods (gpointer data)
+{
+ EMeetingStore *store = E_MEETING_STORE (data);
+ EMeetingStorePrivate *priv;
+ EMeetingAttendee *attendee = NULL;
+ EMeetingStoreQueueData *qdata = NULL;
+ char *query;
+ int i;
+
+ priv = store->priv;
+
+ /* Check to see if there are any remaining attendees in the queue */
+ for (i = 0; i < priv->refresh_queue->len; i++) {
+ attendee = g_ptr_array_index (priv->refresh_queue, i);
+ g_assert (attendee != NULL);
+
+ qdata = g_hash_table_lookup (priv->refresh_data, attendee);
+ if (!qdata)
+ continue;
+
+ if (!qdata->refreshing)
+ break;
+ }
+
+ /* The everything in the queue is being refreshed */
+ if (i >= priv->refresh_queue->len) {
+ priv->refresh_idle_id = 0;
+ return FALSE;
+ }
+
+ /* Indicate we are trying to refresh it */
+ qdata->refreshing = TRUE;
+
+ /* We take a ref in case we get destroyed in the gui during a callback */
+ g_object_ref (qdata->store);
+
+ /* Check the server for free busy data */
+ if (priv->client) {
+ GList *fb_data, *users = NULL;
+ struct icaltimetype itt;
+ time_t startt, endt;
+ const char *user;
+
+ itt = icaltime_null_time ();
+ itt.year = g_date_year (&qdata->start.date);
+ itt.month = g_date_month (&qdata->start.date);
+ itt.day = g_date_day (&qdata->start.date);
+ itt.hour = qdata->start.hour;
+ itt.minute = qdata->start.minute;
+ startt = icaltime_as_timet_with_zone (itt, priv->zone);
+
+ itt = icaltime_null_time ();
+ itt.year = g_date_year (&qdata->end.date);
+ itt.month = g_date_month (&qdata->end.date);
+ itt.day = g_date_day (&qdata->end.date);
+ itt.hour = qdata->end.hour;
+ itt.minute = qdata->end.minute;
+ endt = icaltime_as_timet_with_zone (itt, priv->zone);
+
+ user = itip_strip_mailto (e_meeting_attendee_get_address (attendee));
+ users = g_list_append (users, g_strdup (user));
+ fb_data = cal_client_get_free_busy (priv->client, users, startt, endt);
+
+ g_list_foreach (users, (GFunc)g_free, NULL);
+ g_list_free (users);
+
+ if (fb_data != NULL) {
+ CalComponent *comp = fb_data->data;
+ char *comp_str;
+
+ comp_str = cal_component_get_as_string (comp);
+ process_free_busy (qdata, comp_str);
+ g_free (comp_str);
+ return TRUE;
+ }
+ }
+
+ /* Look for fburl's of attendee with no free busy info on server */
+ if (!priv->book_loaded) {
+ priv->book_load_wait = TRUE;
+ gtk_main ();
+ }
+
+ if (!e_meeting_attendee_is_set_address (attendee)) {
+ process_callbacks (qdata);
+ return TRUE;
+ }
+
+ query = g_strdup_printf ("(contains \"email\" \"%s\")",
+ itip_strip_mailto (e_meeting_attendee_get_address (attendee)));
+ process_callbacks (qdata);
+ g_free (query);
+
+ return TRUE;
+}
+
+static void
+refresh_queue_add (EMeetingStore *store, int row,
+ EMeetingTime *start,
+ EMeetingTime *end,
+ EMeetingStoreRefreshCallback call_back,
+ gpointer data)
+{
+ EMeetingStorePrivate *priv;
+ EMeetingAttendee *attendee;
+ EMeetingStoreQueueData *qdata;
+
+ priv = store->priv;
+
+ attendee = g_ptr_array_index (priv->attendees, row);
+ if (attendee == NULL)
+ return;
+
+ qdata = g_hash_table_lookup (priv->refresh_data, attendee);
+ if (qdata == NULL) {
+ qdata = g_new0 (EMeetingStoreQueueData, 1);
+
+ qdata->store = store;
+ qdata->attendee = attendee;
+ e_meeting_attendee_clear_busy_periods (attendee);
+ e_meeting_attendee_set_has_calendar_info (attendee, FALSE);
+
+ qdata->start = *start;
+ qdata->end = *end;
+ qdata->string = g_string_new (NULL);
+ qdata->call_backs = g_ptr_array_new ();
+ qdata->data = g_ptr_array_new ();
+ g_ptr_array_add (qdata->call_backs, call_back);
+ g_ptr_array_add (qdata->data, data);
+
+ g_hash_table_insert (priv->refresh_data, attendee, qdata);
+ } else {
+ if (e_meeting_time_compare_times (start, &qdata->start) == -1)
+ qdata->start = *start;
+ if (e_meeting_time_compare_times (end, &qdata->end) == 1)
+ qdata->end = *end;
+ g_ptr_array_add (qdata->call_backs, call_back);
+ g_ptr_array_add (qdata->data, data);
+ }
+
+ g_object_ref (attendee);
+ g_ptr_array_add (priv->refresh_queue, attendee);
+
+ if (priv->refresh_idle_id == 0)
+ priv->refresh_idle_id = g_idle_add (refresh_busy_periods, store);
+}
+
+static void
+async_close (GnomeVFSAsyncHandle *handle,
+ GnomeVFSResult result,
+ gpointer data)
+{
+ EMeetingStoreQueueData *qdata = data;
+
+ process_free_busy (qdata, qdata->string->str);
+}
+
+static void
+async_read (GnomeVFSAsyncHandle *handle,
+ GnomeVFSResult result,
+ gpointer buffer,
+ GnomeVFSFileSize requested,
+ GnomeVFSFileSize read,
+ gpointer data)
+{
+ EMeetingStoreQueueData *qdata = data;
+ GnomeVFSFileSize buf_size = BUF_SIZE - 1;
+
+ if (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_EOF) {
+ gnome_vfs_async_close (handle, async_close, qdata);
+ return;
+ }
+
+ ((char *)buffer)[read] = '\0';
+ qdata->string = g_string_append (qdata->string, buffer);
+
+ if (result == GNOME_VFS_ERROR_EOF) {
+ gnome_vfs_async_close (handle, async_close, qdata);
+ return;
+ }
+
+ gnome_vfs_async_read (handle, qdata->buffer, buf_size, async_read, qdata);
+}
+
+void
+e_meeting_store_refresh_all_busy_periods (EMeetingStore *store,
+ EMeetingTime *start,
+ EMeetingTime *end,
+ EMeetingStoreRefreshCallback call_back,
+ gpointer data)
+{
+ int i;
+
+ g_return_if_fail (E_IS_MEETING_STORE (store));
+
+ for (i = 0; i < store->priv->attendees->len; i++)
+ refresh_queue_add (store, i, start, end, call_back, data);
+}
+
+void
+e_meeting_store_refresh_busy_periods (EMeetingStore *store,
+ int row,
+ EMeetingTime *start,
+ EMeetingTime *end,
+ EMeetingStoreRefreshCallback call_back,
+ gpointer data)
+{
+ g_return_if_fail (E_IS_MEETING_STORE (store));
+
+ refresh_queue_add (store, row, start, end, call_back, data);
+}
+
diff --git a/calendar/gui/e-meeting-store.h b/calendar/gui/e-meeting-store.h
new file mode 100644
index 0000000000..e5e518289d
--- /dev/null
+++ b/calendar/gui/e-meeting-store.h
@@ -0,0 +1,108 @@
+/*
+ * e-meeting-store.h
+ *
+ * Copyright (C) 2003 Ximian, Inc.
+ *
+ * Author: Mike Kestner
+ *
+ * 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 _E_MEETING_STORE_H_
+#define _E_MEETING_STORE_H_
+
+#include <gtk/gtkliststore.h>
+#include <cal-client/cal-client.h>
+#include "e-meeting-attendee.h"
+
+G_BEGIN_DECLS
+
+#define E_TYPE_MEETING_STORE (e_meeting_store_get_type ())
+#define E_MEETING_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_MEETING_STORE, EMeetingStore))
+#define E_MEETING_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_MEETING_STORE, EMeetingStoreClass))
+#define E_IS_MEETING_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_MEETING_STORE))
+#define E_IS_MEETING_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_MEETING_STORE))
+
+typedef struct _EMeetingStore EMeetingStore;
+typedef struct _EMeetingStorePrivate EMeetingStorePrivate;
+typedef struct _EMeetingStoreClass EMeetingStoreClass;
+
+typedef enum {
+ E_MEETING_STORE_ADDRESS_COL,
+ E_MEETING_STORE_MEMBER_COL,
+ E_MEETING_STORE_TYPE_COL,
+ E_MEETING_STORE_ROLE_COL,
+ E_MEETING_STORE_RSVP_COL,
+ E_MEETING_STORE_DELTO_COL,
+ E_MEETING_STORE_DELFROM_COL,
+ E_MEETING_STORE_STATUS_COL,
+ E_MEETING_STORE_CN_COL,
+ E_MEETING_STORE_LANGUAGE_COL,
+ E_MEETING_STORE_ATTENDEE_COL,
+ E_MEETING_STORE_ATTENDEE_UNDERLINE_COL,
+ E_MEETING_STORE_COLUMN_COUNT
+} EMeetingStoreColumns;
+
+struct _EMeetingStore {
+ GtkListStore parent;
+
+ EMeetingStorePrivate *priv;
+};
+
+struct _EMeetingStoreClass {
+ GtkListStoreClass parent_class;
+};
+
+typedef void (* EMeetingStoreRefreshCallback) (gpointer data);
+
+GType e_meeting_store_get_type (void);
+GObject *e_meeting_store_new (void);
+
+void e_meeting_store_set_value (EMeetingStore *im, int row, int col, const gchar *val);
+
+CalClient *e_meeting_store_get_cal_client (EMeetingStore *im);
+void e_meeting_store_set_cal_client (EMeetingStore *im, CalClient *client);
+
+icaltimezone *e_meeting_store_get_zone (EMeetingStore *im);
+void e_meeting_store_set_zone (EMeetingStore *im, icaltimezone *zone);
+
+void e_meeting_store_add_attendee (EMeetingStore *im, EMeetingAttendee *ia);
+EMeetingAttendee *e_meeting_store_add_attendee_with_defaults (EMeetingStore *im);
+
+void e_meeting_store_remove_attendee (EMeetingStore *im, EMeetingAttendee *ia);
+void e_meeting_store_remove_all_attendees (EMeetingStore *im);
+
+EMeetingAttendee *e_meeting_store_find_attendee (EMeetingStore *im, const gchar *address, gint *row);
+EMeetingAttendee *e_meeting_store_find_attendee_at_row (EMeetingStore *im, gint row);
+
+gint e_meeting_store_count_actual_attendees (EMeetingStore *im);
+const GPtrArray *e_meeting_store_get_attendees (EMeetingStore *im);
+
+void e_meeting_store_refresh_all_busy_periods (EMeetingStore *im,
+ EMeetingTime *start,
+ EMeetingTime *end,
+ EMeetingStoreRefreshCallback call_back,
+ gpointer data);
+void e_meeting_store_refresh_busy_periods (EMeetingStore *im,
+ int row,
+ EMeetingTime *start,
+ EMeetingTime *end,
+ EMeetingStoreRefreshCallback call_back,
+ gpointer data);
+
+
+G_END_DECLS
+
+#endif
diff --git a/calendar/gui/e-meeting-time-sel-item.c b/calendar/gui/e-meeting-time-sel-item.c
index e19a148e72..c714684569 100644
--- a/calendar/gui/e-meeting-time-sel-item.c
+++ b/calendar/gui/e-meeting-time-sel-item.c
@@ -256,7 +256,6 @@ e_meeting_time_selector_item_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
{
EMeetingTimeSelector *mts;
EMeetingTimeSelectorItem *mts_item;
- ETable *real_table;
EMeetingAttendee *ia;
gint day_x, meeting_start_x, meeting_end_x, bar_y, bar_height;
gint row, row_y, start_x, end_x;
@@ -270,8 +269,6 @@ e_meeting_time_selector_item_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
gc = mts_item->main_gc;
stipple_gc = mts_item->stipple_gc;
- real_table = e_table_scrolled_get_table (E_TABLE_SCROLLED (mts->etable));
-
is_display_top = (GTK_WIDGET (item->canvas) == mts->display_top)
? TRUE : FALSE;
@@ -321,14 +318,11 @@ e_meeting_time_selector_item_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
gdk_gc_set_fill (stipple_gc, GDK_OPAQUE_STIPPLED);
row = y / mts->row_height;
row_y = row * mts->row_height - y;
- while (row < e_meeting_model_count_actual_attendees (mts->model) && row_y < height) {
- gint model_row = e_meeting_model_etable_view_to_model_row (real_table,
- mts->model, row);
-
- ia = e_meeting_model_find_attendee_at_row (mts->model, model_row);
+ while (row < e_meeting_store_count_actual_attendees (mts->model) && row_y < height) {
+ ia = e_meeting_store_find_attendee_at_row (mts->model, row);
if (e_meeting_attendee_get_has_calendar_info (ia)) {
- if (e_meeting_time_selector_item_calculate_busy_range (mts, model_row, x, width, &start_x, &end_x)) {
+ if (e_meeting_time_selector_item_calculate_busy_range (mts, row, x, width, &start_x, &end_x)) {
if (start_x >= width || end_x <= 0) {
gdk_draw_rectangle (drawable, stipple_gc, TRUE, 0, row_y, width, mts->row_height);
} else {
@@ -522,9 +516,9 @@ e_meeting_time_selector_item_paint_all_attendees_busy_periods (EMeetingTimeSelec
y = 2 * mts->row_height - scroll_y - 1;
/* Get the first visible busy periods for all the attendees. */
- first_periods = g_new (gint, e_meeting_model_count_actual_attendees (mts->model));
- for (row = 0; row < e_meeting_model_count_actual_attendees (mts->model); row++) {
- ia = e_meeting_model_find_attendee_at_row (mts->model, row);
+ first_periods = g_new (gint, e_meeting_store_count_actual_attendees (mts->model));
+ for (row = 0; row < e_meeting_store_count_actual_attendees (mts->model); row++) {
+ ia = e_meeting_store_find_attendee_at_row (mts->model, row);
first_periods[row] = e_meeting_time_selector_item_find_first_busy_period (mts_item, date, row);
}
@@ -532,7 +526,7 @@ e_meeting_time_selector_item_paint_all_attendees_busy_periods (EMeetingTimeSelec
busy_type < E_MEETING_FREE_BUSY_LAST;
busy_type++) {
gdk_gc_set_foreground (gc, &mts->busy_colors[busy_type]);
- for (row = 0; row < e_meeting_model_count_actual_attendees (mts->model); row++) {
+ for (row = 0; row < e_meeting_store_count_actual_attendees (mts->model); row++) {
if (first_periods[row] == -1)
continue;
e_meeting_time_selector_item_paint_attendee_busy_periods (mts_item, drawable, x, y, width, row, first_periods[row], busy_type);
@@ -569,7 +563,7 @@ e_meeting_time_selector_item_paint_day (EMeetingTimeSelectorItem *mts_item,
grid_y < height;
grid_y += mts->row_height)
{
- if (attendee_index <= e_meeting_model_count_actual_attendees (mts->model)) {
+ if (attendee_index <= e_meeting_store_count_actual_attendees (mts->model)) {
gdk_gc_set_foreground (gc, &mts->grid_color);
gdk_draw_line (drawable, gc, 0, grid_y,
width, grid_y);
@@ -582,7 +576,7 @@ e_meeting_time_selector_item_paint_day (EMeetingTimeSelectorItem *mts_item,
}
/* Draw the vertical grid lines. */
- unused_y = (e_meeting_model_count_actual_attendees (mts->model) * mts->row_height) - scroll_y;
+ unused_y = (e_meeting_store_count_actual_attendees (mts->model) * mts->row_height) - scroll_y;
if (unused_y >= 0) {
gdk_gc_set_foreground (gc, &mts->grid_color);
for (grid_x = mts->col_width - 1;
@@ -624,15 +618,12 @@ e_meeting_time_selector_item_paint_busy_periods (EMeetingTimeSelectorItem *mts_i
{
EMeetingTimeSelector *mts;
EMeetingFreeBusyType busy_type;
- ETable *real_table;
- gint row, model_row, y, first_period;
+ gint row, y, first_period;
GdkGC *gc;
mts = mts_item->mts;
gc = mts_item->main_gc;
- real_table = e_table_scrolled_get_table (E_TABLE_SCROLLED (mts->etable));
-
/* Calculate the first visible attendee row. */
row = scroll_y / mts->row_height;
@@ -640,11 +631,10 @@ e_meeting_time_selector_item_paint_busy_periods (EMeetingTimeSelectorItem *mts_i
y = row * mts->row_height - scroll_y;
/* Step through the attendees painting the busy periods. */
- while (y < height && row < e_meeting_model_count_actual_attendees (mts->model)) {
- model_row = e_meeting_model_etable_view_to_model_row (real_table, mts->model, row);
+ while (y < height && row < e_meeting_store_count_actual_attendees (mts->model)) {
/* Find the first visible busy period. */
- first_period = e_meeting_time_selector_item_find_first_busy_period (mts_item, date, model_row);
+ first_period = e_meeting_time_selector_item_find_first_busy_period (mts_item, date, row);
if (first_period != -1) {
/* Paint the different types of busy periods, in
reverse order of precedence, so the highest
@@ -653,7 +643,7 @@ e_meeting_time_selector_item_paint_busy_periods (EMeetingTimeSelectorItem *mts_i
busy_type < E_MEETING_FREE_BUSY_LAST;
busy_type++) {
gdk_gc_set_foreground (gc, &mts->busy_colors[busy_type]);
- e_meeting_time_selector_item_paint_attendee_busy_periods (mts_item, drawable, x, y, width, model_row, first_period, busy_type);
+ e_meeting_time_selector_item_paint_attendee_busy_periods (mts_item, drawable, x, y, width, row, first_period, busy_type);
}
}
y += mts->row_height;
@@ -677,7 +667,7 @@ e_meeting_time_selector_item_find_first_busy_period (EMeetingTimeSelectorItem *m
mts = mts_item->mts;
- ia = e_meeting_model_find_attendee_at_row (mts->model, row);
+ ia = e_meeting_store_find_attendee_at_row (mts->model, row);
period_num = e_meeting_attendee_find_first_busy_period (ia, date);
if (period_num == -1)
@@ -710,7 +700,7 @@ e_meeting_time_selector_item_paint_attendee_busy_periods (EMeetingTimeSelectorIt
mts = mts_item->mts;
gc = mts_item->main_gc;
- ia = e_meeting_model_find_attendee_at_row (mts->model, row);
+ ia = e_meeting_store_find_attendee_at_row (mts->model, row);
busy_periods = e_meeting_attendee_get_busy_periods (ia);
for (period_num = first_period;
@@ -990,7 +980,7 @@ e_meeting_time_selector_item_calculate_busy_range (EMeetingTimeSelector *mts,
EMeetingTime busy_periods_start;
EMeetingTime busy_periods_end;
- ia = e_meeting_model_find_attendee_at_row (mts->model, row);
+ ia = e_meeting_store_find_attendee_at_row (mts->model, row);
busy_periods_start = e_meeting_attendee_get_start_busy_range (ia);
busy_periods_end = e_meeting_attendee_get_end_busy_range (ia);
diff --git a/calendar/gui/e-meeting-time-sel.c b/calendar/gui/e-meeting-time-sel.c
index 18e8fd76fe..157320ef16 100644
--- a/calendar/gui/e-meeting-time-sel.c
+++ b/calendar/gui/e-meeting-time-sel.c
@@ -54,18 +54,13 @@
#include <gal/widgets/e-canvas.h>
#include <gal/widgets/e-canvas-utils.h>
-#include <gal/e-table/e-cell-combo.h>
-#include <gal/e-table/e-cell-text.h>
-#include <gal/e-table/e-table-simple.h>
-#include <gal/e-table/e-table-scrolled.h>
-#include <gal/e-table/e-table-header-item.h>
-#include <gal/e-table/e-table-header-utils.h>
#include <widgets/misc/e-dateedit.h>
#include "calendar-component.h"
#include "calendar-config.h"
#include "e-meeting-utils.h"
+#include "e-meeting-list-view.h"
#include "e-meeting-time-sel-item.h"
/* An array of hour strings for 24 hour time, "0:00" .. "23:00". */
@@ -132,9 +127,6 @@ static void e_meeting_time_selector_hadjustment_changed (GtkAdjustment *adjustme
EMeetingTimeSelector *mts);
static void e_meeting_time_selector_vadjustment_changed (GtkAdjustment *adjustment,
EMeetingTimeSelector *mts);
-static void e_meeting_time_selector_table_vadjustment_changed (GtkAdjustment *adjustment,
- EMeetingTimeSelector *mts);
-
static void e_meeting_time_selector_on_canvas_realized (GtkWidget *widget,
EMeetingTimeSelector *mts);
@@ -213,10 +205,9 @@ static void e_meeting_time_selector_update_end_date_edit (EMeetingTimeSelector *
static void e_meeting_time_selector_ensure_meeting_time_shown (EMeetingTimeSelector *mts);
static void e_meeting_time_selector_update_dates_shown (EMeetingTimeSelector *mts);
-static void rows_inserted_cb (ETableModel *etm, int row, int count, gpointer data);
-static void cell_changed_cb (ETableModel *etm, int row, int col, gpointer data);
-static void rows_deleted_cb (ETableModel *etm, int row, int count, gpointer data);
-static void sort_info_changed_cb (ETableSortInfo *info, gpointer data);
+static void row_inserted_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data);
+static void row_changed_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data);
+static void row_deleted_cb (GtkTreeModel *model, GtkTreePath *path, gpointer data);
static GtkTableClass *parent_class;
@@ -267,12 +258,12 @@ e_meeting_time_selector_init (EMeetingTimeSelector * mts)
mts->zoomed_out = TRUE;
mts->dragging_position = E_MEETING_TIME_SELECTOR_POS_NONE;
- mts->etable = NULL;
+ mts->list_view = NULL;
}
void
-e_meeting_time_selector_construct (EMeetingTimeSelector * mts, EMeetingModel *emm)
+e_meeting_time_selector_construct (EMeetingTimeSelector * mts, EMeetingStore *ems)
{
GtkWidget *hbox, *vbox, *separator, *button, *label, *table;
GtkWidget *alignment, *child_hbox, *arrow, *menuitem;
@@ -282,8 +273,6 @@ e_meeting_time_selector_construct (EMeetingTimeSelector * mts, EMeetingModel *em
guint accel_key;
time_t meeting_start_time;
struct tm *meeting_start_tm;
- char *filename;
- ETable *real_table;
guchar stipple_bits[] = {
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
};
@@ -324,27 +313,25 @@ e_meeting_time_selector_construct (EMeetingTimeSelector * mts, EMeetingModel *em
gtk_box_pack_start (GTK_BOX (vbox), mts->attendees_vbox, TRUE, TRUE, 0);
gtk_widget_show (mts->attendees_vbox);
- /* build the etable */
- filename = g_strdup_printf ("%s/config/et-header-meeting-time-sel", evolution_dir);
- mts->model = emm;
+ mts->model = ems;
if (mts->model)
g_object_ref (mts->model);
- g_signal_connect (mts->model, "model_rows_inserted", G_CALLBACK (rows_inserted_cb), mts);
- g_signal_connect (mts->model, "model_cell_changed", G_CALLBACK (cell_changed_cb), mts);
- g_signal_connect (mts->model, "model_rows_deleted", G_CALLBACK (rows_deleted_cb), mts);
+ g_signal_connect (mts->model, "row_inserted", G_CALLBACK (row_inserted_cb), mts);
+ g_signal_connect (mts->model, "row_changed", G_CALLBACK (row_changed_cb), mts);
+ g_signal_connect (mts->model, "row_deleted", G_CALLBACK (row_deleted_cb), mts);
- mts->etable = GTK_WIDGET (e_meeting_model_etable_from_model (mts->model,
- EVOLUTION_ETSPECDIR "/e-meeting-time-sel.etspec",
- filename));
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (mts->etable), GTK_POLICY_NEVER, GTK_POLICY_NEVER);
+ mts->list_view = e_meeting_list_view_new (mts->model);
+ e_meeting_list_view_column_set_visible (mts->list_view, "Role", FALSE);
+ e_meeting_list_view_column_set_visible (mts->list_view, "RSVP", FALSE);
+ gtk_widget_show (GTK_WIDGET (mts->list_view));
- real_table = e_table_scrolled_get_table (E_TABLE_SCROLLED (mts->etable));
+#if 0
+ /* FIXME: do we need sorting here */
g_signal_connect (real_table->sort_info, "sort_info_changed", G_CALLBACK (sort_info_changed_cb), mts);
+#endif
- gtk_box_pack_start (GTK_BOX (mts->attendees_vbox), mts->etable, TRUE, TRUE, 6);
- gtk_widget_show (mts->etable);
- g_free (filename);
+ gtk_box_pack_start (GTK_BOX (mts->attendees_vbox), GTK_WIDGET (mts->list_view), TRUE, TRUE, 6);
/* The free/busy information */
mts->display_top = gnome_canvas_new ();
@@ -666,11 +653,6 @@ e_meeting_time_selector_construct (EMeetingTimeSelector * mts, EMeetingModel *em
g_signal_connect (GTK_LAYOUT (mts->display_main)->vadjustment, "changed",
G_CALLBACK (e_meeting_time_selector_vadjustment_changed), mts);
- g_signal_connect (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (mts->etable)), "value_changed",
- G_CALLBACK (e_meeting_time_selector_table_vadjustment_changed), mts);
- g_signal_connect (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (mts->etable)), "changed",
- G_CALLBACK (e_meeting_time_selector_table_vadjustment_changed), mts);
-
e_meeting_time_selector_recalc_grid (mts);
e_meeting_time_selector_ensure_meeting_time_shown (mts);
e_meeting_time_selector_update_start_date_edit (mts);
@@ -794,13 +776,13 @@ e_meeting_time_selector_autopick_menu_detacher (GtkWidget *widget,
GtkWidget *
-e_meeting_time_selector_new (EMeetingModel *emm)
+e_meeting_time_selector_new (EMeetingStore *ems)
{
GtkWidget *mts;
mts = GTK_WIDGET (g_object_new (e_meeting_time_selector_get_type (), NULL));
- e_meeting_time_selector_construct (E_MEETING_TIME_SELECTOR (mts), emm);
+ e_meeting_time_selector_construct (E_MEETING_TIME_SELECTOR (mts), ems);
return mts;
}
@@ -867,15 +849,14 @@ e_meeting_time_selector_style_set (GtkWidget *widget,
{
EMeetingTimeSelector *mts;
EMeetingTime saved_time;
- ETable *real_table;
- ETableHeader *eth;
int hour, max_hour_width;
- int numcols, col;
int maxheight;
PangoFontDescription *font_desc;
PangoContext *pango_context;
PangoFontMetrics *font_metrics;
PangoLayout *layout;
+ GtkTreePath *path;
+ GdkRectangle cell_area;
if (GTK_WIDGET_CLASS (parent_class)->style_set)
(*GTK_WIDGET_CLASS (parent_class)->style_set)(widget, previous_style);
@@ -901,9 +882,7 @@ e_meeting_time_selector_style_set (GtkWidget *widget,
max_hour_width = MAX (max_hour_width, mts->hour_widths[hour]);
}
- /* FIXME the 3 is for the padding etable adds on */
pango_layout_get_pixel_size (layout, NULL, &mts->row_height);
- mts->row_height += 3;
mts->col_width = max_hour_width + 6;
e_meeting_time_selector_save_position (mts, &saved_time);
@@ -913,21 +892,16 @@ e_meeting_time_selector_style_set (GtkWidget *widget,
gtk_widget_set_usize (mts->display_top, -1, mts->row_height * 3 + 4);
/* Calculate header height */
- real_table = e_table_scrolled_get_table (E_TABLE_SCROLLED (mts->etable));
- eth = real_table->full_header;
- numcols = e_table_header_count (eth);
- maxheight = 0;
- for (col = 0; col < numcols; col++) {
- ETableCol *ecol = e_table_header_get_column (eth, col);
- int height;
-
- height = e_table_header_compute_height (ecol, widget);
-
- if (height > maxheight)
- maxheight = height;
- }
- /* FIXME the 5 is for the padding etable adds on */
- gtk_widget_set_usize (mts->attendees_vbox_spacer, 1, mts->row_height * 3 - maxheight - 5);
+ if (GTK_WIDGET_REALIZED (mts->list_view)) {
+ path = gtk_tree_path_new ();
+ gtk_tree_path_append_index (path, 0);
+ gtk_tree_view_get_cell_area (GTK_TREE_VIEW (mts->list_view), path, NULL, &cell_area);
+ gtk_tree_path_free (path);
+ maxheight = cell_area.y;
+ } else
+ maxheight = 10;
+
+ gtk_widget_set_usize (mts->attendees_vbox_spacer, 1, mts->row_height * 3 - maxheight);
GTK_LAYOUT (mts->display_main)->hadjustment->step_increment = mts->col_width;
GTK_LAYOUT (mts->display_main)->vadjustment->step_increment = mts->row_height;
@@ -993,27 +967,13 @@ e_meeting_time_selector_vadjustment_changed (GtkAdjustment *adjustment,
{
GtkAdjustment *adj;
- adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (mts->etable));
- if (adj->value != adjustment->value) {
- adj->value = adjustment->value;
- gtk_adjustment_value_changed (adj);
- }
-}
-
-static void
-e_meeting_time_selector_table_vadjustment_changed (GtkAdjustment *adjustment,
- EMeetingTimeSelector *mts)
-{
- GtkAdjustment *adj;
-
- adj = GTK_LAYOUT (mts->display_main)->vadjustment;
+ adj = gtk_tree_view_get_vadjustment (GTK_TREE_VIEW (mts->list_view));
if (adj->value != adjustment->value) {
adj->value = adjustment->value;
gtk_adjustment_value_changed (adj);
}
}
-
void
e_meeting_time_selector_get_meeting_time (EMeetingTimeSelector *mts,
gint *start_year,
@@ -1229,17 +1189,17 @@ e_meeting_time_selector_refresh_free_busy (EMeetingTimeSelector *mts, int row, g
if (all) {
int i;
- for (i = 0; i < e_meeting_model_count_actual_attendees (mts->model); i++)
+ for (i = 0; i < e_meeting_store_count_actual_attendees (mts->model); i++)
gtk_object_ref (GTK_OBJECT (mts));
} else {
gtk_object_ref (GTK_OBJECT (mts));
}
if (all)
- e_meeting_model_refresh_all_busy_periods (mts->model, &start, &end,
+ e_meeting_store_refresh_all_busy_periods (mts->model, &start, &end,
e_meeting_time_selector_refresh_cb, mts);
else
- e_meeting_model_refresh_busy_periods (mts->model, row, &start, &end,
+ e_meeting_store_refresh_busy_periods (mts->model, row, &start, &end,
e_meeting_time_selector_refresh_cb, mts);
}
@@ -1387,12 +1347,8 @@ e_meeting_time_selector_on_invite_others_button_expose (GtkWidget *button,
GdkEventExpose *event,
EMeetingTimeSelector *mts)
{
- ETable *real_table;
gboolean click_to_add = TRUE;
- real_table = e_table_scrolled_get_table (E_TABLE_SCROLLED (mts->etable));
- g_object_get (G_OBJECT (real_table), "use_click_to_add", &click_to_add, NULL);
-
gtk_widget_set_sensitive (button, click_to_add);
return FALSE;
}
@@ -1401,7 +1357,7 @@ static void
e_meeting_time_selector_on_invite_others_button_clicked (GtkWidget *button,
EMeetingTimeSelector *mts)
{
- e_meeting_model_invite_others_dialog (mts->model);
+ e_meeting_list_view_invite_others_dialog (mts->list_view);
}
@@ -1561,8 +1517,8 @@ e_meeting_time_selector_autopick (EMeetingTimeSelector *mts,
/* Step through each attendee, checking if the meeting time
intersects one of the attendees busy periods. */
- for (row = 0; row < e_meeting_model_count_actual_attendees (mts->model); row++) {
- attendee = e_meeting_model_find_attendee_at_row (mts->model, row);
+ for (row = 0; row < e_meeting_store_count_actual_attendees (mts->model); row++) {
+ attendee = e_meeting_store_find_attendee_at_row (mts->model, row);
/* Skip optional people if they don't matter. */
if (skip_optional && e_meeting_attendee_get_atype (attendee) == E_MEETING_ATTENDEE_OPTIONAL_PERSON)
@@ -2296,7 +2252,7 @@ e_meeting_time_selector_update_main_canvas_scroll_region (EMeetingTimeSelector *
{
gint height, canvas_height;
- height = mts->row_height * (e_meeting_model_count_actual_attendees (mts->model) + 2);
+ height = mts->row_height * (e_meeting_store_count_actual_attendees (mts->model) + 2);
canvas_height = GTK_WIDGET (mts->display_main)->allocation.height;
height = MAX (height, canvas_height);
@@ -2848,11 +2804,10 @@ e_meeting_time_selector_calculate_time_position (EMeetingTimeSelector *mts,
}
static void
-rows_inserted_cb (ETableModel *etm, int row, int count, gpointer data)
+row_inserted_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
{
EMeetingTimeSelector *mts = E_MEETING_TIME_SELECTOR (data);
- int i;
-
+ int row = gtk_tree_path_get_indices (path) [0];
/* Update the scroll region. */
e_meeting_time_selector_update_main_canvas_scroll_region (mts);
@@ -2861,24 +2816,21 @@ rows_inserted_cb (ETableModel *etm, int row, int count, gpointer data)
gtk_widget_queue_draw (mts->display_main);
/* Get the latest free/busy info */
- for (i = 0; i < count; i++)
- e_meeting_time_selector_refresh_free_busy (mts, row + i, FALSE);
+ e_meeting_time_selector_refresh_free_busy (mts, row, FALSE);
}
static void
-cell_changed_cb (ETableModel *etm, int col, int row, gpointer data)
+row_changed_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
{
EMeetingTimeSelector *mts = E_MEETING_TIME_SELECTOR (data);
-
- if (col != E_MEETING_MODEL_ADDRESS_COL)
- return;
+ int row = gtk_tree_path_get_indices (path) [0];
/* Get the latest free/busy info */
e_meeting_time_selector_refresh_free_busy (mts, row, FALSE);
}
static void
-rows_deleted_cb (ETableModel *etm, int row, int count, gpointer data)
+row_deleted_cb (GtkTreeModel *model, GtkTreePath *path, gpointer data)
{
EMeetingTimeSelector *mts = E_MEETING_TIME_SELECTOR (data);
@@ -2890,12 +2842,3 @@ rows_deleted_cb (ETableModel *etm, int row, int count, gpointer data)
gtk_widget_queue_draw (mts->display_main);
}
-static void
-sort_info_changed_cb (ETableSortInfo *info, gpointer data)
-{
- EMeetingTimeSelector *mts = E_MEETING_TIME_SELECTOR (data);
-
- /* Redraw */
- gtk_widget_queue_draw (mts->display_top);
- gtk_widget_queue_draw (mts->display_main);
-}
diff --git a/calendar/gui/e-meeting-time-sel.h b/calendar/gui/e-meeting-time-sel.h
index cbfffb6a25..ee23dbe672 100644
--- a/calendar/gui/e-meeting-time-sel.h
+++ b/calendar/gui/e-meeting-time-sel.h
@@ -31,11 +31,10 @@
#include <gal/e-text/e-text.h>
#include <gal/e-table/e-table-model.h>
#include <gal/e-table/e-table.h>
-#include "e-meeting-model.h"
+#include "e-meeting-store.h"
+#include "e-meeting-list-view.h"
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
+G_BEGIN_DECLS
/*
* EMeetingTimeSelector displays a list of attendees for a meeting and a
@@ -121,8 +120,8 @@ struct _EMeetingTimeSelector
GtkWidget *attendees_vbox_spacer;
/* The etable and model */
- EMeetingModel *model;
- GtkWidget *etable;
+ EMeetingStore *model;
+ EMeetingListView *list_view;
/* The canvas displaying the dates, times, and the summary
'All Attendees' free/busy display. */
@@ -265,8 +264,8 @@ struct _EMeetingTimeSelectorClass
*/
GtkType e_meeting_time_selector_get_type (void);
-GtkWidget* e_meeting_time_selector_new (EMeetingModel *emm);
-void e_meeting_time_selector_construct (EMeetingTimeSelector * mts, EMeetingModel *emm);
+GtkWidget* e_meeting_time_selector_new (EMeetingStore *ems);
+void e_meeting_time_selector_construct (EMeetingTimeSelector * mts, EMeetingStore *ems);
/* This returns the currently selected meeting time.
Note that months are 1-12 and days are 1-31. The start time is guaranteed to
@@ -375,9 +374,6 @@ gchar* e_meeting_time_selector_dump_time (EMeetingTime*mtstime);
gchar* e_meeting_time_selector_dump_date (GDate *date);
#endif /* E_MEETING_TIME_SELECTOR_DEBUG */
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+G_END_DECLS
#endif /* _E_MEETING_TIME_SELECTOR_H_ */
diff --git a/calendar/gui/e-select-names-editable.c b/calendar/gui/e-select-names-editable.c
new file mode 100644
index 0000000000..2fcc93397a
--- /dev/null
+++ b/calendar/gui/e-select-names-editable.c
@@ -0,0 +1,228 @@
+/*
+ * e-select-names-editable.c
+ *
+ * Author: Mike Kestner <mkestner@ximian.com>
+ *
+ * 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.
+ */
+
+#include <config.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtkcelleditable.h>
+#include <bonobo/bonobo-exception.h>
+#include <bonobo/bonobo-widget.h>
+#include <ebook/e-destination.h>
+
+#include "e-select-names-editable.h"
+#include "Evolution-Addressbook-SelectNames.h"
+
+#define SELECT_NAMES_OAFIID "OAFIID:GNOME_Evolution_Addressbook_SelectNames"
+
+struct _ESelectNamesEditablePriv {
+ GNOME_Evolution_Addressbook_SelectNames select_names;
+ Bonobo_Control control;
+ Bonobo_PropertyBag bag;
+};
+
+static BonoboWidgetClass *parent_class;
+
+static void
+esne_start_editing (GtkCellEditable *cell_editable, GdkEvent *event)
+{
+ ESelectNamesEditable *esne = E_SELECT_NAMES_EDITABLE (cell_editable);
+
+}
+
+static void
+esne_cell_editable_init (GtkCellEditableIface *iface)
+{
+ iface->start_editing = esne_start_editing;
+}
+
+static void
+esne_finalize (GObject *obj)
+{
+ ESelectNamesEditable *esne = (ESelectNamesEditable *) obj;
+
+ if (esne->priv->select_names != CORBA_OBJECT_NIL)
+ bonobo_object_release_unref (esne->priv->select_names, NULL);
+ esne->priv->select_names = CORBA_OBJECT_NIL;
+
+ if (esne->priv->bag != CORBA_OBJECT_NIL)
+ bonobo_object_release_unref (esne->priv->bag, NULL);
+ esne->priv->bag = CORBA_OBJECT_NIL;
+
+ g_free (esne->priv);
+
+ if (G_OBJECT_CLASS (parent_class)->finalize)
+ G_OBJECT_CLASS (parent_class)->finalize (obj);
+}
+
+static void
+esne_init (ESelectNamesEditable *esne)
+{
+ esne->priv = g_new0 (ESelectNamesEditablePriv, 1);
+
+ esne->priv->select_names = CORBA_OBJECT_NIL;
+ esne->priv->control = CORBA_OBJECT_NIL;
+ esne->priv->bag = CORBA_OBJECT_NIL;
+}
+
+static void
+esne_class_init (GObjectClass *klass)
+{
+ klass->finalize = esne_finalize;
+
+ parent_class = BONOBO_WIDGET_CLASS (g_type_class_peek_parent (klass));
+}
+
+GType
+e_select_names_editable_get_type (void)
+{
+ static GType esne_type = 0;
+
+ if (!esne_type) {
+ static const GTypeInfo esne_info = {
+ sizeof (ESelectNamesEditableClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) esne_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (ESelectNamesEditable),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) esne_init,
+ };
+
+ static const GInterfaceInfo cell_editable_info = {
+ (GInterfaceInitFunc) esne_cell_editable_init,
+ NULL,
+ NULL
+ };
+
+ esne_type = g_type_register_static (BONOBO_TYPE_WIDGET, "ESelectNamesEditable", &esne_info, 0);
+
+ g_type_add_interface_static (esne_type, GTK_TYPE_CELL_EDITABLE, &cell_editable_info);
+ }
+
+ return esne_type;
+}
+
+static void
+entry_activate (BonoboListener *listener, const char *event_name, const CORBA_any *arg, CORBA_Environment *ev, gpointer esne)
+{
+ gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (esne));
+ gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (esne));
+}
+
+ESelectNamesEditable *
+e_select_names_editable_construct (ESelectNamesEditable *esne)
+{
+ CORBA_Environment ev;
+
+ CORBA_exception_init (&ev);
+
+ esne->priv->select_names = bonobo_activation_activate_from_id (SELECT_NAMES_OAFIID, 0, NULL, &ev);
+ if (BONOBO_EX (&ev)) {
+ CORBA_exception_free (&ev);
+ return NULL;
+ }
+
+ GNOME_Evolution_Addressbook_SelectNames_addSection (esne->priv->select_names, "A", "A", &ev);
+ if (BONOBO_EX (&ev)) {
+ CORBA_exception_free (&ev);
+ return NULL;
+ }
+
+ esne->priv->control = GNOME_Evolution_Addressbook_SelectNames_getEntryBySection (
+ esne->priv->select_names, "A", &ev);
+ if (BONOBO_EX (&ev)) {
+ CORBA_exception_free (&ev);
+ return NULL;
+ }
+
+ bonobo_widget_construct_control_from_objref (BONOBO_WIDGET (esne), esne->priv->control, CORBA_OBJECT_NIL, &ev);
+
+ CORBA_exception_free (&ev);
+
+ esne->priv->bag = bonobo_control_frame_get_control_property_bag (
+ bonobo_widget_get_control_frame (BONOBO_WIDGET (esne)), NULL);
+ bonobo_event_source_client_add_listener (esne->priv->bag, entry_activate,
+ "GNOME/Evolution/Addressbook/SelectNames:activate:entry",
+ NULL, esne);
+
+ return esne;
+}
+
+ESelectNamesEditable *
+e_select_names_editable_new ()
+{
+ ESelectNamesEditable *esne = g_object_new (E_TYPE_SELECT_NAMES_EDITABLE, NULL);
+
+ if (!esne)
+ return NULL;
+
+ if (!e_select_names_editable_construct (esne)) {
+ g_object_unref (esne);
+ return NULL;
+ }
+
+ return esne;
+}
+
+gchar *
+e_select_names_editable_get_address (ESelectNamesEditable *esne)
+{
+ EDestination **dest;
+ gchar *dest_str;
+ gchar *result;
+
+ g_return_val_if_fail (E_SELECT_NAMES_EDITABLE (esne), NULL);
+
+ dest_str = bonobo_pbclient_get_string (esne->priv->bag, "destinations", NULL);
+ dest = e_destination_importv (dest_str);
+ result = g_strdup (e_destination_get_email (*dest));
+ e_destination_freev (dest);
+
+ return result;
+}
+
+gchar *
+e_select_names_editable_get_name (ESelectNamesEditable *esne)
+{
+ EDestination **dest;
+ gchar *dest_str;
+ gchar *result;
+
+ g_return_val_if_fail (E_SELECT_NAMES_EDITABLE (esne), NULL);
+
+ dest_str = bonobo_pbclient_get_string (esne->priv->bag, "destinations", NULL);
+ dest = e_destination_importv (dest_str);
+ result = g_strdup (e_destination_get_name (*dest));
+ e_destination_freev (dest);
+
+ return result;
+}
+
+void
+e_select_names_editable_set_address (ESelectNamesEditable *esne, const gchar *text)
+{
+ g_return_if_fail (E_IS_SELECT_NAMES_EDITABLE (esne));
+
+ bonobo_pbclient_set_string (esne->priv->bag, "addresses", text, NULL);
+}
+
diff --git a/calendar/gui/e-select-names-editable.h b/calendar/gui/e-select-names-editable.h
new file mode 100644
index 0000000000..867118fe9e
--- /dev/null
+++ b/calendar/gui/e-select-names-editable.h
@@ -0,0 +1,64 @@
+/*
+ * e-select-names-editable.h
+ *
+ * Author: Mike Kestner <mkestner@ximian.com>
+ *
+ * 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.
+ */
+
+#ifndef __E_SELECT_NAMES_EDITABLE_H__
+#define __E_SELECT_NAMES_EDITABLE_H__
+
+#include <bonobo/bonobo-widget.h>
+
+G_BEGIN_DECLS
+
+#define E_TYPE_SELECT_NAMES_EDITABLE (e_select_names_editable_get_type ())
+#define E_SELECT_NAMES_EDITABLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_SELECT_NAMES_EDITABLE, ESelectNamesEditable))
+#define E_SELECT_NAMES_EDITABLE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), E_TYPE_SELECT_NAMES_EDITABLE, ESelectNamesEditableClass))
+#define E_IS_SELECT_NAMES_EDITABLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_SELECT_NAMES_EDITABLE))
+#define E_IS_SELECT_NAMES_EDITABLE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((o), E_TYPE_SELECT_NAMES_EDITABLE))
+#define E_SELECT_NAMES_EDITABLE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), E_TYPE_SELECT_NAMES_EDITABLE, ESelectNamesEditableClass))
+
+typedef struct _ESelectNamesEditable ESelectNamesEditable;
+typedef struct _ESelectNamesEditableClass ESelectNamesEditableClass;
+typedef struct _ESelectNamesEditablePriv ESelectNamesEditablePriv;
+
+struct _ESelectNamesEditable
+{
+ BonoboWidget parent;
+
+ ESelectNamesEditablePriv *priv;
+};
+
+struct _ESelectNamesEditableClass
+{
+ BonoboWidgetClass parent_class;
+};
+
+GType e_select_names_editable_get_type (void);
+
+ESelectNamesEditable *e_select_names_editable_construct (ESelectNamesEditable *esne);
+ESelectNamesEditable *e_select_names_editable_new (void);
+
+gchar *e_select_names_editable_get_address (ESelectNamesEditable *esne);
+void e_select_names_editable_set_address (ESelectNamesEditable *esne, const gchar *text);
+
+gchar *e_select_names_editable_get_name (ESelectNamesEditable *esne);
+G_END_DECLS
+
+#endif /* __E_SELECT_NAMES_EDITABLE_H__ */
diff --git a/calendar/gui/e-select-names-renderer.c b/calendar/gui/e-select-names-renderer.c
new file mode 100644
index 0000000000..9b325d6ac0
--- /dev/null
+++ b/calendar/gui/e-select-names-renderer.c
@@ -0,0 +1,176 @@
+/*
+ * e-select-names-renderer.c
+ *
+ * Author: Mike Kestner <mkestner@ximian.com>
+ *
+ * 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.
+ */
+
+#include <config.h>
+#include <gtk/gtkcellrenderertext.h>
+#include <gal/util/e-util.h>
+
+#include "cal-util/cal-util-marshal.h"
+
+#include "e-select-names-editable.h"
+#include "e-select-names-renderer.h"
+
+
+struct _ESelectNamesRendererPriv {
+ ESelectNamesEditable *editable;
+ gchar *path;
+ gchar *address;
+};
+
+enum {
+ PROP_0,
+ PROP_ADDRESS
+};
+
+enum {
+ CELL_EDITED,
+ LAST_SIGNAL
+};
+
+static GtkCellRendererTextClass *parent_class;
+static gint signals [LAST_SIGNAL];
+
+static void
+esnr_editing_done (GtkCellEditable *editable, ESelectNamesRenderer *cell)
+{
+ gchar *new_address, *new_name;
+
+ new_address = e_select_names_editable_get_address (E_SELECT_NAMES_EDITABLE (editable));
+ new_name = e_select_names_editable_get_name (E_SELECT_NAMES_EDITABLE (editable));
+
+ g_signal_emit (cell, signals [CELL_EDITED], 0, cell->priv->path, new_address, new_name);
+ g_free (new_address);
+ g_free (new_name);
+ g_free (cell->priv->path);
+ cell->priv->path = NULL;
+}
+
+static GtkCellEditable *
+esnr_start_editing (GtkCellRenderer *cell, GdkEvent *event, GtkWidget *widget, const gchar *path,
+ GdkRectangle *bg_area, GdkRectangle *cell_area, GtkCellRendererState flags)
+{
+ ESelectNamesRenderer *sn_cell = E_SELECT_NAMES_RENDERER (cell);
+ GtkCellRendererText *text_cell = GTK_CELL_RENDERER_TEXT (cell);
+ ESelectNamesEditable *editable;
+
+ if (!text_cell->editable)
+ return NULL;
+
+ editable = E_SELECT_NAMES_EDITABLE (e_select_names_editable_new ());
+ e_select_names_editable_set_address (editable, sn_cell->priv->address);
+ gtk_widget_show (GTK_WIDGET (editable));
+
+ g_signal_connect (editable, "editing-done", G_CALLBACK (esnr_editing_done), sn_cell);
+
+ sn_cell->priv->editable = g_object_ref (editable);
+ sn_cell->priv->path = g_strdup (path);
+
+ return GTK_CELL_EDITABLE (editable);
+}
+
+static void
+esnr_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ ESelectNamesRenderer *esnr = E_SELECT_NAMES_RENDERER (object);
+
+ switch (prop_id) {
+ case PROP_ADDRESS:
+ g_value_set_string (value, esnr->priv->address);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+esnr_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ ESelectNamesRenderer *esnr = E_SELECT_NAMES_RENDERER (object);
+
+ switch (prop_id) {
+ case PROP_ADDRESS:
+ g_free (esnr->priv->address);
+ esnr->priv->address = g_strdup (g_value_get_string (value));
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+esnr_finalize (GObject *obj)
+{
+ ESelectNamesRenderer *cell = (ESelectNamesRenderer *) obj;
+
+ if (cell->priv->editable)
+ g_object_unref (cell->priv->editable);
+ cell->priv->editable = NULL;
+
+ g_free (cell->priv->path);
+ g_free (cell->priv->address);
+ g_free (cell->priv);
+
+ if (G_OBJECT_CLASS (parent_class)->finalize)
+ G_OBJECT_CLASS (parent_class)->finalize (obj);
+}
+
+static void
+esnr_init (ESelectNamesRenderer *cell)
+{
+ cell->priv = g_new0 (ESelectNamesRendererPriv, 1);
+}
+
+static void
+esnr_class_init (ESelectNamesRendererClass *class)
+{
+ GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
+ GObjectClass *obj_class = G_OBJECT_CLASS (class);
+
+ parent_class = GTK_CELL_RENDERER_TEXT_CLASS (g_type_class_peek_parent (class));
+
+ obj_class->finalize = esnr_finalize;
+ obj_class->get_property = esnr_get_property;
+ obj_class->set_property = esnr_set_property;
+
+ cell_class->start_editing = esnr_start_editing;
+
+ g_object_class_install_property (obj_class, PROP_ADDRESS,
+ g_param_spec_string ("address", "Address", "Email address.", NULL, G_PARAM_READWRITE));
+
+ signals [CELL_EDITED] = g_signal_new ("cell_edited",
+ G_OBJECT_CLASS_TYPE (obj_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ESelectNamesRendererClass, cell_edited),
+ NULL, NULL,
+ cal_util_marshal_VOID__STRING_STRING_STRING,
+ G_TYPE_NONE, 3,
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+}
+
+E_MAKE_TYPE (e_select_names_renderer, "ESelectNamesRenderer", ESelectNamesRenderer, esnr_class_init, esnr_init, GTK_TYPE_CELL_RENDERER_TEXT)
+
+GtkCellRenderer *
+e_select_names_renderer_new (void)
+{
+ return GTK_CELL_RENDERER (g_object_new (E_TYPE_SELECT_NAMES_RENDERER, NULL));
+}
+
diff --git a/calendar/gui/e-select-names-renderer.h b/calendar/gui/e-select-names-renderer.h
new file mode 100644
index 0000000000..fb045d928f
--- /dev/null
+++ b/calendar/gui/e-select-names-renderer.h
@@ -0,0 +1,63 @@
+/*
+ * e-select-names-renderer.h
+ *
+ * Author: Mike Kestner <mkestner@ximian.com>
+ *
+ * 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.
+ */
+
+#ifndef __E_SELECT_NAMES_RENDERER_H__
+#define __E_SELECT_NAMES_RENDERER_H__
+
+#include <gtk/gtkcellrenderertext.h>
+
+G_BEGIN_DECLS
+
+#define E_TYPE_SELECT_NAMES_RENDERER (e_select_names_renderer_get_type ())
+#define E_SELECT_NAMES_RENDERER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_SELECT_NAMES_RENDERER, ESelectNamesRenderer))
+#define E_SELECT_NAMES_RENDERER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), E_TYPE_SELECT_NAMES_RENDERER, ESelectNamesRendererClass))
+#define E_IS_SELECT_NAMES_RENDERER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_SELECT_NAMES_RENDERER))
+#define E_IS_SELECT_NAMES_RENDERER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((o), E_TYPE_SELECT_NAMES_RENDERER))
+#define E_SELECT_NAMES_RENDERER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), E_TYPE_SELECT_NAMES_RENDERER, ESelectNamesRendererClass))
+
+typedef struct _ESelectNamesRenderer ESelectNamesRenderer;
+typedef struct _ESelectNamesRendererClass ESelectNamesRendererClass;
+typedef struct _ESelectNamesRendererPriv ESelectNamesRendererPriv;
+
+struct _ESelectNamesRenderer
+{
+ GtkCellRendererText parent;
+
+ ESelectNamesRendererPriv *priv;
+};
+
+struct _ESelectNamesRendererClass
+{
+ GtkCellRendererTextClass parent_class;
+
+ void (* cell_edited) (ESelectNamesRenderer *renderer,
+ const gchar *path,
+ const gchar *address,
+ const gchar *name);
+};
+
+GType e_select_names_renderer_get_type (void);
+GtkCellRenderer *e_select_names_renderer_new (void);
+
+G_END_DECLS
+
+#endif /* __E_SELECT_NAMES_RENDERER_H__ */