Files
evolution/calendar/gui/dialogs/comp-editor.c
Damon Chaplin b235a79eff added comparison functions for these special cell types. But the date and
2001-09-26  Damon Chaplin  <damon@ximian.com>

	* gui/e-calendar-table.c (date_compare_cb):
	(percent_compare_cb):
	(priority_compare_cb): added comparison functions for these special
	cell types. But the date and percent ones don't work yet due to the
	use of static text buffers for return cell values.
	(e_calendar_table_init): added the comparison functions to the
	ETableExtras. NOTE: task_compare_cb() never seems to be called.
	I'm not sure why it is there.

	* gui/e-calendar-table.etspec: set the comparison function names for
	the date/percent/priority fields.

	* cal-util/cal-util.c (cal_util_priority_to_string):
	(cal_util_priority_from_string): new utility functions.

	* gui/calendar-model.c (get_priority):
	(set_priority): used above utility functions, and removed the warning
	dialog which isn't useful now that the field isn't editable.

	* gui/dialogs/event-page.c (times_updated): handle timezones and for
	all-day events make sure it stays an all-day event after adjusting.
	Fixes bugs #5945 and #10222.

	* gui/calendar-commands.c (pixmaps): fixed the E_PIXMAP paths - the
	edit items were moved beneath 'EditPlaceholder'. This gets rid of
	those long Bonobo warnings! (and we get the icons back)

	* gui/dialogs/comp-editor.c (pixmaps): removed the PrintPreview toolbar
	icon, since it doesn't appear in the xml file. Gets rid of warning.

	* gui/dialogs/event-page.c (notify_dates_changed): new function to
	emit the notification signal when the dates are changed. It also
	handles timezones now.

	* gui/dialogs/comp-editor-page.h (CompEditorPageDates): used
	CalComponentDateTime for start/end/due so we have the timezone as well
	as the time.

	* gui/dialogs/comp-editor-util.c (comp_editor_dates): updated to get
	the timezones as well as the times.
	(comp_editor_free_dates): new function needed to free all the structs.

	* gui/dialogs/recurrence-page.c (recurrence_page_set_dates): added call
	to preview_recur() to make sure the preview gets updated.

	* gui/dialogs/alarm-page.c (alarm_page_fill_widgets): free the
	CompEditorPageDates struct after use.

	* gui/tag-calendar.c (tag_calendar_by_comp): added 'comp_is_on_server'
	argument. If FALSE, we try to use builtin timezones first. This is
	needed for the recurrence page of the event editor, because the
	timezones may not have been added to the server yet. This and the
	changes to the notification stuff should fix bug #5034.

	* gui/gnome-cal.c (dn_query_obj_updated_cb): call above
	tag_calendar_by_comp() with TRUE since the events will be on the
	server in this case.

	* gui/e-day-view-layout.c:
	* gui/e-day-view.c: made sure an event always takes up at least one
	row, even when the start & end times are the same. Fixes bug #5944.
	I don't know if we should try to also handle events with the end time
	before the start time.

	* gui/e-week-view.c (e_week_view_style_set): check that the small font
	is actually smaller than the normal font. If it isn't, don't use it.
	Hopefully fixes bug #6876.
	(e_week_view_on_new_appointment): if only one day is selected, then
	we set the initial time of the event to 1/2-hour from the start of the
	working day, to differentiate 'New Appointment' from 'New All Day
	Event'. Fixes bug #8892.

	* gui/e-day-view.c (e_day_view_on_new_appointment): do the same as the
	above.

svn path=/trunk/; revision=13186
2001-09-27 04:02:17 +00:00

