Blame src/calendar/gui/e-comp-editor.c.crash-empty-attendee

Packit d2ab36
/*
Packit d2ab36
 * Copyright (C) 2015 Red Hat, Inc. (www.redhat.com)
Packit d2ab36
 *
Packit d2ab36
 * This program is free software: you can redistribute it and/or modify it
Packit d2ab36
 * under the terms of the GNU General Public License as published by
Packit d2ab36
 * the Free Software Foundation.
Packit d2ab36
 *
Packit d2ab36
 * This program is distributed in the hope that it will be useful, but
Packit d2ab36
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit d2ab36
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
Packit d2ab36
 * for more details.
Packit d2ab36
 *
Packit d2ab36
 * You should have received a copy of the GNU General Public License
Packit d2ab36
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Packit d2ab36
 *
Packit d2ab36
 */
Packit d2ab36
Packit d2ab36
#include "evolution-config.h"
Packit d2ab36
Packit d2ab36
#include <glib/gi18n-lib.h>
Packit d2ab36
#include <gtk/gtk.h>
Packit d2ab36
Packit d2ab36
#include <libedataserver/libedataserver.h>
Packit d2ab36
#include <libecal/libecal.h>
Packit d2ab36
#include <e-util/e-util.h>
Packit d2ab36
Packit d2ab36
#include "calendar-config.h"
Packit d2ab36
#include "comp-util.h"
Packit d2ab36
#include "e-cal-dialogs.h"
Packit d2ab36
#include "itip-utils.h"
Packit d2ab36
#include "print.h"
Packit d2ab36
Packit d2ab36
#include "e-comp-editor-page-general.h"
Packit d2ab36
#include "e-comp-editor-page-attachments.h"
Packit d2ab36
#include "e-comp-editor-event.h"
Packit d2ab36
#include "e-comp-editor-memo.h"
Packit d2ab36
#include "e-comp-editor-task.h"
Packit d2ab36
Packit d2ab36
#include "e-comp-editor.h"
Packit d2ab36
Packit d2ab36
struct _ECompEditorPrivate {
Packit d2ab36
	EAlertBar *alert_bar; /* not referenced */
Packit d2ab36
	EActivityBar *activity_bar; /* not referenced */
Packit d2ab36
	GtkNotebook *content; /* not referenced */
Packit d2ab36
Packit d2ab36
	EAlert *validation_alert;
Packit d2ab36
Packit d2ab36
	EShell *shell;
Packit d2ab36
	GSettings *calendar_settings;
Packit d2ab36
	ESource *origin_source;
Packit d2ab36
	icalcomponent *component;
Packit d2ab36
	guint32 flags;
Packit d2ab36
Packit d2ab36
	EFocusTracker *focus_tracker;
Packit d2ab36
	GtkUIManager *ui_manager;
Packit d2ab36
Packit d2ab36
	GSList *pages; /* ECompEditorPage * */
Packit d2ab36
	gulong show_attendees_handler_id;
Packit d2ab36
Packit d2ab36
	ECompEditorPageGeneral *page_general; /* special page, can be added only once; not referenced */
Packit d2ab36
Packit d2ab36
	EActivity *target_client_opening;
Packit d2ab36
Packit d2ab36
	ECalClient *source_client;
Packit d2ab36
	ECalClient *target_client;
Packit d2ab36
	gchar *cal_email_address;
Packit d2ab36
	gchar *alarm_email_address;
Packit d2ab36
	gboolean changed;
Packit d2ab36
	guint updating;
Packit d2ab36
	gchar *title_suffix;
Packit d2ab36
Packit d2ab36
	ECompEditorPropertyPart *dtstart_part;
Packit d2ab36
	ECompEditorPropertyPart *dtend_part;
Packit d2ab36
Packit d2ab36
	GtkWidget *restore_focus;
Packit d2ab36
};
Packit d2ab36
Packit d2ab36
enum {
Packit d2ab36
	PROP_0,
Packit d2ab36
	PROP_ALARM_EMAIL_ADDRESS,
Packit d2ab36
	PROP_CAL_EMAIL_ADDRESS,
Packit d2ab36
	PROP_CHANGED,
Packit d2ab36
	PROP_COMPONENT,
Packit d2ab36
	PROP_FLAGS,
Packit d2ab36
	PROP_ORIGIN_SOURCE,
Packit d2ab36
	PROP_SHELL,
Packit d2ab36
	PROP_SOURCE_CLIENT,
Packit d2ab36
	PROP_TARGET_CLIENT,
Packit d2ab36
	PROP_TITLE_SUFFIX
Packit d2ab36
};
Packit d2ab36
Packit d2ab36
enum {
Packit d2ab36
	TIMES_CHANGED,
Packit d2ab36
	OBJECT_CREATED,
Packit d2ab36
	EDITOR_CLOSED,
Packit d2ab36
	LAST_SIGNAL
Packit d2ab36
};
Packit d2ab36
Packit d2ab36
static guint signals[LAST_SIGNAL];
Packit d2ab36
Packit d2ab36
static GSList *opened_editors = NULL;
Packit d2ab36
Packit d2ab36
static void e_comp_editor_alert_sink_iface_init (EAlertSinkInterface *iface);
Packit d2ab36
Packit d2ab36
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ECompEditor, e_comp_editor, GTK_TYPE_WINDOW,
Packit d2ab36
	G_IMPLEMENT_INTERFACE (E_TYPE_ALERT_SINK, e_comp_editor_alert_sink_iface_init)
