3cf26e43e2
2003-01-25 Hans Petter Jansson <hpj@ximian.com> Mainly making all views use PangoLayouts for text. When drawing a PangoLayout, the draw offset is the top left corner of the layout, not the text's baseline. Keep this in mind when viewing the changes. I'll be brief about the exact changes, since they speak better for themselves. * gui/e-day-view-time-item.c (e_day_view_time_item_get_column_width): Use Pango. (e_day_view_time_item_draw): Use Pango. * gui/e-day-view-top-item.c (e_day_view_top_item_draw): Use Pango. (e_day_view_top_item_draw_long_event): Add some FIXME text so we can see when this is being used. Is it in use at all? * gui/e-day-view.c: No longer specify an explicit X font string for the large font. Use the main font, and change the point size. (e_day_view_init): Use Pango. (e_day_view_style_set): Use Pango. Comment out the gdk_font setting for the drag text items for now. * gui/e-day-view.h: Use Pango. * gui/e-week-view-event-item.c (e_week_view_draw_time): Use Pango. * gui/e-week-view-main-item.c (e_week_view_main_item_draw_day): Use Pango. * gui/e-week-view-titles-item.c (e_week_view_titles_item_draw): Use Pango. * gui/e-week-view.c: No longer specify an explicit X font string for the small font. Use the main font, and change the point size. (e_week_view_init): Use Pango. (e_week_view_destroy): Use Pango. (get_string_width): Implemented for convenience. (get_digit_width): Implemented for convenience. (e_week_view_style_set): Use Pango. (e_week_view_recalc_cell_sizes): Use Pango. (e_week_view_get_time_string_width): Use Pango. * gui/e-week-view.h: Use Pango. Following are some random UTF-8 fixes and a crash fix. * gui/itip-utils.c (comp_description): Use g_locale_to_utf8 (). * gui/dialogs/comp-editor.c (make_title_from_comp): Return a UTF-8 string. * gui/dialogs/alarm-page.c (alarm_page_set_summary): Pass UTF-8 directly to GTK. * gui/dialogs/delete-comp.c (delete_component_dialog): Ditto. * gui/dialogs/meeting-page.c (meeting_page_fill_widgets): Ditto. (meeting_page_construct): Ditto. * gui/dialogs/recurrence-page.c (recurrence_page_set_summary): Ditto. * gui/dialogs/event-editor.c (event_editor_finalize): Fix crash caused by gtk_object_destroy()-ing a non-GtkObject. svn path=/trunk/; revision=19628
502 lines
13 KiB
C
502 lines
13 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
|
|
|
/* Evolution calendar - Event editor dialog
|
|
*
|
|
* Copyright (C) 2000 Ximian, Inc.
|
|
* Copyright (C) 2001 Ximian, Inc.
|
|
*
|
|
* Authors: Miguel de Icaza <miguel@ximian.com>
|
|
* Federico Mena-Quintero <federico@ximian.com>
|
|
* Seth Alves <alves@hungry.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of version 2 of the GNU General Public
|
|
* License as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include <string.h>
|
|
#include <glade/glade.h>
|
|
#include <gal/widgets/e-unicode.h>
|
|
#include <libgnome/gnome-i18n.h>
|
|
#include <widgets/misc/e-dateedit.h>
|
|
|
|
#include "event-page.h"
|
|
#include "alarm-page.h"
|
|
#include "recurrence-page.h"
|
|
#include "meeting-page.h"
|
|
#include "schedule-page.h"
|
|
#include "cancel-comp.h"
|
|
#include "event-editor.h"
|
|
|
|
struct _EventEditorPrivate {
|
|
EventPage *event_page;
|
|
AlarmPage *alarm_page;
|
|
RecurrencePage *recur_page;
|
|
MeetingPage *meet_page;
|
|
SchedulePage *sched_page;
|
|
|
|
EMeetingModel *model;
|
|
|
|
gboolean meeting_shown;
|
|
gboolean updating;
|
|
};
|
|
|
|
|
|
|
|
static void event_editor_class_init (EventEditorClass *class);
|
|
static void event_editor_init (EventEditor *ee);
|
|
static void event_editor_set_cal_client (CompEditor *editor, CalClient *client);
|
|
static void event_editor_edit_comp (CompEditor *editor, CalComponent *comp);
|
|
static gboolean event_editor_send_comp (CompEditor *editor, CalComponentItipMethod method);
|
|
static void event_editor_finalize (GObject *object);
|
|
|
|
static void schedule_meeting_cmd (GtkWidget *widget, gpointer data);
|
|
static void refresh_meeting_cmd (GtkWidget *widget, gpointer data);
|
|
static void cancel_meeting_cmd (GtkWidget *widget, gpointer data);
|
|
static void forward_cmd (GtkWidget *widget, gpointer data);
|
|
|
|
static void model_row_changed_cb (ETableModel *etm, int row, gpointer data);
|
|
static void row_count_changed_cb (ETableModel *etm, int row, int count, gpointer data);
|
|
|
|
static EPixmap pixmaps [] = {
|
|
E_PIXMAP ("/Toolbar/Actions/ActionScheduleMeeting", "schedule-meeting-24.png"),
|
|
E_PIXMAP_END
|
|
};
|
|
|
|
static BonoboUIVerb verbs [] = {
|
|
BONOBO_UI_UNSAFE_VERB ("ActionScheduleMeeting", schedule_meeting_cmd),
|
|
BONOBO_UI_UNSAFE_VERB ("ActionRefreshMeeting", refresh_meeting_cmd),
|
|
BONOBO_UI_UNSAFE_VERB ("ActionCancelMeeting", cancel_meeting_cmd),
|
|
BONOBO_UI_UNSAFE_VERB ("ActionForward", forward_cmd),
|
|
|
|
BONOBO_UI_VERB_END
|
|
};
|
|
|
|
static CompEditorClass *parent_class;
|
|
|
|
|
|
|
|
/**
|
|
* event_editor_get_type:
|
|
*
|
|
* Registers the #EventEditor class if necessary, and returns the type ID
|
|
* associated to it.
|
|
*
|
|
* Return value: The type ID of the #EventEditor class.
|
|
**/
|
|
|
|
E_MAKE_TYPE (event_editor, "EventEditor", EventEditor, event_editor_class_init,
|
|
event_editor_init, TYPE_COMP_EDITOR);
|
|
|
|
/* Class initialization function for the event editor */
|
|
static void
|
|
event_editor_class_init (EventEditorClass *klass)
|
|
{
|
|
GObjectClass *gobject_class;
|
|
CompEditorClass *editor_class;
|
|
|
|
gobject_class = (GObjectClass *) klass;
|
|
editor_class = (CompEditorClass *) klass;
|
|
|
|
parent_class = g_type_class_ref(TYPE_COMP_EDITOR);
|
|
|
|
editor_class->set_cal_client = event_editor_set_cal_client;
|
|
editor_class->edit_comp = event_editor_edit_comp;
|
|
editor_class->send_comp = event_editor_send_comp;
|
|
|
|
gobject_class->finalize = event_editor_finalize;
|
|
}
|
|
|
|
static void
|
|
set_menu_sens (EventEditor *ee)
|
|
{
|
|
EventEditorPrivate *priv;
|
|
gboolean sens, existing, user, read_only;
|
|
|
|
priv = ee->priv;
|
|
|
|
existing = comp_editor_get_existing_org (COMP_EDITOR (ee));
|
|
user = comp_editor_get_user_org (COMP_EDITOR (ee));
|
|
read_only = cal_client_is_read_only (comp_editor_get_cal_client (COMP_EDITOR (ee)));
|
|
|
|
sens = priv->meeting_shown;
|
|
comp_editor_set_ui_prop (COMP_EDITOR (ee),
|
|
"/commands/ActionScheduleMeeting",
|
|
"sensitive", sens || read_only ? "0" : "1");
|
|
|
|
sens = priv->meeting_shown && existing && !user && !read_only;
|
|
comp_editor_set_ui_prop (COMP_EDITOR (ee),
|
|
"/commands/ActionRefreshMeeting",
|
|
"sensitive", sens ? "1" : "0");
|
|
|
|
sens = priv->meeting_shown && existing && user && !read_only;
|
|
comp_editor_set_ui_prop (COMP_EDITOR (ee),
|
|
"/commands/ActionCancelMeeting",
|
|
"sensitive", sens? "1" : "0");
|
|
|
|
comp_editor_set_ui_prop (COMP_EDITOR (ee),
|
|
"/commands/FileSave",
|
|
"sensitive", read_only ? "0" : "1");
|
|
comp_editor_set_ui_prop (COMP_EDITOR (ee),
|
|
"/commands/FileSaveAndClose",
|
|
"sensitive", read_only ? "0" : "1");
|
|
comp_editor_set_ui_prop (COMP_EDITOR (ee),
|
|
"/commands/FileDelete",
|
|
"sensitive", read_only ? "0" : "1");
|
|
}
|
|
|
|
static void
|
|
init_widgets (EventEditor *ee)
|
|
{
|
|
EventEditorPrivate *priv;
|
|
|
|
priv = ee->priv;
|
|
|
|
g_signal_connect((priv->model), "model_row_changed",
|
|
G_CALLBACK (model_row_changed_cb), ee);
|
|
g_signal_connect((priv->model), "model_rows_inserted",
|
|
G_CALLBACK (row_count_changed_cb), ee);
|
|
g_signal_connect((priv->model), "model_rows_deleted",
|
|
G_CALLBACK (row_count_changed_cb), ee);
|
|
}
|
|
|
|
/* Object initialization function for the event editor */
|
|
static void
|
|
event_editor_init (EventEditor *ee)
|
|
{
|
|
EventEditorPrivate *priv;
|
|
|
|
priv = g_new0 (EventEditorPrivate, 1);
|
|
ee->priv = priv;
|
|
|
|
priv->model = E_MEETING_MODEL (e_meeting_model_new ());
|
|
priv->meeting_shown = TRUE;
|
|
priv->updating = FALSE;
|
|
}
|
|
|
|
EventEditor *
|
|
event_editor_construct (EventEditor *ee, CalClient *client)
|
|
{
|
|
EventEditorPrivate *priv;
|
|
|
|
priv = ee->priv;
|
|
|
|
priv->event_page = event_page_new ();
|
|
comp_editor_append_page (COMP_EDITOR (ee),
|
|
COMP_EDITOR_PAGE (priv->event_page),
|
|
_("Appointment"));
|
|
|
|
priv->alarm_page = alarm_page_new ();
|
|
comp_editor_append_page (COMP_EDITOR (ee),
|
|
COMP_EDITOR_PAGE (priv->alarm_page),
|
|
_("Reminder"));
|
|
|
|
priv->recur_page = recurrence_page_new ();
|
|
comp_editor_append_page (COMP_EDITOR (ee),
|
|
COMP_EDITOR_PAGE (priv->recur_page),
|
|
_("Recurrence"));
|
|
|
|
priv->sched_page = schedule_page_new (priv->model);
|
|
comp_editor_append_page (COMP_EDITOR (ee),
|
|
COMP_EDITOR_PAGE (priv->sched_page),
|
|
_("Scheduling"));
|
|
|
|
priv->meet_page = meeting_page_new (priv->model, client);
|
|
comp_editor_append_page (COMP_EDITOR (ee),
|
|
COMP_EDITOR_PAGE (priv->meet_page),
|
|
_("Meeting"));
|
|
|
|
comp_editor_set_cal_client (COMP_EDITOR (ee), client);
|
|
|
|
comp_editor_merge_ui (COMP_EDITOR (ee), "evolution-event-editor.xml", verbs, pixmaps);
|
|
|
|
init_widgets (ee);
|
|
set_menu_sens (ee);
|
|
|
|
return ee;
|
|
}
|
|
|
|
static void
|
|
event_editor_set_cal_client (CompEditor *editor, CalClient *client)
|
|
{
|
|
EventEditor *ee;
|
|
EventEditorPrivate *priv;
|
|
|
|
ee = EVENT_EDITOR (editor);
|
|
priv = ee->priv;
|
|
|
|
e_meeting_model_set_cal_client (priv->model, client);
|
|
|
|
if (parent_class->set_cal_client)
|
|
parent_class->set_cal_client (editor, client);
|
|
}
|
|
|
|
static void
|
|
event_editor_edit_comp (CompEditor *editor, CalComponent *comp)
|
|
{
|
|
EventEditor *ee;
|
|
EventEditorPrivate *priv;
|
|
CalComponentOrganizer organizer;
|
|
GSList *attendees = NULL;
|
|
|
|
ee = EVENT_EDITOR (editor);
|
|
priv = ee->priv;
|
|
|
|
priv->updating = TRUE;
|
|
|
|
if (parent_class->edit_comp)
|
|
parent_class->edit_comp (editor, comp);
|
|
|
|
/* Get meeting related stuff */
|
|
cal_component_get_organizer (comp, &organizer);
|
|
cal_component_get_attendee_list (comp, &attendees);
|
|
|
|
/* Clear things up */
|
|
e_meeting_model_restricted_clear (priv->model);
|
|
e_meeting_model_remove_all_attendees (priv->model);
|
|
|
|
/* Set up the attendees */
|
|
if (attendees == NULL) {
|
|
comp_editor_remove_page (editor, COMP_EDITOR_PAGE (priv->meet_page));
|
|
comp_editor_remove_page (editor, COMP_EDITOR_PAGE (priv->sched_page));
|
|
priv->meeting_shown = FALSE;
|
|
} else {
|
|
GSList *l;
|
|
|
|
if (!priv->meeting_shown) {
|
|
comp_editor_append_page (COMP_EDITOR (ee),
|
|
COMP_EDITOR_PAGE (priv->sched_page),
|
|
_("Scheduling"));
|
|
comp_editor_append_page (COMP_EDITOR (ee),
|
|
COMP_EDITOR_PAGE (priv->meet_page),
|
|
_("Meeting"));
|
|
}
|
|
|
|
for (l = attendees; l != NULL; l = l->next) {
|
|
CalComponentAttendee *ca = l->data;
|
|
EMeetingAttendee *ia;
|
|
|
|
ia = E_MEETING_ATTENDEE (e_meeting_attendee_new_from_cal_component_attendee (ca));
|
|
e_meeting_model_add_attendee (priv->model, ia);
|
|
|
|
g_object_unref((ia));
|
|
}
|
|
|
|
if (organizer.value != NULL) {
|
|
GList *addresses, *l;
|
|
const char *strip;
|
|
int row;
|
|
|
|
strip = itip_strip_mailto (organizer.value);
|
|
|
|
addresses = itip_addresses_get ();
|
|
for (l = addresses; l != NULL; l = l->next) {
|
|
ItipAddress *a = l->data;
|
|
|
|
if (e_meeting_model_find_attendee (priv->model, a->address, &row))
|
|
e_meeting_model_restricted_add (priv->model, row);
|
|
}
|
|
itip_addresses_free (addresses);
|
|
}
|
|
|
|
if (comp_editor_get_user_org (editor))
|
|
e_meeting_model_restricted_clear (priv->model);
|
|
|
|
priv->meeting_shown = TRUE;
|
|
}
|
|
cal_component_free_attendee_list (attendees);
|
|
|
|
set_menu_sens (ee);
|
|
comp_editor_set_needs_send (COMP_EDITOR (ee), priv->meeting_shown && itip_organizer_is_user (comp));
|
|
|
|
priv->updating = FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
event_editor_send_comp (CompEditor *editor, CalComponentItipMethod method)
|
|
{
|
|
EventEditor *ee = EVENT_EDITOR (editor);
|
|
EventEditorPrivate *priv;
|
|
CalComponent *comp = NULL;
|
|
|
|
priv = ee->priv;
|
|
|
|
/* Don't cancel more than once or when just publishing */
|
|
if (method == CAL_COMPONENT_METHOD_PUBLISH ||
|
|
method == CAL_COMPONENT_METHOD_CANCEL)
|
|
goto parent;
|
|
|
|
comp = meeting_page_get_cancel_comp (priv->meet_page);
|
|
if (comp != NULL) {
|
|
CalClient *client;
|
|
gboolean result;
|
|
|
|
client = e_meeting_model_get_cal_client (priv->model);
|
|
result = itip_send_comp (CAL_COMPONENT_METHOD_CANCEL, comp, client, NULL);
|
|
g_object_unref((comp));
|
|
|
|
if (!result)
|
|
return FALSE;
|
|
}
|
|
|
|
parent:
|
|
if (parent_class->send_comp)
|
|
return parent_class->send_comp (editor, method);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/* Destroy handler for the event editor */
|
|
static void
|
|
event_editor_finalize (GObject *object)
|
|
{
|
|
EventEditor *ee;
|
|
EventEditorPrivate *priv;
|
|
|
|
g_return_if_fail (object != NULL);
|
|
g_return_if_fail (IS_EVENT_EDITOR (object));
|
|
|
|
ee = EVENT_EDITOR (object);
|
|
priv = ee->priv;
|
|
|
|
g_object_unref((priv->event_page));
|
|
g_object_unref((priv->alarm_page));
|
|
g_object_unref((priv->recur_page));
|
|
g_object_unref((priv->meet_page));
|
|
g_object_unref((priv->sched_page));
|
|
|
|
g_object_unref((priv->model));
|
|
|
|
if (G_OBJECT_CLASS (parent_class)->finalize)
|
|
(* G_OBJECT_CLASS (parent_class)->finalize) (object);
|
|
}
|
|
|
|
/**
|
|
* event_editor_new:
|
|
* @client: a CalClient
|
|
*
|
|
* Creates a new event editor dialog.
|
|
*
|
|
* Return value: A newly-created event editor dialog, or NULL if the event
|
|
* editor could not be created.
|
|
**/
|
|
EventEditor *
|
|
event_editor_new (CalClient *client)
|
|
{
|
|
EventEditor *ee;
|
|
|
|
ee = EVENT_EDITOR (g_object_new (TYPE_EVENT_EDITOR, NULL));
|
|
return event_editor_construct (ee, client);
|
|
}
|
|
|
|
static void
|
|
show_meeting (EventEditor *ee)
|
|
{
|
|
EventEditorPrivate *priv;
|
|
|
|
priv = ee->priv;
|
|
|
|
if (!priv->meeting_shown) {
|
|
comp_editor_append_page (COMP_EDITOR (ee),
|
|
COMP_EDITOR_PAGE (priv->sched_page),
|
|
_("Scheduling"));
|
|
comp_editor_append_page (COMP_EDITOR (ee),
|
|
COMP_EDITOR_PAGE (priv->meet_page),
|
|
_("Meeting"));
|
|
priv->meeting_shown = TRUE;
|
|
|
|
set_menu_sens (ee);
|
|
comp_editor_set_changed (COMP_EDITOR (ee), priv->meeting_shown);
|
|
comp_editor_set_needs_send (COMP_EDITOR (ee), priv->meeting_shown);
|
|
}
|
|
|
|
comp_editor_show_page (COMP_EDITOR (ee),
|
|
COMP_EDITOR_PAGE (priv->meet_page));
|
|
}
|
|
|
|
void
|
|
event_editor_show_meeting (EventEditor *ee)
|
|
{
|
|
g_return_if_fail (ee != NULL);
|
|
g_return_if_fail (IS_EVENT_EDITOR (ee));
|
|
|
|
|
|
show_meeting (ee);
|
|
}
|
|
|
|
static void
|
|
schedule_meeting_cmd (GtkWidget *widget, gpointer data)
|
|
{
|
|
EventEditor *ee = EVENT_EDITOR (data);
|
|
|
|
show_meeting (ee);
|
|
}
|
|
|
|
static void
|
|
refresh_meeting_cmd (GtkWidget *widget, gpointer data)
|
|
{
|
|
EventEditor *ee = EVENT_EDITOR (data);
|
|
|
|
comp_editor_send_comp (COMP_EDITOR (ee), CAL_COMPONENT_METHOD_REFRESH);
|
|
}
|
|
|
|
static void
|
|
cancel_meeting_cmd (GtkWidget *widget, gpointer data)
|
|
{
|
|
EventEditor *ee = EVENT_EDITOR (data);
|
|
CalComponent *comp;
|
|
|
|
comp = comp_editor_get_current_comp (COMP_EDITOR (ee));
|
|
if (cancel_component_dialog (comp, FALSE)) {
|
|
comp_editor_send_comp (COMP_EDITOR (ee), CAL_COMPONENT_METHOD_CANCEL);
|
|
comp_editor_delete_comp (COMP_EDITOR (ee));
|
|
}
|
|
}
|
|
|
|
static void
|
|
forward_cmd (GtkWidget *widget, gpointer data)
|
|
{
|
|
EventEditor *ee = EVENT_EDITOR (data);
|
|
|
|
if (comp_editor_save_comp (COMP_EDITOR (ee), TRUE))
|
|
comp_editor_send_comp (COMP_EDITOR (ee), CAL_COMPONENT_METHOD_PUBLISH);
|
|
}
|
|
|
|
static void
|
|
model_row_changed_cb (ETableModel *etm, int row, gpointer data)
|
|
{
|
|
EventEditor *ee = EVENT_EDITOR (data);
|
|
EventEditorPrivate *priv;
|
|
|
|
priv = ee->priv;
|
|
|
|
if (!priv->updating) {
|
|
comp_editor_set_changed (COMP_EDITOR (ee), TRUE);
|
|
comp_editor_set_needs_send (COMP_EDITOR (ee), TRUE);
|
|
}
|
|
}
|
|
|
|
static void
|
|
row_count_changed_cb (ETableModel *etm, int row, int count, gpointer data)
|
|
{
|
|
EventEditor *ee = EVENT_EDITOR (data);
|
|
EventEditorPrivate *priv;
|
|
|
|
priv = ee->priv;
|
|
|
|
if (!priv->updating) {
|
|
comp_editor_set_changed (COMP_EDITOR (ee), TRUE);
|
|
comp_editor_set_needs_send (COMP_EDITOR (ee), TRUE);
|
|
}
|
|
}
|