1203 lines
28 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Evolution calendar - Framework for a calendar component editor dialog
*
* Copyright (C) 2001 Ximian, Inc.
*
* Author: Federico Mena-Quintero <federico@ximian.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <gnome.h>
#include <bonobo/bonobo-win.h>
#include <bonobo/bonobo-ui-component.h>
#include <bonobo/bonobo-ui-container.h>
#include <bonobo/bonobo-ui-util.h>
#include <gal/widgets/e-unicode.h>
#include <libgnomeui/gnome-dialog.h>
#include <libgnomeui/gnome-dialog-util.h>
#include <evolution-shell-component-utils.h>
#include "../print.h"
#include "save-comp.h"
#include "delete-comp.h"
#include "send-comp.h"
#include "changed-comp.h"
#include "comp-editor.h"
/* Private part of the CompEditor structure */
struct _CompEditorPrivate {
/* Client to use */
CalClient *client;
/* Calendar object/uid we are editing; this is an internal copy */
CalComponent *comp;
/* The pages we have */
GList *pages;
/* Toplevel window for the dialog */
GtkWidget *window;
BonoboUIComponent *uic;
/* Notebook to hold the pages */
GtkNotebook *notebook;
GtkWidget *filesel;
gboolean changed;
gboolean needs_send;
gboolean updating;
};
static void comp_editor_class_init (CompEditorClass *class);
static void comp_editor_init (CompEditor *editor);
static void comp_editor_destroy (GtkObject *object);
static void real_set_cal_client (CompEditor *editor, CalClient *client);
static void real_edit_comp (CompEditor *editor, CalComponent *comp);
static void real_send_comp (CompEditor *editor, CalComponentItipMethod method);
static void save_comp (CompEditor *editor);
static void save_comp_with_send (CompEditor *editor);
static void delete_comp (CompEditor *editor);
static void close_dialog (CompEditor *editor);
static void page_changed_cb (GtkWidget *widget, gpointer data);
static void page_needs_send_cb (GtkWidget *widget, gpointer data);
static void page_summary_changed_cb (GtkWidget *widget, const char *summary, gpointer data);
static void page_dates_changed_cb (GtkWidget *widget, CompEditorPageDates *dates, gpointer data);
static void obj_updated_cb (CalClient *client, const char *uid, gpointer data);
static void obj_removed_cb (CalClient *client, const char *uid, gpointer data);
static void save_cmd (GtkWidget *widget, gpointer data);
static void save_close_cmd (GtkWidget *widget, gpointer data);
static void save_as_cmd (GtkWidget *widget, gpointer data);
static void delete_cmd (GtkWidget *widget, gpointer data);
static void print_cmd (GtkWidget *widget, gpointer data);
static void print_preview_cmd (GtkWidget *widget, gpointer data);
static void print_setup_cmd (GtkWidget *widget, gpointer data);
static void close_cmd (GtkWidget *widget, gpointer data);
static gint delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer data);
static EPixmap pixmaps [] =
{
E_PIXMAP ("/menu/File/FileSave", "save-16.png"),
E_PIXMAP ("/menu/File/FileSaveAndClose", "save-16.png"),
E_PIXMAP ("/menu/File/FileSaveAs", "save-as-16.png"),
E_PIXMAP ("/menu/File/FileDelete", "evolution-trash-mini.png"),
E_PIXMAP ("/menu/File/FilePrint", "print.xpm"),
E_PIXMAP ("/menu/File/FilePrintPreview", "print-preview.xpm"),
E_PIXMAP ("/Toolbar/FileSaveAndClose", "buttons/save-24.png"),
E_PIXMAP ("/Toolbar/FilePrint", "buttons/print.png"),
E_PIXMAP ("/Toolbar/FileDelete", "buttons/delete-message.png"),
E_PIXMAP_END
};
static BonoboUIVerb verbs [] = {
BONOBO_UI_UNSAFE_VERB ("FileSave", save_cmd),
BONOBO_UI_UNSAFE_VERB ("FileSaveAndClose", save_close_cmd),
BONOBO_UI_UNSAFE_VERB ("FileSaveAs", save_as_cmd),
BONOBO_UI_UNSAFE_VERB ("FileDelete", delete_cmd),
BONOBO_UI_UNSAFE_VERB ("FilePrint", print_cmd),
BONOBO_UI_UNSAFE_VERB ("FilePrintPreview", print_preview_cmd),
BONOBO_UI_UNSAFE_VERB ("FilePrintSetup", print_setup_cmd),
BONOBO_UI_UNSAFE_VERB ("FileClose", close_cmd),
BONOBO_UI_VERB_END
};
#define CLASS(page) (COMP_EDITOR_CLASS (GTK_OBJECT (page)->klass))
static GtkObjectClass *parent_class;
GtkType
comp_editor_get_type (void)
{
static GtkType comp_editor_type = 0;
if (!comp_editor_type) {
static const GtkTypeInfo comp_editor_info = {
"CompEditor",
sizeof (CompEditor),
sizeof (CompEditorClass),
(GtkClassInitFunc) comp_editor_class_init,
(GtkObjectInitFunc) comp_editor_init,
NULL, /* reserved_1 */
NULL, /* reserved_2 */
(GtkClassInitFunc) NULL
};
comp_editor_type = gtk_type_unique (GTK_TYPE_OBJECT,
&comp_editor_info);
}
return comp_editor_type;
}
/* Class initialization function for the calendar component editor */
static void
comp_editor_class_init (CompEditorClass *klass)
{
GtkObjectClass *object_class;
object_class = (GtkObjectClass *) klass;
parent_class = gtk_type_class (GTK_TYPE_OBJECT);
klass->set_cal_client = real_set_cal_client;
klass->edit_comp = real_edit_comp;
klass->send_comp = real_send_comp;
object_class->destroy = comp_editor_destroy;
}
/* Creates the basic in the editor */
static void
setup_widgets (CompEditor *editor)
{
CompEditorPrivate *priv;
BonoboUIContainer *container;
GtkWidget *vbox;
priv = editor->priv;
/* Window and basic vbox */
priv->window = bonobo_window_new ("event-editor", "iCalendar Editor");
gtk_signal_connect (GTK_OBJECT (priv->window), "delete_event",
GTK_SIGNAL_FUNC (delete_event_cb), editor);
priv->uic = bonobo_ui_component_new ("comp-editor");
container = bonobo_ui_container_new ();
bonobo_ui_container_set_win (container, BONOBO_WINDOW (priv->window));
bonobo_ui_component_set_container (priv->uic, BONOBO_OBJREF (container));
bonobo_ui_engine_config_set_path (bonobo_window_get_ui_engine (BONOBO_WINDOW (priv->window)),
"/evolution/UIConf/kvps");
bonobo_ui_component_add_verb_list_with_data (priv->uic, verbs, editor);
bonobo_ui_util_set_ui (priv->uic, EVOLUTION_DATADIR,
"evolution-comp-editor.xml",
"evolution-calendar");
e_pixmaps_update (priv->uic, pixmaps);
vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
gtk_widget_show (vbox);
gtk_container_set_border_width (GTK_CONTAINER (vbox), GNOME_PAD_SMALL);
bonobo_window_set_contents (BONOBO_WINDOW (priv->window), vbox);
/* Notebook */
priv->notebook = GTK_NOTEBOOK (gtk_notebook_new ());
gtk_widget_show (GTK_WIDGET (priv->notebook));
gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (priv->notebook),
TRUE, TRUE, 0);
}
/* Object initialization function for the calendar component editor */
static void
comp_editor_init (CompEditor *editor)
{
CompEditorPrivate *priv;
priv = g_new0 (CompEditorPrivate, 1);
editor->priv = priv;
setup_widgets (editor);
priv->pages = NULL;
priv->changed = FALSE;
priv->needs_send = FALSE;
}
/* Destroy handler for the calendar component editor */
static void
comp_editor_destroy (GtkObject *object)
{
CompEditor *editor;
CompEditorPrivate *priv;
editor = COMP_EDITOR (object);
priv = editor->priv;
gtk_signal_disconnect_by_data (GTK_OBJECT (priv->client), editor);
if (priv->window) {
gtk_widget_destroy (priv->window);
priv->window = NULL;
}
if (priv->comp) {
gtk_object_unref (GTK_OBJECT (priv->comp));
priv->comp = NULL;
}
g_free (priv);
editor->priv = NULL;
if (GTK_OBJECT_CLASS (parent_class)->destroy)
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}
/**
* comp_editor_set_changed:
* @editor: A component editor
* @changed: Value to set the changed state to
*
* Set the dialog changed state to the given value
**/
void
comp_editor_set_changed (CompEditor *editor, gboolean changed)
{
CompEditorPrivate *priv;
priv = editor->priv;
priv->changed = changed;
}
/**
* comp_editor_get_changed:
* @editor: A component editor
*
* Gets the changed state of the dialog
*
* Return value: A boolean indicating if the dialog is in a changed
* state
**/
gboolean
comp_editor_get_changed (CompEditor *editor)
{
CompEditorPrivate *priv;
priv = editor->priv;
return priv->changed;
}
/**
* comp_editor_set_needs_send:
* @editor: A component editor
* @needs_send: Value to set the needs send state to
*
* Set the dialog needs send state to the given value
**/
void
comp_editor_set_needs_send (CompEditor *editor, gboolean needs_send)
{
CompEditorPrivate *priv;
priv = editor->priv;
priv->needs_send = needs_send;
}
/**
* comp_editor_get_needs_send:
* @editor: A component editor
*
* Gets the needs send state of the dialog
*
* Return value: A boolean indicating if the dialog is in a needs send
* state
**/
gboolean
comp_editor_get_needs_send (CompEditor *editor)
{
CompEditorPrivate *priv;
priv = editor->priv;
return priv->needs_send;
}
/**
* comp_editor_append_page:
* @editor: A component editor
* @page: A component editor page
* @label: Label of the page
*
* Appends a page to the editor notebook with the given label
**/
void
comp_editor_append_page (CompEditor *editor,
CompEditorPage *page,
const char *label)
{
CompEditorPrivate *priv;
GtkWidget *page_widget;
GtkWidget *label_widget;
gboolean is_first_page;
g_return_if_fail (editor != NULL);
g_return_if_fail (IS_COMP_EDITOR (editor));
g_return_if_fail (page != NULL);
g_return_if_fail (IS_COMP_EDITOR_PAGE (page));
g_return_if_fail (label != NULL);
priv = editor->priv;
gtk_object_ref (GTK_OBJECT (page));
/* If we are editing something, fill the widgets with current info */
if (priv->comp != NULL) {
CalComponent *comp;
comp = comp_editor_get_current_comp (editor);
comp_editor_page_fill_widgets (page, comp);
gtk_object_unref (GTK_OBJECT (comp));
}
page_widget = comp_editor_page_get_widget (page);
g_assert (page_widget != NULL);
label_widget = gtk_label_new (label);
is_first_page = (priv->pages == NULL);
priv->pages = g_list_append (priv->pages, page);
gtk_notebook_append_page (priv->notebook, page_widget, label_widget);
/* Listen for things happening on the page */
gtk_signal_connect (GTK_OBJECT (page), "needs_send",
GTK_SIGNAL_FUNC (page_needs_send_cb), editor);
gtk_signal_connect (GTK_OBJECT (page), "changed",
GTK_SIGNAL_FUNC (page_changed_cb), editor);
gtk_signal_connect (GTK_OBJECT (page), "summary_changed",
GTK_SIGNAL_FUNC (page_summary_changed_cb), editor);
gtk_signal_connect (GTK_OBJECT (page), "dates_changed",
GTK_SIGNAL_FUNC (page_dates_changed_cb), editor);
/* The first page is the main page of the editor, so we ask it to focus
* its main widget.
*/
if (is_first_page)
comp_editor_page_focus_main_widget (page);
}
/**
* comp_editor_remove_page:
* @editor: A component editor
* @page: A component editor page
*
* Removes the page from the component editor
**/
void
comp_editor_remove_page (CompEditor *editor, CompEditorPage *page)
{
CompEditorPrivate *priv;
GtkWidget *page_widget;
gint page_num;
g_return_if_fail (editor != NULL);
g_return_if_fail (IS_COMP_EDITOR (editor));
g_return_if_fail (page != NULL);
g_return_if_fail (IS_COMP_EDITOR_PAGE (page));
priv = editor->priv;
page_widget = comp_editor_page_get_widget (page);
page_num = gtk_notebook_page_num (priv->notebook, page_widget);
gtk_notebook_remove_page (priv->notebook, page_num);
priv->pages = g_list_remove (priv->pages, page);
gtk_object_unref (GTK_OBJECT (page));
}
/**
* comp_editor_show_page:
* @editor:
* @page:
*
*
**/
void
comp_editor_show_page (CompEditor *editor, CompEditorPage *page)
{
CompEditorPrivate *priv;
GtkWidget *page_widget;
gint page_num;
g_return_if_fail (editor != NULL);
g_return_if_fail (IS_COMP_EDITOR (editor));
g_return_if_fail (page != NULL);
g_return_if_fail (IS_COMP_EDITOR_PAGE (page));
priv = editor->priv;
page_widget = comp_editor_page_get_widget (page);
page_num = gtk_notebook_page_num (priv->notebook, page_widget);
gtk_notebook_set_page (priv->notebook, page_num);
}
/**
* comp_editor_set_cal_client:
* @editor: A component editor
* @client: The calendar client to use
*
* Sets the calendar client used by the editor to update components
**/
void
comp_editor_set_cal_client (CompEditor *editor, CalClient *client)
{
CompEditorClass *klass;
g_return_if_fail (editor != NULL);
g_return_if_fail (IS_COMP_EDITOR (editor));
klass = COMP_EDITOR_CLASS (GTK_OBJECT (editor)->klass);
if (klass->set_cal_client)
klass->set_cal_client (editor, client);
}
/**
* comp_editor_get_cal_client:
* @editor: A component editor
*
* Returns the calendar client of the editor
*
* Return value: The calendar client of the editor
**/
CalClient *
comp_editor_get_cal_client (CompEditor *editor)
{
CompEditorPrivate *priv;
g_return_val_if_fail (editor != NULL, NULL);
g_return_val_if_fail (IS_COMP_EDITOR (editor), NULL);
priv = editor->priv;
return priv->client;
}
/* Creates an appropriate title for the event editor dialog */
static char *
make_title_from_comp (CalComponent *comp)
{
char *title;
const char *type_string;
CalComponentVType type;
CalComponentText text;
if (!comp)
return g_strdup (_("Edit Appointment"));
type = cal_component_get_vtype (comp);
switch (type) {
case CAL_COMPONENT_EVENT:
type_string = _("Appointment - %s");
break;
case CAL_COMPONENT_TODO:
type_string = _("Task - %s");
break;
case CAL_COMPONENT_JOURNAL:
type_string = _("Journal entry - %s");
break;
default:
g_message ("make_title_from_comp(): Cannot handle object of type %d", type);
return NULL;
}
cal_component_get_summary (comp, &text);
if (text.value) {
char *summary;
summary = e_utf8_to_locale_string (text.value);
title = g_strdup_printf (type_string, summary);
g_free (summary);
} else
title = g_strdup_printf (type_string, _("No summary"));
return title;
}
/* Sets the event editor's window title from a calendar component */
static void
set_title_from_comp (CompEditor *editor)
{
CompEditorPrivate *priv;
char *title;
priv = editor->priv;
title = make_title_from_comp (priv->comp);
gtk_window_set_title (GTK_WINDOW (priv->window), title);
g_free (title);
}
static void
fill_widgets (CompEditor *editor)
{
CompEditorPrivate *priv;
GList *l;
priv = editor->priv;
for (l = priv->pages; l != NULL; l = l->next)
comp_editor_page_fill_widgets (l->data, priv->comp);
}
static void
real_set_cal_client (CompEditor *editor, CalClient *client)
{
CompEditorPrivate *priv;
GList *elem;
g_return_if_fail (editor != NULL);
g_return_if_fail (IS_COMP_EDITOR (editor));
priv = editor->priv;
if (client == priv->client)
return;
if (client) {
g_return_if_fail (IS_CAL_CLIENT (client));
g_return_if_fail (cal_client_get_load_state (client) ==
CAL_CLIENT_LOAD_LOADED);
gtk_object_ref (GTK_OBJECT (client));
}
if (priv->client) {
gtk_signal_disconnect_by_data (GTK_OBJECT (priv->client),
editor);
gtk_object_unref (GTK_OBJECT (priv->client));
}
priv->client = client;
/* Pass the client to any pages that need it. */
for (elem = priv->pages; elem; elem = elem->next)
comp_editor_page_set_cal_client (elem->data, client);
gtk_signal_connect (GTK_OBJECT (priv->client), "obj_updated",
GTK_SIGNAL_FUNC (obj_updated_cb), editor);
gtk_signal_connect (GTK_OBJECT (priv->client), "obj_removed",
GTK_SIGNAL_FUNC (obj_removed_cb), editor);
}
static void
real_edit_comp (CompEditor *editor, CalComponent *comp)
{
CompEditorPrivate *priv;
g_return_if_fail (editor != NULL);
g_return_if_fail (IS_COMP_EDITOR (editor));
priv = editor->priv;
if (priv->comp) {
gtk_object_unref (GTK_OBJECT (priv->comp));
priv->comp = NULL;
}
if (comp)
priv->comp = cal_component_clone (comp);
set_title_from_comp (editor);
fill_widgets (editor);
}
static void
real_send_comp (CompEditor *editor, CalComponentItipMethod method)
{
CompEditorPrivate *priv;
g_return_if_fail (editor != NULL);
g_return_if_fail (IS_COMP_EDITOR (editor));
priv = editor->priv;
itip_send_comp (method, priv->comp);
}
/**
* comp_editor_edit_comp:
* @editor: A component editor
* @comp: A calendar component
*
* Starts the editor editing the given component
**/
void
comp_editor_edit_comp (CompEditor *editor, CalComponent *comp)
{
CompEditorClass *klass;
g_return_if_fail (editor != NULL);
g_return_if_fail (IS_COMP_EDITOR (editor));
g_return_if_fail (comp != NULL);
g_return_if_fail (IS_CAL_COMPONENT (comp));
klass = COMP_EDITOR_CLASS (GTK_OBJECT (editor)->klass);
if (klass->edit_comp)
klass->edit_comp (editor, comp);
}
CalComponent *
comp_editor_get_current_comp (CompEditor *editor)
{
CompEditorPrivate *priv;
CalComponent *comp;
GList *l;
g_return_val_if_fail (editor != NULL, NULL);
g_return_val_if_fail (IS_COMP_EDITOR (editor), NULL);
priv = editor->priv;
comp = cal_component_clone (priv->comp);
for (l = priv->pages; l != NULL; l = l->next)
comp_editor_page_fill_component (l->data, comp);
return comp;
}
/**
* comp_editor_save_comp:
* @editor:
*
*
**/
void
comp_editor_save_comp (CompEditor *editor)
{
save_comp (editor);
}
/**
* comp_editor_delete_comp:
* @editor:
*
*
**/
void
comp_editor_delete_comp (CompEditor *editor)
{
delete_comp (editor);
}
/**
* comp_editor_send_comp:
* @editor:
* @method:
*
*
**/
void
comp_editor_send_comp (CompEditor *editor, CalComponentItipMethod method)
{
CompEditorClass *klass;
g_return_if_fail (editor != NULL);
g_return_if_fail (IS_COMP_EDITOR (editor));
klass = COMP_EDITOR_CLASS (GTK_OBJECT (editor)->klass);
if (klass->send_comp)
klass->send_comp (editor, method);
}
/**
* comp_editor_merge_ui:
* @editor:
* @filename:
* @verbs:
*
*
**/
void
comp_editor_merge_ui (CompEditor *editor, const char *filename, BonoboUIVerb *verbs)
{
CompEditorPrivate *priv;
BonoboUIEngine *engine;
BonoboUINode *node;
g_return_if_fail (editor != NULL);
g_return_if_fail (IS_COMP_EDITOR (editor));
priv = editor->priv;
engine = bonobo_window_get_ui_engine (BONOBO_WINDOW (priv->window));
node = bonobo_ui_util_new_ui (priv->uic, filename, "",
"evolution-calendar");
g_assert (node != NULL);
bonobo_ui_engine_xml_merge_tree (engine, "/", node, "comp-editor");
bonobo_ui_component_add_verb_list_with_data (priv->uic, verbs, editor);
}
/**
* comp_editor_set_ui_prop:
* @editor:
* @path:
* @attr:
* @val:
*
*
**/
void
comp_editor_set_ui_prop (CompEditor *editor,
const char *path,
const char *attr,
const char *val)
{
CompEditorPrivate *priv;
g_return_if_fail (editor != NULL);
g_return_if_fail (IS_COMP_EDITOR (editor));
priv = editor->priv;
bonobo_ui_component_set_prop (priv->uic, path, attr, val, NULL);
}
/* Brings attention to a window by raising it and giving it focus */
static void
raise_and_focus (GtkWidget *widget)
{
g_assert (GTK_WIDGET_REALIZED (widget));
gdk_window_show (widget->window);
gtk_widget_grab_focus (widget);
}
/**
* comp_editor_focus:
* @editor: A component editor
*
* Brings the editor window to the front and gives it focus
**/
void
comp_editor_focus (CompEditor *editor)
{
CompEditorPrivate *priv;
g_return_if_fail (editor != NULL);
g_return_if_fail (IS_COMP_EDITOR (editor));
priv = editor->priv;
gtk_widget_show (priv->window);
raise_and_focus (priv->window);
}
static void
save_comp (CompEditor *editor)
{
CompEditorPrivate *priv;
GList *l;
priv = editor->priv;
if (!priv->changed)
return;
for (l = priv->pages; l != NULL; l = l->next)
comp_editor_page_fill_component (l->data, priv->comp);
cal_component_commit_sequence (priv->comp);
priv->updating = TRUE;
if (!cal_client_update_object (priv->client, priv->comp))
g_message ("save_comp (): Could not update the object!");
else
priv->changed = FALSE;
priv->updating = FALSE;
}
static void
save_comp_with_send (CompEditor *editor)
{
CompEditorPrivate *priv;
gboolean send;
priv = editor->priv;
send = priv->changed && priv->needs_send;
save_comp (editor);
if (send && send_component_dialog (priv->comp))
comp_editor_send_comp (editor, CAL_COMPONENT_METHOD_REQUEST);
}
static void
delete_comp (CompEditor *editor)
{
CompEditorPrivate *priv;
const char *uid;
priv = editor->priv;
cal_component_get_uid (priv->comp, &uid);
priv->updating = TRUE;
cal_client_remove_object (priv->client, uid);
priv->updating = FALSE;
close_dialog (editor);
}
static gboolean
prompt_to_save_changes (CompEditor *editor)
{
CompEditorPrivate *priv;
priv = editor->priv;
if (!priv->changed)
return TRUE;
switch (save_component_dialog (GTK_WINDOW (priv->window))) {
case 0: /* Save */
/* FIXME: If an error occurs here, we should popup a dialog
and then return FALSE. */
save_comp_with_send (editor);
return TRUE;
case 1: /* Discard */
return TRUE;
case 2: /* Cancel */
default:
return FALSE;
}
}
/* Closes the dialog box and emits the appropriate signals */
static void
close_dialog (CompEditor *editor)
{
CompEditorPrivate *priv;
GList *l;
priv = editor->priv;
g_assert (priv->window != NULL);
for (l = priv->pages; l != NULL; l = l->next)
gtk_object_unref (GTK_OBJECT (l->data));
gtk_object_destroy (GTK_OBJECT (editor));
}
/* Menu Commands */
static void
save_cmd (GtkWidget *widget, gpointer data)
{
CompEditor *editor = COMP_EDITOR (data);
save_comp_with_send (editor);
}
static void
save_close_cmd (GtkWidget *widget, gpointer data)
{
CompEditor *editor = COMP_EDITOR (data);
save_comp_with_send (editor);
close_dialog (editor);
}
static void
save_as_ok (GtkWidget *widget, gpointer data)
{
CompEditor *editor = COMP_EDITOR (data);
CompEditorPrivate *priv;
struct stat s;
char *path;
int ret = 0;
priv = editor->priv;
path = gtk_file_selection_get_filename (GTK_FILE_SELECTION (priv->filesel));
if (stat (path, &s) == 0) {
GtkWidget *dlg;
GtkWidget *text;
dlg = gnome_dialog_new (_("Overwrite file?"),
GNOME_STOCK_BUTTON_YES,
GNOME_STOCK_BUTTON_NO,
NULL);
text = gtk_label_new (_("A file by that name already exists.\nOverwrite it?"));
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dlg)->vbox), text, TRUE, TRUE, 4);
gtk_window_set_policy (GTK_WINDOW (dlg), FALSE, TRUE, FALSE);
gtk_widget_show (text);
ret = gnome_dialog_run_and_close (GNOME_DIALOG (dlg));
}
if (ret == 0) {
FILE *file;
gchar *ical_string;
icalcomponent *top_level;
icalcomponent *icalcomp;
icalproperty *prop;
top_level = icalcomponent_new (ICAL_VCALENDAR_COMPONENT);
/* RFC 2445, section 4.7.1 */
prop = icalproperty_new_calscale ("GREGORIAN");
icalcomponent_add_property (top_level, prop);
/* RFC 2445, section 4.7.3 */
prop = icalproperty_new_prodid ("-//Ximian//NONSGML Evolution Calendar//EN");
icalcomponent_add_property (top_level, prop);
/* RFC 2445, section 4.7.4. This is the iCalendar spec version, *NOT*
* the product version! Do not change this!
*/
prop = icalproperty_new_version ("2.0");
icalcomponent_add_property (top_level, prop);
icalcomp = cal_component_get_icalcomponent (priv->comp);
g_assert (icalcomp != NULL);
icalcomponent_add_component (top_level, icalcomp);
ical_string = icalcomponent_as_ical_string (top_level);
file = fopen (path, "w");
if (file == NULL) {
g_warning ("Couldn't save item");
gtk_main_quit ();
return;
}
fprintf (file, ical_string);
fclose (file);
gtk_main_quit ();
}
}
static void
save_as_cmd (GtkWidget *widget, gpointer data)
{
CompEditor *editor = COMP_EDITOR (data);
CompEditorPrivate *priv;
GtkFileSelection *fs;
char *path;
priv = editor->priv;
fs = GTK_FILE_SELECTION (gtk_file_selection_new (_("Save As...")));
path = g_strdup_printf ("%s/", g_get_home_dir ());
gtk_file_selection_set_filename (fs, path);
g_free (path);
gtk_signal_connect (GTK_OBJECT (fs->ok_button), "clicked",
GTK_SIGNAL_FUNC (save_as_ok), editor);
gtk_signal_connect (GTK_OBJECT (fs->cancel_button), "clicked",
GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
priv->filesel = GTK_WIDGET (fs);
gtk_widget_show (priv->filesel);
gtk_grab_add (priv->filesel);
gtk_main ();
gtk_widget_destroy (priv->filesel);
priv->filesel = NULL;
}
static void
delete_cmd (GtkWidget *widget, gpointer data)
{
CompEditor *editor = COMP_EDITOR (data);
CompEditorPrivate *priv;
CalComponentVType vtype;
priv = editor->priv;
vtype = cal_component_get_vtype (priv->comp);
if (delete_component_dialog (priv->comp, 1, vtype, priv->window))
delete_comp (editor);
}
static void
print_cmd (GtkWidget *widget, gpointer data)
{
CompEditor *editor = COMP_EDITOR (data);
CalComponent *comp;
comp = comp_editor_get_current_comp (editor);
print_comp (comp, FALSE);
gtk_object_unref (GTK_OBJECT (comp));
}
static void
print_preview_cmd (GtkWidget *widget, gpointer data)
{
CompEditor *editor = COMP_EDITOR (data);
CalComponent *comp;
comp = comp_editor_get_current_comp (editor);
print_comp (comp, TRUE);
gtk_object_unref (GTK_OBJECT (comp));
}
static void
print_setup_cmd (GtkWidget *widget, gpointer data)
{
CompEditor *editor = COMP_EDITOR (data);
CompEditorPrivate *priv;
priv = editor->priv;
print_setup ();
}
static void
close_cmd (GtkWidget *widget, gpointer data)
{
CompEditor *editor = COMP_EDITOR (data);
if (prompt_to_save_changes (editor))
close_dialog (editor);
}
static void
page_changed_cb (GtkWidget *widget, gpointer data)
{
CompEditor *editor = COMP_EDITOR (data);
CompEditorPrivate *priv;
priv = editor->priv;
priv->changed = TRUE;
}
static void
page_needs_send_cb (GtkWidget *widget, gpointer data)
{
CompEditor *editor = COMP_EDITOR (data);
CompEditorPrivate *priv;
priv = editor->priv;
priv->needs_send = TRUE;
}
/* Page signal callbacks */
static void
page_summary_changed_cb (GtkWidget *widget, const char *summary, gpointer data)
{
CompEditor *editor = COMP_EDITOR (data);
CompEditorPrivate *priv;
GList *l;
priv = editor->priv;
for (l = priv->pages; l != NULL; l = l->next)
comp_editor_page_set_summary (l->data, summary);
priv->changed = TRUE;
}
static void
page_dates_changed_cb (GtkWidget *widget,
CompEditorPageDates *dates,
gpointer data)
{
CompEditor *editor = COMP_EDITOR (data);
CompEditorPrivate *priv;
GList *l;
priv = editor->priv;
for (l = priv->pages; l != NULL; l = l->next)
comp_editor_page_set_dates (l->data, dates);
priv->changed = TRUE;
}
static void
obj_updated_cb (CalClient *client, const char *uid, gpointer data)
{
CompEditor *editor = COMP_EDITOR (data);
CompEditorPrivate *priv;
CalComponent *comp = NULL;
CalClientGetStatus status;
const char *edit_uid;
priv = editor->priv;
cal_component_get_uid (priv->comp, &edit_uid);
if (!strcmp (uid, edit_uid) && !priv->updating) {
if (changed_component_dialog (priv->comp, FALSE, priv->changed)) {
status = cal_client_get_object (priv->client, uid, &comp);
if (status == CAL_CLIENT_GET_SUCCESS) {
comp_editor_edit_comp (editor, comp);
gtk_object_unref (GTK_OBJECT (comp));
} else {
GtkWidget *dlg;
dlg = gnome_error_dialog (_("Unable to obtain current version!"));
gnome_dialog_run_and_close (GNOME_DIALOG (dlg));
}
}
}
}
static void
obj_removed_cb (CalClient *client, const char *uid, gpointer data)
{
CompEditor *editor = COMP_EDITOR (data);
CompEditorPrivate *priv;
const char *edit_uid;
priv = editor->priv;
cal_component_get_uid (priv->comp, &edit_uid);
if (!strcmp (uid, edit_uid) && !priv->updating) {
if (changed_component_dialog (priv->comp, TRUE, priv->changed))
close_dialog (editor);
}
}
static gint
delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer data)
{
CompEditor *editor = COMP_EDITOR (data);
if (prompt_to_save_changes (editor))
close_dialog (editor);
return TRUE;
}