Packit d2ab36
	G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE, NULL))
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
ece_restore_focus (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	if (comp_editor->priv->restore_focus) {
Packit d2ab36
		gtk_widget_grab_focus (comp_editor->priv->restore_focus);
Packit d2ab36
Packit d2ab36
		if (GTK_IS_ENTRY (comp_editor->priv->restore_focus))
Packit d2ab36
			gtk_editable_set_position (GTK_EDITABLE (comp_editor->priv->restore_focus), 0);
Packit d2ab36
Packit d2ab36
		comp_editor->priv->restore_focus = NULL;
Packit d2ab36
	}
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
e_comp_editor_enable (ECompEditor *comp_editor,
Packit d2ab36
		      gboolean enable)
Packit d2ab36
{
Packit d2ab36
	GtkActionGroup *group;
Packit d2ab36
	GtkWidget *current_focus;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	current_focus = gtk_window_get_focus (GTK_WINDOW (comp_editor));
Packit d2ab36
Packit d2ab36
	gtk_widget_set_sensitive (GTK_WIDGET (comp_editor->priv->content), enable);
Packit d2ab36
Packit d2ab36
	group = e_comp_editor_get_action_group (comp_editor, "individual");
Packit d2ab36
	gtk_action_group_set_sensitive (group, enable);
Packit d2ab36
Packit d2ab36
	group = e_comp_editor_get_action_group (comp_editor, "core");
Packit d2ab36
	gtk_action_group_set_sensitive (group, enable);
Packit d2ab36
Packit d2ab36
	group = e_comp_editor_get_action_group (comp_editor, "editable");
Packit d2ab36
	gtk_action_group_set_sensitive (group, enable);
Packit d2ab36
Packit d2ab36
	if (enable) {
Packit d2ab36
		e_comp_editor_sensitize_widgets (comp_editor);
Packit d2ab36
		ece_restore_focus (comp_editor);
Packit d2ab36
	} else {
Packit d2ab36
		comp_editor->priv->restore_focus = current_focus;
Packit d2ab36
	}
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
ece_set_attendees_for_delegation (ECalComponent *comp,
Packit d2ab36
				  const gchar *address)
Packit d2ab36
{
Packit d2ab36
	icalproperty *prop;
Packit d2ab36
	icalparameter *param;
Packit d2ab36
	icalcomponent *icalcomp;
Packit d2ab36
	gboolean again;
Packit d2ab36
Packit d2ab36
	icalcomp = e_cal_component_get_icalcomponent (comp);
Packit d2ab36
Packit d2ab36
	for (prop = icalcomponent_get_first_property (icalcomp, ICAL_ATTENDEE_PROPERTY);
Packit d2ab36
	     prop;
Packit d2ab36
	     prop = again ? icalcomponent_get_first_property (icalcomp, ICAL_ATTENDEE_PROPERTY) :
Packit d2ab36
	     icalcomponent_get_next_property (icalcomp, ICAL_ATTENDEE_PROPERTY)) {
Packit d2ab36
		const gchar *attendee = icalproperty_get_attendee (prop);
Packit d2ab36
		const gchar *delfrom = NULL;
Packit d2ab36
Packit d2ab36
		again = FALSE;
Packit d2ab36
		param = icalproperty_get_first_parameter (prop, ICAL_DELEGATEDFROM_PARAMETER);
Packit d2ab36
		if (param)
Packit d2ab36
			delfrom = icalparameter_get_delegatedfrom (param);
Packit d2ab36
		if (!(g_str_equal (itip_strip_mailto (attendee), address) ||
Packit d2ab36
		     ((delfrom && *delfrom) && g_str_equal (itip_strip_mailto (delfrom), address)))) {
Packit d2ab36
			icalcomponent_remove_property (icalcomp, prop);
Packit d2ab36
			icalproperty_free (prop);
Packit d2ab36
			again = TRUE;
Packit d2ab36
		}
Packit d2ab36
Packit d2ab36
	}
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
/* Utility function to get the mime-attachment list from the attachment
Packit d2ab36
 * bar for sending the comp via itip. The list and its contents must
Packit d2ab36
 * be freed by the caller.
Packit d2ab36
 */
Packit d2ab36
static GSList *
Packit d2ab36
ece_get_mime_attach_list (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	ECompEditorPage *page_attachments;
Packit d2ab36
	EAttachmentStore *store;
Packit d2ab36
	GtkTreeModel *model;
Packit d2ab36
	GtkTreeIter iter;
Packit d2ab36
	struct CalMimeAttach *cal_mime_attach;
Packit d2ab36
	GSList *attach_list = NULL;
Packit d2ab36
	gboolean valid;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
Packit d2ab36
Packit d2ab36
	page_attachments = e_comp_editor_get_page (comp_editor, E_TYPE_COMP_EDITOR_PAGE_ATTACHMENTS);
Packit d2ab36
	if (!page_attachments)
Packit d2ab36
		return NULL;
Packit d2ab36
Packit d2ab36
	store = e_comp_editor_page_attachments_get_store (E_COMP_EDITOR_PAGE_ATTACHMENTS (page_attachments));
Packit d2ab36
	if (!store)
Packit d2ab36
		return NULL;
Packit d2ab36
Packit d2ab36
	model = GTK_TREE_MODEL (store);
Packit d2ab36
	valid = gtk_tree_model_get_iter_first (model, &iter);
Packit d2ab36
Packit d2ab36
	while (valid) {
Packit d2ab36
		EAttachment *attachment;
Packit d2ab36
		CamelDataWrapper *wrapper;
Packit d2ab36
		CamelMimePart *mime_part;
Packit d2ab36
		CamelStream *stream;
Packit d2ab36
		GByteArray *byte_array;
Packit d2ab36
		guchar *buffer = NULL;
Packit d2ab36
		const gchar *description;
Packit d2ab36
		const gchar *disposition;
Packit d2ab36
		gint column_id;
Packit d2ab36
Packit d2ab36
		column_id = E_ATTACHMENT_STORE_COLUMN_ATTACHMENT;
Packit d2ab36
		gtk_tree_model_get (model, &iter, column_id, &attachment, -1);
Packit d2ab36
		mime_part = e_attachment_ref_mime_part (attachment);
Packit d2ab36
		g_object_unref (attachment);
Packit d2ab36
Packit d2ab36
		valid = gtk_tree_model_iter_next (model, &iter);
Packit d2ab36
Packit d2ab36
		if (mime_part == NULL)
Packit d2ab36
			continue;
Packit d2ab36
Packit d2ab36
		cal_mime_attach = g_malloc0 (sizeof (struct CalMimeAttach));
Packit d2ab36
		wrapper = camel_medium_get_content (CAMEL_MEDIUM (mime_part));
Packit d2ab36
Packit d2ab36
		byte_array = g_byte_array_new ();
Packit d2ab36
		stream = camel_stream_mem_new_with_byte_array (byte_array);
Packit d2ab36
Packit d2ab36
		camel_data_wrapper_decode_to_stream_sync (
Packit d2ab36
			wrapper, stream, NULL, NULL);
Packit d2ab36
		buffer = g_memdup (byte_array->data, byte_array->len);
Packit d2ab36
Packit d2ab36
		camel_mime_part_set_content_id (mime_part, NULL);
Packit d2ab36
Packit d2ab36
		cal_mime_attach->encoded_data = (gchar *) buffer;
Packit d2ab36
		cal_mime_attach->length = byte_array->len;
Packit d2ab36
		cal_mime_attach->filename =
Packit d2ab36
			g_strdup (camel_mime_part_get_filename (mime_part));
Packit d2ab36
		description = camel_mime_part_get_description (mime_part);
Packit d2ab36
		if (description == NULL || *description == '\0')
Packit d2ab36
			description = _("attachment");
Packit d2ab36
		cal_mime_attach->description = g_strdup (description);
Packit d2ab36
		cal_mime_attach->content_type = camel_data_wrapper_get_mime_type (wrapper);
Packit d2ab36
		cal_mime_attach->content_id = g_strdup (
Packit d2ab36
			camel_mime_part_get_content_id (mime_part));
Packit d2ab36
Packit d2ab36
		disposition = camel_mime_part_get_disposition (mime_part);
Packit d2ab36
		cal_mime_attach->disposition =
Packit d2ab36
			(disposition != NULL) &&
Packit d2ab36
			(g_ascii_strcasecmp (disposition, "inline") == 0);
Packit d2ab36
Packit d2ab36
		attach_list = g_slist_append (attach_list, cal_mime_attach);
Packit d2ab36
Packit d2ab36
		g_object_unref (mime_part);
Packit d2ab36
		g_object_unref (stream);
Packit d2ab36
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	return attach_list;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
e_comp_editor_set_component (ECompEditor *comp_editor,
Packit d2ab36
			     const icalcomponent *component)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
	g_return_if_fail (component != NULL);
Packit d2ab36
Packit d2ab36
	if (comp_editor->priv->component)
Packit d2ab36
		icalcomponent_free (comp_editor->priv->component);
Packit d2ab36
	comp_editor->priv->component = icalcomponent_new_clone ((icalcomponent *) component);
Packit d2ab36
Packit d2ab36
	g_warn_if_fail (comp_editor->priv->component != NULL);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
typedef struct _SaveData {
Packit d2ab36
	ECompEditor *comp_editor;
Packit d2ab36
	ECalClient *source_client;
Packit d2ab36
	ECalClient *target_client;
Packit d2ab36
	icalcomponent *component;
Packit d2ab36
	gboolean with_send;
Packit d2ab36
	gboolean close_after_save;
Packit d2ab36
	ECalObjModType recur_mod;
Packit d2ab36
	gboolean success;
Packit d2ab36
	GError *error;
Packit d2ab36
	gchar *alert_ident;
Packit d2ab36
	gchar *alert_arg_0;
Packit d2ab36
Packit d2ab36
	gboolean object_created;
Packit d2ab36
	ECalComponentItipMethod first_send;
Packit d2ab36
	ECalComponentItipMethod second_send;
Packit d2ab36
	ECalComponent *send_comp;
Packit d2ab36
	EActivity *send_activity;
Packit d2ab36
	gboolean strip_alarms;
Packit d2ab36
	gboolean only_new_attendees;
Packit d2ab36
	GSList *mime_attach_list;
Packit d2ab36
} SaveData;
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
save_data_free (SaveData *sd)
Packit d2ab36
{
Packit d2ab36
	if (sd) {
Packit d2ab36
		e_comp_editor_enable (sd->comp_editor, TRUE);
Packit d2ab36
Packit d2ab36
		if (sd->success) {
Packit d2ab36
			if (sd->close_after_save) {
Packit d2ab36
				g_signal_emit (sd->comp_editor, signals[EDITOR_CLOSED], 0, TRUE, NULL);
Packit d2ab36
				gtk_widget_destroy (GTK_WIDGET (sd->comp_editor));
Packit d2ab36
			} else {
Packit d2ab36
				e_comp_editor_set_component (sd->comp_editor, sd->component);
Packit d2ab36
Packit d2ab36
				e_comp_editor_fill_widgets (sd->comp_editor, sd->component);
Packit d2ab36
Packit d2ab36
				g_clear_object (&sd->comp_editor->priv->source_client);
Packit d2ab36
				sd->comp_editor->priv->source_client = g_object_ref (sd->target_client);
Packit d2ab36
Packit d2ab36
				sd->comp_editor->priv->flags = sd->comp_editor->priv->flags & (~E_COMP_EDITOR_FLAG_IS_NEW);
Packit d2ab36
Packit d2ab36
				e_comp_editor_sensitize_widgets (sd->comp_editor);
Packit d2ab36
				e_comp_editor_set_changed (sd->comp_editor, FALSE);
Packit d2ab36
			}
Packit d2ab36
		} else if (sd->alert_ident) {
Packit d2ab36
			e_alert_submit (
Packit d2ab36
				E_ALERT_SINK (sd->comp_editor), sd->alert_ident, sd->alert_arg_0,
Packit d2ab36
				sd->error ? sd->error->message : _("Unknown error"), NULL);
Packit d2ab36
		}
Packit d2ab36
Packit d2ab36
		if (sd->send_activity && e_activity_get_state (sd->send_activity) != E_ACTIVITY_CANCELLED)
Packit d2ab36
			e_activity_set_state (sd->send_activity, E_ACTIVITY_COMPLETED);
Packit d2ab36
Packit d2ab36
		g_clear_object (&sd->comp_editor);
Packit d2ab36
		g_clear_object (&sd->source_client);
Packit d2ab36
		g_clear_object (&sd->target_client);
Packit d2ab36
		g_clear_object (&sd->send_comp);
Packit d2ab36
		g_clear_object (&sd->send_activity);
Packit d2ab36
		g_clear_error (&sd->error);
Packit d2ab36
		if (sd->component)
Packit d2ab36
			icalcomponent_free (sd->component);
Packit d2ab36
		g_slist_free_full (sd->mime_attach_list, itip_cal_mime_attach_free);
Packit d2ab36
		g_free (sd->alert_ident);
Packit d2ab36
		g_free (sd->alert_arg_0);
Packit d2ab36
		g_free (sd);
Packit d2ab36
	}
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static gboolean
Packit d2ab36
ece_send_process_method (SaveData *sd,
Packit d2ab36
			 ECalComponentItipMethod send_method,
Packit d2ab36
			 ECalComponent *send_comp,
Packit d2ab36
			 ESourceRegistry *registry,
Packit d2ab36
			 GCancellable *cancellable,
Packit d2ab36
			 GAsyncReadyCallback callback,
Packit d2ab36
			 gpointer user_data)
Packit d2ab36
{
Packit d2ab36
	GSList *mime_attach_list = NULL;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (sd != NULL, FALSE);
Packit d2ab36
	g_return_val_if_fail (E_IS_CAL_COMPONENT (send_comp), FALSE);
Packit d2ab36
	g_return_val_if_fail (send_method != E_CAL_COMPONENT_METHOD_NONE, FALSE);
Packit d2ab36
Packit d2ab36
	if (e_cal_component_has_attachments (send_comp) &&
Packit d2ab36
	    e_client_check_capability (E_CLIENT (sd->target_client), CAL_STATIC_CAPABILITY_CREATE_MESSAGES)) {
Packit d2ab36
		/* Clone the component with attachments set to CID:...  */
Packit d2ab36
		GSList *attach_list = NULL;
Packit d2ab36
		GSList *attach;
Packit d2ab36
Packit d2ab36
		/* mime_attach_list is freed by itip_send_component() */
Packit d2ab36
		mime_attach_list = sd->mime_attach_list;
Packit d2ab36
		sd->mime_attach_list = NULL;
Packit d2ab36
Packit d2ab36
		for (attach = mime_attach_list; attach; attach = attach->next) {
Packit d2ab36
			struct CalMimeAttach *cma = (struct CalMimeAttach *) attach->data;
Packit d2ab36
Packit d2ab36
			attach_list = g_slist_append (
Packit d2ab36
				attach_list, g_strconcat (
Packit d2ab36
				"cid:", cma->content_id, NULL));
Packit d2ab36
		}
Packit d2ab36
Packit d2ab36
		if (attach_list) {
Packit d2ab36
			e_cal_component_set_attachment_list (send_comp, attach_list);
Packit d2ab36
Packit d2ab36
			g_slist_free_full (attach_list, g_free);
Packit d2ab36
		}
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	itip_send_component (
Packit d2ab36
		registry, send_method, send_comp, sd->target_client,
Packit d2ab36
		NULL, mime_attach_list, NULL, sd->strip_alarms,
Packit d2ab36
		sd->only_new_attendees, FALSE,
Packit d2ab36
		cancellable, callback, user_data);
Packit d2ab36
Packit d2ab36
	return TRUE;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
ecep_second_send_processed_cb (GObject *source_object,
Packit d2ab36
			       GAsyncResult *result,
Packit d2ab36
			       gpointer user_data)
Packit d2ab36
{
Packit d2ab36
	SaveData *sd = user_data;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (sd != NULL);
Packit d2ab36
Packit d2ab36
	sd->success = itip_send_component_finish (result, &sd->error);
Packit d2ab36
Packit d2ab36
	save_data_free (sd);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
ecep_first_send_processed_cb (GObject *source_object,
Packit d2ab36
			      GAsyncResult *result,
Packit d2ab36
			      gpointer user_data)
Packit d2ab36
{
Packit d2ab36
	SaveData *sd = user_data;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (sd != NULL);
Packit d2ab36
Packit d2ab36
	sd->success = itip_send_component_finish (result, &sd->error);
Packit d2ab36
	if (!sd->success || sd->second_send == E_CAL_COMPONENT_METHOD_NONE) {
Packit d2ab36
		save_data_free (sd);
Packit d2ab36
	} else {
Packit d2ab36
		sd->success = ece_send_process_method (sd, sd->second_send, sd->send_comp,
Packit d2ab36
			e_shell_get_registry (sd->comp_editor->priv->shell),
Packit d2ab36
			e_activity_get_cancellable (sd->send_activity),
Packit d2ab36
			ecep_second_send_processed_cb, sd);
Packit d2ab36
		if (!sd->success)
Packit d2ab36
			save_data_free (sd);
Packit d2ab36
	}
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
ece_prepare_send_component_done (gpointer ptr)
Packit d2ab36
{
Packit d2ab36
	SaveData *sd = ptr;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (sd != NULL);
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (sd->comp_editor));
Packit d2ab36
	g_return_if_fail (sd->send_activity != NULL);
Packit d2ab36
Packit d2ab36
	sd->success = ece_send_process_method (sd, sd->first_send, sd->send_comp,
Packit d2ab36
		e_shell_get_registry (sd->comp_editor->priv->shell),
Packit d2ab36
		e_activity_get_cancellable (sd->send_activity),
Packit d2ab36
		ecep_first_send_processed_cb, sd);
Packit d2ab36
	if (!sd->success)
Packit d2ab36
		save_data_free (sd);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
ece_prepare_send_component_thread (EAlertSinkThreadJobData *job_data,
Packit d2ab36
				   gpointer user_data,
Packit d2ab36
				   GCancellable *cancellable,
Packit d2ab36
				   GError **error)
Packit d2ab36
{
Packit d2ab36
	SaveData *sd = user_data;
Packit d2ab36
	const gchar *alert_ident;
Packit d2ab36
	ECalComponent *send_comp = NULL;
Packit d2ab36
	guint32 flags;
Packit d2ab36
	ESourceRegistry *registry;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (sd != NULL);
Packit d2ab36
	g_return_if_fail (E_IS_CAL_CLIENT (sd->target_client));
Packit d2ab36
	g_return_if_fail (sd->component != NULL);
Packit d2ab36
Packit d2ab36
	while (!sd->send_activity) {
Packit d2ab36
		/* Give the main thread a chance to set this object
Packit d2ab36
		   and give it a 50 milliseconds delay too */
Packit d2ab36
		g_thread_yield ();
Packit d2ab36
		g_usleep (50000);
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	switch (icalcomponent_isa (sd->component)) {
Packit d2ab36
		case ICAL_VEVENT_COMPONENT:
Packit d2ab36
			alert_ident = "calendar:failed-send-event";
Packit d2ab36
			break;
Packit d2ab36
		case ICAL_VJOURNAL_COMPONENT:
Packit d2ab36
			alert_ident = "calendar:failed-send-memo";
Packit d2ab36
			break;
Packit d2ab36
		case ICAL_VTODO_COMPONENT:
Packit d2ab36
			alert_ident = "calendar:failed-send-task";
Packit d2ab36
			break;
Packit d2ab36
		default:
Packit d2ab36
			g_warning ("%s: Cannot send component of kind %d", G_STRFUNC, icalcomponent_isa (sd->component));
Packit d2ab36
			sd->success = FALSE;
Packit d2ab36
			sd->alert_ident = g_strdup ("calendar:failed-send-event");
Packit d2ab36
			return;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	g_free (sd->alert_ident);
Packit d2ab36
	sd->alert_ident = g_strdup (alert_ident);
Packit d2ab36
Packit d2ab36
	e_alert_sink_thread_job_set_alert_ident (job_data, alert_ident);
Packit d2ab36
Packit d2ab36
	flags = e_comp_editor_get_flags (sd->comp_editor);
Packit d2ab36
	registry = e_shell_get_registry (sd->comp_editor->priv->shell);
Packit d2ab36
Packit d2ab36
	if (sd->recur_mod == E_CAL_OBJ_MOD_ALL && e_cal_component_is_instance (sd->send_comp)) {
Packit d2ab36
		/* Ensure we send the master object, not the instance only */
Packit d2ab36
		icalcomponent *icalcomp = NULL;
Packit d2ab36
		const gchar *uid = NULL;
Packit d2ab36
Packit d2ab36
		e_cal_component_get_uid (sd->send_comp, &uid);
Packit d2ab36
		if (e_cal_client_get_object_sync (sd->target_client, uid, NULL, &icalcomp, cancellable, NULL) &&
Packit d2ab36
		    icalcomp != NULL) {
Packit d2ab36
			send_comp = e_cal_component_new_from_icalcomponent (icalcomp);
Packit d2ab36
		}
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	if (!send_comp)
Packit d2ab36
		send_comp = e_cal_component_clone (sd->send_comp);
Packit d2ab36
Packit d2ab36
	cal_comp_util_copy_new_attendees (send_comp, sd->send_comp);
Packit d2ab36
Packit d2ab36
	/* The user updates the delegated status to the Organizer,
Packit d2ab36
	 * so remove all other attendees. */
Packit d2ab36
	if ((flags & E_COMP_EDITOR_FLAG_DELEGATE) != 0) {
Packit d2ab36
		gchar *address;
Packit d2ab36
Packit d2ab36
		address = itip_get_comp_attendee (registry, send_comp, sd->target_client);
Packit d2ab36
Packit d2ab36
		if (address) {
Packit d2ab36
			ece_set_attendees_for_delegation (send_comp, address);
Packit d2ab36
			g_free (address);
Packit d2ab36
		}
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	g_clear_object (&sd->send_comp);
Packit d2ab36
	sd->send_comp = send_comp;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
ece_save_component_done (gpointer ptr)
Packit d2ab36
{
Packit d2ab36
	SaveData *sd = ptr;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (sd != NULL);
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (sd->comp_editor));
Packit d2ab36
Packit d2ab36
	if (sd->success) {
Packit d2ab36
		ECalComponent *comp;
Packit d2ab36
		gboolean delegated, is_new_meeting;
Packit d2ab36
		gboolean only_new_attendees = FALSE;
Packit d2ab36
		gboolean strip_alarms = TRUE;
Packit d2ab36
		guint32 flags;
Packit d2ab36
Packit d2ab36
		if (sd->object_created)
Packit d2ab36
			g_signal_emit (sd->comp_editor, signals[OBJECT_CREATED], 0, NULL);
Packit d2ab36
Packit d2ab36
		comp = e_cal_component_new_from_icalcomponent (icalcomponent_new_clone (sd->component));
Packit d2ab36
		if (sd->comp_editor->priv->page_general) {
Packit d2ab36
			GSList *added_attendees;
Packit d2ab36
Packit d2ab36
			added_attendees = e_comp_editor_page_general_get_added_attendees (sd->comp_editor->priv->page_general);
Packit d2ab36
			cal_comp_util_set_added_attendees_mails (comp, added_attendees);
Packit d2ab36
		}
Packit d2ab36
Packit d2ab36
		flags = e_comp_editor_get_flags (sd->comp_editor);
Packit d2ab36
		is_new_meeting = (flags & E_COMP_EDITOR_FLAG_WITH_ATTENDEES) == 0 ||
Packit d2ab36
			(flags & E_COMP_EDITOR_FLAG_IS_NEW) != 0;
Packit d2ab36
		delegated = (flags & E_COMP_EDITOR_FLAG_DELEGATE) != 0 &&
Packit d2ab36
			e_cal_client_check_save_schedules (sd->target_client);
Packit d2ab36
Packit d2ab36
		if (delegated || (sd->with_send && e_cal_dialogs_send_component (
Packit d2ab36
			GTK_WINDOW (sd->comp_editor), sd->target_client, comp,
Packit d2ab36
			is_new_meeting, &strip_alarms, &only_new_attendees))) {
Packit d2ab36
			ESourceRegistry *registry;
Packit d2ab36
			EActivity *activity;
Packit d2ab36
Packit d2ab36
			registry = e_shell_get_registry (sd->comp_editor->priv->shell);
Packit d2ab36
Packit d2ab36
			if (delegated)
Packit d2ab36
				only_new_attendees = FALSE;
Packit d2ab36
Packit d2ab36
			if ((itip_organizer_is_user (registry, comp, sd->target_client) ||
Packit d2ab36
			     itip_sentby_is_user (registry, comp, sd->target_client))) {
Packit d2ab36
				if (e_cal_component_get_vtype (comp) == E_CAL_COMPONENT_JOURNAL)
Packit d2ab36
					sd->first_send = E_CAL_COMPONENT_METHOD_PUBLISH;
Packit d2ab36
				else
Packit d2ab36
					sd->first_send = E_CAL_COMPONENT_METHOD_REQUEST;
Packit d2ab36
			} else {
Packit d2ab36
				sd->first_send = E_CAL_COMPONENT_METHOD_REQUEST;
Packit d2ab36
Packit d2ab36
				if ((flags & E_COMP_EDITOR_FLAG_DELEGATE) != 0)
Packit d2ab36
					sd->second_send = E_CAL_COMPONENT_METHOD_REPLY;
Packit d2ab36
			}
Packit d2ab36
Packit d2ab36
			sd->mime_attach_list = ece_get_mime_attach_list (sd->comp_editor);
Packit d2ab36
			sd->strip_alarms = strip_alarms;
Packit d2ab36
			sd->only_new_attendees = only_new_attendees;
Packit d2ab36
			sd->send_comp = comp;
Packit d2ab36
			sd->success = FALSE;
Packit d2ab36
			sd->alert_ident = g_strdup ("calendar:failed-send-event");
Packit d2ab36
			sd->alert_arg_0 = e_util_get_source_full_name (registry, e_client_get_source (E_CLIENT (sd->target_client)));
Packit d2ab36
Packit d2ab36
			activity = e_alert_sink_submit_thread_job (E_ALERT_SINK (sd->comp_editor),
Packit d2ab36
				_("Sending notifications to attendees..."), sd->alert_ident, sd->alert_arg_0,
Packit d2ab36
				ece_prepare_send_component_thread, sd, ece_prepare_send_component_done);
Packit d2ab36
Packit d2ab36
			if (activity)
Packit d2ab36
				e_activity_bar_set_activity (sd->comp_editor->priv->activity_bar, activity);
Packit d2ab36
Packit d2ab36
			/* The thread is waiting for this to be set first */
Packit d2ab36
			sd->send_activity = activity;
Packit d2ab36
Packit d2ab36
			return;
Packit d2ab36
		}
Packit d2ab36
Packit d2ab36
		g_clear_object (&comp);
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	save_data_free (sd);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static gboolean
Packit d2ab36
ece_save_component_attachments_sync (ECalClient *cal_client,
Packit d2ab36
				     icalcomponent *component,
Packit d2ab36
				     GCancellable *cancellable,
Packit d2ab36
				     GError **error)
Packit d2ab36
{
Packit d2ab36
	icalproperty *prop;
Packit d2ab36
	const gchar *local_store;
Packit d2ab36
	gchar *target_filename_prefix, *filename_prefix, *tmp;
Packit d2ab36
	gboolean success = TRUE;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (E_IS_CAL_CLIENT (cal_client), FALSE);
Packit d2ab36
	g_return_val_if_fail (component != NULL, FALSE);
Packit d2ab36
Packit d2ab36
	tmp = g_strdup (icalcomponent_get_uid (component));
Packit d2ab36
	e_filename_make_safe (tmp);
Packit d2ab36
	filename_prefix = g_strconcat (tmp, "-", NULL);
Packit d2ab36
	g_free (tmp);
Packit d2ab36
Packit d2ab36
	local_store = e_cal_client_get_local_attachment_store (cal_client);
Packit d2ab36
	if (local_store && *local_store &&
Packit d2ab36
	    g_mkdir_with_parents (local_store, 0700) < 0) {
Packit d2ab36
		g_debug ("%s: Failed to create local store directory '%s'", G_STRFUNC, local_store);
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	target_filename_prefix = g_build_filename (local_store, filename_prefix, NULL);
Packit d2ab36
Packit d2ab36
	g_free (filename_prefix);
Packit d2ab36
Packit d2ab36
	for (prop = icalcomponent_get_first_property (component, ICAL_ATTACH_PROPERTY);
Packit d2ab36
	     prop && success;
Packit d2ab36
	     prop = icalcomponent_get_next_property (component, ICAL_ATTACH_PROPERTY)) {
Packit d2ab36
		icalattach *attach;
Packit d2ab36
		gchar *uri = NULL;
Packit d2ab36
Packit d2ab36
		attach = icalproperty_get_attach (prop);
Packit d2ab36
		if (!attach)
Packit d2ab36
			continue;
Packit d2ab36
Packit d2ab36
		if (icalattach_get_is_url (attach)) {
Packit d2ab36
			const gchar *data;
Packit d2ab36
			gsize buf_size;
Packit d2ab36
Packit d2ab36
			data = icalattach_get_url (attach);
Packit d2ab36
			buf_size = strlen (data);
Packit d2ab36
			uri = g_malloc0 (buf_size + 1);
Packit d2ab36
Packit d2ab36
			icalvalue_decode_ical_string (data, uri, buf_size);
Packit d2ab36
		}
Packit d2ab36
Packit d2ab36
		if (uri) {
Packit d2ab36
			if (g_ascii_strncasecmp (uri, "file://", 7) == 0 &&
Packit d2ab36
			    !g_str_has_prefix (uri + 7, target_filename_prefix)) {
Packit d2ab36
				GFile *source, *destination;
Packit d2ab36
				gchar *decoded_filename;
Packit d2ab36
				gchar *target_filename;
Packit d2ab36
Packit d2ab36
				decoded_filename = g_uri_unescape_string (strrchr (uri, '/') + 1, NULL);
Packit d2ab36
				target_filename = g_strconcat (target_filename_prefix, decoded_filename, NULL);
Packit d2ab36
				g_free (decoded_filename);
Packit d2ab36
Packit d2ab36
				source = g_file_new_for_uri (uri);
Packit d2ab36
				destination = g_file_new_for_path (target_filename);
Packit d2ab36
Packit d2ab36
				if (source && destination) {
Packit d2ab36
					success = g_file_copy (source, destination, G_FILE_COPY_OVERWRITE, cancellable, NULL, NULL, error);
Packit d2ab36
					if (success) {
Packit d2ab36
						g_free (uri);
Packit d2ab36
						uri = g_file_get_uri (destination);
Packit d2ab36
Packit d2ab36
						if (uri) {
Packit d2ab36
							icalattach *new_attach;
Packit d2ab36
							gsize buf_size;
Packit d2ab36
							gchar *buf;
Packit d2ab36
Packit d2ab36
							buf_size = 2 * strlen (uri) + 1;
Packit d2ab36
							buf = g_malloc0 (buf_size);
Packit d2ab36
Packit d2ab36
							icalvalue_encode_ical_string (uri, buf, buf_size);
Packit d2ab36
							new_attach = icalattach_new_from_url (buf);
Packit d2ab36
Packit d2ab36
							icalproperty_set_attach (prop, new_attach);
Packit d2ab36
Packit d2ab36
							icalattach_unref (new_attach);
Packit d2ab36
							g_free (buf);
Packit d2ab36
						}
Packit d2ab36
					}
Packit d2ab36
				}
Packit d2ab36
Packit d2ab36
				g_clear_object (&source);
Packit d2ab36
				g_clear_object (&destination);
Packit d2ab36
				g_free (target_filename);
Packit d2ab36
			}
Packit d2ab36
Packit d2ab36
			g_free (uri);
Packit d2ab36
		}
Packit d2ab36
Packit d2ab36
		success = success & !g_cancellable_set_error_if_cancelled (cancellable, error);
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	g_free (target_filename_prefix);
Packit d2ab36
Packit d2ab36
	return success;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
ece_gather_tzids_cb (icalparameter *param,
Packit d2ab36
		     gpointer user_data)
Packit d2ab36
{
Packit d2ab36
	GHashTable *tzids = user_data;
Packit d2ab36
	const gchar *tzid;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (param != NULL);
Packit d2ab36
	g_return_if_fail (tzids != NULL);
Packit d2ab36
Packit d2ab36
	tzid = icalparameter_get_tzid (param);
Packit d2ab36
	if (tzid && *tzid && g_ascii_strcasecmp (tzid, "UTC") != 0)
Packit d2ab36
		g_hash_table_insert (tzids, g_strdup (tzid), NULL);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static gboolean
Packit d2ab36
ece_save_component_add_timezones_sync (SaveData *sd,
Packit d2ab36
				       GCancellable *cancellable,
Packit d2ab36
				       GError **error)
Packit d2ab36
{
Packit d2ab36
	GHashTable *tzids;
Packit d2ab36
	GHashTableIter iter;
Packit d2ab36
	gpointer key, value;
Packit d2ab36
	gboolean source_is_target;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (sd != NULL, FALSE);
Packit d2ab36
	g_return_val_if_fail (sd->component != NULL, FALSE);
Packit d2ab36
	g_return_val_if_fail (sd->target_client != NULL, FALSE);
Packit d2ab36
Packit d2ab36
	sd->success = TRUE;
Packit d2ab36
Packit d2ab36
	tzids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
Packit d2ab36
	source_is_target = !sd->source_client ||
Packit d2ab36
		e_source_equal (e_client_get_source (E_CLIENT (sd->target_client)),
Packit d2ab36
				e_client_get_source (E_CLIENT (sd->source_client)));
Packit d2ab36
Packit d2ab36
	icalcomponent_foreach_tzid (sd->component, ece_gather_tzids_cb, tzids);
Packit d2ab36
Packit d2ab36
	g_hash_table_iter_init (&iter, tzids);
Packit d2ab36
	while (sd->success && g_hash_table_iter_next (&iter, &key, &value)) {
Packit d2ab36
		const gchar *tzid = key;
Packit d2ab36
		icaltimezone *zone = NULL;
Packit d2ab36
		GError *local_error = NULL;
Packit d2ab36
Packit d2ab36
		if (!e_cal_client_get_timezone_sync (source_is_target ? sd->target_client : sd->source_client,
Packit d2ab36
			tzid, &zone, cancellable, &local_error)) {
Packit d2ab36
			zone = icaltimezone_get_builtin_timezone_from_tzid (tzid);
Packit d2ab36
			if (!zone)
Packit d2ab36
				zone = icaltimezone_get_builtin_timezone (tzid);
Packit d2ab36
			if (!zone) {
Packit d2ab36
				g_propagate_error (error, local_error);
Packit d2ab36
				local_error = NULL;
Packit d2ab36
				sd->success = FALSE;
Packit d2ab36
				break;
Packit d2ab36
			}
Packit d2ab36
		}
Packit d2ab36
Packit d2ab36
		sd->success = e_cal_client_add_timezone_sync (sd->target_client, zone, cancellable, error);
Packit d2ab36
Packit d2ab36
		g_clear_error (&local_error);
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	g_hash_table_destroy (tzids);
Packit d2ab36
Packit d2ab36
	return sd->success;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
ece_save_component_thread (EAlertSinkThreadJobData *job_data,
Packit d2ab36
			   gpointer user_data,
Packit d2ab36
			   GCancellable *cancellable,
Packit d2ab36
			   GError **error)
Packit d2ab36
{
Packit d2ab36
	SaveData *sd = user_data;
Packit d2ab36
	const gchar *create_alert_ident, *modify_alert_ident, *remove_alert_ident, *get_alert_ident;
Packit d2ab36
	gchar *orig_uid, *new_uid = NULL;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (sd != NULL);
Packit d2ab36
	g_return_if_fail (E_IS_CAL_CLIENT (sd->target_client));
Packit d2ab36
	g_return_if_fail (sd->component != NULL);
Packit d2ab36
Packit d2ab36
	switch (icalcomponent_isa (sd->component)) {
Packit d2ab36
		case ICAL_VEVENT_COMPONENT:
Packit d2ab36
			create_alert_ident = "calendar:failed-create-event";
Packit d2ab36
			modify_alert_ident = "calendar:failed-modify-event";
Packit d2ab36
			remove_alert_ident = "calendar:failed-remove-event";
Packit d2ab36
			get_alert_ident = "calendar:failed-get-event";
Packit d2ab36
			break;
Packit d2ab36
		case ICAL_VJOURNAL_COMPONENT:
Packit d2ab36
			create_alert_ident = "calendar:failed-create-memo";
Packit d2ab36
			modify_alert_ident = "calendar:failed-modify-memo";
Packit d2ab36
			remove_alert_ident = "calendar:failed-remove-memo";
Packit d2ab36
			get_alert_ident = "calendar:failed-get-memo";
Packit d2ab36
			break;
Packit d2ab36
		case ICAL_VTODO_COMPONENT:
Packit d2ab36
			create_alert_ident = "calendar:failed-create-task";
Packit d2ab36
			modify_alert_ident = "calendar:failed-modify-task";
Packit d2ab36
			remove_alert_ident = "calendar:failed-remove-task";
Packit d2ab36
			get_alert_ident = "calendar:failed-get-task";
Packit d2ab36
			break;
Packit d2ab36
		default:
Packit d2ab36
			g_warning ("%s: Cannot save component of kind %d", G_STRFUNC, icalcomponent_isa (sd->component));
Packit d2ab36
			return;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	sd->success = ece_save_component_add_timezones_sync (sd, cancellable, error);
Packit d2ab36
	if (!sd->success) {
Packit d2ab36
		e_alert_sink_thread_job_set_alert_ident (job_data, "calendar:failed-add-timezone");
Packit d2ab36
		return;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	sd->success = ece_save_component_attachments_sync (sd->target_client, sd->component, cancellable, error);
Packit d2ab36
	if (!sd->success) {
Packit d2ab36
		e_alert_sink_thread_job_set_alert_ident (job_data, "calendar:failed-save-attachments");
Packit d2ab36
		return;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	orig_uid = g_strdup (icalcomponent_get_uid (sd->component));
Packit d2ab36
Packit d2ab36
	if (cal_comp_is_icalcomp_on_server_sync (sd->component, sd->target_client, cancellable, error)) {
Packit d2ab36
		ECalComponent *comp;
Packit d2ab36
		gboolean has_recurrences;
Packit d2ab36
Packit d2ab36
		e_alert_sink_thread_job_set_alert_ident (job_data, modify_alert_ident);
Packit d2ab36
Packit d2ab36
		comp = e_cal_component_new_from_icalcomponent (icalcomponent_new_clone (sd->component));
Packit d2ab36
		g_return_if_fail (comp != NULL);
Packit d2ab36
Packit d2ab36
		has_recurrences = e_cal_util_component_has_recurrences (sd->component);
Packit d2ab36
Packit d2ab36
		if (has_recurrences && sd->recur_mod == E_CAL_OBJ_MOD_ALL)
Packit d2ab36
			sd->success = comp_util_sanitize_recurrence_master_sync (comp, sd->target_client, cancellable, error);
Packit d2ab36
		else
Packit d2ab36
			sd->success = TRUE;
Packit d2ab36
Packit d2ab36
		if (sd->recur_mod == E_CAL_OBJ_MOD_THIS) {
Packit d2ab36
			e_cal_component_set_rdate_list (comp, NULL);
Packit d2ab36
			e_cal_component_set_rrule_list (comp, NULL);
Packit d2ab36
			e_cal_component_set_exdate_list (comp, NULL);
Packit d2ab36
			e_cal_component_set_exrule_list (comp, NULL);
Packit d2ab36
		}
Packit d2ab36
Packit d2ab36
		sd->success = sd->success && e_cal_client_modify_object_sync (
Packit d2ab36
			sd->target_client, e_cal_component_get_icalcomponent (comp), sd->recur_mod, cancellable, error);
Packit d2ab36
Packit d2ab36
		g_clear_object (&comp);
Packit d2ab36
	} else {
Packit d2ab36
		e_alert_sink_thread_job_set_alert_ident (job_data, create_alert_ident);
Packit d2ab36
Packit d2ab36
		sd->success = e_cal_client_create_object_sync (sd->target_client, sd->component, &new_uid, cancellable, error);
Packit d2ab36
Packit d2ab36
		if (sd->success)
Packit d2ab36
			sd->object_created = TRUE;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	if (sd->success && sd->source_client &&
Packit d2ab36
	    !e_source_equal (e_client_get_source (E_CLIENT (sd->target_client)),
Packit d2ab36
			     e_client_get_source (E_CLIENT (sd->source_client))) &&
Packit d2ab36
	    cal_comp_is_icalcomp_on_server_sync (sd->component, sd->source_client, cancellable, NULL)) {
Packit d2ab36
		ECalObjModType recur_mod = E_CAL_OBJ_MOD_THIS;
Packit d2ab36
Packit d2ab36
		/* Comp found a new home. Remove it from old one. */
Packit d2ab36
		if (e_cal_util_component_is_instance (sd->component) ||
Packit d2ab36
		    e_cal_util_component_has_recurrences (sd->component))
Packit d2ab36
			recur_mod = E_CAL_OBJ_MOD_ALL;
Packit d2ab36
Packit d2ab36
		sd->success = e_cal_client_remove_object_sync (
Packit d2ab36
			sd->source_client, orig_uid,
Packit d2ab36
			NULL, recur_mod, cancellable, error);
Packit d2ab36
Packit d2ab36
		if (!sd->success) {
Packit d2ab36
			gchar *source_display_name;
Packit d2ab36
Packit d2ab36
			source_display_name = e_util_get_source_full_name (e_shell_get_registry (sd->comp_editor->priv->shell),
Packit d2ab36
				e_client_get_source (E_CLIENT (sd->source_client)));
Packit d2ab36
Packit d2ab36
			e_alert_sink_thread_job_set_alert_ident (job_data, remove_alert_ident);
Packit d2ab36
			e_alert_sink_thread_job_set_alert_arg_0 (job_data, source_display_name);
Packit d2ab36
Packit d2ab36
			g_free (source_display_name);
Packit d2ab36
		}
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	if (new_uid) {
Packit d2ab36
		icalcomponent_set_uid (sd->component, new_uid);
Packit d2ab36
		g_free (new_uid);
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	g_free (orig_uid);
Packit d2ab36
Packit d2ab36
	if (sd->success && !sd->close_after_save) {
Packit d2ab36
		icalcomponent *comp = NULL;
Packit d2ab36
		gchar *uid, *rid = NULL;
Packit d2ab36
Packit d2ab36
		uid = g_strdup (icalcomponent_get_uid (sd->component));
Packit d2ab36
		if (icalcomponent_get_first_property (sd->component, ICAL_RECURRENCEID_PROPERTY)) {
Packit d2ab36
			struct icaltimetype ridtt;
Packit d2ab36
Packit d2ab36
			ridtt = icalcomponent_get_recurrenceid (sd->component);
Packit d2ab36
			if (icaltime_is_valid_time (ridtt) && !icaltime_is_null_time (ridtt)) {
Packit d2ab36
				rid = icaltime_as_ical_string_r (ridtt);
Packit d2ab36
			}
Packit d2ab36
		}
Packit d2ab36
Packit d2ab36
		sd->success = e_cal_client_get_object_sync (sd->target_client, uid, rid, &comp, cancellable, error);
Packit d2ab36
		if (sd->success && comp) {
Packit d2ab36
			icalcomponent_free (sd->component);
Packit d2ab36
			sd->component = comp;
Packit d2ab36
		} else {
Packit d2ab36
			e_alert_sink_thread_job_set_alert_ident (job_data, get_alert_ident);
Packit d2ab36
		}
Packit d2ab36
Packit d2ab36
		g_free (uid);
Packit d2ab36
		g_free (rid);
Packit d2ab36
	}
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
ece_save_component (ECompEditor *comp_editor,
Packit d2ab36
		    icalcomponent *component,
Packit d2ab36
		    gboolean with_send,
Packit d2ab36
		    gboolean close_after_save)
Packit d2ab36
{
Packit d2ab36
	EActivity *activity;
Packit d2ab36
	const gchar *summary;
Packit d2ab36
	ECalObjModType recur_mod = E_CAL_OBJ_MOD_THIS;
Packit d2ab36
	SaveData *sd;
Packit d2ab36
	gchar *source_display_name;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
	g_return_if_fail (component != NULL);
Packit d2ab36
Packit d2ab36
	summary = icalcomponent_get_summary (component);
Packit d2ab36
	if (!summary || !*summary) {
Packit d2ab36
		if (!e_cal_dialogs_send_component_prompt_subject (GTK_WINDOW (comp_editor), component)) {
Packit d2ab36
			return;
Packit d2ab36
		}
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	if (e_cal_util_component_is_instance (component)) {
Packit d2ab36
		if (!e_cal_dialogs_recur_icalcomp (comp_editor->priv->target_client,
Packit d2ab36
			component, &recur_mod, GTK_WINDOW (comp_editor), FALSE)) {
Packit d2ab36
			return;
Packit d2ab36
		}
Packit d2ab36
	} else if (e_cal_util_component_has_recurrences (component)) {
Packit d2ab36
		recur_mod = E_CAL_OBJ_MOD_ALL;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	e_comp_editor_enable (comp_editor, FALSE);
Packit d2ab36
Packit d2ab36
	sd = g_new0 (SaveData, 1);
Packit d2ab36
	sd->comp_editor = g_object_ref (comp_editor);
Packit d2ab36
	sd->source_client = comp_editor->priv->source_client ? g_object_ref (comp_editor->priv->source_client) : NULL;
Packit d2ab36
	sd->target_client = g_object_ref (comp_editor->priv->target_client);
Packit d2ab36
	sd->component = icalcomponent_new_clone (component);
Packit d2ab36
	sd->with_send = with_send;
Packit d2ab36
	sd->close_after_save = close_after_save;
Packit d2ab36
	sd->recur_mod = recur_mod;
Packit d2ab36
	sd->first_send = E_CAL_COMPONENT_METHOD_NONE;
Packit d2ab36
	sd->second_send = E_CAL_COMPONENT_METHOD_NONE;
Packit d2ab36
	sd->success = FALSE;
Packit d2ab36
Packit d2ab36
	source_display_name = e_util_get_source_full_name (e_shell_get_registry (comp_editor->priv->shell),
Packit d2ab36
		e_client_get_source (E_CLIENT (sd->target_client)));
Packit d2ab36
Packit d2ab36
	activity = e_alert_sink_submit_thread_job (E_ALERT_SINK (comp_editor),
Packit d2ab36
		_("Saving changes..."), "calendar:failed-create-event", source_display_name,
Packit d2ab36
		ece_save_component_thread, sd, ece_save_component_done);
Packit d2ab36
Packit d2ab36
	if (activity)
Packit d2ab36
		e_activity_bar_set_activity (comp_editor->priv->activity_bar, activity);
Packit d2ab36
Packit d2ab36
	g_clear_object (&activity);
Packit d2ab36
	g_free (source_display_name);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
typedef struct _OpenTargetClientData {
Packit d2ab36
	ECompEditor *comp_editor;
Packit d2ab36
	ESource *source;
Packit d2ab36
	gchar *extension_name;
Packit d2ab36
	EClient *client;
Packit d2ab36
	gchar *cal_email_address;
Packit d2ab36
	gchar *alarm_email_address;
Packit d2ab36
	gboolean is_target_client_change;
Packit d2ab36
	EActivity *activity;
Packit d2ab36
} OpenTargetClientData;
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
open_target_client_data_free (gpointer ptr)
Packit d2ab36
{
Packit d2ab36
	OpenTargetClientData *otc = ptr;
Packit d2ab36
Packit d2ab36
	if (otc) {
Packit d2ab36
		if (otc->comp_editor) {
Packit d2ab36
			if (otc->client) {
Packit d2ab36
				gboolean previous_changed = e_comp_editor_get_changed (otc->comp_editor);
Packit d2ab36
Packit d2ab36
				e_comp_editor_set_alarm_email_address (otc->comp_editor, otc->alarm_email_address);
Packit d2ab36
				e_comp_editor_set_cal_email_address (otc->comp_editor, otc->cal_email_address);
Packit d2ab36
				e_comp_editor_set_target_client (otc->comp_editor, E_CAL_CLIENT (otc->client));
Packit d2ab36
Packit d2ab36
				if (otc->is_target_client_change)
Packit d2ab36
					e_comp_editor_set_changed (otc->comp_editor, TRUE);
Packit d2ab36
				else
Packit d2ab36
					e_comp_editor_set_changed (otc->comp_editor, previous_changed);
Packit d2ab36
			}
Packit d2ab36
Packit d2ab36
			if (otc->comp_editor->priv->activity_bar && otc->activity) {
Packit d2ab36
				if (otc->activity == e_activity_bar_get_activity (otc->comp_editor->priv->activity_bar))
Packit d2ab36
					e_activity_bar_set_activity (otc->comp_editor->priv->activity_bar, NULL);
Packit d2ab36
Packit d2ab36
				if (otc->activity == otc->comp_editor->priv->target_client_opening)
Packit d2ab36
					g_clear_object (&otc->comp_editor->priv->target_client_opening);
Packit d2ab36
			}
Packit d2ab36
Packit d2ab36
			if (otc->source) {
Packit d2ab36
				EShell *shell;
Packit d2ab36
				ECredentialsPrompter *credentials_prompter;
Packit d2ab36
Packit d2ab36
				shell = e_comp_editor_get_shell (otc->comp_editor);
Packit d2ab36
				credentials_prompter = e_shell_get_credentials_prompter (shell);
Packit d2ab36
Packit d2ab36
				e_credentials_prompter_set_auto_prompt_disabled_for (credentials_prompter, otc->source, TRUE);
Packit d2ab36
			}
Packit d2ab36
Packit d2ab36
			e_comp_editor_sensitize_widgets (otc->comp_editor);
Packit d2ab36
		}
Packit d2ab36
Packit d2ab36
		g_clear_object (&otc->comp_editor);
Packit d2ab36
		g_clear_object (&otc->source);
Packit d2ab36
		g_clear_object (&otc->client);
Packit d2ab36
		g_clear_object (&otc->activity);
Packit d2ab36
		g_free (otc->extension_name);
Packit d2ab36
		g_free (otc->cal_email_address);
Packit d2ab36
		g_free (otc->alarm_email_address);
Packit d2ab36
		g_free (otc);
Packit d2ab36
	}
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
comp_editor_open_target_client_thread (EAlertSinkThreadJobData *job_data,
Packit d2ab36
				       gpointer user_data,
Packit d2ab36
				       GCancellable *cancellable,
Packit d2ab36
				       GError **error)
Packit d2ab36
{
Packit d2ab36
	OpenTargetClientData *otc = user_data;
Packit d2ab36
	EClientCache *client_cache;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (otc != NULL);
Packit d2ab36
Packit d2ab36
	if (g_cancellable_set_error_if_cancelled (cancellable, error))
Packit d2ab36
		return;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (otc->comp_editor));
Packit d2ab36
	g_return_if_fail (E_IS_SOURCE (otc->source));
Packit d2ab36
	g_return_if_fail (otc->extension_name != NULL);
Packit d2ab36
Packit d2ab36
	client_cache = e_shell_get_client_cache (e_comp_editor_get_shell (otc->comp_editor));
Packit d2ab36
Packit d2ab36
	otc->client = e_client_cache_get_client_sync (client_cache, otc->source, otc->extension_name,
Packit d2ab36
		30, cancellable, error);
Packit d2ab36
Packit d2ab36
	if (otc->client) {
Packit d2ab36
		/* Cache some properties which require remote calls */
Packit d2ab36
Packit d2ab36
		if (!g_cancellable_is_cancelled (cancellable)) {
Packit d2ab36
			e_client_get_capabilities (otc->client);
Packit d2ab36
		}
Packit d2ab36
Packit d2ab36
		if (!g_cancellable_is_cancelled (cancellable)) {
Packit d2ab36
			e_client_get_backend_property_sync (otc->client,
Packit d2ab36
				CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS,
Packit d2ab36
				&otc->cal_email_address,
Packit d2ab36
				cancellable, error);
Packit d2ab36
		}
Packit d2ab36
Packit d2ab36
		if (!g_cancellable_is_cancelled (cancellable)) {
Packit d2ab36
			e_client_get_backend_property_sync (otc->client,
Packit d2ab36
				CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS,
Packit d2ab36
				&otc->alarm_email_address,
Packit d2ab36
				cancellable, error);
Packit d2ab36
		}
Packit d2ab36
Packit d2ab36
		if (g_cancellable_is_cancelled (cancellable))
Packit d2ab36
			g_clear_object (&otc->client);
Packit d2ab36
	}
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
typedef struct _UpdateActivityBarData {
Packit d2ab36
	ECompEditor *comp_editor;
Packit d2ab36
	EActivity *activity;
Packit d2ab36
} UpdateActivityBarData;
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
update_activity_bar_data_free (gpointer ptr)
Packit d2ab36
{
Packit d2ab36
	UpdateActivityBarData *uab = ptr;
Packit d2ab36
Packit d2ab36
	if (uab) {
Packit d2ab36
		g_clear_object (&uab->comp_editor);
Packit d2ab36
		g_clear_object (&uab->activity);
Packit d2ab36
		g_free (uab);
Packit d2ab36
	}
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static gboolean
Packit d2ab36
update_activity_bar_cb (gpointer user_data)
Packit d2ab36
{
Packit d2ab36
	UpdateActivityBarData *uab = user_data;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (uab != NULL, FALSE);
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (uab->comp_editor), FALSE);
Packit d2ab36
	g_return_val_if_fail (E_IS_ACTIVITY (uab->activity), FALSE);
Packit d2ab36
Packit d2ab36
	if (uab->comp_editor->priv->target_client_opening == uab->activity &&
Packit d2ab36
	    e_activity_get_state (uab->activity) != E_ACTIVITY_CANCELLED &&
Packit d2ab36
	    e_activity_get_state (uab->activity) != E_ACTIVITY_COMPLETED) {
Packit d2ab36
		e_activity_bar_set_activity (uab->comp_editor->priv->activity_bar, uab->activity);
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	return FALSE;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
e_comp_editor_open_target_client (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	OpenTargetClientData *otc;
Packit d2ab36
	ESource *source;
Packit d2ab36
	EActivity *activity;
Packit d2ab36
	ECredentialsPrompter *credentials_prompter;
Packit d2ab36
	gchar *source_display_name, *description = NULL, *alert_ident = NULL, *alert_arg_0 = NULL;
Packit d2ab36
	gboolean is_target_client_change;
Packit d2ab36
	const gchar *extension_name;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
	g_return_if_fail (comp_editor->priv->page_general != NULL);
Packit d2ab36
Packit d2ab36
	source = e_comp_editor_page_general_ref_selected_source (comp_editor->priv->page_general);
Packit d2ab36
	if (!source)
Packit d2ab36
		return;
Packit d2ab36
Packit d2ab36
	if (comp_editor->priv->target_client &&
Packit d2ab36
	    e_client_get_source (E_CLIENT (comp_editor->priv->target_client)) == source) {
Packit d2ab36
		g_clear_object (&source);
Packit d2ab36
		return;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	if (comp_editor->priv->target_client_opening) {
Packit d2ab36
		e_activity_cancel (comp_editor->priv->target_client_opening);
Packit d2ab36
		g_clear_object (&comp_editor->priv->target_client_opening);
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	is_target_client_change = comp_editor->priv->target_client != NULL;
Packit d2ab36
	g_clear_object (&comp_editor->priv->target_client);
Packit d2ab36
Packit d2ab36
	extension_name = e_comp_editor_page_general_get_source_extension_name (comp_editor->priv->page_general);
Packit d2ab36
	source_display_name = e_util_get_source_full_name (
Packit d2ab36
		e_shell_get_registry (e_comp_editor_get_shell (comp_editor)),
Packit d2ab36
		source);
Packit d2ab36
Packit d2ab36
	g_return_if_fail (e_util_get_open_source_job_info (extension_name, source_display_name,
Packit d2ab36
		&description, &alert_ident, &alert_arg_0));
Packit d2ab36
Packit d2ab36
	credentials_prompter = e_shell_get_credentials_prompter (e_comp_editor_get_shell (comp_editor));
Packit d2ab36
	e_credentials_prompter_set_auto_prompt_disabled_for (credentials_prompter, source, FALSE);
Packit d2ab36
Packit d2ab36
	otc = g_new0 (OpenTargetClientData, 1);
Packit d2ab36
	otc->extension_name = g_strdup (extension_name);
Packit d2ab36
	otc->comp_editor = g_object_ref (comp_editor);
Packit d2ab36
	otc->source = g_object_ref (source);
Packit d2ab36
	otc->is_target_client_change = is_target_client_change;
Packit d2ab36
Packit d2ab36
	activity = e_alert_sink_submit_thread_job (
Packit d2ab36
		E_ALERT_SINK (comp_editor), description, alert_ident, alert_arg_0,
Packit d2ab36
		comp_editor_open_target_client_thread, otc,
Packit d2ab36
		open_target_client_data_free);
Packit d2ab36
Packit d2ab36
	otc->activity = g_object_ref (activity);
Packit d2ab36
	comp_editor->priv->target_client_opening = g_object_ref (activity);
Packit d2ab36
Packit d2ab36
	/* Close all alerts */
Packit d2ab36
	while (e_alert_bar_close_alert (comp_editor->priv->alert_bar)) {
Packit d2ab36
		;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	if (comp_editor->priv->activity_bar) {
Packit d2ab36
		UpdateActivityBarData *uab;
Packit d2ab36
Packit d2ab36
		uab = g_new0 (UpdateActivityBarData, 1);
Packit d2ab36
		uab->comp_editor = g_object_ref (comp_editor);
Packit d2ab36
		uab->activity = g_object_ref (activity);
Packit d2ab36
Packit d2ab36
		/* To avoid UI flickering when the source can be opened quickly */
Packit d2ab36
		g_timeout_add_seconds_full (G_PRIORITY_LOW, 1,
Packit d2ab36
			update_activity_bar_cb, uab, update_activity_bar_data_free);
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	g_free (description);
Packit d2ab36
	g_free (alert_ident);
Packit d2ab36
	g_free (alert_arg_0);
Packit d2ab36
	g_free (source_display_name);
Packit d2ab36
	g_clear_object (&source);
Packit d2ab36
	g_clear_object (&activity);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
e_comp_editor_update_window_title (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	ECompEditorClass *comp_editor_class;
Packit d2ab36
	gboolean with_attendees = FALSE;
Packit d2ab36
	const gchar *format, *title_suffix;
Packit d2ab36
	gchar *title;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	if (comp_editor->priv->page_general)
Packit d2ab36
		with_attendees = e_comp_editor_page_general_get_show_attendees (comp_editor->priv->page_general);
Packit d2ab36
Packit d2ab36
	comp_editor_class = E_COMP_EDITOR_GET_CLASS (comp_editor);
Packit d2ab36
	if (with_attendees)
Packit d2ab36
		format = comp_editor_class->title_format_with_attendees;
Packit d2ab36
	else
Packit d2ab36
		format = comp_editor_class->title_format_without_attendees;
Packit d2ab36
Packit d2ab36
	title_suffix = e_comp_editor_get_title_suffix (comp_editor);
Packit d2ab36
Packit d2ab36
	title = g_strdup_printf (format, title_suffix && *title_suffix ? title_suffix : _("No Summary"));
Packit d2ab36
Packit d2ab36
	gtk_window_set_icon_name (GTK_WINDOW (comp_editor), comp_editor_class->icon_name);
Packit d2ab36
	gtk_window_set_title (GTK_WINDOW (comp_editor), title);
Packit d2ab36
Packit d2ab36
	g_free (title);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
e_comp_editor_close (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	g_signal_emit (comp_editor, signals[EDITOR_CLOSED], 0, FALSE, NULL);
Packit d2ab36
Packit d2ab36
	gtk_widget_destroy (GTK_WIDGET (comp_editor));
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
e_comp_editor_save_and_close (ECompEditor *comp_editor,
Packit d2ab36
			      gboolean can_close)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	if (comp_editor->priv->component) {
Packit d2ab36
		icalcomponent *component = icalcomponent_new_clone (comp_editor->priv->component);
Packit d2ab36
		if (component && e_comp_editor_fill_component (comp_editor, component)) {
Packit d2ab36
			ece_save_component (comp_editor, component, TRUE, can_close);
Packit d2ab36
			icalcomponent_free (component);
Packit d2ab36
		}
Packit d2ab36
	}
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static GtkResponseType
Packit d2ab36
ece_save_component_dialog (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	const icalcomponent *component;
Packit d2ab36
	GtkWindow *parent;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), GTK_RESPONSE_NO);
Packit d2ab36
	g_return_val_if_fail (e_comp_editor_get_component (comp_editor) != NULL, GTK_RESPONSE_NO);
Packit d2ab36
Packit d2ab36
	parent = GTK_WINDOW (comp_editor);
Packit d2ab36
	component = e_comp_editor_get_component (comp_editor);
Packit d2ab36
	switch (icalcomponent_isa (component)) {
Packit d2ab36
		case ICAL_VEVENT_COMPONENT:
Packit d2ab36
			if (e_comp_editor_page_general_get_show_attendees (comp_editor->priv->page_general))
Packit d2ab36
				return e_alert_run_dialog_for_args (parent, "calendar:prompt-save-meeting", NULL);
Packit d2ab36
			else
Packit d2ab36
				return e_alert_run_dialog_for_args (parent, "calendar:prompt-save-appointment", NULL);
Packit d2ab36
		case ICAL_VTODO_COMPONENT:
Packit d2ab36
			return e_alert_run_dialog_for_args (parent, "calendar:prompt-save-task", NULL);
Packit d2ab36
		case ICAL_VJOURNAL_COMPONENT:
Packit d2ab36
			return e_alert_run_dialog_for_args (parent, "calendar:prompt-save-memo", NULL);
Packit d2ab36
		default:
Packit d2ab36
			return GTK_RESPONSE_NO;
Packit d2ab36
	}
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static gboolean
Packit d2ab36
e_comp_editor_prompt_and_save_changes (ECompEditor *comp_editor,
Packit d2ab36
				       gboolean with_send)
Packit d2ab36
{
Packit d2ab36
	icalcomponent *component;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), FALSE);
Packit d2ab36
Packit d2ab36
	if (!e_comp_editor_get_changed (comp_editor))
Packit d2ab36
		return TRUE;
Packit d2ab36
Packit d2ab36
	switch (ece_save_component_dialog (comp_editor)) {
Packit d2ab36
	case GTK_RESPONSE_YES: /* Save */
Packit d2ab36
		if (e_client_is_readonly (E_CLIENT (comp_editor->priv->target_client))) {
Packit d2ab36
			e_alert_submit (
Packit d2ab36
				E_ALERT_SINK (comp_editor),
Packit d2ab36
				"calendar:prompt-read-only-cal-editor",
Packit d2ab36
				e_source_get_display_name (
Packit d2ab36
					e_client_get_source (E_CLIENT (comp_editor->priv->target_client))),
Packit d2ab36
				NULL);
Packit d2ab36
			/* don't discard changes when selected readonly calendar */
Packit d2ab36
			return FALSE;
Packit d2ab36
		}
Packit d2ab36
Packit d2ab36
		if (comp_editor->priv->component &&
Packit d2ab36
		    e_comp_editor_page_general_get_show_attendees (comp_editor->priv->page_general) &&
Packit d2ab36
		    icalcomponent_isa (comp_editor->priv->component) == ICAL_VTODO_COMPONENT
Packit d2ab36
		    && e_client_check_capability (E_CLIENT (comp_editor->priv->target_client), CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT)) {
Packit d2ab36
			e_alert_submit (
Packit d2ab36
				E_ALERT_SINK (comp_editor),
Packit d2ab36
				"calendar:prompt-no-task-assignment-editor",
Packit d2ab36
				e_source_get_display_name (
Packit d2ab36
					e_client_get_source (E_CLIENT (comp_editor->priv->target_client))),
Packit d2ab36
				NULL);
Packit d2ab36
			return FALSE;
Packit d2ab36
		}
Packit d2ab36
Packit d2ab36
		component = icalcomponent_new_clone (comp_editor->priv->component);
Packit d2ab36
		if (!e_comp_editor_fill_component (comp_editor, component)) {
Packit d2ab36
			icalcomponent_free (component);
Packit d2ab36
			return FALSE;
Packit d2ab36
		}
Packit d2ab36
Packit d2ab36
		ece_save_component (comp_editor, component, with_send, TRUE);
Packit d2ab36
Packit d2ab36
		return FALSE;
Packit d2ab36
	case GTK_RESPONSE_NO: /* Discard */
Packit d2ab36
		return TRUE;
Packit d2ab36
	case GTK_RESPONSE_CANCEL: /* Cancel */
Packit d2ab36
	default:
Packit d2ab36
		return FALSE;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	return FALSE;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
action_close_cb (GtkAction *action,
Packit d2ab36
                 ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	if (e_comp_editor_prompt_and_save_changes (comp_editor, TRUE))
Packit d2ab36
		e_comp_editor_close (comp_editor);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
action_help_cb (GtkAction *action,
Packit d2ab36
                ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	ECompEditorClass *klass;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	klass = E_COMP_EDITOR_GET_CLASS (comp_editor);
Packit d2ab36
	g_return_if_fail (klass->help_section != NULL);
Packit d2ab36
Packit d2ab36
	e_display_help (GTK_WINDOW (comp_editor), klass->help_section);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
ece_print_or_preview (ECompEditor *comp_editor,
Packit d2ab36
		      GtkPrintOperationAction print_action)
Packit d2ab36
{
Packit d2ab36
	icalcomponent *component;
Packit d2ab36
	ECalComponent *comp;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
	g_return_if_fail (e_comp_editor_get_component (comp_editor) != NULL);
Packit d2ab36
Packit d2ab36
	component = icalcomponent_new_clone (e_comp_editor_get_component (comp_editor));
Packit d2ab36
	if (!e_comp_editor_fill_component (comp_editor, component)) {
Packit d2ab36
		icalcomponent_free (component);
Packit d2ab36
		return;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	comp = e_cal_component_new_from_icalcomponent (component);
Packit d2ab36
	g_return_if_fail (comp != NULL);
Packit d2ab36
Packit d2ab36
	print_comp (comp,
Packit d2ab36
		e_comp_editor_get_target_client (comp_editor),
Packit d2ab36
		calendar_config_get_icaltimezone (),
Packit d2ab36
		calendar_config_get_24_hour_format (),
Packit d2ab36
		print_action);
Packit d2ab36
Packit d2ab36
	g_object_unref (comp);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
action_print_cb (GtkAction *action,
Packit d2ab36
                 ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	ece_print_or_preview (comp_editor, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
action_print_preview_cb (GtkAction *action,
Packit d2ab36
                         ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	ece_print_or_preview (comp_editor, GTK_PRINT_OPERATION_ACTION_PREVIEW);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
action_save_cb (GtkAction *action,
Packit d2ab36
                ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	e_comp_editor_save_and_close (comp_editor, FALSE);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
action_save_and_close_cb (GtkAction *action,
Packit d2ab36
                          ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	e_comp_editor_save_and_close (comp_editor, TRUE);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static gboolean
Packit d2ab36
ece_organizer_email_address_is_user (ECompEditor *comp_editor,
Packit d2ab36
				     EClient *client,
Packit d2ab36
				     const gchar *email_address,
Packit d2ab36
				     gboolean is_organizer)
Packit d2ab36
{
Packit d2ab36
	ESourceRegistry *registry;
Packit d2ab36
	const gchar *cal_email_address;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), FALSE);
Packit d2ab36
	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
Packit d2ab36
Packit d2ab36
	email_address = itip_strip_mailto (email_address);
Packit d2ab36
Packit d2ab36
	if (!email_address || !*email_address)
Packit d2ab36
		return FALSE;
Packit d2ab36
Packit d2ab36
	cal_email_address = e_comp_editor_get_cal_email_address (comp_editor);
Packit d2ab36
	if (cal_email_address && *cal_email_address &&
Packit d2ab36
	    g_ascii_strcasecmp (cal_email_address, email_address) == 0) {
Packit d2ab36
		return TRUE;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	if (is_organizer && e_client_check_capability (client, CAL_STATIC_CAPABILITY_ORGANIZER_NOT_EMAIL_ADDRESS))
Packit d2ab36
		return FALSE;
Packit d2ab36
Packit d2ab36
	registry = e_shell_get_registry (e_comp_editor_get_shell (comp_editor));
Packit d2ab36
Packit d2ab36
	return itip_address_is_user (registry, email_address);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static gboolean
Packit d2ab36
ece_organizer_is_user (ECompEditor *comp_editor,
Packit d2ab36
		       icalcomponent *component,
Packit d2ab36
		       EClient *client)
Packit d2ab36
{
Packit d2ab36
	icalproperty *prop;
Packit d2ab36
	const gchar *organizer;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), FALSE);
Packit d2ab36
	g_return_val_if_fail (component != NULL, FALSE);
Packit d2ab36
	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
Packit d2ab36
Packit d2ab36
	prop = icalcomponent_get_first_property (component, ICAL_ORGANIZER_PROPERTY);
Packit d2ab36
	if (!prop || e_client_check_capability (client, CAL_STATIC_CAPABILITY_NO_ORGANIZER))
Packit d2ab36
		return FALSE;
Packit d2ab36
Packit d2ab36
	organizer = itip_strip_mailto (icalproperty_get_organizer (prop));
Packit d2ab36
	if (!organizer || !*organizer)
Packit d2ab36
		return FALSE;
Packit d2ab36
Packit d2ab36
	return ece_organizer_email_address_is_user (comp_editor, client, organizer, TRUE);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static gboolean
Packit d2ab36
ece_sentby_is_user (ECompEditor *comp_editor,
Packit d2ab36
		    icalcomponent *component,
Packit d2ab36
		    EClient *client)
Packit d2ab36
{
Packit d2ab36
	icalproperty *prop;
Packit d2ab36
	icalparameter *param;
Packit d2ab36
	const gchar *sentby;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), FALSE);
Packit d2ab36
	g_return_val_if_fail (component != NULL, FALSE);
Packit d2ab36
	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
Packit d2ab36
Packit d2ab36
	prop = icalcomponent_get_first_property (component, ICAL_ORGANIZER_PROPERTY);
Packit d2ab36
	if (!prop || e_client_check_capability (client, CAL_STATIC_CAPABILITY_NO_ORGANIZER))
Packit d2ab36
		return FALSE;
Packit d2ab36
Packit d2ab36
	param = icalproperty_get_first_parameter (prop, ICAL_SENTBY_PARAMETER);
Packit d2ab36
	if (!param)
Packit d2ab36
		return FALSE;
Packit d2ab36
Packit d2ab36
	sentby = icalparameter_get_sentby (param);
Packit d2ab36
Packit d2ab36
	return ece_organizer_email_address_is_user (comp_editor, client, sentby, FALSE);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
ece_emit_times_changed_cb (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	g_signal_emit (comp_editor, signals[TIMES_CHANGED], 0, NULL);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
ece_connect_time_parts (ECompEditor *comp_editor,
Packit d2ab36
			ECompEditorPropertyPart *dtstart_part,
Packit d2ab36
			ECompEditorPropertyPart *dtend_part)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
#define update_part(x) G_STMT_START { \
Packit d2ab36
	if (x) \
Packit d2ab36
		g_object_ref (x); \
Packit d2ab36
	if (comp_editor->priv->x) { \
Packit d2ab36
		g_signal_handlers_disconnect_by_func (comp_editor->priv->x, G_CALLBACK (ece_emit_times_changed_cb), comp_editor); \
Packit d2ab36
		g_clear_object (&comp_editor->priv->x); \
Packit d2ab36
	} \
Packit d2ab36
	if (x) { \
Packit d2ab36
		comp_editor->priv->x = x; \
Packit d2ab36
		g_signal_connect_swapped (comp_editor->priv->x, "changed", \
Packit d2ab36
			G_CALLBACK (ece_emit_times_changed_cb), comp_editor); \
Packit d2ab36
	} \
Packit d2ab36
	} G_STMT_END
Packit d2ab36
Packit d2ab36
	update_part (dtstart_part);
Packit d2ab36
	update_part (dtend_part);
Packit d2ab36
Packit d2ab36
#undef update_part
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
ece_sensitize_widgets (ECompEditor *comp_editor,
Packit d2ab36
		       gboolean force_insensitive)
Packit d2ab36
{
Packit d2ab36
	GtkActionGroup *group;
Packit d2ab36
	GSList *link;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	for (link = comp_editor->priv->pages; link; link = g_slist_next (link)) {
Packit d2ab36
		ECompEditorPage *page = link->data;
Packit d2ab36
Packit d2ab36
		g_warn_if_fail (E_IS_COMP_EDITOR_PAGE (page));
Packit d2ab36
		if (!E_IS_COMP_EDITOR_PAGE (page))
Packit d2ab36
			continue;
Packit d2ab36
Packit d2ab36
		e_comp_editor_page_sensitize_widgets (page, force_insensitive);
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	group = e_comp_editor_get_action_group (comp_editor, "individual");
Packit d2ab36
	gtk_action_group_set_sensitive (group, !force_insensitive);
Packit d2ab36
Packit d2ab36
	group = e_comp_editor_get_action_group (comp_editor, "editable");
Packit d2ab36
	gtk_action_group_set_sensitive (group, !force_insensitive);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
ece_fill_widgets (ECompEditor *comp_editor,
Packit d2ab36
		  icalcomponent *component)
Packit d2ab36
{
Packit d2ab36
	GSList *link;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
	g_return_if_fail (component != NULL);
Packit d2ab36
Packit d2ab36
	for (link = comp_editor->priv->pages; link; link = g_slist_next (link)) {
Packit d2ab36
		ECompEditorPage *page = link->data;
Packit d2ab36
Packit d2ab36
		g_warn_if_fail (E_IS_COMP_EDITOR_PAGE (page));
Packit d2ab36
		if (!E_IS_COMP_EDITOR_PAGE (page))
Packit d2ab36
			continue;
Packit d2ab36
Packit d2ab36
		e_comp_editor_page_fill_widgets (page, component);
Packit d2ab36
	}
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static gboolean
Packit d2ab36
ece_fill_component (ECompEditor *comp_editor,
Packit d2ab36
		    icalcomponent *component)
Packit d2ab36
{
Packit d2ab36
	GSList *link;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), FALSE);
Packit d2ab36
	g_return_val_if_fail (component != NULL, FALSE);
Packit d2ab36
Packit d2ab36
	for (link = comp_editor->priv->pages; link; link = g_slist_next (link)) {
Packit d2ab36
		ECompEditorPage *page = link->data;
Packit d2ab36
Packit d2ab36
		g_warn_if_fail (E_IS_COMP_EDITOR_PAGE (page));
Packit d2ab36
		if (!E_IS_COMP_EDITOR_PAGE (page))
Packit d2ab36
			continue;
Packit d2ab36
Packit d2ab36
		if (!e_comp_editor_page_fill_component (page, component))
Packit d2ab36
			return FALSE;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	return TRUE;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
comp_editor_realize_cb (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	if (comp_editor->priv->component) {
Packit d2ab36
		e_comp_editor_fill_widgets (comp_editor, comp_editor->priv->component);
Packit d2ab36
		e_comp_editor_set_changed (comp_editor, FALSE);
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	e_comp_editor_update_window_title (comp_editor);
Packit d2ab36
	e_comp_editor_sensitize_widgets (comp_editor);
Packit d2ab36
Packit d2ab36
	if (comp_editor->priv->page_general && comp_editor->priv->origin_source) {
Packit d2ab36
		e_comp_editor_page_general_set_selected_source (
Packit d2ab36
			comp_editor->priv->page_general,
Packit d2ab36
			comp_editor->priv->origin_source);
Packit d2ab36
		e_comp_editor_set_changed (comp_editor, FALSE);
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	if (comp_editor->priv->page_general) {
Packit d2ab36
		e_comp_editor_page_general_update_view (comp_editor->priv->page_general);
Packit d2ab36
Packit d2ab36
		if (!comp_editor->priv->show_attendees_handler_id) {
Packit d2ab36
			comp_editor->priv->show_attendees_handler_id =
Packit d2ab36
				e_signal_connect_notify_swapped (comp_editor->priv->page_general,
Packit d2ab36
					"notify::show-attendees",
Packit d2ab36
					G_CALLBACK (e_comp_editor_update_window_title), comp_editor);
Packit d2ab36
		}
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	if (!comp_editor->priv->target_client)
Packit d2ab36
		e_comp_editor_open_target_client (comp_editor);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
comp_editor_unrealize_cb (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	if (comp_editor->priv->page_general) {
Packit d2ab36
		e_signal_disconnect_notify_handler (comp_editor->priv->page_general,
Packit d2ab36
			&comp_editor->priv->show_attendees_handler_id);
Packit d2ab36
	}
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static gboolean
Packit d2ab36
comp_editor_delete_event (GtkWidget *widget,
Packit d2ab36
			  GdkEventAny *event)
Packit d2ab36
{
Packit d2ab36
	ECompEditor *comp_editor;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (widget), FALSE);
Packit d2ab36
Packit d2ab36
	comp_editor = E_COMP_EDITOR (widget);
Packit d2ab36
Packit d2ab36
	/* It's disabled when the component is being saved */
Packit d2ab36
	if (gtk_widget_get_sensitive (GTK_WIDGET (comp_editor->priv->content)))
Packit d2ab36
		action_close_cb (NULL, comp_editor);
Packit d2ab36
Packit d2ab36
	return TRUE;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static gboolean
Packit d2ab36
comp_editor_key_press_event (GtkWidget *widget,
Packit d2ab36
			     GdkEventKey *event)
Packit d2ab36
{
Packit d2ab36
	ECompEditor *comp_editor;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (widget), FALSE);
Packit d2ab36
Packit d2ab36
	comp_editor = E_COMP_EDITOR (widget);
Packit d2ab36
Packit d2ab36
	if (event->keyval == GDK_KEY_Escape &&
Packit d2ab36
	    !e_alert_bar_close_alert (comp_editor->priv->alert_bar)) {
Packit d2ab36
		GtkAction *action;
Packit d2ab36
Packit d2ab36
		action = e_comp_editor_get_action (comp_editor, "close");
Packit d2ab36
		gtk_action_activate (action);
Packit d2ab36
Packit d2ab36
		return TRUE;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	/* Chain up to parent's method. */
Packit d2ab36
	return GTK_WIDGET_CLASS (e_comp_editor_parent_class)->key_press_event (widget, event);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
comp_editor_selected_source_notify_cb (ECompEditorPageGeneral *page_general,
Packit d2ab36
				       GParamSpec *param,
Packit d2ab36
				       ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general));
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
	g_return_if_fail (comp_editor->priv->page_general == page_general);
Packit d2ab36
Packit d2ab36
	e_comp_editor_open_target_client (comp_editor);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
e_comp_editor_submit_alert (EAlertSink *alert_sink,
Packit d2ab36
			    EAlert *alert)
Packit d2ab36
{
Packit d2ab36
	ECompEditor *comp_editor;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (alert_sink));
Packit d2ab36
	g_return_if_fail (E_IS_ALERT (alert));
Packit d2ab36
Packit d2ab36
	comp_editor = E_COMP_EDITOR (alert_sink);
Packit d2ab36
Packit d2ab36
	e_alert_bar_submit_alert (comp_editor->priv->alert_bar, alert);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
e_comp_editor_set_origin_source (ECompEditor *comp_editor,
Packit d2ab36
				 ESource *origin_source)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
	if (origin_source)
Packit d2ab36
		g_return_if_fail (E_IS_SOURCE (origin_source));
Packit d2ab36
Packit d2ab36
	g_clear_object (&comp_editor->priv->origin_source);
Packit d2ab36
	if (origin_source)
Packit d2ab36
		comp_editor->priv->origin_source = g_object_ref (origin_source);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
e_comp_editor_set_shell (ECompEditor *comp_editor,
Packit d2ab36
			 EShell *shell)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
	g_return_if_fail (E_IS_SHELL (shell));
Packit d2ab36
Packit d2ab36
	g_clear_object (&comp_editor->priv->shell);
Packit d2ab36
	comp_editor->priv->shell = g_object_ref (shell);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
e_comp_editor_set_property (GObject *object,
Packit d2ab36
			    guint property_id,
Packit d2ab36
			    const GValue *value,
Packit d2ab36
			    GParamSpec *pspec)
Packit d2ab36
{
Packit d2ab36
	switch (property_id) {
Packit d2ab36
		case PROP_ALARM_EMAIL_ADDRESS:
Packit d2ab36
			e_comp_editor_set_alarm_email_address (
Packit d2ab36
				E_COMP_EDITOR (object),
Packit d2ab36
				g_value_get_string (value));
Packit d2ab36
			return;
Packit d2ab36
Packit d2ab36
		case PROP_CAL_EMAIL_ADDRESS:
Packit d2ab36
			e_comp_editor_set_cal_email_address (
Packit d2ab36
				E_COMP_EDITOR (object),
Packit d2ab36
				g_value_get_string (value));
Packit d2ab36
			return;
Packit d2ab36
Packit d2ab36
		case PROP_CHANGED:
Packit d2ab36
			e_comp_editor_set_changed (
Packit d2ab36
				E_COMP_EDITOR (object),
Packit d2ab36
				g_value_get_boolean (value));
Packit d2ab36
			return;
Packit d2ab36
Packit d2ab36
		case PROP_COMPONENT:
Packit d2ab36
			e_comp_editor_set_component (
Packit d2ab36
				E_COMP_EDITOR (object),
Packit d2ab36
				g_value_get_pointer (value));
Packit d2ab36
			return;
Packit d2ab36
Packit d2ab36
		case PROP_FLAGS:
Packit d2ab36
			e_comp_editor_set_flags (
Packit d2ab36
				E_COMP_EDITOR (object),
Packit d2ab36
				g_value_get_uint (value));
Packit d2ab36
			return;
Packit d2ab36
Packit d2ab36
		case PROP_ORIGIN_SOURCE:
Packit d2ab36
			e_comp_editor_set_origin_source (
Packit d2ab36
				E_COMP_EDITOR (object),
Packit d2ab36
				g_value_get_object (value));
Packit d2ab36
			return;
Packit d2ab36
Packit d2ab36
		case PROP_SHELL:
Packit d2ab36
			e_comp_editor_set_shell (
Packit d2ab36
				E_COMP_EDITOR (object),
Packit d2ab36
				g_value_get_object (value));
Packit d2ab36
			return;
Packit d2ab36
Packit d2ab36
		case PROP_SOURCE_CLIENT:
Packit d2ab36
			e_comp_editor_set_source_client (
Packit d2ab36
				E_COMP_EDITOR (object),
Packit d2ab36
				g_value_get_object (value));
Packit d2ab36
			return;
Packit d2ab36
Packit d2ab36
		case PROP_TARGET_CLIENT:
Packit d2ab36
			e_comp_editor_set_target_client (
Packit d2ab36
				E_COMP_EDITOR (object),
Packit d2ab36
				g_value_get_object (value));
Packit d2ab36
			return;
Packit d2ab36
Packit d2ab36
		case PROP_TITLE_SUFFIX:
Packit d2ab36
			e_comp_editor_set_title_suffix (
Packit d2ab36
				E_COMP_EDITOR (object),
Packit d2ab36
				g_value_get_string (value));
Packit d2ab36
			return;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
e_comp_editor_get_property (GObject *object,
Packit d2ab36
			    guint property_id,
Packit d2ab36
			    GValue *value,
Packit d2ab36
			    GParamSpec *pspec)
Packit d2ab36
{
Packit d2ab36
	switch (property_id) {
Packit d2ab36
		case PROP_ALARM_EMAIL_ADDRESS:
Packit d2ab36
			g_value_set_string (
Packit d2ab36
				value,
Packit d2ab36
				e_comp_editor_get_alarm_email_address (
Packit d2ab36
				E_COMP_EDITOR (object)));
Packit d2ab36
			return;
Packit d2ab36
Packit d2ab36
		case PROP_CAL_EMAIL_ADDRESS:
Packit d2ab36
			g_value_set_string (
Packit d2ab36
				value,
Packit d2ab36
				e_comp_editor_get_cal_email_address (
Packit d2ab36
				E_COMP_EDITOR (object)));
Packit d2ab36
			return;
Packit d2ab36
Packit d2ab36
		case PROP_CHANGED:
Packit d2ab36
			g_value_set_boolean (
Packit d2ab36
				value,
Packit d2ab36
				e_comp_editor_get_changed (
Packit d2ab36
				E_COMP_EDITOR (object)));
Packit d2ab36
			return;
Packit d2ab36
Packit d2ab36
		case PROP_COMPONENT:
Packit d2ab36
			g_value_set_pointer (
Packit d2ab36
				value,
Packit d2ab36
				e_comp_editor_get_component (
Packit d2ab36
				E_COMP_EDITOR (object)));
Packit d2ab36
			return;
Packit d2ab36
Packit d2ab36
		case PROP_FLAGS:
Packit d2ab36
			g_value_set_uint (
Packit d2ab36
				value,
Packit d2ab36
				e_comp_editor_get_flags (
Packit d2ab36
				E_COMP_EDITOR (object)));
Packit d2ab36
			return;
Packit d2ab36
Packit d2ab36
		case PROP_ORIGIN_SOURCE:
Packit d2ab36
			g_value_set_object (
Packit d2ab36
				value,
Packit d2ab36
				e_comp_editor_get_origin_source (
Packit d2ab36
				E_COMP_EDITOR (object)));
Packit d2ab36
			return;
Packit d2ab36
Packit d2ab36
		case PROP_SHELL:
Packit d2ab36
			g_value_set_object (
Packit d2ab36
				value,
Packit d2ab36
				e_comp_editor_get_shell (
Packit d2ab36
				E_COMP_EDITOR (object)));
Packit d2ab36
			return;
Packit d2ab36
Packit d2ab36
		case PROP_SOURCE_CLIENT:
Packit d2ab36
			g_value_set_object (
Packit d2ab36
				value,
Packit d2ab36
				e_comp_editor_get_source_client (
Packit d2ab36
				E_COMP_EDITOR (object)));
Packit d2ab36
			return;
Packit d2ab36
Packit d2ab36
		case PROP_TARGET_CLIENT:
Packit d2ab36
			g_value_set_object (
Packit d2ab36
				value,
Packit d2ab36
				e_comp_editor_get_target_client (
Packit d2ab36
				E_COMP_EDITOR (object)));
Packit d2ab36
			return;
Packit d2ab36
Packit d2ab36
		case PROP_TITLE_SUFFIX:
Packit d2ab36
			g_value_set_string (
Packit d2ab36
				value,
Packit d2ab36
				e_comp_editor_get_title_suffix (
Packit d2ab36
				E_COMP_EDITOR (object)));
Packit d2ab36
			return;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
e_comp_editor_constructed (GObject *object)
Packit d2ab36
{
Packit d2ab36
	const gchar *ui =
Packit d2ab36
		"<ui>"
Packit d2ab36
		"  <menubar action='main-menu'>"
Packit d2ab36
		"    <menu action='file-menu'>"
Packit d2ab36
		"      <menuitem action='save'/>"
Packit d2ab36
		"      <menuitem action='save-and-close'/>"
Packit d2ab36
		"      <separator/>"
Packit d2ab36
		"      <placeholder name='custom-actions-placeholder'/>"
Packit d2ab36
		"      <separator/>"
Packit d2ab36
		"      <menuitem action='print-preview'/>"
Packit d2ab36
		"      <menuitem action='print'/>"
Packit d2ab36
		"      <separator/>"
Packit d2ab36
		"      <menuitem action='close'/>"
Packit d2ab36
		"    </menu>"
Packit d2ab36
		"    <menu action='edit-menu'>"
Packit d2ab36
		"      <menuitem action='undo'/>"
Packit d2ab36
		"      <menuitem action='redo'/>"
Packit d2ab36
		"      <separator/>"
Packit d2ab36
		"      <menuitem action='cut-clipboard'/>"
Packit d2ab36
		"      <menuitem action='copy-clipboard'/>"
Packit d2ab36
		"      <menuitem action='paste-clipboard'/>"
Packit d2ab36
		"      <menuitem action='delete-selection'/>"
Packit d2ab36
		"      <separator/>"
Packit d2ab36
		"      <menuitem action='select-all'/>"
Packit d2ab36
		"    </menu>"
Packit d2ab36
		"    <menu action='view-menu'>"
Packit d2ab36
		"      <placeholder name='parts'/>"
Packit d2ab36
		"      <separator />"
Packit d2ab36
		"      <placeholder name='columns'/>"
Packit d2ab36
		"    </menu>"
Packit d2ab36
		"    <menu action='insert-menu'/>"
Packit d2ab36
		"    <menu action='options-menu'>"
Packit d2ab36
		"      <placeholder name='tabs'/>"
Packit d2ab36
		"      <placeholder name='toggles'/>"
Packit d2ab36
		"    </menu>"
Packit d2ab36
		"    <menu action='help-menu'>"
Packit d2ab36
		"      <menuitem action='help'/>"
Packit d2ab36
		"    </menu>"
Packit d2ab36
		"  </menubar>"
Packit d2ab36
		"  <toolbar name='main-toolbar'>"
Packit d2ab36
		"    <toolitem action='save-and-close'/>\n"
Packit d2ab36
		"    <toolitem action='save'/>"
Packit d2ab36
		"    <toolitem action='print'/>"
Packit d2ab36
		"    <separator/>"
Packit d2ab36
		"    <toolitem action='undo'/>"
Packit d2ab36
		"    <toolitem action='redo'/>"
Packit d2ab36
		"    <separator/>"
Packit d2ab36
		"    <placeholder name='content'/>"
Packit d2ab36
		"    <placeholder name='after-content'/>"
Packit d2ab36
		"  </toolbar>"
Packit d2ab36
		"</ui>";
Packit d2ab36
Packit d2ab36
	GtkActionEntry core_entries[] = {
Packit d2ab36
Packit d2ab36
		{ "close",
Packit d2ab36
		  "window-close",
Packit d2ab36
		  N_("_Close"),
Packit d2ab36
		  "<Control>w",
Packit d2ab36
		  N_("Close the current window"),
Packit d2ab36
		  G_CALLBACK (action_close_cb) },
Packit d2ab36
Packit d2ab36
		{ "copy-clipboard",
Packit d2ab36
		  "edit-copy",
Packit d2ab36
		  N_("_Copy"),
Packit d2ab36
		  "<Control>c",
Packit d2ab36
		  N_("Copy the selection"),
Packit d2ab36
		  NULL },  /* Handled by EFocusTracker */
Packit d2ab36
Packit d2ab36
		{ "cut-clipboard",
Packit d2ab36
		  "edit-cut",
Packit d2ab36
		  N_("Cu_t"),
Packit d2ab36
		  "<Control>x",
Packit d2ab36
		  N_("Cut the selection"),
Packit d2ab36
		  NULL },  /* Handled by EFocusTracker */
Packit d2ab36
Packit d2ab36
		{ "delete-selection",
Packit d2ab36
		  "edit-delete",
Packit d2ab36
		  N_("_Delete"),
Packit d2ab36
		  NULL,
Packit d2ab36
		  N_("Delete the selection"),
Packit d2ab36
		  NULL },  /* Handled by EFocusTracker */
Packit d2ab36
Packit d2ab36
		{ "help",
Packit d2ab36
		  "help-browser",
Packit d2ab36
		  N_("_Help"),
Packit d2ab36
		  "F1",
Packit d2ab36
		  N_("View help"),
Packit d2ab36
		  G_CALLBACK (action_help_cb) },
Packit d2ab36
Packit d2ab36
		{ "paste-clipboard",
Packit d2ab36
		  "edit-paste",
Packit d2ab36
		  N_("_Paste"),
Packit d2ab36
		  "<Control>v",
Packit d2ab36
		  N_("Paste the clipboard"),
Packit d2ab36
		  NULL },  /* Handled by EFocusTracker */
Packit d2ab36
Packit d2ab36
		{ "print",
Packit d2ab36
		  "document-print",
Packit d2ab36
		  N_("_Print..."),
Packit d2ab36
		  "<Control>p",
Packit d2ab36
		  NULL,
Packit d2ab36
		  G_CALLBACK (action_print_cb) },
Packit d2ab36
Packit d2ab36
		{ "print-preview",
Packit d2ab36
		  "document-print-preview",
Packit d2ab36
		  N_("Pre_view..."),
Packit d2ab36
		  NULL,
Packit d2ab36
		  NULL,
Packit d2ab36
		  G_CALLBACK (action_print_preview_cb) },
Packit d2ab36
Packit d2ab36
		{ "select-all",
Packit d2ab36
		  "edit-select-all",
Packit d2ab36
		  N_("Select _All"),
Packit d2ab36
		  "<Control>a",
Packit d2ab36
		  N_("Select all text"),
Packit d2ab36
		  NULL },  /* Handled by EFocusTracker */
Packit d2ab36
Packit d2ab36
		{ "undo",
Packit d2ab36
		  "edit-undo",
Packit d2ab36
		  N_("_Undo"),
Packit d2ab36
		  "<Control>z",
Packit d2ab36
		  N_("Undo"),
Packit d2ab36
		  NULL },  /* Handled by EFocusTracker */
Packit d2ab36
Packit d2ab36
		{ "redo",
Packit d2ab36
		  "edit-redo",
Packit d2ab36
		  N_("_Redo"),
Packit d2ab36
		  "<Control>y",
Packit d2ab36
		  N_("Redo"),
Packit d2ab36
		  NULL },  /* Handled by EFocusTracker */
Packit d2ab36
Packit d2ab36
		/* Menus */
Packit d2ab36
Packit d2ab36
		{ "classification-menu",
Packit d2ab36
		  NULL,
Packit d2ab36
		  N_("_Classification"),
Packit d2ab36
		  NULL,
Packit d2ab36
		  NULL,
Packit d2ab36
		  NULL },
Packit d2ab36
Packit d2ab36
		{ "edit-menu",
Packit d2ab36
		  NULL,
Packit d2ab36
		  N_("_Edit"),
Packit d2ab36
		  NULL,
Packit d2ab36
		  NULL,
Packit d2ab36
		  NULL },
Packit d2ab36
Packit d2ab36
		{ "file-menu",
Packit d2ab36
		  NULL,
Packit d2ab36
		  N_("_File"),
Packit d2ab36
		  NULL,
Packit d2ab36
		  NULL,
Packit d2ab36
		  NULL },
Packit d2ab36
Packit d2ab36
		{ "help-menu",
Packit d2ab36
		  NULL,
Packit d2ab36
		  N_("_Help"),
Packit d2ab36
		  NULL,
Packit d2ab36
		  NULL,
Packit d2ab36
		  NULL },
Packit d2ab36
Packit d2ab36
		{ "insert-menu",
Packit d2ab36
		  NULL,
Packit d2ab36
		  N_("_Insert"),
Packit d2ab36
		  NULL,
Packit d2ab36
		  NULL,
Packit d2ab36
		  NULL },
Packit d2ab36
Packit d2ab36
		{ "options-menu",
Packit d2ab36
		  NULL,
Packit d2ab36
		  N_("_Options"),
Packit d2ab36
		  NULL,
Packit d2ab36
		  NULL,
Packit d2ab36
		  NULL },
Packit d2ab36
Packit d2ab36
		{ "view-menu",
Packit d2ab36
		  NULL,
Packit d2ab36
		  N_("_View"),
Packit d2ab36
		  NULL,
Packit d2ab36
		  NULL,
Packit d2ab36
		  NULL }
Packit d2ab36
	};
Packit d2ab36
Packit d2ab36
	GtkActionEntry editable_entries[] = {
Packit d2ab36
Packit d2ab36
		{ "save",
Packit d2ab36
		  "document-save",
Packit d2ab36
		  N_("_Save"),
Packit d2ab36
		  "<Control>s",
Packit d2ab36
		  N_("Save current changes"),
Packit d2ab36
		  G_CALLBACK (action_save_cb) },
Packit d2ab36
Packit d2ab36
		{ "save-and-close",
Packit d2ab36
		  NULL,
Packit d2ab36
		  N_("Save and Close"),
Packit d2ab36
		  NULL,
Packit d2ab36
		  N_("Save current changes and close editor"),
Packit d2ab36
		  G_CALLBACK (action_save_and_close_cb) }
Packit d2ab36
	};
Packit d2ab36
Packit d2ab36
	ECompEditor *comp_editor = E_COMP_EDITOR (object);
Packit d2ab36
	GtkWidget *widget;
Packit d2ab36
	GtkBox *vbox;
Packit d2ab36
	GtkAction *action;
Packit d2ab36
	GtkActionGroup *action_group;
Packit d2ab36
	EFocusTracker *focus_tracker;
Packit d2ab36
	GError *error = NULL;
Packit d2ab36
Packit d2ab36
	G_OBJECT_CLASS (e_comp_editor_parent_class)->constructed (object);
Packit d2ab36
Packit d2ab36
	g_signal_connect (comp_editor, "key-press-event",
Packit d2ab36
		G_CALLBACK (e_util_check_gtk_bindings_in_key_press_event_cb), NULL);
Packit d2ab36
Packit d2ab36
	comp_editor->priv->calendar_settings = e_util_ref_settings ("org.gnome.evolution.calendar");
Packit d2ab36
	comp_editor->priv->ui_manager = gtk_ui_manager_new ();
Packit d2ab36
Packit d2ab36
	gtk_window_add_accel_group (
Packit d2ab36
		GTK_WINDOW (comp_editor),
Packit d2ab36
		gtk_ui_manager_get_accel_group (comp_editor->priv->ui_manager));
Packit d2ab36
Packit d2ab36
	/* Setup Action Groups */
Packit d2ab36
Packit d2ab36
	action_group = gtk_action_group_new ("individual");
Packit d2ab36
	gtk_action_group_set_translation_domain (
Packit d2ab36
		action_group, GETTEXT_PACKAGE);
Packit d2ab36
	gtk_ui_manager_insert_action_group (
Packit d2ab36
		comp_editor->priv->ui_manager, action_group, 0);
Packit d2ab36
	g_object_unref (action_group);
Packit d2ab36
Packit d2ab36
	action_group = gtk_action_group_new ("core");
Packit d2ab36
	gtk_action_group_set_translation_domain (
Packit d2ab36
		action_group, GETTEXT_PACKAGE);
Packit d2ab36
	gtk_action_group_add_actions (
Packit d2ab36
		action_group, core_entries,
Packit d2ab36
		G_N_ELEMENTS (core_entries), comp_editor);
Packit d2ab36
	gtk_ui_manager_insert_action_group (
Packit d2ab36
		comp_editor->priv->ui_manager, action_group, 0);
Packit d2ab36
	g_object_unref (action_group);
Packit d2ab36
Packit d2ab36
	action_group = gtk_action_group_new ("editable");
Packit d2ab36
	gtk_action_group_set_translation_domain (
Packit d2ab36
		action_group, GETTEXT_PACKAGE);
Packit d2ab36
	gtk_action_group_add_actions (
Packit d2ab36
		action_group, editable_entries,
Packit d2ab36
		G_N_ELEMENTS (editable_entries), comp_editor);
Packit d2ab36
	gtk_ui_manager_insert_action_group (
Packit d2ab36
		comp_editor->priv->ui_manager, action_group, 0);
Packit d2ab36
	g_object_unref (action_group);
Packit d2ab36
Packit d2ab36
	action = gtk_action_group_get_action (action_group, "save-and-close");
Packit d2ab36
	if (action) {
Packit d2ab36
		GtkAction *save_action;
Packit d2ab36
		GIcon *icon;
Packit d2ab36
		GIcon *emblemed_icon;
Packit d2ab36
		GEmblem *emblem;
Packit d2ab36
Packit d2ab36
		icon = g_themed_icon_new ("window-close");
Packit d2ab36
		emblemed_icon = g_themed_icon_new ("document-save");
Packit d2ab36
		emblem = g_emblem_new (emblemed_icon);
Packit d2ab36
		g_object_unref (emblemed_icon);
Packit d2ab36
Packit d2ab36
		emblemed_icon = g_emblemed_icon_new (icon, emblem);
Packit d2ab36
		g_object_unref (emblem);
Packit d2ab36
		g_object_unref (icon);
Packit d2ab36
Packit d2ab36
		gtk_action_set_gicon (action, emblemed_icon);
Packit d2ab36
Packit d2ab36
		g_object_unref (emblemed_icon);
Packit d2ab36
Packit d2ab36
		save_action = gtk_action_group_get_action (action_group, "save");
Packit d2ab36
		e_binding_bind_property (
Packit d2ab36
			save_action, "sensitive",
Packit d2ab36
			action, "sensitive",
Packit d2ab36
			G_BINDING_SYNC_CREATE);
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	gtk_ui_manager_add_ui_from_string (comp_editor->priv->ui_manager, ui, -1, &error);
Packit d2ab36
	if (error != NULL) {
Packit d2ab36
		g_warning ("%s: %s", G_STRFUNC, error->message);
Packit d2ab36
		g_error_free (error);
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
Packit d2ab36
	g_object_set (G_OBJECT (widget),
Packit d2ab36
		"hexpand", TRUE,
Packit d2ab36
		"halign", GTK_ALIGN_FILL,
Packit d2ab36
		"vexpand", TRUE,
Packit d2ab36
		"valign", GTK_ALIGN_FILL,
Packit d2ab36
		NULL);
Packit d2ab36
	gtk_widget_show (widget);
Packit d2ab36
Packit d2ab36
	vbox = GTK_BOX (widget);
Packit d2ab36
Packit d2ab36
	gtk_container_add (GTK_CONTAINER (comp_editor), widget);
Packit d2ab36
Packit d2ab36
	widget = e_comp_editor_get_managed_widget (comp_editor, "/main-menu");
Packit d2ab36
	gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
Packit d2ab36
	gtk_widget_set_visible (widget, TRUE);
Packit d2ab36
Packit d2ab36
	widget = e_comp_editor_get_managed_widget (comp_editor, "/main-toolbar");
Packit d2ab36
	gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
Packit d2ab36
	gtk_widget_show (widget);
Packit d2ab36
Packit d2ab36
	gtk_style_context_add_class (
Packit d2ab36
		gtk_widget_get_style_context (widget),
Packit d2ab36
		GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
Packit d2ab36
Packit d2ab36
	widget = e_alert_bar_new ();
Packit d2ab36
	g_object_set (G_OBJECT (widget),
Packit d2ab36
		"hexpand", FALSE,
Packit d2ab36
		"halign", GTK_ALIGN_FILL,
Packit d2ab36
		"vexpand", FALSE,
Packit d2ab36
		"valign", GTK_ALIGN_START,
Packit d2ab36
		NULL);
Packit d2ab36
Packit d2ab36
	comp_editor->priv->alert_bar = E_ALERT_BAR (widget);
Packit d2ab36
Packit d2ab36
	gtk_box_pack_start (vbox, widget, FALSE, FALSE, 0);
Packit d2ab36
Packit d2ab36
	widget = e_activity_bar_new ();
Packit d2ab36
	g_object_set (G_OBJECT (widget),
Packit d2ab36
		"hexpand", FALSE,
Packit d2ab36
		"halign", GTK_ALIGN_FILL,
Packit d2ab36
		"vexpand", FALSE,
Packit d2ab36
		"valign", GTK_ALIGN_START,
Packit d2ab36
		NULL);
Packit d2ab36
Packit d2ab36
	comp_editor->priv->activity_bar = E_ACTIVITY_BAR (widget);
Packit d2ab36
Packit d2ab36
	gtk_box_pack_start (vbox, widget, FALSE, FALSE, 0);
Packit d2ab36
Packit d2ab36
	widget = gtk_notebook_new ();
Packit d2ab36
	g_object_set (G_OBJECT (widget),
Packit d2ab36
		"hexpand", TRUE,
Packit d2ab36
		"halign", GTK_ALIGN_FILL,
Packit d2ab36
		"vexpand", TRUE,
Packit d2ab36
		"valign", GTK_ALIGN_FILL,
Packit d2ab36
		"show-tabs", TRUE,
Packit d2ab36
		"show-border", FALSE,
Packit d2ab36
		NULL);
Packit d2ab36
	gtk_widget_show (widget);
Packit d2ab36
Packit d2ab36
	comp_editor->priv->content = GTK_NOTEBOOK (widget);
Packit d2ab36
Packit d2ab36
	gtk_box_pack_start (vbox, widget, TRUE, TRUE, 0);
Packit d2ab36
Packit d2ab36
	/* Configure an EFocusTracker to manage selection actions. */
Packit d2ab36
Packit d2ab36
	focus_tracker = e_focus_tracker_new (GTK_WINDOW (comp_editor));
Packit d2ab36
Packit d2ab36
	action = e_comp_editor_get_action (comp_editor, "cut-clipboard");
Packit d2ab36
	e_focus_tracker_set_cut_clipboard_action (focus_tracker, action);
Packit d2ab36
Packit d2ab36
	action = e_comp_editor_get_action (comp_editor, "copy-clipboard");
Packit d2ab36
	e_focus_tracker_set_copy_clipboard_action (focus_tracker, action);
Packit d2ab36
Packit d2ab36
	action = e_comp_editor_get_action (comp_editor, "paste-clipboard");
Packit d2ab36
	e_focus_tracker_set_paste_clipboard_action (focus_tracker, action);
Packit d2ab36
Packit d2ab36
	action = e_comp_editor_get_action (comp_editor, "delete-selection");
Packit d2ab36
	e_focus_tracker_set_delete_selection_action (focus_tracker, action);
Packit d2ab36
Packit d2ab36
	action = e_comp_editor_get_action (comp_editor, "select-all");
Packit d2ab36
	e_focus_tracker_set_select_all_action (focus_tracker, action);
Packit d2ab36
Packit d2ab36
	action = e_comp_editor_get_action (comp_editor, "undo");
Packit d2ab36
	e_focus_tracker_set_undo_action (focus_tracker, action);
Packit d2ab36
Packit d2ab36
	action = e_comp_editor_get_action (comp_editor, "redo");
Packit d2ab36
	e_focus_tracker_set_redo_action (focus_tracker, action);
Packit d2ab36
Packit d2ab36
	comp_editor->priv->focus_tracker = focus_tracker;
Packit d2ab36
Packit d2ab36
	/* Desensitize the "save" action. */
Packit d2ab36
	action = e_comp_editor_get_action (comp_editor, "save");
Packit d2ab36
	gtk_action_set_sensitive (action, FALSE);
Packit d2ab36
Packit d2ab36
	e_binding_bind_property (comp_editor, "changed", action, "sensitive", 0);
Packit d2ab36
Packit d2ab36
	g_signal_connect (comp_editor, "realize", G_CALLBACK (comp_editor_realize_cb), NULL);
Packit d2ab36
	g_signal_connect (comp_editor, "unrealize", G_CALLBACK (comp_editor_unrealize_cb), NULL);
Packit d2ab36
Packit d2ab36
	gtk_application_add_window (GTK_APPLICATION (comp_editor->priv->shell), GTK_WINDOW (comp_editor));
Packit d2ab36
Packit d2ab36
	e_extensible_load_extensions (E_EXTENSIBLE (comp_editor));
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
e_comp_editor_dispose (GObject *object)
Packit d2ab36
{
Packit d2ab36
	ECompEditor *comp_editor = E_COMP_EDITOR (object);
Packit d2ab36
Packit d2ab36
	if (comp_editor->priv->page_general) {
Packit d2ab36
		g_signal_handlers_disconnect_by_func (comp_editor->priv->page_general,
Packit d2ab36
			G_CALLBACK (comp_editor_selected_source_notify_cb), comp_editor);
Packit d2ab36
		comp_editor->priv->page_general = NULL;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	if (comp_editor->priv->target_client_opening) {
Packit d2ab36
		e_activity_cancel (comp_editor->priv->target_client_opening);
Packit d2ab36
		g_clear_object (&comp_editor->priv->target_client_opening);
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	g_slist_free_full (comp_editor->priv->pages, g_object_unref);
Packit d2ab36
	comp_editor->priv->pages = NULL;
Packit d2ab36
Packit d2ab36
	g_free (comp_editor->priv->alarm_email_address);
Packit d2ab36
	comp_editor->priv->alarm_email_address = NULL;
Packit d2ab36
Packit d2ab36
	g_free (comp_editor->priv->cal_email_address);
Packit d2ab36
	comp_editor->priv->cal_email_address = NULL;
Packit d2ab36
Packit d2ab36
	g_free (comp_editor->priv->title_suffix);
Packit d2ab36
	comp_editor->priv->title_suffix = NULL;
Packit d2ab36
Packit d2ab36
	if (comp_editor->priv->component) {
Packit d2ab36
		icalcomponent_free (comp_editor->priv->component);
Packit d2ab36
		comp_editor->priv->component = NULL;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	ece_connect_time_parts (comp_editor, NULL, NULL);
Packit d2ab36
Packit d2ab36
	g_clear_object (&comp_editor->priv->origin_source);
Packit d2ab36
	g_clear_object (&comp_editor->priv->shell);
Packit d2ab36
	g_clear_object (&comp_editor->priv->focus_tracker);
Packit d2ab36
	g_clear_object (&comp_editor->priv->ui_manager);
Packit d2ab36
	g_clear_object (&comp_editor->priv->source_client);
Packit d2ab36
	g_clear_object (&comp_editor->priv->target_client);
Packit d2ab36
	g_clear_object (&comp_editor->priv->calendar_settings);
Packit d2ab36
	g_clear_object (&comp_editor->priv->validation_alert);
Packit d2ab36
Packit d2ab36
	comp_editor->priv->activity_bar = NULL;
Packit d2ab36
Packit d2ab36
	opened_editors = g_slist_remove (opened_editors, comp_editor);
Packit d2ab36
Packit d2ab36
	G_OBJECT_CLASS (e_comp_editor_parent_class)->dispose (object);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
e_comp_editor_init (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	comp_editor->priv = G_TYPE_INSTANCE_GET_PRIVATE (comp_editor, E_TYPE_COMP_EDITOR, ECompEditorPrivate);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
e_comp_editor_alert_sink_iface_init (EAlertSinkInterface *iface)
Packit d2ab36
{
Packit d2ab36
	iface->submit_alert = e_comp_editor_submit_alert;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static void
Packit d2ab36
e_comp_editor_class_init (ECompEditorClass *klass)
Packit d2ab36
{
Packit d2ab36
	GtkWidgetClass *widget_class;
Packit d2ab36
	GObjectClass *object_class;
Packit d2ab36
Packit d2ab36
	g_type_class_add_private (klass, sizeof (ECompEditorPrivate));
Packit d2ab36
Packit d2ab36
	klass->sensitize_widgets = ece_sensitize_widgets;
Packit d2ab36
	klass->fill_widgets = ece_fill_widgets;
Packit d2ab36
	klass->fill_component = ece_fill_component;
Packit d2ab36
Packit d2ab36
	widget_class = GTK_WIDGET_CLASS (klass);
Packit d2ab36
	widget_class->delete_event = comp_editor_delete_event;
Packit d2ab36
	widget_class->key_press_event = comp_editor_key_press_event;
Packit d2ab36
Packit d2ab36
	object_class = G_OBJECT_CLASS (klass);
Packit d2ab36
	object_class->set_property = e_comp_editor_set_property;
Packit d2ab36
	object_class->get_property = e_comp_editor_get_property;
Packit d2ab36
	object_class->constructed = e_comp_editor_constructed;
Packit d2ab36
	object_class->dispose = e_comp_editor_dispose;
Packit d2ab36
Packit d2ab36
	g_object_class_install_property (
Packit d2ab36
		object_class,
Packit d2ab36
		PROP_ALARM_EMAIL_ADDRESS,
Packit d2ab36
		g_param_spec_string (
Packit d2ab36
			"alarm-email-address",
Packit d2ab36
			"Alarm Email Address",
Packit d2ab36
			"Target client's alarm email address",
Packit d2ab36
			NULL,
Packit d2ab36
			G_PARAM_READWRITE |
Packit d2ab36
			G_PARAM_STATIC_STRINGS));
Packit d2ab36
Packit d2ab36
	g_object_class_install_property (
Packit d2ab36
		object_class,
Packit d2ab36
		PROP_CAL_EMAIL_ADDRESS,
Packit d2ab36
		g_param_spec_string (
Packit d2ab36
			"cal-email-address",
Packit d2ab36
			"Calendar Email Address",
Packit d2ab36
			"Target client's calendar email address",
Packit d2ab36
			NULL,
Packit d2ab36
			G_PARAM_READWRITE |
Packit d2ab36
			G_PARAM_STATIC_STRINGS));
Packit d2ab36
Packit d2ab36
	g_object_class_install_property (
Packit d2ab36
		object_class,
Packit d2ab36
		PROP_CHANGED,
Packit d2ab36
		g_param_spec_boolean (
Packit d2ab36
			"changed",
Packit d2ab36
			"Changed",
Packit d2ab36
			"Whether the editor content changed",
Packit d2ab36
			FALSE,
Packit d2ab36
			G_PARAM_READWRITE |
Packit d2ab36
			G_PARAM_STATIC_STRINGS));
Packit d2ab36
Packit d2ab36
	g_object_class_install_property (
Packit d2ab36
		object_class,
Packit d2ab36
		PROP_COMPONENT,
Packit d2ab36
		g_param_spec_pointer (
Packit d2ab36
			"component",
Packit d2ab36
			"Component",
Packit d2ab36
			"icalcomponent currently edited",
Packit d2ab36
			G_PARAM_READWRITE |
Packit d2ab36
			G_PARAM_CONSTRUCT_ONLY |
Packit d2ab36
			G_PARAM_STATIC_STRINGS));
Packit d2ab36
Packit d2ab36
	g_object_class_install_property (
Packit d2ab36
		object_class,
Packit d2ab36
		PROP_FLAGS,
Packit d2ab36
		g_param_spec_uint (
Packit d2ab36
			"flags",
Packit d2ab36
			"Flags",
Packit d2ab36
			"Editor flags",
Packit d2ab36
			0, G_MAXUINT, 0,
Packit d2ab36
			G_PARAM_READWRITE |
Packit d2ab36
			G_PARAM_CONSTRUCT_ONLY |
Packit d2ab36
			G_PARAM_STATIC_STRINGS));
Packit d2ab36
Packit d2ab36
	g_object_class_install_property (
Packit d2ab36
		object_class,
Packit d2ab36
		PROP_ORIGIN_SOURCE,
Packit d2ab36
		g_param_spec_object (
Packit d2ab36
			"origin-source",
Packit d2ab36
			"Origin Source",
Packit d2ab36
			"ESource of an ECalClient the component is stored in",
Packit d2ab36
			E_TYPE_SOURCE,
Packit d2ab36
			G_PARAM_READWRITE |
Packit d2ab36
			G_PARAM_CONSTRUCT_ONLY |
Packit d2ab36
			G_PARAM_STATIC_STRINGS));
Packit d2ab36
Packit d2ab36
	g_object_class_install_property (
Packit d2ab36
		object_class,
Packit d2ab36
		PROP_SHELL,
Packit d2ab36
		g_param_spec_object (
Packit d2ab36
			"shell",
Packit d2ab36
			"Shell",
Packit d2ab36
			"EShell",
Packit d2ab36
			E_TYPE_SHELL,
Packit d2ab36
			G_PARAM_READWRITE |
Packit d2ab36
			G_PARAM_CONSTRUCT_ONLY |
Packit d2ab36
			G_PARAM_STATIC_STRINGS));
Packit d2ab36
Packit d2ab36
	g_object_class_install_property (
Packit d2ab36
		object_class,
Packit d2ab36
		PROP_SOURCE_CLIENT,
Packit d2ab36
		g_param_spec_object (
Packit d2ab36
			"source-client",
Packit d2ab36
			"Source Client",
Packit d2ab36
			"ECalClient, the source calendar for the component",
Packit d2ab36
			E_TYPE_CAL_CLIENT,
Packit d2ab36
			G_PARAM_READWRITE |
Packit d2ab36
			G_PARAM_STATIC_STRINGS));
Packit d2ab36
Packit d2ab36
	g_object_class_install_property (
Packit d2ab36
		object_class,
Packit d2ab36
		PROP_TARGET_CLIENT,
Packit d2ab36
		g_param_spec_object (
Packit d2ab36
			"target-client",
Packit d2ab36
			"Target Client",
Packit d2ab36
			"ECalClient currently set as the target calendar for the component",
Packit d2ab36
			E_TYPE_CAL_CLIENT,
Packit d2ab36
			G_PARAM_READWRITE |
Packit d2ab36
			G_PARAM_STATIC_STRINGS));
Packit d2ab36
Packit d2ab36
	g_object_class_install_property (
Packit d2ab36
		object_class,
Packit d2ab36
		PROP_TITLE_SUFFIX,
Packit d2ab36
		g_param_spec_string (
Packit d2ab36
			"title-suffix",
Packit d2ab36
			"Title Suffix",
Packit d2ab36
			"Window title suffix, usually summary of the component",
Packit d2ab36
			NULL,
Packit d2ab36
			G_PARAM_READWRITE |
Packit d2ab36
			G_PARAM_STATIC_STRINGS));
Packit d2ab36
Packit d2ab36
	signals[TIMES_CHANGED] = g_signal_new (
Packit d2ab36
		"times-changed",
Packit d2ab36
		G_TYPE_FROM_CLASS (klass),
Packit d2ab36
		G_SIGNAL_RUN_FIRST,
Packit d2ab36
		G_STRUCT_OFFSET (ECompEditorClass, times_changed),
Packit d2ab36
		NULL, NULL, NULL,
Packit d2ab36
		G_TYPE_NONE, 0,
Packit d2ab36
		G_TYPE_NONE);
Packit d2ab36
Packit d2ab36
	signals[OBJECT_CREATED] = g_signal_new (
Packit d2ab36
		"object-created",
Packit d2ab36
		G_TYPE_FROM_CLASS (klass),
Packit d2ab36
		G_SIGNAL_RUN_FIRST,
Packit d2ab36
		G_STRUCT_OFFSET (ECompEditorClass, object_created),
Packit d2ab36
		NULL, NULL, NULL,
Packit d2ab36
		G_TYPE_NONE, 0,
Packit d2ab36
		G_TYPE_NONE);
Packit d2ab36
Packit d2ab36
	signals[EDITOR_CLOSED] = g_signal_new (
Packit d2ab36
		"editor-closed",
Packit d2ab36
		G_TYPE_FROM_CLASS (klass),
Packit d2ab36
		G_SIGNAL_RUN_LAST,
Packit d2ab36
		G_STRUCT_OFFSET (ECompEditorClass, editor_closed),
Packit d2ab36
		NULL, NULL,
Packit d2ab36
		g_cclosure_marshal_VOID__BOOLEAN,
Packit d2ab36
		G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
void
Packit d2ab36
e_comp_editor_sensitize_widgets (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	ECompEditorClass *comp_editor_class;
Packit d2ab36
	gboolean force_insensitive;
Packit d2ab36
	GtkWidget *current_focus;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	comp_editor_class = E_COMP_EDITOR_GET_CLASS (comp_editor);
Packit d2ab36
	g_return_if_fail (comp_editor_class != NULL);
Packit d2ab36
	g_return_if_fail (comp_editor_class->sensitize_widgets != NULL);
Packit d2ab36
Packit d2ab36
	current_focus = gtk_window_get_focus (GTK_WINDOW (comp_editor));
Packit d2ab36
Packit d2ab36
	force_insensitive = !comp_editor->priv->component;
Packit d2ab36
Packit d2ab36
	if (!force_insensitive) {
Packit d2ab36
		ECalClient *target_client;
Packit d2ab36
Packit d2ab36
		target_client = e_comp_editor_get_target_client (comp_editor);
Packit d2ab36
		if (target_client) {
Packit d2ab36
			EClient *client = E_CLIENT (target_client);
Packit d2ab36
Packit d2ab36
			if (e_client_is_readonly (client)) {
Packit d2ab36
				force_insensitive = TRUE;
Packit d2ab36
			} else {
Packit d2ab36
				if (!e_cal_util_component_has_organizer (comp_editor->priv->component) ||
Packit d2ab36
				    ece_organizer_is_user (comp_editor, comp_editor->priv->component, client) ||
Packit d2ab36
				    ece_sentby_is_user (comp_editor, comp_editor->priv->component, client)) {
Packit d2ab36
					comp_editor->priv->flags = comp_editor->priv->flags | E_COMP_EDITOR_FLAG_ORGANIZER_IS_USER;
Packit d2ab36
				} else {
Packit d2ab36
					comp_editor->priv->flags = comp_editor->priv->flags & (~E_COMP_EDITOR_FLAG_ORGANIZER_IS_USER);
Packit d2ab36
				}
Packit d2ab36
			}
Packit d2ab36
		} else {
Packit d2ab36
			force_insensitive = TRUE;
Packit d2ab36
		}
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	comp_editor_class->sensitize_widgets (comp_editor, force_insensitive);
Packit d2ab36
Packit d2ab36
	if (force_insensitive)
Packit d2ab36
		comp_editor->priv->restore_focus = current_focus;
Packit d2ab36
	else
Packit d2ab36
		ece_restore_focus (comp_editor);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
void
Packit d2ab36
e_comp_editor_fill_widgets (ECompEditor *comp_editor,
Packit d2ab36
			    icalcomponent *component)
Packit d2ab36
{
Packit d2ab36
	ECompEditorClass *comp_editor_class;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
	g_return_if_fail (component != NULL);
Packit d2ab36
Packit d2ab36
	comp_editor_class = E_COMP_EDITOR_GET_CLASS (comp_editor);
Packit d2ab36
	g_return_if_fail (comp_editor_class != NULL);
Packit d2ab36
	g_return_if_fail (comp_editor_class->fill_widgets != NULL);
Packit d2ab36
Packit d2ab36
	e_comp_editor_set_updating (comp_editor, TRUE);
Packit d2ab36
Packit d2ab36
	comp_editor_class->fill_widgets (comp_editor, component);
Packit d2ab36
Packit d2ab36
	e_comp_editor_set_updating (comp_editor, FALSE);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
gboolean
Packit d2ab36
e_comp_editor_fill_component (ECompEditor *comp_editor,
Packit d2ab36
			      icalcomponent *component)
Packit d2ab36
{
Packit d2ab36
	ECompEditorClass *comp_editor_class;
Packit d2ab36
	gboolean is_valid;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), FALSE);
Packit d2ab36
	g_return_val_if_fail (component != NULL, FALSE);
Packit d2ab36
Packit d2ab36
	comp_editor_class = E_COMP_EDITOR_GET_CLASS (comp_editor);
Packit d2ab36
	g_return_val_if_fail (comp_editor_class != NULL, FALSE);
Packit d2ab36
	g_return_val_if_fail (comp_editor_class->fill_component != NULL, FALSE);
Packit d2ab36
Packit d2ab36
	is_valid = comp_editor_class->fill_component (comp_editor, component);
Packit d2ab36
Packit d2ab36
	if (is_valid && comp_editor->priv->validation_alert) {
Packit d2ab36
		e_alert_response (comp_editor->priv->validation_alert, GTK_RESPONSE_CLOSE);
Packit d2ab36
		g_clear_object (&comp_editor->priv->validation_alert);
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	if (is_valid) {
Packit d2ab36
		ECalClient *target_client;
Packit d2ab36
		EClient *client = NULL;
Packit d2ab36
Packit d2ab36
		target_client = e_comp_editor_get_target_client (comp_editor);
Packit d2ab36
		if (target_client)
Packit d2ab36
			client = E_CLIENT (target_client);
Packit d2ab36
Packit d2ab36
		if (!e_cal_util_component_has_organizer (component) || (client && (
Packit d2ab36
		    ece_organizer_is_user (comp_editor, component, client) ||
Packit d2ab36
		    ece_sentby_is_user (comp_editor, component, client)))) {
Packit d2ab36
			gint sequence;
Packit d2ab36
Packit d2ab36
			sequence = icalcomponent_get_sequence (component);
Packit d2ab36
			icalcomponent_set_sequence (component, sequence + 1);
Packit d2ab36
		}
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	return is_valid;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
void
Packit d2ab36
e_comp_editor_set_validation_error (ECompEditor *comp_editor,
Packit d2ab36
				    ECompEditorPage *error_page,
Packit d2ab36
				    GtkWidget *error_widget,
Packit d2ab36
				    const gchar *error_message)
Packit d2ab36
{
Packit d2ab36
	EAlert *alert, *previous_alert;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
	g_return_if_fail (error_message != NULL);
Packit d2ab36
Packit d2ab36
	/* Ignore validation errors when the inner editor is currently updating. */
Packit d2ab36
	if (e_comp_editor_get_updating (comp_editor))
Packit d2ab36
		return;
Packit d2ab36
Packit d2ab36
	alert = e_alert_new ("calendar:comp-editor-failed-validate", error_message, NULL);
Packit d2ab36
Packit d2ab36
	e_alert_bar_add_alert (comp_editor->priv->alert_bar, alert);
Packit d2ab36
Packit d2ab36
	previous_alert = comp_editor->priv->validation_alert;
Packit d2ab36
	comp_editor->priv->validation_alert = alert;
Packit d2ab36
Packit d2ab36
	if (previous_alert) {
Packit d2ab36
		e_alert_response (previous_alert, GTK_RESPONSE_CLOSE);
Packit d2ab36
		g_clear_object (&previous_alert);
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	if (error_page)
Packit d2ab36
		e_comp_editor_select_page (comp_editor, error_page);
Packit d2ab36
Packit d2ab36
	if (error_widget)
Packit d2ab36
		gtk_widget_grab_focus (error_widget);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
EShell *
Packit d2ab36
e_comp_editor_get_shell (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
Packit d2ab36
Packit d2ab36
	return comp_editor->priv->shell;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
GSettings *
Packit d2ab36
e_comp_editor_get_settings (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
Packit d2ab36
Packit d2ab36
	return comp_editor->priv->calendar_settings;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
ESource *
Packit d2ab36
e_comp_editor_get_origin_source (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
Packit d2ab36
Packit d2ab36
	return comp_editor->priv->origin_source;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
icalcomponent *
Packit d2ab36
e_comp_editor_get_component (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
Packit d2ab36
Packit d2ab36
	return comp_editor->priv->component;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
guint32
Packit d2ab36
e_comp_editor_get_flags (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), 0);
Packit d2ab36
Packit d2ab36
	return comp_editor->priv->flags;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
void
Packit d2ab36
e_comp_editor_set_flags (ECompEditor *comp_editor,
Packit d2ab36
			 guint32 flags)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	if (comp_editor->priv->flags == flags)
Packit d2ab36
		return;
Packit d2ab36
Packit d2ab36
	comp_editor->priv->flags = flags;
Packit d2ab36
Packit d2ab36
	g_object_notify (G_OBJECT (comp_editor), "flags");
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
EFocusTracker *
Packit d2ab36
e_comp_editor_get_focus_tracker (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
Packit d2ab36
Packit d2ab36
	return comp_editor->priv->focus_tracker;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
GtkUIManager *
Packit d2ab36
e_comp_editor_get_ui_manager (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
Packit d2ab36
Packit d2ab36
	return comp_editor->priv->ui_manager;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
GtkAction *
Packit d2ab36
e_comp_editor_get_action (ECompEditor *comp_editor,
Packit d2ab36
			  const gchar *action_name)
Packit d2ab36
{
Packit d2ab36
	GtkUIManager *ui_manager;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
Packit d2ab36
	g_return_val_if_fail (action_name != NULL, NULL);
Packit d2ab36
Packit d2ab36
	ui_manager = e_comp_editor_get_ui_manager (comp_editor);
Packit d2ab36
Packit d2ab36
	return e_lookup_action (ui_manager, action_name);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
GtkActionGroup *
Packit d2ab36
e_comp_editor_get_action_group (ECompEditor *comp_editor,
Packit d2ab36
				const gchar *group_name)
Packit d2ab36
{
Packit d2ab36
	GtkUIManager *ui_manager;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
Packit d2ab36
	g_return_val_if_fail (group_name != NULL, NULL);
Packit d2ab36
Packit d2ab36
	ui_manager = e_comp_editor_get_ui_manager (comp_editor);
Packit d2ab36
Packit d2ab36
	return e_lookup_action_group (ui_manager, group_name);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
GtkWidget *
Packit d2ab36
e_comp_editor_get_managed_widget (ECompEditor *comp_editor,
Packit d2ab36
				  const gchar *widget_path)
Packit d2ab36
{
Packit d2ab36
	GtkUIManager *ui_manager;
Packit d2ab36
	GtkWidget *widget;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
Packit d2ab36
	g_return_val_if_fail (widget_path != NULL, NULL);
Packit d2ab36
Packit d2ab36
	ui_manager = e_comp_editor_get_ui_manager (comp_editor);
Packit d2ab36
	widget = gtk_ui_manager_get_widget (ui_manager, widget_path);
Packit d2ab36
	g_return_val_if_fail (widget != NULL, NULL);
Packit d2ab36
Packit d2ab36
	return widget;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
const gchar *
Packit d2ab36
e_comp_editor_get_alarm_email_address (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
Packit d2ab36
Packit d2ab36
	return comp_editor->priv->alarm_email_address;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
void
Packit d2ab36
e_comp_editor_set_alarm_email_address (ECompEditor *comp_editor,
Packit d2ab36
				       const gchar *alarm_email_address)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	if (g_strcmp0 (alarm_email_address, comp_editor->priv->alarm_email_address) == 0)
Packit d2ab36
		return;
Packit d2ab36
Packit d2ab36
	g_free (comp_editor->priv->alarm_email_address);
Packit d2ab36
	comp_editor->priv->alarm_email_address = g_strdup (alarm_email_address);
Packit d2ab36
Packit d2ab36
	g_object_notify (G_OBJECT (comp_editor), "alarm-email-address");
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
const gchar *
Packit d2ab36
e_comp_editor_get_cal_email_address (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
Packit d2ab36
Packit d2ab36
	return comp_editor->priv->cal_email_address;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
void
Packit d2ab36
e_comp_editor_set_cal_email_address (ECompEditor *comp_editor,
Packit d2ab36
				     const gchar *cal_email_address)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	if (g_strcmp0 (cal_email_address, comp_editor->priv->cal_email_address) == 0)
Packit d2ab36
		return;
Packit d2ab36
Packit d2ab36
	g_free (comp_editor->priv->cal_email_address);
Packit d2ab36
	comp_editor->priv->cal_email_address = g_strdup (cal_email_address);
Packit d2ab36
Packit d2ab36
	g_object_notify (G_OBJECT (comp_editor), "cal-email-address");
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
gboolean
Packit d2ab36
e_comp_editor_get_changed (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), FALSE);
Packit d2ab36
Packit d2ab36
	return comp_editor->priv->changed;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
void
Packit d2ab36
e_comp_editor_set_changed (ECompEditor *comp_editor,
Packit d2ab36
			   gboolean changed)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	if ((changed ? 1 : 0) == (comp_editor->priv->changed ? 1 : 0))
Packit d2ab36
		return;
Packit d2ab36
Packit d2ab36
	comp_editor->priv->changed = changed;
Packit d2ab36
Packit d2ab36
	g_object_notify (G_OBJECT (comp_editor), "changed");
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
void
Packit d2ab36
e_comp_editor_ensure_changed (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	e_comp_editor_set_changed (comp_editor, TRUE);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
gboolean
Packit d2ab36
e_comp_editor_get_updating (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), FALSE);
Packit d2ab36
Packit d2ab36
	return comp_editor->priv->updating > 0;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
void
Packit d2ab36
e_comp_editor_set_updating (ECompEditor *comp_editor,
Packit d2ab36
			    gboolean updating)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	if (updating) {
Packit d2ab36
		comp_editor->priv->updating++;
Packit d2ab36
	} else if (comp_editor->priv->updating > 0) {
Packit d2ab36
		comp_editor->priv->updating--;
Packit d2ab36
	} else {
Packit d2ab36
		g_warn_if_reached ();
Packit d2ab36
	}
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
ECalClient *
Packit d2ab36
e_comp_editor_get_source_client (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
Packit d2ab36
Packit d2ab36
	return comp_editor->priv->source_client;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
void
Packit d2ab36
e_comp_editor_set_source_client (ECompEditor *comp_editor,
Packit d2ab36
				 ECalClient *client)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	if (client == comp_editor->priv->source_client)
Packit d2ab36
		return;
Packit d2ab36
Packit d2ab36
	if (client)
Packit d2ab36
		g_object_ref (client);
Packit d2ab36
	g_clear_object (&comp_editor->priv->source_client);
Packit d2ab36
	comp_editor->priv->source_client = client;
Packit d2ab36
Packit d2ab36
	g_object_notify (G_OBJECT (comp_editor), "source-client");
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
ECalClient *
Packit d2ab36
e_comp_editor_get_target_client (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
Packit d2ab36
Packit d2ab36
	return comp_editor->priv->target_client;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
void
Packit d2ab36
e_comp_editor_set_target_client (ECompEditor *comp_editor,
Packit d2ab36
				 ECalClient *client)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	if (client == comp_editor->priv->target_client)
Packit d2ab36
		return;
Packit d2ab36
Packit d2ab36
	if (client)
Packit d2ab36
		g_object_ref (client);
Packit d2ab36
	g_clear_object (&comp_editor->priv->target_client);
Packit d2ab36
	comp_editor->priv->target_client = client;
Packit d2ab36
Packit d2ab36
	g_object_notify (G_OBJECT (comp_editor), "target-client");
Packit d2ab36
Packit d2ab36
	if (client && !comp_editor->priv->source_client && comp_editor->priv->origin_source &&
Packit d2ab36
	    e_source_equal (e_client_get_source (E_CLIENT (client)), comp_editor->priv->origin_source))
Packit d2ab36
		e_comp_editor_set_source_client (comp_editor, client);
Packit d2ab36
Packit d2ab36
	e_comp_editor_sensitize_widgets (comp_editor);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
const gchar *
Packit d2ab36
e_comp_editor_get_title_suffix (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
Packit d2ab36
Packit d2ab36
	return comp_editor->priv->title_suffix;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
void
Packit d2ab36
e_comp_editor_set_title_suffix (ECompEditor *comp_editor,
Packit d2ab36
				const gchar *title_suffix)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	if (g_strcmp0 (title_suffix, comp_editor->priv->title_suffix) == 0)
Packit d2ab36
		return;
Packit d2ab36
Packit d2ab36
	g_free (comp_editor->priv->title_suffix);
Packit d2ab36
	comp_editor->priv->title_suffix = g_strdup (title_suffix);
Packit d2ab36
Packit d2ab36
	g_object_notify (G_OBJECT (comp_editor), "title-suffix");
Packit d2ab36
Packit d2ab36
	e_comp_editor_update_window_title (comp_editor);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
void
Packit d2ab36
e_comp_editor_set_time_parts (ECompEditor *comp_editor,
Packit d2ab36
			      ECompEditorPropertyPart *dtstart_part,
Packit d2ab36
			      ECompEditorPropertyPart *dtend_part)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	if (dtstart_part)
Packit d2ab36
		g_return_if_fail (E_IS_COMP_EDITOR_PROPERTY_PART_DATETIME (dtstart_part));
Packit d2ab36
	if (dtend_part)
Packit d2ab36
		g_return_if_fail (E_IS_COMP_EDITOR_PROPERTY_PART_DATETIME (dtend_part));
Packit d2ab36
Packit d2ab36
	ece_connect_time_parts (comp_editor, dtstart_part, dtend_part);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
void
Packit d2ab36
e_comp_editor_get_time_parts (ECompEditor *comp_editor,
Packit d2ab36
			      ECompEditorPropertyPart **out_dtstart_part,
Packit d2ab36
			      ECompEditorPropertyPart **out_dtend_part)
Packit d2ab36
{
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
Packit d2ab36
	if (out_dtstart_part)
Packit d2ab36
		*out_dtstart_part = comp_editor->priv->dtstart_part;
Packit d2ab36
	if (out_dtend_part)
Packit d2ab36
		*out_dtend_part = comp_editor->priv->dtend_part;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
/* This consumes the @page. */
Packit d2ab36
void
Packit d2ab36
e_comp_editor_add_page (ECompEditor *comp_editor,
Packit d2ab36
			const gchar *label,
Packit d2ab36
			ECompEditorPage *page)
Packit d2ab36
{
Packit d2ab36
	ECompEditor *pages_comp_editor;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
	g_return_if_fail (label != NULL);
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR_PAGE (page));
Packit d2ab36
Packit d2ab36
	pages_comp_editor = e_comp_editor_page_ref_editor (page);
Packit d2ab36
	if (pages_comp_editor != comp_editor) {
Packit d2ab36
		g_warn_if_fail (pages_comp_editor == comp_editor);
Packit d2ab36
		g_clear_object (&pages_comp_editor);
Packit d2ab36
		return;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	g_clear_object (&pages_comp_editor);
Packit d2ab36
Packit d2ab36
	/* One reference uses the GtkNotebook, the other the pages GSList */
Packit d2ab36
	gtk_notebook_append_page (comp_editor->priv->content,
Packit d2ab36
		GTK_WIDGET (page),
Packit d2ab36
		gtk_label_new_with_mnemonic (label));
Packit d2ab36
Packit d2ab36
	comp_editor->priv->pages = g_slist_append (comp_editor->priv->pages, g_object_ref (page));
Packit d2ab36
Packit d2ab36
	g_signal_connect_swapped (page, "changed", G_CALLBACK (e_comp_editor_ensure_changed), comp_editor);
Packit d2ab36
Packit d2ab36
	if (E_IS_COMP_EDITOR_PAGE_GENERAL (page)) {
Packit d2ab36
		ECompEditorPageGeneral *page_general;
Packit d2ab36
Packit d2ab36
		g_return_if_fail (comp_editor->priv->page_general == NULL);
Packit d2ab36
Packit d2ab36
		page_general = E_COMP_EDITOR_PAGE_GENERAL (page);
Packit d2ab36
Packit d2ab36
		g_signal_connect (page_general, "notify::selected-source",
Packit d2ab36
			G_CALLBACK (comp_editor_selected_source_notify_cb), comp_editor);
Packit d2ab36
Packit d2ab36
		comp_editor->priv->page_general = page_general;
Packit d2ab36
Packit d2ab36
		if ((comp_editor->priv->flags & E_COMP_EDITOR_FLAG_WITH_ATTENDEES) != 0) {
Packit d2ab36
			e_comp_editor_page_general_set_show_attendees (page_general, TRUE);
Packit d2ab36
		}
Packit d2ab36
	}
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
/* The returned pointer is owned by the @comp_editor; returns the first instance,
Packit d2ab36
   in order of the addition. */
Packit d2ab36
ECompEditorPage *
Packit d2ab36
e_comp_editor_get_page (ECompEditor *comp_editor,
Packit d2ab36
			GType page_type)
Packit d2ab36
{
Packit d2ab36
	GSList *link;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
Packit d2ab36
	g_return_val_if_fail (g_type_is_a (page_type, E_TYPE_COMP_EDITOR_PAGE), NULL);
Packit d2ab36
	g_return_val_if_fail (page_type != E_TYPE_COMP_EDITOR_PAGE, NULL);
Packit d2ab36
Packit d2ab36
	for (link = comp_editor->priv->pages; link; link = g_slist_next (link)) {
Packit d2ab36
		ECompEditorPage *page = link->data;
Packit d2ab36
Packit d2ab36
		if (G_TYPE_CHECK_INSTANCE_TYPE (page, page_type))
Packit d2ab36
			return page;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	return NULL;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
/* Free the returned GSList with g_slist_free(), the memebers are owned by the comp_editor */
Packit d2ab36
GSList *
Packit d2ab36
e_comp_editor_get_pages (ECompEditor *comp_editor)
Packit d2ab36
{
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
Packit d2ab36
Packit d2ab36
	return g_slist_copy (comp_editor->priv->pages);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
void
Packit d2ab36
e_comp_editor_select_page (ECompEditor *comp_editor,
Packit d2ab36
			   ECompEditorPage *page)
Packit d2ab36
{
Packit d2ab36
	gint page_num;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR_PAGE (page));
Packit d2ab36
Packit d2ab36
	page_num = gtk_notebook_page_num (comp_editor->priv->content, GTK_WIDGET (page));
Packit d2ab36
	g_return_if_fail (page_num != -1);
Packit d2ab36
Packit d2ab36
	gtk_notebook_set_current_page (comp_editor->priv->content, page_num);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
/* Unref returned pointer when done with it. */
Packit d2ab36
static EAlert *
Packit d2ab36
e_comp_editor_add_alert (ECompEditor *comp_editor,
Packit d2ab36
			 const gchar *alert_id,
Packit d2ab36
			 const gchar *primary_text,
Packit d2ab36
			 const gchar *secondary_text)
Packit d2ab36
{
Packit d2ab36
	EAlert *alert;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
Packit d2ab36
	g_return_val_if_fail (alert_id != NULL, NULL);
Packit d2ab36
	g_return_val_if_fail (primary_text != NULL || secondary_text != NULL, NULL);
Packit d2ab36
Packit d2ab36
	alert = e_alert_new (alert_id,
Packit d2ab36
		primary_text ? primary_text : "",
Packit d2ab36
		secondary_text ? secondary_text : "",
Packit d2ab36
		NULL);
Packit d2ab36
Packit d2ab36
	e_alert_bar_add_alert (comp_editor->priv->alert_bar, alert);
Packit d2ab36
Packit d2ab36
	return alert;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
/* Unref returned pointer when done with it. */
Packit d2ab36
EAlert *
Packit d2ab36
e_comp_editor_add_information (ECompEditor *comp_editor,
Packit d2ab36
			       const gchar *primary_text,
Packit d2ab36
			       const gchar *secondary_text)
Packit d2ab36
{
Packit d2ab36
	return e_comp_editor_add_alert (comp_editor, "calendar:comp-editor-information", primary_text, secondary_text);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
/* Unref returned pointer when done with it. */
Packit d2ab36
EAlert *
Packit d2ab36
e_comp_editor_add_warning (ECompEditor *comp_editor,
Packit d2ab36
			   const gchar *primary_text,
Packit d2ab36
			   const gchar *secondary_text)
Packit d2ab36
{
Packit d2ab36
	return e_comp_editor_add_alert (comp_editor, "calendar:comp-editor-warning", primary_text, secondary_text);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
/* Unref returned pointer when done with it. */
Packit d2ab36
EAlert *
Packit d2ab36
e_comp_editor_add_error (ECompEditor *comp_editor,
Packit d2ab36
			 const gchar *primary_text,
Packit d2ab36
			 const gchar *secondary_text)
Packit d2ab36
{
Packit d2ab36
	return e_comp_editor_add_alert (comp_editor, "calendar:comp-editor-error", primary_text, secondary_text);
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
Packit d2ab36
static gboolean
Packit d2ab36
ece_check_start_before_end (ECompEditor *comp_editor,
Packit d2ab36
			    struct icaltimetype *start_tt,
Packit d2ab36
			    struct icaltimetype *end_tt,
Packit d2ab36
			    gboolean adjust_end_time)
Packit d2ab36
{
Packit d2ab36
	struct icaltimetype end_tt_copy;
Packit d2ab36
	icaltimezone *start_zone, *end_zone;
Packit d2ab36
	gint duration = -1;
Packit d2ab36
	gint cmp;
Packit d2ab36
Packit d2ab36
	if ((e_comp_editor_get_flags (comp_editor) & E_COMP_EDITOR_FLAG_IS_NEW) == 0) {
Packit d2ab36
		icalcomponent *icomp;
Packit d2ab36
Packit d2ab36
		icomp = e_comp_editor_get_component (comp_editor);
Packit d2ab36
		if (icomp &&
Packit d2ab36
		    icalcomponent_get_first_property (icomp, ICAL_DTSTART_PROPERTY) &&
Packit d2ab36
		    (icalcomponent_get_first_property (icomp, ICAL_DTEND_PROPERTY) ||
Packit d2ab36
		     icalcomponent_get_first_property (icomp, ICAL_DUE_PROPERTY))) {
Packit d2ab36
			struct icaltimetype orig_start, orig_end;
Packit d2ab36
Packit d2ab36
			orig_start = icalcomponent_get_dtstart (icomp);
Packit d2ab36
			orig_end = icalcomponent_get_dtend (icomp);
Packit d2ab36
Packit d2ab36
			if (icaltime_is_valid_time (orig_start) &&
Packit d2ab36
			    icaltime_is_valid_time (orig_end)) {
Packit d2ab36
				duration = icaltime_as_timet (orig_end) - icaltime_as_timet (orig_start);
Packit d2ab36
			}
Packit d2ab36
		}
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	start_zone = (icaltimezone *) start_tt->zone;
Packit d2ab36
	end_zone = (icaltimezone *) end_tt->zone;
Packit d2ab36
Packit d2ab36
	/* Convert the end time to the same timezone as the start time. */
Packit d2ab36
	end_tt_copy = *end_tt;
Packit d2ab36
Packit d2ab36
	if (start_zone && end_zone && start_zone != end_zone)
Packit d2ab36
		icaltimezone_convert_time (&end_tt_copy, end_zone, start_zone);
Packit d2ab36
Packit d2ab36
	/* Now check if the start time is after the end time. If it is,
Packit d2ab36
	 * we need to modify one of the times. */
Packit d2ab36
	cmp = icaltime_compare (*start_tt, end_tt_copy);
Packit d2ab36
	if (cmp > 0) {
Packit d2ab36
		if (adjust_end_time) {
Packit d2ab36
			/* Try to switch only the date */
Packit d2ab36
			end_tt->year = start_tt->year;
Packit d2ab36
			end_tt->month = start_tt->month;
Packit d2ab36
			end_tt->day = start_tt->day;
Packit d2ab36
Packit d2ab36
			end_tt_copy = *end_tt;
Packit d2ab36
			if (start_zone && end_zone && start_zone != end_zone)
Packit d2ab36
				icaltimezone_convert_time (&end_tt_copy, end_zone, start_zone);
Packit d2ab36
Packit d2ab36
			if (duration > 0)
Packit d2ab36
				icaltime_adjust (&end_tt_copy, 0, 0, 0, -duration);
Packit d2ab36
Packit d2ab36
			if (icaltime_compare (*start_tt, end_tt_copy) >= 0) {
Packit d2ab36
				*end_tt = *start_tt;
Packit d2ab36
Packit d2ab36
				if (duration >= 0) {
Packit d2ab36
					icaltime_adjust (end_tt, 0, 0, 0, duration);
Packit d2ab36
				} else {
Packit d2ab36
					/* Modify the end time, to be the start + 1 hour/day. */
Packit d2ab36
					icaltime_adjust (end_tt, 0, start_tt->is_date ? 24 : 1, 0, 0);
Packit d2ab36
				}
Packit d2ab36
Packit d2ab36
				if (start_zone && end_zone && start_zone != end_zone)
Packit d2ab36
					icaltimezone_convert_time (end_tt, start_zone, end_zone);
Packit d2ab36
			}
Packit d2ab36
		} else {
Packit d2ab36
			/* Try to switch only the date */
Packit d2ab36
			start_tt->year = end_tt->year;
Packit d2ab36
			start_tt->month = end_tt->month;
Packit d2ab36
			start_tt->day = end_tt->day;
Packit d2ab36
Packit d2ab36
			if (icaltime_compare (*start_tt, end_tt_copy) >= 0) {
Packit d2ab36
				*start_tt = *end_tt;
Packit d2ab36
Packit d2ab36
				if (duration >= 0) {
Packit d2ab36
					icaltime_adjust (start_tt, 0, 0, 0, -duration);
Packit d2ab36
				} else {
Packit d2ab36
					/* Modify the start time, to be the end - 1 hour/day. */
Packit d2ab36
					icaltime_adjust (start_tt, 0, start_tt->is_date ? -24 : -1, 0, 0);
Packit d2ab36
				}
Packit d2ab36
Packit d2ab36
				if (start_zone && end_zone && start_zone != end_zone)
Packit d2ab36
					icaltimezone_convert_time (start_tt, end_zone, start_zone);
Packit d2ab36
			}
Packit d2ab36
		}
Packit d2ab36
Packit d2ab36
		return TRUE;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	return FALSE;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
void
Packit d2ab36
e_comp_editor_ensure_start_before_end (ECompEditor *comp_editor,
Packit d2ab36
				       ECompEditorPropertyPart *start_datetime,
Packit d2ab36
				       ECompEditorPropertyPart *end_datetime,
Packit d2ab36
				       gboolean change_end_datetime)
Packit d2ab36
{
Packit d2ab36
	ECompEditorPropertyPartDatetime *start_dtm, *end_dtm;
Packit d2ab36
	struct icaltimetype start_tt, end_tt;
Packit d2ab36
	gboolean set_dtstart = FALSE, set_dtend = FALSE;
Packit d2ab36
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR (comp_editor));
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR_PROPERTY_PART_DATETIME (start_datetime));
Packit d2ab36
	g_return_if_fail (E_IS_COMP_EDITOR_PROPERTY_PART_DATETIME (end_datetime));
Packit d2ab36
Packit d2ab36
	start_dtm = E_COMP_EDITOR_PROPERTY_PART_DATETIME (start_datetime);
Packit d2ab36
	end_dtm = E_COMP_EDITOR_PROPERTY_PART_DATETIME (end_datetime);
Packit d2ab36
Packit d2ab36
	start_tt = e_comp_editor_property_part_datetime_get_value (start_dtm);
Packit d2ab36
	end_tt = e_comp_editor_property_part_datetime_get_value (end_dtm);
Packit d2ab36
Packit d2ab36
	if (icaltime_is_null_time (start_tt) ||
Packit d2ab36
	    icaltime_is_null_time (end_tt) ||
Packit d2ab36
	    !icaltime_is_valid_time (start_tt) ||
Packit d2ab36
	    !icaltime_is_valid_time (end_tt))
Packit d2ab36
		return;
Packit d2ab36
Packit d2ab36
	if (start_tt.is_date || end_tt.is_date) {
Packit d2ab36
		/* All Day Events are simple. We just compare the dates and if
Packit d2ab36
		 * start > end we copy one of them to the other. */
Packit d2ab36
		gint cmp;
Packit d2ab36
Packit d2ab36
		start_tt.is_date = TRUE;
Packit d2ab36
		end_tt.is_date = TRUE;
Packit d2ab36
Packit d2ab36
		cmp = icaltime_compare_date_only (start_tt, end_tt);
Packit d2ab36
Packit d2ab36
		if (cmp > 0) {
Packit d2ab36
			if (change_end_datetime) {
Packit d2ab36
				end_tt = start_tt;
Packit d2ab36
				set_dtend = TRUE;
Packit d2ab36
			} else {
Packit d2ab36
				start_tt = end_tt;
Packit d2ab36
				set_dtstart = TRUE;
Packit d2ab36
			}
Packit d2ab36
		}
Packit d2ab36
	} else {
Packit d2ab36
		if (ece_check_start_before_end (comp_editor, &start_tt, &end_tt, change_end_datetime)) {
Packit d2ab36
			if (change_end_datetime)
Packit d2ab36
				set_dtend = TRUE;
Packit d2ab36
			else
Packit d2ab36
				set_dtstart = TRUE;
Packit d2ab36
		}
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	if (set_dtstart || set_dtend) {
Packit d2ab36
		e_comp_editor_set_updating (comp_editor, TRUE);
Packit d2ab36
Packit d2ab36
		if (set_dtstart)
Packit d2ab36
			e_comp_editor_property_part_datetime_set_value (start_dtm, start_tt);
Packit d2ab36
Packit d2ab36
		if (set_dtend)
Packit d2ab36
			e_comp_editor_property_part_datetime_set_value (end_dtm, end_tt);
Packit d2ab36
Packit d2ab36
		e_comp_editor_set_updating (comp_editor, FALSE);
Packit d2ab36
	}
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
static gboolean
Packit d2ab36
e_comp_editor_holds_component (ECompEditor *comp_editor,
Packit d2ab36
			       ESource *origin_source,
Packit d2ab36
			       const icalcomponent *component)
Packit d2ab36
{
Packit d2ab36
	const gchar *component_uid, *editor_uid;
Packit d2ab36
	gboolean equal;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), FALSE);
Packit d2ab36
	g_return_val_if_fail (component != NULL, FALSE);
Packit d2ab36
Packit d2ab36
	if (!origin_source || !comp_editor->priv->origin_source ||
Packit d2ab36
	    !e_source_equal (origin_source, comp_editor->priv->origin_source))
Packit d2ab36
		return FALSE;
Packit d2ab36
Packit d2ab36
	component_uid = icalcomponent_get_uid ((icalcomponent *) component);
Packit d2ab36
	editor_uid = icalcomponent_get_uid (comp_editor->priv->component);
Packit d2ab36
Packit d2ab36
	if (!component_uid || !editor_uid)
Packit d2ab36
		return FALSE;
Packit d2ab36
Packit d2ab36
	equal = g_strcmp0 (component_uid, editor_uid) == 0;
Packit d2ab36
	if (equal) {
Packit d2ab36
		struct icaltimetype component_rid, editor_rid;
Packit d2ab36
Packit d2ab36
		component_rid = icalcomponent_get_recurrenceid ((icalcomponent *) component);
Packit d2ab36
		editor_rid = icalcomponent_get_recurrenceid (comp_editor->priv->component);
Packit d2ab36
Packit d2ab36
		if (icaltime_is_null_time (component_rid)) {
Packit d2ab36
			equal = icaltime_is_null_time (editor_rid);
Packit d2ab36
		} else if (!icaltime_is_null_time (editor_rid)) {
Packit d2ab36
			equal = icaltime_compare (component_rid, editor_rid) == 0;
Packit d2ab36
		}
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	return equal;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
ECompEditor *
Packit d2ab36
e_comp_editor_open_for_component (GtkWindow *parent,
Packit d2ab36
				  EShell *shell,
Packit d2ab36
				  ESource *origin_source,
Packit d2ab36
				  const icalcomponent *component,
Packit d2ab36
				  guint32 flags /* bit-or of ECompEditorFlags */)
Packit d2ab36
{
Packit d2ab36
	ECompEditor *comp_editor;
Packit d2ab36
	GType comp_editor_type;
Packit d2ab36
Packit d2ab36
	g_return_val_if_fail (E_IS_SHELL (shell), NULL);
Packit d2ab36
	if (origin_source)
Packit d2ab36
		g_return_val_if_fail (E_IS_SOURCE (origin_source), NULL);
Packit d2ab36
	g_return_val_if_fail (component != NULL, NULL);
Packit d2ab36
Packit d2ab36
	comp_editor = e_comp_editor_find_existing_for (origin_source, component);
Packit d2ab36
	if (comp_editor) {
Packit d2ab36
		gtk_window_present (GTK_WINDOW (comp_editor));
Packit d2ab36
		return comp_editor;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	switch (icalcomponent_isa (component)) {
Packit d2ab36
		case ICAL_VEVENT_COMPONENT:
Packit d2ab36
			comp_editor_type = E_TYPE_COMP_EDITOR_EVENT;
Packit d2ab36
			break;
Packit d2ab36
		case ICAL_VTODO_COMPONENT:
Packit d2ab36
			comp_editor_type = E_TYPE_COMP_EDITOR_TASK;
Packit d2ab36
			break;
Packit d2ab36
		case ICAL_VJOURNAL_COMPONENT:
Packit d2ab36
			comp_editor_type = E_TYPE_COMP_EDITOR_MEMO;
Packit d2ab36
			break;
Packit d2ab36
		default:
Packit d2ab36
			g_warn_if_reached ();
Packit d2ab36
			return NULL;
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	comp_editor = g_object_new (comp_editor_type,
Packit d2ab36
		"shell", shell,
Packit d2ab36
		"origin-source", origin_source,
Packit d2ab36
		"component", component,
Packit d2ab36
		"flags", flags,
Packit d2ab36
		NULL);
Packit d2ab36
Packit d2ab36
	opened_editors = g_slist_prepend (opened_editors, comp_editor);
Packit d2ab36
Packit d2ab36
	gtk_widget_show (GTK_WIDGET (comp_editor));
Packit d2ab36
Packit d2ab36
	return comp_editor;
Packit d2ab36
}
Packit d2ab36
Packit d2ab36
ECompEditor *
Packit d2ab36
e_comp_editor_find_existing_for (ESource *origin_source,
Packit d2ab36
				 const icalcomponent *component)
Packit d2ab36
{
Packit d2ab36
	ECompEditor *comp_editor;
Packit d2ab36
	GSList *link;
Packit d2ab36
Packit d2ab36
	if (origin_source)
Packit d2ab36
		g_return_val_if_fail (E_IS_SOURCE (origin_source), NULL);
Packit d2ab36
	g_return_val_if_fail (component != NULL, NULL);
Packit d2ab36
Packit d2ab36
	for (link = opened_editors; link; link = g_slist_next (link)) {
Packit d2ab36
		comp_editor = link->data;
Packit d2ab36
Packit d2ab36
		if (!comp_editor)
Packit d2ab36
			continue;
Packit d2ab36
Packit d2ab36
		if (e_comp_editor_holds_component (comp_editor, origin_source, component)) {
Packit d2ab36
			gtk_window_present (GTK_WINDOW (comp_editor));
Packit d2ab36
			return comp_editor;
Packit d2ab36
		}
Packit d2ab36
	}
Packit d2ab36
Packit d2ab36
	return NULL;
Packit d2ab36
}