aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/gui
diff options
context:
space:
mode:
authorJP Rosevear <jpr@ximian.com>2001-06-20 03:24:08 +0800
committerJP Rosevear <jpr@src.gnome.org>2001-06-20 03:24:08 +0800
commitca603236ed6d7a43bc4587b70d6163ee1d95e310 (patch)
tree458dd3880e4c65f417758684936ef30a2f7dba7f /calendar/gui
parent4b11ecbffc519e8dfccdebaa26b021f131254d78 (diff)
downloadgsoc2013-evolution-ca603236ed6d7a43bc4587b70d6163ee1d95e310.tar
gsoc2013-evolution-ca603236ed6d7a43bc4587b70d6163ee1d95e310.tar.gz
gsoc2013-evolution-ca603236ed6d7a43bc4587b70d6163ee1d95e310.tar.bz2
gsoc2013-evolution-ca603236ed6d7a43bc4587b70d6163ee1d95e310.tar.lz
gsoc2013-evolution-ca603236ed6d7a43bc4587b70d6163ee1d95e310.tar.xz
gsoc2013-evolution-ca603236ed6d7a43bc4587b70d6163ee1d95e310.tar.zst
gsoc2013-evolution-ca603236ed6d7a43bc4587b70d6163ee1d95e310.zip
itip/imip send dialog
2001-06-19 JP Rosevear <jpr@ximian.com> * gui/dialogs/send-comp.c: itip/imip send dialog * gui/dialogs/send-comp.h: new proto * gui/dialogs/recurrence-page.c (recurrence_page_set_dates): only use the weekday picker if visible * gui/dialogs/meeting-page.c: just show the meeting list * gui/dialogs/event-editor.c (event_editor_edit_comp): remove the meeting page if no attendees (schedule_meeting_cmd): schedule a meeting menu item (refresh_meeting_cmd): refresh meeting request menu item (cancel_meeting_cmd): ditto for cancel (forward_cmd): send as attachment * gui/dialogs/comp-editor.c (comp_editor_remove_page): remove page from dialog (comp_editor_show_page): show a given page (comp_editor_get_current_comp): return a cal component representing the current widget state (comp_editor_save_comp): save the cal component (comp_editor_delete_comp): delete the cal component (comp_editor_send_comp): send the cal component (comp_editor_merge_ui): merge xml in to the bonobo gui (setup_widgets): use a bonobo window instead of a gtk window, add menus again (save_as_cmd): save to file on disk - still broken (save_close_cmd): close menu command (save_close_cmd): save and close menu command * gui/dialogs/comp-editor.h: new protos * gui/dialogs/cancel-comp.c (cancel_component_dialog): itip/imip cancellation dialog * gui/dialogs/cancel-comp.h: new proto * gui/dialogs/Makefile.am: build new files * gui/dialogs/comp-editor-page.c (comp_editor_page_notify_needs_send): emit needs_send signal * gui/dialogs/comp-editor-page.h: new signal protos * gui/itip-utils.c (itip_send_comp): new function to send cal components * gui/itip-utils.h: new proto * gui/e-itip-control.c (pstream_load): trim using cal-component wrapper stuff (accept_button_clicked_cb): use itip_send_comp (tentative_button_clicked_cb): ditto (decline_button_clicked_cb): ditto * gui/Makefile.am: compile select name idl stuff * cal-util/cal-component.c (cal_component_get_organizer): get the organizer (cal_component_set_organizer): set the organizer (cal_component_get_recurid): get the recurrence id (cal_component_set_recurid): set the recurrence id (set_attendee_list): actually set the attendee list (get_attendee_list): build the attendee list * cal-util/cal-component.h: new protos svn path=/trunk/; revision=10299
Diffstat (limited to 'calendar/gui')
-rw-r--r--calendar/gui/Makefile.am21
-rw-r--r--calendar/gui/dialogs/Makefile.am7
-rw-r--r--calendar/gui/dialogs/cancel-comp.c84
-rw-r--r--calendar/gui/dialogs/cancel-comp.h30
-rw-r--r--calendar/gui/dialogs/comp-editor-page.c51
-rw-r--r--calendar/gui/dialogs/comp-editor-page.h11
-rw-r--r--calendar/gui/dialogs/comp-editor.c461
-rw-r--r--calendar/gui/dialogs/comp-editor.h42
-rw-r--r--calendar/gui/dialogs/event-editor.c111
-rw-r--r--calendar/gui/dialogs/meeting-page.c739
-rw-r--r--calendar/gui/dialogs/meeting-page.glade103
-rw-r--r--calendar/gui/dialogs/recurrence-page.c10
-rw-r--r--calendar/gui/dialogs/send-comp.c84
-rw-r--r--calendar/gui/dialogs/send-comp.h30
-rw-r--r--calendar/gui/e-itip-control.c487
-rw-r--r--calendar/gui/itip-utils.c228
-rw-r--r--calendar/gui/itip-utils.h14
17 files changed, 1862 insertions, 651 deletions
diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am
index 4aec1db792..6fd84da671 100644
--- a/calendar/gui/Makefile.am
+++ b/calendar/gui/Makefile.am
@@ -1,17 +1,24 @@
## CORBA stuff
IDLS = \
- $(srcdir)/../../composer/Evolution-Composer.idl
-
-IDL_GENERATED = \
- Evolution-Composer.h \
- Evolution-Composer-common.c \
- Evolution-Composer-skels.c \
- Evolution-Composer-stubs.c
+ $(top_srcdir)/composer/Evolution-Composer.idl \
+ $(top_srcdir)/addressbook/gui/component/select-names/Evolution-Addressbook-SelectNames.idl
+
+IDL_GENERATED = \
+e Evolution-Composer.h \
+ Evolution-Composer-common.c \
+ Evolution-Composer-skels.c \
+ Evolution-Composer-stubs.c \
+ Evolution-Addressbook-SelectNames.h \
+ Evolution-Addressbook-SelectNames-common.c \
+ Evolution-Addressbook-SelectNames-skels.c \
+ Evolution-Addressbook-SelectNames-stubs.c
$(IDL_GENERATED): $(IDLS)
$(ORBIT_IDL) -I $(srcdir) -I $(datadir)/idl `$(GNOME_CONFIG) --cflags idl` \
$(srcdir)/../../composer/Evolution-Composer.idl
+ $(ORBIT_IDL) -I $(srcdir) -I $(datadir)/idl `$(GNOME_CONFIG) --cflags idl` \
+ $(top_srcdir)/addressbook/gui/component/select-names/Evolution-Addressbook-SelectNames.idl
SUBDIRS = alarm-notify dialogs
diff --git a/calendar/gui/dialogs/Makefile.am b/calendar/gui/dialogs/Makefile.am
index de97ea2d45..1bd4b5034e 100644
--- a/calendar/gui/dialogs/Makefile.am
+++ b/calendar/gui/dialogs/Makefile.am
@@ -24,6 +24,8 @@ libcal_dialogs_a_SOURCES = \
alarm-page.h \
cal-prefs-dialog.c \
cal-prefs-dialog.h \
+ cancel-comp.c \
+ cancel-comp.h \
comp-editor.c \
comp-editor.h \
comp-editor-page.c \
@@ -38,10 +40,14 @@ libcal_dialogs_a_SOURCES = \
event-editor.h \
event-page.c \
event-page.h \
+ meeting-page.c \
+ meeting-page.h \
recurrence-page.c \
recurrence-page.h \
save-comp.c \
save-comp.h \
+ send-comp.c \
+ send-comp.h \
task-editor.c \
task-editor.h \
task-details-page.c \
@@ -55,6 +61,7 @@ glade_DATA = \
cal-prefs-dialog.glade \
e-timezone-dialog.glade \
event-page.glade \
+ meeting-page.glade \
recurrence-page.glade \
task-details-page.glade \
task-page.glade
diff --git a/calendar/gui/dialogs/cancel-comp.c b/calendar/gui/dialogs/cancel-comp.c
new file mode 100644
index 0000000000..4362f9da7f
--- /dev/null
+++ b/calendar/gui/dialogs/cancel-comp.c
@@ -0,0 +1,84 @@
+/* Evolution calendar - Send calendar component dialog
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Author: JP Rosevear <jpr@ximian.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <libgnome/gnome-defs.h>
+#include <libgnome/gnome-i18n.h>
+#include <libgnomeui/gnome-dialog.h>
+#include <libgnomeui/gnome-dialog-util.h>
+#include <libgnomeui/gnome-uidefs.h>
+#include <gal/widgets/e-unicode.h>
+#include "cancel-comp.h"
+
+
+
+/**
+ * cancel_component_dialog:
+ *
+ * Pops up a dialog box asking the user whether he wants to send a
+ * cancel and delete an iTip/iMip message
+ *
+ * Return value: TRUE if the user clicked Yes, FALSE otherwise.
+ **/
+gboolean
+cancel_component_dialog (CalComponent *comp)
+{
+ GtkWidget *dialog;
+ CalComponentVType vtype;
+ char *str;
+
+ str = _("The meeting status has changed. Send an updated version?");
+
+ vtype = cal_component_get_vtype (comp);
+
+ switch (vtype) {
+ case CAL_COMPONENT_EVENT:
+ str = g_strdup_printf (_("Are you sure you want to cancel "
+ "and delete this meeting?"));
+ break;
+
+ case CAL_COMPONENT_TODO:
+ str = g_strdup_printf (_("Are you sure you want to cancel "
+ "and delete this task?"));
+ break;
+
+ case CAL_COMPONENT_JOURNAL:
+ str = g_strdup_printf (_("Are you sure you want to cancel "
+ "and delete this journal entry?"));
+ break;
+
+ default:
+ g_message ("send_component_dialog(): "
+ "Cannot handle object of type %d", vtype);
+ return FALSE;
+ }
+
+ dialog = gnome_question_dialog_modal (str, NULL, NULL);
+
+ if (gnome_dialog_run (GNOME_DIALOG (dialog)) == GNOME_YES)
+ return TRUE;
+ else
+ return FALSE;
+}
diff --git a/calendar/gui/dialogs/cancel-comp.h b/calendar/gui/dialogs/cancel-comp.h
new file mode 100644
index 0000000000..04f1768e3d
--- /dev/null
+++ b/calendar/gui/dialogs/cancel-comp.h
@@ -0,0 +1,30 @@
+/* Evolution calendar - Send calendar component dialog
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Author: JP Rosevear <jpr@ximian.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CANCEL_COMP_H
+#define CANCEL_COMP_H
+
+#include <glib.h>
+#include <cal-util/cal-component.h>
+
+gboolean cancel_component_dialog (CalComponent *comp);
+
+#endif
diff --git a/calendar/gui/dialogs/comp-editor-page.c b/calendar/gui/dialogs/comp-editor-page.c
index eab0a50566..005314d0c0 100644
--- a/calendar/gui/dialogs/comp-editor-page.c
+++ b/calendar/gui/dialogs/comp-editor-page.c
@@ -34,6 +34,7 @@ static void comp_editor_page_class_init (CompEditorPageClass *class);
enum {
CHANGED,
+ NEEDS_SEND,
SUMMARY_CHANGED,
DATES_CHANGED,
LAST_SIGNAL
@@ -95,6 +96,15 @@ comp_editor_page_class_init (CompEditorPageClass *class)
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
+ comp_editor_page_signals[NEEDS_SEND] =
+ gtk_signal_new ("needs_send",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (CompEditorPageClass,
+ needs_send),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
comp_editor_page_signals[SUMMARY_CHANGED] =
gtk_signal_new ("summary_changed",
GTK_RUN_FIRST,
@@ -189,6 +199,23 @@ comp_editor_page_fill_component (CompEditorPage *page, CalComponent *comp)
}
/**
+ * comp_editor_page_set_cal_client:
+ * @page: An editor page
+ * @client: A #CalClient object
+ *
+ * Sets the #CalClient for the dialog page to use.
+ **/
+void
+comp_editor_page_set_cal_client (CompEditorPage *page, CalClient *client)
+{
+ g_return_if_fail (page != NULL);
+ g_return_if_fail (IS_COMP_EDITOR_PAGE (page));
+
+ if (CLASS (page)->set_cal_client != NULL)
+ (* CLASS (page)->set_cal_client) (page, client);
+}
+
+/**
* comp_editor_page_set_summary:
* @page: An editor page
* @summary: The text of the new summary value
@@ -223,36 +250,34 @@ comp_editor_page_set_dates (CompEditorPage *page, CompEditorPageDates *dates)
}
/**
- * comp_editor_page_set_cal_client:
- * @page: An editor page
- * @client: A #CalClient object
+ * comp_editor_page_notify_changed:
+ * @page: An editor page.
*
- * Sets the #CalClient for the dialog page to use.
+ * Makes an editor page emit the "changed" signal. This is meant to be
+ * used only by page implementations.
**/
void
-comp_editor_page_set_cal_client (CompEditorPage *page, CalClient *client)
+comp_editor_page_notify_changed (CompEditorPage *page)
{
g_return_if_fail (page != NULL);
g_return_if_fail (IS_COMP_EDITOR_PAGE (page));
- if (CLASS (page)->set_cal_client != NULL)
- (* CLASS (page)->set_cal_client) (page, client);
+ gtk_signal_emit (GTK_OBJECT (page), comp_editor_page_signals[CHANGED]);
}
/**
- * comp_editor_page_notify_changed:
- * @page: An editor page.
+ * comp_editor_page_notify_needs_send:
+ * @page:
+ *
*
- * Makes an editor page emit the "changed" signal. This is meant to be
- * used only by page implementations.
**/
void
-comp_editor_page_notify_changed (CompEditorPage *page)
+comp_editor_page_notify_needs_send (CompEditorPage *page)
{
g_return_if_fail (page != NULL);
g_return_if_fail (IS_COMP_EDITOR_PAGE (page));
- gtk_signal_emit (GTK_OBJECT (page), comp_editor_page_signals[CHANGED]);
+ gtk_signal_emit (GTK_OBJECT (page), comp_editor_page_signals[NEEDS_SEND]);
}
/**
diff --git a/calendar/gui/dialogs/comp-editor-page.h b/calendar/gui/dialogs/comp-editor-page.h
index 931aa32d62..c4c31852cf 100644
--- a/calendar/gui/dialogs/comp-editor-page.h
+++ b/calendar/gui/dialogs/comp-editor-page.h
@@ -54,9 +54,11 @@ typedef struct {
/* Notification signals */
- void (* changed) (CompEditorPage *page);
+ void (* changed) (CompEditorPage *page);
+ void (* needs_send) (CompEditorPage *page);
+
void (* summary_changed) (CompEditorPage *page, const char *summary);
- void (* dates_changed) (CompEditorPage *page, const char *dates);
+ void (* dates_changed) (CompEditorPage *page, const char *dates);
/* Virtual methods */
@@ -78,13 +80,14 @@ void comp_editor_page_fill_widgets (CompEditorPage *page,
CalComponent *comp);
void comp_editor_page_fill_component (CompEditorPage *page,
CalComponent *comp);
+void comp_editor_page_set_cal_client (CompEditorPage *page,
+ CalClient *client);
void comp_editor_page_set_summary (CompEditorPage *page,
const char *summary);
void comp_editor_page_set_dates (CompEditorPage *page,
CompEditorPageDates *dates);
-void comp_editor_page_set_cal_client (CompEditorPage *page,
- CalClient *client);
void comp_editor_page_notify_changed (CompEditorPage *page);
+void comp_editor_page_notify_needs_send (CompEditorPage *page);
void comp_editor_page_notify_summary_changed (CompEditorPage *page,
const char *summary);
void comp_editor_page_notify_dates_changed (CompEditorPage *page,
diff --git a/calendar/gui/dialogs/comp-editor.c b/calendar/gui/dialogs/comp-editor.c
index 2d894f3ff2..5347a40df3 100644
--- a/calendar/gui/dialogs/comp-editor.c
+++ b/calendar/gui/dialogs/comp-editor.c
@@ -23,9 +23,18 @@
#include <config.h>
#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include <gnome.h>
+#include <bonobo/bonobo-win.h>
+#include <bonobo/bonobo-ui-component.h>
+#include <bonobo/bonobo-ui-container.h>
+#include <bonobo/bonobo-ui-util.h>
#include <gal/widgets/e-unicode.h>
#include "save-comp.h"
+#include "delete-comp.h"
+#include "send-comp.h"
#include "comp-editor.h"
@@ -43,11 +52,15 @@ struct _CompEditorPrivate {
/* Toplevel window for the dialog */
GtkWidget *window;
-
+ BonoboUIComponent *uic;
+
/* Notebook to hold the pages */
GtkNotebook *notebook;
+ GtkWidget *filesel;
+
gboolean changed;
+ gboolean needs_send;
};
@@ -56,15 +69,37 @@ static void comp_editor_class_init (CompEditorClass *class);
static void comp_editor_init (CompEditor *editor);
static void comp_editor_destroy (GtkObject *object);
+static void real_edit_comp (CompEditor *editor, CalComponent *comp);
+static void save_comp (CompEditor *editor);
+static void delete_comp (CompEditor *editor);
+static void close_dialog (CompEditor *editor);
+
+static void page_changed_cb (GtkWidget *widget, gpointer data);
+static void page_needs_send_cb (GtkWidget *widget, gpointer data);
static void page_summary_changed_cb (GtkWidget *widget, const char *summary, gpointer data);
static void page_dates_changed_cb (GtkWidget *widget, CompEditorPageDates *dates, gpointer data);
-static void page_changed_cb (GtkWidget *widget, gpointer data);
+
+static void save_close_cmd (GtkWidget *widget, gpointer data);
+static void save_as_cmd (GtkWidget *widget, gpointer data);
+static void delete_cmd (GtkWidget *widget, gpointer data);
+static void close_cmd (GtkWidget *widget, gpointer data);
static void save_clicked_cb (GtkWidget *widget, gpointer data);
static void close_clicked_cb (GtkWidget *widget, gpointer data);
static void help_clicked_cb (GtkWidget *widget, gpointer data);
static gint delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer data);
+static BonoboUIVerb verbs [] = {
+ BONOBO_UI_UNSAFE_VERB ("FileSaveAndClose", save_close_cmd),
+ BONOBO_UI_UNSAFE_VERB ("FileSaveAs", save_as_cmd),
+ BONOBO_UI_UNSAFE_VERB ("FileDelete", delete_cmd),
+ BONOBO_UI_UNSAFE_VERB ("FileClose", close_cmd),
+
+ BONOBO_UI_VERB_END
+};
+
+#define CLASS(page) (COMP_EDITOR_CLASS (GTK_OBJECT (page)->klass))
+
static GtkObjectClass *parent_class;
@@ -95,14 +130,16 @@ comp_editor_get_type (void)
/* Class initialization function for the calendar component editor */
static void
-comp_editor_class_init (CompEditorClass *class)
+comp_editor_class_init (CompEditorClass *klass)
{
GtkObjectClass *object_class;
- object_class = (GtkObjectClass *) class;
+ object_class = (GtkObjectClass *) klass;
parent_class = gtk_type_class (GTK_TYPE_OBJECT);
+ klass->edit_comp = real_edit_comp;
+
object_class->destroy = comp_editor_destroy;
}
@@ -111,6 +148,7 @@ static void
setup_widgets (CompEditor *editor)
{
CompEditorPrivate *priv;
+ BonoboUIContainer *container;
GtkWidget *vbox;
GtkWidget *bbox;
GtkWidget *pixmap;
@@ -119,23 +157,29 @@ setup_widgets (CompEditor *editor)
priv = editor->priv;
/* Window and basic vbox */
-
- priv->window = gtk_window_new (GTK_WINDOW_DIALOG);
+ priv->window = bonobo_window_new ("event-editor", "iCalendar Editor");
gtk_signal_connect (GTK_OBJECT (priv->window), "delete_event",
GTK_SIGNAL_FUNC (delete_event_cb), editor);
+ priv->uic = bonobo_ui_component_new ("comp-editor");
+ container = bonobo_ui_container_new ();
+ bonobo_ui_container_set_win (container, BONOBO_WINDOW (priv->window));
+ bonobo_ui_component_set_container (priv->uic, BONOBO_OBJREF (container));
+
+ bonobo_ui_component_add_verb_list_with_data (priv->uic, verbs, editor);
+ bonobo_ui_util_set_ui (priv->uic, EVOLUTION_DATADIR "/gnome/gui",
+ "evolution-comp-editor.xml", "evolution-calendar");
+
vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
gtk_container_set_border_width (GTK_CONTAINER (vbox), GNOME_PAD_SMALL);
- gtk_container_add (GTK_CONTAINER (priv->window), vbox);
+ bonobo_window_set_contents (BONOBO_WINDOW (priv->window), vbox);
/* Notebook */
-
priv->notebook = GTK_NOTEBOOK (gtk_notebook_new ());
gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (priv->notebook),
TRUE, TRUE, 0);
/* Buttons */
-
bbox = gtk_hbutton_box_new ();
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0);
@@ -170,6 +214,7 @@ comp_editor_init (CompEditor *editor)
priv->pages = NULL;
priv->changed = FALSE;
+ priv->needs_send = FALSE;
}
/* Destroy handler for the calendar component editor */
@@ -199,7 +244,7 @@ comp_editor_destroy (GtkObject *object)
/**
* comp_editor_append_page:
* @editor: A component editor
- * @page: Top level widget of the page
+ * @page: A component editor page
* @label: Label of the page
*
* Appends a page to the editor notebook with the given label
@@ -212,7 +257,7 @@ comp_editor_append_page (CompEditor *editor,
CompEditorPrivate *priv;
GtkWidget *page_widget;
GtkWidget *label_widget;
-
+
g_return_if_fail (editor != NULL);
g_return_if_fail (IS_COMP_EDITOR (editor));
g_return_if_fail (page != NULL);
@@ -221,9 +266,15 @@ comp_editor_append_page (CompEditor *editor,
priv = editor->priv;
- /* Only allow adding the pages while a component has not been set */
- g_return_if_fail (priv->comp == NULL);
-
+ /* If we are editing something, fill the widgets with current info */
+ if (priv->comp != NULL) {
+ CalComponent *comp;
+
+ comp = comp_editor_get_current_comp (editor);
+ comp_editor_page_fill_widgets (page, comp);
+ gtk_object_unref (GTK_OBJECT (comp));
+ }
+
page_widget = comp_editor_page_get_widget (page);
g_assert (page_widget != NULL);
@@ -233,12 +284,67 @@ comp_editor_append_page (CompEditor *editor,
gtk_notebook_append_page (priv->notebook, page_widget, label_widget);
/* Listen for things happening on the page */
+ gtk_signal_connect (GTK_OBJECT (page), "needs_send",
+ GTK_SIGNAL_FUNC (page_needs_send_cb), editor);
+ gtk_signal_connect (GTK_OBJECT (page), "changed",
+ GTK_SIGNAL_FUNC (page_changed_cb), editor);
gtk_signal_connect (GTK_OBJECT (page), "summary_changed",
GTK_SIGNAL_FUNC (page_summary_changed_cb), editor);
gtk_signal_connect (GTK_OBJECT (page), "dates_changed",
GTK_SIGNAL_FUNC (page_dates_changed_cb), editor);
- gtk_signal_connect (GTK_OBJECT (page), "changed",
- GTK_SIGNAL_FUNC (page_changed_cb), editor);
+
+}
+
+/**
+ * comp_editor_remove_page:
+ * @editor: A component editor
+ * @page: A component editor page
+ *
+ * Removes the page from the component editor
+ **/
+void
+comp_editor_remove_page (CompEditor *editor, CompEditorPage *page)
+{
+ CompEditorPrivate *priv;
+ GtkWidget *page_widget;
+ gint page_num;
+
+ g_return_if_fail (editor != NULL);
+ g_return_if_fail (IS_COMP_EDITOR (editor));
+ g_return_if_fail (page != NULL);
+ g_return_if_fail (IS_COMP_EDITOR_PAGE (page));
+
+ priv = editor->priv;
+
+ page_widget = comp_editor_page_get_widget (page);
+ page_num = gtk_notebook_page_num (priv->notebook, page_widget);
+ gtk_notebook_remove_page (priv->notebook, page_num);
+}
+
+/**
+ * comp_editor_show_page:
+ * @editor:
+ * @page:
+ *
+ *
+ **/
+void
+comp_editor_show_page (CompEditor *editor, CompEditorPage *page)
+{
+ CompEditorPrivate *priv;
+ GtkWidget *page_widget;
+ gint page_num;
+
+ g_return_if_fail (editor != NULL);
+ g_return_if_fail (IS_COMP_EDITOR (editor));
+ g_return_if_fail (page != NULL);
+ g_return_if_fail (IS_COMP_EDITOR_PAGE (page));
+
+ priv = editor->priv;
+
+ page_widget = comp_editor_page_get_widget (page);
+ page_num = gtk_notebook_page_num (priv->notebook, page_widget);
+ gtk_notebook_set_page (priv->notebook, page_num);
}
/**
@@ -368,15 +474,8 @@ fill_widgets (CompEditor *editor)
comp_editor_page_fill_widgets (l->data, priv->comp);
}
-/**
- * comp_editor_edit_comp:
- * @editor: A component editor
- * @comp: A calendar component
- *
- * Starts the editor editing the given component
- **/
-void
-comp_editor_edit_comp (CompEditor *editor, CalComponent *comp)
+static void
+real_edit_comp (CompEditor *editor, CalComponent *comp)
{
CompEditorPrivate *priv;
@@ -394,9 +493,124 @@ comp_editor_edit_comp (CompEditor *editor, CalComponent *comp)
priv->comp = cal_component_clone (comp);
set_title_from_comp (editor);
- fill_widgets (editor);
+ fill_widgets (editor);
}
+
+/**
+ * comp_editor_edit_comp:
+ * @editor: A component editor
+ * @comp: A calendar component
+ *
+ * Starts the editor editing the given component
+ **/
+void
+comp_editor_edit_comp (CompEditor *editor, CalComponent *comp)
+{
+ CompEditorClass *klass;
+
+ g_return_if_fail (editor != NULL);
+ g_return_if_fail (IS_COMP_EDITOR (editor));
+ g_return_if_fail (comp != NULL);
+ g_return_if_fail (IS_CAL_COMPONENT (comp));
+
+ klass = COMP_EDITOR_CLASS (GTK_OBJECT (editor)->klass);
+
+ if (klass->edit_comp)
+ klass->edit_comp (editor, comp);
+}
+
+CalComponent *
+comp_editor_get_current_comp (CompEditor *editor)
+{
+ CompEditorPrivate *priv;
+ CalComponent *comp;
+ GList *l;
+
+ g_return_val_if_fail (editor != NULL, NULL);
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), NULL);
+
+ priv = editor->priv;
+
+ comp = cal_component_clone (priv->comp);
+ for (l = priv->pages; l != NULL; l = l->next)
+ comp_editor_page_fill_component (l->data, comp);
+
+ return comp;
+}
+
+/**
+ * comp_editor_save_comp:
+ * @editor:
+ *
+ *
+ **/
+void
+comp_editor_save_comp (CompEditor *editor)
+{
+ save_comp (editor);
+}
+
+/**
+ * comp_editor_delete_comp:
+ * @editor:
+ *
+ *
+ **/
+void
+comp_editor_delete_comp (CompEditor *editor)
+{
+ delete_comp (editor);
+}
+
+/**
+ * comp_editor_send_comp:
+ * @editor:
+ * @method:
+ *
+ *
+ **/
+void
+comp_editor_send_comp (CompEditor *editor, CalComponentItipMethod method)
+{
+ CalComponent *comp;
+
+ comp = comp_editor_get_current_comp (editor);
+
+ cal_component_commit_sequence (comp);
+ itip_send_comp (method, comp);
+
+ gtk_object_unref (GTK_OBJECT (comp));
+}
+
+/**
+ * comp_editor_merge_ui:
+ * @editor:
+ * @filename:
+ * @verbs:
+ *
+ *
+ **/
+void
+comp_editor_merge_ui (CompEditor *editor, const char *filename, BonoboUIVerb *verbs)
+{
+ CompEditorPrivate *priv;
+ BonoboUIEngine *engine;
+ BonoboUINode *node;
+
+ g_return_if_fail (editor != NULL);
+ g_return_if_fail (IS_COMP_EDITOR (editor));
+
+ priv = editor->priv;
+
+ engine = bonobo_window_get_ui_engine (BONOBO_WINDOW (priv->window));
+ node = bonobo_ui_util_new_ui (priv->uic, filename, "",
+ "evolution-calendar");
+ g_assert (node != NULL);
+
+ bonobo_ui_engine_xml_merge_tree (engine, "/", node, "comp-editor");
+ bonobo_ui_component_add_verb_list_with_data (priv->uic, verbs, editor);
+}
/* Brings attention to a window by raising it and giving it focus */
static void
@@ -438,17 +652,35 @@ save_comp (CompEditor *editor)
for (l = priv->pages; l != NULL; l = l->next)
comp_editor_page_fill_component (l->data, priv->comp);
+ if (priv->needs_send && send_component_dialog (priv->comp)) {
+ cal_component_commit_sequence (priv->comp);
+ itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, priv->comp);
+ }
+
if (!cal_client_update_object (priv->client, priv->comp))
g_message ("save_comp (): Could not update the object!");
else
priv->changed = FALSE;
}
+static void
+delete_comp (CompEditor *editor)
+{
+ CompEditorPrivate *priv;
+ const char *uid;
+
+ priv = editor->priv;
+
+ cal_component_get_uid (priv->comp, &uid);
+ cal_client_remove_object (priv->client, uid);
+ close_dialog (editor);
+}
+
static gboolean
prompt_to_save_changes (CompEditor *editor)
{
CompEditorPrivate *priv;
-
+
priv = editor->priv;
if (!priv->changed)
@@ -465,7 +697,6 @@ prompt_to_save_changes (CompEditor *editor)
case 2: /* Cancel */
default:
return FALSE;
- break;
}
}
@@ -482,6 +713,144 @@ close_dialog (CompEditor *editor)
gtk_object_destroy (GTK_OBJECT (editor));
}
+/* Menu Commands */
+static void
+save_close_cmd (GtkWidget *widget, gpointer data)
+{
+ CompEditor *editor = COMP_EDITOR (data);
+
+ save_comp (editor);
+ close_dialog (editor);
+}
+
+static void
+save_as_ok (GtkWidget *widget, gpointer data)
+{
+ CompEditor *editor = COMP_EDITOR (data);
+ CompEditorPrivate *priv;
+ char *path;
+ int fd, ret = 0;
+
+ priv = editor->priv;
+
+ path = gtk_file_selection_get_filename (GTK_FILE_SELECTION (priv->filesel));
+
+ fd = open (path, O_RDONLY);
+ if (fd != -1) {
+ GtkWidget *dlg;
+ GtkWidget *text;
+
+ close (fd);
+
+ dlg = gnome_dialog_new (_("Overwrite file?"),
+ GNOME_STOCK_BUTTON_YES,
+ GNOME_STOCK_BUTTON_NO,
+ NULL);
+ text = gtk_label_new (_("A file by that name already exists.\nOverwrite it?"));
+ gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dlg)->vbox), text, TRUE, TRUE, 4);
+ gtk_window_set_policy (GTK_WINDOW (dlg), FALSE, TRUE, FALSE);
+ gtk_widget_show (text);
+
+ ret = gnome_dialog_run_and_close (GNOME_DIALOG (dlg));
+ }
+
+ if (ret == 0) {
+ gchar *ical_string;
+
+ icalcomponent *top_level;
+ icalcomponent *icalcomp;
+ icalproperty *prop;
+
+ top_level = icalcomponent_new (ICAL_VCALENDAR_COMPONENT);
+
+ /* RFC 2445, section 4.7.1 */
+ prop = icalproperty_new_calscale ("GREGORIAN");
+ icalcomponent_add_property (top_level, prop);
+
+ /* RFC 2445, section 4.7.3 */
+ prop = icalproperty_new_prodid ("-//Ximian//NONSGML Evolution Calendar//EN");
+ icalcomponent_add_property (top_level, prop);
+
+ /* RFC 2445, section 4.7.4. This is the iCalendar spec version, *NOT*
+ * the product version! Do not change this!
+ */
+ prop = icalproperty_new_version ("2.0");
+ icalcomponent_add_property (top_level, prop);
+
+ icalcomp = cal_component_get_icalcomponent (priv->comp);
+ g_assert (icalcomp != NULL);
+
+ icalcomponent_add_component (top_level, icalcomp);
+
+ ical_string = icalcomponent_as_ical_string (top_level);
+
+ fd = open (path, O_WRONLY);
+ if (fd == -1) {
+ g_warning ("Couldn't save item");
+ gtk_main_quit ();
+ return;
+ }
+
+ write (fd, ical_string, strlen (ical_string));
+ close (fd);
+
+ gtk_main_quit ();
+ }
+}
+
+static void
+save_as_cmd (GtkWidget *widget, gpointer data)
+{
+ CompEditor *editor = COMP_EDITOR (data);
+ CompEditorPrivate *priv;
+ GtkFileSelection *fs;
+ char *path;
+
+ priv = editor->priv;
+
+ fs = GTK_FILE_SELECTION (gtk_file_selection_new (_("Save As...")));
+ path = g_strdup_printf ("%s/", g_get_home_dir ());
+ gtk_file_selection_set_filename (fs, path);
+ g_free (path);
+
+ gtk_signal_connect (GTK_OBJECT (fs->ok_button), "clicked",
+ GTK_SIGNAL_FUNC (save_as_ok), editor);
+ gtk_signal_connect (GTK_OBJECT (fs->cancel_button), "clicked",
+ GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
+
+ priv->filesel = GTK_WIDGET (fs);
+ gtk_widget_show (priv->filesel);
+ gtk_grab_add (priv->filesel);
+ gtk_main ();
+
+ gtk_widget_destroy (priv->filesel);
+ priv->filesel = NULL;
+}
+
+static void
+delete_cmd (GtkWidget *widget, gpointer data)
+{
+ CompEditor *editor = COMP_EDITOR (data);
+ CompEditorPrivate *priv;
+ CalComponentVType vtype;
+
+ priv = editor->priv;
+
+ vtype = cal_component_get_vtype (priv->comp);
+
+ if (delete_component_dialog (priv->comp, 1, vtype, priv->window))
+ delete_comp (editor);
+}
+
+static void
+close_cmd (GtkWidget *widget, gpointer data)
+{
+ CompEditor *editor = COMP_EDITOR (data);
+
+ if (prompt_to_save_changes (editor))
+ close_dialog (editor);
+}
+
static void
save_clicked_cb (GtkWidget *widget, gpointer data)
{
@@ -500,12 +869,36 @@ close_clicked_cb (GtkWidget *widget, gpointer data)
close_dialog (editor);
}
+/* Button callbacks */
static void
help_clicked_cb (GtkWidget *widget, gpointer data)
{
}
static void
+page_changed_cb (GtkWidget *widget, gpointer data)
+{
+ CompEditor *editor = COMP_EDITOR (data);
+ CompEditorPrivate *priv;
+
+ priv = editor->priv;
+
+ priv->changed = TRUE;
+}
+
+static void
+page_needs_send_cb (GtkWidget *widget, gpointer data)
+{
+ CompEditor *editor = COMP_EDITOR (data);
+ CompEditorPrivate *priv;
+
+ priv = editor->priv;
+
+ priv->needs_send = TRUE;
+}
+
+/* Page signal callbacks */
+static void
page_summary_changed_cb (GtkWidget *widget, const char *summary, gpointer data)
{
CompEditor *editor = COMP_EDITOR (data);
@@ -537,18 +930,6 @@ page_dates_changed_cb (GtkWidget *widget,
priv->changed = TRUE;
}
-
-static void
-page_changed_cb (GtkWidget *widget, gpointer data)
-{
- CompEditor *editor = COMP_EDITOR (data);
- CompEditorPrivate *priv;
-
- priv = editor->priv;
-
- priv->changed = TRUE;
-}
-
static gint
delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer data)
{
diff --git a/calendar/gui/dialogs/comp-editor.h b/calendar/gui/dialogs/comp-editor.h
index 225abeac3c..cf24a2befb 100644
--- a/calendar/gui/dialogs/comp-editor.h
+++ b/calendar/gui/dialogs/comp-editor.h
@@ -23,7 +23,10 @@
#define COMP_EDITOR_H
#include <gtk/gtk.h>
+#include <bonobo/bonobo-ui-engine.h>
+#include <bonobo/bonobo-ui-component.h>
#include "cal-client.h"
+#include "../itip-utils.h"
#include "comp-editor-page.h"
BEGIN_GNOME_DECLS
@@ -47,19 +50,36 @@ typedef struct {
typedef struct {
GtkObjectClass parent_class;
+
+ /* Virtual functions */
+ void (* edit_comp) (CompEditor *page, CalComponent *comp);
} CompEditorClass;
+GtkType comp_editor_get_type (void);
+CompEditor *comp_editor_new (void);
+void comp_editor_append_page (CompEditor *editor,
+ CompEditorPage *page,
+ const char *label);
+void comp_editor_remove_page (CompEditor *editor,
+ CompEditorPage *page);
+void comp_editor_show_page (CompEditor *editor,
+ CompEditorPage *page);
+void comp_editor_set_cal_client (CompEditor *editor,
+ CalClient *client);
+CalClient *comp_editor_get_cal_client (CompEditor *editor);
+void comp_editor_edit_comp (CompEditor *ee,
+ CalComponent *comp);
+CalComponent *comp_editor_get_current_comp (CompEditor *editor);
+void comp_editor_save_comp (CompEditor *editor);
+void comp_editor_delete_comp (CompEditor *editor);
+void comp_editor_send_comp (CompEditor *editor,
+ CalComponentItipMethod method);
+void comp_editor_merge_ui (CompEditor *editor,
+ const char *filename,
+ BonoboUIVerb *verbs);
+void comp_editor_focus (CompEditor *editor);
+
+
-GtkType comp_editor_get_type (void);
-CompEditor *comp_editor_new (void);
-void comp_editor_append_page (CompEditor *editor,
- CompEditorPage *page,
- const char *label);
-void comp_editor_set_cal_client (CompEditor *editor,
- CalClient *client);
-CalClient * comp_editor_get_cal_client (CompEditor *editor);
-void comp_editor_edit_comp (CompEditor *ee,
- CalComponent *comp);
-void comp_editor_focus (CompEditor *editor);
diff --git a/calendar/gui/dialogs/event-editor.c b/calendar/gui/dialogs/event-editor.c
index b53efe12aa..36c06ff1f1 100644
--- a/calendar/gui/dialogs/event-editor.c
+++ b/calendar/gui/dialogs/event-editor.c
@@ -34,21 +34,41 @@
#include "event-page.h"
#include "alarm-page.h"
#include "recurrence-page.h"
+#include "meeting-page.h"
+#include "cancel-comp.h"
#include "event-editor.h"
struct _EventEditorPrivate {
EventPage *event_page;
AlarmPage *alarm_page;
RecurrencePage *recur_page;
+ MeetingPage *meet_page;
+
+ gboolean meeting_shown;
};
static void event_editor_class_init (EventEditorClass *class);
static void event_editor_init (EventEditor *ee);
+static void event_editor_edit_comp (CompEditor *editor, CalComponent *comp);
static void event_editor_destroy (GtkObject *object);
-static CompEditor *parent_class;
+static void schedule_meeting_cmd (GtkWidget *widget, gpointer data);
+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 BonoboUIVerb verbs [] = {
+ BONOBO_UI_UNSAFE_VERB ("ActionScheduleMeeting", schedule_meeting_cmd),
+ BONOBO_UI_UNSAFE_VERB ("ActionRefreshMeeting", refresh_meeting_cmd),
+ BONOBO_UI_UNSAFE_VERB ("ActionCancelMeeting", cancel_meeting_cmd),
+ BONOBO_UI_UNSAFE_VERB ("ActionForward", forward_cmd),
+
+ BONOBO_UI_VERB_END
+};
+
+static CompEditorClass *parent_class;
@@ -86,14 +106,18 @@ event_editor_get_type (void)
/* Class initialization function for the event editor */
static void
-event_editor_class_init (EventEditorClass *class)
+event_editor_class_init (EventEditorClass *klass)
{
GtkObjectClass *object_class;
-
- object_class = (GtkObjectClass *) class;
+ CompEditorClass *editor_class;
+
+ object_class = (GtkObjectClass *) klass;
+ editor_class = (CompEditorClass *) klass;
parent_class = gtk_type_class (TYPE_COMP_EDITOR);
+ editor_class->edit_comp = event_editor_edit_comp;
+
object_class->destroy = event_editor_destroy;
}
@@ -120,7 +144,37 @@ event_editor_init (EventEditor *ee)
comp_editor_append_page (COMP_EDITOR (ee),
COMP_EDITOR_PAGE (priv->recur_page),
_("Recurrence"));
+
+ priv->meet_page = meeting_page_new ();
+ comp_editor_append_page (COMP_EDITOR (ee),
+ COMP_EDITOR_PAGE (priv->meet_page),
+ _("Meeting"));
+
+ priv->meeting_shown = TRUE;
+
+ comp_editor_merge_ui (COMP_EDITOR (ee), EVOLUTION_DATADIR
+ "/gnome/ui/evolution-event-editor.xml",
+ verbs);
+}
+
+static void
+event_editor_edit_comp (CompEditor *editor, CalComponent *comp)
+{
+ EventEditor *ee;
+ EventEditorPrivate *priv;
+ GSList *attendees = NULL;
+ ee = EVENT_EDITOR (editor);
+ priv = ee->priv;
+
+ cal_component_get_attendee_list (comp, &attendees);
+ if (attendees == NULL) {
+ comp_editor_remove_page (editor, COMP_EDITOR_PAGE (priv->meet_page));
+ priv->meeting_shown = FALSE;
+ }
+
+ if (parent_class->edit_comp)
+ parent_class->edit_comp (editor, comp);
}
/* Destroy handler for the event editor */
@@ -153,3 +207,52 @@ event_editor_new (void)
{
return EVENT_EDITOR (gtk_type_new (TYPE_EVENT_EDITOR));
}
+
+static void
+schedule_meeting_cmd (GtkWidget *widget, gpointer data)
+{
+ EventEditor *ee = EVENT_EDITOR (data);
+ EventEditorPrivate *priv;
+
+ priv = ee->priv;
+
+ if (!priv->meeting_shown) {
+ comp_editor_append_page (COMP_EDITOR (ee),
+ COMP_EDITOR_PAGE (priv->meet_page),
+ _("Meeting"));
+ priv->meeting_shown = FALSE;
+ }
+
+ comp_editor_show_page (COMP_EDITOR (ee),
+ COMP_EDITOR_PAGE (priv->meet_page));
+}
+
+static void
+refresh_meeting_cmd (GtkWidget *widget, gpointer data)
+{
+ EventEditor *ee = EVENT_EDITOR (data);
+
+ comp_editor_send_comp (COMP_EDITOR (ee), CAL_COMPONENT_METHOD_REFRESH);
+}
+
+static void
+cancel_meeting_cmd (GtkWidget *widget, gpointer data)
+{
+ EventEditor *ee = EVENT_EDITOR (data);
+ CalComponent *comp;
+
+ comp = comp_editor_get_current_comp (COMP_EDITOR (ee));
+ if (cancel_component_dialog (comp)) {
+ comp_editor_send_comp (COMP_EDITOR (ee), CAL_COMPONENT_METHOD_CANCEL);
+ comp_editor_delete_comp (COMP_EDITOR (ee));
+ }
+}
+
+static void
+forward_cmd (GtkWidget *widget, gpointer data)
+{
+ EventEditor *ee = EVENT_EDITOR (data);
+
+ comp_editor_send_comp (COMP_EDITOR (ee), CAL_COMPONENT_METHOD_PUBLISH);
+}
+
diff --git a/calendar/gui/dialogs/meeting-page.c b/calendar/gui/dialogs/meeting-page.c
index a369646ab4..7932fbd177 100644
--- a/calendar/gui/dialogs/meeting-page.c
+++ b/calendar/gui/dialogs/meeting-page.c
@@ -27,13 +27,16 @@
#endif
#include <liboaf/liboaf.h>
-#include <gtk/gtknotebook.h>
-#include <gtk/gtkradiobutton.h>
+#include <bonobo/bonobo-control.h>
+#include <bonobo/bonobo-widget.h>
#include <gtk/gtksignal.h>
-#include <gtk/gtktable.h>
#include <gtk/gtktogglebutton.h>
#include <gtk/gtkvbox.h>
#include <glade/glade.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/widgets/e-unicode.h>
#include <widgets/misc/e-dateedit.h>
#include <widgets/meeting-time-sel/e-meeting-time-sel.h>
@@ -45,21 +48,72 @@
#define SELECT_NAMES_OAFID "OAFIID:GNOME_Evolution_Addressbook_SelectNames"
+#define MEETING_PAGE_TABLE_SPEC \
+ "<ETableSpecification click-to-add=\"true\" " \
+ " _click-to-add-message=\"Click here to add an attendee\" " \
+ " draw-grid=\"true\">" \
+ " <ETableColumn model_col= \"0\" _title=\"Attendee\" " \
+ " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \
+ " cell=\"string\" compare=\"string\"/>" \
+ " <ETableColumn model_col= \"1\" _title=\"Role\" " \
+ " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \
+ " cell=\"roleedit\" compare=\"string\"/>" \
+ " <ETableColumn model_col= \"2\" _title=\"RSVP\" " \
+ " expansion=\"2.0\" minimum_width=\"10\" resizable=\"true\" " \
+ " cell=\"rsvpedit\" compare=\"string\"/>" \
+ " <ETableColumn model_col= \"3\" _title=\"Status\" " \
+ " expansion=\"2.0\" minimum_width=\"10\" resizable=\"true\" " \
+ " cell=\"statusedit\" compare=\"string\"/>" \
+ " <ETableState>" \
+ " <column source=\"0\"/>" \
+ " <column source=\"1\"/>" \
+ " <column source=\"2\"/>" \
+ " <column source=\"3\"/>" \
+ " <grouping></grouping>" \
+ " </ETableState>" \
+ "</ETableSpecification>"
+
+enum columns {
+ MEETING_ATTENDEE_COL,
+ MEETING_ROLE_COL,
+ MEETING_RSVP_COL,
+ MEETING_STATUS_COL,
+ MEETING_COLUMN_COUNT
+};
+
+struct attendee {
+ char *address;
+ char *member;
+
+ CalComponentCUType cutype;
+ CalComponentRole role;
+ CalComponentPartStat status;
+ gboolean rsvp;
+
+ char *delto;
+ char *delfrom;
+ char *sentby;
+ char *cn;
+ char *language;
+};
+
/* Private part of the MeetingPage structure */
struct _MeetingPagePrivate {
+ /* List of attendees */
+ GSList *attendees;
+
/* Glade XML data */
GladeXML *xml;
/* Widgets from the Glade file */
GtkWidget *main;
-
- EMeetingTimeSelector *selector;
- GtkWidget *table;
-
- /* Other widgets */
- GtkWidget *rb1[2];
- GtkWidget *rb2[2];
+ GtkWidget *organizer;
+ GtkWidget *invite;
+ /* E Table stuff */
+ ETableModel *model;
+ GtkWidget *etable;
+
/* For handling the invite button */
GNOME_Evolution_Addressbook_SelectNames corba_select_names;
@@ -75,8 +129,8 @@ static void meeting_page_destroy (GtkObject *object);
static GtkWidget *meeting_page_get_widget (CompEditorPage *page);
static void meeting_page_fill_widgets (CompEditorPage *page, CalComponent *comp);
static void meeting_page_fill_component (CompEditorPage *page, CalComponent *comp);
-static void meeting_page_set_summary (CompEditorPage *page, const char *summary);
-static void meeting_page_set_dates (CompEditorPage *page, CompEditorPageDates *dates);
+
+static int row_count (ETableModel *etm, void *data);
static CompEditorPageClass *parent_class = NULL;
@@ -130,8 +184,8 @@ meeting_page_class_init (MeetingPageClass *class)
editor_page_class->get_widget = meeting_page_get_widget;
editor_page_class->fill_widgets = meeting_page_fill_widgets;
editor_page_class->fill_component = meeting_page_fill_component;
- editor_page_class->set_summary = meeting_page_set_summary;
- editor_page_class->set_dates = meeting_page_set_dates;
+ editor_page_class->set_summary = NULL;
+ editor_page_class->set_dates = NULL;
object_class->destroy = meeting_page_destroy;
}
@@ -148,8 +202,11 @@ meeting_page_init (MeetingPage *mpage)
priv->xml = NULL;
priv->main = NULL;
- priv->selector = NULL;
-
+ priv->invite = NULL;
+
+ priv->model = NULL;
+ priv->etable = NULL;
+
priv->updating = FALSE;
}
@@ -208,8 +265,9 @@ meeting_page_fill_widgets (CompEditorPage *page, CalComponent *comp)
{
MeetingPage *mpage;
MeetingPagePrivate *priv;
- CalComponentDateTime dtstart, dtend;
- struct icaltimetype start, end;
+ CalComponentOrganizer organizer;
+ GSList *attendees, *l;
+
mpage = MEETING_PAGE (page);
priv = mpage->priv;
@@ -217,25 +275,39 @@ meeting_page_fill_widgets (CompEditorPage *page, CalComponent *comp)
/* Clean the screen */
clear_widgets (mpage);
+
+ cal_component_get_organizer (comp, &organizer);
+ e_dialog_editable_set (priv->organizer, organizer.value);
+
+ cal_component_get_attendee_list (comp, &attendees);
+ for (l = attendees; l != NULL; l = l->next) {
+ CalComponentAttendee *att = l->data;
+ struct attendee *attendee = g_new0 (struct attendee, 1);
+
+ attendee->address = g_strdup (att->value);
+ attendee->member = g_strdup (att->member);
+ attendee->cutype= att->cutype;
+ attendee->role = att->role;
+ attendee->status = att->status;
+ attendee->rsvp = att->rsvp;
+ attendee->delto = g_strdup (att->delto);
+ attendee->delfrom = g_strdup (att->delfrom);
+ attendee->sentby = g_strdup (att->sentby);
+ attendee->cn = g_strdup (att->cn);
+ attendee->language = g_strdup (att->language);
+
+ priv->attendees = g_slist_prepend (priv->attendees, attendee);
+
+ }
+ priv->attendees = g_slist_reverse (priv->attendees);
+ cal_component_free_attendee_list (attendees);
- /* Selector */
- cal_component_get_dtstart (comp, &dtstart);
- cal_component_get_dtend (comp, &dtend);
- start = icaltime_as_zone (*dtstart.value, dtstart.tzid);
- end = icaltime_as_zone (*dtend.value, dtend.tzid);
- e_meeting_time_selector_set_meeting_time (priv->selector,
- start.year,
- start.month,
- start.day,
- start.hour,
- start.minute,
- end.year,
- end.month,
- end.day,
- end.hour,
- end.minute);
- cal_component_free_datetime (&dtstart);
- cal_component_free_datetime (&dtend);
+ /* Table */
+ e_table_model_rows_inserted (priv->model, 0, row_count (priv->model, mpage));
+
+ /* So the comp editor knows we need to send if anything changes */
+ if (priv->attendees != NULL)
+ comp_editor_page_notify_needs_send (COMP_EDITOR_PAGE (mpage));
priv->updating = FALSE;
}
@@ -244,66 +316,48 @@ meeting_page_fill_widgets (CompEditorPage *page, CalComponent *comp)
static void
meeting_page_fill_component (CompEditorPage *page, CalComponent *comp)
{
-#if 0
MeetingPage *mpage;
MeetingPagePrivate *priv;
- CalComponentDateTime date;
- time_t t;
- char *url;
+ CalComponentOrganizer organizer = {NULL, NULL, NULL, NULL};
+ GSList *attendees = NULL, *l;
+ gchar *str;
mpage = MEETING_PAGE (page);
priv = mpage->priv;
- /* Completed Date. */
- date.value = g_new (struct icaltimetype, 1);
- date.tzid = NULL;
-
- t = e_date_edit_get_time (E_DATE_EDIT (priv->completed_date));
- if (t != -1) {
- *date.value = icaltime_from_timet (t, FALSE);
- cal_component_set_completed (comp, date.value);
- } else {
- cal_component_set_completed (comp, NULL);
+ str = e_dialog_editable_get (priv->organizer);
+ if (str == NULL || strlen (str) == 0) {
+ if (str != NULL)
+ g_free (str);
+ return;
}
-
- g_free (date.value);
-
- /* URL. */
- url = e_dialog_editable_get (priv->url);
- cal_component_set_url (comp, url);
- if (url)
- g_free (url);
-#endif
-}
-
-/* set_summary handler for the task page */
-static void
-meeting_page_set_summary (CompEditorPage *page, const char *summary)
-{
-#if 0
- MeetingPage *mpage;
- MeetingPagePrivate *priv;
- gchar *s;
- mpage = MEETING_PAGE (page);
- priv = mpage->priv;
-
- s = e_utf8_to_gtk_string (priv->summary, summary);
- gtk_label_set_text (GTK_LABEL (priv->summary), s);
- g_free (s);
-#endif
-}
-
-static void
-meeting_page_set_dates (CompEditorPage *page, CompEditorPageDates *dates)
-{
- MeetingPage *mpage;
- MeetingPagePrivate *priv;
-
- mpage = MEETING_PAGE (page);
- priv = mpage->priv;
-
-// comp_editor_date_label (dates, priv->date_time);
+ organizer.value = str;
+ cal_component_set_organizer (comp, &organizer);
+ g_free (str);
+
+ for (l = priv->attendees; l != NULL; l = l->next) {
+ struct attendee *attendee = l->data;
+ CalComponentAttendee *att = g_new0 (CalComponentAttendee, 1);
+
+ att->value = attendee->address;
+ att->member = attendee->member;
+ att->cutype= attendee->cutype;
+ att->role = attendee->role;
+ att->status = attendee->status;
+ att->rsvp = attendee->rsvp;
+ att->delto = attendee->delto;
+ att->delfrom = attendee->delfrom;
+ att->sentby = attendee->sentby;
+ att->cn = attendee->cn;
+ att->language = attendee->language;
+
+ attendees = g_slist_prepend (attendees, att);
+
+ }
+ attendees = g_slist_reverse (attendees);
+ cal_component_set_attendee_list (comp, attendees);
+ g_slist_free (attendees);
}
@@ -323,77 +377,58 @@ get_widgets (MeetingPage *mpage)
gtk_widget_ref (priv->main);
gtk_widget_unparent (priv->main);
- priv->selector = E_MEETING_TIME_SELECTOR (GW ("selector"));
- priv->table = GW ("status-table");
+ priv->organizer = GW ("organizer");
+ priv->invite = GW ("invite");
#undef GW
- return (priv->selector
- && priv->table);
+ return (priv->invite
+ && priv->organizer);
}
-/* Creates the radio buttons in the given container */
static void
-create_radio_buttons (GtkWidget *box, GtkWidget **button1, GtkWidget **button2)
+invite_entry_changed (BonoboListener *listener,
+ char *event_name,
+ CORBA_any *arg,
+ CORBA_Environment *ev,
+ gpointer user_data)
{
- GtkWidget *rb1, *rb2;
- GSList *grp;
-
- /* The radio buttions to change views */
- rb1 = gtk_radio_button_new_with_label (NULL,
- "Show attendee scheduling");
- gtk_widget_show (rb1);
-
- grp = gtk_radio_button_group (GTK_RADIO_BUTTON (rb1));
- rb2 = gtk_radio_button_new_with_label (grp, "Show attendee status");
- gtk_widget_show (rb2);
-
- gtk_box_pack_start (GTK_BOX (box), rb1, FALSE, FALSE, 0);
- gtk_box_pack_start (GTK_BOX (box), rb2, FALSE, FALSE, 0);
-
- *button1 = rb1;
- *button2 = rb2;
}
-/* Callback used when the start or end date widgets change. We check that the
- * start date < end date and we set the "all day task" button as appropriate.
- */
static void
-date_changed_cb (EDateEdit *dedit, gpointer data)
+add_section (GNOME_Evolution_Addressbook_SelectNames corba_select_names, const char *name)
{
-#if 0
- MeetingPage *mpage;
- MeetingPagePrivate *priv;
- CompEditorPageDates dates;
+ Bonobo_Control corba_control;
+ CORBA_Environment ev;
+ GtkWidget *control_widget;
+ BonoboControlFrame *cf;
+ Bonobo_PropertyBag pb = CORBA_OBJECT_NIL;
+ CORBA_exception_init (&ev);
- mpage = MEETING_PAGE (data);
- priv = mpage->priv;
+ GNOME_Evolution_Addressbook_SelectNames_addSection (corba_select_names,
+ name, name, &ev);
- if (priv->updating)
+ corba_control =
+ GNOME_Evolution_Addressbook_SelectNames_getEntryBySection (
+ corba_select_names, name, &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ CORBA_exception_free (&ev);
return;
+ }
- dates.start = 0;
- dates.end = 0;
- dates.due = 0;
- dates.complete = e_date_edit_get_time (E_DATE_EDIT (priv->completed_date));
-
- /* Notify upstream */
- comp_editor_page_notify_dates_changed (COMP_EDITOR_PAGE (mpage), &dates);
-#endif
-}
+ CORBA_exception_free (&ev);
-/* This is called when any field is changed; it notifies upstream. */
-static void
-field_changed_cb (GtkWidget *widget, gpointer data)
-{
- MeetingPage *mpage;
- MeetingPagePrivate *priv;
-
- mpage = MEETING_PAGE (data);
- priv = mpage->priv;
-
- if (!priv->updating)
- comp_editor_page_notify_changed (COMP_EDITOR_PAGE (mpage));
+ control_widget = bonobo_widget_new_control_from_objref (
+ corba_control, CORBA_OBJECT_NIL);
+
+ cf = bonobo_widget_get_control_frame (BONOBO_WIDGET (control_widget));
+ pb = bonobo_control_frame_get_control_property_bag (cf, NULL);
+
+ bonobo_event_source_client_add_listener (
+ pb, invite_entry_changed,
+ "Bonobo/Property:change:entry_changed",
+ NULL, NULL);
}
static gboolean
@@ -411,6 +446,10 @@ get_select_name_dialog (MeetingPage *mpage)
priv->corba_select_names = oaf_activate_from_id (SELECT_NAMES_OAFID, 0, NULL, &ev);
+ add_section (priv->corba_select_names, "Required Participants");
+ add_section (priv->corba_select_names, "Optional Participants");
+ add_section (priv->corba_select_names, "Non-Participants");
+
/* OAF seems to be broken -- it can return a CORBA_OBJECT_NIL without
raising an exception in `ev'. */
if (ev._major != CORBA_NO_EXCEPTION || priv->corba_select_names == CORBA_OBJECT_NIL) {
@@ -424,6 +463,20 @@ get_select_name_dialog (MeetingPage *mpage)
return TRUE;
}
+/* This is called when any field is changed; it notifies upstream. */
+static void
+field_changed_cb (GtkWidget *widget, gpointer data)
+{
+ MeetingPage *mpage;
+ MeetingPagePrivate *priv;
+
+ mpage = MEETING_PAGE (data);
+ priv = mpage->priv;
+
+ if (!priv->updating)
+ comp_editor_page_notify_changed (COMP_EDITOR_PAGE (mpage));
+}
+
/* Function called to invite more people */
static void
invite_cb (GtkWidget *widget, gpointer data)
@@ -440,64 +493,363 @@ invite_cb (GtkWidget *widget, gpointer data)
CORBA_exception_init (&ev);
- GNOME_Evolution_Addressbook_SelectNames_addSection (
- priv->corba_select_names, "Required", "Required", &ev);
-
GNOME_Evolution_Addressbook_SelectNames_activateDialog (
- priv->corba_select_names, "Test", &ev);
+ priv->corba_select_names, "Required Participants", &ev);
CORBA_exception_free (&ev);
-
- if (!priv->updating)
- comp_editor_page_notify_changed (COMP_EDITOR_PAGE (mpage));
}
+/* Hooks the widget signals */
static void
-page_toggle_cb (GtkWidget *widget, gpointer data)
+init_widgets (MeetingPage *mpage)
{
+ MeetingPagePrivate *priv;
+
+ priv = mpage->priv;
+
+ /* Organizer */
+ gtk_signal_connect (GTK_OBJECT (priv->organizer), "changed",
+ GTK_SIGNAL_FUNC (field_changed_cb), mpage);
+
+ /* Invite button */
+ gtk_signal_connect (GTK_OBJECT (priv->invite), "clicked",
+ GTK_SIGNAL_FUNC (invite_cb), mpage);
+}
+
+static CalComponentRole
+text_to_role (const char *role)
+{
+ if (!g_strcasecmp (role, "Chair"))
+ return CAL_COMPONENT_ROLE_CHAIR;
+ else if (!g_strcasecmp (role, "Required Participant"))
+ return CAL_COMPONENT_ROLE_REQUIRED;
+ else if (!g_strcasecmp (role, "Optional Participant"))
+ return CAL_COMPONENT_ROLE_OPTIONAL;
+ else if (!g_strcasecmp (role, "Non-Participant"))
+ return CAL_COMPONENT_ROLE_NON;
+ else
+ return CAL_COMPONENT_ROLE_UNKNOWN;
+}
+
+static char *
+role_to_text (CalComponentRole role)
+{
+ switch (role) {
+ case CAL_COMPONENT_ROLE_CHAIR:
+ return "Chair";
+ case CAL_COMPONENT_ROLE_REQUIRED:
+ return "Required Participant";
+ case CAL_COMPONENT_ROLE_OPTIONAL:
+ return "Optional Participant";
+ case CAL_COMPONENT_ROLE_NON:
+ 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 CalComponentPartStat
+text_to_partstat (const char *partstat)
+{
+ if (!g_strcasecmp (partstat, "Needs Action"))
+ return CAL_COMPONENT_PARTSTAT_NEEDSACTION;
+ else if (!g_strcasecmp (partstat, "Accepted"))
+ return CAL_COMPONENT_PARTSTAT_ACCEPTED;
+ else if (!g_strcasecmp (partstat, "Declined"))
+ return CAL_COMPONENT_PARTSTAT_DECLINED;
+ else if (!g_strcasecmp (partstat, "Tentative"))
+ return CAL_COMPONENT_PARTSTAT_TENTATIVE;
+ else if (!g_strcasecmp (partstat, "Delegated"))
+ return CAL_COMPONENT_PARTSTAT_DELEGATED;
+ else if (!g_strcasecmp (partstat, "Completed"))
+ return CAL_COMPONENT_PARTSTAT_COMPLETED;
+ else if (!g_strcasecmp (partstat, "In Process"))
+ return CAL_COMPONENT_PARTSTAT_INPROCESS;
+ else
+ return CAL_COMPONENT_PARTSTAT_UNKNOWN;
+}
+
+static char *
+partstat_to_text (CalComponentPartStat partstat)
+{
+ switch (partstat) {
+ case CAL_COMPONENT_PARTSTAT_NEEDSACTION:
+ return "Needs Action";
+ case CAL_COMPONENT_PARTSTAT_ACCEPTED:
+ return "Accepted";
+ case CAL_COMPONENT_PARTSTAT_DECLINED:
+ return "Declined";
+ case CAL_COMPONENT_PARTSTAT_TENTATIVE:
+ return "Tentative";
+ case CAL_COMPONENT_PARTSTAT_DELEGATED:
+ return "Delegated";
+ case CAL_COMPONENT_PARTSTAT_COMPLETED:
+ return "Completed";
+ case CAL_COMPONENT_PARTSTAT_INPROCESS:
+ return "In Process";
+ case CAL_COMPONENT_PARTSTAT_UNKNOWN:
+ default:
+ return "Unknown";
+ }
+
+ return NULL;
+}
+
+static int
+column_count (ETableModel *etm, void *data)
+{
+ return MEETING_COLUMN_COUNT;
+}
+
+static int
+row_count (ETableModel *etm, void *data)
+{
+ MeetingPage *mpage;
+ MeetingPagePrivate *priv;
+
+ mpage = MEETING_PAGE (data);
+ priv = mpage->priv;
+
+ return g_slist_length (priv->attendees);
+}
+
+static void
+append_row (ETableModel *etm, ETableModel *model, int row, void *data)
+{
MeetingPage *mpage;
MeetingPagePrivate *priv;
- gboolean active;
+ struct attendee *attendee;
+ gint row_cnt;
- mpage = MEETING_PAGE (data);
+ mpage = MEETING_PAGE (data);
priv = mpage->priv;
- active = GTK_TOGGLE_BUTTON (widget)->active;
- if (active)
- gtk_notebook_set_page (GTK_NOTEBOOK (priv->main), 0);
- else
- gtk_notebook_set_page (GTK_NOTEBOOK (priv->main), 1);
+ attendee = g_new0 (struct attendee, 1);
+
+ attendee->address = g_strdup (e_table_model_value_at (model, MEETING_ATTENDEE_COL, row));
+ attendee->role = text_to_role (e_table_model_value_at (model, MEETING_ROLE_COL, row));
+ attendee->rsvp = text_to_boolean (e_table_model_value_at (model, MEETING_RSVP_COL, row));
+ attendee->status = text_to_partstat (e_table_model_value_at (model, MEETING_STATUS_COL, row));
+
+ priv->attendees = g_slist_append (priv->attendees, attendee);
+
+ row_cnt = row_count (etm, data) - 1;
+ e_table_model_row_inserted (E_TABLE_MODEL (etm), row_cnt);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->rb1[0]), active);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->rb1[1]), !active);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->rb2[0]), active);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->rb2[1]), !active);
+ comp_editor_page_notify_needs_send (COMP_EDITOR_PAGE (mpage));
+ comp_editor_page_notify_changed (COMP_EDITOR_PAGE (mpage));
}
+
+static void *
+value_at (ETableModel *etm, int col, int row, void *data)
+{
+ MeetingPage *mpage;
+ MeetingPagePrivate *priv;
+ struct attendee *attendee;
+
+ mpage = MEETING_PAGE (data);
+ priv = mpage->priv;
+
+ attendee = g_slist_nth_data (priv->attendees, row);
-/* Hooks the widget signals */
+ switch (col) {
+ case MEETING_ATTENDEE_COL:
+ return attendee->address;
+ case MEETING_ROLE_COL:
+ return role_to_text (attendee->role);
+ case MEETING_RSVP_COL:
+ return boolean_to_text (attendee->rsvp);
+ case MEETING_STATUS_COL:
+ return partstat_to_text (attendee->status);
+ }
+
+ return NULL;
+}
+
static void
-init_widgets (MeetingPage *mpage)
+set_value_at (ETableModel *etm, int col, int row, const void *val, void *data)
{
+ MeetingPage *mpage;
MeetingPagePrivate *priv;
+ struct attendee *attendee;
+ mpage = MEETING_PAGE (data);
priv = mpage->priv;
+
+ attendee = g_slist_nth_data (priv->attendees, row);
+
+ switch (col) {
+ case MEETING_ATTENDEE_COL:
+ attendee->address = g_strdup (val);
+ break;
+ case MEETING_ROLE_COL:
+ attendee->role = text_to_role (val);
+ break;
+ case MEETING_RSVP_COL:
+ attendee->rsvp = text_to_boolean (val);
+ break;
+ case MEETING_STATUS_COL:
+ attendee->status = text_to_partstat (val);
+ break;
+ }
+
+ if (!priv->updating) {
+ comp_editor_page_notify_needs_send (COMP_EDITOR_PAGE (mpage));
+ comp_editor_page_notify_changed (COMP_EDITOR_PAGE (mpage));
+ }
+}
- /* Selector */
- gtk_signal_connect (GTK_OBJECT (priv->selector->invite_button),
- "clicked", GTK_SIGNAL_FUNC (invite_cb), mpage);
+static gboolean
+is_cell_editable (ETableModel *etm, int col, int row, void *data)
+{
+ return TRUE;
+}
- /* Radio buttons */
- gtk_signal_connect (GTK_OBJECT (priv->rb1[0]), "toggled",
- GTK_SIGNAL_FUNC (page_toggle_cb), mpage);
- gtk_signal_connect (GTK_OBJECT (priv->rb2[0]), "toggled",
- GTK_SIGNAL_FUNC (page_toggle_cb), mpage);
+static void *
+duplicate_value (ETableModel *etm, int col, const void *val, void *data)
+{
+ return g_strdup (val);
+}
+
+static void
+free_value (ETableModel *etm, int col, void *val, void *data)
+{
+ g_free (val);
+}
+
+static void *
+init_value (ETableModel *etm, int col, void *data)
+{
+ switch (col) {
+ case MEETING_ATTENDEE_COL:
+ return g_strdup ("");
+ case MEETING_ROLE_COL:
+ return g_strdup ("Required Participant");
+ case MEETING_RSVP_COL:
+ return g_strdup ("Yes");
+ case MEETING_STATUS_COL:
+ return g_strdup ("Needs Action");
+ }
-#if 0
- /* Completed Date */
- gtk_signal_connect (GTK_OBJECT (priv->completed_date), "changed",
- GTK_SIGNAL_FUNC (date_changed_cb), mpage);
+ return g_strdup ("");
+}
-#endif
+static gboolean
+value_is_empty (ETableModel *etm, int col, const void *val, void *data)
+{
+ if (col == 0) {
+ if (val && !g_strcasecmp (val, ""))
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static char *
+value_to_string (ETableModel *etm, int col, const void *val, void *data)
+{
+ return g_strdup (val);
+}
+
+static void
+build_etable (MeetingPage *mpage)
+{
+ MeetingPagePrivate *priv;
+ ETableExtras *extras;
+ GList *strings;
+ ECell *popup_cell, *cell;
+
+ priv = mpage->priv;
+
+ extras = e_table_extras_new ();
+
+ /* 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);
+ gtk_object_unref (GTK_OBJECT (cell));
+
+ strings = NULL;
+ strings = g_list_append (strings, "Chair");
+ strings = g_list_append (strings, "Required Participant");
+ strings = g_list_append (strings, "Optional Participant");
+ strings = g_list_append (strings, "Non-Participant");
+ strings = g_list_append (strings, "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);
+ gtk_object_unref (GTK_OBJECT (cell));
+
+ strings = NULL;
+ strings = g_list_append (strings, "Yes");
+ strings = g_list_append (strings, "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);
+ gtk_object_unref (GTK_OBJECT (cell));
+
+ strings = NULL;
+ strings = g_list_append (strings, "Needs Action");
+ strings = g_list_append (strings, "Accepted");
+ strings = g_list_append (strings, "Declined");
+ strings = g_list_append (strings, "Tentative");
+ strings = g_list_append (strings, "Delegated");
+
+ e_cell_combo_set_popdown_strings (E_CELL_COMBO (popup_cell), strings);
+ e_table_extras_add_cell (extras, "statusedit", popup_cell);
+
+
+ /* The table itself */
+ priv->model = e_table_simple_new (column_count,
+ row_count,
+ value_at,
+ set_value_at,
+ is_cell_editable,
+ duplicate_value,
+ free_value,
+ init_value,
+ value_is_empty,
+ value_to_string,
+ mpage);
+ gtk_object_set (GTK_OBJECT (priv->model),
+ "append_row", append_row,
+ NULL);
+
+ priv->etable = e_table_scrolled_new (priv->model, extras,
+ MEETING_PAGE_TABLE_SPEC, NULL);
+ gtk_object_unref (GTK_OBJECT (extras));
}
@@ -515,7 +867,6 @@ MeetingPage *
meeting_page_construct (MeetingPage *mpage)
{
MeetingPagePrivate *priv;
- GtkWidget *vbox;
priv = mpage->priv;
@@ -532,20 +883,12 @@ meeting_page_construct (MeetingPage *mpage)
"Could not find all widgets in the XML file!");
return NULL;
}
-
- /* Stuff for the second page */
- vbox = gtk_vbox_new (FALSE, 2);
- gtk_widget_show (vbox);
- gtk_table_attach (GTK_TABLE (priv->table), vbox, 0, 1, 0, 1,
- GTK_EXPAND | GTK_FILL, GTK_FILL, 2, 0);
-
- /* The radio buttions to change views on first page */
- create_radio_buttons (priv->selector->attendees_title_bar_vbox,
- &priv->rb1[0], &priv->rb1[1]);
-
- /* The radio buttions to change views on second page */
- create_radio_buttons (vbox, &priv->rb2[0], &priv->rb2[1]);
-
+
+ /* The etable displaying attendees and their status */
+ build_etable (mpage);
+ gtk_widget_show (priv->etable);
+ gtk_box_pack_start (GTK_BOX (priv->main), priv->etable, TRUE, TRUE, 2);
+
/* Init the widget signals */
init_widgets (mpage);
@@ -573,15 +916,3 @@ meeting_page_new (void)
return mpage;
}
-
-GtkWidget *meeting_page_create_selector (void);
-
-GtkWidget *
-meeting_page_create_selector (void)
-{
- GtkWidget *sel;
-
- sel = e_meeting_time_selector_new ();
-
- return sel;
-}
diff --git a/calendar/gui/dialogs/meeting-page.glade b/calendar/gui/dialogs/meeting-page.glade
index 86e6647b93..4e23c16f67 100644
--- a/calendar/gui/dialogs/meeting-page.glade
+++ b/calendar/gui/dialogs/meeting-page.glade
@@ -25,60 +25,75 @@
<auto_shrink>False</auto_shrink>
<widget>
- <class>GtkNotebook</class>
+ <class>GtkVBox</class>
<name>meeting-page</name>
- <show_tabs>False</show_tabs>
- <show_border>False</show_border>
- <tab_pos>GTK_POS_TOP</tab_pos>
- <scrollable>False</scrollable>
- <tab_hborder>2</tab_hborder>
- <tab_vborder>2</tab_vborder>
- <popup_enable>False</popup_enable>
+ <border_width>5</border_width>
+ <homogeneous>False</homogeneous>
+ <spacing>4</spacing>
<widget>
- <class>Custom</class>
- <name>selector</name>
- <creation_function>meeting_page_create_selector</creation_function>
- <int1>0</int1>
- <int2>0</int2>
- <last_modification_time>Mon, 04 Jun 2001 17:53:38 GMT</last_modification_time>
- </widget>
+ <class>GtkHBox</class>
+ <name>hbox1</name>
+ <homogeneous>False</homogeneous>
+ <spacing>4</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
- <widget>
- <class>GtkLabel</class>
- <child_name>Notebook:tab</child_name>
- <name>label1</name>
- <label>label1</label>
- <justify>GTK_JUSTIFY_CENTER</justify>
- <wrap>False</wrap>
- <xalign>0.5</xalign>
- <yalign>0.5</yalign>
- <xpad>0</xpad>
- <ypad>0</ypad>
+ <widget>
+ <class>GtkLabel</class>
+ <name>label1</name>
+ <label>Organizer</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>organizer</name>
+ <can_focus>True</can_focus>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>Placeholder</class>
+ </widget>
</widget>
<widget>
- <class>GtkTable</class>
- <name>status-table</name>
- <border_width>2</border_width>
- <rows>2</rows>
- <columns>2</columns>
- <homogeneous>False</homogeneous>
- <row_spacing>0</row_spacing>
- <column_spacing>0</column_spacing>
+ <class>Placeholder</class>
</widget>
<widget>
- <class>GtkLabel</class>
- <child_name>Notebook:tab</child_name>
- <name>label2</name>
- <label>label2</label>
- <justify>GTK_JUSTIFY_CENTER</justify>
- <wrap>False</wrap>
- <xalign>0.5</xalign>
- <yalign>0.5</yalign>
- <xpad>0</xpad>
- <ypad>0</ypad>
+ <class>GtkButton</class>
+ <name>invite</name>
+ <can_focus>True</can_focus>
+ <label>Invite Others</label>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
</widget>
</widget>
</widget>
diff --git a/calendar/gui/dialogs/recurrence-page.c b/calendar/gui/dialogs/recurrence-page.c
index 77b22a97ac..c5c45def15 100644
--- a/calendar/gui/dialogs/recurrence-page.c
+++ b/calendar/gui/dialogs/recurrence-page.c
@@ -1726,10 +1726,12 @@ recurrence_page_set_dates (CompEditorPage *page, CompEditorPageDates *dates)
priv->weekday_day_mask = priv->weekday_day_mask | mask;
priv->weekday_blocked_day_mask = mask;
- weekday_picker_set_days (priv->weekday_picker,
- priv->weekday_day_mask);
- weekday_picker_set_blocked_days (priv->weekday_picker,
- priv->weekday_blocked_day_mask);
+ if (priv->weekday_picker != NULL) {
+ weekday_picker_set_days (WEEKDAY_PICKER (priv->weekday_picker),
+ priv->weekday_day_mask);
+ weekday_picker_set_blocked_days (WEEKDAY_PICKER (priv->weekday_picker),
+ priv->weekday_blocked_day_mask);
+ }
}
diff --git a/calendar/gui/dialogs/send-comp.c b/calendar/gui/dialogs/send-comp.c
new file mode 100644
index 0000000000..8b1824866c
--- /dev/null
+++ b/calendar/gui/dialogs/send-comp.c
@@ -0,0 +1,84 @@
+/* Evolution calendar - Send calendar component dialog
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Author: JP Rosevear <jpr@ximian.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <libgnome/gnome-defs.h>
+#include <libgnome/gnome-i18n.h>
+#include <libgnomeui/gnome-dialog.h>
+#include <libgnomeui/gnome-dialog-util.h>
+#include <libgnomeui/gnome-uidefs.h>
+#include <gal/widgets/e-unicode.h>
+#include "send-comp.h"
+
+
+
+/**
+ * send_component_dialog:
+ *
+ * Pops up a dialog box asking the user whether he wants to send a
+ * iTip/iMip message
+ *
+ * Return value: TRUE if the user clicked Yes, FALSE otherwise.
+ **/
+gboolean
+send_component_dialog (CalComponent *comp)
+{
+ GtkWidget *dialog;
+ CalComponentVType vtype;
+ char *str;
+
+ str = _("The meeting status has changed. Send an updated version?");
+
+ vtype = cal_component_get_vtype (comp);
+
+ switch (vtype) {
+ case CAL_COMPONENT_EVENT:
+ str = g_strdup_printf (_("The meeting information has changed. "
+ "Send an updated version?"));
+ break;
+
+ case CAL_COMPONENT_TODO:
+ str = g_strdup_printf (_("The task information has changed. "
+ "Send an updated version?"));
+ break;
+
+ case CAL_COMPONENT_JOURNAL:
+ str = g_strdup_printf (_("The journal entry has changed. "
+ "Send an updated version?"));
+ break;
+
+ default:
+ g_message ("send_component_dialog(): "
+ "Cannot handle object of type %d", vtype);
+ return FALSE;
+ }
+
+ dialog = gnome_question_dialog_modal (str, NULL, NULL);
+
+ if (gnome_dialog_run (GNOME_DIALOG (dialog)) == GNOME_YES)
+ return TRUE;
+ else
+ return FALSE;
+}
diff --git a/calendar/gui/dialogs/send-comp.h b/calendar/gui/dialogs/send-comp.h
new file mode 100644
index 0000000000..f60ab947aa
--- /dev/null
+++ b/calendar/gui/dialogs/send-comp.h
@@ -0,0 +1,30 @@
+/* Evolution calendar - Send calendar component dialog
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Author: JP Rosevear <jpr@ximian.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef SEND_COMP_H
+#define SEND_COMP_H
+
+#include <glib.h>
+#include <cal-util/cal-component.h>
+
+gboolean send_component_dialog (CalComponent *comp);
+
+#endif
diff --git a/calendar/gui/e-itip-control.c b/calendar/gui/e-itip-control.c
index dee4bb64e6..cbd84c52e9 100644
--- a/calendar/gui/e-itip-control.c
+++ b/calendar/gui/e-itip-control.c
@@ -42,6 +42,8 @@
#include "e-itip-control.h"
#include <cal-util/cal-component.h>
#include <cal-client/cal-client.h>
+#include <e-util/e-time-utils.h>
+#include "calendar-config.h"
#include "itip-utils.h"
#define MAIL_COMPOSER_OAF_IID "OAFIID:GNOME_Evolution_Mail_Composer"
@@ -235,149 +237,12 @@ change_my_status (icalparameter_partstat status, EItipControlPrivate *priv)
}
static void
-send_itip_reply (EItipControlPrivate *priv)
-{
- BonoboObjectClient *bonobo_server;
- GNOME_Evolution_Composer composer_server;
- CORBA_Environment ev;
- GNOME_Evolution_Composer_RecipientList *to_list, *cc_list, *bcc_list;
- GNOME_Evolution_Composer_Recipient *recipient;
- CORBA_char *subject;
- CalComponentText caltext;
- CORBA_char *content_type, *filename, *description, *attach_data;
- CORBA_boolean show_inline;
- CORBA_char tempstr[200];
-
- CORBA_exception_init (&ev);
-
- /* First, I obtain an object reference that represents the Composer. */
- bonobo_server = bonobo_object_activate (MAIL_COMPOSER_OAF_IID, 0);
-
- g_return_if_fail (bonobo_server != NULL);
-
- composer_server = bonobo_object_corba_objref (BONOBO_OBJECT (bonobo_server));
-
- /* Now I have to make a CORBA sequence that represents a recipient list with
- one item, for the organizer. */
- to_list = GNOME_Evolution_Composer_RecipientList__alloc ();
- to_list->_maximum = 1;
- to_list->_length = 1;
- to_list->_buffer = CORBA_sequence_GNOME_Evolution_Composer_Recipient_allocbuf (1);
-
- recipient = &(to_list->_buffer[0]);
- recipient->name = CORBA_string_alloc (0); /* FIXME: we may want an actual name here. */
- recipient->name[0] = '\0';
- recipient->address = CORBA_string_alloc (strlen (priv->organizer));
- strcpy (recipient->address, priv->organizer);
-
- cc_list = GNOME_Evolution_Composer_RecipientList__alloc ();
- cc_list->_maximum = cc_list->_length = 0;
- bcc_list = GNOME_Evolution_Composer_RecipientList__alloc ();
- bcc_list->_maximum = bcc_list->_length = 0;
-
- cal_component_get_summary (priv->cal_comp, &caltext);
- subject = CORBA_string_alloc (strlen (caltext.value));
- strcpy (subject, caltext.value);
-
- GNOME_Evolution_Composer_setHeaders (composer_server, to_list, cc_list, bcc_list, subject, &ev);
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_printerr ("gui/e-meeting-edit.c: I couldn't set the composer headers via CORBA! Aagh.\n");
- CORBA_exception_free (&ev);
- return;
- }
-
- sprintf (tempstr, "text/calendar;METHOD=REPLY");
- content_type = CORBA_string_alloc (strlen (tempstr));
- strcpy (content_type, tempstr);
- filename = CORBA_string_alloc (0);
- filename[0] = '\0';
- sprintf (tempstr, "Calendar attachment");
- description = CORBA_string_alloc (strlen (tempstr));
- strcpy (description, tempstr);
- show_inline = FALSE;
-
- /* I need to create an encapsulating iCalendar component, and stuff our reply event
- into it. */
- {
- icalcomponent *comp;
- icalproperty *prop;
- icalvalue *value;
- gchar *ical_string;
-
- comp = icalcomponent_new (ICAL_VCALENDAR_COMPONENT);
-
- prop = icalproperty_new (ICAL_PRODID_PROPERTY);
- value = icalvalue_new_text ("-//HelixCode/Evolution//EN");
- icalproperty_set_value (prop, value);
- icalcomponent_add_property (comp, prop);
-
- prop = icalproperty_new (ICAL_VERSION_PROPERTY);
- value = icalvalue_new_text ("2.0");
- icalproperty_set_value (prop, value);
- icalcomponent_add_property (comp, prop);
-
- prop = icalproperty_new (ICAL_METHOD_PROPERTY);
- value = icalvalue_new_text ("REPLY");
- icalproperty_set_value (prop, value);
- icalcomponent_add_property (comp, prop);
-
- icalcomponent_remove_component (priv->main_comp, priv->comp);
- icalcomponent_add_component (comp, priv->comp);
-
- ical_string = icalcomponent_as_ical_string (comp);
- attach_data = CORBA_string_alloc (strlen (ical_string));
- strcpy (attach_data, ical_string);
-
- icalcomponent_remove_component (comp, priv->comp);
- icalcomponent_add_component (priv->main_comp, priv->comp);
- icalcomponent_free (comp);
-
- }
-
- GNOME_Evolution_Composer_attachData (composer_server,
- content_type, filename, description,
- show_inline, attach_data,
- &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_printerr ("gui/e-meeting-edit.c: I couldn't attach data to the composer via CORBA! Aagh.\n");
- CORBA_exception_free (&ev);
- return;
- }
-
- GNOME_Evolution_Composer_show (composer_server, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_printerr ("gui/e-meeting-edit.c: I couldn't show the composer via CORBA! Aagh.\n");
- CORBA_exception_free (&ev);
- return;
- }
-
- CORBA_exception_free (&ev);
-
- /* Here is where we free our graciously-allocated memory. */
- if (CORBA_sequence_get_release (to_list) != FALSE)
- CORBA_free (to_list->_buffer);
-
- CORBA_free (to_list);
- CORBA_free (cc_list);
- CORBA_free (bcc_list);
-
- CORBA_free (subject);
- CORBA_free (content_type);
- CORBA_free (filename);
- CORBA_free (description);
- CORBA_free (attach_data);
-
-}
-
-static void
accept_button_clicked_cb (GtkWidget *widget, gpointer data)
{
EItipControlPrivate *priv = data;
change_my_status (ICAL_PARTSTAT_ACCEPTED, priv);
- send_itip_reply (priv);
+ itip_send_comp (CAL_COMPONENT_METHOD_REPLY, priv->cal_comp);
update_calendar (priv);
return;
@@ -389,7 +254,7 @@ tentative_button_clicked_cb (GtkWidget *widget, gpointer data)
EItipControlPrivate *priv = data;
change_my_status (ICAL_PARTSTAT_TENTATIVE, priv);
- send_itip_reply (priv);
+ itip_send_comp (CAL_COMPONENT_METHOD_REPLY, priv->cal_comp);
update_calendar (priv);
return;
@@ -401,7 +266,7 @@ decline_button_clicked_cb (GtkWidget *widget, gpointer data)
EItipControlPrivate *priv = data;
change_my_status (ICAL_PARTSTAT_DECLINED, priv);
- send_itip_reply (priv);
+ itip_send_comp (CAL_COMPONENT_METHOD_REPLY, priv->cal_comp);
return;
}
@@ -596,6 +461,7 @@ stream_read (Bonobo_Stream stream)
length += buffer->_length;
CORBA_free (buffer);
+#undef READ_CHUNK_SIZE
} while (1);
CORBA_free (buffer);
@@ -616,7 +482,13 @@ pstream_load (BonoboPersistStream *ps, const Bonobo_Stream stream,
CORBA_Environment *ev)
{
EItipControlPrivate *priv = data;
- gint pos, length, length2;
+ CalComponentText text;
+ CalComponentDateTime datetime;
+ CalComponentOrganizer organizer;
+ icalproperty *prop;
+ GSList *list, *l;
+ time_t t;
+ gint pos = 0;
icalcompiter iter;
icalcomponent_kind comp_kind;
char message[256];
@@ -646,11 +518,10 @@ pstream_load (BonoboPersistStream *ps, const Bonobo_Stream stream,
iter = icalcomponent_begin_component (priv->main_comp, ICAL_ANY_COMPONENT);
priv->comp = icalcompiter_deref (&iter);
-#if 0
{
FILE *fp;
- fp = fopen ("evo.debug", "w");
+ fp = fopen ("/tmp/evo.debug", "w");
fputs ("The raw vCalendar data:\n\n", fp);
fputs (priv->vcalendar, fp);
@@ -663,7 +534,6 @@ pstream_load (BonoboPersistStream *ps, const Bonobo_Stream stream,
fclose (fp);
}
-#endif
if (priv->comp == NULL) {
g_printerr ("e-itip-control.c: I could not extract a proper component from\n"
@@ -690,7 +560,7 @@ pstream_load (BonoboPersistStream *ps, const Bonobo_Stream stream,
break;
default:
/* We don't know what this is, so bail. */
- {
+ {
GtkWidget *dialog;
dialog = gnome_warning_dialog(_("I don't recognize this type of calendar component."));
@@ -700,215 +570,194 @@ pstream_load (BonoboPersistStream *ps, const Bonobo_Stream stream,
priv->vcalendar = NULL;
return;
- }
+ }
break;
} /* End switch. */
+
+ /* Fill in the gui */
+ cal_component_get_organizer (priv->cal_comp, &organizer);
+ priv->organizer = g_strdup (organizer.value);
+ gtk_entry_set_text (GTK_ENTRY (priv->organizer_entry), priv->organizer);
+
+ cal_component_get_summary (priv->cal_comp, &text);
+ gtk_entry_set_text (GTK_ENTRY (priv->summary_entry), text.value);
- /* Okay, good then; now I will pick apart the component to get
- all the things I'll show in my control. */
- {
- icalproperty *prop;
- const char *description, *summary;
- const char *new_text;
- const char *organizer;
- struct icaltimetype dtstart, dtend;
- time_t tstart, tend;
-
- prop = icalcomponent_get_first_property (priv->comp, ICAL_ORGANIZER_PROPERTY);
- if (prop) {
- organizer = icalproperty_get_organizer (prop);
+ cal_component_get_description_list (priv->cal_comp, &list);
+ for (l = list; l != NULL; l = l->next) {
+ text = *((CalComponentText *)l->data);
- /* Here I strip off the "MAILTO:" if it is present. */
- new_text = strchr (organizer, ':');
- if (new_text != NULL)
- new_text++;
- else
- new_text = organizer;
-
- priv->organizer = g_strdup (new_text);
- gtk_entry_set_text (GTK_ENTRY (priv->organizer_entry), new_text);
- }
-
- prop = icalcomponent_get_first_property (priv->comp, ICAL_SUMMARY_PROPERTY);
- if (prop) {
- summary = icalproperty_get_summary (prop);
- gtk_entry_set_text (GTK_ENTRY (priv->summary_entry), summary);
- }
+ gtk_editable_insert_text (GTK_EDITABLE (priv->description_box),
+ text.value, strlen (text.value), &pos);
+ }
+ cal_component_free_text_list (list);
+
+ cal_component_get_dtstart (priv->cal_comp, &datetime);
+ t = icaltime_as_timet (*datetime.value);
+ e_time_format_date_and_time (localtime (&t),
+ calendar_config_get_24_hour_format (),
+ FALSE, FALSE, message, sizeof (message));
+ gtk_label_set_text (GTK_LABEL (priv->dtstart_label), message);
+
+ cal_component_get_dtend (priv->cal_comp, &datetime);
+ t = icaltime_as_timet (*datetime.value);
+ e_time_format_date_and_time (localtime (&t),
+ calendar_config_get_24_hour_format (),
+ FALSE, FALSE, message, sizeof (message));
+ gtk_label_set_text (GTK_LABEL (priv->dtend_label), message);
- prop = icalcomponent_get_first_property (priv->comp, ICAL_DESCRIPTION_PROPERTY);
- if (prop) {
- description = icalproperty_get_summary (prop);
+ /* Clear out any old-assed text that's been lying around in my message box. */
+ gtk_editable_delete_text (GTK_EDITABLE (priv->message_text), 0, -1);
- pos = 0;
- length = strlen (description);
- length2 = strlen (gtk_editable_get_chars
- (GTK_EDITABLE (priv->description_box), 0, -1));
-
- if (length2 > 0)
- gtk_editable_delete_text (GTK_EDITABLE (priv->description_box), 0, length2);
+#if 0
+ prop = icalcomponent_get_first_property (priv->comp, ICAL_ORGANIZER_PROPERTY);
+ if (prop) {
+ organizer = icalproperty_get_organizer (prop);
- gtk_editable_insert_text (GTK_EDITABLE (priv->description_box),
- description,
- length,
- &pos);
- }
-
- prop = icalcomponent_get_first_property (priv->comp, ICAL_DTSTART_PROPERTY);
- dtstart = icalproperty_get_dtstart (prop);
- prop = icalcomponent_get_first_property (priv->comp, ICAL_DTEND_PROPERTY);
- dtend = icalproperty_get_dtend (prop);
-
- tstart = icaltime_as_timet (dtstart);
- tend = icaltime_as_timet (dtend);
-
- gtk_label_set_text (GTK_LABEL (priv->dtstart_label), ctime (&tstart));
- gtk_label_set_text (GTK_LABEL (priv->dtend_label), ctime (&tend));
+ /* Here I strip off the "MAILTO:" if it is present. */
+ new_text = strchr (organizer, ':');
+ if (new_text != NULL)
+ new_text++;
+ else
+ new_text = organizer;
- /* Clear out any old-assed text that's been lying around in my message box. */
- gtk_editable_delete_text (GTK_EDITABLE (priv->message_text), 0, -1);
+ priv->organizer = g_strdup (new_text);
+ gtk_entry_set_text (GTK_ENTRY (priv->organizer_entry), new_text);
+ }
+#endif
- prop = icalcomponent_get_first_property (priv->main_comp, ICAL_METHOD_PROPERTY);
- switch (icalproperty_get_method (prop)) {
- case ICAL_METHOD_PUBLISH:
- {
- GtkWidget *button;
+ prop = icalcomponent_get_first_property (priv->main_comp, ICAL_METHOD_PROPERTY);
+ switch (icalproperty_get_method (prop)) {
+ case ICAL_METHOD_PUBLISH:
+ {
+ GtkWidget *button;
- snprintf (message, 250, "%s has published calendar information, "
- "which you can add to your own calendar. "
- "No reply is necessary.",
- priv->from_address);
+ snprintf (message, 250, "%s has published calendar information, "
+ "which you can add to your own calendar. "
+ "No reply is necessary.",
+ priv->from_address);
- button = gtk_button_new_with_label (_("Add to Calendar"));
- gtk_box_pack_start (GTK_BOX (priv->button_box), button, FALSE, FALSE, 3);
- gtk_widget_show (button);
+ button = gtk_button_new_with_label (_("Add to Calendar"));
+ gtk_box_pack_start (GTK_BOX (priv->button_box), button, FALSE, FALSE, 3);
+ gtk_widget_show (button);
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- GTK_SIGNAL_FUNC (add_button_clicked_cb), priv);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (add_button_clicked_cb), priv);
- break;
- }
- case ICAL_METHOD_REQUEST:
- {
- /* I'll check if I have to rsvp. */
- icalproperty *prop;
- icalparameter *param;
- int rsvp = FALSE;
-
- prop = find_attendee (priv->comp, priv->my_address);
- if (prop) {
- param = get_icalparam_by_type (prop, ICAL_RSVP_PARAMETER);
+ break;
+ }
+ case ICAL_METHOD_REQUEST:
+ {
+ /* I'll check if I have to rsvp. */
+ icalproperty *prop;
+ icalparameter *param;
+ int rsvp = FALSE;
+
+ prop = find_attendee (priv->comp, priv->my_address);
+ if (prop) {
+ param = get_icalparam_by_type (prop, ICAL_RSVP_PARAMETER);
- if (param) {
- if (icalparameter_get_rsvp (param))
- rsvp = TRUE;
- }
+ if (param) {
+ if (icalparameter_get_rsvp (param))
+ rsvp = TRUE;
}
+ }
- snprintf (message, 250, "This is a meeting organized by %s, "
- "who indicated that you %s RSVP.",
- (priv->organizer ? priv->organizer : "an unknown person"),
- (rsvp ? "should" : "don't have to") );
+ snprintf (message, 250, "This is a meeting organized by %s, "
+ "who indicated that you %s RSVP.",
+ (priv->organizer ? priv->organizer : "an unknown person"),
+ (rsvp ? "should" : "don't have to") );
- if (rsvp) {
- GtkWidget *accept_button, *decline_button, *tentative_button;
+ if (rsvp) {
+ GtkWidget *accept_button, *decline_button, *tentative_button;
- accept_button = gtk_button_new_with_label (_(" Accept "));
- decline_button = gtk_button_new_with_label (_(" Decline "));
- tentative_button = gtk_button_new_with_label (_(" Tentative "));
+ accept_button = gtk_button_new_with_label (_(" Accept "));
+ decline_button = gtk_button_new_with_label (_(" Decline "));
+ tentative_button = gtk_button_new_with_label (_(" Tentative "));
- gtk_box_pack_start (GTK_BOX (priv->button_box), decline_button, FALSE, FALSE, 3);
- gtk_box_pack_end (GTK_BOX (priv->button_box), accept_button, FALSE, FALSE, 3);
- gtk_box_pack_end (GTK_BOX (priv->button_box), tentative_button, FALSE, FALSE, 3);
+ gtk_box_pack_start (GTK_BOX (priv->button_box), decline_button, FALSE, FALSE, 3);
+ gtk_box_pack_end (GTK_BOX (priv->button_box), accept_button, FALSE, FALSE, 3);
+ gtk_box_pack_end (GTK_BOX (priv->button_box), tentative_button, FALSE, FALSE, 3);
- gtk_signal_connect (GTK_OBJECT (accept_button), "clicked",
- GTK_SIGNAL_FUNC (accept_button_clicked_cb), priv);
- gtk_signal_connect (GTK_OBJECT (tentative_button), "clicked",
- GTK_SIGNAL_FUNC (tentative_button_clicked_cb), priv);
- gtk_signal_connect (GTK_OBJECT (decline_button), "clicked",
- GTK_SIGNAL_FUNC (decline_button_clicked_cb), priv);
+ gtk_signal_connect (GTK_OBJECT (accept_button), "clicked",
+ GTK_SIGNAL_FUNC (accept_button_clicked_cb), priv);
+ gtk_signal_connect (GTK_OBJECT (tentative_button), "clicked",
+ GTK_SIGNAL_FUNC (tentative_button_clicked_cb), priv);
+ gtk_signal_connect (GTK_OBJECT (decline_button), "clicked",
+ GTK_SIGNAL_FUNC (decline_button_clicked_cb), priv);
- gtk_widget_show (accept_button);
- gtk_widget_show (tentative_button);
- gtk_widget_show (decline_button);
- }
+ gtk_widget_show (accept_button);
+ gtk_widget_show (tentative_button);
+ gtk_widget_show (decline_button);
+ }
- }
- break;
- case ICAL_METHOD_REPLY:
- {
- icalproperty *prop;
- icalparameter *param;
- gboolean success = FALSE;
-
- prop = find_attendee (priv->comp, priv->from_address);
- if (prop) {
- param = get_icalparam_by_type (prop, ICAL_PARTSTAT_PARAMETER);
- if (param) {
- success = TRUE;
-
- priv->new_partstat = icalparameter_get_partstat (param);
- }
- }
+ }
+ break;
+ case ICAL_METHOD_REPLY:
+ {
+ icalproperty *prop;
+ icalparameter *param;
+ gboolean success = FALSE;
+
+ prop = find_attendee (priv->comp, priv->from_address);
+ if (prop) {
+ param = get_icalparam_by_type (prop, ICAL_PARTSTAT_PARAMETER);
+ if (param) {
+ success = TRUE;
- if (!success) {
- snprintf (message, 250, "%s sent a reply to a meeting request, but "
- "the reply is not properly formed.",
- priv->from_address);
+ priv->new_partstat = icalparameter_get_partstat (param);
}
- else {
- GtkWidget *button;
+ }
+
+ if (!success) {
+ snprintf (message, 250, "%s sent a reply to a meeting request, but "
+ "the reply is not properly formed.",
+ priv->from_address);
+ }
+ else {
+ GtkWidget *button;
- button = gtk_button_new_with_label (_("Update Calendar"));
- gtk_box_pack_start (GTK_BOX (priv->button_box), button, FALSE, FALSE, 3);
- gtk_widget_show (button);
+ button = gtk_button_new_with_label (_("Update Calendar"));
+ gtk_box_pack_start (GTK_BOX (priv->button_box), button, FALSE, FALSE, 3);
+ gtk_widget_show (button);
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- GTK_SIGNAL_FUNC (update_reply_cb), priv);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (update_reply_cb), priv);
- snprintf (message, 250, "%s responded to your request, replying with: %s",
- priv->from_address, partstat_values[priv->new_partstat]);
- }
-
- }
- break;
- case ICAL_METHOD_CANCEL:
- {
- if (strcmp (priv->organizer, priv->from_address) != 0) {
- snprintf (message, 250, "%s sent a cancellation request, but is not "
- "the organizer of the meeting.",
- priv->from_address);
- }
- else {
- GtkWidget *button;
-
- button = gtk_button_new_with_label (_("Cancel Meeting"));
- gtk_box_pack_start (GTK_BOX (priv->button_box), button, FALSE, FALSE, 3);
- gtk_widget_show (button);
-
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- GTK_SIGNAL_FUNC (cancel_meeting_cb), priv);
+ snprintf (message, 250, "%s responded to your request, replying with: %s",
+ priv->from_address, partstat_values[priv->new_partstat]);
+ }
- snprintf (message, 250, "%s sent a cancellation request. You can"
- " delete this event from your calendar, if you wish.",
- priv->organizer);
- }
+ }
+ break;
+ case ICAL_METHOD_CANCEL:
+ if (strcmp (priv->organizer, priv->from_address) != 0) {
+ snprintf (message, 250, "%s sent a cancellation request, but is not "
+ "the organizer of the meeting.",
+ priv->from_address);
+ } else {
+ GtkWidget *button;
- }
- break;
- default:
- snprintf (message, 250, "I haven't the slightest notion what this calendar "
- "object represents. Sorry.");
- }
+ button = gtk_button_new_with_label (_("Cancel Meeting"));
+ gtk_box_pack_start (GTK_BOX (priv->button_box), button, FALSE, FALSE, 3);
+ gtk_widget_show (button);
- {
- int pos = 0;
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (cancel_meeting_cb), priv);
- gtk_editable_insert_text (GTK_EDITABLE (priv->message_text), message,
- strlen (message), &pos);
+ snprintf (message, 250, "%s sent a cancellation request. You can"
+ " delete this event from your calendar, if you wish.",
+ priv->organizer);
}
+ break;
+ default:
+ snprintf (message, 250, "I haven't the slightest notion what this calendar "
+ "object represents. Sorry.");
}
+ pos = 0;
+ gtk_editable_insert_text (GTK_EDITABLE (priv->message_text),
+ message, strlen (message), &pos);
} /* pstream_load */
/*
diff --git a/calendar/gui/itip-utils.c b/calendar/gui/itip-utils.c
index 5bf442dec9..239a16ae00 100644
--- a/calendar/gui/itip-utils.c
+++ b/calendar/gui/itip-utils.c
@@ -4,12 +4,46 @@
*
* Authors:
* Jesse Pavel <jpavel@helixcode.com>
+ * JP Rosevear <jpr@ximian.com>
*
- * Copyright 2000, Helix Code, Inc.
+ * Copyright 2001, Ximian, Inc.
*/
+#include <bonobo/bonobo-object.h>
+#include <bonobo/bonobo-object-client.h>
+#include <libgnome/gnome-defs.h>
+#include <libgnome/gnome-i18n.h>
+#include <libgnomeui/gnome-dialog.h>
+#include <libgnomeui/gnome-dialog-util.h>
+#include <gtk/gtkwidget.h>
+#include <ical.h>
+#include <Evolution-Composer.h>
#include "itip-utils.h"
+#define GNOME_EVOLUTION_COMPOSER_OAFIID "OAFIID:GNOME_Evolution_Mail_Composer"
+
+static gchar *itip_methods[] = {
+ "PUBLISH",
+ "REQUEST",
+ "REPLY",
+ "ADD",
+ "CANCEL"
+ "RERESH"
+ "COUNTER"
+ "DECLINECOUNTER"
+};
+
+static icalproperty_method itip_methods_enum[] = {
+ ICAL_METHOD_PUBLISH,
+ ICAL_METHOD_REQUEST,
+ ICAL_METHOD_REPLY,
+ ICAL_METHOD_ADD,
+ ICAL_METHOD_CANCEL,
+ ICAL_METHOD_REFRESH,
+ ICAL_METHOD_COUNTER,
+ ICAL_METHOD_DECLINECOUNTER,
+};
+
gchar *partstat_values[] = {
"Needs action",
"Accepted",
@@ -45,4 +79,196 @@ get_icalparam_by_type (icalproperty *prop, icalparameter_kind kind)
return param;
}
+static void
+error_dialog (gchar *str)
+{
+ GtkWidget *dlg;
+
+ dlg = gnome_error_dialog (str);
+ gnome_dialog_run_and_close (GNOME_DIALOG (dlg));
+}
+
+void
+itip_send_comp (CalComponentItipMethod method, CalComponent *comp)
+{
+ BonoboObjectClient *bonobo_server;
+ GNOME_Evolution_Composer composer_server;
+ CORBA_Environment ev;
+ GSList *attendees, *l;
+ GNOME_Evolution_Composer_RecipientList *to_list, *cc_list, *bcc_list;
+ GNOME_Evolution_Composer_Recipient *recipient;
+ CORBA_char *subject;
+ gint cntr;
+ gint len;
+ CalComponentText caltext;
+ CalComponentOrganizer organizer;
+ CORBA_char *content_type, *filename, *description, *attach_data;
+ CORBA_boolean show_inline;
+ CORBA_char tempstr[200];
+
+ CORBA_exception_init (&ev);
+
+ /* First, I obtain an object reference that represents the Composer. */
+ bonobo_server = bonobo_object_activate (GNOME_EVOLUTION_COMPOSER_OAFIID, 0);
+ g_return_if_fail (bonobo_server != NULL);
+
+ composer_server = BONOBO_OBJREF (bonobo_server);
+
+ switch (method) {
+ case CAL_COMPONENT_METHOD_PUBLISH:
+ case CAL_COMPONENT_METHOD_REQUEST:
+ case CAL_COMPONENT_METHOD_CANCEL:
+ cal_component_get_attendee_list (comp, &attendees);
+ len = g_slist_length (attendees);
+
+ to_list = GNOME_Evolution_Composer_RecipientList__alloc ();
+ to_list->_maximum = len;
+ to_list->_length = len;
+ to_list->_buffer = CORBA_sequence_GNOME_Evolution_Composer_Recipient_allocbuf (len);
+
+ for (cntr = 0, l = attendees; cntr < len; cntr++, l = l->next) {
+ CalComponentAttendee *att = l->data;
+
+ recipient = &(to_list->_buffer[cntr]);
+ if (att->cn)
+ recipient->name = CORBA_string_dup (att->cn);
+ else
+ recipient->name = CORBA_string_dup ("");
+ recipient->address = CORBA_string_dup (att->value);
+ }
+ break;
+
+ case CAL_COMPONENT_METHOD_REPLY:
+ case CAL_COMPONENT_METHOD_ADD:
+ case CAL_COMPONENT_METHOD_REFRESH:
+ case CAL_COMPONENT_METHOD_COUNTER:
+ case CAL_COMPONENT_METHOD_DECLINECOUNTER:
+ cal_component_get_organizer (comp, &organizer);
+ if (organizer.value == NULL) {
+ error_dialog (_("An organizer must be set."));
+ return;
+ }
+
+ len = 1;
+
+ to_list = GNOME_Evolution_Composer_RecipientList__alloc ();
+ to_list->_maximum = len;
+ to_list->_length = len;
+ to_list->_buffer = CORBA_sequence_GNOME_Evolution_Composer_Recipient_allocbuf (len);
+ recipient = &(to_list->_buffer[0]);
+
+ if (organizer.cn != NULL)
+ recipient->name = CORBA_string_dup (organizer.cn);
+ else
+ recipient->name = CORBA_string_dup ("");
+ recipient->address = CORBA_string_dup (organizer.value);
+ break;
+ }
+
+ cc_list = GNOME_Evolution_Composer_RecipientList__alloc ();
+ cc_list->_maximum = cc_list->_length = 0;
+ bcc_list = GNOME_Evolution_Composer_RecipientList__alloc ();
+ bcc_list->_maximum = bcc_list->_length = 0;
+
+ cal_component_get_summary (comp, &caltext);
+ subject = CORBA_string_dup (caltext.value);
+
+ GNOME_Evolution_Composer_setHeaders (composer_server, to_list, cc_list, bcc_list, subject, &ev);
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("Unable to set composer headers while sending iTip message");
+ CORBA_exception_free (&ev);
+ return;
+ }
+
+ sprintf (tempstr, "text/calendar;METHOD=%s", itip_methods[method]);
+ content_type = CORBA_string_dup (tempstr);
+ filename = CORBA_string_dup ("");
+ sprintf (tempstr, "Calendar attachment");
+ description = CORBA_string_dup (tempstr);
+ show_inline = FALSE;
+
+ /* I need to create an encapsulating iCalendar component, and stuff our vEvent
+ into it. */
+ {
+ icalcomponent *icomp, *clone;
+ icalproperty *prop;
+ icalvalue *value;
+ gchar *ical_string;
+
+ icomp = icalcomponent_new (ICAL_VCALENDAR_COMPONENT);
+
+ prop = icalproperty_new (ICAL_PRODID_PROPERTY);
+ value = icalvalue_new_text ("-//Ximian/Evolution//EN");
+ icalproperty_set_value (prop, value);
+ icalcomponent_add_property (icomp, prop);
+
+ prop = icalproperty_new (ICAL_VERSION_PROPERTY);
+ value = icalvalue_new_text ("2.0");
+ icalproperty_set_value (prop, value);
+ icalcomponent_add_property (icomp, prop);
+
+ prop = icalproperty_new (ICAL_METHOD_PROPERTY);
+ value = icalvalue_new_method (itip_methods_enum[method]);
+ icalproperty_set_value (prop, value);
+ icalcomponent_add_property (icomp, prop);
+
+ clone = icalcomponent_new_clone (cal_component_get_icalcomponent (comp));
+ icalcomponent_add_component (icomp, clone);
+
+ ical_string = icalcomponent_as_ical_string (icomp);
+ attach_data = CORBA_string_dup (ical_string);
+
+ icalcomponent_free (icomp);
+ }
+
+ GNOME_Evolution_Composer_attachData (composer_server,
+ content_type, filename, description,
+ show_inline, attach_data,
+ &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("Unable to attach data to the composer while sending iTip message");
+ CORBA_exception_free (&ev);
+ return;
+ }
+
+ GNOME_Evolution_Composer_show (composer_server, &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("Unable to show the composer while sending iTip message");
+ CORBA_exception_free (&ev);
+ return;
+ }
+
+ CORBA_exception_free (&ev);
+
+ /* Let's free shit up. */
+
+ /* Beware--depending on whether CORBA_free is recursive, which I
+ think is is, we might have memory leaks, in which case the code
+ below is necessary. */
+#if 0
+ for (cntr = 0; cntr < priv->numentries; cntr++) {
+ recipient = &(to_list->_buffer[cntr]);
+ CORBA_free (recipient->name);
+ CORBA_free (recipient->address);
+ recipient->name = recipient->address = NULL;
+ }
+#endif
+
+ if (CORBA_sequence_get_release (to_list) != FALSE)
+ CORBA_free (to_list->_buffer);
+
+ CORBA_free (to_list);
+ CORBA_free (cc_list);
+ CORBA_free (bcc_list);
+
+ CORBA_free (subject);
+ CORBA_free (content_type);
+ CORBA_free (filename);
+ CORBA_free (description);
+ CORBA_free (attach_data);
+
+ /* bonobo_object_unref (BONOBO_OBJECT (bonobo_server)); */
+}
diff --git a/calendar/gui/itip-utils.h b/calendar/gui/itip-utils.h
index a2f825be8b..b51696876f 100644
--- a/calendar/gui/itip-utils.h
+++ b/calendar/gui/itip-utils.h
@@ -6,10 +6,24 @@
#include <ical.h>
#include <string.h>
#include <glib.h>
+#include <cal-util/cal-component.h>
extern gchar *partstat_values[];
extern gchar *role_values[];
icalparameter * get_icalparam_by_type (icalproperty *prop, icalparameter_kind kind);
+typedef enum {
+ CAL_COMPONENT_METHOD_PUBLISH,
+ CAL_COMPONENT_METHOD_REQUEST,
+ CAL_COMPONENT_METHOD_REPLY,
+ CAL_COMPONENT_METHOD_ADD,
+ CAL_COMPONENT_METHOD_CANCEL,
+ CAL_COMPONENT_METHOD_REFRESH,
+ CAL_COMPONENT_METHOD_COUNTER,
+ CAL_COMPONENT_METHOD_DECLINECOUNTER
+} CalComponentItipMethod;
+
+void itip_send_comp (CalComponentItipMethod method, CalComponent *comp);
+
#endif