aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/gui/dialogs/comp-editor.c
diff options
context:
space:
mode:
Diffstat (limited to 'calendar/gui/dialogs/comp-editor.c')
-rw-r--r--calendar/gui/dialogs/comp-editor.c4057
1 files changed, 3226 insertions, 831 deletions
diff --git a/calendar/gui/dialogs/comp-editor.c b/calendar/gui/dialogs/comp-editor.c
index a1bf930579..39ca3a81e1 100644
--- a/calendar/gui/dialogs/comp-editor.c
+++ b/calendar/gui/dialogs/comp-editor.c
@@ -1,368 +1,668 @@
-/* Evolution calendar - Framework for a calendar component editor dialog
- *
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Author: Federico Mena-Quintero <federico@ximian.com>
+/*
+ * Evolution calendar - Framework for a calendar component editor dialog
*
* This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
*
* 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.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Federico Mena-Quintero <federico@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*
- * 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 <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <fcntl.h>
#include <unistd.h>
-#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <glib/gstdio.h>
+#include <gio/gio.h>
#include <gdk/gdkkeysyms.h>
-#include <libgnome/gnome-defs.h>
-#include <libgnome/gnome-i18n.h>
-#include <libgnomeui/gnome-uidefs.h>
-#include <libgnomeui/gnome-dialog.h>
-#include <libgnomeui/gnome-dialog-util.h>
-#include <libgnomeui/gnome-stock.h>
-#include <libgnomeui/gnome-window-icon.h>
-#include <libgnomeui/gnome-messagebox.h>
-#include <bonobo/bonobo-ui-container.h>
-#include <bonobo/bonobo-ui-util.h>
-#include <gal/widgets/e-unicode.h>
-#include <gal/widgets/e-gui-utils.h>
-#include <e-util/e-dialog-utils.h>
-#include <evolution-shell-component-utils.h>
+#include <libebackend/libebackend.h>
+
+#include <shell/e-shell.h>
+
#include "../print.h"
+#include "../comp-util.h"
#include "save-comp.h"
#include "delete-comp.h"
#include "send-comp.h"
#include "changed-comp.h"
#include "cancel-comp.h"
+#include "recur-comp.h"
#include "comp-editor.h"
+#include "comp-editor-util.h"
+#include "../calendar-config-keys.h"
-
+#define COMP_EDITOR_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), TYPE_COMP_EDITOR, CompEditorPrivate))
+
+#define d(x)
/* Private part of the CompEditor structure */
struct _CompEditorPrivate {
+
+ gpointer shell; /* weak pointer */
+
+ GSettings *calendar_settings;
+
+ /* EFocusTracker keeps selection actions up-to-date. */
+ EFocusTracker *focus_tracker;
+
+ /* Each CompEditor window gets its own GtkWindowGroup, so it
+ * doesn't block the main window or other CompEditor windows. */
+ GtkWindowGroup *window_group;
+
/* Client to use */
- CalClient *client;
+ ECalClient *cal_client;
+
+ /* Source client (where comp lives currently) */
+ ECalClient *source_client;
+
+ /* View to listen for changes */
+ ECalClientView *view;
+ GCancellable *view_cancellable;
/* Calendar object/uid we are editing; this is an internal copy */
- CalComponent *comp;
+ ECalComponent *comp;
/* The pages we have */
GList *pages;
- /* UI Component for the dialog */
- BonoboUIComponent *uic;
-
/* Notebook to hold the pages */
GtkNotebook *notebook;
- GtkWidget *filesel;
+ /* Attachment handling */
+ GtkWidget *attachment_view;
+
+ /* Manages menus and toolbars */
+ GtkUIManager *ui_manager;
+
+ gchar *summary;
+
+ guint32 attachment_bar_visible : 1;
+
+ /* TODO use this flags for setting all the boolean variables
+ * below */
+ CompEditorFlags flags;
+
+ icaltimezone *zone;
+ gboolean use_24_hour_format;
+
+ GDateWeekday week_start_day;
+
+ gint work_day_end_hour;
+ gint work_day_end_minute;
+ gint work_day_start_hour;
+ gint work_day_start_minute;
gboolean changed;
gboolean needs_send;
- gboolean existing_org;
- gboolean user_org;
-
- gboolean warned;
-
- gboolean updating;
-};
+ gboolean saved;
+
+ CalObjModType mod;
-
+ gboolean existing_org;
+ gboolean user_org;
+ gboolean is_group_item;
-static void comp_editor_class_init (CompEditorClass *class);
-static void comp_editor_init (CompEditor *editor);
-static gint comp_editor_key_press_event (GtkWidget *d, GdkEventKey *e);
-static void comp_editor_destroy (GtkObject *object);
+ gboolean warned;
+};
-static void real_set_cal_client (CompEditor *editor, CalClient *client);
-static void real_edit_comp (CompEditor *editor, CalComponent *comp);
-static gboolean real_send_comp (CompEditor *editor, CalComponentItipMethod method);
-static gboolean prompt_to_save_changes (CompEditor *editor, gboolean send);
-static void delete_comp (CompEditor *editor);
-static void close_dialog (CompEditor *editor);
+enum {
+ PROP_0,
+ PROP_CHANGED,
+ PROP_CLIENT,
+ PROP_FLAGS,
+ PROP_FOCUS_TRACKER,
+ PROP_SHELL,
+ PROP_SUMMARY,
+ PROP_TIMEZONE,
+ PROP_USE_24_HOUR_FORMAT,
+ PROP_WEEK_START_DAY,
+ PROP_WORK_DAY_END_HOUR,
+ PROP_WORK_DAY_END_MINUTE,
+ PROP_WORK_DAY_START_HOUR,
+ PROP_WORK_DAY_START_MINUTE
+};
-static void page_changed_cb (GtkObject *obj, gpointer data);
-static void page_summary_changed_cb (GtkObject *obj, const char *summary, gpointer data);
-static void page_dates_changed_cb (GtkObject *obj, CompEditorPageDates *dates, gpointer data);
+static const gchar *ui =
+"<ui>"
+" <menubar action='main-menu'>"
+" <menu action='file-menu'>"
+" <menuitem action='save'/>"
+" <menuitem action='save-and-close'/>"
+" <separator/>"
+" <menuitem action='print-preview'/>"
+" <menuitem action='print'/>"
+" <separator/>"
+" <menuitem action='close'/>"
+" </menu>"
+" <menu action='edit-menu'>"
+" <menuitem action='cut-clipboard'/>"
+" <menuitem action='copy-clipboard'/>"
+" <menuitem action='paste-clipboard'/>"
+" <menuitem action='delete-selection'/>"
+" <separator/>"
+" <menuitem action='select-all'/>"
+" </menu>"
+" <menu action='view-menu'/>"
+" <menu action='insert-menu'>"
+" <menuitem action='attach'/>"
+" </menu>"
+" <menu action='options-menu'/>"
+" <menu action='help-menu'>"
+" <menuitem action='help'/>"
+" </menu>"
+" </menubar>"
+" <toolbar name='main-toolbar'>"
+" <toolitem action='save-and-close'/>\n"
+" <toolitem action='save'/>\n"
+" <toolitem action='print'/>\n"
+" <separator/>"
+" <placeholder name='content'/>\n"
+" </toolbar>"
+"</ui>";
+
+static void comp_editor_show_help (CompEditor *editor);
+
+static void real_edit_comp (CompEditor *editor,
+ ECalComponent *comp);
+static gboolean real_send_comp (CompEditor *editor,
+ ECalComponentItipMethod method,
+ gboolean strip_alarms);
+static gboolean prompt_and_save_changes (CompEditor *editor,
+ gboolean send);
+static void close_dialog (CompEditor *editor);
+
+static void page_dates_changed_cb (CompEditor *editor,
+ CompEditorPageDates *dates,
+ CompEditorPage *page);
+
+static void obj_modified_cb (ECalClientView *view,
+ const GSList *objs,
+ CompEditor *editor);
+static void obj_removed_cb (ECalClientView *view,
+ const GSList *uids,
+ CompEditor *editor);
+
+G_DEFINE_TYPE_WITH_CODE (
+ CompEditor, comp_editor, GTK_TYPE_WINDOW,
+ G_IMPLEMENT_INTERFACE (E_TYPE_ALERT_SINK, NULL)
+ G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE, NULL))
+
+enum {
+ OBJECT_CREATED,
+ COMP_CLOSED,
+ LAST_SIGNAL
+};
-static void obj_updated_cb (CalClient *client, const char *uid, gpointer data);
-static void obj_removed_cb (CalClient *client, const char *uid, gpointer data);
+static guint signals[LAST_SIGNAL];
+static GList *active_editors;
-static void save_cmd (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 print_cmd (GtkWidget *widget, gpointer data);
-static void print_preview_cmd (GtkWidget *widget, gpointer data);
-static void print_setup_cmd (GtkWidget *widget, gpointer data);
-static void close_cmd (GtkWidget *widget, gpointer data);
+static void
+comp_editor_weak_notify_cb (gpointer unused,
+ GObject *where_the_object_was)
+{
+ active_editors = g_list_remove (active_editors, where_the_object_was);
+}
-static gint delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer data);
+static void
+attachment_store_changed_cb (CompEditor *editor)
+{
+ /* Mark the editor as changed so it prompts about unsaved
+ * changes on close */
+ comp_editor_set_changed (editor, TRUE);
+}
-static EPixmap pixmaps [] =
+static void
+attachment_save_finished (EAttachmentStore *store,
+ GAsyncResult *result,
+ gpointer user_data)
{
- E_PIXMAP ("/menu/File/FileSave", "save-16.png"),
- E_PIXMAP ("/menu/File/FileSaveAndClose", "save-16.png"),
- E_PIXMAP ("/menu/File/FileSaveAs", "save-as-16.png"),
+ GtkWidget *dialog;
+ const gchar *primary_text;
+ gchar **uris;
+ GError *error = NULL;
- E_PIXMAP ("/menu/File/FileDelete", "evolution-trash-mini.png"),
+ struct {
+ gchar **uris;
+ gboolean done;
+ GtkWindow *parent;
+ } *status = user_data;
- E_PIXMAP ("/menu/File/FilePrint", "print.xpm"),
- E_PIXMAP ("/menu/File/FilePrintPreview", "print-preview.xpm"),
+ uris = e_attachment_store_save_finish (store, result, &error);
- E_PIXMAP ("/Toolbar/FileSaveAndClose", "buttons/save-24.png"),
- E_PIXMAP ("/Toolbar/FilePrint", "buttons/print.png"),
- E_PIXMAP ("/Toolbar/FileDelete", "buttons/delete-message.png"),
+ status->uris = uris;
+ status->done = TRUE;
- E_PIXMAP_END
-};
+ if (uris != NULL)
+ goto exit;
-static BonoboUIVerb verbs [] = {
- BONOBO_UI_UNSAFE_VERB ("FileSave", save_cmd),
- 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 ("FilePrint", print_cmd),
- BONOBO_UI_UNSAFE_VERB ("FilePrintPreview", print_preview_cmd),
- BONOBO_UI_UNSAFE_VERB ("FilePrintSetup", print_setup_cmd),
- BONOBO_UI_UNSAFE_VERB ("FileClose", close_cmd),
-
- BONOBO_UI_VERB_END
-};
+ /* Ignore cancellations. */
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ goto exit;
-static GtkObjectClass *parent_class;
+ primary_text = _("Could not save attachments");
-
+ dialog = gtk_message_dialog_new_with_markup (
+ status->parent, GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ "<big><b>%s</b></big>", primary_text);
-GtkType
-comp_editor_get_type (void)
-{
- static GtkType comp_editor_type = 0;
+ gtk_message_dialog_format_secondary_text (
+ GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
- if (!comp_editor_type) {
- static const GtkTypeInfo comp_editor_info = {
- "CompEditor",
- sizeof (CompEditor),
- sizeof (CompEditorClass),
- (GtkClassInitFunc) comp_editor_class_init,
- (GtkObjectInitFunc) comp_editor_init,
- NULL, /* reserved_1 */
- NULL, /* reserved_2 */
- (GtkClassInitFunc) NULL
- };
+ gtk_dialog_run (GTK_DIALOG (dialog));
- comp_editor_type = gtk_type_unique (BONOBO_TYPE_WINDOW,
- &comp_editor_info);
- }
+ gtk_widget_destroy (dialog);
+
+exit:
+ if (error != NULL)
+ g_error_free (error);
- return comp_editor_type;
+ g_object_unref (status->parent);
}
-/* Class initialization function for the calendar component editor */
-static void
-comp_editor_class_init (CompEditorClass *klass)
+static GSList *
+get_attachment_list (CompEditor *editor)
{
- GtkObjectClass *object_class;
- GtkWidgetClass *widget_class;
-
- object_class = GTK_OBJECT_CLASS (klass);
- widget_class = GTK_WIDGET_CLASS (klass);
+ EAttachmentStore *store;
+ EAttachmentView *view;
+ GFile *destination;
+ GSList *list = NULL;
+ const gchar *comp_uid = NULL;
+ const gchar *local_store;
+ gchar *filename_prefix, *tmp;
+ gint ii;
+
+ struct {
+ gchar **uris;
+ gboolean done;
+ GtkWindow *parent;
+ } status;
+
+ e_cal_component_get_uid (editor->priv->comp, &comp_uid);
+ g_return_val_if_fail (comp_uid != NULL, NULL);
+
+ status.uris = NULL;
+ status.done = FALSE;
+ status.parent = g_object_ref (editor);
+
+ view = E_ATTACHMENT_VIEW (editor->priv->attachment_view);
+ store = e_attachment_view_get_store (view);
+
+ tmp = g_strdup (comp_uid);
+ e_filename_make_safe (tmp);
+ filename_prefix = g_strconcat (tmp, "-", NULL);
+ g_free (tmp);
+
+ local_store = e_cal_client_get_local_attachment_store (editor->priv->cal_client);
+ destination = g_file_new_for_path (local_store);
+
+ e_attachment_store_save_async (
+ store, destination, filename_prefix,
+ (GAsyncReadyCallback) attachment_save_finished, &status);
+
+ g_object_unref (destination);
+ g_free (filename_prefix);
+
+ /* We can't return until we have results, so crank
+ * the main loop until the callback gets triggered. */
+ while (!status.done)
+ gtk_main_iteration ();
+
+ if (status.uris == NULL)
+ return NULL;
- parent_class = gtk_type_class (BONOBO_TYPE_WINDOW);
+ /* Transfer the URI strings to the GSList. */
+ for (ii = 0; status.uris[ii] != NULL; ii++) {
+ list = g_slist_prepend (list, status.uris[ii]);
+ status.uris[ii] = NULL;
+ }
- klass->set_cal_client = real_set_cal_client;
- klass->edit_comp = real_edit_comp;
- klass->send_comp = real_send_comp;
+ g_free (status.uris);
- widget_class->key_press_event = comp_editor_key_press_event;
- object_class->destroy = comp_editor_destroy;
+ return g_slist_reverse (list);
}
-/* Creates the basic in the editor */
+/* This sets the focus to the toplevel, so any field being edited is committed.
+ * FIXME: In future we may also want to check some of the fields are valid,
+ * e.g. the EDateEdit fields. */
static void
-setup_widgets (CompEditor *editor)
+commit_all_fields (CompEditor *editor)
{
- CompEditorPrivate *priv;
- BonoboUIContainer *container;
- GtkWidget *vbox;
-
- priv = editor->priv;
+ gtk_window_set_focus (GTK_WINDOW (editor), NULL);
+}
- /* Window and basic vbox */
- bonobo_window_construct (BONOBO_WINDOW (editor),
- "event-editor", "iCalendar Editor");
- gtk_signal_connect (GTK_OBJECT (editor), "delete_event",
- GTK_SIGNAL_FUNC (delete_event_cb), editor);
-
- priv->uic = bonobo_ui_component_new_default ();
- container = bonobo_ui_container_new ();
- bonobo_ui_container_set_win (container, BONOBO_WINDOW (editor));
- bonobo_ui_component_set_container (priv->uic, BONOBO_OBJREF (container));
- bonobo_ui_engine_config_set_path (bonobo_window_get_ui_engine (BONOBO_WINDOW (editor)),
- "/evolution/UIConf/kvps");
-
- bonobo_ui_component_add_verb_list_with_data (priv->uic, verbs, editor);
- bonobo_ui_util_set_ui (priv->uic, EVOLUTION_DATADIR,
- "evolution-comp-editor.xml",
- "evolution-calendar");
- e_pixmaps_update (priv->uic, pixmaps);
-
- vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
- gtk_widget_show (vbox);
- gtk_container_set_border_width (GTK_CONTAINER (vbox), GNOME_PAD_SMALL);
- bonobo_window_set_contents (BONOBO_WINDOW (editor), vbox);
-
- /* Notebook */
- priv->notebook = GTK_NOTEBOOK (gtk_notebook_new ());
- gtk_widget_show (GTK_WIDGET (priv->notebook));
- gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (priv->notebook),
- TRUE, TRUE, 0);
-}
-
-/* Object initialization function for the calendar component editor */
static void
-comp_editor_init (CompEditor *editor)
+changes_view_ready_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
- CompEditorPrivate *priv;
+ CompEditor *editor = user_data;
+ ECalClientView *view = NULL;
+ gboolean success;
+ GError *error = NULL;
- priv = g_new0 (CompEditorPrivate, 1);
- editor->priv = priv;
+ g_return_if_fail (editor != NULL);
- setup_widgets (editor);
+ success = e_cal_client_get_view_finish (
+ E_CAL_CLIENT (source_object), result, &view, &error);
- priv->pages = NULL;
- priv->changed = FALSE;
- priv->needs_send = FALSE;
- priv->existing_org = FALSE;
- priv->user_org = FALSE;
- priv->warned = FALSE;
-}
+ if (!success)
+ view = NULL;
+ if (view) {
+ editor->priv->view = view;
+ g_signal_connect (
+ view, "objects_modified",
+ G_CALLBACK (obj_modified_cb), editor);
+ g_signal_connect (
+ view, "objects_removed",
+ G_CALLBACK (obj_removed_cb), editor);
-static gint
-comp_editor_key_press_event (GtkWidget *d, GdkEventKey *e)
-{
- if (e->keyval == GDK_Escape) {
- if (prompt_to_save_changes (COMP_EDITOR (d), TRUE))
- close_dialog (COMP_EDITOR (d));
- return TRUE;
- }
+ e_cal_client_view_start (view, &error);
- if (GTK_WIDGET_CLASS (parent_class)->key_press_event)
- return (* GTK_WIDGET_CLASS (parent_class)->key_press_event) (d, e);
-
- return FALSE;
+ if (error != NULL) {
+ g_warning (
+ "%s: Failed to start view: %s",
+ G_STRFUNC, error->message);
+ g_error_free (error);
+ }
+ } else if (error) {
+ if (!g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_CANCELLED) &&
+ !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning (
+ "%s: Failed to get view: %s",
+ G_STRFUNC, error->message);
+ g_error_free (error);
+ }
}
-/* Destroy handler for the calendar component editor */
static void
-comp_editor_destroy (GtkObject *object)
+listen_for_changes (CompEditor *editor)
{
- CompEditor *editor;
CompEditorPrivate *priv;
- GList *l;
+ const gchar *uid = NULL;
- editor = COMP_EDITOR (object);
priv = editor->priv;
- gtk_signal_disconnect_by_data (GTK_OBJECT (priv->client), editor);
+ /* Discard change listener */
+ if (priv->view_cancellable) {
+ g_cancellable_cancel (priv->view_cancellable);
+ g_object_unref (priv->view_cancellable);
+ priv->view_cancellable = NULL;
+ }
- /* We want to destroy the pages after the widgets get destroyed,
- since they have lots of signal handlers connected to the widgets
- with the pages as the data. */
- for (l = priv->pages; l != NULL; l = l->next)
- gtk_object_unref (GTK_OBJECT (l->data));
+ if (priv->view) {
+ g_signal_handlers_disconnect_matched (
+ priv->view, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, editor);
- if (priv->comp) {
- gtk_object_unref (GTK_OBJECT (priv->comp));
- priv->comp = NULL;
+ g_object_unref (priv->view);
+ priv->view = NULL;
+ }
+
+ /* Listen for changes */
+ if (priv->comp)
+ e_cal_component_get_uid (priv->comp, &uid);
+
+ if (uid) {
+ gchar *query;
+
+ priv->view_cancellable = g_cancellable_new ();
+ query = g_strdup_printf ("(uid? \"%s\")", uid);
+ e_cal_client_get_view (
+ priv->source_client,
+ query, priv->view_cancellable,
+ changes_view_ready_cb, editor);
+ g_free (query);
}
+}
+
+static void
+send_timezone (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ icaltimezone *zone = value;
+ CompEditor *editor = user_data;
+ GError *error = NULL;
- g_free (priv);
- editor->priv = NULL;
+ e_cal_client_add_timezone_sync (editor->priv->cal_client, zone, NULL, &error);
- if (GTK_OBJECT_CLASS (parent_class)->destroy)
- (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+ if (error != NULL) {
+ g_warning (
+ "%s: Failed to add timezone: %s",
+ G_STRFUNC, error->message);
+ g_error_free (error);
+ }
}
static gboolean
save_comp (CompEditor *editor)
{
CompEditorPrivate *priv;
- CalComponent *clone;
+ CompEditorFlags flags;
+ ECalComponent *clone;
+ ESourceRegistry *registry;
+ EShell *shell;
GList *l;
- CalClientResult result;
+ gboolean result;
+ GError *error = NULL;
+ GHashTable *timezones;
+ const gchar *orig_uid = NULL;
+ gchar *orig_uid_copy;
+ icalcomponent *icalcomp;
priv = editor->priv;
if (!priv->changed)
return TRUE;
- clone = cal_component_clone (priv->comp);
+ flags = comp_editor_get_flags (editor);
+ shell = comp_editor_get_shell (editor);
+
+ registry = e_shell_get_registry (shell);
+
+ /* Stop listening because we are about to change things */
+ if (priv->view) {
+ g_signal_handlers_disconnect_matched (
+ priv->view,
+ G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL,
+ editor);
+
+ g_object_unref (priv->view);
+ priv->view = NULL;
+ }
+
+ /* Update on the server */
+ timezones = g_hash_table_new (g_str_hash, g_str_equal);
+
+ clone = e_cal_component_clone (priv->comp);
+ comp_editor_copy_new_attendees (clone, priv->comp);
for (l = priv->pages; l != NULL; l = l->next) {
- if (!comp_editor_page_fill_component (l->data, clone)) {
- gtk_object_unref (GTK_OBJECT (clone));
+ if (IS_COMP_EDITOR_PAGE (l->data) &&
+ !comp_editor_page_fill_component (l->data, clone)) {
+ g_object_unref (clone);
+ g_hash_table_destroy (timezones);
comp_editor_show_page (editor, COMP_EDITOR_PAGE (l->data));
return FALSE;
}
+
+ /* retrieve all timezones */
+ if (IS_COMP_EDITOR_PAGE (l->data))
+ comp_editor_page_fill_timezones (l->data, timezones);
}
-
+
/* If we are not the organizer, we don't update the sequence number */
- if (!cal_component_has_organizer (clone) || itip_organizer_is_user (clone))
- cal_component_commit_sequence (clone);
+ if (!e_cal_component_has_organizer (clone) ||
+ itip_organizer_is_user (registry, clone, priv->cal_client) ||
+ itip_sentby_is_user (registry, clone, priv->cal_client))
+ e_cal_component_commit_sequence (clone);
else
- cal_component_abort_sequence (clone);
+ e_cal_component_abort_sequence (clone);
- gtk_object_unref (GTK_OBJECT (priv->comp));
+ g_object_unref (priv->comp);
priv->comp = clone;
- priv->updating = TRUE;
+ e_cal_component_get_uid (priv->comp, &orig_uid);
+ /* Make a copy of it, because call of e_cal_create_object()
+ * rewrites the internal uid. */
+ orig_uid_copy = g_strdup (orig_uid);
+
+ /* send timezones */
+ g_hash_table_foreach (timezones, (GHFunc) send_timezone, editor);
+ g_hash_table_destroy (timezones);
+
+ /* Attachments*/
+
+ e_cal_component_set_attachment_list (
+ priv->comp, get_attachment_list (editor));
+ icalcomp = e_cal_component_get_icalcomponent (priv->comp);
+ /* send the component to the server */
+ if (!cal_comp_is_on_server (priv->comp, priv->cal_client)) {
+ gchar *uid = NULL;
+ result = e_cal_client_create_object_sync (
+ priv->cal_client, icalcomp, &uid, NULL, &error);
+ if (result) {
+ icalcomponent_set_uid (icalcomp, uid);
+ g_free (uid);
+ g_signal_emit_by_name (editor, "object_created");
+ }
+ } else {
+ gboolean has_recurrences;
- result = cal_client_update_object (priv->client, priv->comp);
- if (result != CAL_CLIENT_RESULT_SUCCESS) {
- GtkWidget *dlg;
- char *msg;
+ has_recurrences =
+ e_cal_component_has_recurrences (priv->comp);
- switch (result) {
- case CAL_CLIENT_RESULT_INVALID_OBJECT :
- msg = g_strdup (_("Could not update invalid object"));
- break;
- case CAL_CLIENT_RESULT_NOT_FOUND :
- msg = g_strdup (_("Object not found, not updated"));
- break;
- case CAL_CLIENT_RESULT_PERMISSION_DENIED :
- msg = g_strdup (_("You don't have permissions to update this object"));
- break;
- default :
- msg = g_strdup (_("Could not update object"));
- break;
+ if (has_recurrences && priv->mod == CALOBJ_MOD_ALL)
+ comp_util_sanitize_recurrence_master (
+ priv->comp, priv->cal_client);
+
+ if (priv->mod == CALOBJ_MOD_THIS) {
+ e_cal_component_set_rdate_list (priv->comp, NULL);
+ e_cal_component_set_rrule_list (priv->comp, NULL);
+ e_cal_component_set_exdate_list (priv->comp, NULL);
+ e_cal_component_set_exrule_list (priv->comp, NULL);
+ }
+ result = e_cal_client_modify_object_sync (
+ priv->cal_client, icalcomp, priv->mod, NULL, &error);
+
+ if (priv->mod == CALOBJ_MOD_THIS) {
+ if (result && ((flags & COMP_EDITOR_DELEGATE) ||
+ !e_cal_component_has_organizer (clone) ||
+ itip_organizer_is_user (registry, clone, priv->cal_client) ||
+ itip_sentby_is_user (registry, clone, priv->cal_client)))
+ e_cal_component_commit_sequence (clone);
+ else
+ e_cal_component_abort_sequence (clone);
+ }
+ }
+
+ /* If the delay delivery is set, the items will not be created in
+ * the server immediately, so we need not show them in the view.
+ * They will appear as soon as the server creates it after the
+ * delay period. */
+ if (result && e_cal_component_has_attendees (priv->comp)) {
+ gboolean delay_set = FALSE;
+ icalproperty *icalprop;
+ icalprop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY);
+ while (icalprop) {
+ const gchar *x_name;
+
+ x_name = icalproperty_get_x_name (icalprop);
+ if (!strcmp (x_name, "X-EVOLUTION-OPTIONS-DELAY")) {
+ delay_set = TRUE;
+ break;
+ }
+
+ icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY);
+ }
+ if (delay_set) {
+ g_free (orig_uid_copy);
+ return TRUE;
}
+ }
+
+ if (!result) {
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (
+ NULL, 0,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ "%s", (error != NULL) ? error->message :
+ _("Could not update object"));
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
- dlg = gnome_error_dialog (msg);
- gnome_dialog_run_and_close (GNOME_DIALOG (dlg));
- g_free (msg);
+ if (error)
+ g_error_free (error);
+
+ g_free (orig_uid_copy);
return FALSE;
} else {
- priv->changed = FALSE;
+ if (priv->source_client &&
+ !e_source_equal (e_client_get_source (E_CLIENT (priv->cal_client)),
+ e_client_get_source (E_CLIENT (priv->source_client))) &&
+ cal_comp_is_on_server (priv->comp, priv->source_client)) {
+ /* Comp found a new home. Remove it from old one. */
+ GError *error = NULL;
+
+ if (e_cal_component_is_instance (priv->comp) ||
+ e_cal_component_has_recurrences (priv->comp))
+ e_cal_client_remove_object_sync (
+ priv->source_client, orig_uid_copy,
+ NULL, CALOBJ_MOD_ALL, NULL, &error);
+ else
+ e_cal_client_remove_object_sync (
+ priv->source_client,
+ orig_uid_copy, NULL, CALOBJ_MOD_THIS, NULL, &error);
+
+ if (error != NULL) {
+ g_warning (
+ "%s: Failed to remove object: %s",
+ G_STRFUNC, error->message);
+ g_error_free (error);
+ }
+
+ /* Let priv->source_client point to new home,
+ * so we can move it again this session. */
+ g_object_unref (priv->source_client);
+ priv->source_client = g_object_ref (priv->cal_client);
+
+ listen_for_changes (editor);
+ }
+
+ comp_editor_set_changed (editor, FALSE);
+ priv->saved = TRUE;
}
- priv->updating = FALSE;
+ g_free (orig_uid_copy);
return TRUE;
}
@@ -371,144 +671,2055 @@ static gboolean
save_comp_with_send (CompEditor *editor)
{
CompEditorPrivate *priv;
- gboolean send;
+ CompEditorFlags flags;
+ ESourceRegistry *registry;
+ EShell *shell;
+ gboolean send, delegated, only_new_attendees = FALSE;
+ gboolean delegate;
+ gboolean strip_alarms = TRUE;
priv = editor->priv;
+ flags = comp_editor_get_flags (editor);
+ shell = comp_editor_get_shell (editor);
+
+ registry = e_shell_get_registry (shell);
+
send = priv->changed && priv->needs_send;
+ delegate = flags & COMP_EDITOR_DELEGATE;
+
+ if (delegate) {
+ icalcomponent *icalcomp = e_cal_component_get_icalcomponent (priv->comp);
+ icalproperty *icalprop;
+
+ icalprop = icalproperty_new_x ("1");
+ icalproperty_set_x_name (icalprop, "X-EVOLUTION-DELEGATED");
+ icalcomponent_add_property (icalcomp, icalprop);
+ }
if (!save_comp (editor))
return FALSE;
- if (send && send_component_dialog (priv->comp, !priv->existing_org)) {
- if (itip_organizer_is_user (priv->comp))
- return comp_editor_send_comp (editor, CAL_COMPONENT_METHOD_REQUEST);
- else
- return comp_editor_send_comp (editor, CAL_COMPONENT_METHOD_REPLY);
- }
+ delegated = delegate && !e_cal_client_check_save_schedules (priv->cal_client);
+ if (delegated || (send && send_component_dialog (
+ (GtkWindow *) editor, priv->cal_client, priv->comp,
+ !priv->existing_org, &strip_alarms, !priv->existing_org ?
+ NULL : &only_new_attendees))) {
+ if (delegated)
+ only_new_attendees = FALSE;
+
+ comp_editor_set_flags (
+ editor, (comp_editor_get_flags (editor) &
+ (~COMP_EDITOR_SEND_TO_NEW_ATTENDEES_ONLY)) |
+ (only_new_attendees ?
+ COMP_EDITOR_SEND_TO_NEW_ATTENDEES_ONLY : 0));
+
+ if ((itip_organizer_is_user (registry, priv->comp, priv->cal_client) ||
+ itip_sentby_is_user (registry, priv->comp, priv->cal_client))) {
+ if (e_cal_component_get_vtype (priv->comp) == E_CAL_COMPONENT_JOURNAL)
+ return comp_editor_send_comp (
+ editor, E_CAL_COMPONENT_METHOD_PUBLISH,
+ strip_alarms);
+ else
+ return comp_editor_send_comp (
+ editor, E_CAL_COMPONENT_METHOD_REQUEST,
+ strip_alarms);
+ } else {
+ if (!comp_editor_send_comp (
+ editor, E_CAL_COMPONENT_METHOD_REQUEST,
+ strip_alarms))
+ return FALSE;
+
+ if (delegate)
+ return comp_editor_send_comp (
+ editor, E_CAL_COMPONENT_METHOD_REPLY,
+ strip_alarms);
+ }
+ }
return TRUE;
}
static void
-delete_comp (CompEditor *editor)
+update_window_border (CompEditor *editor,
+ const gchar *description)
+{
+ const gchar *icon_name;
+ const gchar *format;
+ gchar *title;
+
+ if (editor->priv->comp == NULL) {
+ title = g_strdup (_("Edit Appointment"));
+ icon_name = "x-office-calendar";
+ goto exit;
+
+ } else switch (e_cal_component_get_vtype (editor->priv->comp)) {
+ case E_CAL_COMPONENT_EVENT:
+ if (editor->priv->is_group_item)
+ format = _("Meeting - %s");
+ else
+ format = _("Appointment - %s");
+ icon_name = "appointment-new";
+ break;
+
+ case E_CAL_COMPONENT_TODO:
+ if (editor->priv->is_group_item)
+ format = _("Assigned Task - %s");
+ else
+ format = _("Task - %s");
+ icon_name = "stock_task";
+ break;
+
+ case E_CAL_COMPONENT_JOURNAL:
+ format = _("Memo - %s");
+ icon_name = "stock_insert-note";
+ break;
+
+ default:
+ g_return_if_reached ();
+ }
+
+ if (description == NULL || *description == '\0') {
+ ECalComponentText text;
+
+ e_cal_component_get_summary (editor->priv->comp, &text);
+ description = text.value;
+ }
+
+ if (description == NULL || *description == '\0')
+ description = _("No Summary");
+
+ title = g_strdup_printf (format, description);
+
+exit:
+ gtk_window_set_icon_name (GTK_WINDOW (editor), icon_name);
+ gtk_window_set_title (GTK_WINDOW (editor), title);
+
+ g_free (title);
+}
+
+static void
+action_attach_cb (GtkAction *action,
+ CompEditor *editor)
+{
+ EAttachmentStore *store;
+ EAttachmentView *view;
+
+ view = E_ATTACHMENT_VIEW (editor->priv->attachment_view);
+ store = e_attachment_view_get_store (view);
+
+ e_attachment_store_run_load_dialog (store, GTK_WINDOW (editor));
+}
+
+static void
+action_classification_cb (GtkRadioAction *action,
+ GtkRadioAction *current,
+ CompEditor *editor)
+{
+ comp_editor_set_changed (editor, TRUE);
+}
+
+static void
+action_close_cb (GtkAction *action,
+ CompEditor *editor)
+{
+ commit_all_fields (editor);
+
+ if (prompt_and_save_changes (editor, TRUE))
+ close_dialog (editor);
+}
+
+static void
+action_help_cb (GtkAction *action,
+ CompEditor *editor)
+{
+ comp_editor_show_help (editor);
+}
+
+static void
+action_print_cb (GtkAction *action,
+ CompEditor *editor)
+{
+ CompEditorPrivate *priv = editor->priv;
+ ECalComponent *comp;
+ GList *l;
+ icalcomponent *component;
+ icalcomponent *clone;
+ icaltimezone *zone;
+ gboolean use_24_hour_format;
+
+ comp = e_cal_component_new ();
+ component = e_cal_component_get_icalcomponent (priv->comp);
+ clone = icalcomponent_new_clone (component);
+ e_cal_component_set_icalcomponent (comp, clone);
+
+ for (l = priv->pages; l != NULL; l = l->next)
+ comp_editor_page_fill_component (l->data, comp);
+
+ zone = comp_editor_get_timezone (editor);
+ use_24_hour_format = comp_editor_get_use_24_hour_format (editor);
+
+ print_comp (
+ comp, priv->cal_client, zone, use_24_hour_format,
+ GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG);
+
+ g_object_unref (comp);
+}
+
+static void
+action_print_preview_cb (GtkAction *action,
+ CompEditor *editor)
+{
+ CompEditorPrivate *priv = editor->priv;
+ ECalComponent *comp;
+ GList *l;
+ icalcomponent *component;
+ icalcomponent *clone;
+ icaltimezone *zone;
+ gboolean use_24_hour_format;
+
+ comp = e_cal_component_new ();
+ component = e_cal_component_get_icalcomponent (priv->comp);
+ clone = icalcomponent_new_clone (component);
+ e_cal_component_set_icalcomponent (comp, clone);
+
+ for (l = priv->pages; l != NULL; l = l->next)
+ comp_editor_page_fill_component (l->data, comp);
+
+ zone = comp_editor_get_timezone (editor);
+ use_24_hour_format = comp_editor_get_use_24_hour_format (editor);
+
+ print_comp (
+ comp, priv->cal_client, zone, use_24_hour_format,
+ GTK_PRINT_OPERATION_ACTION_PREVIEW);
+
+ g_object_unref (comp);
+}
+
+static gboolean
+remove_event_dialog (ECalClient *client,
+ ECalComponent *comp,
+ GtkWindow *parent)
+{
+ GtkWidget *dialog;
+ gboolean ret;
+
+ g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), TRUE);
+
+ dialog = gtk_message_dialog_new (
+ parent, 0, GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_YES_NO, "%s", _("Keep original item?"));
+ gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
+ ret = gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_YES;
+ gtk_widget_destroy (dialog);
+
+ return ret;
+}
+
+static void
+save_and_close_editor (CompEditor *editor,
+ gboolean can_close)
+{
+ CompEditorPrivate *priv = editor->priv;
+ EAttachmentStore *store;
+ EAttachmentView *view;
+ ECalComponentText text;
+ gboolean delegated = FALSE;
+ gboolean correct = FALSE;
+ ECalComponent *comp;
+ const gchar *uid = NULL;
+
+ view = E_ATTACHMENT_VIEW (priv->attachment_view);
+ store = e_attachment_view_get_store (view);
+
+ if (e_attachment_store_get_num_loading (store) > 0) {
+ gboolean response = 1;
+ /*FIXME: Cannot use mail functions from calendar!!!! */
+#if 0
+ ECalComponentVType vtype = e_cal_component_get_vtype (editor->priv->comp);
+
+ if (vtype == E_CAL_COMPONENT_EVENT)
+ response = em_utils_prompt_user (
+ (GtkWindow *) widget,
+ NULL,
+ "calendar:ask-send-event-pending-download",
+ NULL);
+ else
+ response = em_utils_prompt_user (
+ (GtkWindow *) widget,
+ NULL,
+ "calendar:ask-send-task-pending-download",
+ NULL);
+#endif
+ if (!response)
+ return;
+ }
+
+ if (e_client_is_readonly (E_CLIENT (priv->cal_client))) {
+ e_alert_submit (
+ E_ALERT_SINK (editor),
+ "calendar:prompt-read-only-cal-editor",
+ e_source_get_display_name (
+ e_client_get_source (E_CLIENT (priv->cal_client))),
+ NULL);
+ return;
+ }
+
+ if ((comp_editor_get_flags (editor) & COMP_EDITOR_IS_ASSIGNED) != 0
+ && e_cal_component_get_vtype (priv->comp) == E_CAL_COMPONENT_TODO
+ && e_client_check_capability (E_CLIENT (priv->cal_client), CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT)) {
+ e_alert_submit (
+ E_ALERT_SINK (editor),
+ "calendar:prompt-no-task-assignment-editor",
+ e_source_get_display_name (
+ e_client_get_source (E_CLIENT (priv->cal_client))),
+ NULL);
+ return;
+ }
+
+ commit_all_fields (editor);
+ if (e_cal_component_has_recurrences (priv->comp)) {
+ if (!recur_component_dialog (
+ priv->cal_client, priv->comp, &priv->mod,
+ GTK_WINDOW (editor), delegated))
+ return;
+ } else if (e_cal_component_is_instance (priv->comp))
+ priv->mod = CALOBJ_MOD_THIS;
+
+ comp = comp_editor_get_current_comp (editor, &correct);
+ e_cal_component_get_summary (comp, &text);
+ g_object_unref (comp);
+
+ if (!correct)
+ return;
+
+ if (!text.value)
+ if (!send_component_prompt_subject (
+ (GtkWindow *) editor, priv->cal_client, priv->comp))
+ return;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (editor), FALSE);
+
+ if (save_comp_with_send (editor)) {
+ CompEditorFlags flags;
+ gboolean delegate;
+
+ flags = comp_editor_get_flags (editor);
+ delegate = flags & COMP_EDITOR_DELEGATE;
+
+ if (delegate && !remove_event_dialog (
+ priv->cal_client, priv->comp, GTK_WINDOW (editor))) {
+ GError *error = NULL;
+
+ e_cal_component_get_uid (priv->comp, &uid);
+
+ if (e_cal_component_is_instance (priv->comp) ||
+ e_cal_component_has_recurrences (priv->comp)) {
+ gchar *rid;
+ rid = e_cal_component_get_recurid_as_string (priv->comp);
+ e_cal_client_remove_object_sync (
+ priv->cal_client, uid, rid,
+ priv->mod, NULL, &error);
+ g_free (rid);
+ } else
+ e_cal_client_remove_object_sync (
+ priv->cal_client, uid, NULL,
+ CALOBJ_MOD_THIS, NULL, &error);
+
+ g_clear_error (&error);
+ }
+ } else
+ correct = FALSE;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (editor), TRUE);
+
+ if (correct) {
+ if (can_close)
+ close_dialog (editor);
+ else {
+ ECalComponent *comp;
+ ECalClientSourceType source_type;
+ icalcomponent *icalcomp = NULL;
+ const gchar *uid = NULL;
+ gchar *rid = NULL;
+ GError *error = NULL;
+
+ comp_editor_set_changed (editor, FALSE);
+
+ /*
+ * A server can modify the event on save. Considering this, it is needed to fetch the updated
+ * version of the event from server, updating the component, then user can keep editing the
+ * event
+ */
+ e_cal_component_get_uid (priv->comp, &uid);
+ rid = e_cal_component_get_recurid_as_string (priv->comp);
+
+ source_type = e_cal_client_get_source_type (priv->cal_client);
+ if (!e_cal_client_get_object_sync (priv->cal_client, uid, rid, &icalcomp, NULL, &error)) {
+ if (error != NULL) {
+ switch (source_type) {
+ case (E_CAL_CLIENT_SOURCE_TYPE_TASKS):
+ g_warning ("Unable to retrieve saved component from the task list, returned error was: %s", error->message);
+ break;
+ case (E_CAL_CLIENT_SOURCE_TYPE_MEMOS):
+ g_warning ("Unable to retrieve saved component from the memo list, returned error was: %s", error->message);
+ break;
+ case (E_CAL_CLIENT_SOURCE_TYPE_EVENTS):
+ default:
+ g_warning ("Unable to retrieve saved component from the calendar, returned error was: %s", error->message);
+ break;
+ }
+ g_clear_error (&error);
+ } else {
+ switch (source_type) {
+ case (E_CAL_CLIENT_SOURCE_TYPE_TASKS):
+ g_warning ("Unable to retrieve saved component from the task list");
+ break;
+ case (E_CAL_CLIENT_SOURCE_TYPE_MEMOS):
+ g_warning ("Unable to retrieve saved component from the memo list");
+ break;
+ case (E_CAL_CLIENT_SOURCE_TYPE_EVENTS):
+ default:
+ g_warning ("Unable to retrieve saved component from the calendar");
+ break;
+ }
+ }
+ e_notice (
+ GTK_WINDOW (editor),
+ GTK_MESSAGE_ERROR,
+ _("Unable to synchronize with the server"));
+ } else {
+ comp = e_cal_component_new ();
+ if (e_cal_component_set_icalcomponent (comp, icalcomp)) {
+ gboolean has_recurrences;
+
+ has_recurrences = e_cal_component_has_recurrences (comp);
+
+ if (has_recurrences && priv->mod == CALOBJ_MOD_ALL)
+ comp_util_sanitize_recurrence_master (comp, priv->cal_client);
+
+ comp_editor_edit_comp (editor, comp);
+ } else {
+ switch (source_type) {
+ case (E_CAL_CLIENT_SOURCE_TYPE_TASKS):
+ g_warning ("Unable to update the editor with the retrieved component from the task list");
+ break;
+ case (E_CAL_CLIENT_SOURCE_TYPE_MEMOS):
+ g_warning ("Unable to update the editor with the retrieved component from the memo list");
+ break;
+ case (E_CAL_CLIENT_SOURCE_TYPE_EVENTS):
+ default:
+ g_warning ("Unable to update the editor with the retrieved component from the calendar");
+ break;
+ }
+ e_notice (
+ GTK_WINDOW (editor),
+ GTK_MESSAGE_ERROR,
+ _("Unable to synchronize with the server"));
+ icalcomponent_free (icalcomp);
+ }
+ g_object_unref (comp);
+ }
+ g_free (rid);
+ }
+ }
+}
+
+static void
+action_save_cb (GtkAction *action,
+ CompEditor *editor)
+{
+ save_and_close_editor (editor, FALSE);
+}
+
+static void
+action_save_and_close_cb (GtkAction *action,
+ CompEditor *editor)
+{
+ save_and_close_editor (editor, TRUE);
+}
+
+static void
+action_view_categories_cb (GtkToggleAction *action,
+ CompEditor *editor)
+{
+ CompEditorClass *class;
+ gboolean active;
+
+ class = COMP_EDITOR_GET_CLASS (editor);
+ active = gtk_toggle_action_get_active (action);
+
+ if (class->show_categories != NULL)
+ class->show_categories (editor, active);
+}
+
+static void
+action_view_role_cb (GtkToggleAction *action,
+ CompEditor *editor)
+{
+ CompEditorClass *class;
+ gboolean active;
+
+ class = COMP_EDITOR_GET_CLASS (editor);
+ active = gtk_toggle_action_get_active (action);
+
+ if (class->show_role != NULL)
+ class->show_role (editor, active);
+}
+
+static void
+action_view_rsvp_cb (GtkToggleAction *action,
+ CompEditor *editor)
+{
+ CompEditorClass *class;
+ gboolean active;
+
+ class = COMP_EDITOR_GET_CLASS (editor);
+ active = gtk_toggle_action_get_active (action);
+
+ if (class->show_rsvp != NULL)
+ class->show_rsvp (editor, active);
+}
+
+static void
+action_view_status_cb (GtkToggleAction *action,
+ CompEditor *editor)
+{
+ CompEditorClass *class;
+ gboolean active;
+
+ class = COMP_EDITOR_GET_CLASS (editor);
+ active = gtk_toggle_action_get_active (action);
+
+ if (class->show_status != NULL)
+ class->show_status (editor, active);
+}
+
+static void
+action_view_time_zone_cb (GtkToggleAction *action,
+ CompEditor *editor)
+{
+ CompEditorClass *class;
+ gboolean active;
+
+ class = COMP_EDITOR_GET_CLASS (editor);
+ active = gtk_toggle_action_get_active (action);
+
+ if (class->show_time_zone != NULL)
+ class->show_time_zone (editor, active);
+}
+
+static void
+action_view_type_cb (GtkToggleAction *action,
+ CompEditor *editor)
+{
+ CompEditorClass *class;
+ gboolean active;
+
+ class = COMP_EDITOR_GET_CLASS (editor);
+ active = gtk_toggle_action_get_active (action);
+
+ if (class->show_type != NULL)
+ class->show_type (editor, active);
+}
+
+static GtkActionEntry core_entries[] = {
+
+ { "close",
+ GTK_STOCK_CLOSE,
+ NULL,
+ NULL,
+ N_("Close the current window"),
+ G_CALLBACK (action_close_cb) },
+
+ { "copy-clipboard",
+ GTK_STOCK_COPY,
+ NULL,
+ NULL,
+ N_("Copy the selection"),
+ NULL }, /* Handled by EFocusTracker */
+
+ { "cut-clipboard",
+ GTK_STOCK_CUT,
+ NULL,
+ NULL,
+ N_("Cut the selection"),
+ NULL }, /* Handled by EFocusTracker */
+
+ { "delete-selection",
+ GTK_STOCK_DELETE,
+ NULL,
+ NULL,
+ N_("Delete the selection"),
+ NULL }, /* Handled by EFocusTracker */
+
+ { "help",
+ GTK_STOCK_HELP,
+ NULL,
+ NULL,
+ N_("View help"),
+ G_CALLBACK (action_help_cb) },
+
+ { "paste-clipboard",
+ GTK_STOCK_PASTE,
+ NULL,
+ NULL,
+ N_("Paste the clipboard"),
+ NULL }, /* Handled by EFocusTracker */
+
+ { "print",
+ GTK_STOCK_PRINT,
+ NULL,
+ "<Control>p",
+ NULL,
+ G_CALLBACK (action_print_cb) },
+
+ { "print-preview",
+ GTK_STOCK_PRINT_PREVIEW,
+ NULL,
+ NULL,
+ NULL,
+ G_CALLBACK (action_print_preview_cb) },
+
+ { "save",
+ GTK_STOCK_SAVE,
+ NULL,
+ NULL,
+ N_("Save current changes"),
+ G_CALLBACK (action_save_cb) },
+
+ { "save-and-close",
+ NULL,
+ N_("Save and Close"),
+ NULL,
+ N_("Save current changes and close editor"),
+ G_CALLBACK (action_save_and_close_cb) },
+
+ { "select-all",
+ GTK_STOCK_SELECT_ALL,
+ NULL,
+ "<Control>a",
+ N_("Select all text"),
+ NULL }, /* Handled by EFocusTracker */
+
+ /* Menus */
+
+ { "classification-menu",
+ NULL,
+ N_("_Classification"),
+ NULL,
+ NULL,
+ NULL },
+
+ { "edit-menu",
+ NULL,
+ N_("_Edit"),
+ NULL,
+ NULL,
+ NULL },
+
+ { "file-menu",
+ NULL,
+ N_("_File"),
+ NULL,
+ NULL,
+ NULL },
+
+ { "help-menu",
+ NULL,
+ N_("_Help"),
+ NULL,
+ NULL,
+ NULL },
+
+ { "insert-menu",
+ NULL,
+ N_("_Insert"),
+ NULL,
+ NULL,
+ NULL },
+
+ { "options-menu",
+ NULL,
+ N_("_Options"),
+ NULL,
+ NULL,
+ NULL },
+
+ { "view-menu",
+ NULL,
+ N_("_View"),
+ NULL,
+ NULL,
+ NULL }
+};
+
+static GtkActionEntry individual_entries[] = {
+
+ { "attach",
+ "mail-attachment",
+ N_("_Attachment..."),
+ "<Control>m",
+ N_("Attach a file"),
+ G_CALLBACK (action_attach_cb) }
+};
+
+static GtkToggleActionEntry core_toggle_entries[] = {
+
+ { "view-categories",
+ NULL,
+ N_("_Categories"),
+ NULL,
+ N_("Toggles whether to display categories"),
+ G_CALLBACK (action_view_categories_cb),
+ FALSE },
+
+ { "view-time-zone",
+ "stock_timezone",
+ N_("Time _Zone"),
+ NULL,
+ N_("Toggles whether the time zone is displayed"),
+ G_CALLBACK (action_view_time_zone_cb),
+ FALSE }
+};
+
+static GtkRadioActionEntry classification_radio_entries[] = {
+
+ { "classify-public",
+ NULL,
+ N_("Pu_blic"),
+ NULL,
+ N_("Classify as public"),
+ E_CAL_COMPONENT_CLASS_PUBLIC },
+
+ { "classify-private",
+ NULL,
+ N_("_Private"),
+ NULL,
+ N_("Classify as private"),
+ E_CAL_COMPONENT_CLASS_PRIVATE },
+
+ { "classify-confidential",
+ NULL,
+ N_("_Confidential"),
+ NULL,
+ N_("Classify as confidential"),
+ E_CAL_COMPONENT_CLASS_CONFIDENTIAL }
+};
+
+static GtkToggleActionEntry coordinated_toggle_entries[] = {
+
+ { "view-role",
+ NULL,
+ N_("R_ole Field"),
+ NULL,
+ N_("Toggles whether the Role field is displayed"),
+ G_CALLBACK (action_view_role_cb),
+ FALSE },
+
+ { "view-rsvp",
+ NULL,
+ N_("_RSVP"),
+ NULL,
+ N_("Toggles whether the RSVP field is displayed"),
+ G_CALLBACK (action_view_rsvp_cb),
+ FALSE },
+
+ { "view-status",
+ NULL,
+ N_("_Status Field"),
+ NULL,
+ N_("Toggles whether the Status field is displayed"),
+ G_CALLBACK (action_view_status_cb),
+ FALSE },
+
+ { "view-type",
+ NULL,
+ N_("_Type Field"),
+ NULL,
+ N_("Toggles whether the Attendee Type is displayed"),
+ G_CALLBACK (action_view_type_cb),
+ FALSE }
+};
+
+static void
+comp_editor_set_shell (CompEditor *editor,
+ EShell *shell)
+{
+ g_return_if_fail (E_IS_SHELL (shell));
+ g_return_if_fail (editor->priv->shell == NULL);
+
+ editor->priv->shell = shell;
+
+ g_object_add_weak_pointer (G_OBJECT (shell), &editor->priv->shell);
+}
+
+static void
+comp_editor_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_CHANGED:
+ comp_editor_set_changed (
+ COMP_EDITOR (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_CLIENT:
+ comp_editor_set_client (
+ COMP_EDITOR (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_FLAGS:
+ comp_editor_set_flags (
+ COMP_EDITOR (object),
+ g_value_get_int (value));
+ return;
+
+ case PROP_SHELL:
+ comp_editor_set_shell (
+ COMP_EDITOR (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_SUMMARY:
+ comp_editor_set_summary (
+ COMP_EDITOR (object),
+ g_value_get_string (value));
+ return;
+
+ case PROP_TIMEZONE:
+ comp_editor_set_timezone (
+ COMP_EDITOR (object),
+ g_value_get_pointer (value));
+ return;
+
+ case PROP_USE_24_HOUR_FORMAT:
+ comp_editor_set_use_24_hour_format (
+ COMP_EDITOR (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_WEEK_START_DAY:
+ comp_editor_set_week_start_day (
+ COMP_EDITOR (object),
+ g_value_get_enum (value));
+ return;
+
+ case PROP_WORK_DAY_END_HOUR:
+ comp_editor_set_work_day_end_hour (
+ COMP_EDITOR (object),
+ g_value_get_int (value));
+ return;
+
+ case PROP_WORK_DAY_END_MINUTE:
+ comp_editor_set_work_day_end_minute (
+ COMP_EDITOR (object),
+ g_value_get_int (value));
+ return;
+
+ case PROP_WORK_DAY_START_HOUR:
+ comp_editor_set_work_day_start_hour (
+ COMP_EDITOR (object),
+ g_value_get_int (value));
+ return;
+
+ case PROP_WORK_DAY_START_MINUTE:
+ comp_editor_set_work_day_start_minute (
+ COMP_EDITOR (object),
+ g_value_get_int (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+comp_editor_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_CHANGED:
+ g_value_set_boolean (
+ value, comp_editor_get_changed (
+ COMP_EDITOR (object)));
+ return;
+
+ case PROP_CLIENT:
+ g_value_set_object (
+ value, comp_editor_get_client (
+ COMP_EDITOR (object)));
+ return;
+
+ case PROP_FLAGS:
+ g_value_set_int (
+ value, comp_editor_get_flags (
+ COMP_EDITOR (object)));
+ return;
+
+ case PROP_FOCUS_TRACKER:
+ g_value_set_object (
+ value, comp_editor_get_focus_tracker (
+ COMP_EDITOR (object)));
+ return;
+
+ case PROP_SHELL:
+ g_value_set_object (
+ value, comp_editor_get_shell (
+ COMP_EDITOR (object)));
+ return;
+
+ case PROP_SUMMARY:
+ g_value_set_string (
+ value, comp_editor_get_summary (
+ COMP_EDITOR (object)));
+ return;
+
+ case PROP_TIMEZONE:
+ g_value_set_pointer (
+ value, comp_editor_get_timezone (
+ COMP_EDITOR (object)));
+ return;
+
+ case PROP_USE_24_HOUR_FORMAT:
+ g_value_set_boolean (
+ value, comp_editor_get_use_24_hour_format (
+ COMP_EDITOR (object)));
+ return;
+
+ case PROP_WEEK_START_DAY:
+ g_value_set_enum (
+ value, comp_editor_get_week_start_day (
+ COMP_EDITOR (object)));
+ return;
+
+ case PROP_WORK_DAY_END_HOUR:
+ g_value_set_int (
+ value, comp_editor_get_work_day_end_hour (
+ COMP_EDITOR (object)));
+ return;
+
+ case PROP_WORK_DAY_END_MINUTE:
+ g_value_set_int (
+ value, comp_editor_get_work_day_end_minute (
+ COMP_EDITOR (object)));
+ return;
+
+ case PROP_WORK_DAY_START_HOUR:
+ g_value_set_int (
+ value, comp_editor_get_work_day_start_hour (
+ COMP_EDITOR (object)));
+ return;
+
+ case PROP_WORK_DAY_START_MINUTE:
+ g_value_set_int (
+ value, comp_editor_get_work_day_start_minute (
+ COMP_EDITOR (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+unref_page_cb (gpointer editor_page,
+ gpointer comp_editor)
+{
+ if (IS_COMP_EDITOR_PAGE (editor_page)) {
+ GtkWidget *page_widget;
+ CompEditorPage *page = COMP_EDITOR_PAGE (editor_page);
+ CompEditor *editor = COMP_EDITOR (comp_editor);
+
+ g_return_if_fail (page != NULL);
+ g_return_if_fail (editor != NULL);
+
+ page_widget = comp_editor_page_get_widget (page);
+ g_signal_handlers_disconnect_matched (
+ page_widget, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, page);
+ }
+
+ g_signal_handlers_disconnect_matched (
+ editor_page, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, comp_editor);
+ g_object_unref (editor_page);
+}
+
+static void
+comp_editor_dispose (GObject *object)
{
CompEditorPrivate *priv;
- const char *uid;
- priv = editor->priv;
+ priv = COMP_EDITOR_GET_PRIVATE (object);
- cal_component_get_uid (priv->comp, &uid);
- priv->updating = TRUE;
- cal_client_remove_object (priv->client, uid);
- priv->updating = FALSE;
- close_dialog (editor);
+ if (priv->shell != NULL) {
+ g_object_remove_weak_pointer (
+ G_OBJECT (priv->shell), &priv->shell);
+ priv->shell = NULL;
+ }
+
+ if (priv->focus_tracker != NULL) {
+ g_object_unref (priv->focus_tracker);
+ priv->focus_tracker = NULL;
+ }
+
+ if (priv->window_group != NULL) {
+ g_object_unref (priv->window_group);
+ priv->window_group = NULL;
+ }
+
+ if (priv->cal_client) {
+ g_object_unref (priv->cal_client);
+ priv->cal_client = NULL;
+ }
+
+ if (priv->source_client) {
+ g_object_unref (priv->source_client);
+ priv->source_client = NULL;
+ }
+
+ if (priv->view_cancellable) {
+ g_cancellable_cancel (priv->view_cancellable);
+ g_object_unref (priv->view_cancellable);
+ priv->view_cancellable = NULL;
+ }
+
+ if (priv->view) {
+ g_signal_handlers_disconnect_matched (
+ priv->view, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, object);
+ g_object_unref (priv->view);
+ priv->view = NULL;
+ }
+
+ if (priv->attachment_view) {
+ EAttachmentStore *store;
+
+ store = e_attachment_view_get_store (
+ E_ATTACHMENT_VIEW (priv->attachment_view));
+ g_signal_handlers_disconnect_matched (
+ store, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, object);
+ g_object_unref (priv->attachment_view);
+ priv->attachment_view = NULL;
+ }
+
+ /* We want to destroy the pages after the widgets get destroyed,
+ * since they have lots of signal handlers connected to the widgets
+ * with the pages as the data. */
+ g_list_foreach (priv->pages, (GFunc) unref_page_cb, object);
+ g_list_free (priv->pages);
+ priv->pages = NULL;
+
+ if (priv->comp) {
+ g_object_unref (priv->comp);
+ priv->comp = NULL;
+ }
+
+ if (priv->ui_manager != NULL) {
+ g_object_unref (priv->ui_manager);
+ priv->ui_manager = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (comp_editor_parent_class)->dispose (object);
+}
+
+static void
+comp_editor_finalize (GObject *object)
+{
+ CompEditorPrivate *priv;
+
+ priv = COMP_EDITOR_GET_PRIVATE (object);
+
+ g_object_unref (priv->calendar_settings);
+ g_free (priv->summary);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (comp_editor_parent_class)->finalize (object);
+}
+
+static void
+comp_editor_constructed (GObject *object)
+{
+ e_extensible_load_extensions (E_EXTENSIBLE (object));
+
+ /* Chain up to parent's constructed() method. */
+ G_OBJECT_CLASS (comp_editor_parent_class)->constructed (object);
+}
+
+static void
+comp_editor_bind_settings (CompEditor *editor)
+{
+ GtkAction *action;
+
+ g_return_if_fail (editor != NULL);
+
+ action = comp_editor_get_action (editor, "view-categories");
+ g_settings_bind (
+ editor->priv->calendar_settings, "editor-show-categories",
+ action, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ action = comp_editor_get_action (editor, "view-role");
+ g_settings_bind (
+ editor->priv->calendar_settings, "editor-show-role",
+ action, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ action = comp_editor_get_action (editor, "view-rsvp");
+ g_settings_bind (
+ editor->priv->calendar_settings, "editor-show-rsvp",
+ action, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ action = comp_editor_get_action (editor, "view-status");
+ g_settings_bind (
+ editor->priv->calendar_settings, "editor-show-status",
+ action, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ action = comp_editor_get_action (editor, "view-time-zone");
+ g_settings_bind (
+ editor->priv->calendar_settings, "editor-show-timezone",
+ action, "active",
+ G_SETTINGS_BIND_DEFAULT);
+
+ action = comp_editor_get_action (editor, "view-type");
+ g_settings_bind (
+ editor->priv->calendar_settings, "editor-show-type",
+ action, "active",
+ G_SETTINGS_BIND_DEFAULT);
+}
+
+static gboolean
+comp_editor_delete_event (GtkWidget *widget,
+ GdkEventAny *event)
+{
+ CompEditor *editor;
+
+ editor = COMP_EDITOR (widget);
+
+ commit_all_fields (editor);
+
+ if (prompt_and_save_changes (editor, TRUE))
+ close_dialog (editor);
+
+ return TRUE;
+}
+
+static gboolean
+comp_editor_key_press_event (GtkWidget *widget,
+ GdkEventKey *event)
+{
+ CompEditor *editor;
+
+ editor = COMP_EDITOR (widget);
+
+ if (event->keyval == GDK_KEY_Escape) {
+ commit_all_fields (editor);
+
+ if (prompt_and_save_changes (editor, TRUE))
+ close_dialog (editor);
+
+ return TRUE;
+ }
+
+ /* Chain up to parent's key_press_event() method. */
+ return GTK_WIDGET_CLASS (comp_editor_parent_class)->
+ key_press_event (widget, event);
+}
+
+static gboolean
+comp_editor_drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time)
+{
+ CompEditorPrivate *priv;
+ EAttachmentView *view;
+
+ priv = COMP_EDITOR_GET_PRIVATE (widget);
+ view = E_ATTACHMENT_VIEW (priv->attachment_view);
+
+ return e_attachment_view_drag_motion (view, context, x, y, time);
+}
+
+static void
+comp_editor_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection,
+ guint info,
+ guint time)
+{
+ CompEditorPrivate *priv;
+ EAttachmentView *view;
+
+ priv = COMP_EDITOR_GET_PRIVATE (widget);
+ view = E_ATTACHMENT_VIEW (priv->attachment_view);
+
+ /* Forward the data to the attachment view. Note that calling
+ * e_attachment_view_drag_data_received() will not work because
+ * that function only handles the case where all the other drag
+ * handlers have failed. */
+ e_attachment_paned_drag_data_received (
+ E_ATTACHMENT_PANED (view),
+ context, x, y, selection, info, time);
+}
+
+static void
+comp_editor_class_init (CompEditorClass *class)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ g_type_class_add_private (class, sizeof (CompEditorPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = comp_editor_set_property;
+ object_class->get_property = comp_editor_get_property;
+ object_class->dispose = comp_editor_dispose;
+ object_class->finalize = comp_editor_finalize;
+ object_class->constructed = comp_editor_constructed;
+
+ widget_class = GTK_WIDGET_CLASS (class);
+ widget_class->delete_event = comp_editor_delete_event;
+ widget_class->key_press_event = comp_editor_key_press_event;
+ widget_class->drag_motion = comp_editor_drag_motion;
+ widget_class->drag_data_received = comp_editor_drag_data_received;
+
+ class->help_section = "memos-usage";
+ class->edit_comp = real_edit_comp;
+ class->send_comp = real_send_comp;
+ class->object_created = NULL;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_CHANGED,
+ g_param_spec_boolean (
+ "changed",
+ NULL,
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_CLIENT,
+ g_param_spec_object (
+ "client",
+ NULL,
+ NULL,
+ E_TYPE_CAL_CLIENT,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ /* FIXME: Use a proper flags type instead of int. */
+ g_object_class_install_property (
+ object_class,
+ PROP_FLAGS,
+ g_param_spec_int (
+ "flags",
+ NULL,
+ NULL,
+ G_MININT,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_FOCUS_TRACKER,
+ g_param_spec_object (
+ "focus-tracker",
+ NULL,
+ NULL,
+ E_TYPE_FOCUS_TRACKER,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SHELL,
+ g_param_spec_object (
+ "shell",
+ NULL,
+ NULL,
+ E_TYPE_SHELL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SUMMARY,
+ g_param_spec_string (
+ "summary",
+ NULL,
+ NULL,
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_TIMEZONE,
+ g_param_spec_pointer (
+ "timezone",
+ "Time Zone",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_USE_24_HOUR_FORMAT,
+ g_param_spec_boolean (
+ "use-24-hour-format",
+ "Use 24-hour Format",
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_WEEK_START_DAY,
+ g_param_spec_enum (
+ "week-start-day",
+ "Week Start Day",
+ NULL,
+ E_TYPE_DATE_WEEKDAY,
+ G_DATE_MONDAY,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_WORK_DAY_END_HOUR,
+ g_param_spec_int (
+ "work-day-end-hour",
+ "Work Day End Hour",
+ NULL,
+ 0,
+ 23,
+ 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_WORK_DAY_END_MINUTE,
+ g_param_spec_int (
+ "work-day-end-minute",
+ "Work Day End Minute",
+ NULL,
+ 0,
+ 59,
+ 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_WORK_DAY_START_HOUR,
+ g_param_spec_int (
+ "work-day-start-hour",
+ "Work Day Start Hour",
+ NULL,
+ 0,
+ 23,
+ 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_WORK_DAY_START_MINUTE,
+ g_param_spec_int (
+ "work-day-start-minute",
+ "Work Day Start Minute",
+ NULL,
+ 0,
+ 59,
+ 0,
+ G_PARAM_READWRITE));
+
+ signals[OBJECT_CREATED] = g_signal_new (
+ "object_created",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (CompEditorClass, object_created),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[COMP_CLOSED] = g_signal_new (
+ "comp_closed",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (CompEditorClass, comp_closed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+}
+
+static void
+comp_editor_init (CompEditor *editor)
+{
+ CompEditorPrivate *priv;
+ EAttachmentView *view;
+ EAttachmentStore *store;
+ EFocusTracker *focus_tracker;
+ GdkDragAction drag_actions;
+ GtkTargetList *target_list;
+ GtkTargetEntry *targets;
+ GtkActionGroup *action_group;
+ GtkActionGroup *action_group_2;
+ GtkAction *action;
+ GtkWidget *container;
+ GtkWidget *widget;
+ GtkWindow *window;
+ EShell *shell;
+ gboolean express_mode;
+ gint n_targets;
+ GError *error = NULL;
+
+ /* FIXME We already have a 'shell' property. Move stuff
+ * that depends on it to a constructed() method. */
+ shell = e_shell_get_default ();
+ express_mode = e_shell_get_express_mode (shell);
+
+ editor->priv = priv = COMP_EDITOR_GET_PRIVATE (editor);
+
+ g_object_weak_ref (
+ G_OBJECT (editor), (GWeakNotify)
+ comp_editor_weak_notify_cb, NULL);
+
+ active_editors = g_list_prepend (active_editors, editor);
+
+ priv->calendar_settings = g_settings_new ("org.gnome.evolution.calendar");
+
+ /* Each editor window gets its own window group. */
+ window = GTK_WINDOW (editor);
+ priv->window_group = gtk_window_group_new ();
+ gtk_window_group_add_window (priv->window_group, window);
+
+ priv->pages = NULL;
+ priv->changed = FALSE;
+ priv->needs_send = FALSE;
+ priv->mod = CALOBJ_MOD_ALL;
+ priv->existing_org = FALSE;
+ priv->user_org = FALSE;
+ priv->warned = FALSE;
+ priv->is_group_item = FALSE;
+ priv->saved = FALSE;
+
+ priv->ui_manager = gtk_ui_manager_new ();
+
+ gtk_window_add_accel_group (
+ GTK_WINDOW (editor),
+ gtk_ui_manager_get_accel_group (priv->ui_manager));
+
+ /* Setup Action Groups */
+
+ action_group = gtk_action_group_new ("core");
+ gtk_action_group_set_translation_domain (
+ action_group, GETTEXT_PACKAGE);
+ gtk_action_group_add_actions (
+ action_group, core_entries,
+ G_N_ELEMENTS (core_entries), editor);
+ gtk_action_group_add_toggle_actions (
+ action_group, core_toggle_entries,
+ G_N_ELEMENTS (core_toggle_entries), editor);
+ gtk_ui_manager_insert_action_group (
+ priv->ui_manager, action_group, 0);
+ g_object_unref (action_group);
+
+ action = gtk_action_group_get_action (action_group, "save-and-close");
+ if (action) {
+ GtkAction *save_action;
+ GIcon *icon;
+ GIcon *emblemed_icon;
+ GEmblem *emblem;
+
+ icon = g_themed_icon_new (GTK_STOCK_CLOSE);
+ emblemed_icon = g_themed_icon_new (GTK_STOCK_SAVE);
+ emblem = g_emblem_new (emblemed_icon);
+ g_object_unref (emblemed_icon);
+
+ emblemed_icon = g_emblemed_icon_new (icon, emblem);
+ g_object_unref (emblem);
+ g_object_unref (icon);
+
+ gtk_action_set_gicon (action, emblemed_icon);
+
+ g_object_unref (emblemed_icon);
+
+ save_action = gtk_action_group_get_action (action_group, "save");
+ g_object_bind_property (
+ save_action, "sensitive",
+ action, "sensitive",
+ G_BINDING_SYNC_CREATE);
+ }
+
+ action_group = gtk_action_group_new ("individual");
+ gtk_action_group_set_translation_domain (
+ action_group, GETTEXT_PACKAGE);
+ gtk_action_group_add_actions (
+ action_group, individual_entries,
+ G_N_ELEMENTS (individual_entries), editor);
+ gtk_action_group_add_radio_actions (
+ action_group, classification_radio_entries,
+ G_N_ELEMENTS (classification_radio_entries),
+ E_CAL_COMPONENT_CLASS_PUBLIC,
+ G_CALLBACK (action_classification_cb), editor);
+ gtk_ui_manager_insert_action_group (
+ priv->ui_manager, action_group, 0);
+ g_object_unref (action_group);
+
+ action_group = gtk_action_group_new ("editable");
+ gtk_action_group_set_translation_domain (
+ action_group, GETTEXT_PACKAGE);
+ gtk_ui_manager_insert_action_group (
+ priv->ui_manager, action_group, 0);
+ g_object_unref (action_group);
+
+ action_group = gtk_action_group_new ("coordinated");
+ gtk_action_group_set_translation_domain (
+ action_group, GETTEXT_PACKAGE);
+ gtk_action_group_add_toggle_actions (
+ action_group, coordinated_toggle_entries,
+ G_N_ELEMENTS (coordinated_toggle_entries), editor);
+ gtk_ui_manager_insert_action_group (
+ priv->ui_manager, action_group, 0);
+ g_object_unref (action_group);
+
+ /* Configure an EFocusTracker to manage selection actions. */
+
+ focus_tracker = e_focus_tracker_new (GTK_WINDOW (editor));
+
+ action = comp_editor_get_action (editor, "cut-clipboard");
+ e_focus_tracker_set_cut_clipboard_action (focus_tracker, action);
+
+ action = comp_editor_get_action (editor, "copy-clipboard");
+ e_focus_tracker_set_copy_clipboard_action (focus_tracker, action);
+
+ action = comp_editor_get_action (editor, "paste-clipboard");
+ e_focus_tracker_set_paste_clipboard_action (focus_tracker, action);
+
+ action = comp_editor_get_action (editor, "delete-selection");
+ e_focus_tracker_set_delete_selection_action (focus_tracker, action);
+
+ action = comp_editor_get_action (editor, "select-all");
+ e_focus_tracker_set_select_all_action (focus_tracker, action);
+
+ priv->focus_tracker = focus_tracker;
+
+ /* Fine Tuning */
+
+ action = comp_editor_get_action (editor, "attach");
+ g_object_set (action, "short-label", _("Attach"), NULL);
+
+ /* Desensitize the "save" action. */
+ action = comp_editor_get_action (editor, "save");
+ gtk_action_set_sensitive (action, FALSE);
+
+ gtk_ui_manager_add_ui_from_string (priv->ui_manager, ui, -1, &error);
+ if (error != NULL) {
+ g_warning ("%s: %s", G_STRFUNC, error->message);
+ g_error_free (error);
+ }
+
+ /* Setup Widgets */
+
+ container = GTK_WIDGET (editor);
+
+ widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_container_add (GTK_CONTAINER (container), widget);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = comp_editor_get_managed_widget (editor, "/main-menu");
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_set_visible (widget, TRUE);
+
+ widget = comp_editor_get_managed_widget (editor, "/main-toolbar");
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ gtk_style_context_add_class (
+ gtk_widget_get_style_context (widget),
+ GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
+
+ widget = e_attachment_paned_new ();
+ e_attachment_paned_set_resize_toplevel (
+ E_ATTACHMENT_PANED (widget), TRUE);
+ gtk_container_set_border_width (GTK_CONTAINER (widget), 6);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ priv->attachment_view = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ if (express_mode) {
+ widget = e_attachment_paned_get_view_combo (
+ E_ATTACHMENT_PANED (widget));
+ gtk_widget_hide (widget);
+ }
+
+ container = e_attachment_paned_get_content_area (
+ E_ATTACHMENT_PANED (priv->attachment_view));
+
+ widget = gtk_notebook_new ();
+ gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), express_mode);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ priv->notebook = GTK_NOTEBOOK (widget);
+ gtk_widget_show (widget);
+
+ /* Drag-and-Drop Support */
+
+ view = E_ATTACHMENT_VIEW (priv->attachment_view);
+ target_list = e_attachment_view_get_target_list (view);
+ drag_actions = e_attachment_view_get_drag_actions (view);
+
+ targets = gtk_target_table_new_from_list (target_list, &n_targets);
+
+ gtk_drag_dest_set (
+ GTK_WIDGET (editor), GTK_DEST_DEFAULT_ALL,
+ targets, n_targets, drag_actions);
+
+ gtk_target_table_free (targets, n_targets);
+
+ gtk_window_set_type_hint (
+ GTK_WINDOW (editor), GDK_WINDOW_TYPE_HINT_NORMAL);
+
+ action_group = comp_editor_get_action_group (editor, "individual");
+ action_group_2 = e_attachment_view_get_action_group (view, "editable");
+
+ g_object_bind_property (
+ action_group, "sensitive",
+ action_group_2, "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ /* Listen for attachment store changes. */
+
+ store = e_attachment_view_get_store (view);
+
+ g_signal_connect_swapped (
+ store, "row-deleted",
+ G_CALLBACK (attachment_store_changed_cb), editor);
+
+ g_signal_connect_swapped (
+ store, "row-inserted",
+ G_CALLBACK (attachment_store_changed_cb), editor);
+
+ comp_editor_bind_settings (editor);
+
+ gtk_application_add_window (
+ GTK_APPLICATION (shell), GTK_WINDOW (editor));
}
static gboolean
-prompt_to_save_changes (CompEditor *editor, gboolean send)
+prompt_and_save_changes (CompEditor *editor,
+ gboolean send)
{
CompEditorPrivate *priv;
+ gboolean correct = FALSE;
+ ECalComponent *comp;
+ ECalComponentText text;
priv = editor->priv;
if (!priv->changed)
return TRUE;
- switch (save_component_dialog (GTK_WINDOW (editor))) {
- case 0: /* Save */
+ switch (save_component_dialog (GTK_WINDOW (editor), priv->comp)) {
+ case GTK_RESPONSE_YES: /* Save */
+ if (e_client_is_readonly (E_CLIENT (priv->cal_client))) {
+ e_alert_submit (
+ E_ALERT_SINK (editor),
+ "calendar:prompt-read-only-cal-editor",
+ e_source_get_display_name (
+ e_client_get_source (E_CLIENT (priv->cal_client))),
+ NULL);
+ /* don't discard changes when selected readonly calendar */
+ return FALSE;
+ }
+
+ if ((comp_editor_get_flags (editor) & COMP_EDITOR_IS_ASSIGNED) != 0
+ && e_cal_component_get_vtype (priv->comp) == E_CAL_COMPONENT_TODO
+ && e_client_check_capability (E_CLIENT (priv->cal_client), CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT)) {
+ e_alert_submit (
+ E_ALERT_SINK (editor),
+ "calendar:prompt-no-task-assignment-editor",
+ e_source_get_display_name (
+ e_client_get_source (E_CLIENT (priv->cal_client))),
+ NULL);
+ return FALSE;
+ }
+
+ comp = comp_editor_get_current_comp (editor, &correct);
+ e_cal_component_get_summary (comp, &text);
+ g_object_unref (comp);
+
+ if (!correct)
+ return FALSE;
+
+ if (!text.value)
+ if (!send_component_prompt_subject (
+ (GtkWindow *) editor, priv->cal_client, priv->comp))
+ return FALSE;
+
+ if (e_cal_component_is_instance (priv->comp))
+ if (!recur_component_dialog (
+ priv->cal_client, priv->comp, &priv->mod,
+ GTK_WINDOW (editor), FALSE))
+ return FALSE;
+
if (send && save_comp_with_send (editor))
return TRUE;
else if (!send && save_comp (editor))
return TRUE;
else
return FALSE;
- case 1: /* Discard */
+ case GTK_RESPONSE_NO: /* Discard */
return TRUE;
- case 2: /* Cancel */
+ case GTK_RESPONSE_CANCEL: /* Cancel */
default:
return FALSE;
}
}
-/* This sets the focus to the toplevel, so any field being edited is committed.
- FIXME: In future we may also want to check some of the fields are valid,
- e.g. the EDateEdit fields. */
+/* Menu callbacks */
+
static void
-commit_all_fields (CompEditor *editor)
+comp_editor_show_help (CompEditor *editor)
{
- CompEditorPrivate *priv;
+ CompEditorClass *class;
- priv = editor->priv;
+ class = COMP_EDITOR_GET_CLASS (editor);
+ g_return_if_fail (class->help_section != NULL);
- gtk_window_set_focus (GTK_WINDOW (editor), NULL);
+ e_display_help (GTK_WINDOW (editor), class->help_section);
}
/* Closes the dialog box and emits the appropriate signals */
static void
close_dialog (CompEditor *editor)
{
- CompEditorPrivate *priv;
+ CompEditorPrivate *priv = editor->priv;
- priv = editor->priv;
+ g_signal_emit_by_name (editor, "comp_closed", priv->saved);
+
+ /* FIXME Unfortunately we do this here because otherwise corba
+ * calls happen during destruction and we might get a change
+ * notification back when we are in an inconsistent state */
+ if (priv->view)
+ g_signal_handlers_disconnect_matched (
+ priv->view, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, editor);
- gtk_object_destroy (GTK_OBJECT (editor));
+ gtk_widget_destroy (GTK_WIDGET (editor));
}
-
+static gint
+comp_editor_compare (CompEditor *editor_a,
+ const gchar *uid_b)
+{
+ const gchar *uid_a = NULL;
+
+ e_cal_component_get_uid (editor_a->priv->comp, &uid_a);
+
+ return g_strcmp0 (uid_a, uid_b);
+}
void
-comp_editor_set_existing_org (CompEditor *editor, gboolean existing_org)
+comp_editor_set_existing_org (CompEditor *editor,
+ gboolean existing_org)
{
- CompEditorPrivate *priv;
-
- g_return_if_fail (editor != NULL);
g_return_if_fail (IS_COMP_EDITOR (editor));
- priv = editor->priv;
-
- priv->existing_org = existing_org;
+ editor->priv->existing_org = existing_org;
}
gboolean
comp_editor_get_existing_org (CompEditor *editor)
{
- CompEditorPrivate *priv;
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), FALSE);
+
+ return editor->priv->existing_org;
+}
+
+void
+comp_editor_set_user_org (CompEditor *editor,
+ gboolean user_org)
+{
+ g_return_if_fail (IS_COMP_EDITOR (editor));
- g_return_val_if_fail (editor != NULL, FALSE);
+ editor->priv->user_org = user_org;
+}
+
+gboolean
+comp_editor_get_user_org (CompEditor *editor)
+{
g_return_val_if_fail (IS_COMP_EDITOR (editor), FALSE);
- priv = editor->priv;
+ return editor->priv->user_org;
+}
- return priv->existing_org;
+void
+comp_editor_set_group_item (CompEditor *editor,
+ gboolean group_item)
+{
+ g_return_if_fail (IS_COMP_EDITOR (editor));
+
+ editor->priv->is_group_item = group_item;
+}
+
+gboolean
+comp_editor_get_group_item (CompEditor *editor)
+{
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), FALSE);
+
+ return editor->priv->is_group_item;
}
void
-comp_editor_set_user_org (CompEditor *editor, gboolean user_org)
+comp_editor_set_classification (CompEditor *editor,
+ ECalComponentClassification classification)
{
- CompEditorPrivate *priv;
+ GtkAction *action;
- g_return_if_fail (editor != NULL);
g_return_if_fail (IS_COMP_EDITOR (editor));
- priv = editor->priv;
+ switch (classification) {
+ case E_CAL_COMPONENT_CLASS_PUBLIC:
+ case E_CAL_COMPONENT_CLASS_PRIVATE:
+ case E_CAL_COMPONENT_CLASS_CONFIDENTIAL:
+ break;
+ default:
+ classification = E_CAL_COMPONENT_CLASS_PUBLIC;
+ break;
+ }
- priv->user_org = user_org;
+ action = comp_editor_get_action (editor, "classify-public");
+ gtk_radio_action_set_current_value (
+ GTK_RADIO_ACTION (action), classification);
}
-gboolean
-comp_editor_get_user_org (CompEditor *editor)
+ECalComponentClassification
+comp_editor_get_classification (CompEditor *editor)
{
- CompEditorPrivate *priv;
+ GtkAction *action;
+
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), 0);
+
+ action = comp_editor_get_action (editor, "classify-public");
+ return gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action));
+}
+
+EShell *
+comp_editor_get_shell (CompEditor *editor)
+{
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), NULL);
+
+ return editor->priv->shell;
+}
+
+void
+comp_editor_set_summary (CompEditor *editor,
+ const gchar *summary)
+{
+ gboolean show_warning;
+
+ g_return_if_fail (IS_COMP_EDITOR (editor));
+
+ if (g_strcmp0 (editor->priv->summary, summary) == 0)
+ return;
+
+ g_free (editor->priv->summary);
+ editor->priv->summary = g_strdup (summary);
+
+ show_warning =
+ !editor->priv->warned &&
+ !(editor->priv->flags & COMP_EDITOR_DELEGATE) &&
+ editor->priv->existing_org &&
+ !editor->priv->user_org && !(editor->priv->flags & COMP_EDITOR_NEW_ITEM);
+
+ if (show_warning) {
+ e_notice (
+ editor->priv->notebook, GTK_MESSAGE_INFO,
+ _("Changes made to this item may be "
+ "discarded if an update arrives"));
+ editor->priv->warned = TRUE;
+ }
+
+ update_window_border (editor, summary);
+
+ g_object_notify (G_OBJECT (editor), "summary");
+}
+
+const gchar *
+comp_editor_get_summary (CompEditor *editor)
+{
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), NULL);
+
+ return editor->priv->summary;
+}
+
+icaltimezone *
+comp_editor_get_timezone (CompEditor *editor)
+{
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), NULL);
+
+ return editor->priv->zone;
+}
+
+void
+comp_editor_set_timezone (CompEditor *editor,
+ icaltimezone *zone)
+{
+ g_return_if_fail (IS_COMP_EDITOR (editor));
+
+ if (editor->priv->zone == zone)
+ return;
+
+ editor->priv->zone = zone;
- g_return_val_if_fail (editor != NULL, FALSE);
+ g_object_notify (G_OBJECT (editor), "timezone");
+}
+
+gboolean
+comp_editor_get_use_24_hour_format (CompEditor *editor)
+{
g_return_val_if_fail (IS_COMP_EDITOR (editor), FALSE);
- priv = editor->priv;
+ return editor->priv->use_24_hour_format;
+}
+
+void
+comp_editor_set_use_24_hour_format (CompEditor *editor,
+ gboolean use_24_hour_format)
+{
+ g_return_if_fail (IS_COMP_EDITOR (editor));
+
+ if (editor->priv->use_24_hour_format == use_24_hour_format)
+ return;
+
+ editor->priv->use_24_hour_format = use_24_hour_format;
+
+ g_object_notify (G_OBJECT (editor), "use-24-hour-format");
+}
+
+GDateWeekday
+comp_editor_get_week_start_day (CompEditor *editor)
+{
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), 0);
- return priv->user_org;
+ return editor->priv->week_start_day;
}
+void
+comp_editor_set_week_start_day (CompEditor *editor,
+ GDateWeekday week_start_day)
+{
+ g_return_if_fail (IS_COMP_EDITOR (editor));
+ g_return_if_fail (g_date_valid_weekday (week_start_day));
+
+ if (week_start_day == editor->priv->week_start_day)
+ return;
+
+ editor->priv->week_start_day = week_start_day;
+
+ g_object_notify (G_OBJECT (editor), "week-start-day");
+}
+
+gint
+comp_editor_get_work_day_end_hour (CompEditor *editor)
+{
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), 0);
+
+ return editor->priv->work_day_end_hour;
+}
+
+void
+comp_editor_set_work_day_end_hour (CompEditor *editor,
+ gint work_day_end_hour)
+{
+ g_return_if_fail (IS_COMP_EDITOR (editor));
+
+ if (editor->priv->work_day_end_hour == work_day_end_hour)
+ return;
+
+ editor->priv->work_day_end_hour = work_day_end_hour;
+
+ g_object_notify (G_OBJECT (editor), "work-day-end-hour");
+}
+
+gint
+comp_editor_get_work_day_end_minute (CompEditor *editor)
+{
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), 0);
+
+ return editor->priv->work_day_end_minute;
+}
+
+void
+comp_editor_set_work_day_end_minute (CompEditor *editor,
+ gint work_day_end_minute)
+{
+ g_return_if_fail (IS_COMP_EDITOR (editor));
+
+ if (editor->priv->work_day_end_minute == work_day_end_minute)
+ return;
+
+ editor->priv->work_day_end_minute = work_day_end_minute;
+
+ g_object_notify (G_OBJECT (editor), "work-day-end-minute");
+}
+
+gint
+comp_editor_get_work_day_start_hour (CompEditor *editor)
+{
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), 0);
+
+ return editor->priv->work_day_start_hour;
+}
+
+void
+comp_editor_set_work_day_start_hour (CompEditor *editor,
+ gint work_day_start_hour)
+{
+ g_return_if_fail (IS_COMP_EDITOR (editor));
+
+ if (editor->priv->work_day_start_hour == work_day_start_hour)
+ return;
+
+ editor->priv->work_day_start_hour = work_day_start_hour;
+
+ g_object_notify (G_OBJECT (editor), "work-day-start-hour");
+}
+
+gint
+comp_editor_get_work_day_start_minute (CompEditor *editor)
+{
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), 0);
+
+ return editor->priv->work_day_start_minute;
+}
+
+void
+comp_editor_set_work_day_start_minute (CompEditor *editor,
+ gint work_day_start_minute)
+{
+ g_return_if_fail (IS_COMP_EDITOR (editor));
+
+ if (editor->priv->work_day_start_minute == work_day_start_minute)
+ return;
+
+ editor->priv->work_day_start_minute = work_day_start_minute;
+
+ g_object_notify (G_OBJECT (editor), "work-day-start-minute");
+}
/**
* comp_editor_set_changed:
@@ -518,13 +2729,41 @@ comp_editor_get_user_org (CompEditor *editor)
* Set the dialog changed state to the given value
**/
void
-comp_editor_set_changed (CompEditor *editor, gboolean changed)
+comp_editor_set_changed (CompEditor *editor,
+ gboolean changed)
{
- CompEditorPrivate *priv;
+ GtkAction *action;
+ gboolean show_warning;
- priv = editor->priv;
+ g_return_if_fail (IS_COMP_EDITOR (editor));
- priv->changed = changed;
+ /* always process below changes, because other parts of
+ * the editor listen for 'changed' notifications to update
+ * its widgets, thus do it even the value actually didn't change
+ */
+ if (editor->priv->changed != changed) {
+ editor->priv->changed = changed;
+
+ action = comp_editor_get_action (editor, "save");
+ g_return_if_fail (action != NULL);
+ gtk_action_set_sensitive (action, changed);
+ }
+
+ show_warning =
+ changed && !editor->priv->warned &&
+ !(editor->priv->flags & COMP_EDITOR_DELEGATE) &&
+ editor->priv->existing_org && !editor->priv->user_org
+ && !(editor->priv->flags & COMP_EDITOR_NEW_ITEM);
+
+ if (show_warning) {
+ e_notice (
+ editor->priv->notebook, GTK_MESSAGE_INFO,
+ _("Changes made to this item may be "
+ "discarded if an update arrives"));
+ editor->priv->warned = TRUE;
+ }
+
+ g_object_notify (G_OBJECT (editor), "changed");
}
/**
@@ -539,11 +2778,107 @@ comp_editor_set_changed (CompEditor *editor, gboolean changed)
gboolean
comp_editor_get_changed (CompEditor *editor)
{
- CompEditorPrivate *priv;
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), FALSE);
- priv = editor->priv;
+ return editor->priv->changed;
+}
+
+EFocusTracker *
+comp_editor_get_focus_tracker (CompEditor *editor)
+{
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), NULL);
+
+ return editor->priv->focus_tracker;
+}
+
+void
+comp_editor_set_flags (CompEditor *editor,
+ CompEditorFlags flags)
+{
+ g_return_if_fail (IS_COMP_EDITOR (editor));
+
+ if (editor->priv->flags == flags)
+ return;
+
+ editor->priv->flags = flags;
+ editor->priv->user_org = flags & COMP_EDITOR_USER_ORG;
+
+ g_object_notify (G_OBJECT (editor), "flags");
+}
+
+CompEditorFlags
+comp_editor_get_flags (CompEditor *editor)
+{
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), 0);
+
+ return editor->priv->flags;
+}
+
+GtkUIManager *
+comp_editor_get_ui_manager (CompEditor *editor)
+{
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), NULL);
- return priv->changed;
+ return editor->priv->ui_manager;
+}
+
+GtkAction *
+comp_editor_get_action (CompEditor *editor,
+ const gchar *action_name)
+{
+ GtkUIManager *ui_manager;
+
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), NULL);
+ g_return_val_if_fail (action_name != NULL, NULL);
+
+ ui_manager = comp_editor_get_ui_manager (editor);
+
+ return e_lookup_action (ui_manager, action_name);
+}
+
+GtkActionGroup *
+comp_editor_get_action_group (CompEditor *editor,
+ const gchar *group_name)
+{
+ GtkUIManager *ui_manager;
+
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), NULL);
+ g_return_val_if_fail (group_name != NULL, NULL);
+
+ ui_manager = comp_editor_get_ui_manager (editor);
+
+ return e_lookup_action_group (ui_manager, group_name);
+}
+
+GtkWidget *
+comp_editor_get_managed_widget (CompEditor *editor,
+ const gchar *widget_path)
+{
+ GtkUIManager *ui_manager;
+ GtkWidget *widget;
+
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), NULL);
+ g_return_val_if_fail (widget_path != NULL, NULL);
+
+ ui_manager = comp_editor_get_ui_manager (editor);
+ widget = gtk_ui_manager_get_widget (ui_manager, widget_path);
+ g_return_val_if_fail (widget != NULL, NULL);
+
+ return widget;
+}
+
+CompEditor *
+comp_editor_find_instance (const gchar *uid)
+{
+ GList *link;
+
+ g_return_val_if_fail (uid != NULL, NULL);
+
+ link = g_list_find_custom (
+ active_editors, uid,
+ (GCompareFunc) comp_editor_compare);
+
+ return (link != NULL) ? link->data : NULL;
}
/**
@@ -554,13 +2889,12 @@ comp_editor_get_changed (CompEditor *editor)
* Set the dialog needs send state to the given value
**/
void
-comp_editor_set_needs_send (CompEditor *editor, gboolean needs_send)
+comp_editor_set_needs_send (CompEditor *editor,
+ gboolean needs_send)
{
- CompEditorPrivate *priv;
-
- priv = editor->priv;
+ g_return_if_fail (IS_COMP_EDITOR (editor));
- priv->needs_send = needs_send;
+ editor->priv->needs_send = needs_send;
}
/**
@@ -575,15 +2909,14 @@ comp_editor_set_needs_send (CompEditor *editor, gboolean needs_send)
gboolean
comp_editor_get_needs_send (CompEditor *editor)
{
- CompEditorPrivate *priv;
-
- priv = editor->priv;
+ g_return_val_if_fail (IS_COMP_EDITOR (editor), FALSE);
- return priv->needs_send;
+ return editor->priv->needs_send;
}
-static void page_mapped_cb (GtkWidget *page_widget,
- CompEditorPage *page)
+static void
+page_mapped_cb (GtkWidget *page_widget,
+ CompEditorPage *page)
{
GtkWidget *toplevel;
@@ -592,13 +2925,15 @@ static void page_mapped_cb (GtkWidget *page_widget,
return;
if (page->accel_group) {
- gtk_window_add_accel_group (GTK_WINDOW (toplevel),
- page->accel_group);
+ gtk_window_add_accel_group (
+ GTK_WINDOW (toplevel),
+ page->accel_group);
}
}
-static void page_unmapped_cb (GtkWidget *page_widget,
- CompEditorPage *page)
+static void
+page_unmapped_cb (GtkWidget *page_widget,
+ CompEditorPage *page)
{
GtkWidget *toplevel;
@@ -607,72 +2942,127 @@ static void page_unmapped_cb (GtkWidget *page_widget,
return;
if (page->accel_group) {
- gtk_window_remove_accel_group (GTK_WINDOW (toplevel),
- page->accel_group);
+ gtk_window_remove_accel_group (GTK_WINDOW (toplevel), page->accel_group);
+ }
+}
+
+/**
+ * comp_editor_append_widget:
+ * @editor: A component editor
+ * @page: A component editor page
+ * @label: Label of the page. Should be NULL if add is FALSE.
+ * @add: Add's the page into the notebook if TRUE
+ *
+ * Appends a page to the notebook if add is TRUE else
+ * just adds it to the list of pages.
+ **/
+void
+comp_editor_append_widget (CompEditor *editor,
+ GtkWidget *page,
+ const gchar *label,
+ gboolean add)
+{
+ CompEditorPrivate *priv;
+ GtkWidget *label_widget = NULL;
+
+ g_return_if_fail (IS_COMP_EDITOR (editor));
+
+ priv = editor->priv;
+
+ g_object_ref (page);
+
+ if (label)
+ label_widget = gtk_label_new_with_mnemonic (label);
+
+ priv->pages = g_list_append (priv->pages, page);
+
+ if (add) {
+ gtk_notebook_append_page (priv->notebook, page, label_widget);
+ gtk_container_child_set (
+ GTK_CONTAINER (priv->notebook), page,
+ "tab-fill", FALSE, "tab-expand", FALSE, NULL);
}
+
+ /* Listen for when the page is mapped/unmapped so we can
+ * install/uninstall the appropriate GtkAccelGroup.
+ g_signal_connect (
+ page, "map",
+ G_CALLBACK (page_mapped_cb), page);
+ g_signal_connect (
+ page, "unmap",
+ G_CALLBACK (page_unmapped_cb), page);
+ */
+
}
/**
* comp_editor_append_page:
* @editor: A component editor
* @page: A component editor page
- * @label: Label of the page
+ * @label: Label of the page. Should be NULL if add is FALSE.
+ * @add: Add's the page into the notebook if TRUE
*
- * Appends a page to the editor notebook with the given label
+ * Appends a page to the notebook if add is TRUE else
+ * just adds it to the list of pages.
**/
void
comp_editor_append_page (CompEditor *editor,
- CompEditorPage *page,
- const char *label)
+ CompEditorPage *page,
+ const gchar *label,
+ gboolean add)
{
CompEditorPrivate *priv;
GtkWidget *page_widget;
- GtkWidget *label_widget;
+ GtkWidget *label_widget = NULL;
gboolean is_first_page;
- 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));
- g_return_if_fail (label != NULL);
priv = editor->priv;
- gtk_object_ref (GTK_OBJECT (page));
+ g_object_ref (page);
/* If we are editing something, fill the widgets with current info */
if (priv->comp != NULL) {
- CalComponent *comp;
+ ECalComponent *comp;
- comp = comp_editor_get_current_comp (editor);
+ comp = comp_editor_get_current_comp (editor, NULL);
comp_editor_page_fill_widgets (page, comp);
- gtk_object_unref (GTK_OBJECT (comp));
+ g_object_unref (comp);
}
page_widget = comp_editor_page_get_widget (page);
- g_assert (page_widget != NULL);
+ g_return_if_fail (page_widget != NULL);
- label_widget = gtk_label_new (label);
+ if (label)
+ label_widget = gtk_label_new_with_mnemonic (label);
is_first_page = (priv->pages == NULL);
priv->pages = g_list_append (priv->pages, page);
- gtk_notebook_append_page (priv->notebook, page_widget, label_widget);
+
+ if (add) {
+ gtk_notebook_append_page (
+ priv->notebook, page_widget, label_widget);
+ gtk_container_child_set (
+ GTK_CONTAINER (priv->notebook), page_widget,
+ "tab-fill", FALSE, "tab-expand", FALSE, NULL);
+ }
/* Listen for things happening on the page */
- 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);
+ g_signal_connect_swapped (
+ page, "dates_changed",
+ G_CALLBACK (page_dates_changed_cb), editor);
/* Listen for when the page is mapped/unmapped so we can
- install/uninstall the appropriate GtkAccelGroup. */
- gtk_signal_connect (GTK_OBJECT (page_widget), "map",
- GTK_SIGNAL_FUNC (page_mapped_cb), page);
- gtk_signal_connect (GTK_OBJECT (page_widget), "unmap",
- GTK_SIGNAL_FUNC (page_unmapped_cb), page);
+ * install/uninstall the appropriate GtkAccelGroup. */
+ g_signal_connect (
+ page_widget, "map",
+ G_CALLBACK (page_mapped_cb), page);
+ g_signal_connect (
+ page_widget, "unmap",
+ G_CALLBACK (page_unmapped_cb), page);
/* The first page is the main page of the editor, so we ask it to focus
* its main widget.
@@ -689,15 +3079,14 @@ comp_editor_append_page (CompEditor *editor,
* Removes the page from the component editor
**/
void
-comp_editor_remove_page (CompEditor *editor, CompEditorPage *page)
+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;
@@ -706,15 +3095,17 @@ comp_editor_remove_page (CompEditor *editor, CompEditorPage *page)
page_num = gtk_notebook_page_num (priv->notebook, page_widget);
if (page_num == -1)
return;
-
+
/* Disconnect all the signals added in append_page(). */
- gtk_signal_disconnect_by_data (GTK_OBJECT (page), editor);
- gtk_signal_disconnect_by_data (GTK_OBJECT (page_widget), page);
+ g_signal_handlers_disconnect_matched (
+ page, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, editor);
+ g_signal_handlers_disconnect_matched (
+ page_widget, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, page);
gtk_notebook_remove_page (priv->notebook, page_num);
priv->pages = g_list_remove (priv->pages, page);
- gtk_object_unref (GTK_OBJECT (page));
+ g_object_unref (page);
}
/**
@@ -725,259 +3116,412 @@ comp_editor_remove_page (CompEditor *editor, CompEditorPage *page)
*
**/
void
-comp_editor_show_page (CompEditor *editor, CompEditorPage *page)
+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);
+ gtk_notebook_set_current_page (priv->notebook, page_num);
}
/**
- * comp_editor_set_cal_client:
+ * comp_editor_set_client:
* @editor: A component editor
- * @client: The calendar client to use
+ * @cal_client: The calendar client to use
*
* Sets the calendar client used by the editor to update components
**/
void
-comp_editor_set_cal_client (CompEditor *editor, CalClient *client)
+comp_editor_set_client (CompEditor *editor,
+ ECalClient *cal_client)
{
- CompEditorClass *klass;
-
- g_return_if_fail (editor != NULL);
g_return_if_fail (IS_COMP_EDITOR (editor));
+ g_return_if_fail (cal_client == NULL || E_IS_CAL_CLIENT (cal_client));
+
+ if (editor->priv->cal_client == cal_client)
+ return;
+
+ if (cal_client != NULL)
+ g_object_ref (cal_client);
- klass = COMP_EDITOR_CLASS (GTK_OBJECT (editor)->klass);
+ if (editor->priv->cal_client != NULL)
+ g_object_unref (editor->priv->cal_client);
- if (klass->set_cal_client)
- klass->set_cal_client (editor, client);
+ editor->priv->cal_client = cal_client;
+
+ if (editor->priv->source_client == NULL && cal_client != NULL)
+ editor->priv->source_client = g_object_ref (cal_client);
+
+ g_object_notify (G_OBJECT (editor), "client");
}
/**
- * comp_editor_get_cal_client:
+ * comp_editor_get_client:
* @editor: A component editor
*
* Returns the calendar client of the editor
*
* Return value: The calendar client of the editor
**/
-CalClient *
-comp_editor_get_cal_client (CompEditor *editor)
+ECalClient *
+comp_editor_get_client (CompEditor *editor)
{
- CompEditorPrivate *priv;
-
- g_return_val_if_fail (editor != NULL, NULL);
g_return_val_if_fail (IS_COMP_EDITOR (editor), NULL);
- priv = editor->priv;
-
- return priv->client;
+ return editor->priv->cal_client;
}
-/* Creates an appropriate title for the event editor dialog */
-static char *
-make_title_from_comp (CalComponent *comp)
+static void
+attachment_loaded_cb (EAttachment *attachment,
+ GAsyncResult *result,
+ GtkWindow *parent)
{
- char *title;
- const char *type_string;
- CalComponentVType type;
- CalComponentText text;
-
- if (!comp)
- return g_strdup (_("Edit Appointment"));
+ GFileInfo *file_info;
+ const gchar *display_name;
+ const gchar *uid;
+ gchar *new_name;
+
+ /* Prior to 2.27.2, attachment files were named:
+ *
+ * <component-uid> '-' <actual-filename>
+ * -------------------------------------
+ * (one long filename)
+ *
+ * Here we fix the display name if this form is detected so we
+ * don't show the component UID in the user interface. If the
+ * user saves changes in the editor, the attachment will be
+ * written to disk as:
+ *
+ * <component-uid> / <actual-filename>
+ * --------------- -----------------
+ * (directory) (original name)
+ *
+ * So this is a lazy migration from the old form to the new.
+ */
- type = cal_component_get_vtype (comp);
- switch (type) {
- case CAL_COMPONENT_EVENT:
- type_string = _("Appointment - %s");
- break;
- case CAL_COMPONENT_TODO:
- type_string = _("Task - %s");
- break;
- case CAL_COMPONENT_JOURNAL:
- type_string = _("Journal entry - %s");
- break;
- default:
- g_message ("make_title_from_comp(): Cannot handle object of type %d", type);
- return NULL;
+ file_info = e_attachment_ref_file_info (attachment);
+ if (file_info == NULL) {
+ /* failed to load an attachment file */
+ e_attachment_load_handle_error (attachment, result, parent);
+ return;
}
- cal_component_get_summary (comp, &text);
- if (text.value) {
- char *summary;
- summary = e_utf8_to_locale_string (text.value);
- title = g_strdup_printf (type_string, summary);
- g_free (summary);
- } else
- title = g_strdup_printf (type_string, _("No summary"));
-
- return title;
-}
+ display_name = g_file_info_get_display_name (file_info);
+ uid = g_object_get_data (G_OBJECT (attachment), "uid");
-static const char *
-make_icon_from_comp (CalComponent *comp)
-{
- CalComponentVType type;
-
- if (!comp)
- return EVOLUTION_ICONSDIR "/evolution-calendar-mini.png";
-
- type = cal_component_get_vtype (comp);
- switch (type) {
- case CAL_COMPONENT_EVENT:
- return EVOLUTION_ICONSDIR "/buttons/new_appointment.png";
- break;
- case CAL_COMPONENT_TODO:
- return EVOLUTION_ICONSDIR "/buttons/new_task.png";
- break;
- default:
- return EVOLUTION_ICONSDIR "/evolution-calendar-mini.png";
+ if (g_str_has_prefix (display_name, uid)) {
+ new_name = g_strdup (display_name + strlen (uid) + 1);
+ g_file_info_set_display_name (file_info, new_name);
+ g_object_notify (G_OBJECT (attachment), "file-info");
+ g_free (new_name);
}
-}
-/* Sets the event editor's window title from a calendar component */
-static void
-set_title_from_comp (CompEditor *editor)
-{
- CompEditorPrivate *priv;
- char *title;
+ g_object_unref (file_info);
- priv = editor->priv;
- title = make_title_from_comp (priv->comp);
- gtk_window_set_title (GTK_WINDOW (editor), title);
- g_free (title);
+ e_attachment_load_handle_error (attachment, result, parent);
}
static void
-set_icon_from_comp (CompEditor *editor)
+set_attachment_list (CompEditor *editor,
+ GSList *uri_list)
{
- CompEditorPrivate *priv;
- const char *file;
+ EAttachmentStore *store;
+ EAttachmentView *view;
+ const gchar *uid = NULL;
+ GSList *iter;
+
+ view = E_ATTACHMENT_VIEW (editor->priv->attachment_view);
+ store = e_attachment_view_get_store (view);
+
+ if (e_attachment_store_get_num_attachments (store) > 0) {
+ /* To prevent repopulating the
+ * bar due to redraw functions in fill_widget.
+ * Assumes it can be set only once.
+ */
+ return;
+ }
- priv = editor->priv;
- file = make_icon_from_comp (priv->comp);
- gnome_window_icon_set_from_file (GTK_WINDOW (editor), file);
+ /* XXX What an awkward API this is. Takes a return location
+ * for a constant string instead of just returning it. */
+ e_cal_component_get_uid (editor->priv->comp, &uid);
+
+ for (iter = uri_list; iter != NULL; iter = iter->next) {
+ EAttachment *attachment;
+
+ attachment = e_attachment_new_for_uri (iter->data);
+ e_attachment_store_add_attachment (store, attachment);
+ g_object_set_data_full (
+ G_OBJECT (attachment),
+ "uid", g_strdup (uid),
+ (GDestroyNotify) g_free);
+ e_attachment_load_async (
+ attachment, (GAsyncReadyCallback)
+ attachment_loaded_cb, editor);
+ g_object_unref (attachment);
+ }
}
static void
fill_widgets (CompEditor *editor)
{
+ EAttachmentStore *store;
+ EAttachmentView *view;
CompEditorPrivate *priv;
- GList *l;
+ GtkAction *action;
+ GList *iter;
+
+ view = E_ATTACHMENT_VIEW (editor->priv->attachment_view);
+ store = e_attachment_view_get_store (view);
priv = editor->priv;
- for (l = priv->pages; l != NULL; l = l->next)
- comp_editor_page_fill_widgets (l->data, priv->comp);
+ /*Check if attachments are available here and set them*/
+ if (e_cal_component_has_attachments (priv->comp)) {
+ GSList *attachment_list = NULL;
+ e_cal_component_get_attachment_list (priv->comp, &attachment_list);
+ g_signal_handlers_block_by_func (
+ store, G_CALLBACK (attachment_store_changed_cb),
+ editor);
+ set_attachment_list (editor, attachment_list);
+ g_signal_handlers_unblock_by_func (
+ store, G_CALLBACK (attachment_store_changed_cb),
+ editor);
+ g_slist_foreach (attachment_list, (GFunc) g_free, NULL);
+ g_slist_free (attachment_list);
+ }
+
+ action = comp_editor_get_action (editor, "classify-public");
+ g_signal_handlers_block_by_func (
+ action, G_CALLBACK (action_classification_cb), editor);
+
+ for (iter = priv->pages; iter != NULL; iter = iter->next) {
+ if (IS_COMP_EDITOR_PAGE (iter->data))
+ comp_editor_page_fill_widgets (iter->data, priv->comp);
+ }
+
+ g_signal_handlers_unblock_by_func (
+ action, G_CALLBACK (action_classification_cb), editor);
}
static void
-real_set_cal_client (CompEditor *editor, CalClient *client)
+real_edit_comp (CompEditor *editor,
+ ECalComponent *comp)
{
CompEditorPrivate *priv;
- GList *elem;
- g_return_if_fail (editor != NULL);
g_return_if_fail (IS_COMP_EDITOR (editor));
priv = editor->priv;
- if (client == priv->client)
- return;
-
- if (client) {
- g_return_if_fail (IS_CAL_CLIENT (client));
- g_return_if_fail (cal_client_get_load_state (client) ==
- CAL_CLIENT_LOAD_LOADED);
- gtk_object_ref (GTK_OBJECT (client));
+ if (priv->comp) {
+ g_object_unref (priv->comp);
+ priv->comp = NULL;
}
- if (priv->client) {
- gtk_signal_disconnect_by_data (GTK_OBJECT (priv->client),
- editor);
- gtk_object_unref (GTK_OBJECT (priv->client));
+ if (comp) {
+ priv->comp = e_cal_component_clone (comp);
+ comp_editor_copy_new_attendees (priv->comp, comp);
}
- priv->client = client;
+ priv->existing_org = e_cal_component_has_organizer (comp);
+ priv->warned = FALSE;
+
+ update_window_border (editor, NULL);
- /* Pass the client to any pages that need it. */
- for (elem = priv->pages; elem; elem = elem->next)
- comp_editor_page_set_cal_client (elem->data, client);
+ fill_widgets (editor);
- gtk_signal_connect (GTK_OBJECT (priv->client), "obj_updated",
- GTK_SIGNAL_FUNC (obj_updated_cb), editor);
+ comp_editor_set_changed (editor, FALSE);
- gtk_signal_connect (GTK_OBJECT (priv->client), "obj_removed",
- GTK_SIGNAL_FUNC (obj_removed_cb), editor);
+ listen_for_changes (editor);
}
+/* TODO These functions should be available in e-cal-component.c */
static void
-real_edit_comp (CompEditor *editor, CalComponent *comp)
+set_attendees_for_delegation (ECalComponent *comp,
+ const gchar *address,
+ ECalComponentItipMethod method)
{
- CompEditorPrivate *priv;
-
- g_return_if_fail (editor != NULL);
- g_return_if_fail (IS_COMP_EDITOR (editor));
+ icalproperty *prop;
+ icalparameter *param;
+ icalcomponent *icalcomp;
+
+ icalcomp = e_cal_component_get_icalcomponent (comp);
+
+ for (prop = icalcomponent_get_first_property (icalcomp, ICAL_ATTENDEE_PROPERTY);
+ prop;
+ prop = icalcomponent_get_next_property (icalcomp, ICAL_ATTENDEE_PROPERTY)) {
+ const gchar *attendee = icalproperty_get_attendee (prop);
+ const gchar *delfrom = NULL;
+
+ param = icalproperty_get_first_parameter (prop, ICAL_DELEGATEDFROM_PARAMETER);
+ if (param)
+ delfrom = icalparameter_get_delegatedfrom (param);
+ if (!(g_str_equal (itip_strip_mailto (attendee), address) ||
+ ((delfrom && *delfrom) &&
+ g_str_equal (itip_strip_mailto (delfrom), address)))) {
+ icalcomponent_remove_property (icalcomp, prop);
+ }
- priv = editor->priv;
+ }
- if (priv->comp) {
- gtk_object_unref (GTK_OBJECT (priv->comp));
- priv->comp = NULL;
+}
+
+static void
+get_users_from_memo_comp (ECalComponent *comp,
+ GSList **users)
+{
+ icalcomponent *icalcomp;
+ icalproperty *icalprop;
+ const gchar *attendees = NULL;
+ gchar **emails, **iter;
+
+ icalcomp = e_cal_component_get_icalcomponent (comp);
+
+ for (icalprop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY);
+ icalprop != NULL;
+ icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY)) {
+ const gchar *x_name;
+
+ x_name = icalproperty_get_x_name (icalprop);
+
+ if (g_str_equal (x_name, "X-EVOLUTION-RECIPIENTS"))
+ break;
}
- if (comp)
- priv->comp = cal_component_clone (comp);
+ if (icalprop) {
+ attendees = icalproperty_get_x (icalprop);
+ emails = g_strsplit (attendees, ";", -1);
- priv->existing_org = cal_component_has_organizer (comp);
- priv->user_org = itip_organizer_is_user (comp);
- priv->warned = FALSE;
-
- set_title_from_comp (editor);
- set_icon_from_comp (editor);
- fill_widgets (editor);
+ iter = emails;
+ while (*iter) {
+ *users = g_slist_append (*users, g_strdup (*iter));
+ iter++;
+ }
+ g_strfreev (emails);
+ }
}
-
static gboolean
-real_send_comp (CompEditor *editor, CalComponentItipMethod method)
+real_send_comp (CompEditor *editor,
+ ECalComponentItipMethod method,
+ gboolean strip_alarms)
{
CompEditorPrivate *priv;
- CalComponent *tmp_comp;
-
- g_return_val_if_fail (editor != NULL, FALSE);
+ CompEditorFlags flags;
+ EShell *shell;
+ ESourceRegistry *registry;
+ ECalComponent *send_comp = NULL;
+ gchar *address = NULL;
+ GSList *users = NULL;
+
g_return_val_if_fail (IS_COMP_EDITOR (editor), FALSE);
priv = editor->priv;
- if (itip_send_comp (method, priv->comp, priv->client, NULL)) {
- tmp_comp = priv->comp;
- gtk_object_ref (GTK_OBJECT (tmp_comp));
- comp_editor_edit_comp (editor, tmp_comp);
- gtk_object_unref (GTK_OBJECT (tmp_comp));
-
- comp_editor_set_changed (editor, TRUE);
- save_comp (editor);
+ flags = comp_editor_get_flags (editor);
+ shell = comp_editor_get_shell (editor);
- return TRUE;
+ registry = e_shell_get_registry (shell);
+
+ if (priv->mod == CALOBJ_MOD_ALL && e_cal_component_is_instance (priv->comp)) {
+ /* Ensure we send the master object, not the instance only */
+ icalcomponent *icalcomp = NULL;
+ const gchar *uid = NULL;
+
+ e_cal_component_get_uid (priv->comp, &uid);
+ if (e_cal_client_get_object_sync (priv->cal_client, uid, NULL, &icalcomp, NULL, NULL) && icalcomp) {
+ send_comp = e_cal_component_new ();
+ if (!e_cal_component_set_icalcomponent (send_comp, icalcomp)) {
+ icalcomponent_free (icalcomp);
+ g_object_unref (send_comp);
+ send_comp = NULL;
+ }
+ }
+ }
+
+ if (!send_comp)
+ send_comp = e_cal_component_clone (priv->comp);
+
+ comp_editor_copy_new_attendees (send_comp, priv->comp);
+
+ if (e_cal_component_get_vtype (send_comp) == E_CAL_COMPONENT_JOURNAL)
+ get_users_from_memo_comp (send_comp, &users);
+
+ /* The user updates the delegated status to the Organizer,
+ * so remove all other attendees. */
+ if (flags & COMP_EDITOR_DELEGATE) {
+ address = itip_get_comp_attendee (
+ registry, send_comp, priv->cal_client);
+
+ if (address)
+ set_attendees_for_delegation (send_comp, address, method);
+ }
+
+ if (!e_cal_component_has_attachments (priv->comp) ||
+ e_client_check_capability (
+ E_CLIENT (priv->cal_client),
+ CAL_STATIC_CAPABILITY_CREATE_MESSAGES)) {
+ if (itip_send_comp (
+ registry, method, send_comp, priv->cal_client,
+ NULL, NULL, users, strip_alarms,
+ priv->flags & COMP_EDITOR_SEND_TO_NEW_ATTENDEES_ONLY)) {
+ g_object_unref (send_comp);
+ return TRUE;
+ }
+ } else {
+ /* Clone the component with attachments set to CID:... */
+ GSList *attach_list = NULL;
+ GSList *mime_attach_list, *attach;
+
+ /* mime_attach_list is freed by itip_send_comp */
+ mime_attach_list = comp_editor_get_mime_attach_list (editor);
+
+ for (attach = mime_attach_list; attach; attach = attach->next) {
+ struct CalMimeAttach *cma = (struct CalMimeAttach *) attach->data;
+
+ attach_list = g_slist_append (
+ attach_list, g_strconcat (
+ "cid:", cma->content_id, NULL));
+ }
+
+ if (attach_list) {
+ e_cal_component_set_attachment_list (send_comp, attach_list);
+
+ g_slist_foreach (attach_list, (GFunc) g_free, NULL);
+ g_slist_free (attach_list);
+ }
+
+ if (itip_send_comp (
+ registry, method, send_comp, priv->cal_client,
+ NULL, mime_attach_list, users, strip_alarms,
+ priv->flags & COMP_EDITOR_SEND_TO_NEW_ATTENDEES_ONLY)) {
+ gboolean saved = save_comp (editor);
+
+ g_object_unref (send_comp);
+
+ if (!saved)
+ comp_editor_set_changed (editor, TRUE);
+
+ return saved;
+ }
}
+ g_object_unref (send_comp);
+ g_free (address);
comp_editor_set_changed (editor, TRUE);
return FALSE;
-}
+}
/**
* comp_editor_edit_comp:
@@ -987,52 +3531,61 @@ real_send_comp (CompEditor *editor, CalComponentItipMethod method)
* Starts the editor editing the given component
**/
void
-comp_editor_edit_comp (CompEditor *editor, CalComponent *comp)
+comp_editor_edit_comp (CompEditor *editor,
+ ECalComponent *comp)
{
- CompEditorClass *klass;
+ CompEditorClass *class;
- 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));
+ g_return_if_fail (E_IS_CAL_COMPONENT (comp));
- klass = COMP_EDITOR_CLASS (GTK_OBJECT (editor)->klass);
+ class = COMP_EDITOR_GET_CLASS (editor);
- if (klass->edit_comp)
- klass->edit_comp (editor, comp);
+ if (class->edit_comp)
+ class->edit_comp (editor, comp);
}
-CalComponent *
+ECalComponent *
comp_editor_get_comp (CompEditor *editor)
{
- CompEditorPrivate *priv;
-
- g_return_val_if_fail (editor != NULL, NULL);
g_return_val_if_fail (IS_COMP_EDITOR (editor), NULL);
- priv = editor->priv;
-
- return priv->comp;
+ return editor->priv->comp;
}
-CalComponent *
-comp_editor_get_current_comp (CompEditor *editor)
+/**
+ * comp_editor_get_current_comp
+ * @editor: a #CompEditor
+ * @correct: Set this no non-%NULL if you are interested to know if all
+ * pages reported success when filling component.
+ *
+ * Returns: Newly allocated component, should be unref-ed by g_object_unref().
+ **/
+ECalComponent *
+comp_editor_get_current_comp (CompEditor *editor,
+ gboolean *correct)
{
CompEditorPrivate *priv;
- CalComponent *comp;
+ ECalComponent *comp;
GList *l;
+ gboolean all_ok = TRUE;
- 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);
+ comp = e_cal_component_clone (priv->comp);
+ comp_editor_copy_new_attendees (comp, priv->comp);
if (priv->changed) {
- for (l = priv->pages; l != NULL; l = l->next)
- comp_editor_page_fill_component (l->data, comp);
+ for (l = priv->pages; l != NULL; l = l->next) {
+ if (IS_COMP_EDITOR_PAGE (l->data))
+ all_ok = comp_editor_page_fill_component (l->data, comp) && all_ok;
+ }
}
+ if (correct)
+ *correct = all_ok;
+
return comp;
}
@@ -1043,9 +3596,10 @@ comp_editor_get_current_comp (CompEditor *editor)
*
**/
gboolean
-comp_editor_save_comp (CompEditor *editor, gboolean send)
+comp_editor_save_comp (CompEditor *editor,
+ gboolean send)
{
- return prompt_to_save_changes (editor, send);
+ return prompt_and_save_changes (editor, send);
}
/**
@@ -1057,7 +3611,24 @@ comp_editor_save_comp (CompEditor *editor, gboolean send)
void
comp_editor_delete_comp (CompEditor *editor)
{
- delete_comp (editor);
+ CompEditorPrivate *priv;
+ const gchar *uid;
+
+ g_return_if_fail (IS_COMP_EDITOR (editor));
+
+ priv = editor->priv;
+
+ e_cal_component_get_uid (priv->comp, &uid);
+ if (e_cal_component_is_instance (priv->comp) ||
+ e_cal_component_has_recurrences (priv->comp))
+ e_cal_client_remove_object_sync (
+ priv->cal_client, uid, NULL,
+ CALOBJ_MOD_ALL, NULL, NULL);
+ else
+ e_cal_client_remove_object_sync (
+ priv->cal_client, uid, NULL,
+ CALOBJ_MOD_THIS, NULL, NULL);
+ close_dialog (editor);
}
/**
@@ -1068,17 +3639,18 @@ comp_editor_delete_comp (CompEditor *editor)
*
**/
gboolean
-comp_editor_send_comp (CompEditor *editor, CalComponentItipMethod method)
+comp_editor_send_comp (CompEditor *editor,
+ ECalComponentItipMethod method,
+ gboolean strip_alarms)
{
- CompEditorClass *klass;
+ CompEditorClass *class;
- g_return_val_if_fail (editor != NULL, FALSE);
g_return_val_if_fail (IS_COMP_EDITOR (editor), FALSE);
- klass = COMP_EDITOR_CLASS (GTK_OBJECT (editor)->klass);
+ class = COMP_EDITOR_GET_CLASS (editor);
- if (klass->send_comp)
- return klass->send_comp (editor, method);
+ if (class->send_comp)
+ return class->send_comp (editor, method, strip_alarms);
return FALSE;
}
@@ -1087,344 +3659,167 @@ gboolean
comp_editor_close (CompEditor *editor)
{
gboolean close;
-
- g_return_val_if_fail (editor != NULL, FALSE);
+
g_return_val_if_fail (IS_COMP_EDITOR (editor), FALSE);
commit_all_fields (editor);
-
- close = prompt_to_save_changes (editor, TRUE);
+
+ close = prompt_and_save_changes (editor, TRUE);
if (close)
close_dialog (editor);
return close;
}
-/**
- * comp_editor_merge_ui:
- * @editor:
- * @filename:
- * @verbs:
- *
- *
- **/
-void
-comp_editor_merge_ui (CompEditor *editor,
- const char *filename,
- BonoboUIVerb *verbs,
- EPixmap *component_pixmaps)
-{
- CompEditorPrivate *priv;
-
- g_return_if_fail (editor != NULL);
- g_return_if_fail (IS_COMP_EDITOR (editor));
-
- priv = editor->priv;
-
- bonobo_ui_util_set_ui (priv->uic, EVOLUTION_DATADIR, filename, "evolution-calendar");
- bonobo_ui_component_add_verb_list_with_data (priv->uic, verbs, editor);
-
- if (component_pixmaps != NULL)
- e_pixmaps_update (priv->uic, component_pixmaps);
-}
-
-/**
- * comp_editor_set_ui_prop:
- * @editor:
- * @path:
- * @attr:
- * @val:
- *
- *
- **/
-void
-comp_editor_set_ui_prop (CompEditor *editor,
- const char *path,
- const char *attr,
- const char *val)
-{
- CompEditorPrivate *priv;
-
- g_return_if_fail (editor != NULL);
- g_return_if_fail (IS_COMP_EDITOR (editor));
-
- priv = editor->priv;
-
- bonobo_ui_component_set_prop (priv->uic, path, attr, val, NULL);
-}
-
-
-/* Brings attention to a window by raising it and giving it focus */
-static void
-raise_and_focus (GtkWidget *widget)
-{
- g_assert (GTK_WIDGET_REALIZED (widget));
- gdk_window_show (widget->window);
- gtk_widget_grab_focus (widget);
-}
-
-/**
- * comp_editor_focus:
- * @editor: A component editor
- *
- * Brings the editor window to the front and gives it focus
- **/
-void
-comp_editor_focus (CompEditor *editor)
-{
- CompEditorPrivate *priv;
-
- g_return_if_fail (editor != NULL);
- g_return_if_fail (IS_COMP_EDITOR (editor));
-
- priv = editor->priv;
-
- gtk_widget_show (GTK_WIDGET (editor));
- raise_and_focus (GTK_WIDGET (editor));
-}
-
-/* Menu Commands */
-static void
-save_cmd (GtkWidget *widget, gpointer data)
-{
- CompEditor *editor = COMP_EDITOR (data);
-
- commit_all_fields (editor);
-
- save_comp_with_send (editor);
-}
-
-static void
-save_close_cmd (GtkWidget *widget, gpointer data)
-{
- CompEditor *editor = COMP_EDITOR (data);
-
- commit_all_fields (editor);
-
- if (save_comp_with_send (editor))
- close_dialog (editor);
-}
-
-static void
-save_as_cmd (GtkWidget *widget, gpointer data)
-{
- CompEditor *editor = COMP_EDITOR (data);
- CompEditorPrivate *priv;
- char *filename;
- char *ical_string;
- FILE *file;
-
- priv = editor->priv;
-
- commit_all_fields (editor);
-
- filename = e_file_dialog_save (_("Save as..."));
- if (filename == NULL)
- return;
-
- ical_string = cal_client_get_component_as_string (priv->client, priv->comp);
- if (ical_string == NULL) {
- g_warning ("Couldn't convert item to a string");
- return;
- }
-
- file = fopen (filename, "w");
- if (file == NULL) {
- g_warning ("Couldn't save item");
- return;
- }
-
- fprintf (file, ical_string);
- g_free (ical_string);
- fclose (file);
-}
-
-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, FALSE, 1, vtype, GTK_WIDGET (editor))) {
- if (itip_organizer_is_user (priv->comp)
- && cancel_component_dialog (priv->comp, TRUE))
- itip_send_comp (CAL_COMPONENT_METHOD_CANCEL, priv->comp, priv->client, NULL);
-
- delete_comp (editor);
- }
-}
-
-static void
-print_cmd (GtkWidget *widget, gpointer data)
-{
- CompEditor *editor = COMP_EDITOR (data);
- CalComponent *comp;
-
- commit_all_fields (editor);
-
- comp = comp_editor_get_current_comp (editor);
- print_comp (comp, editor->priv->client, FALSE);
- gtk_object_unref (GTK_OBJECT (comp));
-}
-
-static void
-print_preview_cmd (GtkWidget *widget, gpointer data)
-{
- CompEditor *editor = COMP_EDITOR (data);
- CalComponent *comp;
-
- commit_all_fields (editor);
-
- comp = comp_editor_get_current_comp (editor);
- print_comp (comp, editor->priv->client, TRUE);
- gtk_object_unref (GTK_OBJECT (comp));
-}
-
-static void
-print_setup_cmd (GtkWidget *widget, gpointer data)
-{
- CompEditor *editor = COMP_EDITOR (data);
- CompEditorPrivate *priv;
-
- priv = editor->priv;
-
- print_setup ();
-}
-
-static void
-close_cmd (GtkWidget *widget, gpointer data)
-{
- CompEditor *editor = COMP_EDITOR (data);
-
- commit_all_fields (editor);
-
- if (prompt_to_save_changes (editor, TRUE))
- close_dialog (editor);
-}
-
-static void
-page_changed_cb (GtkObject *obj, gpointer data)
+/* Utility function to get the mime-attachment list from the attachment
+ * bar for sending the comp via itip. The list and its contents must
+ * be freed by the caller.
+ */
+GSList *
+comp_editor_get_mime_attach_list (CompEditor *editor)
{
- CompEditor *editor = COMP_EDITOR (data);
- CompEditorPrivate *priv;
+ EAttachmentStore *store;
+ EAttachmentView *view;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ struct CalMimeAttach *cal_mime_attach;
+ GSList *attach_list = NULL;
+ gboolean valid;
+
+ view = E_ATTACHMENT_VIEW (editor->priv->attachment_view);
+ store = e_attachment_view_get_store (view);
+
+ model = GTK_TREE_MODEL (store);
+ valid = gtk_tree_model_get_iter_first (model, &iter);
+
+ while (valid) {
+ EAttachment *attachment;
+ CamelDataWrapper *wrapper;
+ CamelMimePart *mime_part;
+ CamelStream *stream;
+ GByteArray *byte_array;
+ guchar *buffer = NULL;
+ const gchar *description;
+ const gchar *disposition;
+ gint column_id;
+
+ column_id = E_ATTACHMENT_STORE_COLUMN_ATTACHMENT;
+ gtk_tree_model_get (model, &iter, column_id, &attachment, -1);
+ mime_part = e_attachment_ref_mime_part (attachment);
+ g_object_unref (attachment);
+
+ valid = gtk_tree_model_iter_next (model, &iter);
+
+ if (mime_part == NULL)
+ continue;
+
+ cal_mime_attach = g_malloc0 (sizeof (struct CalMimeAttach));
+ wrapper = camel_medium_get_content (CAMEL_MEDIUM (mime_part));
+
+ byte_array = g_byte_array_new ();
+ stream = camel_stream_mem_new_with_byte_array (byte_array);
+
+ camel_data_wrapper_decode_to_stream_sync (
+ wrapper, stream, NULL, NULL);
+ buffer = g_memdup (byte_array->data, byte_array->len);
+
+ camel_mime_part_set_content_id (mime_part, NULL);
+
+ cal_mime_attach->encoded_data = (gchar *) buffer;
+ cal_mime_attach->length = byte_array->len;
+ cal_mime_attach->filename =
+ g_strdup (camel_mime_part_get_filename (mime_part));
+ description = camel_mime_part_get_description (mime_part);
+ if (description == NULL || *description == '\0')
+ description = _("attachment");
+ cal_mime_attach->description = g_strdup (description);
+ cal_mime_attach->content_type = g_strdup (
+ camel_data_wrapper_get_mime_type (wrapper));
+ cal_mime_attach->content_id = g_strdup (
+ camel_mime_part_get_content_id (mime_part));
+
+ disposition = camel_mime_part_get_disposition (mime_part);
+ cal_mime_attach->disposition =
+ (disposition != NULL) &&
+ (g_ascii_strcasecmp (disposition, "inline") == 0);
+
+ attach_list = g_slist_append (attach_list, cal_mime_attach);
+
+ g_object_unref (mime_part);
+ g_object_unref (stream);
- priv = editor->priv;
-
- priv->changed = TRUE;
-
- if (!priv->warned && priv->existing_org && !priv->user_org) {
- e_notice (NULL, GNOME_MESSAGE_BOX_INFO,
- _("Changes made to this item may be discarded if an update arrives via email"));
- priv->warned = TRUE;
}
-
-}
-/* Page signal callbacks */
-static void
-page_summary_changed_cb (GtkObject *obj, const char *summary, gpointer data)
-{
- CompEditor *editor = COMP_EDITOR (data);
- CompEditorPrivate *priv;
- GList *l;
-
- priv = editor->priv;
-
- for (l = priv->pages; l != NULL; l = l->next)
- if (obj != l->data)
- comp_editor_page_set_summary (l->data, summary);
-
- priv->changed = TRUE;
-
- if (!priv->warned && priv->existing_org && !priv->user_org) {
- e_notice (NULL, GNOME_MESSAGE_BOX_INFO,
- _("Changes made to this item may be discarded if an update arrives via email"));
- priv->warned = TRUE;
- }
+ return attach_list;
}
static void
-page_dates_changed_cb (GtkObject *obj,
- CompEditorPageDates *dates,
- gpointer data)
+page_dates_changed_cb (CompEditor *editor,
+ CompEditorPageDates *dates,
+ CompEditorPage *page)
{
- CompEditor *editor = COMP_EDITOR (data);
- CompEditorPrivate *priv;
+ CompEditorPrivate *priv = editor->priv;
GList *l;
- priv = editor->priv;
-
for (l = priv->pages; l != NULL; l = l->next)
- if (obj != l->data)
+ if (page != (CompEditorPage *) l->data && IS_COMP_EDITOR_PAGE (l->data))
comp_editor_page_set_dates (l->data, dates);
- priv->changed = TRUE;
-
- if (!priv->warned && priv->existing_org && !priv->user_org) {
- e_notice (NULL, GNOME_MESSAGE_BOX_INFO,
- _("Changes made to this item may be discarded if an update arrives via email"));
+ if (!priv->warned && priv->existing_org && !priv->user_org &&
+ !(editor->priv->flags & COMP_EDITOR_NEW_ITEM)) {
+ e_notice (
+ priv->notebook, GTK_MESSAGE_INFO,
+ _("Changes made to this item may be discarded "
+ "if an update arrives"));
priv->warned = TRUE;
}
}
static void
-obj_updated_cb (CalClient *client, const char *uid, gpointer data)
+obj_modified_cb (ECalClientView *view,
+ const GSList *objects,
+ CompEditor *editor)
{
- CompEditor *editor = COMP_EDITOR (data);
CompEditorPrivate *priv;
- CalComponent *comp = NULL;
- CalClientGetStatus status;
- const char *edit_uid;
+ ECalComponent *comp = NULL;
priv = editor->priv;
- cal_component_get_uid (priv->comp, &edit_uid);
-
- if (!strcmp (uid, edit_uid) && !priv->updating) {
- if (changed_component_dialog (priv->comp, FALSE, priv->changed)) {
- status = cal_client_get_object (priv->client, uid, &comp);
- if (status == CAL_CLIENT_GET_SUCCESS) {
- comp_editor_edit_comp (editor, comp);
- gtk_object_unref (GTK_OBJECT (comp));
- } else {
- GtkWidget *dlg;
-
- dlg = gnome_error_dialog (_("Unable to obtain current version!"));
- gnome_dialog_run_and_close (GNOME_DIALOG (dlg));
- }
+ /* We queried based on a specific UID so we definitely changed */
+ if (changed_component_dialog (
+ (GtkWindow *) editor, priv->comp, FALSE, priv->changed)) {
+ icalcomponent *icalcomp = icalcomponent_new_clone (objects->data);
+
+ comp = e_cal_component_new ();
+ if (e_cal_component_set_icalcomponent (comp, icalcomp)) {
+ comp_editor_edit_comp (editor, comp);
+ } else {
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (
+ NULL, 0,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ "%s",
+ _("Unable to use current version!"));
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ icalcomponent_free (icalcomp);
}
- }
-}
-
-static void
-obj_removed_cb (CalClient *client, const char *uid, gpointer data)
-{
- CompEditor *editor = COMP_EDITOR (data);
- CompEditorPrivate *priv;
- const char *edit_uid;
- priv = editor->priv;
-
- cal_component_get_uid (priv->comp, &edit_uid);
-
- if (!strcmp (uid, edit_uid) && !priv->updating) {
- if (changed_component_dialog (priv->comp, TRUE, priv->changed))
- close_dialog (editor);
+ g_object_unref (comp);
}
}
-static gint
-delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer data)
+static void
+obj_removed_cb (ECalClientView *view,
+ const GSList *uids,
+ CompEditor *editor)
{
- CompEditor *editor = COMP_EDITOR (data);
+ CompEditorPrivate *priv = editor->priv;
- if (prompt_to_save_changes (editor, TRUE))
+ if (changed_component_dialog (
+ GTK_WINDOW (editor), priv->comp, TRUE, priv->changed))
close_dialog (editor);
-
- return TRUE;
}