From f0d3f3afdfa314e1e8cd7d8da790878008a46aad Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Wed, 24 Jun 2009 12:59:33 -0400 Subject: Radically reorganize source code. - Collect all shell modules into a new top-level 'modules' directory: $(top_srcdir)/modules/addressbook $(top_srcdir)/modules/calendar $(top_srcdir)/modules/mail Nothing is allowed to link to these, not plugins nor other modules. THIS SOLVES BUG #571275 AND OPENS THE DOOR TO PORTING TO MAC OS X. - Mimic the libevolution-mail-shared library from master (except drop the "shared" suffix) and have libevolution-mail-importers and all mail-related plugins link to it. - Discard the a11y subdirectories and have the files live alongside their counterpart widgets. --- modules/calendar/Makefile.am | 81 ++ modules/calendar/e-cal-shell-backend.c | 666 ++++++++++++++ modules/calendar/e-cal-shell-backend.h | 70 ++ modules/calendar/e-cal-shell-content.c | 827 ++++++++++++++++++ modules/calendar/e-cal-shell-content.h | 108 +++ modules/calendar/e-cal-shell-migrate.c | 796 +++++++++++++++++ modules/calendar/e-cal-shell-migrate.h | 38 + modules/calendar/e-cal-shell-settings.c | 59 ++ modules/calendar/e-cal-shell-settings.h | 33 + modules/calendar/e-cal-shell-sidebar.c | 759 ++++++++++++++++ modules/calendar/e-cal-shell-sidebar.h | 101 +++ modules/calendar/e-cal-shell-view-actions.c | 1202 ++++++++++++++++++++++++++ modules/calendar/e-cal-shell-view-actions.h | 153 ++++ modules/calendar/e-cal-shell-view-memopad.c | 526 +++++++++++ modules/calendar/e-cal-shell-view-private.c | 650 ++++++++++++++ modules/calendar/e-cal-shell-view-private.h | 170 ++++ modules/calendar/e-cal-shell-view-taskpad.c | 654 ++++++++++++++ modules/calendar/e-cal-shell-view.c | 226 +++++ modules/calendar/e-cal-shell-view.h | 69 ++ modules/calendar/e-memo-shell-backend.c | 613 +++++++++++++ modules/calendar/e-memo-shell-backend.h | 70 ++ modules/calendar/e-memo-shell-content.c | 676 +++++++++++++++ modules/calendar/e-memo-shell-content.h | 96 ++ modules/calendar/e-memo-shell-migrate.c | 257 ++++++ modules/calendar/e-memo-shell-migrate.h | 38 + modules/calendar/e-memo-shell-sidebar.c | 718 +++++++++++++++ modules/calendar/e-memo-shell-sidebar.h | 95 ++ modules/calendar/e-memo-shell-view-actions.c | 949 ++++++++++++++++++++ modules/calendar/e-memo-shell-view-actions.h | 87 ++ modules/calendar/e-memo-shell-view-private.c | 524 +++++++++++ modules/calendar/e-memo-shell-view-private.h | 126 +++ modules/calendar/e-memo-shell-view.c | 222 +++++ modules/calendar/e-memo-shell-view.h | 67 ++ modules/calendar/e-task-shell-backend.c | 621 +++++++++++++ modules/calendar/e-task-shell-backend.h | 70 ++ modules/calendar/e-task-shell-content.c | 700 +++++++++++++++ modules/calendar/e-task-shell-content.h | 100 +++ modules/calendar/e-task-shell-migrate.c | 664 ++++++++++++++ modules/calendar/e-task-shell-migrate.h | 38 + modules/calendar/e-task-shell-sidebar.c | 696 +++++++++++++++ modules/calendar/e-task-shell-sidebar.h | 97 +++ modules/calendar/e-task-shell-view-actions.c | 1154 +++++++++++++++++++++++++ modules/calendar/e-task-shell-view-actions.h | 105 +++ modules/calendar/e-task-shell-view-private.c | 744 ++++++++++++++++ modules/calendar/e-task-shell-view-private.h | 141 +++ modules/calendar/e-task-shell-view.c | 255 ++++++ modules/calendar/e-task-shell-view.h | 67 ++ modules/calendar/evolution-module-calendar.c | 65 ++ 48 files changed, 17243 insertions(+) create mode 100644 modules/calendar/Makefile.am create mode 100644 modules/calendar/e-cal-shell-backend.c create mode 100644 modules/calendar/e-cal-shell-backend.h create mode 100644 modules/calendar/e-cal-shell-content.c create mode 100644 modules/calendar/e-cal-shell-content.h create mode 100644 modules/calendar/e-cal-shell-migrate.c create mode 100644 modules/calendar/e-cal-shell-migrate.h create mode 100644 modules/calendar/e-cal-shell-settings.c create mode 100644 modules/calendar/e-cal-shell-settings.h create mode 100644 modules/calendar/e-cal-shell-sidebar.c create mode 100644 modules/calendar/e-cal-shell-sidebar.h create mode 100644 modules/calendar/e-cal-shell-view-actions.c create mode 100644 modules/calendar/e-cal-shell-view-actions.h create mode 100644 modules/calendar/e-cal-shell-view-memopad.c create mode 100644 modules/calendar/e-cal-shell-view-private.c create mode 100644 modules/calendar/e-cal-shell-view-private.h create mode 100644 modules/calendar/e-cal-shell-view-taskpad.c create mode 100644 modules/calendar/e-cal-shell-view.c create mode 100644 modules/calendar/e-cal-shell-view.h create mode 100644 modules/calendar/e-memo-shell-backend.c create mode 100644 modules/calendar/e-memo-shell-backend.h create mode 100644 modules/calendar/e-memo-shell-content.c create mode 100644 modules/calendar/e-memo-shell-content.h create mode 100644 modules/calendar/e-memo-shell-migrate.c create mode 100644 modules/calendar/e-memo-shell-migrate.h create mode 100644 modules/calendar/e-memo-shell-sidebar.c create mode 100644 modules/calendar/e-memo-shell-sidebar.h create mode 100644 modules/calendar/e-memo-shell-view-actions.c create mode 100644 modules/calendar/e-memo-shell-view-actions.h create mode 100644 modules/calendar/e-memo-shell-view-private.c create mode 100644 modules/calendar/e-memo-shell-view-private.h create mode 100644 modules/calendar/e-memo-shell-view.c create mode 100644 modules/calendar/e-memo-shell-view.h create mode 100644 modules/calendar/e-task-shell-backend.c create mode 100644 modules/calendar/e-task-shell-backend.h create mode 100644 modules/calendar/e-task-shell-content.c create mode 100644 modules/calendar/e-task-shell-content.h create mode 100644 modules/calendar/e-task-shell-migrate.c create mode 100644 modules/calendar/e-task-shell-migrate.h create mode 100644 modules/calendar/e-task-shell-sidebar.c create mode 100644 modules/calendar/e-task-shell-sidebar.h create mode 100644 modules/calendar/e-task-shell-view-actions.c create mode 100644 modules/calendar/e-task-shell-view-actions.h create mode 100644 modules/calendar/e-task-shell-view-private.c create mode 100644 modules/calendar/e-task-shell-view-private.h create mode 100644 modules/calendar/e-task-shell-view.c create mode 100644 modules/calendar/e-task-shell-view.h create mode 100644 modules/calendar/evolution-module-calendar.c (limited to 'modules/calendar') diff --git a/modules/calendar/Makefile.am b/modules/calendar/Makefile.am new file mode 100644 index 0000000000..9c2d41dc38 --- /dev/null +++ b/modules/calendar/Makefile.am @@ -0,0 +1,81 @@ +INCLUDES = \ + -DG_LOG_DOMAIN=\"calendar-modules\" \ + -I$(top_srcdir) \ + -I$(top_srcdir)/widgets \ + -DEVOLUTION_ETSPECDIR=\""$(etspecdir)"\" \ + $(EVOLUTION_CALENDAR_CFLAGS) + +module_LTLIBRARIES = \ + libevolution-module-calendar.la + +libevolution_module_calendar_la_SOURCES = \ + evolution-module-calendar.c \ + e-cal-shell-backend.c \ + e-cal-shell-backend.h \ + e-cal-shell-content.c \ + e-cal-shell-content.h \ + e-cal-shell-migrate.c \ + e-cal-shell-migrate.h \ + e-cal-shell-settings.c \ + e-cal-shell-settings.h \ + e-cal-shell-sidebar.c \ + e-cal-shell-sidebar.h \ + e-cal-shell-view.c \ + e-cal-shell-view.h \ + e-cal-shell-view-actions.c \ + e-cal-shell-view-actions.h \ + e-cal-shell-view-memopad.c \ + e-cal-shell-view-private.c \ + e-cal-shell-view-private.h \ + e-cal-shell-view-taskpad.c \ + e-memo-shell-backend.c \ + e-memo-shell-backend.h \ + e-memo-shell-content.c \ + e-memo-shell-content.h \ + e-memo-shell-migrate.c \ + e-memo-shell-migrate.h \ + e-memo-shell-sidebar.c \ + e-memo-shell-sidebar.h \ + e-memo-shell-view.c \ + e-memo-shell-view.h \ + e-memo-shell-view-actions.c \ + e-memo-shell-view-actions.h \ + e-memo-shell-view-private.c \ + e-memo-shell-view-private.h \ + e-task-shell-backend.c \ + e-task-shell-backend.h \ + e-task-shell-content.c \ + e-task-shell-content.h \ + e-task-shell-migrate.c \ + e-task-shell-migrate.h \ + e-task-shell-sidebar.c \ + e-task-shell-sidebar.h \ + e-task-shell-view.c \ + e-task-shell-view.h \ + e-task-shell-view-actions.c \ + e-task-shell-view-actions.h \ + e-task-shell-view-private.c \ + e-task-shell-view-private.h + +# Removed from all three +# $(top_builddir)/a11y/calendar/libevolution-calendar-a11y.la + +libevolution_module_calendar_la_LIBADD = \ + $(top_builddir)/shell/libeshell.la \ + $(top_builddir)/calendar/gui/libcal-gui.la \ + $(top_builddir)/calendar/importers/libevolution-calendar-importers.la \ + $(top_builddir)/mail/libevolution-mail.la \ + $(top_builddir)/addressbook/gui/contact-editor/libecontacteditor.la \ + $(top_builddir)/addressbook/gui/contact-list-editor/libecontactlisteditor.la \ + $(top_builddir)/e-util/libeutil.la \ + $(top_builddir)/filter/libfilter.la \ + $(top_builddir)/widgets/menus/libmenus.la \ + $(top_builddir)/widgets/misc/libemiscwidgets.la \ + $(top_builddir)/widgets/table/libetable.la \ + $(CAMEL_LIBS) \ + $(EVOLUTION_CALENDAR_LIBS) + +libevolution_module_calendar_la_LDFLAGS = \ + -module -avoid-version $(NO_UNDEFINED) + +-include $(top_srcdir)/git.mk diff --git a/modules/calendar/e-cal-shell-backend.c b/modules/calendar/e-cal-shell-backend.c new file mode 100644 index 0000000000..675a3d4fa6 --- /dev/null +++ b/modules/calendar/e-cal-shell-backend.c @@ -0,0 +1,666 @@ +/* + * e-cal-shell-backend.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-backend.h" + +#include +#include +#include +#include +#include +#include + +#include "e-util/e-import.h" +#include "shell/e-shell.h" +#include "shell/e-shell-backend.h" +#include "shell/e-shell-window.h" +#include "widgets/misc/e-preferences-window.h" + +#include "calendar/common/authentication.h" +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/comp-util.h" +#include "calendar/gui/e-attachment-handler-calendar.h" +#include "calendar/gui/e-cal-config.h" +#include "calendar/gui/e-cal-event.h" +#include "calendar/gui/dialogs/cal-prefs-dialog.h" +#include "calendar/gui/dialogs/calendar-setup.h" +#include "calendar/gui/dialogs/event-editor.h" +#include "calendar/importers/evolution-calendar-importer.h" + +#include "e-cal-shell-migrate.h" +#include "e-cal-shell-settings.h" +#include "e-cal-shell-view.h" + +#define E_CAL_SHELL_BACKEND_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_CAL_SHELL_BACKEND, ECalShellBackendPrivate)) + +#define CONTACTS_BASE_URI "contacts://" +#define WEATHER_BASE_URI "weather://" +#define WEB_BASE_URI "webcal://" +#define PERSONAL_RELATIVE_URI "system" + +struct _ECalShellBackendPrivate { + ESourceList *source_list; +}; + +enum { + PROP_0, + PROP_SOURCE_LIST +}; + +static gpointer parent_class; +static GType cal_shell_backend_type; + +static void +cal_shell_backend_ensure_sources (EShellBackend *shell_backend) +{ + /* XXX This is basically the same algorithm across all backends. + * Maybe we could somehow integrate this into EShellBackend? */ + + ECalShellBackendPrivate *priv; + ESourceGroup *on_this_computer; + ESourceGroup *on_the_web; + ESourceGroup *contacts; + ESourceGroup *weather; + ESource *birthdays; + ESource *personal; + EShell *shell; + EShellSettings *shell_settings; + GSList *groups, *iter; + const gchar *data_dir; + const gchar *name; + gchar *base_uri; + gchar *filename; + gchar *property; + + on_this_computer = NULL; + on_the_web = NULL; + contacts = NULL; + weather = NULL; + birthdays = NULL; + personal = NULL; + + priv = E_CAL_SHELL_BACKEND_GET_PRIVATE (shell_backend); + + shell = e_shell_backend_get_shell (shell_backend); + shell_settings = e_shell_get_shell_settings (shell); + + if (!e_cal_get_sources (&priv->source_list, E_CAL_SOURCE_TYPE_EVENT, NULL)) { + g_warning ("Could not get calendar sources from GConf!"); + return; + } + + data_dir = e_shell_backend_get_data_dir (shell_backend); + filename = g_build_filename (data_dir, "local", NULL); + base_uri = g_filename_to_uri (filename, NULL, NULL); + g_free (filename); + + groups = e_source_list_peek_groups (priv->source_list); + for (iter = groups; iter != NULL; iter = iter->next) { + ESourceGroup *source_group = iter->data; + const gchar *group_base_uri; + + group_base_uri = e_source_group_peek_base_uri (source_group); + + /* Compare only "file://" part. if the user's home + * changes, we do not want to create another group. */ + if (on_this_computer == NULL && + strncmp (base_uri, group_base_uri, 7) == 0) + on_this_computer = source_group; + + else if (on_the_web == NULL && + strcmp (WEB_BASE_URI, group_base_uri) == 0) + on_the_web = source_group; + + else if (contacts == NULL && + strcmp (CONTACTS_BASE_URI, group_base_uri) == 0) + contacts = source_group; + + else if (weather == NULL && + strcmp (WEATHER_BASE_URI, group_base_uri) == 0) + weather = source_group; + } + + name = _("On This Computer"); + + if (on_this_computer != NULL) { + GSList *sources; + const gchar *group_base_uri; + + /* Force the group name to the current locale. */ + e_source_group_set_name (on_this_computer, name); + + sources = e_source_group_peek_sources (on_this_computer); + group_base_uri = e_source_group_peek_base_uri (on_this_computer); + + /* Make sure this group includes a "Personal" source. */ + for (iter = sources; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + const gchar *relative_uri; + + relative_uri = e_source_peek_relative_uri (source); + if (relative_uri == NULL) + continue; + + if (strcmp (PERSONAL_RELATIVE_URI, relative_uri) != 0) + continue; + + personal = source; + break; + } + + /* Make sure we have the correct base URI. This can + * change when the user's home directory changes. */ + if (strcmp (base_uri, group_base_uri) != 0) { + e_source_group_set_base_uri ( + on_this_computer, base_uri); + + /* XXX We shouldn't need this sync call here as + * set_base_uri() results in synching to GConf, + * but that happens in an idle loop and too late + * to prevent the user from seeing a "Cannot + * Open ... because of invalid URI" error. */ + e_source_list_sync (priv->source_list, NULL); + } + + } else { + ESourceGroup *source_group; + + source_group = e_source_group_new (name, base_uri); + e_source_list_add_group (priv->source_list, source_group, -1); + g_object_unref (source_group); + } + + name = _("Personal"); + + if (personal == NULL) { + ESource *source; + GSList *selected; + gchar *primary; + + source = e_source_new (name, PERSONAL_RELATIVE_URI); + e_source_group_add_source (on_this_computer, source, -1); + g_object_unref (source); + + primary = e_shell_settings_get_string ( + shell_settings, "cal-primary-calendar"); + + selected = calendar_config_get_calendars_selected (); + + if (primary == NULL && selected == NULL) { + const gchar *uid; + + uid = e_source_peek_uid (source); + selected = g_slist_prepend (NULL, g_strdup (uid)); + + e_shell_settings_set_string ( + shell_settings, "cal-primary-calendar", uid); + calendar_config_set_calendars_selected (selected); + } + + g_slist_foreach (selected, (GFunc) g_free, NULL); + g_slist_free (selected); + g_free (primary); + } else { + /* Force the source name to the current locale. */ + e_source_set_name (personal, name); + } + + name = _("On The Web"); + + if (on_the_web == NULL) { + ESourceGroup *source_group; + + source_group = e_source_group_new (name, WEB_BASE_URI); + e_source_list_add_group (priv->source_list, source_group, -1); + g_object_unref (source_group); + } else { + /* Force the group name to the current locale. */ + e_source_group_set_name (on_the_web, name); + } + + name = _("Contacts"); + + if (contacts != NULL) { + GSList *sources; + + /* Force the group name to the current locale. */ + e_source_group_set_name (contacts, name); + + sources = e_source_group_peek_sources (contacts); + + if (sources != NULL) { + GSList *trash; + + /* There is only one source under Contacts. */ + birthdays = E_SOURCE (sources->data); + sources = g_slist_next (sources); + + /* Delete any other sources in this group. + * Earlier versions allowed you to create + * additional sources under Contacts. */ + trash = g_slist_copy (sources); + while (trash != NULL) { + ESource *source = trash->data; + e_source_group_remove_source (contacts, source); + trash = g_slist_delete_link (trash, trash); + } + + } + } else { + ESourceGroup *source_group; + + source_group = e_source_group_new (name, CONTACTS_BASE_URI); + e_source_list_add_group (priv->source_list, source_group, -1); + g_object_unref (source_group); + + /* This is now a borrowed reference. */ + contacts = source_group; + } + + /* XXX e_source_group_get_property() returns a newly-allocated + * string when it could just as easily return a const string. + * Unfortunately, fixing that would break the API. */ + property = e_source_group_get_property (contacts, "create_source"); + if (property == NULL) + e_source_group_set_property (contacts, "create_source", "no"); + g_free (property); + + name = _("Birthdays & Anniversaries"); + + if (birthdays == NULL) { + ESource *source; + const gchar *name; + + name = _("Birthdays & Anniversaries"); + source = e_source_new (name, "/"); + e_source_group_add_source (contacts, source, -1); + g_object_unref (source); + + /* This is now a borrowed reference. */ + birthdays = source; + } else { + /* Force the source name to the current locale. */ + e_source_set_name (birthdays, name); + } + + if (e_source_get_property (birthdays, "delete") == NULL) + e_source_set_property (birthdays, "delete", "no"); + + if (e_source_peek_color_spec (birthdays) == NULL) + e_source_set_color_spec (birthdays, "#DDBECE"); + + name = _("Weather"); + + if (weather == NULL) { + ESourceGroup *source_group; + + source_group = e_source_group_new (name, WEATHER_BASE_URI); + e_source_list_add_group (priv->source_list, source_group, -1); + g_object_unref (source_group); + } else { + /* Force the group name to the current locale. */ + e_source_group_set_name (weather, name); + } + + g_free (base_uri); +} + +static void +cal_shell_backend_cal_opened_cb (ECal *cal, + ECalendarStatus status, + GtkAction *action) +{ + EShell *shell; + ECalComponent *comp; + CompEditor *editor; + CompEditorFlags flags = 0; + const gchar *action_name; + gboolean all_day; + + /* FIXME Pass this in. */ + shell = e_shell_get_default (); + + /* XXX Handle errors better. */ + if (status != E_CALENDAR_STATUS_OK) + return; + + action_name = gtk_action_get_name (action); + + flags |= COMP_EDITOR_NEW_ITEM; + flags |= COMP_EDITOR_USER_ORG; + if (strcmp (action_name, "event-meeting-new") == 0) + flags |= COMP_EDITOR_MEETING; + + all_day = (strcmp (action_name, "event-all-day-new") == 0); + + editor = event_editor_new (cal, shell, flags); + comp = cal_comp_event_new_with_current_time (cal, all_day); + comp_editor_edit_comp (editor, comp); + + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (comp); + g_object_unref (cal); +} + +static void +action_event_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + ECal *cal = NULL; + ECalSourceType source_type; + ESourceList *source_list; + EShellSettings *shell_settings; + EShell *shell; + gchar *uid; + + /* This callback is used for both appointments and meetings. */ + + source_type = E_CAL_SOURCE_TYPE_EVENT; + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + if (!e_cal_get_sources (&source_list, source_type, NULL)) { + g_warning ("Could not get calendar sources from GConf!"); + return; + } + + uid = e_shell_settings_get_string ( + shell_settings, "cal-primary-calendar"); + + if (uid != NULL) { + ESource *source; + + source = e_source_list_peek_source_by_uid (source_list, uid); + if (source != NULL) + cal = auth_new_cal_from_source (source, source_type); + g_free (uid); + } + + if (cal == NULL) + cal = auth_new_cal_from_default (source_type); + + g_return_if_fail (cal != NULL); + + g_signal_connect ( + cal, "cal-opened", + G_CALLBACK (cal_shell_backend_cal_opened_cb), action); + + e_cal_open_async (cal, FALSE); +} + +static void +action_calendar_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + calendar_setup_new_calendar (GTK_WINDOW (shell_window)); +} + +static GtkActionEntry item_entries[] = { + + { "event-new", + "appointment-new", + NC_("New", "_Appointment"), + "a", + N_("Create a new appointment"), + G_CALLBACK (action_event_new_cb) }, + + { "event-all-day-new", + "stock_new-24h-appointment", + NC_("New", "All Day A_ppointment"), + NULL, + N_("Create a new all-day appointment"), + G_CALLBACK (action_event_new_cb) }, + + { "event-meeting-new", + "stock_new-meeting", + NC_("New", "M_eeting"), + "e", + N_("Create a new meeting request"), + G_CALLBACK (action_event_new_cb) } +}; + +static GtkActionEntry source_entries[] = { + + { "calendar-new", + "x-office-calendar", + NC_("New", "Cale_ndar"), + NULL, + N_("Create a new calendar"), + G_CALLBACK (action_calendar_new_cb) } +}; + +static void +cal_shell_backend_init_hooks (void) +{ + e_plugin_hook_register_type (e_cal_config_hook_get_type ()); + e_plugin_hook_register_type (e_cal_event_hook_get_type ()); +} + +static void +cal_shell_backend_init_importers (void) +{ + EImportClass *import_class; + EImportImporter *importer; + + import_class = g_type_class_ref (e_import_get_type ()); + + importer = gnome_calendar_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); + + importer = ical_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); + + importer = vcal_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); +} + +static void +cal_shell_backend_init_preferences (EShell *shell) +{ + GtkWidget *preferences_window; + + preferences_window = e_shell_get_preferences_window (shell); + + e_preferences_window_add_page ( + E_PREFERENCES_WINDOW (preferences_window), + "calendar-and-tasks", + "preferences-calendar-and-tasks", + _("Calendar and Tasks"), + calendar_prefs_dialog_new (shell), + 600); +} + +static gboolean +cal_shell_backend_handle_uri_cb (EShellBackend *shell_backend, + const gchar *uri) +{ + /* FIXME */ + return FALSE; +} + +static void +cal_shell_backend_window_created_cb (EShellBackend *shell_backend, + GtkWindow *window) +{ + const gchar *backend_name; + + if (!E_IS_SHELL_WINDOW (window)) + return; + + backend_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name; + + e_shell_window_register_new_item_actions ( + E_SHELL_WINDOW (window), backend_name, + item_entries, G_N_ELEMENTS (item_entries)); + + e_shell_window_register_new_source_actions ( + E_SHELL_WINDOW (window), backend_name, + source_entries, G_N_ELEMENTS (source_entries)); +} + +static void +cal_shell_backend_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SOURCE_LIST: + g_value_set_object ( + value, + e_cal_shell_backend_get_source_list ( + E_CAL_SHELL_BACKEND (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +cal_shell_backend_dispose (GObject *object) +{ + ECalShellBackendPrivate *priv; + + priv = E_CAL_SHELL_BACKEND_GET_PRIVATE (object); + + if (priv->source_list != NULL) { + g_object_unref (priv->source_list); + priv->source_list = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +cal_shell_backend_constructed (GObject *object) +{ + EShell *shell; + EShellBackend *shell_backend; + + shell_backend = E_SHELL_BACKEND (object); + shell = e_shell_backend_get_shell (shell_backend); + + cal_shell_backend_ensure_sources (shell_backend); + + g_signal_connect_swapped ( + shell, "handle-uri", + G_CALLBACK (cal_shell_backend_handle_uri_cb), + shell_backend); + + g_signal_connect_swapped ( + shell, "window-created", + G_CALLBACK (cal_shell_backend_window_created_cb), + shell_backend); + + cal_shell_backend_init_hooks (); + cal_shell_backend_init_importers (); + + /* Initialize settings before initializing preferences, + * since the preferences bind to the shell settings. */ + e_cal_shell_backend_init_settings (shell); + cal_shell_backend_init_preferences (shell); + + e_attachment_handler_calendar_get_type (); +} + +static void +cal_shell_backend_class_init (ECalShellBackendClass *class) +{ + GObjectClass *object_class; + EShellBackendClass *shell_backend_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ECalShellBackendPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->get_property = cal_shell_backend_get_property; + object_class->dispose = cal_shell_backend_dispose; + object_class->constructed = cal_shell_backend_constructed; + + shell_backend_class = E_SHELL_BACKEND_CLASS (class); + shell_backend_class->shell_view_type = E_TYPE_CAL_SHELL_VIEW; + shell_backend_class->name = "calendar"; + shell_backend_class->aliases = ""; + shell_backend_class->schemes = "calendar"; + shell_backend_class->sort_order = 400; + shell_backend_class->start = NULL; + shell_backend_class->is_busy = NULL; + shell_backend_class->shutdown = NULL; + shell_backend_class->migrate = e_cal_shell_backend_migrate; + + g_object_class_install_property ( + object_class, + PROP_SOURCE_LIST, + g_param_spec_object ( + "source-list", + _("Source List"), + _("The registry of calendars"), + E_TYPE_SOURCE_LIST, + G_PARAM_READABLE)); +} + +static void +cal_shell_backend_init (ECalShellBackend *cal_shell_backend) +{ + cal_shell_backend->priv = + E_CAL_SHELL_BACKEND_GET_PRIVATE (cal_shell_backend); +} + +GType +e_cal_shell_backend_get_type (void) +{ + return cal_shell_backend_type; +} + +void +e_cal_shell_backend_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (ECalShellBackendClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) cal_shell_backend_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ECalShellBackend), + 0, /* n_preallocs */ + (GInstanceInitFunc) cal_shell_backend_init, + NULL /* value_table */ + }; + + cal_shell_backend_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_BACKEND, + "ECalShellBackend", &type_info, 0); +} + +ESourceList * +e_cal_shell_backend_get_source_list (ECalShellBackend *cal_shell_backend) +{ + g_return_val_if_fail ( + E_IS_CAL_SHELL_BACKEND (cal_shell_backend), NULL); + + return cal_shell_backend->priv->source_list; +} diff --git a/modules/calendar/e-cal-shell-backend.h b/modules/calendar/e-cal-shell-backend.h new file mode 100644 index 0000000000..497e200490 --- /dev/null +++ b/modules/calendar/e-cal-shell-backend.h @@ -0,0 +1,70 @@ +/* + * e-cal-shell-backend.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_CAL_SHELL_BACKEND_H +#define E_CAL_SHELL_BACKEND_H + +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_CAL_SHELL_BACKEND \ + (e_cal_shell_backend_get_type ()) +#define E_CAL_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_CAL_SHELL_BACKEND, ECalShellBackend)) +#define E_CAL_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_CAL_SHELL_BACKEND, ECalShellBackendClass)) +#define E_IS_CAL_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_CAL_SHELL_BACKEND)) +#define E_IS_CAL_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_CAL_SHELL_BACKEND)) +#define E_CAL_SHELL_BACKEND_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_CAL_SHELL_BACKEND, ECalShellBackendClass)) + +G_BEGIN_DECLS + +typedef struct _ECalShellBackend ECalShellBackend; +typedef struct _ECalShellBackendClass ECalShellBackendClass; +typedef struct _ECalShellBackendPrivate ECalShellBackendPrivate; + +struct _ECalShellBackend { + EShellBackend parent; + ECalShellBackendPrivate *priv; +}; + +struct _ECalShellBackendClass { + EShellBackendClass parent_class; +}; + +GType e_cal_shell_backend_get_type (void); +void e_cal_shell_backend_register_type + (GTypeModule *type_module); +ESourceList * e_cal_shell_backend_get_source_list + (ECalShellBackend *cal_shell_backend); + +G_END_DECLS + +#endif /* E_CAL_SHELL_BACKEND_H */ diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c new file mode 100644 index 0000000000..6afb40dce7 --- /dev/null +++ b/modules/calendar/e-cal-shell-content.c @@ -0,0 +1,827 @@ +/* + * e-cal-shell-content.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-content.h" + +#include +#include + +#include "e-util/gconf-bridge.h" + +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/e-cal-list-view-config.h" +#include "calendar/gui/e-cal-model-calendar.h" +#include "calendar/gui/e-calendar-table.h" +#include "calendar/gui/e-calendar-table-config.h" +#include "calendar/gui/e-day-view-config.h" +#include "calendar/gui/e-memo-table-config.h" +#include "calendar/gui/e-week-view-config.h" + +#include "widgets/menus/gal-view-etable.h" + +#define E_CAL_SHELL_CONTENT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_CAL_SHELL_CONTENT, ECalShellContentPrivate)) + +struct _ECalShellContentPrivate { + GtkWidget *hpaned; + GtkWidget *notebook; + GtkWidget *vpaned; + + GtkWidget *day_view; + GtkWidget *work_week_view; + GtkWidget *week_view; + GtkWidget *month_view; + GtkWidget *list_view; + GtkWidget *task_table; + GtkWidget *memo_table; + + EDayViewConfig *day_view_config; + EDayViewConfig *work_week_view_config; + EWeekViewConfig *week_view_config; + EWeekViewConfig *month_view_config; + ECalListViewConfig *list_view_config; + ECalendarTableConfig *task_table_config; + EMemoTableConfig *memo_table_config; + + GalViewInstance *view_instance; + + guint paned_binding_id; +}; + +enum { + PROP_0 +}; + +/* Used to indicate who has the focus within the calendar view. */ +typedef enum { + FOCUS_CALENDAR, + FOCUS_MEMO_TABLE, + FOCUS_TASK_TABLE, + FOCUS_OTHER +} FocusLocation; + +static gpointer parent_class; +static GType cal_shell_content_type; + +static void +cal_shell_content_display_view_cb (ECalShellContent *cal_shell_content, + GalView *gal_view) +{ + /* FIXME */ +} + +static void +cal_shell_content_notify_view_id_cb (ECalShellContent *cal_shell_content) +{ + EShellContent *shell_content; + EShellView *shell_view; + GConfBridge *bridge; + GtkWidget *paned; + guint binding_id; + const gchar *key; + const gchar *view_id; + + bridge = gconf_bridge_get (); + paned = cal_shell_content->priv->hpaned; + binding_id = cal_shell_content->priv->paned_binding_id; + + shell_content = E_SHELL_CONTENT (cal_shell_content); + shell_view = e_shell_content_get_shell_view (shell_content); + view_id = e_shell_view_get_view_id (shell_view); + + if (binding_id > 0) + gconf_bridge_unbind (bridge, binding_id); + + if (view_id != NULL && strcmp (view_id, "Month_View") == 0) + key = "/apps/evolution/calendar/display/month_hpane_position"; + else + key = "/apps/evolution/calendar/display/hpane_position"; + + binding_id = gconf_bridge_bind_property_delayed ( + bridge, key, G_OBJECT (paned), "position"); + + cal_shell_content->priv->paned_binding_id = binding_id; +} + +static FocusLocation +cal_shell_content_get_focus_location (ECalShellContent *cal_shell_content) +{ + return FOCUS_OTHER; +#if 0 /* TEMPORARILY DISABLED */ + GtkWidget *widget; + GnomeCalendar *calendar; + ECalendarTable *task_table; + EMemoTable *memo_table; + ETable *table; + ECalendarView *calendar_view; + + calendar = GNOME_CALENDAR (cal_shell_content->priv->calendar); + widget = gnome_calendar_get_current_view_widget (calendar); + + memo_table = E_MEMO_TABLE (cal_shell_content->priv->memo_table); + task_table = E_CALENDAR_TABLE (cal_shell_content->priv->task_table); + + table = e_memo_table_get_table (memo_table); + if (GTK_WIDGET_HAS_FOCUS (table->table_canvas)) + return FOCUS_MEMO_TABLE; + + table = e_calendar_table_get_table (task_table); + if (GTK_WIDGET_HAS_FOCUS (table->table_canvas)) + return FOCUS_TASK_TABLE; + + if (E_IS_DAY_VIEW (widget)) { + EDayView *view = E_DAY_VIEW (widget); + + if (GTK_WIDGET_HAS_FOCUS (view->top_canvas)) + return FOCUS_CALENDAR; + + if (GNOME_CANVAS (view->top_canvas)->focused_item != NULL) + return FOCUS_CALENDAR; + + if (GTK_WIDGET_HAS_FOCUS (view->main_canvas)) + return FOCUS_CALENDAR; + + if (GNOME_CANVAS (view->main_canvas)->focused_item != NULL) + return FOCUS_CALENDAR; + + } else if (E_IS_WEEK_VIEW (widget)) { + EWeekView *view = E_WEEK_VIEW (widget); + + if (GTK_WIDGET_HAS_FOCUS (view->main_canvas)) + return FOCUS_CALENDAR; + + if (GNOME_CANVAS (view->main_canvas)->focused_item != NULL) + return FOCUS_CALENDAR; + + } else if (E_IS_CAL_LIST_VIEW (widget)) { + ECalListView *view = E_CAL_LIST_VIEW (widget); + + table = e_table_scrolled_get_table (view->table_scrolled); + if (GTK_WIDGET_HAS_FOCUS (table)) + return FOCUS_CALENDAR; + } + + return FOCUS_OTHER; +#endif +} + +static void +cal_shell_content_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +cal_shell_content_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +cal_shell_content_dispose (GObject *object) +{ + ECalShellContentPrivate *priv; + + priv = E_CAL_SHELL_CONTENT_GET_PRIVATE (object); + + if (priv->hpaned != NULL) { + g_object_unref (priv->hpaned); + priv->hpaned = NULL; + } + + if (priv->notebook != NULL) { + g_object_unref (priv->notebook); + priv->notebook = NULL; + } + + if (priv->vpaned != NULL) { + g_object_unref (priv->vpaned); + priv->vpaned = NULL; + } + + if (priv->day_view != NULL) { + g_object_unref (priv->day_view); + priv->day_view = NULL; + } + + if (priv->work_week_view != NULL) { + g_object_unref (priv->work_week_view); + priv->work_week_view = NULL; + } + + if (priv->week_view != NULL) { + g_object_unref (priv->week_view); + priv->week_view = NULL; + } + + if (priv->month_view != NULL) { + g_object_unref (priv->month_view); + priv->month_view = NULL; + } + + if (priv->list_view != NULL) { + g_object_unref (priv->list_view); + priv->list_view = NULL; + } + + if (priv->task_table != NULL) { + g_object_unref (priv->task_table); + priv->task_table = NULL; + } + + if (priv->memo_table != NULL) { + g_object_unref (priv->memo_table); + priv->memo_table = NULL; + } + + if (priv->day_view_config != NULL) { + g_object_unref (priv->day_view_config); + priv->day_view_config = NULL; + } + + if (priv->work_week_view_config != NULL) { + g_object_unref (priv->work_week_view_config); + priv->work_week_view_config = NULL; + } + + if (priv->week_view_config != NULL) { + g_object_unref (priv->week_view_config); + priv->week_view_config = NULL; + } + + if (priv->month_view_config != NULL) { + g_object_unref (priv->month_view_config); + priv->month_view_config = NULL; + } + + if (priv->list_view_config != NULL) { + g_object_unref (priv->list_view_config); + priv->list_view_config = NULL; + } + + if (priv->task_table_config != NULL) { + g_object_unref (priv->task_table_config); + priv->task_table_config = NULL; + } + + if (priv->memo_table_config != NULL) { + g_object_unref (priv->memo_table_config); + priv->memo_table_config = NULL; + } + + if (priv->view_instance != NULL) { + g_object_unref (priv->view_instance); + priv->view_instance = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +cal_shell_content_finalize (GObject *object) +{ + ECalShellContentPrivate *priv; + + priv = E_CAL_SHELL_CONTENT_GET_PRIVATE (object); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +cal_shell_content_constructed (GObject *object) +{ + ECalShellContentPrivate *priv; + ECalModelCalendar *cal_model; + ECalModel *memo_model; + ECalModel *task_model; + EShellContent *shell_content; + EShellBackend *shell_backend; + EShellView *shell_view; + EShellWindow *shell_window; + EShellContent *foreign_content; + EShellView *foreign_view; + GalViewInstance *view_instance; + GConfBridge *bridge; + GtkWidget *container; + GtkWidget *widget; + const gchar *config_dir; + const gchar *key; + gchar *filename; + gchar *markup; + gint page_num; + + priv = E_CAL_SHELL_CONTENT_GET_PRIVATE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + shell_content = E_SHELL_CONTENT (object); + shell_view = e_shell_content_get_shell_view (shell_content); + shell_window = e_shell_view_get_shell_window (shell_view); + + shell_backend = e_shell_view_get_shell_backend (shell_view); + config_dir = e_shell_backend_get_config_dir (shell_backend); + + /* Calendar model for the views. */ + cal_model = e_cal_model_calendar_new (); + e_cal_model_set_flags ( + E_CAL_MODEL (cal_model), + E_CAL_MODEL_FLAGS_EXPAND_RECURRENCES); + + /* We borrow the memopad and taskpad models from the memo + * and task views, loading the views if necessary. */ + + foreign_view = e_shell_window_get_shell_view (shell_window, "memos"); + foreign_content = e_shell_view_get_shell_content (foreign_view); + g_object_get (foreign_content, "model", &memo_model, NULL); + + foreign_view = e_shell_window_get_shell_view (shell_window, "tasks"); + foreign_content = e_shell_view_get_shell_content (foreign_view); + g_object_get (foreign_content, "model", &task_model, NULL); + + /* Build content widgets. */ + + container = GTK_WIDGET (object); + + /* FIXME Need to deal with saving and restoring the position. + * Month view has its own position. */ + widget = gtk_hpaned_new (); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->hpaned = g_object_ref (widget); + gtk_widget_show (widget); + + container = priv->hpaned; + + widget = gtk_notebook_new (); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE); + gtk_notebook_set_show_border (GTK_NOTEBOOK (widget), FALSE); + gtk_paned_pack1 (GTK_PANED (container), widget, FALSE, TRUE); + priv->notebook = g_object_ref (widget); + gtk_widget_show (widget); + + /* FIXME Need to deal with saving and restoring the position. + * Month view has its own position. */ + widget = gtk_vpaned_new (); + gtk_paned_pack2 (GTK_PANED (container), widget, TRUE, TRUE); + priv->vpaned = g_object_ref (widget); + gtk_widget_show (widget); + + container = priv->notebook; + + /* Add views in the order defined by GnomeCalendarViewType, such + * that the notebook page number corresponds to the view type. + * The assertions below ensure that stays true. */ + +#if 0 /* Not so fast... get the memo/task pads working first. */ + /* FIXME Need to establish a calendar and timezone first. */ + widget = e_day_view_new (E_CAL_MODEL (cal_model)); + e_calendar_view_set_calendar ( + E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); + e_calendar_view_set_timezone ( + E_CALENDAR_VIEW (widget), priv->timezone); + page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); + gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); + g_return_if_fail (page_num == GNOME_CAL_DAY_VIEW); + priv->day_view = g_object_ref (widget); + gtk_widget_show (widget); + + /* FIXME Need to establish a calendar and timezone first. */ + widget = e_day_view_new (E_CAL_MODEL (cal_model)); + e_day_view_set_work_week_view (E_DAY_VIEW (widget), TRUE); + e_day_view_set_days_shown (E_DAY_VIEW (widget), 5); + e_calendar_view_set_calendar ( + E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); + e_calendar_view_set_timezone ( + E_CALENDAR_VIEW (widget), priv->timezone); + page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); + gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); + g_return_if_fail (page_num == GNOME_CAL_WORK_WEEK_VIEW); + priv->work_week_view = g_object_ref (widget); + gtk_widget_show (widget); + + /* FIXME Need to establish a calendar and timezone first. */ + widget = e_week_view_new (E_CAL_MODEL (cal_model)); + e_calendar_view_set_calendar ( + E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); + e_calendar_view_set_timezone ( + E_CALENDAR_VIEW (widget), priv->timezone); + page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); + gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); + g_return_if_fail (page_num == GNOME_CAL_WEEK_VIEW); + priv->week_view = g_object_ref (widget); + gtk_widget_show (widget); + + /* FIXME Need to establish a calendar and timezone first. */ + widget = e_week_view_new (E_CAL_MODEL (cal_model)); + e_week_view_set_multi_week_view (E_WEEK_VIEW (widget), TRUE); + e_week_view_set_weeks_shown (E_WEEK_VIEW (widget), 6); + e_calendar_view_set_calendar ( + E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); + e_calendar_view_set_timezone ( + E_CALENDAR_VIEW (widget), priv->timezone); + page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); + gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); + g_return_if_fail (page_num == GNOME_CAL_MONTH_VIEW); + priv->month_view = g_object_ref (widget); + gtk_widget_show (widget); + + /* FIXME Need to establish a calendar and timezone first. */ + widget = e_cal_list_view_new (E_CAL_MODEL (cal_model)); + e_calendar_view_set_calendar ( + E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); + e_calendar_view_set_timezone ( + E_CALENDAR_VIEW (widget), priv->timezone); + page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); + gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); + g_return_if_fail (page_num == GNOME_CAL_LIST_VIEW); + priv->list_view = g_object_ref (widget); + gtk_widget_show (widget); +#endif + + container = priv->vpaned; + + widget = gtk_vbox_new (FALSE, 0); + gtk_paned_pack1 (GTK_PANED (container), widget, FALSE, FALSE); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_hseparator_new (); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, TRUE, 0); + gtk_widget_show (widget); + + widget = gtk_label_new (NULL); + markup = g_strdup_printf ("%s", _("Tasks")); + gtk_label_set_markup (GTK_LABEL (widget), markup); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, TRUE, 0); + gtk_widget_show (widget); + g_free (markup); + + widget = e_calendar_table_new (shell_view, task_model); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + priv->task_table = g_object_ref (widget); + gtk_widget_show (widget); + + filename = g_build_filename (config_dir, "TaskPad", NULL); + e_calendar_table_load_state (E_CALENDAR_TABLE (widget), filename); + g_free (filename); + + container = priv->vpaned; + + widget = gtk_vbox_new (FALSE, 0); + gtk_paned_pack2 (GTK_PANED (container), widget, TRUE, FALSE); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_label_new (NULL); + markup = g_strdup_printf ("%s", _("Memos")); + gtk_label_set_markup (GTK_LABEL (widget), markup); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, TRUE, 0); + gtk_widget_show (widget); + g_free (markup); + + widget = e_memo_table_new (shell_view, memo_model); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + priv->memo_table = g_object_ref (widget); + gtk_widget_show (widget); + + filename = g_build_filename (config_dir, "MemoPad", NULL); + e_memo_table_load_state (E_MEMO_TABLE (widget), filename); + g_free (filename); + + /* Configuration managers for views and tables. */ + priv->day_view_config = e_day_view_config_new ( + E_DAY_VIEW (priv->day_view)); + priv->work_week_view_config = e_day_view_config_new ( + E_DAY_VIEW (priv->work_week_view)); + priv->week_view_config = e_week_view_config_new ( + E_WEEK_VIEW (priv->week_view)); + priv->month_view_config = e_week_view_config_new ( + E_WEEK_VIEW (priv->month_view)); + priv->list_view_config = e_cal_list_view_config_new ( + E_CAL_LIST_VIEW (priv->list_view)); + priv->task_table_config = e_calendar_table_config_new ( + E_CALENDAR_TABLE (priv->task_table)); + priv->memo_table_config = e_memo_table_config_new ( + E_MEMO_TABLE (priv->memo_table)); + + /* Load the view instance. */ + + view_instance = e_shell_view_new_view_instance (shell_view, NULL); + g_signal_connect_swapped ( + view_instance, "display-view", + G_CALLBACK (cal_shell_content_display_view_cb), + object); + gal_view_instance_load (view_instance); + priv->view_instance = view_instance; + + g_signal_connect_swapped ( + shell_view, "notify::view-id", + G_CALLBACK (cal_shell_content_notify_view_id_cb), + object); + + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (priv->vpaned); + key = "/apps/evolution/calendar/display/vpane_position"; + gconf_bridge_bind_property_delayed (bridge, key, object, "position"); + + g_object_unref (memo_model); + g_object_unref (task_model); +} + +static void +cal_shell_content_class_init (ECalShellContentClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ECalShellContentPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = cal_shell_content_set_property; + object_class->get_property = cal_shell_content_get_property; + object_class->dispose = cal_shell_content_dispose; + object_class->finalize = cal_shell_content_finalize; + object_class->constructed = cal_shell_content_constructed; +} + +static void +cal_shell_content_init (ECalShellContent *cal_shell_content) +{ + cal_shell_content->priv = + E_CAL_SHELL_CONTENT_GET_PRIVATE (cal_shell_content); + + /* Postpone widget construction until we have a shell view. */ +} + +GType +e_cal_shell_content_get_type (void) +{ + return cal_shell_content_type; +} + +void +e_cal_shell_content_register_type (GTypeModule *type_module) +{ + static const GTypeInfo type_info = { + sizeof (ECalShellContentClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) cal_shell_content_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ECalShellContent), + 0, /* n_preallocs */ + (GInstanceInitFunc) cal_shell_content_init, + NULL /* value_table */ + }; + + cal_shell_content_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_CONTENT, + "ECalShellContent", &type_info, 0); +} + +GtkWidget * +e_cal_shell_content_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_CAL_SHELL_CONTENT, + "shell-view", shell_view, NULL); +} + +GnomeCalendar * +e_cal_shell_content_get_calendar (ECalShellContent *cal_shell_content) +{ + g_return_val_if_fail ( + E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL); + + /* FIXME */ + /*return GNOME_CALENDAR (cal_shell_content->priv->calendar);*/ + return NULL; +} + +EMemoTable * +e_cal_shell_content_get_memo_table (ECalShellContent *cal_shell_content) +{ + g_return_val_if_fail ( + E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL); + + return E_MEMO_TABLE (cal_shell_content->priv->memo_table); +} + +ECalendarTable * +e_cal_shell_content_get_task_table (ECalShellContent *cal_shell_content) +{ + g_return_val_if_fail ( + E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL); + + return E_CALENDAR_TABLE (cal_shell_content->priv->task_table); +} + +icaltimezone * +e_cal_shell_content_get_timezone (ECalShellContent *cal_shell_content) +{ + g_return_val_if_fail ( + E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL); + + /* FIXME */ + /*return cal_shell_content->priv->timezone;*/ + return NULL; +} + +GalViewInstance * +e_cal_shell_content_get_view_instance (ECalShellContent *cal_shell_content) +{ + g_return_val_if_fail ( + E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL); + + return cal_shell_content->priv->view_instance; +} + +void +e_cal_shell_content_copy_clipboard (ECalShellContent *cal_shell_content) +{ +#if 0 + GnomeCalendar *calendar; + EMemoTable *memo_table; + ECalendarTable *task_table; + + g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); + + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + switch (cal_shell_content_get_focus_location (cal_shell_content)) { + case FOCUS_CALENDAR: + gnome_calendar_copy_clipboard (calendar); + break; + + case FOCUS_MEMO_TABLE: + e_memo_table_copy_clipboard (memo_table); + break; + + case FOCUS_TASK_TABLE: + e_calendar_table_copy_clipboard (task_table); + break; + + default: + g_return_if_reached (); + } +#endif +} + +void +e_cal_shell_content_cut_clipboard (ECalShellContent *cal_shell_content) +{ +#if 0 + GnomeCalendar *calendar; + EMemoTable *memo_table; + ECalendarTable *task_table; + + g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); + + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + switch (cal_shell_content_get_focus_location (cal_shell_content)) { + case FOCUS_CALENDAR: + gnome_calendar_cut_clipboard (calendar); + break; + + case FOCUS_MEMO_TABLE: + e_memo_table_copy_clipboard (memo_table); + break; + + case FOCUS_TASK_TABLE: + e_calendar_table_copy_clipboard (task_table); + break; + + default: + g_return_if_reached (); + } +#endif +} + +void +e_cal_shell_content_paste_clipboard (ECalShellContent *cal_shell_content) +{ +#if 0 + GnomeCalendar *calendar; + EMemoTable *memo_table; + ECalendarTable *task_table; + + g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); + + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + switch (cal_shell_content_get_focus_location (cal_shell_content)) { + case FOCUS_CALENDAR: + gnome_calendar_paste_clipboard (calendar); + break; + + case FOCUS_MEMO_TABLE: + e_memo_table_copy_clipboard (memo_table); + break; + + case FOCUS_TASK_TABLE: + e_calendar_table_copy_clipboard (task_table); + break; + + default: + g_return_if_reached (); + } +#endif +} + +void +e_cal_shell_content_delete_selection (ECalShellContent *cal_shell_content) +{ +#if 0 + GnomeCalendar *calendar; + EMemoTable *memo_table; + ECalendarTable *task_table; + + g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); + + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + switch (cal_shell_content_get_focus_location (cal_shell_content)) { + case FOCUS_CALENDAR: + gnome_calendar_delete_selection (calendar); + break; + + case FOCUS_MEMO_TABLE: + e_memo_table_delete_selected (memo_table); + break; + + case FOCUS_TASK_TABLE: + e_calendar_table_delete_selected (task_table); + break; + + default: + g_return_if_reached (); + } +#endif +} + +void +e_cal_shell_content_delete_selected_occurrence (ECalShellContent *cal_shell_content) +{ +#if 0 + GnomeCalendar *calendar; + FocusLocation focus; + + g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); + + focus = cal_shell_content_get_focus_location (cal_shell_content); + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + + if (focus == FOCUS_CALENDAR) + gnome_calendar_delete_selected_occurrence (calendar); +#endif +} diff --git a/modules/calendar/e-cal-shell-content.h b/modules/calendar/e-cal-shell-content.h new file mode 100644 index 0000000000..44e13f733c --- /dev/null +++ b/modules/calendar/e-cal-shell-content.h @@ -0,0 +1,108 @@ +/* + * e-cal-shell-content.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_CAL_SHELL_CONTENT_H +#define E_CAL_SHELL_CONTENT_H + +#include +#include + +#include +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_CAL_SHELL_CONTENT \ + (e_cal_shell_content_get_type ()) +#define E_CAL_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_CAL_SHELL_CONTENT, ECalShellContent)) +#define E_CAL_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_CAL_SHELL_CONTENT, ECalShellContentClass)) +#define E_IS_CAL_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_CAL_SHELL_CONTENT)) +#define E_IS_CAL_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_CAL_SHELL_CONTENT)) +#define E_CAL_SHELL_CONTENT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_CAL_SHELL_CONTENT, ECalShellContentClass)) + +G_BEGIN_DECLS + +typedef struct _ECalShellContent ECalShellContent; +typedef struct _ECalShellContentClass ECalShellContentClass; +typedef struct _ECalShellContentPrivate ECalShellContentPrivate; + +enum { + E_CAL_SHELL_CONTENT_SELECTION_SINGLE = 1 << 0, + E_CAL_SHELL_CONTENT_SELECTION_MULTIPLE = 1 << 1, + E_CAL_SHELL_CONTENT_SELECTION_IS_ASSIGNABLE = 1 << 2, + E_CAL_SHELL_CONTENT_SELECTION_IS_COMPLETE = 1 << 3, + E_CAL_SHELL_CONTENT_SELECTION_IS_EDITABLE = 1 << 4, + E_CAL_SHELL_CONTENT_SELECTION_IS_MEETING = 1 << 5, + E_CAL_SHELL_CONTENT_SELECTION_IS_ORGANIZER = 1 << 6, + E_CAL_SHELL_CONTENT_SELECTION_IS_RECURRING = 1 << 7, + E_CAL_SHELL_CONTENT_SELECTION_CAN_ACCEPT = 1 << 8, + E_CAL_SHELL_CONTENT_SELECTION_CAN_DELEGATE = 1 << 9, + E_CAL_SHELL_CONTENT_SELECTION_CAN_SAVE = 1 << 10 +}; + +struct _ECalShellContent { + EShellContent parent; + ECalShellContentPrivate *priv; +}; + +struct _ECalShellContentClass { + EShellContentClass parent_class; +}; + +GType e_cal_shell_content_get_type (void); +void e_cal_shell_content_register_type + (GTypeModule *type_module); +GtkWidget * e_cal_shell_content_new (EShellView *shell_view); +GnomeCalendar * e_cal_shell_content_get_calendar + (ECalShellContent *cal_shell_content); +EMemoTable * e_cal_shell_content_get_memo_table + (ECalShellContent *cal_shell_content); +ECalendarTable *e_cal_shell_content_get_task_table + (ECalShellContent *cal_shell_content); +icaltimezone * e_cal_shell_content_get_timezone + (ECalShellContent *cal_shell_content); +GalViewInstance * + e_cal_shell_content_get_view_instance + (ECalShellContent *cal_shell_content); +void e_cal_shell_content_copy_clipboard + (ECalShellContent *cal_shell_content); +void e_cal_shell_content_cut_clipboard + (ECalShellContent *cal_shell_content); +void e_cal_shell_content_paste_clipboard + (ECalShellContent *cal_shell_content); +void e_cal_shell_content_delete_selection + (ECalShellContent *cal_shell_content); +void e_cal_shell_content_delete_selected_occurrence + (ECalShellContent *cal_shell_content); + +G_END_DECLS + +#endif /* E_CAL_SHELL_CONTENT_H */ diff --git a/modules/calendar/e-cal-shell-migrate.c b/modules/calendar/e-cal-shell-migrate.c new file mode 100644 index 0000000000..9887a5332c --- /dev/null +++ b/modules/calendar/e-cal-shell-migrate.c @@ -0,0 +1,796 @@ +/* + * e-cal-shell-backend-migrate.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-migrate.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "e-util/e-bconf-map.h" +#include "e-util/e-folder-map.h" +#include "e-util/e-util-private.h" +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/calendar-config-keys.h" +#include "calendar/gui/e-cal-event.h" +#include "shell/e-shell.h" + +#define WEBCAL_BASE_URI "webcal://" +#define CONTACTS_BASE_URI "contacts://" +#define BAD_CONTACTS_BASE_URI "contact://" +#define PERSONAL_RELATIVE_URI "system" + +static e_gconf_map_t calendar_display_map[] = { + /* /Calendar/Display */ + { "Timezone", "calendar/display/timezone", E_GCONF_MAP_STRING }, + { "Use24HourFormat", "calendar/display/use_24hour_format", E_GCONF_MAP_BOOL }, + { "WeekStartDay", "calendar/display/week_start_day", E_GCONF_MAP_INT }, + { "DayStartHour", "calendar/display/day_start_hour", E_GCONF_MAP_INT }, + { "DayStartMinute", "calendar/display/day_start_minute", E_GCONF_MAP_INT }, + { "DayEndHour", "calendar/display/day_end_hour", E_GCONF_MAP_INT }, + { "DayEndMinute", "calendar/display/day_end_minute", E_GCONF_MAP_INT }, + { "TimeDivisions", "calendar/display/time_divisions", E_GCONF_MAP_INT }, + { "View", "calendar/display/default_view", E_GCONF_MAP_INT }, + { "HPanePosition", "calendar/display/hpane_position", E_GCONF_MAP_FLOAT }, + { "VPanePosition", "calendar/display/vpane_position", E_GCONF_MAP_FLOAT }, + { "MonthHPanePosition", "calendar/display/month_hpane_position", E_GCONF_MAP_FLOAT }, + { "MonthVPanePosition", "calendar/display/month_vpane_position", E_GCONF_MAP_FLOAT }, + { "CompressWeekend", "calendar/display/compress_weekend", E_GCONF_MAP_BOOL }, + { "ShowEventEndTime", "calendar/display/show_event_end", E_GCONF_MAP_BOOL }, + { "WorkingDays", "calendar/display/working_days", E_GCONF_MAP_INT }, + { NULL }, +}; + +static e_gconf_map_t calendar_other_map[] = { + /* /Calendar/Other */ + { "ConfirmDelete", "calendar/prompts/confirm_delete", E_GCONF_MAP_BOOL }, + { "ConfirmExpunge", "calendar/prompts/confirm_purge", E_GCONF_MAP_BOOL }, + { "UseDefaultReminder", "calendar/other/use_default_reminder", E_GCONF_MAP_BOOL }, + { "DefaultReminderInterval", "calendar/other/default_reminder_interval", E_GCONF_MAP_INT }, + { "DefaultReminderUnits", "calendar/other/default_reminder_units", E_GCONF_MAP_STRING }, + { NULL }, +}; + +static e_gconf_map_t calendar_datenavigator_map[] = { + /* /Calendar/DateNavigator */ + { "ShowWeekNumbers", "calendar/date_navigator/show_week_numbers", E_GCONF_MAP_BOOL }, + { NULL }, +}; + +static e_gconf_map_t calendar_alarmnotify_map[] = { + /* /Calendar/AlarmNotify */ + { "LastNotificationTime", "calendar/notify/last_notification_time", E_GCONF_MAP_INT }, + { "CalendarToLoad%i", "calendar/notify/calendars", E_GCONF_MAP_STRING|E_GCONF_MAP_LIST }, + { "BlessedProgram%i", "calendar/notify/programs", E_GCONF_MAP_STRING|E_GCONF_MAP_LIST }, + { NULL }, +}; + +static e_gconf_map_list_t calendar_remap_list[] = { + + { "/Calendar/Display", calendar_display_map }, + { "/Calendar/Other/Map", calendar_other_map }, + { "/Calendar/DateNavigator", calendar_datenavigator_map }, + { "/Calendar/AlarmNotify", calendar_alarmnotify_map }, + + { NULL }, +}; + +static GtkWidget *window; +static GtkLabel *label; +static GtkProgressBar *progress; + +#ifndef G_OS_WIN32 + +/* No previous versions have been available on Win32, so don't + * bother with upgrade support from 1.x on Win32. + */ + +static void +setup_progress_dialog (void) +{ + GtkWidget *vbox, *hbox, *w; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title ((GtkWindow *) window, _("Migrating...")); + gtk_window_set_modal ((GtkWindow *) window, TRUE); + gtk_container_set_border_width ((GtkContainer *) window, 6); + + vbox = gtk_vbox_new (FALSE, 6); + gtk_widget_show (vbox); + gtk_container_add ((GtkContainer *) window, vbox); + + w = gtk_label_new (_("The location and hierarchy of the Evolution calendar " + "folders has changed since Evolution 1.x.\n\nPlease be " + "patient while Evolution migrates your folders...")); + + gtk_label_set_line_wrap ((GtkLabel *) w, TRUE); + gtk_widget_show (w); + gtk_box_pack_start_defaults ((GtkBox *) vbox, w); + + hbox = gtk_hbox_new (FALSE, 6); + gtk_widget_show (hbox); + gtk_box_pack_start_defaults ((GtkBox *) vbox, hbox); + + label = (GtkLabel *) gtk_label_new (""); + gtk_widget_show ((GtkWidget *) label); + gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) label); + + progress = (GtkProgressBar *) gtk_progress_bar_new (); + gtk_widget_show ((GtkWidget *) progress); + gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) progress); + + gtk_widget_show (window); +} + +static void +dialog_close (void) +{ + gtk_widget_destroy ((GtkWidget *) window); +} + +static void +dialog_set_folder_name (const gchar *folder_name) +{ + gchar *text; + + text = g_strdup_printf (_("Migrating '%s':"), folder_name); + gtk_label_set_text (label, text); + g_free (text); + + gtk_progress_bar_set_fraction (progress, 0.0); + + while (gtk_events_pending ()) + gtk_main_iteration (); +} + +static void +dialog_set_progress (double percent) +{ + gchar text[5]; + + snprintf (text, sizeof (text), "%d%%", (gint) (percent * 100.0f)); + + gtk_progress_bar_set_fraction (progress, percent); + gtk_progress_bar_set_text (progress, text); + + while (gtk_events_pending ()) + gtk_main_iteration (); +} + +static gboolean +check_for_conflict (ESourceGroup *group, gchar *name) +{ + GSList *sources; + GSList *s; + + sources = e_source_group_peek_sources (group); + + for (s = sources; s; s = s->next) { + ESource *source = E_SOURCE (s->data); + + if (!strcmp (e_source_peek_name (source), name)) + return TRUE; + } + + return FALSE; +} + +static gchar * +get_source_name (ESourceGroup *group, const gchar *path) +{ + gchar **p = g_strsplit (path, "/", 0); + gint i, j, starting_index; + gint num_elements; + gboolean conflict; + GString *s = g_string_new (NULL); + + for (i = 0; p[i]; i ++); + + num_elements = i; + i--; + + /* p[i] is now the last path element */ + + /* check if it conflicts */ + starting_index = i; + do { + for (j = starting_index; j < num_elements; j += 2) { + if (j != starting_index) + g_string_append_c (s, '_'); + g_string_append (s, p[j]); + } + + conflict = check_for_conflict (group, s->str); + + + /* if there was a conflict back up 2 levels (skipping the /subfolder/ element) */ + if (conflict) + starting_index -= 2; + + /* we always break out if we can't go any further, + regardless of whether or not we conflict. */ + if (starting_index < 0) + break; + + } while (conflict); + g_strfreev (p); + + return g_string_free (s, FALSE); +} + +static gboolean +migrate_ical (ECal *old_ecal, ECal *new_ecal) +{ + GList *l, *objects; + gint num_added = 0; + gint num_objects; + gboolean retval = TRUE; + + /* both ecals are loaded, start the actual migration */ + if (!e_cal_get_object_list (old_ecal, "#t", &objects, NULL)) + return FALSE; + + num_objects = g_list_length (objects); + for (l = objects; l; l = l->next) { + icalcomponent *ical_comp = l->data; + GError *error = NULL; + + if (!e_cal_create_object (new_ecal, ical_comp, NULL, &error)) { + g_warning ("Migration of object failed: %s", error->message); + retval = FALSE; + } + + g_clear_error (&error); + + num_added ++; + dialog_set_progress ((double)num_added / num_objects); + } + + g_list_foreach (objects, (GFunc) icalcomponent_free, NULL); + g_list_free (objects); + + return retval; +} + +static gboolean +migrate_ical_folder_to_source (gchar *old_path, ESource *new_source, ECalSourceType type) +{ + ECal *old_ecal = NULL, *new_ecal = NULL; + ESource *old_source; + ESourceGroup *group; + gchar *old_uri = g_strdup_printf ("file://%s", old_path); + GError *error = NULL; + gboolean retval = FALSE; + + group = e_source_group_new ("", old_uri); + old_source = e_source_new ("", ""); + e_source_group_add_source (group, old_source, -1); + + dialog_set_folder_name (e_source_peek_name (new_source)); + + if (!(old_ecal = e_cal_new (old_source, type))) { + g_warning ("could not find a backend for '%s'", e_source_get_uri (old_source)); + goto finish; + } + if (!e_cal_open (old_ecal, FALSE, &error)) { + g_warning ("failed to load source ecal for migration: '%s' (%s)", error->message, + e_source_get_uri (old_source)); + goto finish; + } + + if (!(new_ecal = e_cal_new (new_source, type))) { + g_warning ("could not find a backend for '%s'", e_source_get_uri (new_source)); + goto finish; + } + if (!e_cal_open (new_ecal, FALSE, &error)) { + g_warning ("failed to load destination ecal for migration: '%s' (%s)", error->message, + e_source_get_uri (new_source)); + goto finish; + } + + retval = migrate_ical (old_ecal, new_ecal); + +finish: + g_clear_error (&error); + if (old_ecal) + g_object_unref (old_ecal); + g_object_unref (group); + if (new_ecal) + g_object_unref (new_ecal); + g_free (old_uri); + + return retval; +} + +static gboolean +migrate_ical_folder (gchar *old_path, ESourceGroup *dest_group, gchar *source_name, ECalSourceType type) +{ + ESource *new_source; + gboolean retval; + + new_source = e_source_new (source_name, source_name); + e_source_set_relative_uri (new_source, e_source_peek_uid (new_source)); + e_source_group_add_source (dest_group, new_source, -1); + + retval = migrate_ical_folder_to_source (old_path, new_source, type); + + g_object_unref (new_source); + + return retval; +} + +#endif /* !G_OS_WIN32 */ + +#ifndef G_OS_WIN32 + +static void +migrate_pilot_db_key (const gchar *key, gpointer user_data) +{ + EXmlHash *xmlhash = user_data; + + e_xmlhash_add (xmlhash, key, ""); +} + +static void +migrate_pilot_data (const gchar *component, const gchar *conduit, const gchar *old_path, const gchar *new_path) +{ + gchar *changelog, *map; + const gchar *dent; + const gchar *ext; + gchar *filename; + GDir *dir; + + if (!(dir = g_dir_open (old_path, 0, NULL))) + return; + + map = g_alloca (12 + strlen (conduit)); + sprintf (map, "pilot-map-%s-", conduit); + + changelog = g_alloca (24 + strlen (conduit)); + sprintf (changelog, "pilot-sync-evolution-%s-", conduit); + + while ((dent = g_dir_read_name (dir))) { + if (!strncmp (dent, map, strlen (map)) && + ((ext = strrchr (dent, '.')) && !strcmp (ext, ".xml"))) { + /* pilot map file - src and dest file formats are identical */ + guchar inbuf[4096]; + gsize nread, nwritten; + gint fd0, fd1; + gssize n; + + filename = g_build_filename (old_path, dent, NULL); + if ((fd0 = g_open (filename, O_RDONLY|O_BINARY, 0)) == -1) { + g_free (filename); + continue; + } + + g_free (filename); + filename = g_build_filename (new_path, dent, NULL); + if ((fd1 = g_open (filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666)) == -1) { + g_free (filename); + close (fd0); + continue; + } + + do { + do { + n = read (fd0, inbuf, sizeof (inbuf)); + } while (n == -1 && errno == EINTR); + + if (n < 1) + break; + + nread = n; + nwritten = 0; + do { + do { + n = write (fd1, inbuf + nwritten, nread - nwritten); + } while (n == -1 && errno == EINTR); + + if (n > 0) + nwritten += n; + } while (nwritten < nread && n != -1); + + if (n == -1) + break; + } while (1); + + if (n != -1) + n = fsync (fd1); + + if (n == -1) { + g_warning ("Failed to migrate %s: %s", dent, strerror (errno)); + g_unlink (filename); + } + + close (fd0); + close (fd1); + g_free (filename); + } else if (!strncmp (dent, changelog, strlen (changelog)) && + ((ext = strrchr (dent, '.')) && !strcmp (ext, ".db"))) { + /* src and dest formats differ, src format is db3 while dest format is xml */ + EXmlHash *xmlhash; + EDbHash *dbhash; + struct stat st; + + filename = g_build_filename (old_path, dent, NULL); + if (g_stat (filename, &st) == -1) { + g_free (filename); + continue; + } + + dbhash = e_dbhash_new (filename); + g_free (filename); + + filename = g_strdup_printf ("%s/%s.ics-%s", new_path, component, dent); + if (g_stat (filename, &st) != -1) + g_unlink (filename); + xmlhash = e_xmlhash_new (filename); + g_free (filename); + + e_dbhash_foreach_key (dbhash, migrate_pilot_db_key, xmlhash); + + e_dbhash_destroy (dbhash); + + e_xmlhash_write (xmlhash); + e_xmlhash_destroy (xmlhash); + } + } + + g_dir_close (dir); +} + +#endif + +static ESourceGroup * +create_calendar_contact_source (ESourceList *source_list) +{ + ESourceGroup *group; + ESource *source; + + /* Create the contacts group */ + group = e_source_group_new (_("Contacts"), CONTACTS_BASE_URI); + e_source_list_add_group (source_list, group, -1); + + source = e_source_new (_("Birthdays & Anniversaries"), "/"); + e_source_group_add_source (group, source, -1); + g_object_unref (source); + + e_source_set_color_spec (source, "#FED4D3"); + e_source_group_set_readonly (group, TRUE); + + return group; +} + +static void +create_calendar_sources (EShellBackend *shell_backend, + ESourceList *source_list, + ESourceGroup **on_this_computer, + ESource **personal_source, + ESourceGroup **on_the_web, + ESourceGroup **contacts) +{ + EShell *shell; + EShellSettings *shell_settings; + GSList *groups; + ESourceGroup *group; + gchar *base_uri, *base_uri_proto; + const gchar *base_dir; + + *on_this_computer = NULL; + *on_the_web = NULL; + *contacts = NULL; + *personal_source = NULL; + + shell = e_shell_backend_get_shell (shell_backend); + shell_settings = e_shell_get_shell_settings (shell); + + base_dir = e_shell_backend_get_config_dir (shell_backend); + base_uri = g_build_filename (base_dir, "local", NULL); + + base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL); + + groups = e_source_list_peek_groups (source_list); + if (groups) { + /* groups are already there, we need to search for things... */ + GSList *g; + + for (g = groups; g; g = g->next) { + + group = E_SOURCE_GROUP (g->data); + + if (!strcmp (BAD_CONTACTS_BASE_URI, e_source_group_peek_base_uri (group))) + e_source_group_set_base_uri (group, CONTACTS_BASE_URI); + + if (!strcmp (base_uri, e_source_group_peek_base_uri (group))) + e_source_group_set_base_uri (group, base_uri_proto); + + if (!*on_this_computer && !strcmp (base_uri_proto, e_source_group_peek_base_uri (group))) + *on_this_computer = g_object_ref (group); + else if (!*on_the_web && !strcmp (WEBCAL_BASE_URI, e_source_group_peek_base_uri (group))) + *on_the_web = g_object_ref (group); + else if (!*contacts && !strcmp (CONTACTS_BASE_URI, e_source_group_peek_base_uri (group))) + *contacts = g_object_ref (group); + } + } + + if (*on_this_computer) { + /* make sure "Personal" shows up as a source under + this group */ + GSList *sources = e_source_group_peek_sources (*on_this_computer); + GSList *s; + for (s = sources; s; s = s->next) { + ESource *source = E_SOURCE (s->data); + const gchar *relative_uri; + + relative_uri = e_source_peek_relative_uri (source); + if (relative_uri == NULL) + continue; + if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) { + *personal_source = g_object_ref (source); + break; + } + } + } else { + /* create the local source group */ + group = e_source_group_new (_("On This Computer"), base_uri_proto); + e_source_list_add_group (source_list, group, -1); + + *on_this_computer = group; + } + + if (!*personal_source) { + gchar *primary_calendar; + + /* Create the default Person calendar */ + ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); + e_source_group_add_source (*on_this_computer, source, -1); + + primary_calendar = e_shell_settings_get_string ( + shell_settings, "cal-primary-calendar"); + + if (!primary_calendar && !calendar_config_get_calendars_selected ()) { + GSList selected; + + e_shell_settings_set_string ( + shell_settings, "cal-primary-calendar", + e_source_peek_uid (source)); + + selected.data = (gpointer)e_source_peek_uid (source); + selected.next = NULL; + calendar_config_set_calendars_selected (&selected); + } + + g_free (primary_calendar); + e_source_set_color_spec (source, "#BECEDD"); + *personal_source = source; + } + + if (!*on_the_web) { + /* Create the Webcal source group */ + group = e_source_group_new (_("On The Web"), WEBCAL_BASE_URI); + e_source_list_add_group (source_list, group, -1); + + *on_the_web = group; + } + + if (!*contacts) { + group = create_calendar_contact_source (source_list); + + *contacts = group; + } + + g_free (base_uri_proto); + g_free (base_uri); +} + +gboolean +e_cal_shell_backend_migrate (EShellBackend *shell_backend, + gint major, + gint minor, + gint micro, + GError **error) +{ + ESourceGroup *on_this_computer = NULL, *on_the_web = NULL, *contacts = NULL; + ESource *personal_source = NULL; + ESourceList *source_list; + ECalEvent *ece; + ECalEventTargetModule *target; + gboolean retval = FALSE; + + source_list = g_object_get_data ( + G_OBJECT (shell_backend), "source-list"); + + /* we call this unconditionally now - create_groups either + creates the groups/sources or it finds the necessary + groups/sources. */ + create_calendar_sources ( + shell_backend, source_list, &on_this_computer, + &personal_source, &on_the_web, &contacts); + +#ifndef G_OS_WIN32 + if (major == 1) { + xmlDocPtr config_doc = NULL; + gchar *conf_file; + struct stat st; + + conf_file = g_build_filename (g_get_home_dir (), "evolution", "config.xmldb", NULL); + if (lstat (conf_file, &st) == 0 && S_ISREG (st.st_mode)) + config_doc = xmlParseFile (conf_file); + g_free (conf_file); + + if (config_doc && minor <= 2) { + GConfClient *gconf; + gint res = 0; + + /* move bonobo config to gconf */ + gconf = gconf_client_get_default (); + + res = e_bconf_import (gconf, config_doc, calendar_remap_list); + + g_object_unref (gconf); + + xmlFreeDoc(config_doc); + + if (res != 0) { + /* FIXME: set proper domain/code */ + g_set_error(error, 0, 0, _("Unable to migrate old settings from evolution/config.xmldb")); + goto fail; + } + } + + if (minor <= 4) { + GSList *migration_dirs, *l; + gchar *path, *local_cal_folder; + + setup_progress_dialog (); + + path = g_build_filename (g_get_home_dir (), "evolution", "local", NULL); + migration_dirs = e_folder_map_local_folders (path, "calendar"); + local_cal_folder = g_build_filename (path, "Calendar", NULL); + g_free (path); + + if (personal_source) + migrate_ical_folder_to_source (local_cal_folder, personal_source, E_CAL_SOURCE_TYPE_EVENT); + + for (l = migration_dirs; l; l = l->next) { + gchar *source_name; + + if (personal_source && !strcmp ((gchar *)l->data, local_cal_folder)) + continue; + + source_name = get_source_name (on_this_computer, (gchar *)l->data); + + if (!migrate_ical_folder (l->data, on_this_computer, source_name, E_CAL_SOURCE_TYPE_EVENT)) { + /* FIXME: domain/code */ + g_set_error(error, 0, 0, _("Unable to migrate calendar `%s'"), source_name); + g_free(source_name); + goto fail; + } + + g_free (source_name); + } + + g_free (local_cal_folder); + + dialog_close (); + } + + if (minor <= 4 || (minor == 5 && micro < 5)) { + GConfClient *gconf; + GConfValue *gconf_val; + gint i; + const gchar *keys[] = { + CALENDAR_CONFIG_HPANE_POS, + CALENDAR_CONFIG_VPANE_POS, + CALENDAR_CONFIG_MONTH_HPANE_POS, + CALENDAR_CONFIG_MONTH_VPANE_POS, + NULL + }; + + gconf = gconf_client_get_default (); + + for (i = 0; keys[i]; i++) { + gconf_val = gconf_client_get (gconf, keys[i], NULL); + if (gconf_val) { + if (gconf_val->type != GCONF_VALUE_INT) + gconf_client_unset (gconf, keys[i], NULL); + gconf_value_free (gconf_val); + } + } + + g_object_unref (gconf); + } + + if (minor < 5 || (minor == 5 && micro <= 10)) { + gchar *old_path, *new_path; + + old_path = g_build_filename (g_get_home_dir (), "evolution", "local", "Calendar", NULL); + new_path = g_build_filename (e_shell_backend_get_config_dir (shell_backend), + "local", "system", NULL); + migrate_pilot_data ("calendar", "calendar", old_path, new_path); + g_free (new_path); + g_free (old_path); + } + + /* we only need to do this next step if people ran + older versions of 1.5. We need to clear out the + absolute URI's that were assigned to ESources + during one phase of development, as they take + precedent over relative uris (but aren't updated + when editing an ESource). */ + if (minor == 5 && micro <= 11) { + GSList *g; + for (g = e_source_list_peek_groups (source_list); g; g = g->next) { + ESourceGroup *group = g->data; + GSList *s; + + for (s = e_source_group_peek_sources (group); s; s = s->next) { + ESource *source = s->data; + e_source_set_absolute_uri (source, NULL); + } + } + } + + } +#endif /* !G_OS_WIN32 */ + + e_source_list_sync (source_list, NULL); + + /** @Event: component.migration + * @Title: Migration step in component initialization + * @Target: ECalEventTargetComponent + * + * component.migration is emitted during the calendar component + * initialization process. This allows new calendar backend types + * to be distributed as an e-d-s backend and a plugin without + * reaching their grubby little fingers into migration.c + */ + /* Fire off migration event */ + ece = e_cal_event_peek (); + target = e_cal_event_target_new_module (ece, shell_backend, 0); + e_event_emit ((EEvent *) ece, "module.migration", (EEventTarget *) target); + + retval = TRUE; +fail: + if (on_this_computer) + g_object_unref (on_this_computer); + if (on_the_web) + g_object_unref (on_the_web); + if (contacts) + g_object_unref (contacts); + if (personal_source) + g_object_unref (personal_source); + + return retval; +} + diff --git a/modules/calendar/e-cal-shell-migrate.h b/modules/calendar/e-cal-shell-migrate.h new file mode 100644 index 0000000000..359ca5ea22 --- /dev/null +++ b/modules/calendar/e-cal-shell-migrate.h @@ -0,0 +1,38 @@ +/* + * e-cal-shell-backend-migrate.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_CAL_SHELL_BACKEND_MIGRATE_H +#define E_CAL_SHELL_BACKEND_MIGRATE_H + +#include +#include + +G_BEGIN_DECLS + +gboolean e_cal_shell_backend_migrate (EShellBackend *shell_backend, + gint major, + gint minor, + gint micro, + GError **error); + +G_END_DECLS + +#endif /* E_CAL_SHELL_BACKEND_MIGRATE_H */ diff --git a/modules/calendar/e-cal-shell-settings.c b/modules/calendar/e-cal-shell-settings.c new file mode 100644 index 0000000000..03af4aeebc --- /dev/null +++ b/modules/calendar/e-cal-shell-settings.c @@ -0,0 +1,59 @@ +/* + * e-cal-shell-backend-settings.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-settings.h" + +#include + +void +e_cal_shell_backend_init_settings (EShell *shell) +{ + EShellSettings *shell_settings; + + shell_settings = e_shell_get_shell_settings (shell); + + /* XXX Default values should match the GConf schema. + * Yes it's redundant, but we're stuck with GConf. */ + + e_shell_settings_install_property ( + g_param_spec_string ( + "cal-primary-calendar", + NULL, + NULL, + NULL, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "cal-primary-calendar", + "/apps/evolution/calendar/display/primary_calendar"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "cal-use-system-timezone", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "cal-use-system-timezone", + "/apps/evolution/calendar/display/use_system_timezone"); +} diff --git a/modules/calendar/e-cal-shell-settings.h b/modules/calendar/e-cal-shell-settings.h new file mode 100644 index 0000000000..de8b22888b --- /dev/null +++ b/modules/calendar/e-cal-shell-settings.h @@ -0,0 +1,33 @@ +/* + * e-cal-shell-backend-settings.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_CAL_SHELL_BACKEND_SETTINGS_H +#define E_CAL_SHELL_BACKEND_SETTINGS_H + +#include + +G_BEGIN_DECLS + +void e_cal_shell_backend_init_settings (EShell *shell); + +G_END_DECLS + +#endif /* E_CAL_SHELL_BACKEND_SETTINGS_H */ diff --git a/modules/calendar/e-cal-shell-sidebar.c b/modules/calendar/e-cal-shell-sidebar.c new file mode 100644 index 0000000000..dc7df596d6 --- /dev/null +++ b/modules/calendar/e-cal-shell-sidebar.c @@ -0,0 +1,759 @@ +/* + * e-cal-shell-sidebar.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-sidebar.h" + +#include +#include + +#include "e-util/e-error.h" +#include "e-util/gconf-bridge.h" +#include "calendar/common/authentication.h" +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/e-calendar-selector.h" +#include "calendar/gui/e-mini-calendar-config.h" +#include "calendar/gui/misc.h" + +#include "e-cal-shell-backend.h" +#include "e-cal-shell-view.h" + +#define E_CAL_SHELL_SIDEBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_CAL_SHELL_SIDEBAR, ECalShellSidebarPrivate)) + +struct _ECalShellSidebarPrivate { + GtkWidget *paned; + GtkWidget *selector; + GtkWidget *mini_calendar; + + /* UID -> Client */ + GHashTable *client_table; + + EMiniCalendarConfig *mini_calendar_config; +}; + +enum { + PROP_0, + PROP_MINI_CALENDAR, + PROP_SELECTOR +}; + +enum { + CLIENT_ADDED, + CLIENT_REMOVED, + STATUS_MESSAGE, + LAST_SIGNAL +}; + +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; +static GType cal_shell_sidebar_type; + +static void +cal_shell_sidebar_emit_client_added (ECalShellSidebar *cal_shell_sidebar, + ECal *client) +{ + guint signal_id = signals[CLIENT_ADDED]; + + g_signal_emit (cal_shell_sidebar, signal_id, 0, client); +} + +static void +cal_shell_sidebar_emit_client_removed (ECalShellSidebar *cal_shell_sidebar, + ECal *client) +{ + guint signal_id = signals[CLIENT_REMOVED]; + + g_signal_emit (cal_shell_sidebar, signal_id, 0, client); +} + +static void +cal_shell_sidebar_emit_status_message (ECalShellSidebar *cal_shell_sidebar, + const gchar *status_message) +{ + guint signal_id = signals[STATUS_MESSAGE]; + + g_signal_emit (cal_shell_sidebar, signal_id, 0, status_message); +} + +static void +cal_shell_sidebar_backend_died_cb (ECalShellSidebar *cal_shell_sidebar, + ECal *client) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + GHashTable *client_table; + ESource *source; + const gchar *uid; + + client_table = cal_shell_sidebar->priv->client_table; + + shell_sidebar = E_SHELL_SIDEBAR (cal_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + source = e_cal_get_source (client); + uid = e_source_peek_uid (source); + + g_object_ref (source); + + g_hash_table_remove (client_table, uid); + cal_shell_sidebar_emit_status_message (cal_shell_sidebar, NULL); + + e_error_run ( + GTK_WINDOW (shell_window), + "calendar:calendar-crashed", NULL); + + g_object_unref (source); +} + +static void +cal_shell_sidebar_backend_error_cb (ECalShellSidebar *cal_shell_sidebar, + const gchar *message, + ECal *client) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + GtkWidget *dialog; + const gchar *uri; + gchar *uri_no_passwd; + + shell_sidebar = E_SHELL_SIDEBAR (cal_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + uri = e_cal_get_uri (client); + uri_no_passwd = get_uri_without_password (uri); + + dialog = gtk_message_dialog_new ( + GTK_WINDOW (shell_window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, + _("Error on %s\n%s"), + uri_no_passwd, message); + + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + + g_free (uri_no_passwd); +} + +static void +cal_shell_sidebar_client_opened_cb (ECalShellSidebar *cal_shell_sidebar, + ECalendarStatus status, + ECal *client) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + ESource *source; + + source = e_cal_get_source (client); + + shell_sidebar = E_SHELL_SIDEBAR (cal_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + if (status == E_CALENDAR_STATUS_AUTHENTICATION_FAILED || + status == E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED) + auth_cal_forget_password (client); + + switch (status) { + case E_CALENDAR_STATUS_OK: + g_signal_handlers_disconnect_matched ( + client, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, + cal_shell_sidebar_client_opened_cb, NULL); + + cal_shell_sidebar_emit_status_message ( + cal_shell_sidebar, _("Loading calendars")); + cal_shell_sidebar_emit_client_added ( + cal_shell_sidebar, client); + cal_shell_sidebar_emit_status_message ( + cal_shell_sidebar, NULL); + break; + + case E_CALENDAR_STATUS_AUTHENTICATION_FAILED: + e_cal_open_async (client, FALSE); + break; + + case E_CALENDAR_STATUS_BUSY: + break; + + case E_CALENDAR_STATUS_REPOSITORY_OFFLINE: + e_error_run ( + GTK_WINDOW (shell_window), + "calendar:prompt-no-contents-offline-calendar", + NULL); + break; + + default: + cal_shell_sidebar_emit_client_removed ( + cal_shell_sidebar, client); + break; + } +} + +static void +cal_shell_sidebar_row_changed_cb (ECalShellSidebar *cal_shell_sidebar, + GtkTreePath *tree_path, + GtkTreeIter *tree_iter, + GtkTreeModel *tree_model) +{ + ESourceSelector *selector; + ESource *source; + + /* XXX ESourceSelector's underlying tree store has only one + * column: ESource objects. While we're not supposed to + * know this, listening for "row-changed" signals from + * the model is easier to deal with than the selector's + * "selection-changed" signal, which doesn't tell you + * _which_ row changed. */ + + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + gtk_tree_model_get (tree_model, tree_iter, 0, &source, -1); + + /* XXX This signal gets emitted a lot while the model is being + * rebuilt, during which time we won't get a valid ESource. + * ESourceSelector should probably block this signal while + * rebuilding the model, but we'll be forgiving and not + * emit a warning. */ + if (!E_IS_SOURCE (source)) + return; + + if (e_source_selector_source_is_selected (selector, source)) + e_cal_shell_sidebar_add_source (cal_shell_sidebar, source); + else + e_cal_shell_sidebar_remove_source (cal_shell_sidebar, source); +} + +static void +cal_shell_sidebar_selection_changed_cb (ECalShellSidebar *cal_shell_sidebar, + ESourceSelector *selector) +{ + GSList *list, *iter; + + /* This signal is emitted less frequently than "row-changed", + * especially when the model is being rebuilt. So we'll take + * it easy on poor GConf. */ + + list = e_source_selector_get_selection (selector); + + for (iter = list; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + + iter->data = (gpointer) e_source_peek_uid (source); + g_object_unref (source); + } + + calendar_config_set_calendars_selected (list); + + g_slist_free (list); +} + +static void +cal_shell_sidebar_primary_selection_changed_cb (ECalShellSidebar *cal_shell_sidebar, + ESourceSelector *selector) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + EShellSettings *shell_settings; + ESource *source; + + /* XXX ESourceSelector needs a "primary-selection-uid" property + * so we can just bind the property with GConfBridge. */ + + source = e_source_selector_peek_primary_selection (selector); + if (source == NULL) + return; + + shell_sidebar = E_SHELL_SIDEBAR (cal_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + e_shell_settings_set_string ( + shell_settings, "cal-primary-calendar", + e_source_peek_uid (source)); +} + +static void +cal_shell_sidebar_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_MINI_CALENDAR: + g_value_set_object ( + value, e_cal_shell_sidebar_get_mini_calendar ( + E_CAL_SHELL_SIDEBAR (object))); + return; + + case PROP_SELECTOR: + g_value_set_object ( + value, e_cal_shell_sidebar_get_selector ( + E_CAL_SHELL_SIDEBAR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +cal_shell_sidebar_dispose (GObject *object) +{ + ECalShellSidebarPrivate *priv; + + priv = E_CAL_SHELL_SIDEBAR_GET_PRIVATE (object); + + if (priv->paned != NULL) { + g_object_unref (priv->paned); + priv->paned = NULL; + } + + if (priv->selector != NULL) { + g_object_unref (priv->selector); + priv->selector = NULL; + } + + if (priv->mini_calendar != NULL) { + g_object_unref (priv->mini_calendar); + priv->mini_calendar = NULL; + } + + g_hash_table_remove_all (priv->client_table); + + if (priv->mini_calendar_config != NULL) { + g_object_unref (priv->mini_calendar_config); + priv->mini_calendar = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +cal_shell_sidebar_finalize (GObject *object) +{ + ECalShellSidebarPrivate *priv; + + priv = E_CAL_SHELL_SIDEBAR_GET_PRIVATE (object); + + g_hash_table_destroy (priv->client_table); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +cal_shell_sidebar_constructed (GObject *object) +{ + ECalShellSidebarPrivate *priv; + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + EShellBackend *shell_backend; + EShellSidebar *shell_sidebar; + EShellSettings *shell_settings; + ESourceSelector *selector; + ESourceList *source_list; + ESource *source; + ECalendarItem *calitem; + GConfBridge *bridge; + GtkTreeModel *model; + GtkWidget *container; + GtkWidget *widget; + AtkObject *a11y; + GSList *list, *iter; + const gchar *key; + gchar *uid; + + priv = E_CAL_SHELL_SIDEBAR_GET_PRIVATE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + shell_sidebar = E_SHELL_SIDEBAR (object); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_backend = e_shell_view_get_shell_backend (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + source_list = e_cal_shell_backend_get_source_list ( + E_CAL_SHELL_BACKEND (shell_backend)); + + container = GTK_WIDGET (shell_sidebar); + + widget = gtk_vpaned_new (); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->paned = g_object_ref (widget); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_paned_add1 (GTK_PANED (container), widget); + gtk_widget_show (widget); + + container = widget; + + widget = e_calendar_selector_new (source_list); + e_source_selector_set_select_new (E_SOURCE_SELECTOR (widget), TRUE); + gtk_container_add (GTK_CONTAINER (container), widget); + a11y = gtk_widget_get_accessible (widget); + atk_object_set_name (a11y, _("Calendar Selector")); + priv->selector = g_object_ref (widget); + gtk_widget_show (widget); + + container = priv->paned; + + widget = e_calendar_new (); + calitem = E_CALENDAR (widget)->calitem; + e_calendar_item_set_days_start_week_sel (calitem, 9); + e_calendar_item_set_max_days_sel (calitem, 42); + gtk_paned_add2 (GTK_PANED (container), widget); + priv->mini_calendar = g_object_ref (widget); + gtk_widget_show (widget); + + priv->mini_calendar_config = + e_mini_calendar_config_new (E_CALENDAR (widget)); + + /* Restore the selector state from the last session. */ + + selector = E_SOURCE_SELECTOR (priv->selector); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (selector)); + + g_signal_connect_swapped ( + model, "row-changed", + G_CALLBACK (cal_shell_sidebar_row_changed_cb), + object); + + source = NULL; + uid = e_shell_settings_get_string ( + shell_settings, "cal-primary-calendar"); + if (uid != NULL) + source = e_source_list_peek_source_by_uid (source_list, uid); + if (source == NULL) + source = e_source_list_peek_source_any (source_list); + if (source != NULL) + e_source_selector_set_primary_selection (selector, source); + g_free (uid); + + list = calendar_config_get_calendars_selected (); + for (iter = list; iter != NULL; iter = iter->next) { + uid = iter->data; + source = e_source_list_peek_source_by_uid (source_list, uid); + g_free (uid); + + if (source == NULL) + continue; + + e_source_selector_select_source (selector, source); + } + g_slist_free (list); + + /* Listen for subsequent changes to the selector. */ + + g_signal_connect_swapped ( + selector, "selection-changed", + G_CALLBACK (cal_shell_sidebar_selection_changed_cb), + object); + + g_signal_connect_swapped ( + selector, "primary-selection-changed", + G_CALLBACK (cal_shell_sidebar_primary_selection_changed_cb), + object); + + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (priv->paned); + key = "/apps/evolution/calendar/display/date_navigator_vpane_position"; + gconf_bridge_bind_property_delayed (bridge, key, object, "position"); +} + +static void +cal_shell_sidebar_client_removed (ECalShellSidebar *cal_shell_sidebar, + ECal *client) +{ + ESourceSelector *selector; + GHashTable *client_table; + ESource *source; + const gchar *uid; + + client_table = cal_shell_sidebar->priv->client_table; + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + + g_signal_handlers_disconnect_matched ( + client, G_SIGNAL_MATCH_DATA, 0, 0, + NULL, NULL, cal_shell_sidebar); + + source = e_cal_get_source (client); + e_source_selector_unselect_source (selector, source); + + uid = e_source_peek_uid (source); + g_hash_table_remove (client_table, uid); + + cal_shell_sidebar_emit_status_message (cal_shell_sidebar, NULL); +} + +static void +cal_shell_sidebar_class_init (ECalShellSidebarClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ECalShellSidebarPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->get_property = cal_shell_sidebar_get_property; + object_class->dispose = cal_shell_sidebar_dispose; + object_class->finalize = cal_shell_sidebar_finalize; + object_class->constructed = cal_shell_sidebar_constructed; + + class->client_removed = cal_shell_sidebar_client_removed; + + g_object_class_install_property ( + object_class, + PROP_MINI_CALENDAR, + g_param_spec_object ( + "mini-calendar", + _("Mini-Calendar Widget"), + _("This widget displays a miniature calendar"), + E_TYPE_CALENDAR, + G_PARAM_READABLE)); + + g_object_class_install_property ( + object_class, + PROP_SELECTOR, + g_param_spec_object ( + "selector", + _("Source Selector Widget"), + _("This widget displays groups of calendars"), + E_TYPE_SOURCE_SELECTOR, + G_PARAM_READABLE)); + + signals[CLIENT_ADDED] = g_signal_new ( + "client-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ECalShellSidebarClass, client_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CAL); + + signals[CLIENT_REMOVED] = g_signal_new ( + "client-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ECalShellSidebarClass, client_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CAL); + + signals[STATUS_MESSAGE] = g_signal_new ( + "status-message", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (ECalShellSidebarClass, status_message), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); +} + +static void +cal_shell_sidebar_init (ECalShellSidebar *cal_shell_sidebar) +{ + GHashTable *client_table; + + client_table = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_object_unref); + + cal_shell_sidebar->priv = + E_CAL_SHELL_SIDEBAR_GET_PRIVATE (cal_shell_sidebar); + + cal_shell_sidebar->priv->client_table = client_table; + + /* Postpone widget construction until we have a shell view. */ +} + +GType +e_cal_shell_sidebar_get_type (void) +{ + return cal_shell_sidebar_type; +} + +void +e_cal_shell_sidebar_register_type (GTypeModule *type_module) +{ + static const GTypeInfo type_info = { + sizeof (ECalShellSidebarClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) cal_shell_sidebar_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ECalShellSidebar), + 0, /* n_preallocs */ + (GInstanceInitFunc) cal_shell_sidebar_init, + NULL /* value_table */ + }; + + cal_shell_sidebar_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_SIDEBAR, + "ECalShellSidebar", &type_info, 0); +} + +GtkWidget * +e_cal_shell_sidebar_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_CAL_SHELL_SIDEBAR, + "shell-view", shell_view, NULL); +} + +GList * +e_cal_shell_sidebar_get_clients (ECalShellSidebar *cal_shell_sidebar) +{ + GHashTable *client_table; + + g_return_val_if_fail ( + E_IS_CAL_SHELL_SIDEBAR (cal_shell_sidebar), NULL); + + client_table = cal_shell_sidebar->priv->client_table; + + return g_hash_table_get_values (client_table); +} + +ECalendar * +e_cal_shell_sidebar_get_mini_calendar (ECalShellSidebar *cal_shell_sidebar) +{ + g_return_val_if_fail ( + E_IS_CAL_SHELL_SIDEBAR (cal_shell_sidebar), NULL); + + return E_CALENDAR (cal_shell_sidebar->priv->mini_calendar); +} + +ESourceSelector * +e_cal_shell_sidebar_get_selector (ECalShellSidebar *cal_shell_sidebar) +{ + g_return_val_if_fail ( + E_IS_CAL_SHELL_SIDEBAR (cal_shell_sidebar), NULL); + + return E_SOURCE_SELECTOR (cal_shell_sidebar->priv->selector); +} + +void +e_cal_shell_sidebar_add_source (ECalShellSidebar *cal_shell_sidebar, + ESource *source) +{ + ESourceSelector *selector; + GHashTable *client_table; + ECal *client; + const gchar *uid; + const gchar *uri; + gchar *message; + + g_return_if_fail (E_IS_CAL_SHELL_SIDEBAR (cal_shell_sidebar)); + g_return_if_fail (E_IS_SOURCE (source)); + + client_table = cal_shell_sidebar->priv->client_table; + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + + uid = e_source_peek_uid (source); + client = g_hash_table_lookup (client_table, uid); + + if (client != NULL) + return; + + client = auth_new_cal_from_source (source, E_CAL_SOURCE_TYPE_EVENT); + g_return_if_fail (client != NULL); + + g_signal_connect_swapped ( + client, "backend-died", + G_CALLBACK (cal_shell_sidebar_backend_died_cb), + cal_shell_sidebar); + + g_signal_connect_swapped ( + client, "backend-error", + G_CALLBACK (cal_shell_sidebar_backend_error_cb), + cal_shell_sidebar); + + g_hash_table_insert (client_table, g_strdup (uid), client); + e_source_selector_select_source (selector, source); + + uri = e_cal_get_uri (client); + message = g_strdup_printf (_("Opening calendar at %s"), uri); + cal_shell_sidebar_emit_status_message (cal_shell_sidebar, message); + g_free (message); + + g_signal_connect_swapped ( + client, "cal-opened", + G_CALLBACK (cal_shell_sidebar_client_opened_cb), + cal_shell_sidebar); + + e_cal_open_async (client, FALSE); +} + +void +e_cal_shell_sidebar_remove_source (ECalShellSidebar *cal_shell_sidebar, + ESource *source) +{ + ESourceSelector *selector; + GHashTable *client_table; + ECal *client; + const gchar *uid; + + g_return_if_fail (E_IS_CAL_SHELL_SIDEBAR (cal_shell_sidebar)); + g_return_if_fail (E_IS_SOURCE (source)); + + client_table = cal_shell_sidebar->priv->client_table; + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + + uid = e_source_peek_uid (source); + client = g_hash_table_lookup (client_table, uid); + + if (client == NULL) + return; + + cal_shell_sidebar_emit_client_removed (cal_shell_sidebar, client); +} diff --git a/modules/calendar/e-cal-shell-sidebar.h b/modules/calendar/e-cal-shell-sidebar.h new file mode 100644 index 0000000000..c555537abf --- /dev/null +++ b/modules/calendar/e-cal-shell-sidebar.h @@ -0,0 +1,101 @@ +/* + * e-cal-shell-sidebar.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_CAL_SHELL_SIDEBAR_H +#define E_CAL_SHELL_SIDEBAR_H + +#include +#include + +#include +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_CAL_SHELL_SIDEBAR \ + (e_cal_shell_sidebar_get_type ()) +#define E_CAL_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_CAL_SHELL_SIDEBAR, ECalShellSidebar)) +#define E_CAL_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_CAL_SHELL_SIDEBAR, ECalShellSidebarClass)) +#define E_IS_CAL_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_CAL_SHELL_SIDEBAR)) +#define E_IS_CAL_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_CAL_SHELL_SIDEBAR)) +#define E_CAL_SHELL_SIDEBAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_CAL_SHELL_SIDEBAR, ECalShellSidebarClass)) + +G_BEGIN_DECLS + +typedef struct _ECalShellSidebar ECalShellSidebar; +typedef struct _ECalShellSidebarClass ECalShellSidebarClass; +typedef struct _ECalShellSidebarPrivate ECalShellSidebarPrivate; + +enum { + E_CAL_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE = 1 << 0, + E_CAL_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_EMPTY = 1 << 1, + E_CAL_SHELL_SIDEBAR_SOURCE_CAN_GO_OFFLINE = 1 << 2, + E_CAL_SHELL_SIDEBAR_SOURCE_CAN_DELETE = 1 << 3 +}; + +struct _ECalShellSidebar { + EShellSidebar parent; + ECalShellSidebarPrivate *priv; +}; + +struct _ECalShellSidebarClass { + EShellSidebarClass parent_class; + + /* Signals */ + void (*client_added) (ECalShellSidebar *cal_shell_sidebar, + ECal *client); + void (*client_removed) (ECalShellSidebar *cal_shell_sidebar, + ECal *client); + void (*status_message) (ECalShellSidebar *cal_shell_sidebar, + const gchar *status_message); +}; + +GType e_cal_shell_sidebar_get_type (void); +void e_cal_shell_sidebar_register_type + (GTypeModule *type_module); +GtkWidget * e_cal_shell_sidebar_new (EShellView *shell_view); +GList * e_cal_shell_sidebar_get_clients + (ECalShellSidebar *cal_shell_sidebar); +ECalendar * e_cal_shell_sidebar_get_mini_calendar + (ECalShellSidebar *cal_shell_sidebar); +ESourceSelector * + e_cal_shell_sidebar_get_selector + (ECalShellSidebar *cal_shell_sidebar); +void e_cal_shell_sidebar_add_source + (ECalShellSidebar *cal_shell_sidebar, + ESource *source); +void e_cal_shell_sidebar_remove_source + (ECalShellSidebar *cal_shell_sidebar, + ESource *source); + +G_END_DECLS + +#endif /* E_CAL_SHELL_SIDEBAR_H */ diff --git a/modules/calendar/e-cal-shell-view-actions.c b/modules/calendar/e-cal-shell-view-actions.c new file mode 100644 index 0000000000..02b7af609e --- /dev/null +++ b/modules/calendar/e-cal-shell-view-actions.c @@ -0,0 +1,1202 @@ +/* + * e-cal-shell-view-actions.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-view-private.h" + +static void +action_calendar_copy_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellSidebar *cal_shell_sidebar; + EShellWindow *shell_window; + EShellView *shell_view; + ESourceSelector *selector; + ESource *source; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (E_IS_SOURCE (source)); + + copy_source_dialog ( + GTK_WINDOW (shell_window), + source, E_CAL_SOURCE_TYPE_EVENT); +} + +static void +action_calendar_delete_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellContent *cal_shell_content; + ECalShellSidebar *cal_shell_sidebar; + EShellWindow *shell_window; + EShellView *shell_view; + ECalendarView *calendar_view; + GnomeCalendarViewType view_type; + ECalModel *model; + ESourceSelector *selector; + ESourceGroup *source_group; + ESourceList *source_list; + ESource *source; + gint response; + gchar *uri; + GError *error = NULL; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + cal_shell_content = cal_shell_content->priv->cal_shell_content; + view_type = e_cal_shell_content_get_current_view (cal_shell_content); + calendar_view = e_cal_shell_content_get_calendar_view ( + cal_shell_content, view_type); + model = e_calendar_view_get_model (calendar_view); + + cal_shell_sidebar = cal_shell_sidebar->priv->cal_shell_sidebar; + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (E_IS_SOURCE (source)); + + /* Ask for confirmation. */ + response = e_error_run ( + GTK_WINDOW (shell_window), + "calendar:prompt-delete-calendar", + e_source_peek_name (source)); + if (response != GTK_RESPONSE_YES) + return; + + uri = e_source_get_uri (source); + client = e_cal_model_get_client_for_uri (model, uri); + if (client == NULL) + client = e_cal_new_from_uri (uri, E_CAL_SOURCE_TYPE_EVENT); + g_free (uri); + + g_return_if_fail (client != NULL); + + if (!e_cal_remove (client, &error)) { + g_warning ("%s", error->message); + g_error_free (error); + return; + } + + if (e_source_selector_source_is_selected (selector, source)) { + e_cal_shell_sidebar_remove_source ( + cal_shell_sidebar, source); + e_source_selector_unselect_source (selector, source); + } + + source_group = e_source_peek_group (source); + e_source_group_remove_source (source_group, source); + + source_list = cal_shell_view->priv->source_list; + if (!e_source_list_sync (source_list, &error)) { + g_warning ("%s", error->message); + g_error_free (error); + } +#endif +} + +static void +action_calendar_go_back_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellContent *cal_shell_content; + GnomeCalendar *calendar; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + + gnome_calendar_previous (calendar); +#endif +} + +static void +action_calendar_go_forward_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellContent *cal_shell_content; + GnomeCalendar *calendar; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + + gnome_calendar_next (calendar); +#endif +} + +static void +action_calendar_go_today_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellContent *cal_shell_content; + GnomeCalendar *calendar; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + + gnome_calendar_goto_today (calendar); +#endif +} + +static void +action_calendar_jump_to_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellContent *cal_shell_content; + GnomeCalendar *calendar; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + + goto_dialog (calendar); +#endif +} + +static void +action_calendar_new_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + EShellView *shell_view; + EShellWindow *shell_window; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + calendar_setup_new_calendar (GTK_WINDOW (shell_window)); +#endif +} + +static void +action_calendar_print_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellContent *cal_shell_content; + GnomeCalendar *calendar; + GtkPrintOperationAction print_action; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; + + if (gnome_calendar_get_view (calendar) == GNOME_CAL_LIST_VIEW) { + ECalListView *list_view; + GtkWidget *widget; + ETable *table; + + widget = gnome_calendar_get_current_view_widget (calendar); + list_view = E_CAL_LIST_VIEW (widget); + table = e_table_scrolled_get_table (list_view->table_scrolled); + print_table (table, _("Print"), _("Calendar"), action); + } else { + time_t start; + + gnome_calendar_get_current_time_range (calendar, &start, NULL); + print_calendar (calendar, action, start); + } +#endif +} + +static void +action_calendar_print_preview_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellContent *cal_shell_content; + GnomeCalendar *calendar; + GtkPrintOperationAction print_action; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW; + + if (gnome_calendar_get_view (calendar) == GNOME_CAL_LIST_VIEW) { + ECalListView *list_view; + GtkWidget *widget; + ETable *table; + + widget = gnome_calendar_get_current_view_widget (calendar); + list_view = E_CAL_LIST_VIEW (widget); + table = e_table_scrolled_get_table (list_view->table_scrolled); + print_table (table, _("Print"), _("Calendar"), action); + } else { + time_t start; + + gnome_calendar_get_current_time_range (calendar, &start, NULL); + print_calendar (calendar, action, start); + } +#endif +} + +static void +action_calendar_properties_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellSidebar *cal_shell_sidebar; + EShellView *shell_view; + EShellWindow *shell_window; + ESource *source; + ESourceSelector *selector; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (E_IS_SOURCE (source)); + + calendar_setup_edit_calendar (GTK_WINDOW (shell_window), source); +#endif +} + +static void +action_calendar_purge_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_calendar_rename_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellSidebar *cal_shell_sidebar; + ESourceSelector *selector; + + cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + + e_source_selector_edit_primary_selection (selector); +} + +static void +action_calendar_search_cb (GtkRadioAction *action, + GtkRadioAction *current, + ECalShellView *cal_shell_view) +{ + EShellView *shell_view; + EShellContent *shell_content; + const gchar *search_hint; + + /* XXX Figure out a way to handle this in EShellContent + * instead of every shell view having to handle it. + * The problem is EShellContent does not know what + * the search option actions are for this view. It + * would have to dig up the popup menu and retrieve + * the action for each menu item. Seems messy. */ + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + + search_hint = gtk_action_get_label (GTK_ACTION (current)); + e_shell_content_set_search_hint (shell_content, search_hint); +} + +static void +action_calendar_select_one_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellSidebar *cal_shell_sidebar; + ESourceSelector *selector; + ESource *primary; + GSList *list, *iter; + + /* XXX ESourceSelector should provide a function for this. */ + + cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + primary = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (primary != NULL); + + list = e_source_selector_get_selection (selector); + for (iter = list; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + + if (source == primary) + continue; + + e_source_selector_unselect_source (selector, source); + } + e_source_selector_free_selection (list); + + e_source_selector_select_source (selector, primary); +} + +static void +action_calendar_view_cb (GtkRadioAction *action, + GtkRadioAction *current, + ECalShellView *cal_shell_view) +{ + EShellView *shell_view; + GnomeCalendarViewType view_type; + const gchar *view_id; + + shell_view = E_SHELL_VIEW (cal_shell_view); + view_type = gtk_radio_action_get_current_value (action); + + switch (view_type) { + case GNOME_CAL_DAY_VIEW: + view_id = "Day_View"; + break; + + case GNOME_CAL_WORK_WEEK_VIEW: + view_id = "Work_Week_View"; + break; + + case GNOME_CAL_WEEK_VIEW: + view_id = "Week_View"; + break; + + case GNOME_CAL_MONTH_VIEW: + view_id = "Month_View"; + break; + + case GNOME_CAL_LIST_VIEW: + view_id = "List_View"; + break; + + default: + g_return_if_reached (); + } + + e_shell_view_set_view_id (shell_view, view_id); +} + +static void +action_event_all_day_new_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_clipboard_copy_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + e_cal_shell_content_copy_clipboard (cal_shell_content); +} + +static void +action_event_clipboard_cut_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + e_cal_shell_content_cut_clipboard (cal_shell_content); +} + +static void +action_event_clipboard_paste_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + e_cal_shell_content_paste_clipboard (cal_shell_content); +} + +static void +action_event_copy_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_delegate_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_delete_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + e_cal_shell_content_delete_selection (cal_shell_content); +} + +static void +action_event_delete_occurrence_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + e_cal_shell_content_delete_selected_occurrence (cal_shell_content); +} + +static void +action_event_delete_occurrence_all_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + + /* XXX Same as "event-delete". */ + cal_shell_content = cal_shell_view->priv->cal_shell_content; + e_cal_shell_content_delete_selection (cal_shell_content); +} + +static void +action_event_forward_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_meeting_new_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_move_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_new_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_occurrence_movable_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_open_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellContent *cal_shell_content; + GnomeCalendar *calendar; + GtkWidget *widget; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + widget = gnome_calendar_get_current_view_widget (calendar); + + e_calendar_view_open_event (E_CALENDAR_VIEW (widget)); +#endif +} + +static void +action_event_print_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_reply_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_reply_all_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_save_as_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_event_schedule_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +static void +action_gal_save_custom_view_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EShellView *shell_view; + GalViewInstance *view_instance; + + /* All shell views respond to the activation of this action, + * which is defined by EShellWindow. But only the currently + * active shell view proceeds with saving the custom view. */ + shell_view = E_SHELL_VIEW (cal_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + view_instance = e_cal_shell_content_get_view_instance (cal_shell_content); + gal_view_instance_save_as (view_instance); +} + +static void +action_search_execute_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + EShellView *shell_view; + + /* All shell views respond to the activation of this action, + * which is defined by EShellWindow. But only the currently + * active shell view proceeds with executing the search. */ + shell_view = E_SHELL_VIEW (cal_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + e_cal_shell_view_execute_search (cal_shell_view); +} + +static void +action_search_filter_cb (GtkRadioAction *action, + GtkRadioAction *current, + ECalShellView *cal_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + gtk_action_activate (ACTION (SEARCH_EXECUTE)); +} + +static GtkActionEntry calendar_entries[] = { + + { "calendar-copy", + GTK_STOCK_COPY, + N_("_Copy..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_copy_cb) }, + + { "calendar-delete", + GTK_STOCK_DELETE, + NULL, + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_delete_cb) }, + + { "calendar-go-back", + GTK_STOCK_GO_BACK, + N_("Previous"), + NULL, + N_("Go Back"), + G_CALLBACK (action_calendar_go_back_cb) }, + + { "calendar-go-forward", + GTK_STOCK_GO_FORWARD, + N_("Next"), + NULL, + N_("Go Forward"), + G_CALLBACK (action_calendar_go_forward_cb) }, + + { "calendar-go-today", + "go-today", + N_("Select _Today"), + "t", + N_("Select today"), + G_CALLBACK (action_calendar_go_today_cb) }, + + { "calendar-jump-to", + GTK_STOCK_JUMP_TO, + N_("Select _Date"), + "g", + N_("Select a specific date"), + G_CALLBACK (action_calendar_jump_to_cb) }, + + { "calendar-new", + "x-office-calendar", + N_("_New Calendar"), + NULL, + N_("Create a new calendar"), + G_CALLBACK (action_calendar_new_cb) }, + + { "calendar-properties", + GTK_STOCK_PROPERTIES, + NULL, + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_properties_cb) }, + + { "calendar-purge", + NULL, + N_("Purg_e"), + "e", + N_("Purge old appointments and meetings"), + G_CALLBACK (action_calendar_purge_cb) }, + + { "calendar-rename", + NULL, + N_("_Rename..."), + "F2", + N_("Rename the selected calendar"), + G_CALLBACK (action_calendar_rename_cb) }, + + { "calendar-select-one", + "stock_check-filled", + N_("Show _Only This Calendar"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_select_one_cb) }, + + { "event-clipboard-copy", + GTK_STOCK_COPY, + NULL, + NULL, + N_("Copy the selection"), + G_CALLBACK (action_event_clipboard_copy_cb) }, + + { "event-clipboard-cut", + GTK_STOCK_CUT, + NULL, + NULL, + N_("Cut the selection"), + G_CALLBACK (action_event_clipboard_cut_cb) }, + + { "event-clipboard-paste", + GTK_STOCK_PASTE, + NULL, + NULL, + N_("Paste the clipboard"), + G_CALLBACK (action_event_clipboard_paste_cb) }, + + { "event-copy", + NULL, + N_("Cop_y to Calendar..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_copy_cb) }, + + { "event-delegate", + NULL, + N_("_Delegate Meeting..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_delegate_cb) }, + + { "event-delete", + GTK_STOCK_DELETE, + NULL, + NULL, + N_("Delete the appointment"), + G_CALLBACK (action_event_delete_cb) }, + + { "event-delete-occurrence", + GTK_STOCK_DELETE, + N_("Delete This _Occurrence"), + NULL, + N_("Delete this occurrence"), + G_CALLBACK (action_event_delete_occurrence_cb) }, + + { "event-delete-occurrence-all", + GTK_STOCK_DELETE, + N_("Delete _All Occurrences"), + NULL, + N_("Delete all occurrences"), + G_CALLBACK (action_event_delete_occurrence_all_cb) }, + + { "event-all-day-new", + NULL, + N_("New All Day _Event..."), + NULL, + N_("Create a new all day event"), + G_CALLBACK (action_event_all_day_new_cb) }, + + { "event-forward", + "mail-forward", + N_("_Forward as iCalendar..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_forward_cb) }, + + { "event-meeting-new", + NULL, + N_("New _Meeting..."), + NULL, + N_("Create a new meeting"), + G_CALLBACK (action_event_meeting_new_cb) }, + + { "event-move", + NULL, + N_("Mo_ve to Calendar..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_move_cb) }, + + { "event-new", + NULL, + N_("New _Appointment..."), + NULL, + N_("Create a new appointment"), + G_CALLBACK (action_event_new_cb) }, + + { "event-occurrence-movable", + NULL, + N_("Make this Occurrence _Movable"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_occurrence_movable_cb) }, + + { "event-open", + NULL, + N_("_Open Appointment"), + "o", + N_("View the current appointment"), + G_CALLBACK (action_event_open_cb) }, + + { "event-reply", + "mail-reply-sender", + N_("_Reply"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_reply_cb) }, + + { "event-reply-all", + "mail-reply-all", + N_("Reply to _All"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_reply_all_cb) }, + + { "event-save-as", + GTK_STOCK_SAVE_AS, + NULL, + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_save_as_cb) }, + + { "event-schedule", + NULL, + N_("_Schedule Meeting..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_schedule_cb) }, + + /*** Menus ***/ + + { "calendar-actions-menu", + NULL, + N_("_Actions"), + NULL, + NULL, + NULL } +}; + +static EPopupActionEntry calendar_popup_entries[] = { + + /* FIXME No equivalent main menu items for the any of the calendar + * popup menu items and for many of the event popup menu items. + * This is an accessibility issue. */ + + { "calendar-popup-copy", + NULL, + "calendar-copy" }, + + { "calendar-popup-delete", + NULL, + "calendar-delete" }, + + { "calendar-popup-go-today", + NULL, + "calendar-go-today" }, + + { "calendar-popup-jump-to", + NULL, + "calendar-jump-to" }, + + { "calendar-popup-properties", + NULL, + "calendar-properties" }, + + { "calendar-popup-rename", + NULL, + "calendar-rename" }, + + { "calendar-popup-select-one", + NULL, + "calendar-select-one" }, + + { "event-popup-clipboard-copy", + NULL, + "event-clipboard-copy" }, + + { "event-popup-clipboard-cut", + NULL, + "event-clipboard-cut" }, + + { "event-popup-clipboard-paste", + NULL, + "event-clipboard-paste" }, + + { "event-popup-copy", + NULL, + "event-copy" }, + + { "event-popup-delegate", + NULL, + "event-delegate" }, + + { "event-popup-delete", + NULL, + "event-delete" }, + + { "event-popup-delete-occurrence", + NULL, + "event-delete-occurrence" }, + + { "event-popup-delete-occurrence-all", + NULL, + "event-delete-occurrence-all" }, + + { "event-popup-forward", + NULL, + "event-forward" }, + + { "event-popup-move", + NULL, + "event-move" }, + + { "event-popup-occurrence-movable", + NULL, + "event-occurrence-movable" }, + + { "event-popup-open", + NULL, + "event-open" }, + + { "event-popup-reply", + NULL, + "event-reply" }, + + { "event-popup-reply-all", + NULL, + "event-reply-all" }, + + { "event-popup-save-as", + NULL, + "event-save-as" }, + + { "event-popup-schedule", + NULL, + "event-schedule" } +}; + +static GtkRadioActionEntry calendar_view_entries[] = { + + { "calendar-view-day", + "view-calendar-day", + N_("Day"), + NULL, + N_("Show one day"), + GNOME_CAL_DAY_VIEW }, + + { "calendar-view-list", + "view-calendar-list", + N_("List"), + NULL, + N_("Show as list"), + GNOME_CAL_LIST_VIEW }, + + { "calendar-view-month", + "view-calendar-month", + N_("Month"), + NULL, + N_("Show one month"), + GNOME_CAL_MONTH_VIEW }, + + { "calendar-view-week", + "view-calendar-week", + N_("Week"), + NULL, + N_("Show one week"), + GNOME_CAL_WEEK_VIEW }, + + { "calendar-view-workweek", + "view-calendar-workweek", + N_("Work Week"), + NULL, + N_("Show one work week"), + GNOME_CAL_WORK_WEEK_VIEW } +}; + +static GtkRadioActionEntry calendar_filter_entries[] = { + + { "calendar-filter-active-appointments", + NULL, + N_("Active Appointements"), + NULL, + NULL, /* XXX Add a tooltip! */ + CALENDAR_FILTER_ACTIVE_APPOINTMENTS }, + + { "calendar-filter-any-category", + NULL, + N_("Any Category"), + NULL, + NULL, /* XXX Add a tooltip! */ + CALENDAR_FILTER_ANY_CATEGORY }, + + { "calendar-filter-next-7-days-appointments", + NULL, + N_("Next 7 Days' Appointments"), + NULL, + NULL, /* XXX Add a tooltip! */ + CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS }, + + { "calendar-filter-unmatched", + NULL, + N_("Unmatched"), + NULL, + NULL, /* XXX Add a tooltip! */ + CALENDAR_FILTER_UNMATCHED } +}; + +static GtkRadioActionEntry calendar_search_entries[] = { + + { "calendar-search-any-field-contains", + NULL, + N_("Any field contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + CALENDAR_SEARCH_ANY_FIELD_CONTAINS }, + + { "calendar-search-description-contains", + NULL, + N_("Description contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + CALENDAR_SEARCH_DESCRIPTION_CONTAINS }, + + { "calendar-search-summary-contains", + NULL, + N_("Summary contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + CALENDAR_SEARCH_SUMMARY_CONTAINS } +}; + +static GtkActionEntry lockdown_printing_entries[] = { + + { "calendar-print", + GTK_STOCK_PRINT, + NULL, + "p", + N_("Print this calendar"), + G_CALLBACK (action_calendar_print_cb) }, + + { "calendar-print-preview", + GTK_STOCK_PRINT_PREVIEW, + NULL, + NULL, + N_("Preview the calendar to be printed"), + G_CALLBACK (action_calendar_print_preview_cb) }, + + { "event-print", + GTK_STOCK_PRINT, + NULL, + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_event_print_cb) } +}; + +static EPopupActionEntry lockdown_printing_popup_entries[] = { + + { "event-popup-print", + NULL, + "event-print" } +}; + +void +e_cal_shell_view_actions_init (ECalShellView *cal_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkActionGroup *action_group; + GtkAction *action; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + /* Calendar Actions */ + action_group = ACTION_GROUP (CALENDAR); + gtk_action_group_add_actions ( + action_group, calendar_entries, + G_N_ELEMENTS (calendar_entries), cal_shell_view); + e_action_group_add_popup_actions ( + action_group, calendar_popup_entries, + G_N_ELEMENTS (calendar_popup_entries)); + gtk_action_group_add_radio_actions ( + action_group, calendar_view_entries, + G_N_ELEMENTS (calendar_view_entries), GNOME_CAL_DAY_VIEW, + G_CALLBACK (action_calendar_view_cb), cal_shell_view); + gtk_action_group_add_radio_actions ( + action_group, calendar_search_entries, + G_N_ELEMENTS (calendar_search_entries), + CALENDAR_SEARCH_SUMMARY_CONTAINS, + G_CALLBACK (action_calendar_search_cb), cal_shell_view); + + /* Lockdown Printing Actions */ + action_group = ACTION_GROUP (LOCKDOWN_PRINTING); + gtk_action_group_add_actions ( + action_group, lockdown_printing_entries, + G_N_ELEMENTS (lockdown_printing_entries), cal_shell_view); + e_action_group_add_popup_actions ( + action_group, lockdown_printing_popup_entries, + G_N_ELEMENTS (lockdown_printing_popup_entries)); + + /* Fine tuning. */ + + action = ACTION (CALENDAR_GO_TODAY); + g_object_set (action, "short-label", _("Today"), NULL); + + action = ACTION (CALENDAR_JUMP_TO); + g_object_set (action, "short-label", _("Go To"), NULL); + + action = ACTION (EVENT_DELETE); + g_object_set (action, "short-label", _("Delete"), NULL); + + g_signal_connect ( + ACTION (GAL_SAVE_CUSTOM_VIEW), "activate", + G_CALLBACK (action_gal_save_custom_view_cb), cal_shell_view); + + g_signal_connect ( + ACTION (SEARCH_EXECUTE), "activate", + G_CALLBACK (action_search_execute_cb), cal_shell_view); + + /* Initialize the memo and task pad actions. */ + e_cal_shell_view_memopad_actions_init (cal_shell_view); + e_cal_shell_view_taskpad_actions_init (cal_shell_view); +} + +void +e_cal_shell_view_update_search_filter (ECalShellView *cal_shell_view) +{ + EShellContent *shell_content; + EShellWindow *shell_window; + EShellView *shell_view; + GtkActionGroup *action_group; + GtkRadioAction *radio_action; + GList *list, *iter; + GSList *group; + gint ii; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + action_group = ACTION_GROUP (CALENDAR_FILTER); + e_action_group_remove_all_actions (action_group); + + /* Add the standard filter actions. */ + gtk_action_group_add_radio_actions ( + action_group, calendar_filter_entries, + G_N_ELEMENTS (calendar_filter_entries), + CALENDAR_FILTER_ANY_CATEGORY, + G_CALLBACK (action_search_filter_cb), + cal_shell_view); + + /* Retrieve the radio group from an action we just added. */ + list = gtk_action_group_list_actions (action_group); + radio_action = GTK_RADIO_ACTION (list->data); + group = gtk_radio_action_get_group (radio_action); + g_list_free (list); + + /* Build the category actions. */ + + list = e_categories_get_list (); + for (iter = list, ii = 0; iter != NULL; iter = iter->next, ii++) { + const gchar *category_name = iter->data; + const gchar *filename; + GtkAction *action; + gchar *action_name; + + action_name = g_strdup_printf ( + "calendar-filter-category-%d", ii); + radio_action = gtk_radio_action_new ( + action_name, category_name, NULL, NULL, ii); + g_free (action_name); + + /* Convert the category icon file to a themed icon name. */ + filename = e_categories_get_icon_file_for (category_name); + if (filename != NULL && *filename != '\0') { + gchar *basename; + gchar *cp; + + basename = g_path_get_basename (filename); + + /* Lose the file extension. */ + if ((cp = strrchr (basename, '.')) != NULL) + *cp = '\0'; + + g_object_set ( + radio_action, "icon-name", basename, NULL); + + g_free (basename); + } + + gtk_radio_action_set_group (radio_action, group); + group = gtk_radio_action_get_group (radio_action); + + /* The action group takes ownership of the action. */ + action = GTK_ACTION (radio_action); + gtk_action_group_add_action (action_group, action); + g_object_unref (radio_action); + } + g_list_free (list); + + /* Use any action in the group; doesn't matter which. */ + e_shell_content_set_filter_action (shell_content, radio_action); + + ii = CALENDAR_FILTER_UNMATCHED; + e_shell_content_add_filter_separator_after (shell_content, ii); + + ii = CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS; + e_shell_content_add_filter_separator_after (shell_content, ii); +} diff --git a/modules/calendar/e-cal-shell-view-actions.h b/modules/calendar/e-cal-shell-view-actions.h new file mode 100644 index 0000000000..b02906f179 --- /dev/null +++ b/modules/calendar/e-cal-shell-view-actions.h @@ -0,0 +1,153 @@ +/* + * e-cal-shell-view-actions.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_CAL_SHELL_VIEW_ACTIONS_H +#define E_CAL_SHELL_VIEW_ACTIONS_H + +#include + +/* Calendar Actions */ +#define E_SHELL_WINDOW_ACTION_CALENDAR_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-copy") +#define E_SHELL_WINDOW_ACTION_CALENDAR_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-delete") +#define E_SHELL_WINDOW_ACTION_CALENDAR_GO_BACK(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-go-back") +#define E_SHELL_WINDOW_ACTION_CALENDAR_GO_FORWARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-go-forward") +#define E_SHELL_WINDOW_ACTION_CALENDAR_GO_TODAY(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-go-today") +#define E_SHELL_WINDOW_ACTION_CALENDAR_JUMP_TO(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-jump-to") +#define E_SHELL_WINDOW_ACTION_CALENDAR_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-new") +#define E_SHELL_WINDOW_ACTION_CALENDAR_PRINT(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-print") +#define E_SHELL_WINDOW_ACTION_CALENDAR_PRINT_PREVIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-print-preview") +#define E_SHELL_WINDOW_ACTION_CALENDAR_PROPERTIES(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-properties") +#define E_SHELL_WINDOW_ACTION_CALENDAR_PURGE(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-purge") +#define E_SHELL_WINDOW_ACTION_CALENDAR_RENAME(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-rename") +#define E_SHELL_WINDOW_ACTION_CALENDAR_SELECT_ONE(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-select-one") +#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_DAY(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-view-day") +#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_LIST(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-view-list") +#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_MONTH(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-view-month") +#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_WEEK(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-view-week") +#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_WORKWEEK(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-view-workweek") + +/* Event Actions */ +#define E_SHELL_WINDOW_ACTION_EVENT_CLIPBOARD_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "event-clipboard-copy") +#define E_SHELL_WINDOW_ACTION_EVENT_CLIPBOARD_CUT(window) \ + E_SHELL_WINDOW_ACTION ((window), "event-clipboard-cut") +#define E_SHELL_WINDOW_ACTION_EVENT_CLIPBOARD_PASTE(window) \ + E_SHELL_WINDOW_ACTION ((window), "event-clipboard-paste") +#define E_SHELL_WINDOW_ACTION_EVENT_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "event-delete") +#define E_SHELL_WINDOW_ACTION_EVENT_DELETE_OCCURRENCE(window) \ + E_SHELL_WINDOW_ACTION ((window), "event-delete-occurrence") +#define E_SHELL_WINDOW_ACTION_EVENT_DELETE_OCCURRENCE_ALL(window) \ + E_SHELL_WINDOW_ACTION ((window), "event-delete-occurrence-all") +#define E_SHELL_WINDOW_ACTION_EVENT_OPEN(window) \ + E_SHELL_WINDOW_ACTION ((window), "event-open") + +/* Memo Pad Actions */ +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_CLIPBOARD_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-clipboard-copy") +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_CLIPBOARD_CUT(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-clipboard-cut") +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_CLIPBOARD_PASTE(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-clipboard-paste") +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-delete") +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_FORWARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-forward") +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-new") +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_OPEN(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-open") +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_OPEN_URL(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-open-url") +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_PRINT(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-print") +#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_SAVE_AS(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-save-as") + +/* Task Pad Actions */ +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_ASSIGN(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-assign") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_CLIPBOARD_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-clipboard-copy") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_CLIPBOARD_CUT(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-clipboard-cut") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_CLIPBOARD_PASTE(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-clipboard-paste") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-delete") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_FORWARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-forward") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_MARK_COMPLETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-mark-complete") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_MARK_INCOMPLETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-mark-incomplete") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-new") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_OPEN(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-open") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_OPEN_URL(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-open-url") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_PRINT(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-print") +#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_SAVE_AS(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-save-as") + +/* Calendar Query Actions */ +#define E_SHELL_WINDOW_ACTION_CALENDAR_FILTER_ACTIVE_APPOINTMENTS(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-filter-active-appointments") +#define E_SHELL_WINDOW_ACTION_CALENDAR_FILTER_ANY_CATEGORY(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-filter-any-category") +#define E_SHELL_WINDOW_ACTION_CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-filter-next-7-days-appointments") +#define E_SHELL_WINDOW_ACTION_CALENDAR_FILTER_UNMATCHED(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-filter-unmatched") +#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_ANY_FIELD_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-search-any-field-contains") +#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_DESCRIPTION_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-search-description-contains") +#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_SUMMARY_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "calendar-search-summary-contains") + +/* Action Groups */ +#define E_SHELL_WINDOW_ACTION_GROUP_CALENDAR(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "calendar") +#define E_SHELL_WINDOW_ACTION_GROUP_CALENDAR_FILTER(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "calendar-filter") + +#endif /* E_CAL_SHELL_VIEW_ACTIONS_H */ diff --git a/modules/calendar/e-cal-shell-view-memopad.c b/modules/calendar/e-cal-shell-view-memopad.c new file mode 100644 index 0000000000..ecee72d8b5 --- /dev/null +++ b/modules/calendar/e-cal-shell-view-memopad.c @@ -0,0 +1,526 @@ +/* + * e-cal-shell-view-memopad.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-view-private.h" + +/* Much of this file is based on e-memo-shell-view-actions.c. */ + +static void +action_calendar_memopad_clipboard_copy_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + e_memo_table_copy_clipboard (memo_table); +} + +static void +action_calendar_memopad_clipboard_cut_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + e_memo_table_cut_clipboard (memo_table); +} + +static void +action_calendar_memopad_clipboard_paste_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + e_memo_table_paste_clipboard (memo_table); +} + +static void +action_calendar_memopad_delete_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + e_cal_shell_view_memopad_set_status_message ( + cal_shell_view, _("Deleting selected memos..."), -1.0); + e_memo_table_delete_selected (memo_table); + e_cal_shell_view_memopad_set_status_message ( + cal_shell_view, NULL, -1.0); +} + +static void +action_calendar_memopad_forward_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + ECalComponent *comp; + icalcomponent *clone; + GSList *list; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only forward the first selected memo. */ + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_component_set_icalcomponent (comp, clone); + itip_send_comp ( + E_CAL_COMPONENT_METHOD_PUBLISH, comp, + comp_data->client, NULL, NULL, NULL, TRUE); + g_object_unref (comp); +} + +static void +action_calendar_memopad_new_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + ECal *client; + ECalComponent *comp; + CompEditor *editor; + GSList *list; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + client = comp_data->client; + editor = memo_editor_new (client, shell, COMP_EDITOR_NEW_ITEM); + comp = cal_comp_memo_new_with_defaults (client); + comp_editor_edit_comp (editor, comp); + + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (comp); + g_object_unref (client); +} + +static void +action_calendar_memopad_open_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + GSList *list; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only open the first selected memo. */ + e_cal_shell_view_memopad_open_memo (cal_shell_view, comp_data); +} + +static void +action_calendar_memopad_open_url_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + icalproperty *prop; + const gchar *uri; + GSList *list; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only open the URI of the first selected memo. */ + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_URL_PROPERTY); + g_return_if_fail (prop == NULL); + + uri = icalproperty_get_url (prop); + e_show_uri (GTK_WINDOW (shell_window), uri); +} + +static void +action_calendar_memopad_print_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + ECalComponent *comp; + icalcomponent *clone; + GtkPrintOperationAction print_action; + GSList *list; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only print the first selected memo. */ + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; + e_cal_component_set_icalcomponent (comp, clone); + print_comp (comp, comp_data->client, print_action); + g_object_unref (comp); +} + +static void +action_calendar_memopad_save_as_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + GSList *list; + gchar *filename; + gchar *string; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + filename = e_file_dialog_save (_("Save as..."), NULL); + if (filename == NULL) + return; + + /* XXX We only save the first selected memo. */ + string = e_cal_get_component_as_string ( + comp_data->client, comp_data->icalcomp); + if (string == NULL) { + g_warning ("Could not convert memo to a string."); + return; + } + + e_write_file_uri (filename, string); + + g_free (filename); + g_free (string); +} + +static GtkActionEntry calendar_memopad_entries[] = { + + { "calendar-memopad-clipboard-copy", + GTK_STOCK_COPY, + NULL, + NULL, + N_("Copy selected memo"), + G_CALLBACK (action_calendar_memopad_clipboard_copy_cb) }, + + { "calendar-memopad-clipboard-cut", + GTK_STOCK_CUT, + NULL, + NULL, + N_("Cut selected memo"), + G_CALLBACK (action_calendar_memopad_clipboard_cut_cb) }, + + { "calendar-memopad-clipboard-paste", + GTK_STOCK_PASTE, + NULL, + NULL, + N_("Paste memo from the clipboard"), + G_CALLBACK (action_calendar_memopad_clipboard_paste_cb) }, + + { "calendar-memopad-delete", + GTK_STOCK_DELETE, + N_("_Delete Memo"), + NULL, + N_("Delete selected memos"), + G_CALLBACK (action_calendar_memopad_delete_cb) }, + + { "calendar-memopad-forward", + "mail-forward", + N_("_Forward as iCalendar..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_memopad_forward_cb) }, + + { "calendar-memopad-new", + "stock_insert-note", + N_("New _Memo"), + NULL, + N_("Create a new memo"), + G_CALLBACK (action_calendar_memopad_new_cb) }, + + { "calendar-memopad-open", + GTK_STOCK_OPEN, + N_("_Open Memo"), + NULL, + N_("View the selected memo"), + G_CALLBACK (action_calendar_memopad_open_cb) }, + + { "calendar-memopad-open-url", + "applications-internet", + N_("Open _Web Page"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_memopad_open_url_cb) }, + + { "calendar-memopad-save-as", + GTK_STOCK_SAVE_AS, + NULL, + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_memopad_save_as_cb) } +}; + +static GtkActionEntry lockdown_printing_entries[] = { + + { "calendar-memopad-print", + GTK_STOCK_PRINT, + NULL, + NULL, + N_("Print the selected memo"), + G_CALLBACK (action_calendar_memopad_print_cb) } +}; + +void +e_cal_shell_view_memopad_actions_init (ECalShellView *cal_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkActionGroup *action_group; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + /* Calendar Actions */ + action_group = ACTION_GROUP (CALENDAR); + gtk_action_group_add_actions ( + action_group, calendar_memopad_entries, + G_N_ELEMENTS (calendar_memopad_entries), cal_shell_view); + + /* Lockdown Printing Actions */ + action_group = ACTION_GROUP (LOCKDOWN_PRINTING); + gtk_action_group_add_actions ( + action_group, lockdown_printing_entries, + G_N_ELEMENTS (lockdown_printing_entries), cal_shell_view); +} + +void +e_cal_shell_view_memopad_actions_update (ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EShellWindow *shell_window; + EShellView *shell_view; + EMemoTable *memo_table; + ETable *table; + GtkAction *action; + GSList *list, *iter; + const gchar *label; + gboolean editable = TRUE; + gboolean has_url = FALSE; + gboolean sensitive; + gint n_selected; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + + table = e_memo_table_get_table (memo_table); + n_selected = e_table_selected_count (table); + + list = e_memo_table_get_selected (memo_table); + for (iter = list; iter != NULL; iter = iter->next) { + ECalModelComponent *comp_data = iter->data; + icalproperty *prop; + gboolean read_only; + + e_cal_is_read_only (comp_data->client, &read_only, NULL); + editable &= !read_only; + + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_URL_PROPERTY); + has_url |= (prop != NULL); + } + g_slist_free (list); + + action = ACTION (CALENDAR_MEMOPAD_CLIPBOARD_COPY); + sensitive = (n_selected > 0); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_MEMOPAD_CLIPBOARD_CUT); + sensitive = (n_selected > 0) && editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_MEMOPAD_CLIPBOARD_PASTE); + sensitive = editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_MEMOPAD_DELETE); + sensitive = (n_selected > 0) && editable; + gtk_action_set_sensitive (action, sensitive); + label = ngettext ("Delete Memo", "Delete Memos", n_selected); + g_object_set (action, "label", label, NULL); + + action = ACTION (CALENDAR_MEMOPAD_FORWARD); + sensitive = (n_selected == 1); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_MEMOPAD_OPEN); + sensitive = (n_selected == 1); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_MEMOPAD_OPEN_URL); + sensitive = (n_selected == 1) && has_url; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_MEMOPAD_PRINT); + sensitive = (n_selected == 1); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_MEMOPAD_SAVE_AS); + sensitive = (n_selected == 1); + gtk_action_set_sensitive (action, sensitive); +} + +void +e_cal_shell_view_memopad_open_memo (ECalShellView *cal_shell_view, + ECalModelComponent *comp_data) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + CompEditor *editor; + CompEditorFlags flags = 0; + ECalComponent *comp; + icalcomponent *clone; + const gchar *uid; + + g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); + g_return_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data)); + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + + uid = icalcomponent_get_uid (comp_data->icalcomp); + editor = comp_editor_find_instance (uid); + + if (editor != NULL) + goto exit; + + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_component_set_icalcomponent (comp, clone); + + if (e_cal_component_has_organizer (comp)) + flags |= COMP_EDITOR_IS_SHARED; + + if (itip_organizer_is_user (comp, comp_data->client)) + flags |= COMP_EDITOR_USER_ORG; + + editor = memo_editor_new (comp_data->client, shell, flags); + comp_editor_edit_comp (editor, comp); + + g_object_unref (comp); + +exit: + gtk_window_present (GTK_WINDOW (editor)); +} + +void +e_cal_shell_view_memopad_set_status_message (ECalShellView *cal_shell_view, + const gchar *status_message, + gdouble percent) +{ + EActivity *activity; + EShellView *shell_view; + EShellBackend *shell_backend; + + g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + activity = cal_shell_view->priv->memopad_activity; + + if (status_message == NULL || *status_message == '\0') { + if (activity != NULL) { + e_activity_complete (activity); + g_object_unref (activity); + activity = NULL; + } + + } else if (activity == NULL) { + activity = e_activity_new (status_message); + e_activity_set_percent (activity, percent); + e_shell_backend_add_activity (shell_backend, activity); + + } else { + e_activity_set_percent (activity, percent); + e_activity_set_primary_text (activity, status_message); + } + + cal_shell_view->priv->memopad_activity = activity; +} diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c new file mode 100644 index 0000000000..f681a2c2f3 --- /dev/null +++ b/modules/calendar/e-cal-shell-view-private.c @@ -0,0 +1,650 @@ +/* + * e-cal-shell-view-private.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-view-private.h" + +#include "calendar/gui/calendar-view-factory.h" +#include "widgets/menus/gal-view-factory-etable.h" + +static void +cal_shell_view_process_completed_tasks (ECalShellView *cal_shell_view, + gboolean config_changed) +{ +#if 0 + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + e_calendar_table_process_completed_tasks ( + task_table, clients, config_changed); +#endif +} + +static void +cal_shell_view_config_timezone_changed_cb (GConfClient *client, + guint id, + GConfEntry *entry, + gpointer user_data) +{ + ECalShellView *cal_shell_view = user_data; + + e_cal_shell_view_update_timezone (cal_shell_view); +} + +static struct tm +cal_shell_view_get_current_time (ECalendarItem *calitem, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + struct icaltimetype tt; + icaltimezone *timezone; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + timezone = e_cal_shell_content_get_timezone (cal_shell_content); + + tt = icaltime_from_timet_with_zone (time (NULL), FALSE, timezone); + + return icaltimetype_to_tm (&tt); +} + +static void +cal_shell_view_mini_calendar_date_range_changed_cb (ECalShellView *cal_shell_view, + ECalendarItem *calitem) +{ + /* FIXME gnome-calendar.c calls update_query() here. */ +} + +static void +cal_shell_view_mini_calendar_selection_changed_cb (ECalShellView *cal_shell_view, + ECalendarItem *calitem) +{ + /* FIXME */ +} + +static void +cal_shell_view_mini_calendar_scroll_event_cb (ECalShellView *cal_shell_view, + GdkEventScroll *event, + ECalendar *mini_calendar) +{ + ECalendarItem *calitem; + GDate start_date, end_date; + + calitem = mini_calendar->calitem; + if (!e_calendar_item_get_selection (calitem, &start_date, &end_date)) + return; + + switch (event->direction) { + case GDK_SCROLL_UP: + g_date_subtract_months (&start_date, 1); + g_date_subtract_months (&end_date, 1); + break; + + case GDK_SCROLL_DOWN: + g_date_add_months (&start_date, 1); + g_date_add_months (&end_date, 1); + break; + + default: + g_return_if_reached (); + } + + /* XXX Does ECalendarItem emit a signal for this? If so, maybe + * we could move this handler into ECalShellSidebar. */ + e_calendar_item_set_selection (calitem, &start_date, &end_date); + + cal_shell_view_mini_calendar_date_range_changed_cb ( + cal_shell_view, calitem); +} + +static gboolean +cal_shell_view_selector_popup_event_cb (EShellView *shell_view, + ESource *primary_source, + GdkEventButton *event) +{ + const gchar *widget_path; + + widget_path = "/calendar-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); + + return TRUE; +} + +static void +cal_shell_view_memopad_popup_event_cb (EShellView *shell_view, + GdkEventButton *event) +{ + const gchar *widget_path; + + widget_path = "/calendar-memopad-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); +} + +static void +cal_shell_view_taskpad_popup_event_cb (EShellView *shell_view, + GdkEventButton *event) +{ + const gchar *widget_path; + + widget_path = "/calendar-taskpad-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); +} + +static void +cal_shell_view_load_view_collection (EShellViewClass *shell_view_class) +{ + GalViewCollection *collection; + GalViewFactory *factory; + ETableSpecification *spec; + const gchar *base_dir; + gchar *filename; + + collection = shell_view_class->view_collection; + + base_dir = EVOLUTION_ETSPECDIR; + spec = e_table_specification_new (); + filename = g_build_filename (base_dir, ETSPEC_FILENAME, NULL); + if (!e_table_specification_load_from_file (spec, filename)) + g_critical ("Unable to load ETable specification file " + "for calendars"); + g_free (filename); + + factory = calendar_view_factory_new (GNOME_CAL_DAY_VIEW); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + + factory = calendar_view_factory_new (GNOME_CAL_WORK_WEEK_VIEW); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + + factory = calendar_view_factory_new (GNOME_CAL_WEEK_VIEW); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + + factory = calendar_view_factory_new (GNOME_CAL_MONTH_VIEW); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + + factory = gal_view_factory_etable_new (spec); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + g_object_unref (spec); + + gal_view_collection_load (collection); +} + +static void +cal_shell_view_notify_view_id_cb (ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + GalViewInstance *view_instance; + const gchar *view_id; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + view_instance = + e_cal_shell_content_get_view_instance (cal_shell_content); + view_id = e_shell_view_get_view_id (E_SHELL_VIEW (cal_shell_view)); + + /* A NULL view ID implies we're in a custom view. But you can + * only get to a custom view via the "Define Views" dialog, which + * would have already modified the view instance appropriately. + * Furthermore, there's no way to refer to a custom view by ID + * anyway, since custom views have no IDs. */ + if (view_id == NULL) + return; + + gal_view_instance_set_current_view_id (view_instance, view_id); +} + +void +e_cal_shell_view_private_init (ECalShellView *cal_shell_view, + EShellViewClass *shell_view_class) +{ + if (!gal_view_collection_loaded (shell_view_class->view_collection)) + cal_shell_view_load_view_collection (shell_view_class); + + g_signal_connect ( + cal_shell_view, "notify::view-id", + G_CALLBACK (cal_shell_view_notify_view_id_cb), NULL); +} + +void +e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) +{ + ECalShellViewPrivate *priv = cal_shell_view->priv; + ECalShellContent *cal_shell_content; + ECalShellSidebar *cal_shell_sidebar; + EShellBackend *shell_backend; + EShellContent *shell_content; + EShellSidebar *shell_sidebar; + EShellWindow *shell_window; + EShellView *shell_view; + GnomeCalendar *calendar; + ECalendar *mini_calendar; + EMemoTable *memo_table; + ECalendarTable *task_table; + ESourceSelector *selector; + guint id; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + e_shell_window_add_action_group (shell_window, "calendar"); + e_shell_window_add_action_group (shell_window, "calendar-filter"); + + /* Cache these to avoid lots of awkward casting. */ + priv->cal_shell_backend = g_object_ref (shell_backend); + priv->cal_shell_content = g_object_ref (shell_content); + priv->cal_shell_sidebar = g_object_ref (shell_sidebar); + + cal_shell_content = E_CAL_SHELL_CONTENT (shell_content); + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + cal_shell_sidebar = E_CAL_SHELL_SIDEBAR (shell_sidebar); + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + mini_calendar = e_cal_shell_sidebar_get_mini_calendar (cal_shell_sidebar); + + e_calendar_item_set_get_time_callback ( + mini_calendar->calitem, (ECalendarItemGetTimeCallback) + cal_shell_view_get_current_time, cal_shell_view, NULL); + +#if 0 /* KILL-BONOBO */ + g_signal_connect_swapped ( + calendar, "dates-shown-changed", + G_CALLBACK (e_cal_shell_view_update_sidebar), + cal_shell_view); +#endif + + g_signal_connect_swapped ( + mini_calendar, "scroll-event", + G_CALLBACK (cal_shell_view_mini_calendar_scroll_event_cb), + cal_shell_view); + + g_signal_connect_swapped ( + mini_calendar->calitem, "date-range-changed", + G_CALLBACK (cal_shell_view_mini_calendar_date_range_changed_cb), + cal_shell_view); + + g_signal_connect_swapped ( + mini_calendar->calitem, "selection-changed", + G_CALLBACK (cal_shell_view_mini_calendar_selection_changed_cb), + cal_shell_view); + + g_signal_connect_swapped ( + selector, "popup-event", + G_CALLBACK (cal_shell_view_selector_popup_event_cb), + cal_shell_view); + + g_signal_connect_swapped ( + memo_table, "popup-event", + G_CALLBACK (cal_shell_view_memopad_popup_event_cb), + cal_shell_view); + + g_signal_connect_swapped ( + memo_table, "status-message", + G_CALLBACK (e_cal_shell_view_memopad_set_status_message), + cal_shell_view); + + g_signal_connect_swapped ( + task_table, "popup-event", + G_CALLBACK (cal_shell_view_taskpad_popup_event_cb), + cal_shell_view); + + g_signal_connect_swapped ( + task_table, "status-message", + G_CALLBACK (e_cal_shell_view_taskpad_set_status_message), + cal_shell_view); + + g_signal_connect_swapped ( + e_memo_table_get_table (memo_table), "selection-change", + G_CALLBACK (e_cal_shell_view_memopad_actions_update), + cal_shell_view); + + g_signal_connect_swapped ( + e_calendar_table_get_table (task_table), "selection-change", + G_CALLBACK (e_cal_shell_view_taskpad_actions_update), + cal_shell_view); + + e_categories_register_change_listener ( + G_CALLBACK (e_cal_shell_view_update_search_filter), + cal_shell_view); + + /* Listen for configuration changes. */ + + /* Timezone */ + id = calendar_config_add_notification_timezone ( + cal_shell_view_config_timezone_changed_cb, cal_shell_view); + priv->notifications = g_list_prepend ( + priv->notifications, GUINT_TO_POINTER (id)); + + e_cal_shell_view_actions_init (cal_shell_view); + e_cal_shell_view_update_sidebar (cal_shell_view); + e_cal_shell_view_update_search_filter (cal_shell_view); + e_cal_shell_view_update_timezone (cal_shell_view); +} + +void +e_cal_shell_view_private_dispose (ECalShellView *cal_shell_view) +{ + ECalShellViewPrivate *priv = cal_shell_view->priv; + GList *iter; + + DISPOSE (priv->cal_shell_backend); + DISPOSE (priv->cal_shell_content); + DISPOSE (priv->cal_shell_sidebar); + + if (priv->calendar_activity != NULL) { + /* XXX Activity is not cancellable. */ + e_activity_complete (priv->calendar_activity); + g_object_unref (priv->calendar_activity); + priv->calendar_activity = NULL; + } + + if (priv->memopad_activity != NULL) { + /* XXX Activity is not cancellable. */ + e_activity_complete (priv->memopad_activity); + g_object_unref (priv->memopad_activity); + priv->memopad_activity = NULL; + } + + if (priv->taskpad_activity != NULL) { + /* XXX Activity is not cancellable. */ + e_activity_complete (priv->taskpad_activity); + g_object_unref (priv->taskpad_activity); + priv->taskpad_activity = NULL; + } + + for (iter = priv->notifications; iter != NULL; iter = iter->next) { + guint notification_id = GPOINTER_TO_UINT (iter->data); + calendar_config_remove_notification (notification_id); + } + g_list_free (priv->notifications); + priv->notifications = NULL; +} + +void +e_cal_shell_view_private_finalize (ECalShellView *cal_shell_view) +{ + /* XXX Nothing to do? */ +} + +void +e_cal_shell_view_execute_search (ECalShellView *cal_shell_view) +{ + /* FIXME */ +} + +void +e_cal_shell_view_open_event (ECalShellView *cal_shell_view, + ECalModelComponent *comp_data) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + CompEditor *editor; + CompEditorFlags flags = 0; + ECalComponent *comp; + icalcomponent *clone; + icalproperty *prop; + const gchar *uid; + + g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); + g_return_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data)); + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + + uid = icalcomponent_get_uid (comp_data->icalcomp); + editor = comp_editor_find_instance (uid); + + if (editor != NULL) + goto exit; + + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_component_set_icalcomponent (comp, clone); + + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_ATTENDEE_PROPERTY); + if (prop != NULL) + flags |= COMP_EDITOR_MEETING; + + if (itip_organizer_is_user (comp, comp_data->client)) + flags |= COMP_EDITOR_USER_ORG; + + if (itip_sentby_is_user (comp, comp_data->client)) + flags |= COMP_EDITOR_USER_ORG; + + if (!e_cal_component_has_attendees (comp)) + flags |= COMP_EDITOR_USER_ORG; + + editor = event_editor_new (comp_data->client, shell, flags); + comp_editor_edit_comp (editor, comp); + + g_object_ref (comp); + +exit: + gtk_window_present (GTK_WINDOW (editor)); +} + +void +e_cal_shell_view_set_status_message (ECalShellView *cal_shell_view, + const gchar *status_message, + gdouble percent) +{ + EActivity *activity; + EShellView *shell_view; + EShellBackend *shell_backend; + + g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + activity = cal_shell_view->priv->calendar_activity; + + if (status_message == NULL || *status_message == '\0') { + if (activity != NULL) { + e_activity_complete (activity); + g_object_unref (activity); + activity = NULL; + } + + } else if (activity == NULL) { + activity = e_activity_new (status_message); + e_activity_set_percent (activity, percent); + e_shell_backend_add_activity (shell_backend, activity); + + } else { + e_activity_set_percent (activity, percent); + e_activity_set_primary_text (activity, status_message); + } + + cal_shell_view->priv->calendar_activity = activity; +} + +void +e_cal_shell_view_update_sidebar (ECalShellView *cal_shell_view) +{ +#if 0 /* KILL-BONOBO */ + EShellView *shell_view; + EShellSidebar *shell_sidebar; + GnomeCalendar *calendar; + GnomeCalendarViewType view; + time_t start_time, end_time; + struct tm start_tm, end_tm; + struct icaltimetype start_tt, end_tt; + icaltimezone *timezone; + gchar buffer[512]; + gchar end_buffer[512]; + + g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + + calendar = e_cal_shell_view_get_calendar (cal_shell_view); + + gnome_calendar_get_visible_time_range ( + calendar, &start_time, &end_time); + timezone = gnome_calendar_get_timezone (calendar); + view = gnome_calendar_get_view (calendar); + + start_tt = icaltime_from_timet_with_zone (start_time, FALSE, timezone); + start_tm.tm_year = start_tt.year - 1900; + start_tm.tm_mon = start_tt.month - 1; + start_tm.tm_mday = start_tt.day; + start_tm.tm_hour = start_tt.hour; + start_tm.tm_min = start_tt.minute; + start_tm.tm_sec = start_tt.second; + start_tm.tm_isdst = -1; + start_tm.tm_wday = time_day_of_week ( + start_tt.day, start_tt.month - 1, start_tt.year); + + /* Subtract one from end_time so we don't get an extra day. */ + end_tt = icaltime_from_timet_with_zone (end_time - 1, FALSE, timezone); + end_tm.tm_year = end_tt.year - 1900; + end_tm.tm_mon = end_tt.month - 1; + end_tm.tm_mday = end_tt.day; + end_tm.tm_hour = end_tt.hour; + end_tm.tm_min = end_tt.minute; + end_tm.tm_sec = end_tt.second; + end_tm.tm_isdst = -1; + end_tm.tm_wday = time_day_of_week ( + end_tt.day, end_tt.month - 1, end_tt.year); + + switch (view) { + case GNOME_CAL_DAY_VIEW: + case GNOME_CAL_WORK_WEEK_VIEW: + case GNOME_CAL_WEEK_VIEW: + if (start_tm.tm_year == end_tm.tm_year && + start_tm.tm_mon == end_tm.tm_mon && + start_tm.tm_mday == end_tm.tm_mday) { + e_utf8_strftime ( + buffer, sizeof (buffer), + _("%A %d %b %Y"), &start_tm); + } else if (start_tm.tm_year == end_tm.tm_year) { + e_utf8_strftime ( + buffer, sizeof (buffer), + _("%a %d %b"), &start_tm); + e_utf8_strftime ( + end_buffer, sizeof (end_buffer), + _("%a %d %b %Y"), &end_tm); + strcat (buffer, " - "); + strcat (buffer, end_buffer); + } else { + e_utf8_strftime ( + buffer, sizeof (buffer), + _("%a %d %b %Y"), &start_tm); + e_utf8_strftime ( + end_buffer, sizeof (end_buffer), + _("%a %d %b %Y"), &end_tm); + strcat (buffer, " - "); + strcat (buffer, end_buffer); + } + break; + + case GNOME_CAL_MONTH_VIEW: + case GNOME_CAL_LIST_VIEW: + if (start_tm.tm_year == end_tm.tm_year) { + if (start_tm.tm_mon == end_tm.tm_mon) { + e_utf8_strftime ( + buffer, + sizeof (buffer), + "%d", &start_tm); + e_utf8_strftime ( + end_buffer, + sizeof (end_buffer), + _("%d %b %Y"), &end_tm); + strcat (buffer, " - "); + strcat (buffer, end_buffer); + } else { + e_utf8_strftime ( + buffer, + sizeof (buffer), + _("%d %b"), &start_tm); + e_utf8_strftime ( + end_buffer, + sizeof (end_buffer), + _("%d %b %Y"), &end_tm); + strcat (buffer, " - "); + strcat (buffer, end_buffer); + } + } else { + e_utf8_strftime ( + buffer, sizeof (buffer), + _("%d %b %Y"), &start_tm); + e_utf8_strftime ( + end_buffer, sizeof (end_buffer), + _("%d %b %Y"), &end_tm); + strcat (buffer, " - "); + strcat (buffer, end_buffer); + } + break; + + default: + g_return_if_reached (); + } + + e_shell_sidebar_set_secondary_text (shell_sidebar, buffer); +#endif +} + +void +e_cal_shell_view_update_timezone (ECalShellView *cal_shell_view) +{ +#if 0 + ECalShellContent *cal_shell_content; + ECalShellSidebar *cal_shell_sidebar; + GnomeCalendarViewType view_type; + ECalendarView *calendar_view; + icaltimezone *timezone; + GList *clients, *iter; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + view_type = e_cal_shell_content_get_current_view (cal_shell_content); + calendar_view = e_cal_shell_content_get_calendar_view ( + cal_shell_content, view_type); + + cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; + clients = e_cal_shell_sidebar_get_clients (cal_shell_sidebar); + + timezone = calendar_config_get_icaltimezone (); + + for (iter = clients; iter != NULL; iter = iter->next) { + ECal *client = iter->data; + + if (e_cal_get_load_state (client) == E_CAL_LOAD_LOADED) + e_cal_set_default_timezone (client, timezone, NULL); + } + + e_calendar_view_set_icaltimezone (calendar_view, timezone); + + g_list_free (clients); +#endif +} diff --git a/modules/calendar/e-cal-shell-view-private.h b/modules/calendar/e-cal-shell-view-private.h new file mode 100644 index 0000000000..8308e0bf7f --- /dev/null +++ b/modules/calendar/e-cal-shell-view-private.h @@ -0,0 +1,170 @@ +/* + * e-cal-shell-view-private.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_CAL_SHELL_VIEW_PRIVATE_H +#define E_CAL_SHELL_VIEW_PRIVATE_H + +#include "e-cal-shell-view.h" + +#include +#include +#include +#include +#include + +#include "e-util/e-util.h" +#include "e-util/e-dialog-utils.h" +#include "widgets/misc/e-popup-action.h" + +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/comp-util.h" +#include "calendar/gui/e-cal-list-view.h" +#include "calendar/gui/e-cal-model-tasks.h" +#include "calendar/gui/e-calendar-view.h" +#include "calendar/gui/gnome-cal.h" +/*#include "calendar/gui/goto.h"*/ +#include "calendar/gui/print.h" +#include "calendar/gui/dialogs/copy-source-dialog.h" +#include "calendar/gui/dialogs/event-editor.h" +#include "calendar/gui/dialogs/memo-editor.h" +#include "calendar/gui/dialogs/task-editor.h" + +#include "e-cal-shell-backend.h" +#include "e-cal-shell-content.h" +#include "e-cal-shell-sidebar.h" +#include "e-cal-shell-view-actions.h" + +#define E_CAL_SHELL_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_CAL_SHELL_VIEW, ECalShellViewPrivate)) + +/* Shorthand, requires a variable named "shell_window". */ +#define ACTION(name) \ + (E_SHELL_WINDOW_ACTION_##name (shell_window)) +#define ACTION_GROUP(name) \ + (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) + +/* For use in dispose() methods. */ +#define DISPOSE(obj) \ + G_STMT_START { \ + if ((obj) != NULL) { g_object_unref (obj); (obj) = NULL; } \ + } G_STMT_END + +/* ETable Specifications */ +#define ETSPEC_FILENAME "e-calendar-table.etspec" + +G_BEGIN_DECLS + +/* Filter items are displayed in ascending order. + * Non-negative values are reserved for categories. */ +enum { + CALENDAR_FILTER_ANY_CATEGORY = -4, + CALENDAR_FILTER_UNMATCHED = -3, + CALENDAR_FILTER_ACTIVE_APPOINTMENTS = -2, + CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS = -1 +}; + +/* Search items are displayed in ascending order. */ +enum { + CALENDAR_SEARCH_SUMMARY_CONTAINS, + CALENDAR_SEARCH_DESCRIPTION_CONTAINS, + CALENDAR_SEARCH_ANY_FIELD_CONTAINS +}; + +struct _ECalShellViewPrivate { + + /* These are just for convenience. */ + ECalShellBackend *cal_shell_backend; + ECalShellContent *cal_shell_content; + ECalShellSidebar *cal_shell_sidebar; + + /* The last time explicitly selected by the user. */ + time_t base_view_time; + + EActivity *calendar_activity; + EActivity *memopad_activity; + EActivity *taskpad_activity; + + /* GConf notification IDs */ + GList *notifications; +}; + +void e_cal_shell_view_private_init + (ECalShellView *cal_shell_view, + EShellViewClass *shell_view_class); +void e_cal_shell_view_private_constructed + (ECalShellView *cal_shell_view); +void e_cal_shell_view_private_dispose + (ECalShellView *cal_shell_view); +void e_cal_shell_view_private_finalize + (ECalShellView *cal_shell_view); + +/* Private Utilities */ + +void e_cal_shell_view_actions_init + (ECalShellView *cal_shell_view); +void e_cal_shell_view_execute_search + (ECalShellView *cal_shell_view); +void e_cal_shell_view_open_event + (ECalShellView *cal_shell_view, + ECalModelComponent *comp_data); +void e_cal_shell_view_set_status_message + (ECalShellView *cal_shell_view, + const gchar *status_message, + gdouble percent); +void e_cal_shell_view_update_sidebar + (ECalShellView *cal_shell_view); +void e_cal_shell_view_update_search_filter + (ECalShellView *cal_shell_view); +void e_cal_shell_view_update_timezone + (ECalShellView *cal_shell_view); + +/* Memo Pad Utilities */ + +void e_cal_shell_view_memopad_actions_init + (ECalShellView *cal_shell_view); +void e_cal_shell_view_memopad_actions_update + (ECalShellView *cal_shell_view); +void e_cal_shell_view_memopad_open_memo + (ECalShellView *cal_shell_view, + ECalModelComponent *comp_data); +void e_cal_shell_view_memopad_set_status_message + (ECalShellView *cal_shell_view, + const gchar *status_message, + gdouble percent); + +/* Task Pad Utilities */ + +void e_cal_shell_view_taskpad_actions_init + (ECalShellView *cal_shell_view); +void e_cal_shell_view_taskpad_actions_update + (ECalShellView *cal_shell_view); +void e_cal_shell_view_taskpad_open_task + (ECalShellView *cal_shell_view, + ECalModelComponent *comp_data); +void e_cal_shell_view_taskpad_set_status_message + (ECalShellView *cal_shell_view, + const gchar *status_message, + gdouble percent); + +G_END_DECLS + +#endif /* E_CAL_SHELL_VIEW_PRIVATE_H */ diff --git a/modules/calendar/e-cal-shell-view-taskpad.c b/modules/calendar/e-cal-shell-view-taskpad.c new file mode 100644 index 0000000000..bdd136b6f7 --- /dev/null +++ b/modules/calendar/e-cal-shell-view-taskpad.c @@ -0,0 +1,654 @@ +/* + * e-cal-shell-view-taskpad.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-view-private.h" + +/* Much of this file is based on e-task-shell-view-actions.c. */ + +static void +action_calendar_taskpad_assign_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + GSList *list; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only open the first selected task. */ + e_cal_shell_view_taskpad_open_task (cal_shell_view, comp_data); + + /* FIXME Need to actually assign the task. */ +} + +static void +action_calendar_taskpad_clipboard_copy_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + e_calendar_table_copy_clipboard (task_table); +} + +static void +action_calendar_taskpad_clipboard_cut_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + e_calendar_table_cut_clipboard (task_table); +} + +static void +action_calendar_taskpad_clipboard_paste_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + e_calendar_table_paste_clipboard (task_table); +} + +static void +action_calendar_taskpad_delete_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + e_cal_shell_view_taskpad_set_status_message ( + cal_shell_view, _("Deleting selected tasks..."), -1.0); + e_calendar_table_delete_selected (task_table); + e_cal_shell_view_taskpad_set_status_message ( + cal_shell_view, NULL, -1.0); +} + +static void +action_calendar_taskpad_forward_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + ECalComponent *comp; + icalcomponent *clone; + GSList *list; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only forward the first selected task. */ + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_component_set_icalcomponent (comp, clone); + itip_send_comp ( + E_CAL_COMPONENT_METHOD_PUBLISH, comp, + comp_data->client, NULL, NULL, NULL, TRUE); + g_object_unref (comp); +} + +static void +action_calendar_taskpad_mark_complete_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + ECalModel *model; + GSList *list, *iter; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + list = e_calendar_table_get_selected (task_table); + model = e_calendar_table_get_model (task_table); + + for (iter = list; iter != NULL; iter = iter->next) { + ECalModelComponent *comp_data = iter->data; + e_cal_model_tasks_mark_comp_complete ( + E_CAL_MODEL_TASKS (model), comp_data); + } + + g_slist_free (list); +} + +static void +action_calendar_taskpad_mark_incomplete_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + ECalModel *model; + GSList *list, *iter; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + list = e_calendar_table_get_selected (task_table); + model = e_calendar_table_get_model (task_table); + + for (iter = list; iter != NULL; iter = iter->next) { + ECalModelComponent *comp_data = iter->data; + e_cal_model_tasks_mark_comp_incomplete ( + E_CAL_MODEL_TASKS (model), comp_data); + } + + g_slist_free (list); +} + +static void +action_calendar_taskpad_new_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + ECal *client; + ECalComponent *comp; + CompEditor *editor; + GSList *list; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + client = comp_data->client; + editor = task_editor_new (client, shell, COMP_EDITOR_NEW_ITEM); + comp = cal_comp_task_new_with_defaults (client); + comp_editor_edit_comp (editor, comp); + + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (comp); + g_object_unref (client); +} + +static void +action_calendar_taskpad_open_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + GSList *list; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only open the first selected task. */ + e_cal_shell_view_taskpad_open_task (cal_shell_view, comp_data); +} + +static void +action_calendar_taskpad_open_url_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + icalproperty *prop; + const gchar *uri; + GSList *list; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + + /* XXX We only open the URI of the first selected task. */ + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_URL_PROPERTY); + g_return_if_fail (prop == NULL); + + uri = icalproperty_get_url (prop); + e_show_uri (GTK_WINDOW (shell_window), uri); +} + +static void +action_calendar_taskpad_print_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + ECalComponent *comp; + icalcomponent *clone; + GtkPrintOperationAction print_action; + GSList *list; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only print the first selected task. */ + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; + e_cal_component_set_icalcomponent (comp, clone); + print_comp (comp, comp_data->client, print_action); + g_object_unref (comp); +} + +static void +action_calendar_taskpad_save_as_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + GSList *list; + gchar *filename; + gchar *string; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + filename = e_file_dialog_save (_("Save as..."), NULL); + if (filename == NULL) + return; + + string = e_cal_get_component_as_string ( + comp_data->client, comp_data->icalcomp); + if (string == NULL) { + g_warning ("Could not convert task to a string"); + return; + } + + e_write_file_uri (filename, string); + + g_free (filename); + g_free (string); +} + +static GtkActionEntry calendar_taskpad_entries[] = { + + { "calendar-taskpad-assign", + NULL, + N_("_Assign Task"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_taskpad_assign_cb) }, + + { "calendar-taskpad-clipboard-copy", + GTK_STOCK_COPY, + NULL, + NULL, + N_("Copy selected tasks"), + G_CALLBACK (action_calendar_taskpad_clipboard_copy_cb) }, + + { "calendar-taskpad-clipboard-cut", + GTK_STOCK_CUT, + NULL, + NULL, + N_("Cut selected tasks"), + G_CALLBACK (action_calendar_taskpad_clipboard_cut_cb) }, + + { "calendar-taskpad-clipboard-paste", + GTK_STOCK_PASTE, + NULL, + NULL, + N_("Paste tasks from the clipboard"), + G_CALLBACK (action_calendar_taskpad_clipboard_paste_cb) }, + + { "calendar-taskpad-delete", + GTK_STOCK_DELETE, + N_("_Delete Task"), + NULL, + N_("Delete selected tasks"), + G_CALLBACK (action_calendar_taskpad_delete_cb) }, + + { "calendar-taskpad-forward", + "mail-forward", + N_("_Forward as iCalendar..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_taskpad_forward_cb) }, + + { "calendar-taskpad-mark-complete", + NULL, + N_("_Mark as Complete"), + NULL, + N_("Mark selected tasks as complete"), + G_CALLBACK (action_calendar_taskpad_mark_complete_cb) }, + + { "calendar-taskpad-mark-incomplete", + NULL, + N_("_Mar_k as Incomplete"), + NULL, + N_("Mark selected tasks as incomplete"), + G_CALLBACK (action_calendar_taskpad_mark_incomplete_cb) }, + + { "calendar-taskpad-new", + "stock_task", + N_("New _Task"), + NULL, + N_("Create a new task"), + G_CALLBACK (action_calendar_taskpad_new_cb) }, + + { "calendar-taskpad-open", + GTK_STOCK_OPEN, + N_("_Open Task"), + NULL, + N_("View the selected task"), + G_CALLBACK (action_calendar_taskpad_open_cb) }, + + { "calendar-taskpad-open-url", + "applications-internet", + N_("Open _Web Page"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_taskpad_open_url_cb) }, + + { "calendar-taskpad-save-as", + GTK_STOCK_SAVE_AS, + N_("_Save as iCalendar..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_calendar_taskpad_save_as_cb) } +}; + +static GtkActionEntry lockdown_printing_entries[] = { + + { "calendar-taskpad-print", + GTK_STOCK_PRINT, + NULL, + NULL, + N_("Print the selected task"), + G_CALLBACK (action_calendar_taskpad_print_cb) } +}; + +void +e_cal_shell_view_taskpad_actions_init (ECalShellView *cal_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkActionGroup *action_group; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + /* Calendar Actions */ + action_group = ACTION_GROUP (CALENDAR); + gtk_action_group_add_actions ( + action_group, calendar_taskpad_entries, + G_N_ELEMENTS (calendar_taskpad_entries), cal_shell_view); + + /* Lockdown Printing Actions */ + action_group = ACTION_GROUP (LOCKDOWN_PRINTING); + gtk_action_group_add_actions ( + action_group, lockdown_printing_entries, + G_N_ELEMENTS (lockdown_printing_entries), cal_shell_view); +} + +void +e_cal_shell_view_taskpad_actions_update (ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + EShellWindow *shell_window; + EShellView *shell_view; + ECalendarTable *task_table; + ETable *table; + GtkAction *action; + GSList *list, *iter; + const gchar *label; + gboolean assignable = TRUE; + gboolean editable = TRUE; + gboolean has_url = FALSE; + gboolean sensitive; + gint n_selected; + gint n_complete = 0; + gint n_incomplete = 0; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + task_table = e_cal_shell_content_get_task_table (cal_shell_content); + + table = e_calendar_table_get_table (task_table); + n_selected = e_table_selected_count (table); + + list = e_calendar_table_get_selected (task_table); + for (iter = list; iter != NULL; iter = iter->next) { + ECalModelComponent *comp_data = iter->data; + icalproperty *prop; + const gchar *cap; + gboolean read_only; + + e_cal_is_read_only (comp_data->client, &read_only, NULL); + editable &= !read_only; + + cap = CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT; + if (e_cal_get_static_capability (comp_data->client, cap)) + assignable = FALSE; + + cap = CAL_STATIC_CAPABILITY_NO_CONV_TO_ASSIGN_TASK; + if (e_cal_get_static_capability (comp_data->client, cap)) + assignable = FALSE; + + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_URL_PROPERTY); + has_url |= (prop != NULL); + + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_COMPLETED_PROPERTY); + if (prop != NULL) + n_complete++; + else + n_incomplete++; + } + g_slist_free (list); + + action = ACTION (CALENDAR_TASKPAD_ASSIGN); + sensitive = (n_selected == 1) && editable && assignable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_CLIPBOARD_COPY); + sensitive = (n_selected > 0); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_CLIPBOARD_CUT); + sensitive = (n_selected > 0) && editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_CLIPBOARD_PASTE); + sensitive = editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_DELETE); + sensitive = (n_selected > 0) && editable; + gtk_action_set_sensitive (action, sensitive); + label = ngettext ("Delete Task", "Delete Tasks", n_selected); + g_object_set (action, "label", label, NULL); + + action = ACTION (CALENDAR_TASKPAD_FORWARD); + sensitive = (n_selected == 1); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_MARK_COMPLETE); + sensitive = (n_selected > 0) && editable && (n_incomplete > 0); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_MARK_INCOMPLETE); + sensitive = (n_selected > 0) && editable && (n_complete > 0); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_OPEN); + sensitive = (n_selected == 1); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_OPEN_URL); + sensitive = (n_selected == 1) && has_url; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_PRINT); + sensitive = (n_selected == 1); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_TASKPAD_SAVE_AS); + sensitive = (n_selected == 1); + gtk_action_set_sensitive (action, sensitive); +} + +void +e_cal_shell_view_taskpad_open_task (ECalShellView *cal_shell_view, + ECalModelComponent *comp_data) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + CompEditor *editor; + CompEditorFlags flags = 0; + ECalComponent *comp; + icalcomponent *clone; + icalproperty *prop; + const gchar *uid; + + g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); + g_return_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data)); + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + + uid = icalcomponent_get_uid (comp_data->icalcomp); + editor = comp_editor_find_instance (uid); + + if (editor != NULL) + goto exit; + + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_component_set_icalcomponent (comp, clone); + + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_ATTENDEE_PROPERTY); + if (prop != NULL) + flags |= COMP_EDITOR_IS_ASSIGNED; + + if (itip_organizer_is_user (comp, comp_data->client)) + flags |= COMP_EDITOR_USER_ORG; + + if (!e_cal_component_has_attendees (comp)) + flags |= COMP_EDITOR_USER_ORG; + + editor = task_editor_new (comp_data->client, shell, flags); + comp_editor_edit_comp (editor, comp); + + g_object_ref (comp); + + if (flags & COMP_EDITOR_IS_ASSIGNED) + task_editor_show_assignment (TASK_EDITOR (editor)); + +exit: + gtk_window_present (GTK_WINDOW (editor)); +} + +void +e_cal_shell_view_taskpad_set_status_message (ECalShellView *cal_shell_view, + const gchar *status_message, + gdouble percent) +{ + EActivity *activity; + EShellView *shell_view; + EShellBackend *shell_backend; + + g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + activity = cal_shell_view->priv->taskpad_activity; + + if (status_message == NULL || *status_message == '\0') { + if (activity != NULL) { + e_activity_complete (activity); + g_object_unref (activity); + activity = NULL; + } + + } else if (activity == NULL) { + activity = e_activity_new (status_message); + e_activity_set_percent (activity, percent); + e_shell_backend_add_activity (shell_backend, activity); + + } else { + e_activity_set_percent (activity, percent); + e_activity_set_primary_text (activity, status_message); + } + + cal_shell_view->priv->taskpad_activity = activity; +} diff --git a/modules/calendar/e-cal-shell-view.c b/modules/calendar/e-cal-shell-view.c new file mode 100644 index 0000000000..5bf1c749a1 --- /dev/null +++ b/modules/calendar/e-cal-shell-view.c @@ -0,0 +1,226 @@ +/* + * e-cal-shell-view.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-view-private.h" + +static gpointer parent_class; +static GType cal_shell_view_type; + +static void +cal_shell_view_dispose (GObject *object) +{ + e_cal_shell_view_private_dispose (E_CAL_SHELL_VIEW (object)); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +cal_shell_view_finalize (GObject *object) +{ + e_cal_shell_view_private_finalize (E_CAL_SHELL_VIEW (object)); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +cal_shell_view_constructed (GObject *object) +{ + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + e_cal_shell_view_private_constructed (E_CAL_SHELL_VIEW (object)); +} + +static void +cal_shell_view_update_actions (EShellView *shell_view) +{ +#if 0 + ECalShellViewPrivate *priv; + ECalShellContent *cal_shell_content; + ECalShellSidebar *cal_shell_sidebar; + EShellWindow *shell_window; + GnomeCalendar *calendar; + ECalModel *model; + ESourceSelector *selector; + ESource *source; + GtkAction *action; + GtkWidget *widget; + GList *list, *iter; + const gchar *uri = NULL; + gboolean user_created_source; + gboolean editable = TRUE; + gboolean recurring = FALSE; + gboolean sensitive; + gint n_selected; + + priv = E_CAL_SHELL_VIEW_GET_PRIVATE (shell_view); + + shell_window = e_shell_view_get_shell_window (shell_view); + + cal_shell_content = priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + widget = gnome_calendar_get_current_view_widget (calendar); + model = e_calendar_view_get_model (E_CALENDAR_VIEW (widget)); + + cal_shell_sidebar = priv->cal_shell_sidebar; + selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); + + list = e_calendar_view_get_selected_events (E_CALENDAR_VIEW (widget)); + n_selected = g_list_length (list); + + for (iter = list; iter != NULL; iter = iter->next) { + ECalModelComponent *comp_data = iter->data; + gboolean read_only; + + e_cal_is_read_only (comp_data->client, &read_only, NULL); + editable &= !read_only; + + if (e_cal_util_component_has_recurrences (comp_data->icalcomp)) + recurring |= TRUE; + else if (e_cal_util_component_is_instance (comp_data->icalcomp)) + recurring |= TRUE; + } + + source = e_source_selector_peek_primary_selection (selector); + if (source != NULL) + uri = e_source_peek_relative_uri (source); + user_created_source = (uri != NULL && strcmp (uri, "system") != 0); + + action = ACTION (CALENDAR_COPY); + sensitive = (source != NULL); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_DELETE); + sensitive = user_created_source; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_PROPERTIES); + sensitive = (source != NULL); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CALENDAR_RENAME); + sensitive = has_primary_source; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (EVENT_CLIPBOARD_COPY); + sensitive = (n_selected > 0); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (EVENT_CLIPBOARD_CUT); + sensitive = (n_selected > 0) && editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (EVENT_CLIPBOARD_PASTE); + sensitive = editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (EVENT_DELETE); + sensitive = (n_selected > 0) && editable && !recurring; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (EVENT_DELETE_OCCURRENCE); + sensitive = (n_selected > 0) && editable && recurring; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (EVENT_DELETE_OCCURRENCE_ALL); + sensitive = (n_selected > 0) && editable && recurring; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (EVENT_OPEN); + sensitive = (n_selected == 1); + gtk_action_set_sensitive (action, sensitive); +#endif +} + +static void +cal_shell_view_class_init (ECalShellViewClass *class, + GTypeModule *type_module) +{ + GObjectClass *object_class; + EShellViewClass *shell_view_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ECalShellViewPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->dispose = cal_shell_view_dispose; + object_class->finalize = cal_shell_view_finalize; + object_class->constructed = cal_shell_view_constructed; + + shell_view_class = E_SHELL_VIEW_CLASS (class); + shell_view_class->label = _("Calendar"); + shell_view_class->icon_name = "x-office-calendar"; + shell_view_class->ui_definition = "evolution-calendars.ui"; + shell_view_class->ui_manager_id = "org.gnome.evolution.calendars"; + shell_view_class->search_options = "/calendar-search-options"; + shell_view_class->search_rules = "caltypes.xml"; + shell_view_class->new_shell_content = e_cal_shell_content_new; + shell_view_class->new_shell_sidebar = e_cal_shell_sidebar_new; + shell_view_class->update_actions = cal_shell_view_update_actions; +} + +static void +cal_shell_view_init (ECalShellView *cal_shell_view, + EShellViewClass *shell_view_class) +{ + cal_shell_view->priv = + E_CAL_SHELL_VIEW_GET_PRIVATE (cal_shell_view); + + e_cal_shell_view_private_init (cal_shell_view, shell_view_class); +} + +GType +e_cal_shell_view_get_type (void) +{ + return cal_shell_view_type; +} + +void +e_cal_shell_view_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (ECalShellViewClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) cal_shell_view_class_init, + (GClassFinalizeFunc) NULL, + type_module, + sizeof (ECalShellView), + 0, /* n_preallocs */ + (GInstanceInitFunc) cal_shell_view_init, + NULL /* value_table */ + }; + + cal_shell_view_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_VIEW, + "ECalShellView", &type_info, 0); +} + +GnomeCalendar * +e_cal_shell_view_get_calendar (ECalShellView *cal_shell_view) +{ + g_return_val_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view), NULL); + + /* FIXME */ + return NULL; +} diff --git a/modules/calendar/e-cal-shell-view.h b/modules/calendar/e-cal-shell-view.h new file mode 100644 index 0000000000..67fa15220c --- /dev/null +++ b/modules/calendar/e-cal-shell-view.h @@ -0,0 +1,69 @@ +/* + * e-cal-shell-view.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_CAL_SHELL_VIEW_H +#define E_CAL_SHELL_VIEW_H + +#include +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_CAL_SHELL_VIEW \ + (e_cal_shell_view_get_type ()) +#define E_CAL_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_CAL_SHELL_VIEW, ECalShellView)) +#define E_CAL_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_CAL_SHELL_VIEW, ECalShellViewClass)) +#define E_IS_CAL_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_CAL_SHELL_VIEW)) +#define E_IS_CAL_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_CAL_SHELL_VIEW)) +#define E_CAL_SHELL_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_CAL_SHELL_VIEW, ECalShellViewClass)) + +G_BEGIN_DECLS + +typedef struct _ECalShellView ECalShellView; +typedef struct _ECalShellViewClass ECalShellViewClass; +typedef struct _ECalShellViewPrivate ECalShellViewPrivate; + +struct _ECalShellView { + EShellView parent; + ECalShellViewPrivate *priv; +}; + +struct _ECalShellViewClass { + EShellViewClass parent_class; +}; + +GType e_cal_shell_view_get_type (void); +void e_cal_shell_view_register_type (GTypeModule *type_module); +GnomeCalendar * e_cal_shell_view_get_calendar (ECalShellView *cal_shell_view); + +G_END_DECLS + +#endif /* E_CAL_SHELL_VIEW_H */ diff --git a/modules/calendar/e-memo-shell-backend.c b/modules/calendar/e-memo-shell-backend.c new file mode 100644 index 0000000000..d2734e066a --- /dev/null +++ b/modules/calendar/e-memo-shell-backend.c @@ -0,0 +1,613 @@ +/* + * e-memo-shell-backend.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-memo-shell-backend.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "shell/e-shell.h" +#include "shell/e-shell-backend.h" +#include "shell/e-shell-window.h" + +#include "calendar/common/authentication.h" +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/comp-util.h" +#include "calendar/gui/dialogs/calendar-setup.h" +#include "calendar/gui/dialogs/memo-editor.h" + +#include "e-memo-shell-migrate.h" +#include "e-memo-shell-view.h" + +#define E_MEMO_SHELL_BACKEND_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MEMO_SHELL_BACKEND, EMemoShellBackendPrivate)) + +#define WEB_BASE_URI "webcal://" +#define PERSONAL_RELATIVE_URI "system" + +struct _EMemoShellBackendPrivate { + ESourceList *source_list; +}; + +enum { + PROP_0, + PROP_SOURCE_LIST +}; + +static gpointer parent_class; +static GType memo_shell_backend_type; + +static void +memo_module_ensure_sources (EShellBackend *shell_backend) +{ + /* XXX This is basically the same algorithm across all modules. + * Maybe we could somehow integrate this into EShellBackend? */ + + EMemoShellBackendPrivate *priv; + ESourceGroup *on_this_computer; + ESourceGroup *on_the_web; + ESource *personal; + GSList *groups, *iter; + const gchar *data_dir; + const gchar *name; + gchar *base_uri; + gchar *filename; + + on_this_computer = NULL; + on_the_web = NULL; + personal = NULL; + + priv = E_MEMO_SHELL_BACKEND_GET_PRIVATE (shell_backend); + + if (!e_cal_get_sources (&priv->source_list, E_CAL_SOURCE_TYPE_JOURNAL, NULL)) { + g_warning ("Could not get memo sources from GConf!"); + return; + } + + data_dir = e_shell_backend_get_data_dir (shell_backend); + filename = g_build_filename (data_dir, "local", NULL); + base_uri = g_filename_to_uri (filename, NULL, NULL); + g_free (filename); + + groups = e_source_list_peek_groups (priv->source_list); + for (iter = groups; iter != NULL; iter = iter->next) { + ESourceGroup *source_group = iter->data; + const gchar *group_base_uri; + + group_base_uri = e_source_group_peek_base_uri (source_group); + + /* Compare only "file://" part. If the user's home + * changes, we do not want to create another group. */ + if (on_this_computer == NULL && + strncmp (base_uri, group_base_uri, 7) == 0) + on_this_computer = source_group; + + else if (on_the_web == NULL && + strcmp (WEB_BASE_URI, group_base_uri) == 0) + on_the_web = source_group; + } + + name = _("On This Computer"); + + if (on_this_computer != NULL) { + GSList *sources; + const gchar *group_base_uri; + + /* Force the group name to the current locale. */ + e_source_group_set_name (on_this_computer, name); + + sources = e_source_group_peek_sources (on_this_computer); + group_base_uri = e_source_group_peek_base_uri (on_this_computer); + + /* Make sure this group includes a "Personal" source. */ + for (iter = sources; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + const gchar *relative_uri; + + relative_uri = e_source_peek_relative_uri (source); + if (relative_uri == NULL) + continue; + + if (strcmp (PERSONAL_RELATIVE_URI, relative_uri) != 0) + continue; + + personal = source; + break; + } + + /* Make sure we have the correct base URI. This can + * change when the user's home directory changes. */ + if (strcmp (base_uri, group_base_uri) != 0) { + e_source_group_set_base_uri ( + on_this_computer, base_uri); + + /* XXX We shouldn't need this sync call here as + * set_base_uri() results in synching to GConf, + * but that happens in an idle loop and too late + * to prevent the user from seeing a "Cannot + * Open ... because of invalid URI" error. */ + e_source_list_sync (priv->source_list, NULL); + } + + } else { + ESourceGroup *source_group; + + source_group = e_source_group_new (name, base_uri); + e_source_list_add_group (priv->source_list, source_group, -1); + g_object_unref (source_group); + } + + name = _("Personal"); + + if (personal == NULL) { + ESource *source; + GSList *selected; + gchar *primary; + + source = e_source_new (name, PERSONAL_RELATIVE_URI); + e_source_group_add_source (on_this_computer, source, -1); + g_object_unref (source); + + primary = calendar_config_get_primary_memos (); + selected = calendar_config_get_memos_selected (); + + if (primary == NULL && selected == NULL) { + const gchar *uid; + + uid = e_source_peek_uid (source); + selected = g_slist_prepend (NULL, g_strdup (uid)); + + calendar_config_set_primary_memos (uid); + calendar_config_set_memos_selected (selected); + } + + g_slist_foreach (selected, (GFunc) g_free, NULL); + g_slist_free (selected); + g_free (primary); + } else { + /* Force the source name to the current locale. */ + e_source_set_name (personal, name); + } + + name = _("On The Web"); + + if (on_the_web == NULL) { + ESourceGroup *source_group; + + source_group = e_source_group_new (name, WEB_BASE_URI); + e_source_list_add_group (priv->source_list, source_group, -1); + g_object_unref (source_group); + } else { + /* Force the group name to the current locale. */ + e_source_group_set_name (on_the_web, name); + } + + g_free (base_uri); +} + +static void +memo_module_cal_opened_cb (ECal *cal, + ECalendarStatus status, + GtkAction *action) +{ + EShell *shell; + ECalComponent *comp; + CompEditor *editor; + CompEditorFlags flags = 0; + const gchar *action_name; + + /* FIXME Pass this in. */ + shell = e_shell_get_default (); + + /* XXX Handle errors better. */ + if (status != E_CALENDAR_STATUS_OK) + return; + + action_name = gtk_action_get_name (action); + + flags |= COMP_EDITOR_NEW_ITEM; + if (strcmp (action_name, "memo-shared-new") == 0) { + flags |= COMP_EDITOR_IS_SHARED; + flags |= COMP_EDITOR_USER_ORG; + } + + editor = memo_editor_new (cal, shell, flags); + comp = cal_comp_memo_new_with_defaults (cal); + comp_editor_edit_comp (editor, comp); + + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (comp); + g_object_unref (cal); +} + +static void +action_memo_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + ECal *cal = NULL; + ECalSourceType source_type; + ESourceList *source_list; + gchar *uid; + + /* This callback is used for both memos and shared memos. */ + + source_type = E_CAL_SOURCE_TYPE_JOURNAL; + + if (!e_cal_get_sources (&source_list, source_type, NULL)) { + g_warning ("Could not get memo sources from GConf!"); + return; + } + + uid = calendar_config_get_primary_memos (); + + if (uid != NULL) { + ESource *source; + + source = e_source_list_peek_source_by_uid (source_list, uid); + if (source != NULL) + cal = auth_new_cal_from_source (source, source_type); + g_free (uid); + } + + if (cal == NULL) + cal = auth_new_cal_from_default (source_type); + + g_return_if_fail (cal != NULL); + + g_signal_connect ( + cal, "cal-opened", + G_CALLBACK (memo_module_cal_opened_cb), action); + + e_cal_open_async (cal, FALSE); +} + +static void +action_memo_list_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + calendar_setup_new_memo_list (GTK_WINDOW (shell_window)); +} + +static GtkActionEntry item_entries[] = { + + { "memo-new", + "stock_insert-note", + NC_("New", "Mem_o"), + "o", + N_("Create a new memo"), + G_CALLBACK (action_memo_new_cb) }, + + { "memo-shared-new", + "stock_insert-note", + N_("_Shared Memo"), + "h", + N_("Create a new shared memo"), + G_CALLBACK (action_memo_new_cb) } +}; + +static GtkActionEntry source_entries[] = { + + { "memo-list-new", + "stock_notes", + NC_("New", "Memo Li_st"), + NULL, + N_("Create a new memo list"), + G_CALLBACK (action_memo_list_new_cb) } +}; + +static gboolean +memo_module_handle_uri_cb (EShellBackend *shell_backend, + const gchar *uri) +{ + EShell *shell; + CompEditor *editor; + CompEditorFlags flags = 0; + ECal *client; + ECalComponent *comp; + ESource *source; + ESourceList *source_list; + ECalSourceType source_type; + EUri *euri; + icalcomponent *icalcomp; + const gchar *cp; + gchar *source_uid = NULL; + gchar *comp_uid = NULL; + gchar *comp_rid = NULL; + gboolean handled = FALSE; + GError *error = NULL; + + source_type = E_CAL_SOURCE_TYPE_JOURNAL; + shell = e_shell_backend_get_shell (shell_backend); + + if (strncmp (uri, "memo:", 5) != 0) + return FALSE; + + euri = e_uri_new (uri); + cp = euri->query; + if (cp == NULL) + goto exit; + + while (*cp != '\0') { + gchar *header; + gchar *content; + gsize header_len; + gsize content_len; + + header_len = strcspn (cp, "=&"); + + /* If it's malformed, give up. */ + if (cp[header_len] != '=') + break; + + header = (gchar *) cp; + header[header_len] = '\0'; + cp += header_len + 1; + + content_len = strcspn (cp, "&"); + + content = g_strndup (cp, content_len); + if (g_ascii_strcasecmp (header, "source-uid") == 0) + source_uid = g_strdup (content); + else if (g_ascii_strcasecmp (header, "comp-uid") == 0) + comp_uid = g_strdup (content); + else if (g_ascii_strcasecmp (header, "comp-rid") == 0) + comp_rid = g_strdup (content); + g_free (content); + + cp += content_len; + if (*cp == '&') { + cp++; + if (strcmp (cp, "amp;") == 0) + cp += 4; + } + } + + if (source_uid == NULL || comp_uid == NULL) + goto exit; + + /* URI is valid, so consider it handled. Whether + * we successfully open it is another matter... */ + handled = TRUE; + + if (!e_cal_get_sources (&source_list, source_type, NULL)) { + g_printerr ("Could not get memo sources from GConf!\n"); + goto exit; + } + + source = e_source_list_peek_source_by_uid (source_list, source_uid); + if (source == NULL) { + g_printerr ("No source for UID `%s'\n", source_uid); + g_object_unref (source_list); + goto exit; + } + + client = auth_new_cal_from_source (source, source_type); + if (client == NULL || !e_cal_open (client, TRUE, &error)) { + g_printerr ("%s\n", error->message); + g_object_unref (source_list); + g_error_free (error); + goto exit; + } + + /* XXX Copied from e_memo_shell_view_open_memo(). + * Clearly a new utility function is needed. */ + + editor = comp_editor_find_instance (comp_uid); + + if (editor != NULL) + goto present; + + if (!e_cal_get_object (client, comp_uid, comp_rid, &icalcomp, &error)) { + g_printerr ("%s\n", error->message); + g_object_unref (source_list); + g_error_free (error); + goto exit; + } + + comp = e_cal_component_new (); + e_cal_component_set_icalcomponent (comp, icalcomp); + + if (e_cal_component_has_organizer (comp)) + flags |= COMP_EDITOR_IS_SHARED; + + if (itip_organizer_is_user (comp, client)) + flags |= COMP_EDITOR_USER_ORG; + + editor = memo_editor_new (client, shell, flags); + comp_editor_edit_comp (editor, comp); + + g_object_unref (comp); + +present: + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (source_list); + g_object_unref (client); + +exit: + g_free (source_uid); + g_free (comp_uid); + g_free (comp_rid); + + e_uri_free (euri); + + return handled; +} + +static void +memo_module_window_created_cb (EShellBackend *shell_backend, + GtkWindow *window) +{ + const gchar *module_name; + + if (!E_IS_SHELL_WINDOW (window)) + return; + + module_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name; + + e_shell_window_register_new_item_actions ( + E_SHELL_WINDOW (window), module_name, + item_entries, G_N_ELEMENTS (item_entries)); + + e_shell_window_register_new_source_actions ( + E_SHELL_WINDOW (window), module_name, + source_entries, G_N_ELEMENTS (source_entries)); +} + +static void +memo_shell_backend_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SOURCE_LIST: + g_value_set_object ( + value, + e_memo_shell_backend_get_source_list ( + E_MEMO_SHELL_BACKEND (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +memo_shell_backend_dispose (GObject *object) +{ + EMemoShellBackendPrivate *priv; + + priv = E_MEMO_SHELL_BACKEND_GET_PRIVATE (object); + + if (priv->source_list != NULL) { + g_object_unref (priv->source_list); + priv->source_list = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +memo_shell_backend_constructed (GObject *object) +{ + EShell *shell; + EShellBackend *shell_backend; + + shell_backend = E_SHELL_BACKEND (object); + shell = e_shell_backend_get_shell (shell_backend); + + memo_module_ensure_sources (shell_backend); + + g_signal_connect_swapped ( + shell, "handle-uri", + G_CALLBACK (memo_module_handle_uri_cb), shell_backend); + + g_signal_connect_swapped ( + shell, "window-created", + G_CALLBACK (memo_module_window_created_cb), shell_backend); +} + +static void +memo_shell_backend_class_init (EMemoShellBackendClass *class) +{ + GObjectClass *object_class; + EShellBackendClass *shell_backend_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMemoShellBackendPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->get_property = memo_shell_backend_get_property; + object_class->dispose = memo_shell_backend_dispose; + object_class->constructed = memo_shell_backend_constructed; + + shell_backend_class = E_SHELL_BACKEND_CLASS (class); + shell_backend_class->shell_view_type = E_TYPE_MEMO_SHELL_VIEW; + shell_backend_class->name = "memos"; + shell_backend_class->aliases = ""; + shell_backend_class->schemes = "memo"; + shell_backend_class->sort_order = 500; + shell_backend_class->start = NULL; + shell_backend_class->is_busy = NULL; + shell_backend_class->shutdown = NULL; + shell_backend_class->migrate = e_memo_shell_backend_migrate; + + g_object_class_install_property ( + object_class, + PROP_SOURCE_LIST, + g_param_spec_object ( + "source-list", + _("Source List"), + _("The registry of memo lists"), + E_TYPE_SOURCE_LIST, + G_PARAM_READABLE)); +} + +static void +memo_shell_backend_init (EMemoShellBackend *memo_shell_backend) +{ + memo_shell_backend->priv = + E_MEMO_SHELL_BACKEND_GET_PRIVATE (memo_shell_backend); +} + +GType +e_memo_shell_backend_get_type (void) +{ + return memo_shell_backend_type; +} + +void +e_memo_shell_backend_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (EMemoShellBackendClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) memo_shell_backend_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMemoShellBackend), + 0, /* n_preallocs */ + (GInstanceInitFunc) memo_shell_backend_init, + NULL /* value_table */ + }; + + memo_shell_backend_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_BACKEND, + "EMemoShellBackend", &type_info, 0); +} + +ESourceList * +e_memo_shell_backend_get_source_list (EMemoShellBackend *memo_shell_backend) +{ + g_return_val_if_fail ( + E_IS_MEMO_SHELL_BACKEND (memo_shell_backend), NULL); + + return memo_shell_backend->priv->source_list; +} diff --git a/modules/calendar/e-memo-shell-backend.h b/modules/calendar/e-memo-shell-backend.h new file mode 100644 index 0000000000..37fe41a784 --- /dev/null +++ b/modules/calendar/e-memo-shell-backend.h @@ -0,0 +1,70 @@ +/* + * e-memo-shell-backend.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MEMO_SHELL_BACKEND_H +#define E_MEMO_SHELL_BACKEND_H + +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_MEMO_SHELL_BACKEND \ + (e_memo_shell_backend_get_type ()) +#define E_MEMO_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MEMO_SHELL_BACKEND, EMemoShellBackend)) +#define E_MEMO_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MEMO_SHELL_BACKEND, EMemoShellBackendClass)) +#define E_IS_MEMO_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MEMO_SHELL_BACKEND)) +#define E_IS_MEMO_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MEMO_SHELL_BACKEND)) +#define E_MEMO_SHELL_BACKEND_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MEMO_SHELL_BACKEND, EMemoShellBackendClass)) + +G_BEGIN_DECLS + +typedef struct _EMemoShellBackend EMemoShellBackend; +typedef struct _EMemoShellBackendClass EMemoShellBackendClass; +typedef struct _EMemoShellBackendPrivate EMemoShellBackendPrivate; + +struct _EMemoShellBackend { + EShellBackend parent; + EMemoShellBackendPrivate *priv; +}; + +struct _EMemoShellBackendClass { + EShellBackendClass parent_class; +}; + +GType e_memo_shell_backend_get_type (void); +void e_memo_shell_backend_register_type + (GTypeModule *type_module); +ESourceList * e_memo_shell_backend_get_source_list + (EMemoShellBackend *memo_shell_backend); + +G_END_DECLS + +#endif /* E_MEMO_SHELL_BACKEND_H */ diff --git a/modules/calendar/e-memo-shell-content.c b/modules/calendar/e-memo-shell-content.c new file mode 100644 index 0000000000..ce020158ae --- /dev/null +++ b/modules/calendar/e-memo-shell-content.c @@ -0,0 +1,676 @@ +/* + * e-memo-shell-content.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-memo-shell-content.h" + +#include + +#include "e-util/gconf-bridge.h" + +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/comp-util.h" +#include "calendar/gui/e-cal-model-memos.h" +#include "calendar/gui/e-memo-table.h" +#include "calendar/gui/e-memo-table-config.h" + +#include "widgets/menus/gal-view-etable.h" + +#define E_MEMO_SHELL_CONTENT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MEMO_SHELL_CONTENT, EMemoShellContentPrivate)) + +#define E_MEMO_TABLE_DEFAULT_STATE \ + "" \ + "" \ + " " \ + " " \ + " " \ + " " \ + "" + +struct _EMemoShellContentPrivate { + GtkWidget *paned; + GtkWidget *memo_table; + GtkWidget *memo_preview; + + ECalModel *memo_model; + EMemoTableConfig *table_config; + GalViewInstance *view_instance; + + gchar *current_uid; +}; + +enum { + PROP_0, + PROP_MODEL, + PROP_PREVIEW_VISIBLE +}; + +enum { + TARGET_VCALENDAR +}; + +static GtkTargetEntry drag_types[] = { + { (gchar *) "text/calendar", 0, TARGET_VCALENDAR }, + { (gchar *) "text/x-calendar", 0, TARGET_VCALENDAR } +}; + +static gpointer parent_class; +static GType memo_shell_content_type; + +static void +memo_shell_content_display_view_cb (EMemoShellContent *memo_shell_content, + GalView *gal_view) +{ + EMemoTable *memo_table; + ETable *table; + + if (!GAL_IS_VIEW_ETABLE (gal_view)) + return; + + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + table = e_memo_table_get_table (memo_table); + + gal_view_etable_attach_table (GAL_VIEW_ETABLE (gal_view), table); +} + +static void +memo_shell_content_table_foreach_cb (gint model_row, + gpointer user_data) +{ + ECalModelComponent *comp_data; + icalcomponent *clone; + icalcomponent *vcal; + gchar *string; + + struct { + ECalModel *model; + GSList *list; + } *foreach_data = user_data; + + comp_data = e_cal_model_get_component_at ( + foreach_data->model, model_row); + + vcal = e_cal_util_new_top_level (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_util_add_timezones_from_component (vcal, comp_data->icalcomp); + icalcomponent_add_component (vcal, clone); + + /* String is owned by libical; do not free. */ + string = icalcomponent_as_ical_string (vcal); + if (string != NULL) { + ESource *source; + const gchar *source_uid; + + source = e_cal_get_source (comp_data->client); + source_uid = e_source_peek_uid (source); + + foreach_data->list = g_slist_prepend ( + foreach_data->list, + g_strdup_printf ("%s\n%s", source_uid, string)); + } + + icalcomponent_free (vcal); +} + +static void +memo_shell_content_table_drag_data_get_cb (EMemoShellContent *memo_shell_content, + gint row, + gint col, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time) +{ + EMemoTable *memo_table; + ETable *table; + + struct { + ECalModel *model; + GSList *list; + } foreach_data; + + if (info != TARGET_VCALENDAR) + return; + + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + table = e_memo_table_get_table (memo_table); + + foreach_data.model = e_memo_table_get_model (memo_table); + foreach_data.list = NULL; + + e_table_selected_row_foreach ( + table, memo_shell_content_table_foreach_cb, + &foreach_data); + + if (foreach_data.list != NULL) { + cal_comp_selection_set_string_list ( + selection_data, foreach_data.list); + g_slist_foreach (foreach_data.list, (GFunc) g_free, NULL); + g_slist_free (foreach_data.list); + } +} + +static void +memo_shell_content_table_drag_data_delete_cb (EMemoShellContent *memo_shell_content, + gint row, + gint col, + GdkDragContext *context) +{ + /* Moved components are deleted from source immediately when moved, + * because some of them can be part of destination source, and we + * don't want to delete not-moved memos. There is no such information + * which event has been moved and which not, so skip this method. */ +} + +static void +memo_shell_content_cursor_change_cb (EMemoShellContent *memo_shell_content, + gint row, + ETable *table) +{ + ECalComponentPreview *memo_preview; + EMemoTable *memo_table; + ECalModel *memo_model; + ECalModelComponent *comp_data; + ECalComponent *comp; + const gchar *uid; + + memo_model = e_memo_shell_content_get_memo_model (memo_shell_content); + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + memo_preview = e_memo_shell_content_get_memo_preview (memo_shell_content); + + if (e_table_selected_count (table) != 1) { + e_cal_component_preview_clear (memo_preview); + return; + } + + row = e_table_get_cursor_row (table); + comp_data = e_cal_model_get_component_at (memo_model, row); + + comp = e_cal_component_new (); + e_cal_component_set_icalcomponent ( + comp, icalcomponent_new_clone (comp_data->icalcomp)); + e_cal_component_preview_display ( + memo_preview, comp_data->client, comp); + + e_cal_component_get_uid (comp, &uid); + g_free (memo_shell_content->priv->current_uid); + memo_shell_content->priv->current_uid = g_strdup (uid); + + g_object_unref (comp); +} + +static void +memo_shell_content_selection_change_cb (EMemoShellContent *memo_shell_content, + ETable *table) +{ + ECalComponentPreview *memo_preview; + + memo_preview = e_memo_shell_content_get_memo_preview (memo_shell_content); + + /* XXX Old code emits a "selection-changed" signal here. */ + + if (e_table_selected_count (table) != 1) + e_cal_component_preview_clear (memo_preview); +} + +static void +memo_shell_content_model_row_changed_cb (EMemoShellContent *memo_shell_content, + gint row, + ETableModel *model) +{ + ECalModelComponent *comp_data; + EMemoTable *memo_table; + ETable *table; + const gchar *current_uid; + const gchar *uid; + + current_uid = memo_shell_content->priv->current_uid; + if (current_uid == NULL) + return; + + comp_data = e_cal_model_get_component_at (E_CAL_MODEL (model), row); + if (comp_data == NULL) + return; + + uid = icalcomponent_get_uid (comp_data->icalcomp); + if (g_strcmp0 (uid, current_uid) != 0) + return; + + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + table = e_memo_table_get_table (memo_table); + + memo_shell_content_cursor_change_cb (memo_shell_content, 0, table); +} + +static void +memo_shell_content_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_PREVIEW_VISIBLE: + e_memo_shell_content_set_preview_visible ( + E_MEMO_SHELL_CONTENT (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +memo_shell_content_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_MODEL: + g_value_set_object ( + value, e_memo_shell_content_get_memo_model ( + E_MEMO_SHELL_CONTENT (object))); + return; + + case PROP_PREVIEW_VISIBLE: + g_value_set_boolean ( + value, e_memo_shell_content_get_preview_visible ( + E_MEMO_SHELL_CONTENT (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +memo_shell_content_dispose (GObject *object) +{ + EMemoShellContentPrivate *priv; + + priv = E_MEMO_SHELL_CONTENT_GET_PRIVATE (object); + + if (priv->paned != NULL) { + g_object_unref (priv->paned); + priv->paned = NULL; + } + + if (priv->memo_table != NULL) { + g_object_unref (priv->memo_table); + priv->memo_table = NULL; + } + + if (priv->memo_preview != NULL) { + g_object_unref (priv->memo_preview); + priv->memo_preview = NULL; + } + + if (priv->memo_model != NULL) { + g_object_unref (priv->memo_model); + priv->memo_model = NULL; + } + + if (priv->table_config != NULL) { + g_object_unref (priv->table_config); + priv->table_config = NULL; + } + + if (priv->view_instance != NULL) { + g_object_unref (priv->view_instance); + priv->view_instance = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +memo_shell_content_finalize (GObject *object) +{ + EMemoShellContentPrivate *priv; + + priv = E_MEMO_SHELL_CONTENT_GET_PRIVATE (object); + + g_free (priv->current_uid); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +memo_shell_content_constructed (GObject *object) +{ + EMemoShellContentPrivate *priv; + EShellContent *shell_content; + EShellView *shell_view; + GalViewInstance *view_instance; + ETable *table; + GConfBridge *bridge; + GtkWidget *container; + GtkWidget *widget; + const gchar *key; + + priv = E_MEMO_SHELL_CONTENT_GET_PRIVATE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + shell_content = E_SHELL_CONTENT (object); + shell_view = e_shell_content_get_shell_view (shell_content); + + /* Build content widgets. */ + + container = GTK_WIDGET (object); + + widget = gtk_vpaned_new (); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->paned = g_object_ref (widget); + gtk_widget_show (widget); + + container = widget; + + widget = e_memo_table_new (shell_view, priv->memo_model); + gtk_paned_add1 (GTK_PANED (container), widget); + priv->memo_table = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_paned_add2 (GTK_PANED (container), widget); + gtk_widget_show (widget); + + container = widget; + + widget = e_cal_component_preview_new (); + e_cal_component_preview_set_default_timezone ( + E_CAL_COMPONENT_PREVIEW (widget), + calendar_config_get_icaltimezone ()); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->memo_preview = g_object_ref (widget); + gtk_widget_show (widget); + + /* Configure the memo table. */ + + widget = E_MEMO_TABLE (priv->memo_table)->etable; + table = e_table_scrolled_get_table (E_TABLE_SCROLLED (widget)); + + priv->table_config = e_memo_table_config_new ( + E_MEMO_TABLE (priv->memo_table)); + + e_table_set_state (table, E_MEMO_TABLE_DEFAULT_STATE); + + e_table_drag_source_set ( + table, GDK_BUTTON1_MASK, + drag_types, G_N_ELEMENTS (drag_types), + GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_ASK); + + g_signal_connect_swapped ( + table, "table-drag-data-get", + G_CALLBACK (memo_shell_content_table_drag_data_get_cb), + object); + + g_signal_connect_swapped ( + table, "table-drag-data-delete", + G_CALLBACK (memo_shell_content_table_drag_data_delete_cb), + object); + + g_signal_connect_swapped ( + table, "cursor-change", + G_CALLBACK (memo_shell_content_cursor_change_cb), + object); + + g_signal_connect_swapped ( + table, "selection-change", + G_CALLBACK (memo_shell_content_selection_change_cb), + object); + + g_signal_connect_swapped ( + priv->memo_model, "model-row-changed", + G_CALLBACK (memo_shell_content_model_row_changed_cb), + object); + + /* Load the view instance. */ + + view_instance = e_shell_view_new_view_instance (shell_view, NULL); + g_signal_connect_swapped ( + view_instance, "display-view", + G_CALLBACK (memo_shell_content_display_view_cb), + object); + gal_view_instance_load (view_instance); + priv->view_instance = view_instance; + + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (priv->paned); + key = "/apps/evolution/calendar/display/memo_vpane_position"; + gconf_bridge_bind_property_delayed (bridge, key, object, "position"); +} + +static guint32 +memo_shell_content_check_state (EShellContent *shell_content) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ETable *table; + GSList *list, *iter; + gboolean editable = TRUE; + gboolean has_url = FALSE; + gint n_selected; + guint32 state = 0; + + memo_shell_content = E_MEMO_SHELL_CONTENT (shell_content); + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + table = e_memo_table_get_table (memo_table); + n_selected = e_table_selected_count (table); + + list = e_memo_table_get_selected (memo_table); + for (iter = list; iter != NULL; iter = iter->next) { + ECalModelComponent *comp_data = iter->data; + icalproperty *prop; + gboolean read_only; + + e_cal_is_read_only (comp_data->client, &read_only, NULL); + editable &= !read_only; + + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_URL_PROPERTY); + has_url |= (prop != NULL); + } + g_slist_free (list); + + if (n_selected == 1) + state |= E_MEMO_SHELL_CONTENT_SELECTION_SINGLE; + if (n_selected > 1) + state |= E_MEMO_SHELL_CONTENT_SELECTION_MULTIPLE; + if (editable) + state |= E_MEMO_SHELL_CONTENT_SELECTION_CAN_EDIT; + if (has_url) + state |= E_MEMO_SHELL_CONTENT_SELECTION_HAS_URL; + + return state; +} + +static void +memo_shell_content_class_init (EMemoShellContentClass *class) +{ + GObjectClass *object_class; + EShellContentClass *shell_content_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMemoShellContentPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = memo_shell_content_set_property; + object_class->get_property = memo_shell_content_get_property; + object_class->dispose = memo_shell_content_dispose; + object_class->finalize = memo_shell_content_finalize; + object_class->constructed = memo_shell_content_constructed; + + shell_content_class = E_SHELL_CONTENT_CLASS (class); + shell_content_class->check_state = memo_shell_content_check_state; + + g_object_class_install_property ( + object_class, + PROP_MODEL, + g_param_spec_object ( + "model", + _("Model"), + _("The memo table model"), + E_TYPE_CAL_MODEL, + G_PARAM_READABLE)); + + g_object_class_install_property ( + object_class, + PROP_PREVIEW_VISIBLE, + g_param_spec_boolean ( + "preview-visible", + _("Preview is Visible"), + _("Whether the preview pane is visible"), + TRUE, + G_PARAM_READWRITE)); +} + +static void +memo_shell_content_init (EMemoShellContent *memo_shell_content) +{ + memo_shell_content->priv = + E_MEMO_SHELL_CONTENT_GET_PRIVATE (memo_shell_content); + + memo_shell_content->priv->memo_model = e_cal_model_memos_new (); + + /* Postpone widget construction until we have a shell view. */ +} + +GType +e_memo_shell_content_get_type (void) +{ + return memo_shell_content_type; +} + +void +e_memo_shell_content_register_type (GTypeModule *type_module) +{ + static const GTypeInfo type_info = { + sizeof (EMemoShellContentClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) memo_shell_content_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMemoShellContent), + 0, /* n_preallocs */ + (GInstanceInitFunc) memo_shell_content_init, + NULL /* value_table */ + }; + + memo_shell_content_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_CONTENT, + "EMemoShellContent", &type_info, 0); +} + +GtkWidget * +e_memo_shell_content_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_MEMO_SHELL_CONTENT, + "shell-view", shell_view, NULL); +} + +ECalModel * +e_memo_shell_content_get_memo_model (EMemoShellContent *memo_shell_content) +{ + g_return_val_if_fail ( + E_IS_MEMO_SHELL_CONTENT (memo_shell_content), NULL); + + return memo_shell_content->priv->memo_model; +} + +ECalComponentPreview * +e_memo_shell_content_get_memo_preview (EMemoShellContent *memo_shell_content) +{ + g_return_val_if_fail ( + E_IS_MEMO_SHELL_CONTENT (memo_shell_content), NULL); + + return E_CAL_COMPONENT_PREVIEW ( + memo_shell_content->priv->memo_preview); +} + +EMemoTable * +e_memo_shell_content_get_memo_table (EMemoShellContent *memo_shell_content) +{ + g_return_val_if_fail ( + E_IS_MEMO_SHELL_CONTENT (memo_shell_content), NULL); + + return E_MEMO_TABLE (memo_shell_content->priv->memo_table); +} + +GalViewInstance * +e_memo_shell_content_get_view_instance (EMemoShellContent *memo_shell_content) +{ + g_return_val_if_fail ( + E_IS_MEMO_SHELL_CONTENT (memo_shell_content), NULL); + + return memo_shell_content->priv->view_instance; +} + +gboolean +e_memo_shell_content_get_preview_visible (EMemoShellContent *memo_shell_content) +{ + GtkPaned *paned; + GtkWidget *child; + + g_return_val_if_fail ( + E_IS_MEMO_SHELL_CONTENT (memo_shell_content), FALSE); + + paned = GTK_PANED (memo_shell_content->priv->paned); + child = gtk_paned_get_child2 (paned); + + return GTK_WIDGET_VISIBLE (child); +} + +void +e_memo_shell_content_set_preview_visible (EMemoShellContent *memo_shell_content, + gboolean preview_visible) +{ + GtkPaned *paned; + GtkWidget *child; + + g_return_if_fail (E_IS_MEMO_SHELL_CONTENT (memo_shell_content)); + + paned = GTK_PANED (memo_shell_content->priv->paned); + child = gtk_paned_get_child2 (paned); + + if (preview_visible) + gtk_widget_show (child); + else + gtk_widget_hide (child); + + g_object_notify (G_OBJECT (memo_shell_content), "preview-visible"); +} diff --git a/modules/calendar/e-memo-shell-content.h b/modules/calendar/e-memo-shell-content.h new file mode 100644 index 0000000000..84c22d6ce4 --- /dev/null +++ b/modules/calendar/e-memo-shell-content.h @@ -0,0 +1,96 @@ +/* + * e-memo-shell-content.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MEMO_SHELL_CONTENT_H +#define E_MEMO_SHELL_CONTENT_H + +#include +#include + +#include +#include + +#include + +/* Standard GObject macros */ +#define E_TYPE_MEMO_SHELL_CONTENT \ + (e_memo_shell_content_get_type ()) +#define E_MEMO_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MEMO_SHELL_CONTENT, EMemoShellContent)) +#define E_MEMO_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MEMO_SHELL_CONTENT, EMemoShellContentClass)) +#define E_IS_MEMO_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MEMO_SHELL_CONTENT)) +#define E_IS_MEMO_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MEMO_SHELL_CONTENT)) +#define E_MEMO_SHELL_CONTENT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MEMO_SHELL_CONTENT, EMemoShellContentClass)) + +G_BEGIN_DECLS + +typedef struct _EMemoShellContent EMemoShellContent; +typedef struct _EMemoShellContentClass EMemoShellContentClass; +typedef struct _EMemoShellContentPrivate EMemoShellContentPrivate; + +enum { + E_MEMO_SHELL_CONTENT_SELECTION_SINGLE = 1 << 0, + E_MEMO_SHELL_CONTENT_SELECTION_MULTIPLE = 1 << 1, + E_MEMO_SHELL_CONTENT_SELECTION_CAN_EDIT = 1 << 2, + E_MEMO_SHELL_CONTENT_SELECTION_HAS_URL = 1 << 3 +}; + +struct _EMemoShellContent { + EShellContent parent; + EMemoShellContentPrivate *priv; +}; + +struct _EMemoShellContentClass { + EShellContentClass parent_class; +}; + +GType e_memo_shell_content_get_type (void); +void e_memo_shell_content_register_type + (GTypeModule *type_module); +GtkWidget * e_memo_shell_content_new(EShellView *shell_view); +ECalModel * e_memo_shell_content_get_memo_model + (EMemoShellContent *memo_shell_conent); +ECalComponentPreview * + e_memo_shell_content_get_memo_preview + (EMemoShellContent *memo_shell_content); +EMemoTable * e_memo_shell_content_get_memo_table + (EMemoShellContent *memo_shell_content); +GalViewInstance * + e_memo_shell_content_get_view_instance + (EMemoShellContent *memo_shell_content); +gboolean e_memo_shell_content_get_preview_visible + (EMemoShellContent *memo_shell_content); +void e_memo_shell_content_set_preview_visible + (EMemoShellContent *memo_shell_content, + gboolean preview_visible); + +G_END_DECLS + +#endif /* E_MEMO_SHELL_CONTENT_H */ diff --git a/modules/calendar/e-memo-shell-migrate.c b/modules/calendar/e-memo-shell-migrate.c new file mode 100644 index 0000000000..d2e7df6d1b --- /dev/null +++ b/modules/calendar/e-memo-shell-migrate.c @@ -0,0 +1,257 @@ +/* + * e-memo-shell-migrate.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-memo-shell-migrate.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/calendar-config-keys.h" + +#define WEBCAL_BASE_URI "webcal://" +#define PERSONAL_RELATIVE_URI "system" +#define GROUPWISE_BASE_URI "groupwise://" + +static void +create_memo_sources (EShellBackend *shell_backend, + ESourceList *source_list, + ESourceGroup **on_this_computer, + ESourceGroup **on_the_web, + ESource **personal_source) +{ + GSList *groups; + ESourceGroup *group; + gchar *base_uri, *base_uri_proto; + const gchar *base_dir; + + *on_this_computer = NULL; + *on_the_web = NULL; + *personal_source = NULL; + + base_dir = e_shell_backend_get_config_dir (shell_backend); + base_uri = g_build_filename (base_dir, "local", NULL); + + base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL); + + groups = e_source_list_peek_groups (source_list); + if (groups) { + /* groups are already there, we need to search for things... */ + GSList *g; + + for (g = groups; g; g = g->next) { + + group = E_SOURCE_GROUP (g->data); + + if (!*on_this_computer && !strcmp (base_uri_proto, e_source_group_peek_base_uri (group))) + *on_this_computer = g_object_ref (group); + else if (!*on_the_web && !strcmp (WEBCAL_BASE_URI, e_source_group_peek_base_uri (group))) + *on_the_web = g_object_ref (group); + } + } + + if (*on_this_computer) { + /* make sure "Personal" shows up as a source under + this group */ + GSList *sources = e_source_group_peek_sources (*on_this_computer); + GSList *s; + for (s = sources; s; s = s->next) { + ESource *source = E_SOURCE (s->data); + const gchar *relative_uri; + + relative_uri = e_source_peek_relative_uri (source); + if (relative_uri == NULL) + continue; + if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) { + *personal_source = g_object_ref (source); + break; + } + } + } else { + /* create the local source group */ + group = e_source_group_new (_("On This Computer"), base_uri_proto); + e_source_list_add_group (source_list, group, -1); + + *on_this_computer = group; + } + + if (!*personal_source) { + /* Create the default Person task list */ + ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); + e_source_group_add_source (*on_this_computer, source, -1); + + if (!calendar_config_get_primary_memos () && !calendar_config_get_memos_selected ()) { + GSList selected; + + calendar_config_set_primary_memos (e_source_peek_uid (source)); + + selected.data = (gpointer)e_source_peek_uid (source); + selected.next = NULL; + calendar_config_set_memos_selected (&selected); + } + + e_source_set_color_spec (source, "#BECEDD"); + *personal_source = source; + } + + if (!*on_the_web) { + /* Create the Webcal source group */ + group = e_source_group_new (_("On The Web"), WEBCAL_BASE_URI); + e_source_list_add_group (source_list, group, -1); + + *on_the_web = group; + } + + g_free (base_uri_proto); + g_free (base_uri); +} + +static gboolean +is_groupwise_account (EAccount *account) +{ + if (account->source->url != NULL) { + return g_str_has_prefix (account->source->url, GROUPWISE_BASE_URI); + } else { + return FALSE; + } +} + +static void +add_gw_esource (ESourceList *source_list, const gchar *group_name, const gchar *source_name, CamelURL *url, GConfClient *client) +{ + ESourceGroup *group; + ESource *source; + GSList *ids, *temp; + GError *error = NULL; + gchar *relative_uri; + const gchar *soap_port; + const gchar * use_ssl; + const gchar *poa_address; + const gchar *offline_sync; + + + poa_address = url->host; + if (!poa_address || strlen (poa_address) ==0) + return; + soap_port = camel_url_get_param (url, "soap_port"); + + if (!soap_port || strlen (soap_port) == 0) + soap_port = "7191"; + + use_ssl = camel_url_get_param (url, "use_ssl"); + offline_sync = camel_url_get_param (url, "offline_sync"); + + group = e_source_group_new (group_name, GROUPWISE_BASE_URI); + if (!e_source_list_add_group (source_list, group, -1)) + return; + relative_uri = g_strdup_printf ("%s@%s/", url->user, poa_address); + + source = e_source_new (source_name, relative_uri); + e_source_set_property (source, "auth", "1"); + e_source_set_property (source, "username", url->user); + e_source_set_property (source, "port", camel_url_get_param (url, "soap_port")); + e_source_set_property (source, "auth-domain", "Groupwise"); + e_source_set_property (source, "use_ssl", use_ssl); + e_source_set_property (source, "offline_sync", offline_sync ? "1" : "0" ); + + e_source_set_color_spec (source, "#EEBC60"); + e_source_group_add_source (group, source, -1); + + ids = gconf_client_get_list (client, CALENDAR_CONFIG_MEMOS_SELECTED_MEMOS, GCONF_VALUE_STRING, &error); + if ( error != NULL ) { + g_warning("%s (%s) %s\n", G_STRLOC, G_STRFUNC, error->message); + g_error_free(error); + } + ids = g_slist_append (ids, g_strdup (e_source_peek_uid (source))); + gconf_client_set_list (client, CALENDAR_CONFIG_MEMOS_SELECTED_MEMOS, GCONF_VALUE_STRING, ids, NULL); + temp = ids; + for (; temp != NULL; temp = g_slist_next (temp)) + g_free (temp->data); + + g_slist_free (ids); + g_object_unref (source); + g_object_unref (group); + g_free (relative_uri); +} + +gboolean +e_memo_shell_backend_migrate (EShellBackend *shell_backend, + gint major, + gint minor, + gint revision, + GError **error) +{ + ESourceGroup *on_this_computer = NULL; + ESourceGroup *on_the_web = NULL; + ESource *personal_source = NULL; + ESourceList *source_list = NULL; + gboolean retval = FALSE; + + source_list = g_object_get_data ( + G_OBJECT (shell_backend), "source-list"); + + /* we call this unconditionally now - create_groups either + creates the groups/sources or it finds the necessary + groups/sources. */ + create_memo_sources ( + shell_backend, source_list, &on_this_computer, + &on_the_web, &personal_source); + + /* Migration for Gw accounts between versions < 2.8 */ + if (major == 2 && minor < 8) { + EAccountList *al; + EAccount *a; + CamelURL *url; + EIterator *it; + GConfClient *gconf_client = gconf_client_get_default (); + al = e_account_list_new (gconf_client); + for (it = e_list_get_iterator((EList *)al); + e_iterator_is_valid(it); + e_iterator_next(it)) { + a = (EAccount *) e_iterator_get(it); + if (!a->enabled || !is_groupwise_account (a)) + continue; + url = camel_url_new (a->source->url, NULL); + add_gw_esource (source_list, a->name, _("Notes"), url, gconf_client); + camel_url_free (url); + } + g_object_unref (al); + g_object_unref (gconf_client); + } + + e_source_list_sync (source_list, NULL); + retval = TRUE; + + if (on_this_computer) + g_object_unref (on_this_computer); + if (on_the_web) + g_object_unref (on_the_web); + if (personal_source) + g_object_unref (personal_source); + + return retval; +} diff --git a/modules/calendar/e-memo-shell-migrate.h b/modules/calendar/e-memo-shell-migrate.h new file mode 100644 index 0000000000..ba163c6950 --- /dev/null +++ b/modules/calendar/e-memo-shell-migrate.h @@ -0,0 +1,38 @@ +/* + * e-memo-shell-backend-migrate.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MEMO_SHELL_BACKEND_MIGRATE_H +#define E_MEMO_SHELL_BACKEND_MIGRATE_H + +#include +#include + +G_BEGIN_DECLS + +gboolean e_memo_shell_backend_migrate (EShellBackend *shell_backend, + gint major, + gint minor, + gint micro, + GError **error); + +G_END_DECLS + +#endif /* E_MEMO_SHELL_BACKEND_MIGRATE_H */ diff --git a/modules/calendar/e-memo-shell-sidebar.c b/modules/calendar/e-memo-shell-sidebar.c new file mode 100644 index 0000000000..ca5d05c40b --- /dev/null +++ b/modules/calendar/e-memo-shell-sidebar.c @@ -0,0 +1,718 @@ +/* + * e-memo-shell-sidebar.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-memo-shell-sidebar.h" + +#include +#include +#include + +#include "e-util/e-error.h" +#include "e-util/e-util.h" +#include "calendar/common/authentication.h" +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/e-memo-list-selector.h" +#include "calendar/gui/misc.h" + +#include "e-memo-shell-view.h" +#include "e-memo-shell-backend.h" + +#define E_MEMO_SHELL_SIDEBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MEMO_SHELL_SIDEBAR, EMemoShellSidebarPrivate)) + +struct _EMemoShellSidebarPrivate { + GtkWidget *selector; + + /* UID -> Client */ + GHashTable *client_table; +}; + +enum { + PROP_0, + PROP_SELECTOR +}; + +enum { + CLIENT_ADDED, + CLIENT_REMOVED, + STATUS_MESSAGE, + LAST_SIGNAL +}; + +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; +static GType memo_shell_sidebar_type; + +static void +memo_shell_sidebar_emit_client_added (EMemoShellSidebar *memo_shell_sidebar, + ECal *client) +{ + guint signal_id = signals[CLIENT_ADDED]; + + g_signal_emit (memo_shell_sidebar, signal_id, 0, client); +} + +static void +memo_shell_sidebar_emit_client_removed (EMemoShellSidebar *memo_shell_sidebar, + ECal *client) +{ + guint signal_id = signals[CLIENT_REMOVED]; + + g_signal_emit (memo_shell_sidebar, signal_id, 0, client); +} + +static void +memo_shell_sidebar_emit_status_message (EMemoShellSidebar *memo_shell_sidebar, + const gchar *status_message) +{ + guint signal_id = signals[STATUS_MESSAGE]; + + g_signal_emit (memo_shell_sidebar, signal_id, 0, status_message, -1.0); +} + +static void +memo_shell_sidebar_update_timezone (EMemoShellSidebar *memo_shell_sidebar) +{ + GHashTable *client_table; + icaltimezone *zone; + GList *values; + + zone = calendar_config_get_icaltimezone (); + client_table = memo_shell_sidebar->priv->client_table; + values = g_hash_table_get_values (client_table); + + while (values != NULL) { + ECal *client = values->data; + + if (e_cal_get_load_state (client) == E_CAL_LOAD_LOADED) + e_cal_set_default_timezone (client, zone, NULL); + + values = g_list_delete_link (values, values); + } + + /* XXX Need to call e_cal_component_preview_set_default_timezone() + * here but the sidebar is not really supposed to access content + * stuff. I guess we could emit an "update-timezone" signal + * here, but that feels wrong. Maybe this whole thing should + * be in EMemoShellView instead. */ +} + +static void +memo_shell_sidebar_backend_died_cb (EMemoShellSidebar *memo_shell_sidebar, + ECal *client) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + GHashTable *client_table; + ESource *source; + const gchar *uid; + + client_table = memo_shell_sidebar->priv->client_table; + + shell_sidebar = E_SHELL_SIDEBAR (memo_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + source = e_cal_get_source (client); + uid = e_source_peek_uid (source); + + g_object_ref (source); + + g_hash_table_remove (client_table, uid); + memo_shell_sidebar_emit_status_message (memo_shell_sidebar, NULL); + + e_error_run ( + GTK_WINDOW (shell_window), + "calendar:memos-crashed", NULL); + + g_object_unref (source); +} + +static void +memo_shell_sidebar_backend_error_cb (EMemoShellSidebar *memo_shell_sidebar, + const gchar *message, + ECal *client) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + GtkWidget *dialog; + const gchar *uri; + gchar *uri_no_passwd; + + shell_sidebar = E_SHELL_SIDEBAR (memo_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + uri = e_cal_get_uri (client); + uri_no_passwd = get_uri_without_password (uri); + + dialog = gtk_message_dialog_new ( + GTK_WINDOW (shell_window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, + _("Error on %s\n%s"), + uri_no_passwd, message); + + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + + g_free (uri_no_passwd); +} + +static void +memo_shell_sidebar_client_opened_cb (EMemoShellSidebar *memo_shell_sidebar, + ECalendarStatus status, + ECal *client) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + ESource *source; + + source = e_cal_get_source (client); + + shell_sidebar = E_SHELL_SIDEBAR (memo_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + if (status == E_CALENDAR_STATUS_AUTHENTICATION_FAILED || + status == E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED) + auth_cal_forget_password (client); + + switch (status) { + case E_CALENDAR_STATUS_OK: + g_signal_handlers_disconnect_matched ( + client, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, + memo_shell_sidebar_client_opened_cb, NULL); + + memo_shell_sidebar_emit_status_message ( + memo_shell_sidebar, _("Loading memos")); + memo_shell_sidebar_emit_client_added ( + memo_shell_sidebar, client); + memo_shell_sidebar_emit_status_message ( + memo_shell_sidebar, NULL); + break; + + case E_CALENDAR_STATUS_AUTHENTICATION_FAILED: + e_cal_open_async (client, FALSE); + break; + + case E_CALENDAR_STATUS_BUSY: + break; + + case E_CALENDAR_STATUS_REPOSITORY_OFFLINE: + e_error_run ( + GTK_WINDOW (shell_window), + "calendar:prompt-no-contents-offline-memos", + NULL); + break; + + default: + memo_shell_sidebar_emit_client_removed ( + memo_shell_sidebar, client); + break; + } +} + +static void +memo_shell_sidebar_row_changed_cb (EMemoShellSidebar *memo_shell_sidebar, + GtkTreePath *tree_path, + GtkTreeIter *tree_iter, + GtkTreeModel *tree_model) +{ + ESourceSelector *selector; + ESource *source; + + /* XXX ESourceSelector's underlying tree store has only one + * column: ESource objects. While we're not supposed to + * know this, listening for "row-changed" signals from + * the model is easier to deal with than the selector's + * "selection-changed" signal, which doesn't tell you + * _which_ row changed. */ + + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + gtk_tree_model_get (tree_model, tree_iter, 0, &source, -1); + + /* XXX This signal gets emitted a lot while the model is being + * rebuilt, during which time we won't get a valid ESource. + * ESourceSelector should probably block this signal while + * rebuilding the model, but we'll be forgiving and not + * emit a warning. */ + if (!E_IS_SOURCE (source)) + return; + + if (e_source_selector_source_is_selected (selector, source)) + e_memo_shell_sidebar_add_source (memo_shell_sidebar, source); + else + e_memo_shell_sidebar_remove_source (memo_shell_sidebar, source); +} + +static void +memo_shell_sidebar_selection_changed_cb (EMemoShellSidebar *memo_shell_sidebar, + ESourceSelector *selector) +{ + GSList *list, *iter; + + /* This signal is emitted less frequently than "row-changed", + * especially when the model is being rebuilt. So we'll take + * it easy on poor GConf. */ + + list = e_source_selector_get_selection (selector); + + for (iter = list; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + + iter->data = (gpointer) e_source_peek_uid (source); + g_object_unref (source); + } + + calendar_config_set_memos_selected (list); + + g_slist_free (list); +} + +static void +memo_shell_sidebar_primary_selection_changed_cb (EMemoShellSidebar *memo_shell_sidebar, + ESourceSelector *selector) +{ + ESource *source; + const gchar *uid; + + /* XXX ESourceSelector needs a "primary-selection-uid" property + * so we can just bind the property with GConfBridge. */ + + source = e_source_selector_peek_primary_selection (selector); + if (source == NULL) + return; + + uid = e_source_peek_uid (source); + calendar_config_set_primary_memos (uid); +} + +static void +memo_shell_sidebar_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SELECTOR: + g_value_set_object ( + value, e_memo_shell_sidebar_get_selector ( + E_MEMO_SHELL_SIDEBAR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +memo_shell_sidebar_dispose (GObject *object) +{ + EMemoShellSidebarPrivate *priv; + + priv = E_MEMO_SHELL_SIDEBAR_GET_PRIVATE (object); + + if (priv->selector != NULL) { + g_object_unref (priv->selector); + priv->selector = NULL; + } + + g_hash_table_remove_all (priv->client_table); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +memo_shell_sidebar_finalize (GObject *object) +{ + EMemoShellSidebarPrivate *priv; + + priv = E_MEMO_SHELL_SIDEBAR_GET_PRIVATE (object); + + g_hash_table_destroy (priv->client_table); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +memo_shell_sidebar_constructed (GObject *object) +{ + EMemoShellSidebarPrivate *priv; + EShellView *shell_view; + EShellBackend *shell_backend; + EShellSidebar *shell_sidebar; + ESourceSelector *selector; + ESourceList *source_list; + ESource *source; + GtkContainer *container; + GtkTreeModel *model; + GtkWidget *widget; + AtkObject *a11y; + GSList *list, *iter; + gchar *uid; + + priv = E_MEMO_SHELL_SIDEBAR_GET_PRIVATE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + shell_sidebar = E_SHELL_SIDEBAR (object); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + source_list = e_memo_shell_backend_get_source_list ( + E_MEMO_SHELL_BACKEND (shell_backend)); + + container = GTK_CONTAINER (shell_sidebar); + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_container_add (container, widget); + gtk_widget_show (widget); + + container = GTK_CONTAINER (widget); + + widget = e_memo_list_selector_new (source_list); + e_source_selector_set_select_new (E_SOURCE_SELECTOR (widget), TRUE); + gtk_container_add (container, widget); + a11y = gtk_widget_get_accessible (widget); + atk_object_set_name (a11y, _("Memo List Selector")); + priv->selector = g_object_ref (widget); + gtk_widget_show (widget); + + /* Restore the selector state from the last session. */ + + selector = E_SOURCE_SELECTOR (priv->selector); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); + + g_signal_connect_swapped ( + model, "row-changed", + G_CALLBACK (memo_shell_sidebar_row_changed_cb), + object); + + source = NULL; + uid = calendar_config_get_primary_memos (); + if (uid != NULL) + source = e_source_list_peek_source_by_uid (source_list, uid); + if (source == NULL) + source = e_source_list_peek_source_any (source_list); + if (source != NULL) + e_source_selector_set_primary_selection (selector, source); + g_free (uid); + + list = calendar_config_get_memos_selected (); + for (iter = list; iter != NULL; iter = iter->next) { + uid = iter->data; + source = e_source_list_peek_source_by_uid (source_list, uid); + g_free (uid); + + if (source == NULL) + continue; + + e_source_selector_select_source (selector, source); + } + g_slist_free (list); + + /* Listen for subsequent changes to the selector. */ + + g_signal_connect_swapped ( + widget, "selection-changed", + G_CALLBACK (memo_shell_sidebar_selection_changed_cb), + object); + + g_signal_connect_swapped ( + widget, "primary-selection-changed", + G_CALLBACK (memo_shell_sidebar_primary_selection_changed_cb), + object); +} + +static guint32 +memo_shell_sidebar_check_state (EShellSidebar *shell_sidebar) +{ + EMemoShellSidebar *memo_shell_sidebar; + ESourceSelector *selector; + ESource *source; + gboolean is_system = FALSE; + guint32 state = 0; + + memo_shell_sidebar = E_MEMO_SHELL_SIDEBAR (shell_sidebar); + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + + if (source != NULL) { + const gchar *uri; + + uri = e_source_peek_relative_uri (source); + is_system = (uri == NULL || strcmp (uri, "system") == 0); + } + + if (source != NULL) + state |= E_MEMO_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE; + if (is_system) + state |= E_MEMO_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM; + + return state; +} + +static void +memo_shell_sidebar_client_added (EMemoShellSidebar *memo_shell_sidebar, + ECal *client) +{ + memo_shell_sidebar_update_timezone (memo_shell_sidebar); +} + +static void +memo_shell_sidebar_client_removed (EMemoShellSidebar *memo_shell_sidebar, + ECal *client) +{ + ESourceSelector *selector; + GHashTable *client_table; + ESource *source; + const gchar *uid; + + client_table = memo_shell_sidebar->priv->client_table; + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + + g_signal_handlers_disconnect_matched ( + client, G_SIGNAL_MATCH_DATA, 0, 0, + NULL, NULL, memo_shell_sidebar); + + source = e_cal_get_source (client); + e_source_selector_unselect_source (selector, source); + + uid = e_source_peek_uid (source); + g_hash_table_remove (client_table, uid); + + memo_shell_sidebar_emit_status_message (memo_shell_sidebar, NULL); +} + +static void +memo_shell_sidebar_class_init (EMemoShellSidebarClass *class) +{ + GObjectClass *object_class; + EShellSidebarClass *shell_sidebar_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMemoShellSidebarPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->get_property = memo_shell_sidebar_get_property; + object_class->dispose = memo_shell_sidebar_dispose; + object_class->finalize = memo_shell_sidebar_finalize; + object_class->constructed = memo_shell_sidebar_constructed; + + shell_sidebar_class = E_SHELL_SIDEBAR_CLASS (class); + shell_sidebar_class->check_state = memo_shell_sidebar_check_state; + + class->client_added = memo_shell_sidebar_client_added; + class->client_removed = memo_shell_sidebar_client_removed; + + g_object_class_install_property ( + object_class, + PROP_SELECTOR, + g_param_spec_object ( + "selector", + _("Source Selector Widget"), + _("This widget displays groups of memo lists"), + E_TYPE_SOURCE_SELECTOR, + G_PARAM_READABLE)); + + signals[CLIENT_ADDED] = g_signal_new ( + "client-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMemoShellSidebarClass, client_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CAL); + + signals[CLIENT_REMOVED] = g_signal_new ( + "client-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMemoShellSidebarClass, client_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CAL); + + signals[STATUS_MESSAGE] = g_signal_new ( + "status-message", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EMemoShellSidebarClass, status_message), + NULL, NULL, + e_marshal_VOID__STRING_DOUBLE, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_DOUBLE); +} + +static void +memo_shell_sidebar_init (EMemoShellSidebar *memo_shell_sidebar) +{ + GHashTable *client_table; + + client_table = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_object_unref); + + memo_shell_sidebar->priv = + E_MEMO_SHELL_SIDEBAR_GET_PRIVATE (memo_shell_sidebar); + + memo_shell_sidebar->priv->client_table = client_table; + + /* Postpone widget construction until we have a shell view. */ +} + +GType +e_memo_shell_sidebar_get_type (void) +{ + return memo_shell_sidebar_type; +} + +void +e_memo_shell_sidebar_register_type (GTypeModule *type_module) +{ + static const GTypeInfo type_info = { + sizeof (EMemoShellSidebarClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) memo_shell_sidebar_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMemoShellSidebar), + 0, /* n_preallocs */ + (GInstanceInitFunc) memo_shell_sidebar_init, + NULL /* value_table */ + }; + + memo_shell_sidebar_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_SIDEBAR, + "EMemoShellSidebar", &type_info, 0); +} + +GtkWidget * +e_memo_shell_sidebar_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_MEMO_SHELL_SIDEBAR, + "shell-view", shell_view, NULL); +} + +ESourceSelector * +e_memo_shell_sidebar_get_selector (EMemoShellSidebar *memo_shell_sidebar) +{ + g_return_val_if_fail ( + E_IS_MEMO_SHELL_SIDEBAR (memo_shell_sidebar), NULL); + + return E_SOURCE_SELECTOR (memo_shell_sidebar->priv->selector); +} + +void +e_memo_shell_sidebar_add_source (EMemoShellSidebar *memo_shell_sidebar, + ESource *source) +{ + ESourceSelector *selector; + GHashTable *client_table; + ECal *client; + const gchar *uid; + const gchar *uri; + gchar *message; + + g_return_if_fail (E_IS_MEMO_SHELL_SIDEBAR (memo_shell_sidebar)); + g_return_if_fail (E_IS_SOURCE (source)); + + client_table = memo_shell_sidebar->priv->client_table; + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + + uid = e_source_peek_uid (source); + client = g_hash_table_lookup (client_table, uid); + + if (client != NULL) + return; + + client = auth_new_cal_from_source (source, E_CAL_SOURCE_TYPE_JOURNAL); + g_return_if_fail (client != NULL); + + g_signal_connect_swapped ( + client, "backend-died", + G_CALLBACK (memo_shell_sidebar_backend_died_cb), + memo_shell_sidebar); + + g_signal_connect_swapped ( + client, "backend-error", + G_CALLBACK (memo_shell_sidebar_backend_error_cb), + memo_shell_sidebar); + + g_hash_table_insert (client_table, g_strdup (uid), client); + e_source_selector_select_source (selector, source); + + uri = e_cal_get_uri (client); + message = g_strdup_printf (_("Opening memos at %s"), uri); + memo_shell_sidebar_emit_status_message (memo_shell_sidebar, message); + g_free (message); + + g_signal_connect_swapped ( + client, "cal-opened", + G_CALLBACK (memo_shell_sidebar_client_opened_cb), + memo_shell_sidebar); + + e_cal_open_async (client, FALSE); +} + +void +e_memo_shell_sidebar_remove_source (EMemoShellSidebar *memo_shell_sidebar, + ESource *source) +{ + ESourceSelector *selector; + GHashTable *client_table; + ECal *client; + const gchar *uid; + + g_return_if_fail (E_IS_MEMO_SHELL_SIDEBAR (memo_shell_sidebar)); + g_return_if_fail (E_IS_SOURCE (source)); + + client_table = memo_shell_sidebar->priv->client_table; + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + + uid = e_source_peek_uid (source); + client = g_hash_table_lookup (client_table, uid); + + if (client == NULL) + return; + + memo_shell_sidebar_emit_client_removed (memo_shell_sidebar, client); +} diff --git a/modules/calendar/e-memo-shell-sidebar.h b/modules/calendar/e-memo-shell-sidebar.h new file mode 100644 index 0000000000..665c8f218a --- /dev/null +++ b/modules/calendar/e-memo-shell-sidebar.h @@ -0,0 +1,95 @@ +/* + * e-memo-shell-sidebar.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MEMO_SHELL_SIDEBAR_H +#define E_MEMO_SHELL_SIDEBAR_H + +#include +#include + +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_MEMO_SHELL_SIDEBAR \ + (e_memo_shell_sidebar_get_type ()) +#define E_MEMO_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MEMO_SHELL_SIDEBAR, EMemoShellSidebar)) +#define E_MEMO_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MEMO_SHELL_SIDEBAR, EMemoShellSidebarClass)) +#define E_IS_MEMO_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MEMO_SHELL_SIDEBAR)) +#define E_IS_MEMO_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MEMO_SHELL_SIDEBAR)) +#define E_MEMO_SHELL_SIDEBAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MEMO_SHELL_SIDEBAR, EMemoShellSidebarClass)) + +G_BEGIN_DECLS + +typedef struct _EMemoShellSidebar EMemoShellSidebar; +typedef struct _EMemoShellSidebarClass EMemoShellSidebarClass; +typedef struct _EMemoShellSidebarPrivate EMemoShellSidebarPrivate; + +enum { + E_MEMO_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE = 1 << 0, + E_MEMO_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM = 1 << 1 +}; + +struct _EMemoShellSidebar { + EShellSidebar parent; + EMemoShellSidebarPrivate *priv; +}; + +struct _EMemoShellSidebarClass { + EShellSidebarClass parent_class; + + /* Signals */ + void (*client_added) (EMemoShellSidebar *memo_shell_sidebar, + ECal *client); + void (*client_removed) (EMemoShellSidebar *memo_shell_sidebar, + ECal *client); + void (*status_message) (EMemoShellSidebar *memo_shell_sidebar, + const gchar *status_message, + gdouble percent); +}; + +GType e_memo_shell_sidebar_get_type (void); +void e_memo_shell_sidebar_register_type + (GTypeModule *type_module); +GtkWidget * e_memo_shell_sidebar_new(EShellView *shell_view); +ESourceSelector * + e_memo_shell_sidebar_get_selector + (EMemoShellSidebar *memo_shell_sidebar); +void e_memo_shell_sidebar_add_source + (EMemoShellSidebar *memo_shell_sidebar, + ESource *source); +void e_memo_shell_sidebar_remove_source + (EMemoShellSidebar *memo_shell_sidebar, + ESource *source); + +G_END_DECLS + +#endif /* E_MEMO_SHELL_SIDEBAR_H */ diff --git a/modules/calendar/e-memo-shell-view-actions.c b/modules/calendar/e-memo-shell-view-actions.c new file mode 100644 index 0000000000..1736606abe --- /dev/null +++ b/modules/calendar/e-memo-shell-view-actions.c @@ -0,0 +1,949 @@ +/* + * e-memo-shell-view-actions.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-memo-shell-view-private.h" + +static void +action_gal_save_custom_view_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EShellView *shell_view; + GalViewInstance *view_instance; + + /* All shell views respond to the activation of this action, + * which is defined by EShellWindow. But only the currently + * active shell view proceeds with saving the custom view. */ + shell_view = E_SHELL_VIEW (memo_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + view_instance = e_memo_shell_content_get_view_instance (memo_shell_content); + gal_view_instance_save_as (view_instance); +} + +static void +action_memo_clipboard_copy_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + e_memo_table_copy_clipboard (memo_table); +} + +static void +action_memo_clipboard_cut_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + e_memo_table_cut_clipboard (memo_table); +} + +static void +action_memo_clipboard_paste_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + e_memo_table_paste_clipboard (memo_table); +} + +static void +action_memo_delete_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + ECalComponentPreview *memo_preview; + EMemoTable *memo_table; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + memo_preview = e_memo_shell_content_get_memo_preview (memo_shell_content); + + e_memo_shell_view_set_status_message ( + memo_shell_view, _("Deleting selected memos..."), -1.0); + e_memo_table_delete_selected (memo_table); + e_memo_shell_view_set_status_message (memo_shell_view, NULL, -1.0); + + e_cal_component_preview_clear (memo_preview); +} + +static void +action_memo_forward_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + ECalComponent *comp; + icalcomponent *clone; + GSList *list; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only forward the first selected memo. */ + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_component_set_icalcomponent (comp, clone); + itip_send_comp ( + E_CAL_COMPONENT_METHOD_PUBLISH, comp, + comp_data->client, NULL, NULL, NULL, TRUE); + g_object_unref (comp); +} + +static void +action_memo_list_copy_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellSidebar *memo_shell_sidebar; + EShellWindow *shell_window; + EShellView *shell_view; + ESourceSelector *selector; + ESource *source; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (E_IS_SOURCE (source)); + + copy_source_dialog ( + GTK_WINDOW (shell_window), + source, E_CAL_SOURCE_TYPE_JOURNAL); +} + +static void +action_memo_list_delete_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellBackend *memo_shell_backend; + EMemoShellContent *memo_shell_content; + EMemoShellSidebar *memo_shell_sidebar; + EShellWindow *shell_window; + EShellView *shell_view; + EMemoTable *memo_table; + ECal *client; + ECalModel *model; + ESourceSelector *selector; + ESourceGroup *source_group; + ESourceList *source_list; + ESource *source; + gint response; + gchar *uri; + GError *error = NULL; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + memo_shell_backend = memo_shell_view->priv->memo_shell_backend; + source_list = e_memo_shell_backend_get_source_list (memo_shell_backend); + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + model = e_memo_table_get_model (memo_table); + + memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (E_IS_SOURCE (source)); + + /* Ask for confirmation. */ + response = e_error_run ( + GTK_WINDOW (shell_window), + "calendar:prompt-delete-memo-list", + e_source_peek_name (source)); + if (response != GTK_RESPONSE_YES) + return; + + uri = e_source_get_uri (source); + client = e_cal_model_get_client_for_uri (model, uri); + if (client == NULL) + client = e_cal_new_from_uri (uri, E_CAL_SOURCE_TYPE_JOURNAL); + g_free (uri); + + g_return_if_fail (client != NULL); + + if (!e_cal_remove (client, &error)) { + g_warning ("%s", error->message); + g_error_free (error); + return; + } + + if (e_source_selector_source_is_selected (selector, source)) { + e_memo_shell_sidebar_remove_source ( + memo_shell_sidebar, source); + e_source_selector_unselect_source (selector, source); + } + + source_group = e_source_peek_group (source); + e_source_group_remove_source (source_group, source); + + if (!e_source_list_sync (source_list, &error)) { + g_warning ("%s", error->message); + g_error_free (error); + } +} + +static void +action_memo_list_new_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + calendar_setup_new_memo_list (GTK_WINDOW (shell_window)); +} + +static void +action_memo_list_print_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ETable *table; + GtkPrintOperationAction print_action; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + table = e_memo_table_get_table (memo_table); + + print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; + print_table (table, _("Print Memos"), _("Memos"), print_action); +} + +static void +action_memo_list_print_preview_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ETable *table; + GtkPrintOperationAction print_action; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + table = e_memo_table_get_table (memo_table); + + print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW; + print_table (table, _("Print Memos"), _("Memos"), print_action); +} + +static void +action_memo_list_properties_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellSidebar *memo_shell_sidebar; + EShellView *shell_view; + EShellWindow *shell_window; + ESource *source; + ESourceSelector *selector; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (E_IS_SOURCE (source)); + + calendar_setup_edit_memo_list (GTK_WINDOW (shell_window), source); +} + +static void +action_memo_list_rename_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellSidebar *memo_shell_sidebar; + ESourceSelector *selector; + + memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + + e_source_selector_edit_primary_selection (selector); +} + +static void +action_memo_list_select_one_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellSidebar *memo_shell_sidebar; + ESourceSelector *selector; + ESource *primary; + GSList *list, *iter; + + /* XXX ESourceSelector should provide a function for this. */ + + memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + primary = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (primary != NULL); + + list = e_source_selector_get_selection (selector); + for (iter = list; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + + if (source == primary) + continue; + + e_source_selector_unselect_source (selector, source); + } + e_source_selector_free_selection (list); + + e_source_selector_select_source (selector, primary); +} + +static void +action_memo_new_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + ECal *client; + ECalComponent *comp; + CompEditor *editor; + GSList *list; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + client = comp_data->client; + editor = memo_editor_new (client, shell, COMP_EDITOR_NEW_ITEM); + comp = cal_comp_memo_new_with_defaults (client); + comp_editor_edit_comp (editor, comp); + + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (comp); + g_object_unref (client); +} + +static void +action_memo_open_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + GSList *list; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only open the first selected memo. */ + e_memo_shell_view_open_memo (memo_shell_view, comp_data); +} + +static void +action_memo_open_url_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + icalproperty *prop; + const gchar *uri; + GSList *list; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only open the URI of the first selected memo. */ + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_URL_PROPERTY); + g_return_if_fail (prop == NULL); + + uri = icalproperty_get_url (prop); + e_show_uri (GTK_WINDOW (shell_window), uri); +} + +static void +action_memo_preview_cb (GtkToggleAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + gboolean visible; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + visible = gtk_toggle_action_get_active (action); + e_memo_shell_content_set_preview_visible (memo_shell_content, visible); +} + +static void +action_memo_print_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + ECalComponent *comp; + icalcomponent *clone; + GtkPrintOperationAction print_action; + GSList *list; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only print the first selected memo. */ + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; + e_cal_component_set_icalcomponent (comp, clone); + print_comp (comp, comp_data->client, print_action); + g_object_unref (comp); +} + +static void +action_memo_save_as_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ECalModelComponent *comp_data; + GSList *list; + gchar *filename; + gchar *string; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + list = e_memo_table_get_selected (memo_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + filename = e_file_dialog_save (_("Save as..."), NULL); + if (filename == NULL) + return; + + /* XXX We only save the first selected memo. */ + string = e_cal_get_component_as_string ( + comp_data->client, comp_data->icalcomp); + if (string == NULL) { + g_warning ("Could not convert memo to a string"); + return; + } + + e_write_file_uri (filename, string); + + g_free (filename); + g_free (string); +} + +static void +action_memo_search_cb (GtkRadioAction *action, + GtkRadioAction *current, + EMemoShellView *memo_shell_view) +{ + EShellView *shell_view; + EShellContent *shell_content; + const gchar *search_hint; + + /* XXX Figure out a way to handle this in EShellContent + * instead of every shell view having to handle it. + * The problem is EShellContent does not know what + * the search option actions are for this view. It + * would have to dig up the popup menu and retrieve + * the action for each menu item. Seems messy. */ + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + + search_hint = gtk_action_get_label (GTK_ACTION (current)); + e_shell_content_set_search_hint (shell_content, search_hint); +} + +static void +action_search_execute_cb (GtkAction *action, + EMemoShellView *memo_shell_view) +{ + EShellView *shell_view; + + /* All shell views respond to the activation of this action, + * which is defined by EShellWindow. But only the currently + * active shell view proceeds with executing the search. */ + shell_view = E_SHELL_VIEW (memo_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + e_memo_shell_view_execute_search (memo_shell_view); +} + +static void +action_search_filter_cb (GtkRadioAction *action, + GtkRadioAction *current, + EMemoShellView *memo_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + gtk_action_activate (ACTION (SEARCH_EXECUTE)); +} + +static GtkActionEntry memo_entries[] = { + + { "memo-clipboard-copy", + GTK_STOCK_COPY, + NULL, + NULL, + N_("Copy selected memo"), + G_CALLBACK (action_memo_clipboard_copy_cb) }, + + { "memo-clipboard-cut", + GTK_STOCK_CUT, + NULL, + NULL, + N_("Cut selected memo"), + G_CALLBACK (action_memo_clipboard_cut_cb) }, + + { "memo-clipboard-paste", + GTK_STOCK_PASTE, + NULL, + NULL, + N_("Paste memo from the clipboard"), + G_CALLBACK (action_memo_clipboard_paste_cb) }, + + { "memo-delete", + GTK_STOCK_DELETE, + N_("_Delete Memo"), + NULL, + N_("Delete selected memos"), + G_CALLBACK (action_memo_delete_cb) }, + + { "memo-forward", + "mail-forward", + N_("_Forward as iCalendar..."), + "f", + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_memo_forward_cb) }, + + { "memo-list-copy", + GTK_STOCK_COPY, + N_("_Copy..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_memo_list_copy_cb) }, + + { "memo-list-delete", + GTK_STOCK_DELETE, + N_("_Delete"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_memo_list_delete_cb) }, + + { "memo-list-new", + "stock_notes", + N_("_New Memo List"), + NULL, + N_("Create a new memo list"), + G_CALLBACK (action_memo_list_new_cb) }, + + { "memo-list-properties", + GTK_STOCK_PROPERTIES, + NULL, + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_memo_list_properties_cb) }, + + { "memo-list-rename", + NULL, + N_("_Rename..."), + "F2", + N_("Rename the selected memo list"), + G_CALLBACK (action_memo_list_rename_cb) }, + + { "memo-list-select-one", + "stock_check-filled", + N_("Show _Only This Memo List"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_memo_list_select_one_cb) }, + + { "memo-new", + "stock_insert-note", + N_("New _Memo"), + NULL, + N_("Create a new memo"), + G_CALLBACK (action_memo_new_cb) }, + + { "memo-open", + GTK_STOCK_OPEN, + N_("_Open Memo"), + "o", + N_("View the selected memo"), + G_CALLBACK (action_memo_open_cb) }, + + { "memo-open-url", + "applications-internet", + N_("Open _Web Page"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_memo_open_url_cb) }, + + { "memo-save-as", + GTK_STOCK_SAVE_AS, + N_("_Save as iCalendar..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_memo_save_as_cb) } +}; + +static EPopupActionEntry memo_popup_entries[] = { + + { "memo-list-popup-copy", + NULL, + "memo-list-copy" }, + + { "memo-list-popup-delete", + NULL, + "memo-list-delete" }, + + { "memo-list-popup-properties", + NULL, + "memo-list-properties" }, + + { "memo-list-popup-rename", + NULL, + "memo-list-rename" }, + + { "memo-list-popup-select-one", + NULL, + "memo-list-select-one" }, + + { "memo-popup-clipboard-copy", + NULL, + "memo-clipboard-copy" }, + + { "memo-popup-clipboard-cut", + NULL, + "memo-clipboard-cut" }, + + { "memo-popup-clipboard-paste", + NULL, + "memo-clipboard-paste" }, + + { "memo-popup-delete", + NULL, + "memo-delete" }, + + { "memo-popup-forward", + NULL, + "memo-forward" }, + + { "memo-popup-open", + NULL, + "memo-open" }, + + { "memo-popup-open-url", + NULL, + "memo-open-url" }, + + { "memo-popup-save-as", + NULL, + "memo-save-as" } +}; + +static GtkToggleActionEntry memo_toggle_entries[] = { + + { "memo-preview", + NULL, + N_("Memo _Preview"), + "m", + N_("Show memo preview pane"), + G_CALLBACK (action_memo_preview_cb), + TRUE } +}; + +static GtkRadioActionEntry memo_filter_entries[] = { + + { "memo-filter-any-category", + NULL, + N_("Any Category"), + NULL, + NULL, + MEMO_FILTER_ANY_CATEGORY }, + + { "memo-filter-unmatched", + NULL, + N_("Unmatched"), + NULL, + NULL, + MEMO_FILTER_UNMATCHED } +}; + +static GtkRadioActionEntry memo_search_entries[] = { + + { "memo-search-any-field-contains", + NULL, + N_("Any field contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + MEMO_SEARCH_ANY_FIELD_CONTAINS }, + + { "memo-search-description-contains", + NULL, + N_("Description contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + MEMO_SEARCH_DESCRIPTION_CONTAINS }, + + { "memo-search-summary-contains", + NULL, + N_("Summary contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + MEMO_SEARCH_SUMMARY_CONTAINS } +}; + +static GtkActionEntry lockdown_printing_entries[] = { + + { "memo-list-print", + GTK_STOCK_PRINT, + NULL, + "p", + N_("Print the list of memos"), + G_CALLBACK (action_memo_list_print_cb) }, + + { "memo-list-print-preview", + GTK_STOCK_PRINT_PREVIEW, + NULL, + NULL, + N_("Preview the list of memos to be printed"), + G_CALLBACK (action_memo_list_print_preview_cb) }, + + { "memo-print", + GTK_STOCK_PRINT, + NULL, + NULL, + N_("Print the selected memo"), + G_CALLBACK (action_memo_print_cb) } +}; + +static EPopupActionEntry lockdown_printing_popup_entries[] = { + + { "memo-popup-print", + NULL, + "memo-print" } +}; + +void +e_memo_shell_view_actions_init (EMemoShellView *memo_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkActionGroup *action_group; + GConfBridge *bridge; + GtkAction *action; + GObject *object; + const gchar *key; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + /* Memo Actions */ + action_group = ACTION_GROUP (MEMOS); + gtk_action_group_add_actions ( + action_group, memo_entries, + G_N_ELEMENTS (memo_entries), memo_shell_view); + e_action_group_add_popup_actions ( + action_group, memo_popup_entries, + G_N_ELEMENTS (memo_popup_entries)); + gtk_action_group_add_toggle_actions ( + action_group, memo_toggle_entries, + G_N_ELEMENTS (memo_toggle_entries), memo_shell_view); + gtk_action_group_add_radio_actions ( + action_group, memo_search_entries, + G_N_ELEMENTS (memo_search_entries), + MEMO_SEARCH_SUMMARY_CONTAINS, + G_CALLBACK (action_memo_search_cb), memo_shell_view); + + /* Lockdown Printing Actions */ + action_group = ACTION_GROUP (LOCKDOWN_PRINTING); + gtk_action_group_add_actions ( + action_group, lockdown_printing_entries, + G_N_ELEMENTS (lockdown_printing_entries), memo_shell_view); + e_action_group_add_popup_actions ( + action_group, lockdown_printing_popup_entries, + G_N_ELEMENTS (lockdown_printing_popup_entries)); + + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (ACTION (MEMO_PREVIEW)); + key = "/apps/evolution/calendar/display/show_memo_preview"; + gconf_bridge_bind_property (bridge, key, object, "active"); + + /* Fine tuning. */ + + action = ACTION (MEMO_DELETE); + g_object_set (action, "short-label", _("Delete"), NULL); + + g_signal_connect ( + ACTION (GAL_SAVE_CUSTOM_VIEW), "activate", + G_CALLBACK (action_gal_save_custom_view_cb), memo_shell_view); + + g_signal_connect ( + ACTION (SEARCH_EXECUTE), "activate", + G_CALLBACK (action_search_execute_cb), memo_shell_view); +} + +void +e_memo_shell_view_update_search_filter (EMemoShellView *memo_shell_view) +{ + EShellContent *shell_content; + EShellWindow *shell_window; + EShellView *shell_view; + GtkActionGroup *action_group; + GtkRadioAction *radio_action; + GList *list, *iter; + GSList *group; + gint ii; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + action_group = ACTION_GROUP (MEMOS_FILTER); + e_action_group_remove_all_actions (action_group); + + /* Add the standard filter actions. */ + gtk_action_group_add_radio_actions ( + action_group, memo_filter_entries, + G_N_ELEMENTS (memo_filter_entries), + MEMO_FILTER_ANY_CATEGORY, + G_CALLBACK (action_search_filter_cb), + memo_shell_view); + + /* Retrieve the radio group from an action we just added. */ + list = gtk_action_group_list_actions (action_group); + radio_action = GTK_RADIO_ACTION (list->data); + group = gtk_radio_action_get_group (radio_action); + g_list_free (list); + + /* Build the category actions. */ + + list = e_categories_get_list (); + for (iter = list, ii = 0; iter != NULL; iter = iter->next, ii++) { + const gchar *category_name = iter->data; + const gchar *filename; + GtkAction *action; + gchar *action_name; + + action_name = g_strdup_printf ( + "memo-filter-category-%d", ii); + radio_action = gtk_radio_action_new ( + action_name, category_name, NULL, NULL, ii); + g_free (action_name); + + /* Convert the category icon file to a themed icon name. */ + filename = e_categories_get_icon_file_for (category_name); + if (filename != NULL && *filename != '\0') { + gchar *basename; + gchar *cp; + + basename = g_path_get_basename (filename); + + /* Lose the file extension. */ + if ((cp = strrchr (basename, '.')) != NULL) + *cp = '\0'; + + g_object_set ( + radio_action, "icon-name", basename, NULL); + + g_free (basename); + } + + gtk_radio_action_set_group (radio_action, group); + group = gtk_radio_action_get_group (radio_action); + + /* The action group takes ownership of the action. */ + action = GTK_ACTION (radio_action); + gtk_action_group_add_action (action_group, action); + g_object_unref (radio_action); + } + g_list_free (list); + + /* Use any action in the group; doesn't matter which. */ + e_shell_content_set_filter_action (shell_content, radio_action); + + ii = MEMO_FILTER_UNMATCHED; + e_shell_content_add_filter_separator_after (shell_content, ii); +} diff --git a/modules/calendar/e-memo-shell-view-actions.h b/modules/calendar/e-memo-shell-view-actions.h new file mode 100644 index 0000000000..d6fd3ca514 --- /dev/null +++ b/modules/calendar/e-memo-shell-view-actions.h @@ -0,0 +1,87 @@ +/* + * e-memo-shell-view-actions.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MEMO_SHELL_VIEW_ACTIONS_H +#define E_MEMO_SHELL_VIEW_ACTIONS_H + +#include + +/* Memo Actions */ +#define E_SHELL_WINDOW_ACTION_MEMO_CLIPBOARD_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-clipboard-copy") +#define E_SHELL_WINDOW_ACTION_MEMO_CLIPBOARD_CUT(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-clipboard-cut") +#define E_SHELL_WINDOW_ACTION_MEMO_CLIPBOARD_PASTE(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-clipboard-paste") +#define E_SHELL_WINDOW_ACTION_MEMO_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-delete") +#define E_SHELL_WINDOW_ACTION_MEMO_FORWARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-forward") +#define E_SHELL_WINDOW_ACTION_MEMO_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-new") +#define E_SHELL_WINDOW_ACTION_MEMO_OPEN(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-open") +#define E_SHELL_WINDOW_ACTION_MEMO_OPEN_URL(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-open-url") +#define E_SHELL_WINDOW_ACTION_MEMO_PREVIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-preview") +#define E_SHELL_WINDOW_ACTION_MEMO_PRINT(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-print") +#define E_SHELL_WINDOW_ACTION_MEMO_SAVE_AS(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-save-as") + +/* Memo List Actions */ +#define E_SHELL_WINDOW_ACTION_MEMO_LIST_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-list-copy") +#define E_SHELL_WINDOW_ACTION_MEMO_LIST_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-list-delete") +#define E_SHELL_WINDOW_ACTION_MEMO_LIST_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-list-new") +#define E_SHELL_WINDOW_ACTION_MEMO_LIST_PRINT(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-list-print") +#define E_SHELL_WINDOW_ACTION_MEMO_LIST_PRINT_PREVIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-list-print-preview") +#define E_SHELL_WINDOW_ACTION_MEMO_LIST_PROPERTIES(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-list-properties") +#define E_SHELL_WINDOW_ACTION_MEMO_LIST_RENAME(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-list-rename") +#define E_SHELL_WINDOW_ACTION_MEMO_LIST_SELECT_ONE(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-list-select-one") + +/* Memo Query Actions */ +#define E_SHELL_WINDOW_ACTION_MEMO_FILTER_ANY_CATEGORY(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-filter-any-category") +#define E_SHELL_WINDOW_ACTION_MEMO_FILTER_UNMATCHED(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-filter-unmatched") +#define E_SHELL_WINDOW_ACTION_MEMO_SEARCH_ANY_FIELD_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-search-any-field-contains") +#define E_SHELL_WINDOW_ACTION_MEMO_SEARCH_DESCRIPTION_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-search-description-contains") +#define E_SHELL_WINDOW_ACTION_MEMO_SEARCH_SUMMARY_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-search-summary-contains") + +/* Action Groups */ +#define E_SHELL_WINDOW_ACTION_GROUP_MEMOS(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "memos") +#define E_SHELL_WINDOW_ACTION_GROUP_MEMOS_FILTER(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "memos-filter") + +#endif /* E_MEMO_SHELL_VIEW_ACTIONS_H */ diff --git a/modules/calendar/e-memo-shell-view-private.c b/modules/calendar/e-memo-shell-view-private.c new file mode 100644 index 0000000000..69d6c0afe2 --- /dev/null +++ b/modules/calendar/e-memo-shell-view-private.c @@ -0,0 +1,524 @@ +/* + * e-memo-shell-view-private.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-memo-shell-view-private.h" + +#include "widgets/menus/gal-view-factory-etable.h" + +static void +memo_shell_view_table_popup_event_cb (EShellView *shell_view, + GdkEventButton *event) +{ + const gchar *widget_path; + + widget_path = "/memo-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); +} + +static void +memo_shell_view_table_user_created_cb (EMemoShellView *memo_shell_view, + EMemoTable *memo_table) +{ + EMemoShellSidebar *memo_shell_sidebar; + ECalModel *model; + ECal *client; + ESource *source; + + /* This is the "Click to Add" handler. */ + + model = e_memo_table_get_model (memo_table); + client = e_cal_model_get_default_client (model); + source = e_cal_get_source (client); + + memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; + e_memo_shell_sidebar_add_source (memo_shell_sidebar, source); + + e_cal_model_add_client (model, client); +} + +static void +memo_shell_view_selector_client_added_cb (EMemoShellView *memo_shell_view, + ECal *client) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ECalModel *model; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + model = e_memo_table_get_model (memo_table); + + e_cal_model_add_client (model, client); +} + +static void +memo_shell_view_selector_client_removed_cb (EMemoShellView *memo_shell_view, + ECal *client) +{ + EMemoShellContent *memo_shell_content; + EMemoTable *memo_table; + ECalModel *model; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + model = e_memo_table_get_model (memo_table); + + e_cal_model_remove_client (model, client); +} + +static gboolean +memo_shell_view_selector_popup_event_cb (EShellView *shell_view, + ESource *primary_source, + GdkEventButton *event) +{ + const gchar *widget_path; + + widget_path = "/memo-list-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); + + return TRUE; +} + +static void +memo_shell_view_load_view_collection (EShellViewClass *shell_view_class) +{ + GalViewCollection *collection; + GalViewFactory *factory; + ETableSpecification *spec; + const gchar *base_dir; + gchar *filename; + + collection = shell_view_class->view_collection; + + base_dir = EVOLUTION_ETSPECDIR; + spec = e_table_specification_new (); + filename = g_build_filename (base_dir, ETSPEC_FILENAME, NULL); + if (!e_table_specification_load_from_file (spec, filename)) + g_critical ("Unable to load ETable specification file " + "for memos"); + g_free (filename); + + factory = gal_view_factory_etable_new (spec); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + g_object_unref (spec); + + gal_view_collection_load (collection); +} + +static void +memo_shell_view_notify_view_id_cb (EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + GalViewInstance *view_instance; + const gchar *view_id; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + view_instance = + e_memo_shell_content_get_view_instance (memo_shell_content); + view_id = e_shell_view_get_view_id (E_SHELL_VIEW (memo_shell_view)); + + /* A NULL view ID implies we're in a custom view. But you can + * only get to a custom view via the "Define Views" dialog, which + * would have already modified the view instance appropriately. + * Furthermore, there's no way to refer to a custom view by ID + * anyway, since custom views have no IDs. */ + if (view_id == NULL) + return; + + gal_view_instance_set_current_view_id (view_instance, view_id); +} + +void +e_memo_shell_view_private_init (EMemoShellView *memo_shell_view, + EShellViewClass *shell_view_class) +{ + if (!gal_view_collection_loaded (shell_view_class->view_collection)) + memo_shell_view_load_view_collection (shell_view_class); + + g_signal_connect ( + memo_shell_view, "notify::view-id", + G_CALLBACK (memo_shell_view_notify_view_id_cb), NULL); +} + +void +e_memo_shell_view_private_constructed (EMemoShellView *memo_shell_view) +{ + EMemoShellViewPrivate *priv = memo_shell_view->priv; + EMemoShellContent *memo_shell_content; + EMemoShellSidebar *memo_shell_sidebar; + EShellView *shell_view; + EShellBackend *shell_backend; + EShellContent *shell_content; + EShellSidebar *shell_sidebar; + EShellWindow *shell_window; + EMemoTable *memo_table; + ECalModel *model; + ETable *table; + ESourceSelector *selector; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + e_shell_window_add_action_group (shell_window, "memos"); + e_shell_window_add_action_group (shell_window, "memos-filter"); + + /* Cache these to avoid lots of awkward casting. */ + priv->memo_shell_backend = g_object_ref (shell_backend); + priv->memo_shell_content = g_object_ref (shell_content); + priv->memo_shell_sidebar = g_object_ref (shell_sidebar); + + memo_shell_content = E_MEMO_SHELL_CONTENT (shell_content); + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + model = e_memo_table_get_model (memo_table); + table = e_memo_table_get_table (memo_table); + + memo_shell_sidebar = E_MEMO_SHELL_SIDEBAR (shell_sidebar); + selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + + g_signal_connect_swapped ( + memo_table, "open-component", + G_CALLBACK (e_memo_shell_view_open_memo), + memo_shell_view); + + g_signal_connect_swapped ( + memo_table, "popup-event", + G_CALLBACK (memo_shell_view_table_popup_event_cb), + memo_shell_view); + + g_signal_connect_swapped ( + memo_table, "status-message", + G_CALLBACK (e_memo_shell_view_set_status_message), + memo_shell_view); + + g_signal_connect_swapped ( + memo_table, "user-created", + G_CALLBACK (memo_shell_view_table_user_created_cb), + memo_shell_view); + + g_signal_connect_swapped ( + model, "model-changed", + G_CALLBACK (e_memo_shell_view_update_sidebar), + memo_shell_view); + + g_signal_connect_swapped ( + model, "model-rows-deleted", + G_CALLBACK (e_memo_shell_view_update_sidebar), + memo_shell_view); + + g_signal_connect_swapped ( + model, "model-rows-inserted", + G_CALLBACK (e_memo_shell_view_update_sidebar), + memo_shell_view); + + g_signal_connect_swapped ( + table, "selection-change", + G_CALLBACK (e_memo_shell_view_update_sidebar), + memo_shell_view); + + g_signal_connect_swapped ( + memo_shell_sidebar, "client-added", + G_CALLBACK (memo_shell_view_selector_client_added_cb), + memo_shell_view); + + g_signal_connect_swapped ( + memo_shell_sidebar, "client-removed", + G_CALLBACK (memo_shell_view_selector_client_removed_cb), + memo_shell_view); + + g_signal_connect_swapped ( + memo_shell_sidebar, "status-message", + G_CALLBACK (e_memo_shell_view_set_status_message), + memo_shell_view); + + g_signal_connect_swapped ( + selector, "popup-event", + G_CALLBACK (memo_shell_view_selector_popup_event_cb), + memo_shell_view); + + g_signal_connect_swapped ( + selector, "primary-selection-changed", + G_CALLBACK (e_shell_view_update_actions), + memo_shell_view); + + e_categories_register_change_listener ( + G_CALLBACK (e_memo_shell_view_update_search_filter), + memo_shell_view); + + e_memo_shell_view_actions_init (memo_shell_view); + e_memo_shell_view_update_sidebar (memo_shell_view); + e_memo_shell_view_update_search_filter (memo_shell_view); + + e_memo_shell_view_execute_search (memo_shell_view); +} + +void +e_memo_shell_view_private_dispose (EMemoShellView *memo_shell_view) +{ + EMemoShellViewPrivate *priv = memo_shell_view->priv; + + DISPOSE (priv->memo_shell_backend); + DISPOSE (priv->memo_shell_content); + DISPOSE (priv->memo_shell_sidebar); + + if (memo_shell_view->priv->activity != NULL) { + /* XXX Activity is not cancellable. */ + e_activity_complete (memo_shell_view->priv->activity); + g_object_unref (memo_shell_view->priv->activity); + memo_shell_view->priv->activity = NULL; + } +} + +void +e_memo_shell_view_private_finalize (EMemoShellView *memo_shell_view) +{ + /* XXX Nothing to do? */ +} + +void +e_memo_shell_view_execute_search (EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EShellView *shell_view; + EShellWindow *shell_window; + EShellContent *shell_content; + GtkAction *action; + GString *string; + ECalComponentPreview *memo_preview; + EMemoTable *memo_table; + ECalModel *model; + FilterRule *rule; + const gchar *format; + const gchar *text; + gchar *query; + gchar *temp; + gint value; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + text = e_shell_content_get_search_text (shell_content); + + shell_window = e_shell_view_get_shell_window (shell_view); + action = ACTION (MEMO_SEARCH_ANY_FIELD_CONTAINS); + value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + + if (text == NULL || *text == '\0') { + text = ""; + value = MEMO_SEARCH_SUMMARY_CONTAINS; + } + + switch (value) { + default: + text = ""; + /* fall through */ + + case MEMO_SEARCH_SUMMARY_CONTAINS: + format = "(contains? \"summary\" %s)"; + break; + + case MEMO_SEARCH_DESCRIPTION_CONTAINS: + format = "(contains? \"description\" %s)"; + break; + + case MEMO_SEARCH_ANY_FIELD_CONTAINS: + format = "(contains? \"any\" %s)"; + break; + } + + /* Build the query. */ + string = g_string_new (""); + e_sexp_encode_string (string, text); + query = g_strdup_printf (format, string->str); + g_string_free (string, TRUE); + + /* Apply selected filter. */ + value = e_shell_content_get_filter_value (shell_content); + switch (value) { + case MEMO_FILTER_ANY_CATEGORY: + break; + + case MEMO_FILTER_UNMATCHED: + temp = g_strdup_printf ( + "(and (has-categories? #f) %s", query); + g_free (query); + query = temp; + break; + + default: + { + GList *categories; + const gchar *category_name; + + categories = e_categories_get_list (); + category_name = g_list_nth_data (categories, value); + g_list_free (categories); + + temp = g_strdup_printf ( + "(and (has-categories? \"%s\") %s)", + category_name, query); + g_free (query); + query = temp; + } + } + + /* XXX This is wrong. We need to programmatically construct a + * FilterRule, tell it to build code, and pass the resulting + * expression string to ECalModel. */ + rule = filter_rule_new (); + e_shell_content_set_search_rule (shell_content, rule); + g_object_unref (rule); + + /* Submit the query. */ + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + model = e_memo_table_get_model (memo_table); + e_cal_model_set_search_query (model, query); + g_free (query); + + memo_preview = + e_memo_shell_content_get_memo_preview (memo_shell_content); + e_cal_component_preview_clear (memo_preview); +} + +void +e_memo_shell_view_open_memo (EMemoShellView *memo_shell_view, + ECalModelComponent *comp_data) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + CompEditor *editor; + CompEditorFlags flags = 0; + ECalComponent *comp; + icalcomponent *clone; + const gchar *uid; + + g_return_if_fail (E_IS_MEMO_SHELL_VIEW (memo_shell_view)); + g_return_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data)); + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + + uid = icalcomponent_get_uid (comp_data->icalcomp); + editor = comp_editor_find_instance (uid); + + if (editor != NULL) + goto exit; + + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_component_set_icalcomponent (comp, clone); + + if (e_cal_component_has_organizer (comp)) + flags |= COMP_EDITOR_IS_SHARED; + + if (itip_organizer_is_user (comp, comp_data->client)) + flags |= COMP_EDITOR_USER_ORG; + + editor = memo_editor_new (comp_data->client, shell, flags); + comp_editor_edit_comp (editor, comp); + + g_object_unref (comp); + +exit: + gtk_window_present (GTK_WINDOW (editor)); +} + +void +e_memo_shell_view_set_status_message (EMemoShellView *memo_shell_view, + const gchar *status_message, + gdouble percent) +{ + EActivity *activity; + EShellView *shell_view; + EShellBackend *shell_backend; + + g_return_if_fail (E_IS_MEMO_SHELL_VIEW (memo_shell_view)); + + activity = memo_shell_view->priv->activity; + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + if (status_message == NULL || *status_message == '\0') { + if (activity != NULL) { + e_activity_complete (activity); + g_object_unref (activity); + activity = NULL; + } + + } else if (activity == NULL) { + activity = e_activity_new (status_message); + e_activity_set_percent (activity, percent); + e_shell_backend_add_activity (shell_backend, activity); + + } else { + e_activity_set_percent (activity, percent); + e_activity_set_primary_text (activity, status_message); + } + + memo_shell_view->priv->activity = activity; +} + +void +e_memo_shell_view_update_sidebar (EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EShellView *shell_view; + EShellSidebar *shell_sidebar; + EMemoTable *memo_table; + ECalModel *model; + ETable *table; + GString *string; + const gchar *format; + gint n_rows; + gint n_selected; + + shell_view = E_SHELL_VIEW (memo_shell_view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); + + model = e_memo_table_get_model (memo_table); + table = e_memo_table_get_table (memo_table); + + n_rows = e_table_model_row_count (E_TABLE_MODEL (model)); + n_selected = e_table_selected_count (table); + + string = g_string_sized_new (64); + + format = ngettext ("%d memo", "%d memos", n_rows); + g_string_append_printf (string, format, n_rows); + + if (n_selected > 0) { + format = _("%d selected"); + g_string_append_len (string, ", ", 2); + g_string_append_printf (string, format, n_selected); + } + + e_shell_sidebar_set_secondary_text (shell_sidebar, string->str); + + g_string_free (string, TRUE); +} diff --git a/modules/calendar/e-memo-shell-view-private.h b/modules/calendar/e-memo-shell-view-private.h new file mode 100644 index 0000000000..c41eaed7c0 --- /dev/null +++ b/modules/calendar/e-memo-shell-view-private.h @@ -0,0 +1,126 @@ +/* + * e-memo-shell-view-private.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MEMO_SHELL_VIEW_PRIVATE_H +#define E_MEMO_SHELL_VIEW_PRIVATE_H + +#include "e-memo-shell-view.h" + +#include +#include +#include +#include + +#include "e-util/e-dialog-utils.h" +#include "e-util/e-error.h" +#include "e-util/e-util.h" +#include "e-util/gconf-bridge.h" +#include "widgets/misc/e-popup-action.h" + +#include "calendar/gui/comp-util.h" +#include "calendar/gui/e-cal-component-preview.h" +#include "calendar/gui/e-calendar-selector.h" +#include "calendar/gui/print.h" +#include "calendar/gui/dialogs/calendar-setup.h" +#include "calendar/gui/dialogs/copy-source-dialog.h" +#include "calendar/gui/dialogs/memo-editor.h" + +#include "e-memo-shell-backend.h" +#include "e-memo-shell-content.h" +#include "e-memo-shell-sidebar.h" +#include "e-memo-shell-view-actions.h" + +#define E_MEMO_SHELL_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MEMO_SHELL_VIEW, EMemoShellViewPrivate)) + +/* Shorthand, requires a variable named "shell_window". */ +#define ACTION(name) \ + (E_SHELL_WINDOW_ACTION_##name (shell_window)) +#define ACTION_GROUP(name) \ + (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) + +/* For use in dispose() methods. */ +#define DISPOSE(obj) \ + G_STMT_START { \ + if ((obj) != NULL) { g_object_unref (obj); (obj) = NULL; } \ + } G_STMT_END + +/* ETable Specifications */ +#define ETSPEC_FILENAME "e-memo-table.etspec" + +G_BEGIN_DECLS + +/* Filter items are displayed in ascending order. + * Non-negative values are reserved for categories. */ +enum { + MEMO_FILTER_ANY_CATEGORY = -2, + MEMO_FILTER_UNMATCHED = -1 +}; + +/* Search items are displayed in ascending order. */ +enum { + MEMO_SEARCH_SUMMARY_CONTAINS, + MEMO_SEARCH_DESCRIPTION_CONTAINS, + MEMO_SEARCH_ANY_FIELD_CONTAINS +}; + +struct _EMemoShellViewPrivate { + + /* These are just for convenience. */ + EMemoShellBackend *memo_shell_backend; + EMemoShellContent *memo_shell_content; + EMemoShellSidebar *memo_shell_sidebar; + + EActivity *activity; +}; + +void e_memo_shell_view_private_init + (EMemoShellView *memo_shell_view, + EShellViewClass *shell_view_class); +void e_memo_shell_view_private_constructed + (EMemoShellView *memo_shell_view); +void e_memo_shell_view_private_dispose + (EMemoShellView *memo_shell_view); +void e_memo_shell_view_private_finalize + (EMemoShellView *memo_shell_view); + +/* Private Utilities */ + +void e_memo_shell_view_actions_init + (EMemoShellView *memo_shell_view); +void e_memo_shell_view_execute_search + (EMemoShellView *memo_shell_view); +void e_memo_shell_view_open_memo + (EMemoShellView *memo_shell_view, + ECalModelComponent *comp_data); +void e_memo_shell_view_set_status_message + (EMemoShellView *memo_shell_view, + const gchar *status_message, + gdouble percent); +void e_memo_shell_view_update_sidebar + (EMemoShellView *memo_shell_view); +void e_memo_shell_view_update_search_filter + (EMemoShellView *memo_shell_view); + +G_END_DECLS + +#endif /* E_MEMO_SHELL_VIEW_PRIVATE_H */ diff --git a/modules/calendar/e-memo-shell-view.c b/modules/calendar/e-memo-shell-view.c new file mode 100644 index 0000000000..e2964b061c --- /dev/null +++ b/modules/calendar/e-memo-shell-view.c @@ -0,0 +1,222 @@ +/* + * e-memo-shell-view.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-memo-shell-view-private.h" + +static gpointer parent_class; +static GType memo_shell_view_type; + +static void +memo_shell_view_dispose (GObject *object) +{ + e_memo_shell_view_private_dispose (E_MEMO_SHELL_VIEW (object)); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +memo_shell_view_finalize (GObject *object) +{ + e_memo_shell_view_private_finalize (E_MEMO_SHELL_VIEW (object)); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +memo_shell_view_constructed (GObject *object) +{ + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + e_memo_shell_view_private_constructed (E_MEMO_SHELL_VIEW (object)); +} + +static void +memo_shell_view_update_actions (EShellView *shell_view) +{ + EMemoShellViewPrivate *priv; + EShellContent *shell_content; + EShellSidebar *shell_sidebar; + EShellWindow *shell_window; + GtkAction *action; + const gchar *label; + gboolean sensitive; + guint32 state; + + /* Be descriptive. */ + gboolean any_memos_selected; + gboolean has_primary_source; + gboolean multiple_memos_selected; + gboolean primary_source_is_system; + gboolean selection_has_url; + gboolean single_memo_selected; + gboolean sources_are_editable; + + priv = E_MEMO_SHELL_VIEW_GET_PRIVATE (shell_view); + + shell_window = e_shell_view_get_shell_window (shell_view); + + shell_content = e_shell_view_get_shell_content (shell_view); + state = e_shell_content_check_state (shell_content); + + single_memo_selected = + (state & E_MEMO_SHELL_CONTENT_SELECTION_SINGLE); + multiple_memos_selected = + (state & E_MEMO_SHELL_CONTENT_SELECTION_MULTIPLE); + sources_are_editable = + (state & E_MEMO_SHELL_CONTENT_SELECTION_CAN_EDIT); + selection_has_url = + (state & E_MEMO_SHELL_CONTENT_SELECTION_HAS_URL); + + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + state = e_shell_sidebar_check_state (shell_sidebar); + + has_primary_source = + (state & E_MEMO_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE); + primary_source_is_system = + (state & E_MEMO_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM); + + any_memos_selected = + (single_memo_selected || multiple_memos_selected); + + action = ACTION (MEMO_CLIPBOARD_COPY); + sensitive = any_memos_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_CLIPBOARD_CUT); + sensitive = any_memos_selected && sources_are_editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_CLIPBOARD_PASTE); + sensitive = sources_are_editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_DELETE); + sensitive = any_memos_selected && sources_are_editable; + gtk_action_set_sensitive (action, sensitive); + if (multiple_memos_selected) + label = _("Delete Memos"); + else + label = _("Delete Memo"); + g_object_set (action, "label", label, NULL); + + action = ACTION (MEMO_FORWARD); + sensitive = single_memo_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_LIST_COPY); + sensitive = has_primary_source; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_LIST_DELETE); + sensitive = has_primary_source && !primary_source_is_system; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_LIST_PROPERTIES); + sensitive = has_primary_source; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_LIST_RENAME); + sensitive = has_primary_source; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_OPEN); + sensitive = single_memo_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_OPEN_URL); + sensitive = single_memo_selected && selection_has_url; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_PRINT); + sensitive = single_memo_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MEMO_SAVE_AS); + sensitive = single_memo_selected; + gtk_action_set_sensitive (action, sensitive); +} + +static void +memo_shell_view_class_init (EMemoShellViewClass *class, + GTypeModule *type_module) +{ + GObjectClass *object_class; + EShellViewClass *shell_view_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMemoShellViewPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->dispose = memo_shell_view_dispose; + object_class->finalize = memo_shell_view_finalize; + object_class->constructed = memo_shell_view_constructed; + + shell_view_class = E_SHELL_VIEW_CLASS (class); + shell_view_class->label = _("Memos"); + shell_view_class->icon_name = "evolution-memos"; + shell_view_class->ui_definition = "evolution-memos.ui"; + shell_view_class->ui_manager_id = "org.gnome.evolution.memos"; + shell_view_class->search_options = "/memo-search-options"; + shell_view_class->search_rules = "memotypes.xml"; + shell_view_class->new_shell_content = e_memo_shell_content_new; + shell_view_class->new_shell_sidebar = e_memo_shell_sidebar_new; + shell_view_class->update_actions = memo_shell_view_update_actions; +} + +static void +memo_shell_view_init (EMemoShellView *memo_shell_view, + EShellViewClass *shell_view_class) +{ + memo_shell_view->priv = + E_MEMO_SHELL_VIEW_GET_PRIVATE (memo_shell_view); + + e_memo_shell_view_private_init (memo_shell_view, shell_view_class); +} + +GType +e_memo_shell_view_get_type (void) +{ + return memo_shell_view_type; +} + +void +e_memo_shell_view_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (EMemoShellViewClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) memo_shell_view_class_init, + (GClassFinalizeFunc) NULL, + type_module, + sizeof (EMemoShellView), + 0, /* n_preallocs */ + (GInstanceInitFunc) memo_shell_view_init, + NULL /* value_table */ + }; + + memo_shell_view_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_VIEW, + "EMemoShellView", &type_info, 0); +} diff --git a/modules/calendar/e-memo-shell-view.h b/modules/calendar/e-memo-shell-view.h new file mode 100644 index 0000000000..686ae734c9 --- /dev/null +++ b/modules/calendar/e-memo-shell-view.h @@ -0,0 +1,67 @@ +/* + * e-memo-shell-view.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MEMO_SHELL_VIEW_H +#define E_MEMO_SHELL_VIEW_H + +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_MEMO_SHELL_VIEW \ + (e_memo_shell_view_get_type ()) +#define E_MEMO_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MEMO_SHELL_VIEW, EMemoShellView)) +#define E_MEMO_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MEMO_SHELL_VIEW, EMemoShellViewClass)) +#define E_IS_MEMO_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MEMO_SHELL_VIEW)) +#define E_IS_MEMO_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MEMO_SHELL_VIEW)) +#define E_MEMO_SHELL_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MEMO_SHELL_VIEW, EMemoShellViewClass)) + +G_BEGIN_DECLS + +typedef struct _EMemoShellView EMemoShellView; +typedef struct _EMemoShellViewClass EMemoShellViewClass; +typedef struct _EMemoShellViewPrivate EMemoShellViewPrivate; + +struct _EMemoShellView { + EShellView parent; + EMemoShellViewPrivate *priv; +}; + +struct _EMemoShellViewClass { + EShellViewClass parent_class; +}; + +GType e_memo_shell_view_get_type (void); +void e_memo_shell_view_register_type (GTypeModule *type_module); + +G_END_DECLS + +#endif /* E_MEMO_SHELL_VIEW_H */ diff --git a/modules/calendar/e-task-shell-backend.c b/modules/calendar/e-task-shell-backend.c new file mode 100644 index 0000000000..6bded3e412 --- /dev/null +++ b/modules/calendar/e-task-shell-backend.c @@ -0,0 +1,621 @@ +/* + * e-task-shell-backend.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-task-shell-backend.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "shell/e-shell.h" +#include "shell/e-shell-backend.h" +#include "shell/e-shell-window.h" + +#include "calendar/common/authentication.h" +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/comp-util.h" +#include "calendar/gui/dialogs/calendar-setup.h" +#include "calendar/gui/dialogs/task-editor.h" + +#include "e-task-shell-content.h" +#include "e-task-shell-migrate.h" +#include "e-task-shell-sidebar.h" +#include "e-task-shell-view.h" + +#define E_TASK_SHELL_BACKEND_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_TASK_SHELL_BACKEND, ETaskShellBackendPrivate)) + +#define WEB_BASE_URI "webcal://" +#define PERSONAL_RELATIVE_URI "system" + +struct _ETaskShellBackendPrivate { + ESourceList *source_list; +}; + +enum { + PROP_0, + PROP_SOURCE_LIST +}; + +static gpointer parent_class; +static GType task_shell_backend_type; + +static void +task_module_ensure_sources (EShellBackend *shell_backend) +{ + /* XXX This is basically the same algorithm across all modules. + * Maybe we could somehow integrate this into EShellBackend? */ + + ETaskShellBackendPrivate *priv; + ESourceGroup *on_this_computer; + ESourceGroup *on_the_web; + ESource *personal; + GSList *groups, *iter; + const gchar *data_dir; + const gchar *name; + gchar *base_uri; + gchar *filename; + + on_this_computer = NULL; + on_the_web = NULL; + personal = NULL; + + priv = E_TASK_SHELL_BACKEND_GET_PRIVATE (shell_backend); + + if (!e_cal_get_sources (&priv->source_list, E_CAL_SOURCE_TYPE_TODO, NULL)) { + g_warning ("Could not get task sources from GConf!"); + return; + } + + data_dir = e_shell_backend_get_data_dir (shell_backend); + filename = g_build_filename (data_dir, "local", NULL); + base_uri = g_filename_to_uri (filename, NULL, NULL); + g_free (filename); + + groups = e_source_list_peek_groups (priv->source_list); + for (iter = groups; iter != NULL; iter = iter->next) { + ESourceGroup *source_group = iter->data; + const gchar *group_base_uri; + + group_base_uri = e_source_group_peek_base_uri (source_group); + + /* Compare only "file://" part. If the user's home + * changes, we do not want to create another group. */ + if (on_this_computer == NULL && + strncmp (base_uri, group_base_uri, 7) == 0) + on_this_computer = source_group; + + else if (on_the_web == NULL && + strcmp (WEB_BASE_URI, group_base_uri) == 0) + on_the_web = source_group; + } + + name = _("On This Computer"); + + if (on_this_computer != NULL) { + GSList *sources; + const gchar *group_base_uri; + + /* Force the group name to the current locale. */ + e_source_group_set_name (on_this_computer, name); + + sources = e_source_group_peek_sources (on_this_computer); + group_base_uri = e_source_group_peek_base_uri (on_this_computer); + + /* Make sure this group includes a "Personal" source. */ + for (iter = sources; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + const gchar *relative_uri; + + relative_uri = e_source_peek_relative_uri (source); + if (relative_uri == NULL) + continue; + + if (strcmp (PERSONAL_RELATIVE_URI, relative_uri) != 0) + continue; + + personal = source; + break; + } + + /* Make sure we have the correct base URI. This can + * change when the user's home directory changes. */ + if (strcmp (base_uri, group_base_uri) != 0) { + e_source_group_set_base_uri ( + on_this_computer, base_uri); + + /* XXX We shouldn't need this sync call here as + * set_base_uri() results in synching to GConf, + * but that happens in an idle loop and too late + * to prevent the user from seeing a "Cannot + * Open ... because of invalid URI" error. */ + e_source_list_sync (priv->source_list, NULL); + } + + } else { + ESourceGroup *source_group; + + source_group = e_source_group_new (name, base_uri); + e_source_list_add_group (priv->source_list, source_group, -1); + g_object_unref (source_group); + } + + name = _("Personal"); + + if (personal == NULL) { + ESource *source; + GSList *selected; + gchar *primary; + + source = e_source_new (name, PERSONAL_RELATIVE_URI); + e_source_group_add_source (on_this_computer, source, -1); + g_object_unref (source); + + primary = calendar_config_get_primary_tasks (); + selected = calendar_config_get_tasks_selected (); + + if (primary == NULL && selected == NULL) { + const gchar *uid; + + uid = e_source_peek_uid (source); + selected = g_slist_prepend (NULL, g_strdup (uid)); + + calendar_config_set_primary_tasks (uid); + calendar_config_set_tasks_selected (selected); + } + + g_slist_foreach (selected, (GFunc) g_free, NULL); + g_slist_free (selected); + g_free (primary); + } else { + /* Force the source name to the current locale. */ + e_source_set_name (personal, name); + } + + name = _("On The Web"); + + if (on_the_web == NULL) { + ESourceGroup *source_group; + + source_group = e_source_group_new (name, WEB_BASE_URI); + e_source_list_add_group (priv->source_list, source_group, -1); + g_object_unref (source_group); + } else { + /* Force the group name to the current locale. */ + e_source_group_set_name (on_the_web, name); + } + + g_free (base_uri); +} + +static void +task_module_cal_opened_cb (ECal *cal, + ECalendarStatus status, + GtkAction *action) +{ + EShell *shell; + ECalComponent *comp; + CompEditor *editor; + CompEditorFlags flags = 0; + const gchar *action_name; + + /* FIXME Pass this in. */ + shell = e_shell_get_default (); + + /* XXX Handle errors better. */ + if (status != E_CALENDAR_STATUS_OK) + return; + + action_name = gtk_action_get_name (action); + + flags |= COMP_EDITOR_NEW_ITEM; + if (strcmp (action_name, "task-assigned-new") == 0) { + flags |= COMP_EDITOR_IS_ASSIGNED; + flags |= COMP_EDITOR_USER_ORG; + } + + editor = task_editor_new (cal, shell, flags); + comp = cal_comp_task_new_with_defaults (cal); + comp_editor_edit_comp (editor, comp); + + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (comp); + g_object_unref (cal); +} + +static void +action_task_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + ECal *cal = NULL; + ECalSourceType source_type; + ESourceList *source_list; + gchar *uid; + + /* This callback is used for both tasks and assigned tasks. */ + + source_type = E_CAL_SOURCE_TYPE_TODO; + + if (!e_cal_get_sources (&source_list, source_type, NULL)) { + g_warning ("Could not get task sources from GConf!"); + return; + } + + uid = calendar_config_get_primary_tasks (); + + if (uid != NULL) { + ESource *source; + + source = e_source_list_peek_source_by_uid (source_list, uid); + if (source != NULL) + cal = auth_new_cal_from_source (source, source_type); + g_free (uid); + } + + if (cal == NULL) + cal = auth_new_cal_from_default (source_type); + + g_return_if_fail (cal != NULL); + + g_signal_connect ( + cal, "cal-opened", + G_CALLBACK (task_module_cal_opened_cb), action); + + e_cal_open_async (cal, FALSE); +} + +static void +action_task_list_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + calendar_setup_new_task_list (GTK_WINDOW (shell_window)); +} + +static GtkActionEntry item_entries[] = { + + { "task-new", + "stock_task", + NC_("New", "_Task"), + "t", + N_("Create a new task"), + G_CALLBACK (action_task_new_cb) }, + + { "task-assigned-new", + "stock_task", + N_("Assigne_d Task"), + NULL, + N_("Create a new assigned task"), + G_CALLBACK (action_task_new_cb) } +}; + +static GtkActionEntry source_entries[] = { + + { "task-list-new", + "stock_todo", + NC_("New", "Tas_k List"), + NULL, + N_("Create a new task list"), + G_CALLBACK (action_task_list_new_cb) } +}; + +static gboolean +task_module_handle_uri_cb (EShellBackend *shell_backend, + const gchar *uri) +{ + EShell *shell; + CompEditor *editor; + CompEditorFlags flags = 0; + ECal *client; + ECalComponent *comp; + ESource *source; + ESourceList *source_list; + ECalSourceType source_type; + EUri *euri; + icalcomponent *icalcomp; + icalproperty *icalprop; + const gchar *cp; + gchar *source_uid = NULL; + gchar *comp_uid = NULL; + gchar *comp_rid = NULL; + gboolean handled = FALSE; + GError *error = NULL; + + source_type = E_CAL_SOURCE_TYPE_TODO; + shell = e_shell_backend_get_shell (shell_backend); + + if (strncmp (uri, "task:", 5) != 0) + return FALSE; + + euri = e_uri_new (uri); + cp = euri->query; + if (cp == NULL) + goto exit; + + while (*cp != '\0') { + gchar *header; + gchar *content; + gsize header_len; + gsize content_len; + + header_len = strcspn (cp, "=&"); + + /* If it's malformed, give up. */ + if (cp[header_len] != '=') + break; + + header = (gchar *) cp; + header[header_len] = '\0'; + cp += header_len + 1; + + content_len = strcspn (cp, "&"); + + content = g_strndup (cp, content_len); + if (g_ascii_strcasecmp (header, "source-uid") == 0) + source_uid = g_strdup (content); + else if (g_ascii_strcasecmp (header, "comp-uid") == 0) + comp_uid = g_strdup (content); + else if (g_ascii_strcasecmp (header, "comp-rid") == 0) + comp_rid = g_strdup (content); + g_free (content); + + cp += content_len; + if (*cp == '&') { + cp++; + if (strcmp (cp, "amp;") == 0) + cp += 4; + } + } + + if (source_uid != NULL || comp_uid != NULL) + goto exit; + + /* URI is valid, so consider it handled. Whether + * we successfully open it is another matter... */ + handled = TRUE; + + if (!e_cal_get_sources (&source_list, source_type, NULL)) { + g_printerr ("Could not get task sources from GConf!\n"); + goto exit; + } + + source = e_source_list_peek_source_by_uid (source_list, source_uid); + if (source == NULL) { + g_printerr ("No source for UID `%s'\n", source_uid); + g_object_unref (source_list); + goto exit; + } + + client = auth_new_cal_from_source (source, source_type); + if (client == NULL || !e_cal_open (client, TRUE, &error)) { + g_printerr ("%s\n", error->message); + g_object_unref (source_list); + g_error_free (error); + goto exit; + } + + /* XXX Copied from e_task_shell_view_open_task(). + * Clearly a new utility function is needed. */ + + editor = comp_editor_find_instance (comp_uid); + + if (editor != NULL) + goto present; + + if (!e_cal_get_object (client, comp_uid, comp_rid, &icalcomp, &error)) { + g_printerr ("%s\n", error->message); + g_object_unref (source_list); + g_error_free (error); + goto exit; + } + + comp = e_cal_component_new (); + e_cal_component_set_icalcomponent (comp, icalcomp); + + icalprop = icalcomponent_get_first_property ( + icalcomp, ICAL_ATTENDEE_PROPERTY); + if (icalprop != NULL) + flags |= COMP_EDITOR_IS_ASSIGNED; + + if (itip_organizer_is_user (comp, client)) + flags |= COMP_EDITOR_USER_ORG; + + if (!e_cal_component_has_attendees (comp)) + flags |= COMP_EDITOR_USER_ORG; + + editor = task_editor_new (client, shell, flags); + comp_editor_edit_comp (editor, comp); + + g_object_unref (comp); + +present: + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (source_list); + g_object_unref (client); + +exit: + g_free (source_uid); + g_free (comp_uid); + g_free (comp_rid); + + e_uri_free (euri); + + return handled; +} + +static void +task_module_window_created_cb (EShellBackend *shell_backend, + GtkWindow *window) +{ + const gchar *module_name; + + if (!E_IS_SHELL_WINDOW (window)) + return; + + module_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name; + + e_shell_window_register_new_item_actions ( + E_SHELL_WINDOW (window), module_name, + item_entries, G_N_ELEMENTS (item_entries)); + + e_shell_window_register_new_source_actions ( + E_SHELL_WINDOW (window), module_name, + source_entries, G_N_ELEMENTS (source_entries)); +} + +static void +task_shell_backend_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SOURCE_LIST: + g_value_set_object ( + value, + e_task_shell_backend_get_source_list ( + E_TASK_SHELL_BACKEND (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +task_shell_backend_dispose (GObject *object) +{ + ETaskShellBackendPrivate *priv; + + priv = E_TASK_SHELL_BACKEND_GET_PRIVATE (object); + + if (priv->source_list != NULL) { + g_object_unref (priv->source_list); + priv->source_list = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +task_shell_backend_constructed (GObject *object) +{ + EShell *shell; + EShellBackend *shell_backend; + + shell_backend = E_SHELL_BACKEND (object); + shell = e_shell_backend_get_shell (shell_backend); + + task_module_ensure_sources (shell_backend); + + g_signal_connect_swapped ( + shell, "handle-uri", + G_CALLBACK (task_module_handle_uri_cb), shell_backend); + + g_signal_connect_swapped ( + shell, "window-created", + G_CALLBACK (task_module_window_created_cb), shell_backend); +} + +static void +task_shell_backend_class_init (ETaskShellBackendClass *class) +{ + GObjectClass *object_class; + EShellBackendClass *shell_backend_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ETaskShellBackendPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->get_property = task_shell_backend_get_property; + object_class->dispose = task_shell_backend_dispose; + object_class->constructed = task_shell_backend_constructed; + + shell_backend_class = E_SHELL_BACKEND_CLASS (class); + shell_backend_class->shell_view_type = E_TYPE_TASK_SHELL_VIEW; + shell_backend_class->name = "tasks"; + shell_backend_class->aliases = ""; + shell_backend_class->schemes = "task"; + shell_backend_class->sort_order = 600; + shell_backend_class->start = NULL; + shell_backend_class->is_busy = NULL; + shell_backend_class->shutdown = NULL; + shell_backend_class->migrate = e_task_shell_backend_migrate; + + g_object_class_install_property ( + object_class, + PROP_SOURCE_LIST, + g_param_spec_object ( + "source-list", + _("Source List"), + _("The registry of task lists"), + E_TYPE_SOURCE_LIST, + G_PARAM_READABLE)); +} + +static void +task_shell_backend_init (ETaskShellBackend *task_shell_backend) +{ + task_shell_backend->priv = + E_TASK_SHELL_BACKEND_GET_PRIVATE (task_shell_backend); +} + +GType +e_task_shell_backend_get_type (void) +{ + return task_shell_backend_type; +} + +void +e_task_shell_backend_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (ETaskShellBackendClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) task_shell_backend_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ETaskShellBackend), + 0, /* n_preallocs */ + (GInstanceInitFunc) task_shell_backend_init, + NULL /* value_table */ + }; + + task_shell_backend_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_BACKEND, + "ETaskShellBackend", &type_info, 0); +} + +ESourceList * +e_task_shell_backend_get_source_list (ETaskShellBackend *task_shell_backend) +{ + g_return_val_if_fail ( + E_IS_TASK_SHELL_BACKEND (task_shell_backend), NULL); + + return task_shell_backend->priv->source_list; +} diff --git a/modules/calendar/e-task-shell-backend.h b/modules/calendar/e-task-shell-backend.h new file mode 100644 index 0000000000..63b157ad85 --- /dev/null +++ b/modules/calendar/e-task-shell-backend.h @@ -0,0 +1,70 @@ +/* + * e-task-shell-backend.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_TASK_SHELL_BACKEND_H +#define E_TASK_SHELL_BACKEND_H + +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_TASK_SHELL_BACKEND \ + (e_task_shell_backend_get_type ()) +#define E_TASK_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_TASK_SHELL_BACKEND, ETaskShellBackend)) +#define E_TASK_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_TASK_SHELL_BACKEND, ETaskShellBackendClass)) +#define E_IS_TASK_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_TASK_SHELL_BACKEND)) +#define E_IS_TASK_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_TASK_SHELL_BACKEND)) +#define E_TASK_SHELL_BACKEND_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_TASK_SHELL_BACKEND, ETaskShellBackendClass)) + +G_BEGIN_DECLS + +typedef struct _ETaskShellBackend ETaskShellBackend; +typedef struct _ETaskShellBackendClass ETaskShellBackendClass; +typedef struct _ETaskShellBackendPrivate ETaskShellBackendPrivate; + +struct _ETaskShellBackend { + EShellBackend parent; + ETaskShellBackendPrivate *priv; +}; + +struct _ETaskShellBackendClass { + EShellBackendClass parent_class; +}; + +GType e_task_shell_backend_get_type (void); +void e_task_shell_backend_register_type + (GTypeModule *type_module); +ESourceList * e_task_shell_backend_get_source_list + (ETaskShellBackend *task_shell_backend); + +G_END_DECLS + +#endif /* E_TASK_SHELL_BACKEND_H */ diff --git a/modules/calendar/e-task-shell-content.c b/modules/calendar/e-task-shell-content.c new file mode 100644 index 0000000000..0177c6c3c3 --- /dev/null +++ b/modules/calendar/e-task-shell-content.c @@ -0,0 +1,700 @@ +/* + * e-task-shell-content.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-task-shell-content.h" + +#include + +#include "e-util/gconf-bridge.h" + +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/comp-util.h" +#include "calendar/gui/e-cal-model-tasks.h" +#include "calendar/gui/e-calendar-table.h" +#include "calendar/gui/e-calendar-table-config.h" + +#include "widgets/menus/gal-view-etable.h" + +#define E_TASK_SHELL_CONTENT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_TASK_SHELL_CONTENT, ETaskShellContentPrivate)) + +#define E_CALENDAR_TABLE_DEFAULT_STATE \ + "" \ + "" \ + " " \ + " " \ + " " \ + " " \ + " " \ + "" + +struct _ETaskShellContentPrivate { + GtkWidget *paned; + GtkWidget *task_table; + GtkWidget *task_preview; + + ECalModel *task_model; + ECalendarTableConfig *table_config; + GalViewInstance *view_instance; + + gchar *current_uid; +}; + +enum { + PROP_0, + PROP_MODEL, + PROP_PREVIEW_VISIBLE +}; + +enum { + TARGET_VCALENDAR +}; + +static GtkTargetEntry drag_types[] = { + { (gchar *) "text/calendar", 0, TARGET_VCALENDAR }, + { (gchar *) "text/x-calendar", 0, TARGET_VCALENDAR } +}; + +static gpointer parent_class; +static GType task_shell_content_type; + +static void +task_shell_content_display_view_cb (ETaskShellContent *task_shell_content, + GalView *gal_view) +{ + ECalendarTable *task_table; + ETable *table; + + if (!GAL_IS_VIEW_ETABLE (gal_view)) + return; + + task_table = e_task_shell_content_get_task_table (task_shell_content); + table = e_calendar_table_get_table (task_table); + + gal_view_etable_attach_table (GAL_VIEW_ETABLE (gal_view), table); +} + +static void +task_shell_content_table_foreach_cb (gint model_row, + gpointer user_data) +{ + ECalModelComponent *comp_data; + icalcomponent *clone; + icalcomponent *vcal; + gchar *string; + + struct { + ECalModel *model; + GSList *list; + } *foreach_data = user_data; + + comp_data = e_cal_model_get_component_at ( + foreach_data->model, model_row); + + vcal = e_cal_util_new_top_level (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_util_add_timezones_from_component (vcal, comp_data->icalcomp); + icalcomponent_add_component (vcal, clone); + + /* String is owned by libical; do not free. */ + string = icalcomponent_as_ical_string (vcal); + if (string != NULL) { + ESource *source; + const gchar *source_uid; + + source = e_cal_get_source (comp_data->client); + source_uid = e_source_peek_uid (source); + + foreach_data->list = g_slist_prepend ( + foreach_data->list, + g_strdup_printf ("%s\n%s", source_uid, string)); + } + + icalcomponent_free (vcal); +} + +static void +task_shell_content_table_drag_data_get_cb (ETaskShellContent *task_shell_content, + gint row, + gint col, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time) +{ + ECalendarTable *task_table; + ETable *table; + + struct { + ECalModel *model; + GSList *list; + } foreach_data; + + if (info != TARGET_VCALENDAR) + return; + + task_table = e_task_shell_content_get_task_table (task_shell_content); + table = e_calendar_table_get_table (task_table); + + foreach_data.model = e_calendar_table_get_model (task_table); + foreach_data.list = NULL; + + e_table_selected_row_foreach ( + table, task_shell_content_table_foreach_cb, + &foreach_data); + + if (foreach_data.list != NULL) { + cal_comp_selection_set_string_list ( + selection_data, foreach_data.list); + g_slist_foreach (foreach_data.list, (GFunc) g_free, NULL); + g_slist_free (foreach_data.list); + } +} + +static void +task_shell_content_table_drag_data_delete_cb (ETaskShellContent *task_shell_content, + gint row, + gint col, + GdkDragContext *context) +{ + /* Moved components are deleted from source immediately when moved, + * because some of them can be part of destination source, and we + * don't want to delete not-moved tasks. There is no such information + * which event has been moved and which not, so skip this method. */ +} + +static void +task_shell_content_cursor_change_cb (ETaskShellContent *task_shell_content, + gint row, + ETable *table) +{ + ECalComponentPreview *task_preview; + ECalendarTable *task_table; + ECalModel *task_model; + ECalModelComponent *comp_data; + ECalComponent *comp; + const gchar *uid; + + task_model = e_task_shell_content_get_task_model (task_shell_content); + task_table = e_task_shell_content_get_task_table (task_shell_content); + task_preview = e_task_shell_content_get_task_preview (task_shell_content); + + if (e_table_selected_count (table) != 1) { + e_cal_component_preview_clear (task_preview); + return; + } + + row = e_table_get_cursor_row (table); + comp_data = e_cal_model_get_component_at (task_model, row); + + comp = e_cal_component_new (); + e_cal_component_set_icalcomponent ( + comp, icalcomponent_new_clone (comp_data->icalcomp)); + e_cal_component_preview_display ( + task_preview, comp_data->client, comp); + + e_cal_component_get_uid (comp, &uid); + g_free (task_shell_content->priv->current_uid); + task_shell_content->priv->current_uid = g_strdup (uid); + + g_object_unref (comp); +} + +static void +task_shell_content_selection_change_cb (ETaskShellContent *task_shell_content, + ETable *table) +{ + ECalComponentPreview *task_preview; + + task_preview = e_task_shell_content_get_task_preview (task_shell_content); + + if (e_table_selected_count (table) != 1) + e_cal_component_preview_clear (task_preview); +} + +static void +task_shell_content_model_row_changed_cb (ETaskShellContent *task_shell_content, + gint row, + ETableModel *model) +{ + ECalModelComponent *comp_data; + ECalendarTable *task_table; + ETable *table; + const gchar *current_uid; + const gchar *uid; + + current_uid = task_shell_content->priv->current_uid; + if (current_uid == NULL) + return; + + comp_data = e_cal_model_get_component_at (E_CAL_MODEL (model), row); + if (comp_data == NULL) + return; + + uid = icalcomponent_get_uid (comp_data->icalcomp); + if (g_strcmp0 (uid, current_uid) != 0) + return; + + task_table = e_task_shell_content_get_task_table (task_shell_content); + table = e_calendar_table_get_table (task_table); + + task_shell_content_cursor_change_cb (task_shell_content, 0, table); +} + +static void +task_shell_content_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_PREVIEW_VISIBLE: + e_task_shell_content_set_preview_visible ( + E_TASK_SHELL_CONTENT (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +task_shell_content_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_MODEL: + g_value_set_object ( + value, e_task_shell_content_get_task_model ( + E_TASK_SHELL_CONTENT (object))); + return; + + case PROP_PREVIEW_VISIBLE: + g_value_set_boolean ( + value, e_task_shell_content_get_preview_visible ( + E_TASK_SHELL_CONTENT (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +task_shell_content_dispose (GObject *object) +{ + ETaskShellContentPrivate *priv; + + priv = E_TASK_SHELL_CONTENT_GET_PRIVATE (object); + + if (priv->paned != NULL) { + g_object_unref (priv->paned); + priv->paned = NULL; + } + + if (priv->task_table != NULL) { + g_object_unref (priv->task_table); + priv->task_table = NULL; + } + + if (priv->task_preview != NULL) { + g_object_unref (priv->task_preview); + priv->task_preview = NULL; + } + + if (priv->task_model != NULL) { + g_object_unref (priv->task_model); + priv->task_model = NULL; + } + + if (priv->table_config != NULL) { + g_object_unref (priv->table_config); + priv->table_config = NULL; + } + + if (priv->view_instance != NULL) { + g_object_unref (priv->view_instance); + priv->view_instance = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +task_shell_content_finalize (GObject *object) +{ + ETaskShellContentPrivate *priv; + + priv = E_TASK_SHELL_CONTENT_GET_PRIVATE (object); + + g_free (priv->current_uid); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +task_shell_content_constructed (GObject *object) +{ + ETaskShellContentPrivate *priv; + EShellContent *shell_content; + EShellView *shell_view; + GalViewInstance *view_instance; + ETable *table; + GConfBridge *bridge; + GtkWidget *container; + GtkWidget *widget; + const gchar *key; + + priv = E_TASK_SHELL_CONTENT_GET_PRIVATE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + shell_content = E_SHELL_CONTENT (object); + shell_view = e_shell_content_get_shell_view (shell_content); + + /* Build content widgets. */ + + container = GTK_WIDGET (object); + + widget = gtk_vpaned_new (); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->paned = g_object_ref (widget); + gtk_widget_show (widget); + + container = widget; + + widget = e_calendar_table_new (shell_view, priv->task_model); + gtk_paned_add1 (GTK_PANED (container), widget); + priv->task_table = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_paned_add2 (GTK_PANED (container), widget); + gtk_widget_show (widget); + + container = widget; + + widget = e_cal_component_preview_new (); + e_cal_component_preview_set_default_timezone ( + E_CAL_COMPONENT_PREVIEW (widget), + calendar_config_get_icaltimezone ()); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->task_preview = g_object_ref (widget); + gtk_widget_show (widget); + + /* Configure the task table. */ + + widget = E_CALENDAR_TABLE (priv->task_table)->etable; + table = e_table_scrolled_get_table (E_TABLE_SCROLLED (widget)); + + priv->table_config = e_calendar_table_config_new ( + E_CALENDAR_TABLE (priv->task_table)); + + e_table_set_state (table, E_CALENDAR_TABLE_DEFAULT_STATE); + + e_table_drag_source_set ( + table, GDK_BUTTON1_MASK, + drag_types, G_N_ELEMENTS (drag_types), + GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_ASK); + + g_signal_connect_swapped ( + table, "table-drag-data-get", + G_CALLBACK (task_shell_content_table_drag_data_get_cb), + object); + + g_signal_connect_swapped ( + table, "table-drag-data-delete", + G_CALLBACK (task_shell_content_table_drag_data_delete_cb), + object); + + g_signal_connect_swapped ( + table, "cursor-change", + G_CALLBACK (task_shell_content_cursor_change_cb), + object); + + g_signal_connect_swapped ( + table, "selection-change", + G_CALLBACK (task_shell_content_selection_change_cb), + object); + + g_signal_connect_swapped ( + priv->task_model, "model-row-changed", + G_CALLBACK (task_shell_content_model_row_changed_cb), + object); + + /* Load the view instance. */ + + view_instance = e_shell_view_new_view_instance (shell_view, NULL); + g_signal_connect_swapped ( + view_instance, "display-view", + G_CALLBACK (task_shell_content_display_view_cb), + object); + gal_view_instance_load (view_instance); + priv->view_instance = view_instance; + + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (priv->paned); + key = "/apps/evolution/calendar/display/task_vpane_position"; + gconf_bridge_bind_property_delayed (bridge, key, object, "position"); +} + +static guint32 +task_shell_content_check_state (EShellContent *shell_content) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ETable *table; + GSList *list, *iter; + gboolean assignable = TRUE; + gboolean editable = TRUE; + gboolean has_url = FALSE; + gint n_selected; + gint n_complete = 0; + gint n_incomplete = 0; + guint32 state = 0; + + task_shell_content = E_TASK_SHELL_CONTENT (shell_content); + task_table = e_task_shell_content_get_task_table (task_shell_content); + + table = e_calendar_table_get_table (task_table); + n_selected = e_table_selected_count (table); + + list = e_calendar_table_get_selected (task_table); + for (iter = list; iter != NULL; iter = iter->next) { + ECalModelComponent *comp_data = iter->data; + icalproperty *prop; + const gchar *cap; + gboolean read_only; + + e_cal_is_read_only (comp_data->client, &read_only, NULL); + editable &= !read_only; + + cap = CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT; + if (e_cal_get_static_capability (comp_data->client, cap)) + assignable = FALSE; + + cap = CAL_STATIC_CAPABILITY_NO_CONV_TO_ASSIGN_TASK; + if (e_cal_get_static_capability (comp_data->client, cap)) + assignable = FALSE; + + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_URL_PROPERTY); + has_url |= (prop != NULL); + + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_COMPLETED_PROPERTY); + if (prop != NULL) + n_complete++; + else + n_incomplete++; + } + g_slist_free (list); + + if (n_selected == 1) + state |= E_TASK_SHELL_CONTENT_SELECTION_SINGLE; + if (n_selected > 1) + state |= E_TASK_SHELL_CONTENT_SELECTION_MULTIPLE; + if (assignable) + state |= E_TASK_SHELL_CONTENT_SELECTION_CAN_ASSIGN; + if (editable) + state |= E_TASK_SHELL_CONTENT_SELECTION_CAN_EDIT; + if (n_complete > 0) + state |= E_TASK_SHELL_CONTENT_SELECTION_HAS_COMPLETE; + if (n_incomplete > 0) + state |= E_TASK_SHELL_CONTENT_SELECTION_HAS_INCOMPLETE; + if (has_url) + state |= E_TASK_SHELL_CONTENT_SELECTION_HAS_URL; + + return state; +} + +static void +task_shell_content_class_init (ETaskShellContentClass *class) +{ + GObjectClass *object_class; + EShellContentClass *shell_content_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ETaskShellContentPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = task_shell_content_set_property; + object_class->get_property = task_shell_content_get_property; + object_class->dispose = task_shell_content_dispose; + object_class->finalize = task_shell_content_finalize; + object_class->constructed = task_shell_content_constructed; + + shell_content_class = E_SHELL_CONTENT_CLASS (class); + shell_content_class->check_state = task_shell_content_check_state; + + g_object_class_install_property ( + object_class, + PROP_MODEL, + g_param_spec_object ( + "model", + _("Model"), + _("The task table model"), + E_TYPE_CAL_MODEL, + G_PARAM_READABLE)); + + g_object_class_install_property ( + object_class, + PROP_PREVIEW_VISIBLE, + g_param_spec_boolean ( + "preview-visible", + _("Preview is Visible"), + _("Whether the preview pane is visible"), + TRUE, + G_PARAM_READWRITE)); +} + +static void +task_shell_content_init (ETaskShellContent *task_shell_content) +{ + task_shell_content->priv = + E_TASK_SHELL_CONTENT_GET_PRIVATE (task_shell_content); + + task_shell_content->priv->task_model = e_cal_model_tasks_new (); + + /* Postpone widget construction until we have a shell view. */ +} + +GType +e_task_shell_content_get_type (void) +{ + return task_shell_content_type; +} + +void +e_task_shell_content_register_type (GTypeModule *type_module) +{ + static const GTypeInfo type_info = { + sizeof (ETaskShellContentClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) task_shell_content_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ETaskShellContent), + 0, /* n_preallocs */ + (GInstanceInitFunc) task_shell_content_init, + NULL /* value_table */ + }; + + task_shell_content_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_CONTENT, + "ETaskShellContent", &type_info, 0); +} + +GtkWidget * +e_task_shell_content_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_TASK_SHELL_CONTENT, + "shell-view", shell_view, NULL); +} + +ECalModel * +e_task_shell_content_get_task_model (ETaskShellContent *task_shell_content) +{ + g_return_val_if_fail ( + E_IS_TASK_SHELL_CONTENT (task_shell_content), NULL); + + return task_shell_content->priv->task_model; +} + +ECalComponentPreview * +e_task_shell_content_get_task_preview (ETaskShellContent *task_shell_content) +{ + g_return_val_if_fail ( + E_IS_TASK_SHELL_CONTENT (task_shell_content), NULL); + + return E_CAL_COMPONENT_PREVIEW ( + task_shell_content->priv->task_preview); +} + +ECalendarTable * +e_task_shell_content_get_task_table (ETaskShellContent *task_shell_content) +{ + g_return_val_if_fail ( + E_IS_TASK_SHELL_CONTENT (task_shell_content), NULL); + + return E_CALENDAR_TABLE (task_shell_content->priv->task_table); +} + +GalViewInstance * +e_task_shell_content_get_view_instance (ETaskShellContent *task_shell_content) +{ + g_return_val_if_fail ( + E_IS_TASK_SHELL_CONTENT (task_shell_content), NULL); + + return task_shell_content->priv->view_instance; +} + +gboolean +e_task_shell_content_get_preview_visible (ETaskShellContent *task_shell_content) +{ + GtkPaned *paned; + GtkWidget *child; + + g_return_val_if_fail ( + E_IS_TASK_SHELL_CONTENT (task_shell_content), FALSE); + + paned = GTK_PANED (task_shell_content->priv->paned); + child = gtk_paned_get_child2 (paned); + + return GTK_WIDGET_VISIBLE (child); +} + +void +e_task_shell_content_set_preview_visible (ETaskShellContent *task_shell_content, + gboolean preview_visible) +{ + GtkPaned *paned; + GtkWidget *child; + + g_return_if_fail (E_IS_TASK_SHELL_CONTENT (task_shell_content)); + + paned = GTK_PANED (task_shell_content->priv->paned); + child = gtk_paned_get_child2 (paned); + + if (preview_visible) + gtk_widget_show (child); + else + gtk_widget_hide (child); + + g_object_notify (G_OBJECT (task_shell_content), "preview-visible"); +} diff --git a/modules/calendar/e-task-shell-content.h b/modules/calendar/e-task-shell-content.h new file mode 100644 index 0000000000..7e0b2128a7 --- /dev/null +++ b/modules/calendar/e-task-shell-content.h @@ -0,0 +1,100 @@ +/* + * e-task-shell-content.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_TASK_SHELL_CONTENT_H +#define E_TASK_SHELL_CONTENT_H + +#include +#include + +#include +#include +#include + +#include + +/* Standard GObject macros */ +#define E_TYPE_TASK_SHELL_CONTENT \ + (e_task_shell_content_get_type ()) +#define E_TASK_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_TASK_SHELL_CONTENT, ETaskShellContent)) +#define E_TASK_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_TASK_SHELL_CONTENT, ETaskShellContentClass)) +#define E_IS_TASK_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_TASK_SHELL_CONTENT)) +#define E_IS_TASK_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_TASK_SHELL_CONTENT)) +#define E_TASK_SHELL_CONTENT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_TASK_SHELL_CONTENT, ETaskShellContentClass)) + +G_BEGIN_DECLS + +typedef struct _ETaskShellContent ETaskShellContent; +typedef struct _ETaskShellContentClass ETaskShellContentClass; +typedef struct _ETaskShellContentPrivate ETaskShellContentPrivate; + +enum { + E_TASK_SHELL_CONTENT_SELECTION_SINGLE = 1 << 0, + E_TASK_SHELL_CONTENT_SELECTION_MULTIPLE = 1 << 1, + E_TASK_SHELL_CONTENT_SELECTION_CAN_ASSIGN = 1 << 2, + E_TASK_SHELL_CONTENT_SELECTION_CAN_EDIT = 1 << 3, + E_TASK_SHELL_CONTENT_SELECTION_HAS_COMPLETE = 1 << 4, + E_TASK_SHELL_CONTENT_SELECTION_HAS_INCOMPLETE = 1 << 5, + E_TASK_SHELL_CONTENT_SELECTION_HAS_URL = 1 << 6 +}; + +struct _ETaskShellContent { + EShellContent parent; + ETaskShellContentPrivate *priv; +}; + +struct _ETaskShellContentClass { + EShellContentClass parent_class; +}; + +GType e_task_shell_content_get_type (void); +void e_task_shell_content_register_type + (GTypeModule *type_module); +GtkWidget * e_task_shell_content_new(EShellView *shell_view); +ECalModel * e_task_shell_content_get_task_model + (ETaskShellContent *task_shell_content); +ECalComponentPreview * + e_task_shell_content_get_task_preview + (ETaskShellContent *task_shell_content); +ECalendarTable *e_task_shell_content_get_task_table + (ETaskShellContent *task_shell_content); +GalViewInstance * + e_task_shell_content_get_view_instance + (ETaskShellContent *task_shell_content); +gboolean e_task_shell_content_get_preview_visible + (ETaskShellContent *task_shell_content); +void e_task_shell_content_set_preview_visible + (ETaskShellContent *task_shell_content, + gboolean preview_visible); + +G_END_DECLS + +#endif /* E_TASK_SHELL_CONTENT_H */ diff --git a/modules/calendar/e-task-shell-migrate.c b/modules/calendar/e-task-shell-migrate.c new file mode 100644 index 0000000000..ced54bafdf --- /dev/null +++ b/modules/calendar/e-task-shell-migrate.c @@ -0,0 +1,664 @@ +/* + * e-task-shell-backend-migrate.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-task-shell-migrate.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "e-util/e-bconf-map.h" +#include "e-util/e-folder-map.h" +#include "e-util/e-util-private.h" +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/calendar-config-keys.h" + +#define WEBCAL_BASE_URI "webcal://" +#define PERSONAL_RELATIVE_URI "system" + +static e_gconf_map_t calendar_tasks_map[] = { + /* /Calendar/Tasks */ + { "HideCompletedTasks", "calendar/tasks/hide_completed", E_GCONF_MAP_BOOL }, + { "HideCompletedTasksUnits", "calendar/tasks/hide_completed_units", E_GCONF_MAP_STRING }, + { "HideCompletedTasksValue", "calendar/tasks/hide_completed_value", E_GCONF_MAP_INT }, + { NULL }, +}; + +static e_gconf_map_t calendar_tasks_colours_map[] = { + /* /Calendar/Tasks/Colors */ + { "TasksDueToday", "calendar/tasks/colors/due_today", E_GCONF_MAP_STRING }, + { "TasksOverDue", "calendar/tasks/colors/overdue", E_GCONF_MAP_STRING }, + { "TasksDueToday", "calendar/tasks/colors/due_today", E_GCONF_MAP_STRING }, + { NULL }, +}; + +static e_gconf_map_list_t task_remap_list[] = { + + { "/Calendar/Tasks", calendar_tasks_map }, + { "/Calendar/Tasks/Colors", calendar_tasks_colours_map }, + + { NULL }, +}; + +static GtkWidget *window; +static GtkLabel *label; +static GtkProgressBar *progress; + +#ifndef G_OS_WIN32 + +/* No previous versions have been available on Win32, so don't + * bother with upgrade support from 1.x on Win32. + */ + +static void +setup_progress_dialog (void) +{ + GtkWidget *vbox, *hbox, *w; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title ((GtkWindow *) window, _("Migrating...")); + gtk_window_set_modal ((GtkWindow *) window, TRUE); + gtk_container_set_border_width ((GtkContainer *) window, 6); + + vbox = gtk_vbox_new (FALSE, 6); + gtk_widget_show (vbox); + gtk_container_add ((GtkContainer *) window, vbox); + + w = gtk_label_new (_("The location and hierarchy of the Evolution task " + "folders has changed since Evolution 1.x.\n\nPlease be " + "patient while Evolution migrates your folders...")); + + gtk_label_set_line_wrap ((GtkLabel *) w, TRUE); + gtk_widget_show (w); + gtk_box_pack_start_defaults ((GtkBox *) vbox, w); + + hbox = gtk_hbox_new (FALSE, 6); + gtk_widget_show (hbox); + gtk_box_pack_start_defaults ((GtkBox *) vbox, hbox); + + label = (GtkLabel *) gtk_label_new (""); + gtk_widget_show ((GtkWidget *) label); + gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) label); + + progress = (GtkProgressBar *) gtk_progress_bar_new (); + gtk_widget_show ((GtkWidget *) progress); + gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) progress); + + gtk_widget_show (window); +} + +static void +dialog_close (void) +{ + gtk_widget_destroy ((GtkWidget *) window); +} + +static void +dialog_set_folder_name (const gchar *folder_name) +{ + gchar *text; + + text = g_strdup_printf (_("Migrating '%s':"), folder_name); + gtk_label_set_text (label, text); + g_free (text); + + gtk_progress_bar_set_fraction (progress, 0.0); + + while (gtk_events_pending ()) + gtk_main_iteration (); +} + +static void +dialog_set_progress (double percent) +{ + gchar text[5]; + + snprintf (text, sizeof (text), "%d%%", (gint) (percent * 100.0f)); + + gtk_progress_bar_set_fraction (progress, percent); + gtk_progress_bar_set_text (progress, text); + + while (gtk_events_pending ()) + gtk_main_iteration (); +} + +static gboolean +check_for_conflict (ESourceGroup *group, gchar *name) +{ + GSList *sources; + GSList *s; + + sources = e_source_group_peek_sources (group); + + for (s = sources; s; s = s->next) { + ESource *source = E_SOURCE (s->data); + + if (!strcmp (e_source_peek_name (source), name)) + return TRUE; + } + + return FALSE; +} + +static gchar * +get_source_name (ESourceGroup *group, const gchar *path) +{ + gchar **p = g_strsplit (path, "/", 0); + gint i, j, starting_index; + gint num_elements; + gboolean conflict; + GString *s = g_string_new (NULL); + + for (i = 0; p[i]; i ++); + + num_elements = i; + i--; + + /* p[i] is now the last path element */ + + /* check if it conflicts */ + starting_index = i; + do { + for (j = starting_index; j < num_elements; j += 2) { + if (j != starting_index) + g_string_append_c (s, '_'); + g_string_append (s, p[j]); + } + + conflict = check_for_conflict (group, s->str); + + + /* if there was a conflict back up 2 levels (skipping the /subfolder/ element) */ + if (conflict) + starting_index -= 2; + + /* we always break out if we can't go any further, + regardless of whether or not we conflict. */ + if (starting_index < 0) + break; + + } while (conflict); + g_strfreev (p); + + return g_string_free (s, FALSE); +} + +static gboolean +migrate_ical (ECal *old_ecal, ECal *new_ecal) +{ + GList *l, *objects; + gint num_added = 0; + gint num_objects; + gboolean retval = TRUE; + + /* both ecals are loaded, start the actual migration */ + if (!e_cal_get_object_list (old_ecal, "#t", &objects, NULL)) + return FALSE; + + num_objects = g_list_length (objects); + for (l = objects; l; l = l->next) { + icalcomponent *ical_comp = l->data; + GError *error = NULL; + + if (!e_cal_create_object (new_ecal, ical_comp, NULL, &error)) { + g_warning ("Migration of object failed: %s", error->message); + retval = FALSE; + } + + g_clear_error (&error); + + num_added ++; + dialog_set_progress ((double)num_added / num_objects); + } + + g_list_foreach (objects, (GFunc) icalcomponent_free, NULL); + g_list_free (objects); + + return retval; +} + +static gboolean +migrate_ical_folder_to_source (gchar *old_path, ESource *new_source, ECalSourceType type) +{ + ECal *old_ecal = NULL, *new_ecal = NULL; + ESource *old_source; + ESourceGroup *group; + gchar *old_uri = g_strdup_printf ("file://%s", old_path); + GError *error = NULL; + gboolean retval = FALSE; + + group = e_source_group_new ("", old_uri); + old_source = e_source_new ("", ""); + e_source_group_add_source (group, old_source, -1); + + dialog_set_folder_name (e_source_peek_name (new_source)); + + if (!(old_ecal = e_cal_new (old_source, type))) { + g_warning ("could not find a backend for '%s'", e_source_get_uri (old_source)); + goto finish; + } + if (!e_cal_open (old_ecal, FALSE, &error)) { + g_warning ("failed to load source ecal for migration: '%s' (%s)", error->message, + e_source_get_uri (old_source)); + goto finish; + } + + if (!(new_ecal = e_cal_new (new_source, type))) { + g_warning ("could not find a backend for '%s'", e_source_get_uri (new_source)); + goto finish; + } + if (!e_cal_open (new_ecal, FALSE, &error)) { + g_warning ("failed to load destination ecal for migration: '%s' (%s)", error->message, + e_source_get_uri (new_source)); + goto finish; + } + + retval = migrate_ical (old_ecal, new_ecal); + +finish: + g_clear_error (&error); + if (old_ecal) + g_object_unref (old_ecal); + g_object_unref (group); + if (new_ecal) + g_object_unref (new_ecal); + g_free (old_uri); + + return retval; +} + +static gboolean +migrate_ical_folder (gchar *old_path, ESourceGroup *dest_group, gchar *source_name, ECalSourceType type) +{ + ESource *new_source; + gboolean retval; + + new_source = e_source_new (source_name, source_name); + e_source_set_relative_uri (new_source, e_source_peek_uid (new_source)); + e_source_group_add_source (dest_group, new_source, -1); + + retval = migrate_ical_folder_to_source (old_path, new_source, type); + + g_object_unref (new_source); + + return retval; +} + +#endif /* !G_OS_WIN32 */ + +#ifndef G_OS_WIN32 + +static void +migrate_pilot_db_key (const gchar *key, gpointer user_data) +{ + EXmlHash *xmlhash = user_data; + + e_xmlhash_add (xmlhash, key, ""); +} + +static void +migrate_pilot_data (const gchar *component, const gchar *conduit, const gchar *old_path, const gchar *new_path) +{ + gchar *changelog, *map; + const gchar *dent; + const gchar *ext; + gchar *filename; + GDir *dir; + + if (!(dir = g_dir_open (old_path, 0, NULL))) + return; + + map = g_alloca (12 + strlen (conduit)); + sprintf (map, "pilot-map-%s-", conduit); + + changelog = g_alloca (24 + strlen (conduit)); + sprintf (changelog, "pilot-sync-evolution-%s-", conduit); + + while ((dent = g_dir_read_name (dir))) { + if (!strncmp (dent, map, strlen (map)) && + ((ext = strrchr (dent, '.')) && !strcmp (ext, ".xml"))) { + /* pilot map file - src and dest file formats are identical */ + guchar inbuf[4096]; + gsize nread, nwritten; + gint fd0, fd1; + gssize n; + + filename = g_build_filename (old_path, dent, NULL); + if ((fd0 = g_open (filename, O_RDONLY|O_BINARY, 0)) == -1) { + g_free (filename); + continue; + } + + g_free (filename); + filename = g_build_filename (new_path, dent, NULL); + if ((fd1 = g_open (filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666)) == -1) { + g_free (filename); + close (fd0); + continue; + } + + do { + do { + n = read (fd0, inbuf, sizeof (inbuf)); + } while (n == -1 && errno == EINTR); + + if (n < 1) + break; + + nread = n; + nwritten = 0; + do { + do { + n = write (fd1, inbuf + nwritten, nread - nwritten); + } while (n == -1 && errno == EINTR); + + if (n > 0) + nwritten += n; + } while (nwritten < nread && n != -1); + + if (n == -1) + break; + } while (1); + + if (n != -1) + n = fsync (fd1); + + if (n == -1) { + g_warning ("Failed to migrate %s: %s", dent, strerror (errno)); + g_unlink (filename); + } + + close (fd0); + close (fd1); + g_free (filename); + } else if (!strncmp (dent, changelog, strlen (changelog)) && + ((ext = strrchr (dent, '.')) && !strcmp (ext, ".db"))) { + /* src and dest formats differ, src format is db3 while dest format is xml */ + EXmlHash *xmlhash; + EDbHash *dbhash; + struct stat st; + + filename = g_build_filename (old_path, dent, NULL); + if (g_stat (filename, &st) == -1) { + g_free (filename); + continue; + } + + dbhash = e_dbhash_new (filename); + g_free (filename); + + filename = g_strdup_printf ("%s/%s.ics-%s", new_path, component, dent); + if (g_stat (filename, &st) != -1) + g_unlink (filename); + xmlhash = e_xmlhash_new (filename); + g_free (filename); + + e_dbhash_foreach_key (dbhash, migrate_pilot_db_key, xmlhash); + + e_dbhash_destroy (dbhash); + + e_xmlhash_write (xmlhash); + e_xmlhash_destroy (xmlhash); + } + } + + g_dir_close (dir); +} + +#endif + +static void +create_task_sources (EShellBackend *shell_backend, + ESourceList *source_list, + ESourceGroup **on_this_computer, + ESourceGroup **on_the_web, + ESource **personal_source) +{ + GSList *groups; + ESourceGroup *group; + gchar *base_uri, *base_uri_proto; + const gchar *base_dir; + + *on_this_computer = NULL; + *on_the_web = NULL; + *personal_source = NULL; + + base_dir = e_shell_backend_get_config_dir (shell_backend); + base_uri = g_build_filename (base_dir, "local", NULL); + + base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL); + + groups = e_source_list_peek_groups (source_list); + if (groups) { + /* groups are already there, we need to search for things... */ + GSList *g; + + for (g = groups; g; g = g->next) { + + group = E_SOURCE_GROUP (g->data); + + if (!*on_this_computer && !strcmp (base_uri_proto, e_source_group_peek_base_uri (group))) + *on_this_computer = g_object_ref (group); + else if (!*on_the_web && !strcmp (WEBCAL_BASE_URI, e_source_group_peek_base_uri (group))) + *on_the_web = g_object_ref (group); + } + } + + if (*on_this_computer) { + /* make sure "Personal" shows up as a source under + this group */ + GSList *sources = e_source_group_peek_sources (*on_this_computer); + GSList *s; + for (s = sources; s; s = s->next) { + ESource *source = E_SOURCE (s->data); + const gchar *relative_uri; + + relative_uri = e_source_peek_relative_uri (source); + if (relative_uri == NULL) + continue; + if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) { + *personal_source = g_object_ref (source); + break; + } + } + } else { + /* create the local source group */ + group = e_source_group_new (_("On This Computer"), base_uri_proto); + e_source_list_add_group (source_list, group, -1); + + *on_this_computer = group; + } + + if (!*personal_source) { + /* Create the default Person task list */ + ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); + e_source_group_add_source (*on_this_computer, source, -1); + + if (!calendar_config_get_primary_tasks () && !calendar_config_get_tasks_selected ()) { + GSList selected; + + calendar_config_set_primary_tasks (e_source_peek_uid (source)); + + selected.data = (gpointer)e_source_peek_uid (source); + selected.next = NULL; + calendar_config_set_tasks_selected (&selected); + } + + e_source_set_color_spec (source, "#BECEDD"); + *personal_source = source; + } + + if (!*on_the_web) { + /* Create the Webcal source group */ + group = e_source_group_new (_("On The Web"), WEBCAL_BASE_URI); + e_source_list_add_group (source_list, group, -1); + + *on_the_web = group; + } + + g_free (base_uri_proto); + g_free (base_uri); +} + +gboolean +e_task_shell_backend_migrate (EShellBackend *shell_backend, + gint major, + gint minor, + gint micro, + GError **error) +{ + ESourceGroup *on_this_computer = NULL; + ESourceGroup *on_the_web = NULL; + ESource *personal_source = NULL; + ESourceList *source_list; + gboolean retval = FALSE; + + source_list = g_object_get_data ( + G_OBJECT (source_list), "source-list"); + + /* we call this unconditionally now - create_groups either + creates the groups/sources or it finds the necessary + groups/sources. */ + create_task_sources ( + shell_backend, source_list, &on_this_computer, + &on_the_web, &personal_source); + +#ifndef G_OS_WIN32 + if (major == 1) { + xmlDocPtr config_doc = NULL; + gchar *conf_file; + + conf_file = g_build_filename (g_get_home_dir (), "evolution", "config.xmldb", NULL); + if (g_file_test (conf_file, G_FILE_TEST_IS_REGULAR)) + config_doc = e_xml_parse_file (conf_file); + g_free (conf_file); + + if (config_doc && minor <= 2) { + GConfClient *gconf; + gint res = 0; + + /* move bonobo config to gconf */ + gconf = gconf_client_get_default (); + + res = e_bconf_import (gconf, config_doc, task_remap_list); + + g_object_unref (gconf); + + xmlFreeDoc(config_doc); + + if (res != 0) { + g_set_error(error, 0, 0, _("Unable to migrate old settings from evolution/config.xmldb")); + goto fail; + } + } + + if (minor <= 4) { + GSList *migration_dirs, *l; + gchar *path, *local_task_folder; + + setup_progress_dialog (); + + path = g_build_filename (g_get_home_dir (), "evolution", "local", NULL); + migration_dirs = e_folder_map_local_folders (path, "tasks"); + local_task_folder = g_build_filename (path, "Tasks", NULL); + g_free (path); + + if (personal_source) + migrate_ical_folder_to_source (local_task_folder, personal_source, E_CAL_SOURCE_TYPE_TODO); + + for (l = migration_dirs; l; l = l->next) { + gchar *source_name; + + if (personal_source && !strcmp ((gchar *)l->data, local_task_folder)) + continue; + + source_name = get_source_name (on_this_computer, (gchar *)l->data); + + if (!migrate_ical_folder (l->data, on_this_computer, source_name, E_CAL_SOURCE_TYPE_TODO)) { + /* FIXME: domain/code */ + g_set_error(error, 0, 0, _("Unable to migrate tasks `%s'"), source_name); + g_free(source_name); + goto fail; + } + + g_free (source_name); + } + + g_free (local_task_folder); + + dialog_close (); + } + + if (minor < 5 || (minor == 5 && micro <= 10)) { + gchar *old_path, *new_path; + + old_path = g_build_filename (g_get_home_dir (), "evolution", "local", "Tasks", NULL); + new_path = g_build_filename (e_shell_backend_get_config_dir (shell_backend), + "local", "system", NULL); + migrate_pilot_data ("tasks", "todo", old_path, new_path); + g_free (new_path); + g_free (old_path); + } + + /* we only need to do this next step if people ran + older versions of 1.5. We need to clear out the + absolute URI's that were assigned to ESources + during one phase of development, as they take + precedent over relative uris (but aren't updated + when editing an ESource). */ + if (minor == 5 && micro <= 11) { + GSList *g; + for (g = e_source_list_peek_groups (source_list); g; g = g->next) { + ESourceGroup *group = g->data; + GSList *s; + + for (s = e_source_group_peek_sources (group); s; s = s->next) { + ESource *source = s->data; + e_source_set_absolute_uri (source, NULL); + } + } + } + } +#endif /* !G_OS_WIN32 */ + e_source_list_sync (source_list, NULL); + retval = TRUE; +fail: + if (on_this_computer) + g_object_unref (on_this_computer); + if (on_the_web) + g_object_unref (on_the_web); + if (personal_source) + g_object_unref (personal_source); + + return retval; +} diff --git a/modules/calendar/e-task-shell-migrate.h b/modules/calendar/e-task-shell-migrate.h new file mode 100644 index 0000000000..4cb91c9f4a --- /dev/null +++ b/modules/calendar/e-task-shell-migrate.h @@ -0,0 +1,38 @@ +/* + * e-task-shell-backend-migrate.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_TASK_SHELL_BACKEND_MIGRATE_H +#define E_TASK_SHELL_BACKEND_MIGRATE_H + +#include +#include + +G_BEGIN_DECLS + +gboolean e_task_shell_backend_migrate (EShellBackend *shell_backend, + gint major, + gint minor, + gint micro, + GError **error); + +G_END_DECLS + +#endif /* E_TASK_SHELL_BACKEND_MIGRATE_H */ diff --git a/modules/calendar/e-task-shell-sidebar.c b/modules/calendar/e-task-shell-sidebar.c new file mode 100644 index 0000000000..827a0a037e --- /dev/null +++ b/modules/calendar/e-task-shell-sidebar.c @@ -0,0 +1,696 @@ +/* + * e-task-shell-sidebar.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-task-shell-sidebar.h" + +#include +#include +#include + +#include "e-util/e-error.h" +#include "e-util/e-util.h" +#include "calendar/common/authentication.h" +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/e-task-list-selector.h" +#include "calendar/gui/misc.h" + +#include "e-task-shell-backend.h" +#include "e-task-shell-view.h" + +#define E_TASK_SHELL_SIDEBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_TASK_SHELL_SIDEBAR, ETaskShellSidebarPrivate)) + +struct _ETaskShellSidebarPrivate { + GtkWidget *selector; + + /* UID -> Client */ + GHashTable *client_table; +}; + +enum { + PROP_0, + PROP_SELECTOR +}; + +enum { + CLIENT_ADDED, + CLIENT_REMOVED, + STATUS_MESSAGE, + LAST_SIGNAL +}; + +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; +static GType task_shell_sidebar_type; + +static void +task_shell_sidebar_emit_client_added (ETaskShellSidebar *task_shell_sidebar, + ECal *client) +{ + guint signal_id = signals[CLIENT_ADDED]; + + g_signal_emit (task_shell_sidebar, signal_id, 0, client); +} + +static void +task_shell_sidebar_emit_client_removed (ETaskShellSidebar *task_shell_sidebar, + ECal *client) +{ + guint signal_id = signals[CLIENT_REMOVED]; + + g_signal_emit (task_shell_sidebar, signal_id, 0, client); +} + +static void +task_shell_sidebar_emit_status_message (ETaskShellSidebar *task_shell_sidebar, + const gchar *status_message) +{ + guint signal_id = signals[STATUS_MESSAGE]; + + g_signal_emit (task_shell_sidebar, signal_id, 0, status_message, -1.0); +} + +static void +task_shell_sidebar_backend_died_cb (ETaskShellSidebar *task_shell_sidebar, + ECal *client) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + GHashTable *client_table; + ESource *source; + const gchar *uid; + + client_table = task_shell_sidebar->priv->client_table; + + shell_sidebar = E_SHELL_SIDEBAR (task_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + source = e_cal_get_source (client); + uid = e_source_peek_uid (source); + + g_object_ref (source); + + g_hash_table_remove (client_table, uid); + task_shell_sidebar_emit_status_message (task_shell_sidebar, NULL); + + e_error_run ( + GTK_WINDOW (shell_window), + "calendar:tasks-crashed", NULL); + + g_object_unref (source); +} + +static void +task_shell_sidebar_backend_error_cb (ETaskShellSidebar *task_shell_sidebar, + const gchar *message, + ECal *client) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + GtkWidget *dialog; + const gchar *uri; + gchar *uri_no_passwd; + + shell_sidebar = E_SHELL_SIDEBAR (task_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + uri = e_cal_get_uri (client); + uri_no_passwd = get_uri_without_password (uri); + + dialog = gtk_message_dialog_new ( + GTK_WINDOW (shell_window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, + _("Error on %s\n%s"), + uri_no_passwd, message); + + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + + g_free (uri_no_passwd); +} + +static void +task_shell_sidebar_client_opened_cb (ETaskShellSidebar *task_shell_sidebar, + ECalendarStatus status, + ECal *client) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + ESource *source; + + source = e_cal_get_source (client); + + shell_sidebar = E_SHELL_SIDEBAR (task_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + if (status == E_CALENDAR_STATUS_AUTHENTICATION_FAILED || + status == E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED) + auth_cal_forget_password (client); + + switch (status) { + case E_CALENDAR_STATUS_OK: + g_signal_handlers_disconnect_matched ( + client, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, + task_shell_sidebar_client_opened_cb, NULL); + + task_shell_sidebar_emit_status_message ( + task_shell_sidebar, _("Loading tasks")); + task_shell_sidebar_emit_client_added ( + task_shell_sidebar, client); + task_shell_sidebar_emit_status_message ( + task_shell_sidebar, NULL); + break; + + case E_CALENDAR_STATUS_AUTHENTICATION_FAILED: + e_cal_open_async (client, FALSE); + break; + + case E_CALENDAR_STATUS_BUSY: + break; + + case E_CALENDAR_STATUS_REPOSITORY_OFFLINE: + e_error_run ( + GTK_WINDOW (shell_window), + "calendar:prompt-no-contents-offline-tasks", + NULL); + break; + + default: + task_shell_sidebar_emit_client_removed ( + task_shell_sidebar, client); + break; + } +} + +static void +task_shell_sidebar_row_changed_cb (ETaskShellSidebar *task_shell_sidebar, + GtkTreePath *tree_path, + GtkTreeIter *tree_iter, + GtkTreeModel *tree_model) +{ + ESourceSelector *selector; + ESource *source; + + /* XXX ESourceSelector's underlying tree store has only one + * column: ESource objects. While we're not supposed to + * know this, listening for "row-changed" signals from + * the model is easier to deal with than the selector's + * "selection-changed" signal, which doesn't tell you + * _which_ row changed. */ + + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + gtk_tree_model_get (tree_model, tree_iter, 0, &source, -1); + + /* XXX This signal gets emitted a lot while the model is being + * rebuilt, during which time we won't get a valid ESource. + * ESourceSelector should probably block this signal while + * rebuilding the model, but we'll be forgiving and not + * emit a warning. */ + if (!E_IS_SOURCE (source)) + return; + + if (e_source_selector_source_is_selected (selector, source)) + e_task_shell_sidebar_add_source (task_shell_sidebar, source); + else + e_task_shell_sidebar_remove_source (task_shell_sidebar, source); +} + +static void +task_shell_sidebar_selection_changed_cb (ETaskShellSidebar *task_shell_sidebar, + ESourceSelector *selector) +{ + GSList *list, *iter; + + /* This signal is emitted less frequently than "row-changed", + * especially when the model is being rebuilt. So we'll take + * it easy on poor GConf. */ + + list = e_source_selector_get_selection (selector); + + for (iter = list; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + + iter->data = (gpointer) e_source_peek_uid (source); + g_object_unref (source); + } + + calendar_config_set_tasks_selected (list); + + g_slist_free (list); +} + +static void +task_shell_sidebar_primary_selection_changed_cb (ETaskShellSidebar *task_shell_sidebar, + ESourceSelector *selector) +{ + ESource *source; + const gchar *uid; + + /* XXX ESourceSelector needs a "primary-selection-uid" property + * so we can just bind the property with GConfBridge. */ + + source = e_source_selector_peek_primary_selection (selector); + if (source == NULL) + return; + + uid = e_source_peek_uid (source); + calendar_config_set_primary_tasks (uid); +} + +static void +task_shell_sidebar_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SELECTOR: + g_value_set_object ( + value, e_task_shell_sidebar_get_selector ( + E_TASK_SHELL_SIDEBAR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +task_shell_sidebar_dispose (GObject *object) +{ + ETaskShellSidebarPrivate *priv; + + priv = E_TASK_SHELL_SIDEBAR_GET_PRIVATE (object); + + if (priv->selector != NULL) { + g_object_unref (priv->selector); + priv->selector = NULL; + } + + g_hash_table_remove_all (priv->client_table); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +task_shell_sidebar_finalize (GObject *object) +{ + ETaskShellSidebarPrivate *priv; + + priv = E_TASK_SHELL_SIDEBAR_GET_PRIVATE (object); + + g_hash_table_destroy (priv->client_table); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +task_shell_sidebar_constructed (GObject *object) +{ + ETaskShellSidebarPrivate *priv; + EShellView *shell_view; + EShellBackend *shell_backend; + EShellSidebar *shell_sidebar; + ESourceSelector *selector; + ESourceList *source_list; + ESource *source; + GtkContainer *container; + GtkTreeModel *model; + GtkWidget *widget; + AtkObject *a11y; + GSList *list, *iter; + gchar *uid; + + priv = E_TASK_SHELL_SIDEBAR_GET_PRIVATE (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + shell_sidebar = E_SHELL_SIDEBAR (object); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + source_list = e_task_shell_backend_get_source_list ( + E_TASK_SHELL_BACKEND (shell_backend)); + + container = GTK_CONTAINER (shell_sidebar); + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_container_add (container, widget); + gtk_widget_show (widget); + + container = GTK_CONTAINER (widget); + + widget = e_task_list_selector_new (source_list); + e_source_selector_set_select_new (E_SOURCE_SELECTOR (widget), TRUE); + gtk_container_add (container, widget); + a11y = gtk_widget_get_accessible (widget); + atk_object_set_name (a11y, _("Task List Selector")); + priv->selector = g_object_ref (widget); + gtk_widget_show (widget); + + /* Restore the selector state from the last session. */ + + selector = E_SOURCE_SELECTOR (priv->selector); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); + + g_signal_connect_swapped ( + model, "row-changed", + G_CALLBACK (task_shell_sidebar_row_changed_cb), + object); + + source = NULL; + uid = calendar_config_get_primary_tasks (); + if (uid != NULL) + source = e_source_list_peek_source_by_uid (source_list, uid); + if (source == NULL) + source = e_source_list_peek_source_any (source_list); + if (source != NULL) + e_source_selector_set_primary_selection (selector, source); + g_free (uid); + + list = calendar_config_get_tasks_selected (); + for (iter = list; iter != NULL; iter = iter->next) { + uid = iter->data; + source = e_source_list_peek_source_by_uid (source_list, uid); + g_free (uid); + + if (source == NULL) + continue; + + e_source_selector_select_source (selector, source); + } + g_slist_free (list); + + /* Listen for subsequent changes to the selector. */ + + g_signal_connect_swapped ( + widget, "selection-changed", + G_CALLBACK (task_shell_sidebar_selection_changed_cb), + object); + + g_signal_connect_swapped ( + widget, "primary-selection-changed", + G_CALLBACK (task_shell_sidebar_primary_selection_changed_cb), + object); +} + +static guint32 +task_shell_sidebar_check_state (EShellSidebar *shell_sidebar) +{ + ETaskShellSidebar *task_shell_sidebar; + ESourceSelector *selector; + ESource *source; + gboolean is_system = FALSE; + guint32 state = 0; + + task_shell_sidebar = E_TASK_SHELL_SIDEBAR (shell_sidebar); + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + + if (source != NULL) { + const gchar *uri; + + uri = e_source_peek_relative_uri (source); + is_system = (uri == NULL || strcmp (uri, "system") == 0); + } + + if (source != NULL) + state |= E_TASK_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE; + if (is_system) + state |= E_TASK_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM; + + return state; +} + +static void +task_shell_sidebar_client_removed (ETaskShellSidebar *task_shell_sidebar, + ECal *client) +{ + ESourceSelector *selector; + GHashTable *client_table; + ESource *source; + const gchar *uid; + + client_table = task_shell_sidebar->priv->client_table; + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + + g_signal_handlers_disconnect_matched ( + client, G_SIGNAL_MATCH_DATA, 0, 0, + NULL, NULL, task_shell_sidebar); + + source = e_cal_get_source (client); + e_source_selector_unselect_source (selector, source); + + uid = e_source_peek_uid (source); + g_hash_table_remove (client_table, uid); + + task_shell_sidebar_emit_status_message (task_shell_sidebar, NULL); +} + +static void +task_shell_sidebar_class_init (ETaskShellSidebarClass *class) +{ + GObjectClass *object_class; + EShellSidebarClass *shell_sidebar_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ETaskShellSidebarPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->get_property = task_shell_sidebar_get_property; + object_class->dispose = task_shell_sidebar_dispose; + object_class->finalize = task_shell_sidebar_finalize; + object_class->constructed = task_shell_sidebar_constructed; + + shell_sidebar_class = E_SHELL_SIDEBAR_CLASS (class); + shell_sidebar_class->check_state = task_shell_sidebar_check_state; + + class->client_removed = task_shell_sidebar_client_removed; + + g_object_class_install_property ( + object_class, + PROP_SELECTOR, + g_param_spec_object ( + "selector", + _("Source Selector Widget"), + _("This widget displays groups of task lists"), + E_TYPE_SOURCE_SELECTOR, + G_PARAM_READABLE)); + + signals[CLIENT_ADDED] = g_signal_new ( + "client-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ETaskShellSidebarClass, client_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CAL); + + signals[CLIENT_REMOVED] = g_signal_new ( + "client-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ETaskShellSidebarClass, client_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CAL); + + signals[STATUS_MESSAGE] = g_signal_new ( + "status-message", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (ETaskShellSidebarClass, status_message), + NULL, NULL, + e_marshal_VOID__STRING_DOUBLE, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_DOUBLE); +} + +static void +task_shell_sidebar_init (ETaskShellSidebar *task_shell_sidebar) +{ + GHashTable *client_table; + + client_table = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_object_unref); + + task_shell_sidebar->priv = + E_TASK_SHELL_SIDEBAR_GET_PRIVATE (task_shell_sidebar); + + task_shell_sidebar->priv->client_table = client_table; + + /* Postpone widget construction until we have a shell view. */ +} + +GType +e_task_shell_sidebar_get_type (void) +{ + return task_shell_sidebar_type; +} + +void +e_task_shell_sidebar_register_type (GTypeModule *type_module) +{ + static const GTypeInfo type_info = { + sizeof (ETaskShellSidebarClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) task_shell_sidebar_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ETaskShellSidebar), + 0, /* n_preallocs */ + (GInstanceInitFunc) task_shell_sidebar_init, + NULL /* value_table */ + }; + + task_shell_sidebar_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_SIDEBAR, + "ETaskShellSidebar", &type_info, 0); +} + +GtkWidget * +e_task_shell_sidebar_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_TASK_SHELL_SIDEBAR, + "shell-view", shell_view, NULL); +} + +GList * +e_task_shell_sidebar_get_clients (ETaskShellSidebar *task_shell_sidebar) +{ + GHashTable *client_table; + + g_return_val_if_fail ( + E_IS_TASK_SHELL_SIDEBAR (task_shell_sidebar), NULL); + + client_table = task_shell_sidebar->priv->client_table; + + return g_hash_table_get_values (client_table); +} + +ESourceSelector * +e_task_shell_sidebar_get_selector (ETaskShellSidebar *task_shell_sidebar) +{ + g_return_val_if_fail ( + E_IS_TASK_SHELL_SIDEBAR (task_shell_sidebar), NULL); + + return E_SOURCE_SELECTOR (task_shell_sidebar->priv->selector); +} + +void +e_task_shell_sidebar_add_source (ETaskShellSidebar *task_shell_sidebar, + ESource *source) +{ + ESourceSelector *selector; + GHashTable *client_table; + ECal *client; + const gchar *uid; + const gchar *uri; + gchar *message; + + g_return_if_fail (E_IS_TASK_SHELL_SIDEBAR (task_shell_sidebar)); + g_return_if_fail (E_IS_SOURCE (source)); + + client_table = task_shell_sidebar->priv->client_table; + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + + uid = e_source_peek_uid (source); + client = g_hash_table_lookup (client_table, uid); + + if (client != NULL) + return; + + client = auth_new_cal_from_source (source, E_CAL_SOURCE_TYPE_TODO); + g_return_if_fail (client != NULL); + + g_signal_connect_swapped ( + client, "backend-died", + G_CALLBACK (task_shell_sidebar_backend_died_cb), + task_shell_sidebar); + + g_signal_connect_swapped ( + client, "backend-error", + G_CALLBACK (task_shell_sidebar_backend_error_cb), + task_shell_sidebar); + + g_hash_table_insert (client_table, g_strdup (uid), client); + e_source_selector_select_source (selector, source); + + uri = e_cal_get_uri (client); + message = g_strdup_printf (_("Opening tasks at %s"), uri); + task_shell_sidebar_emit_status_message (task_shell_sidebar, message); + g_free (message); + + g_signal_connect_swapped ( + client, "cal-opened", + G_CALLBACK (task_shell_sidebar_client_opened_cb), + task_shell_sidebar); + + e_cal_open_async (client, FALSE); +} + +void +e_task_shell_sidebar_remove_source (ETaskShellSidebar *task_shell_sidebar, + ESource *source) +{ + ESourceSelector *selector; + GHashTable *client_table; + ECal *client; + const gchar *uid; + + g_return_if_fail (E_IS_TASK_SHELL_SIDEBAR (task_shell_sidebar)); + g_return_if_fail (E_IS_SOURCE (source)); + + client_table = task_shell_sidebar->priv->client_table; + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + + uid = e_source_peek_uid (source); + client = g_hash_table_lookup (client_table, uid); + + if (client == NULL) + return; + + task_shell_sidebar_emit_client_removed (task_shell_sidebar, client); +} diff --git a/modules/calendar/e-task-shell-sidebar.h b/modules/calendar/e-task-shell-sidebar.h new file mode 100644 index 0000000000..5d4c74fe11 --- /dev/null +++ b/modules/calendar/e-task-shell-sidebar.h @@ -0,0 +1,97 @@ +/* + * e-task-shell-sidebar.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_TASK_SHELL_SIDEBAR_H +#define E_TASK_SHELL_SIDEBAR_H + +#include +#include + +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_TASK_SHELL_SIDEBAR \ + (e_task_shell_sidebar_get_type ()) +#define E_TASK_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_TASK_SHELL_SIDEBAR, ETaskShellSidebar)) +#define E_TASK_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_TASK_SHELL_SIDEBAR, ETaskShellSidebarClass)) +#define E_IS_TASK_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_TASK_SHELL_SIDEBAR)) +#define E_IS_TASK_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_TASK_SHELL_SIDEBAR)) +#define E_TASK_SHELL_SIDEBAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_TASK_SHELL_SIDEBAR, ETaskShellSidebarClass)) + +G_BEGIN_DECLS + +typedef struct _ETaskShellSidebar ETaskShellSidebar; +typedef struct _ETaskShellSidebarClass ETaskShellSidebarClass; +typedef struct _ETaskShellSidebarPrivate ETaskShellSidebarPrivate; + +enum { + E_TASK_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE = 1 << 0, + E_TASK_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM = 1 << 1 +}; + +struct _ETaskShellSidebar { + EShellSidebar parent; + ETaskShellSidebarPrivate *priv; +}; + +struct _ETaskShellSidebarClass { + EShellSidebarClass parent_class; + + /* Signals */ + void (*client_added) (ETaskShellSidebar *task_shell_sidebar, + ECal *client); + void (*client_removed) (ETaskShellSidebar *task_shell_sidebar, + ECal *client); + void (*status_message) (ETaskShellSidebar *task_shell_sidebar, + const gchar *status_message, + gdouble percent); +}; + +GType e_task_shell_sidebar_get_type (void); +void e_task_shell_sidebar_register_type + (GTypeModule *type_module); +GtkWidget * e_task_shell_sidebar_new(EShellView *shell_view); +GList * e_task_shell_sidebar_get_clients + (ETaskShellSidebar *task_shell_sidebar); +ESourceSelector * + e_task_shell_sidebar_get_selector + (ETaskShellSidebar *task_shell_sidebar); +void e_task_shell_sidebar_add_source + (ETaskShellSidebar *task_shell_sidebar, + ESource *source); +void e_task_shell_sidebar_remove_source + (ETaskShellSidebar *task_shell_sidebar, + ESource *source); + +G_END_DECLS + +#endif /* E_TASK_SHELL_SIDEBAR_H */ diff --git a/modules/calendar/e-task-shell-view-actions.c b/modules/calendar/e-task-shell-view-actions.c new file mode 100644 index 0000000000..4deed9fdf0 --- /dev/null +++ b/modules/calendar/e-task-shell-view-actions.c @@ -0,0 +1,1154 @@ +/* + * e-task-shell-view-actions.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-task-shell-view-private.h" + +static void +action_gal_save_custom_view_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + EShellView *shell_view; + GalViewInstance *view_instance; + + /* All shell views respond to the activation of this action, + * which is defined by EShellWindow. But only the currently + * active shell view proceeds with saving the custom view. */ + shell_view = E_SHELL_VIEW (task_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + task_shell_content = task_shell_view->priv->task_shell_content; + view_instance = e_task_shell_content_get_view_instance (task_shell_content); + gal_view_instance_save_as (view_instance); +} + +static void +action_search_execute_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + EShellView *shell_view; + + /* All shell views respond to the activation of this action, + * which is defined by EShellWindow. But only the currently + * active shell view proceeds with executing the search. */ + shell_view = E_SHELL_VIEW (task_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + e_task_shell_view_execute_search (task_shell_view); +} + +static void +action_search_filter_cb (GtkRadioAction *action, + GtkRadioAction *current, + ETaskShellView *task_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + gtk_action_activate (ACTION (SEARCH_EXECUTE)); +} + +static void +action_task_assign_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + GSList *list; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only open the first selected task. */ + e_task_shell_view_open_task (task_shell_view, comp_data); + + /* FIXME Need to actually assign the task. */ +} + +static void +action_task_clipboard_copy_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + e_calendar_table_copy_clipboard (task_table); +} + +static void +action_task_clipboard_cut_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + e_calendar_table_cut_clipboard (task_table); +} + +static void +action_task_clipboard_paste_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + e_calendar_table_paste_clipboard (task_table); +} + +static void +action_task_delete_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalComponentPreview *task_preview; + ECalendarTable *task_table; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + task_preview = e_task_shell_content_get_task_preview (task_shell_content); + + e_task_shell_view_set_status_message ( + task_shell_view, _("Deleting selected tasks..."), -1.0); + e_calendar_table_delete_selected (task_table); + e_task_shell_view_set_status_message (task_shell_view, NULL, -1.0); + + e_cal_component_preview_clear (task_preview); +} + +static void +action_task_forward_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + ECalComponent *comp; + icalcomponent *clone; + GSList *list; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only forward the first selected task. */ + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_component_set_icalcomponent (comp, clone); + itip_send_comp ( + E_CAL_COMPONENT_METHOD_PUBLISH, comp, + comp_data->client, NULL, NULL, NULL, TRUE); + g_object_unref (comp); +} + +static void +action_task_list_copy_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellSidebar *task_shell_sidebar; + EShellWindow *shell_window; + EShellView *shell_view; + ESourceSelector *selector; + ESource *source; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (E_IS_SOURCE (source)); + + copy_source_dialog ( + GTK_WINDOW (shell_window), + source, E_CAL_SOURCE_TYPE_TODO); +} + +static void +action_task_list_delete_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellBackend *task_shell_backend; + ETaskShellContent *task_shell_content; + ETaskShellSidebar *task_shell_sidebar; + EShellWindow *shell_window; + EShellView *shell_view; + ECalendarTable *task_table; + ECal *client; + ECalModel *model; + ESourceSelector *selector; + ESourceGroup *source_group; + ESourceList *source_list; + ESource *source; + gint response; + gchar *uri; + GError *error = NULL; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + task_shell_backend = task_shell_view->priv->task_shell_backend; + source_list = e_task_shell_backend_get_source_list (task_shell_backend); + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + model = e_calendar_table_get_model (task_table); + + task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (E_IS_SOURCE (source)); + + /* Ask for confirmation. */ + response = e_error_run ( + GTK_WINDOW (shell_window), + "calendar:prompt-delete-task-list", + e_source_peek_name (source)); + if (response != GTK_RESPONSE_YES) + return; + + uri = e_source_get_uri (source); + client = e_cal_model_get_client_for_uri (model, uri); + if (client == NULL) + client = e_cal_new_from_uri (uri, E_CAL_SOURCE_TYPE_JOURNAL); + g_free (uri); + + g_return_if_fail (client != NULL); + + if (!e_cal_remove (client, &error)) { + g_warning ("%s", error->message); + g_error_free (error); + return; + } + + if (e_source_selector_source_is_selected (selector, source)) { + e_task_shell_sidebar_remove_source ( + task_shell_sidebar, source); + e_source_selector_unselect_source (selector, source); + } + + source_group = e_source_peek_group (source); + e_source_group_remove_source (source_group, source); + + if (!e_source_list_sync (source_list, &error)) { + g_warning ("%s", error->message); + g_error_free (error); + } +} + +static void +action_task_list_new_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + calendar_setup_new_task_list (GTK_WINDOW (shell_window)); +} + +static void +action_task_list_print_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ETable *table; + GtkPrintOperationAction print_action; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + table = e_calendar_table_get_table (task_table); + + print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; + print_table (table, _("Print Tasks"), _("Tasks"), print_action); +} + +static void +action_task_list_print_preview_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ETable *table; + GtkPrintOperationAction print_action; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + table = e_calendar_table_get_table (task_table); + + print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW; + print_table (table, _("Print Tasks"), _("Tasks"), print_action); +} + +static void +action_task_list_properties_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellSidebar *task_shell_sidebar; + EShellView *shell_view; + EShellWindow *shell_window; + ESource *source; + ESourceSelector *selector; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + source = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (E_IS_SOURCE (source)); + + calendar_setup_edit_task_list (GTK_WINDOW (shell_window), source); +} + +static void +action_task_list_rename_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellSidebar *task_shell_sidebar; + ESourceSelector *selector; + + task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + + e_source_selector_edit_primary_selection (selector); +} + +static void +action_task_list_select_one_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellSidebar *task_shell_sidebar; + ESourceSelector *selector; + ESource *primary; + GSList *list, *iter; + + /* XXX ESourceSelector should provide a function for this. */ + + task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + primary = e_source_selector_peek_primary_selection (selector); + g_return_if_fail (primary != NULL); + + list = e_source_selector_get_selection (selector); + for (iter = list; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + + if (source == primary) + continue; + + e_source_selector_unselect_source (selector, source); + } + e_source_selector_free_selection (list); + + e_source_selector_select_source (selector, primary); +} + +static void +action_task_mark_complete_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModel *model; + GSList *list, *iter; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + list = e_calendar_table_get_selected (task_table); + model = e_calendar_table_get_model (task_table); + + for (iter = list; iter != NULL; iter = iter->next) { + ECalModelComponent *comp_data = iter->data; + e_cal_model_tasks_mark_comp_complete ( + E_CAL_MODEL_TASKS (model), comp_data); + } + + g_slist_free (list); +} + +static void +action_task_mark_incomplete_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModel *model; + GSList *list, *iter; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + list = e_calendar_table_get_selected (task_table); + model = e_calendar_table_get_model (task_table); + + for (iter = list; iter != NULL; iter = iter->next) { + ECalModelComponent *comp_data = iter->data; + e_cal_model_tasks_mark_comp_incomplete ( + E_CAL_MODEL_TASKS (model), comp_data); + } + + g_slist_free (list); +} + +static void +action_task_new_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + ECal *client; + ECalComponent *comp; + CompEditor *editor; + GSList *list; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + client = comp_data->client; + editor = task_editor_new (client, shell, COMP_EDITOR_NEW_ITEM); + comp = cal_comp_task_new_with_defaults (client); + comp_editor_edit_comp (editor, comp); + + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (comp); + g_object_unref (client); +} + +static void +action_task_open_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + GSList *list; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only open the first selected task. */ + e_task_shell_view_open_task (task_shell_view, comp_data); +} + +static void +action_task_open_url_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + icalproperty *prop; + const gchar *uri; + GSList *list; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + + /* XXX We only open the URI of the first selected task. */ + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_URL_PROPERTY); + g_return_if_fail (prop == NULL); + + uri = icalproperty_get_url (prop); + e_show_uri (GTK_WINDOW (shell_window), uri); +} + +static void +action_task_preview_cb (GtkToggleAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + gboolean visible; + + task_shell_content = task_shell_view->priv->task_shell_content; + visible = gtk_toggle_action_get_active (action); + e_task_shell_content_set_preview_visible (task_shell_content, visible); +} + +static void +action_task_print_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + ECalComponent *comp; + icalcomponent *clone; + GtkPrintOperationAction print_action; + GSList *list; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + /* XXX We only print the first selected task. */ + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; + e_cal_component_set_icalcomponent (comp, clone); + print_comp (comp, comp_data->client, print_action); + g_object_unref (comp); +} + +static void +action_task_purge_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkWidget *dialog; + GtkWidget *widget; + gboolean active; + gint response; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + if (!calendar_config_get_confirm_purge ()) + goto purge; + + /* XXX This needs reworked. The dialog looks like ass. */ + + dialog = gtk_message_dialog_new ( + GTK_WINDOW (shell_window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_YES_NO, + "%s", _("This operation will permanently erase all tasks " + "marked as completed. If you continue, you will not be able " + "to recover these tasks.\n\nReally erase these tasks?")); + + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_NO); + + widget = gtk_check_button_new_with_label (_("Do not ask me again")); + gtk_box_pack_start ( + GTK_BOX (GTK_DIALOG (dialog)->vbox), widget, TRUE, TRUE, 6); + gtk_widget_show (widget); + + response = gtk_dialog_run (GTK_DIALOG (dialog)); + active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)); + gtk_widget_destroy (dialog); + + if (response != GTK_RESPONSE_YES) + return; + + if (active) + calendar_config_set_confirm_purge (FALSE); + +purge: + + /* FIXME */ + ; +} + +static void +action_task_save_as_cb (GtkAction *action, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModelComponent *comp_data; + GSList *list; + gchar *filename; + gchar *string; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + list = e_calendar_table_get_selected (task_table); + g_return_if_fail (list != NULL); + comp_data = list->data; + g_slist_free (list); + + filename = e_file_dialog_save (_("Save as..."), NULL); + if (filename == NULL) + return; + + string = e_cal_get_component_as_string ( + comp_data->client, comp_data->icalcomp); + if (string == NULL) { + g_warning ("Could not convert task to a string"); + return; + } + + e_write_file_uri (filename, string); + + g_free (filename); + g_free (string); +} + +static void +action_task_search_cb (GtkRadioAction *action, + GtkRadioAction *current, + ETaskShellView *task_shell_view) +{ + EShellView *shell_view; + EShellContent *shell_content; + const gchar *search_hint; + + /* XXX Figure out a way to handle this in EShellContent + * instead of every shell view having to handle it. + * The problem is EShellContent does not know what + * the search option actions are for this view. It + * would have to dig up the popup menu and retrieve + * the action for each menu item. Seems messy. */ + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + + search_hint = gtk_action_get_label (GTK_ACTION (current)); + e_shell_content_set_search_hint (shell_content, search_hint); +} + +static GtkActionEntry task_entries[] = { + + { "task-assign", + NULL, + N_("_Assign Task"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_task_assign_cb) }, + + { "task-clipboard-copy", + GTK_STOCK_COPY, + NULL, + NULL, + N_("Copy selected tasks"), + G_CALLBACK (action_task_clipboard_copy_cb) }, + + { "task-clipboard-cut", + GTK_STOCK_CUT, + NULL, + NULL, + N_("Cut selected tasks"), + G_CALLBACK (action_task_clipboard_cut_cb) }, + + { "task-clipboard-paste", + GTK_STOCK_PASTE, + NULL, + NULL, + N_("Paste tasks from the clipboard"), + G_CALLBACK (action_task_clipboard_paste_cb) }, + + { "task-delete", + GTK_STOCK_DELETE, + N_("_Delete Task"), + NULL, + N_("Delete selected tasks"), + G_CALLBACK (action_task_delete_cb) }, + + { "task-forward", + "mail-forward", + N_("_Forward as iCalendar..."), + "f", + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_task_forward_cb) }, + + { "task-list-copy", + GTK_STOCK_COPY, + N_("Copy..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_task_list_copy_cb) }, + + { "task-list-delete", + GTK_STOCK_DELETE, + N_("_Delete"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_task_list_delete_cb) }, + + { "task-list-new", + "stock_todo", + N_("_New Task List"), + NULL, + N_("Create a new task list"), + G_CALLBACK (action_task_list_new_cb) }, + + { "task-list-properties", + GTK_STOCK_PROPERTIES, + NULL, + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_task_list_properties_cb) }, + + { "task-list-rename", + NULL, + N_("_Rename..."), + "F2", + N_("Rename the selected task list"), + G_CALLBACK (action_task_list_rename_cb) }, + + { "task-list-select-one", + "stock_check-filled", + N_("Show _Only This Task List"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_task_list_select_one_cb) }, + + { "task-mark-complete", + NULL, + N_("_Mark as Complete"), + "k", + N_("Mark selected tasks as complete"), + G_CALLBACK (action_task_mark_complete_cb) }, + + { "task-mark-incomplete", + NULL, + N_("Mar_k as Incomplete"), + NULL, + N_("Mark selected tasks as incomplete"), + G_CALLBACK (action_task_mark_incomplete_cb) }, + + { "task-new", + "stock_task", + N_("New _Task"), + NULL, + N_("Create a new task"), + G_CALLBACK (action_task_new_cb) }, + + { "task-open", + GTK_STOCK_OPEN, + N_("_Open Task"), + "o", + N_("View the selected task"), + G_CALLBACK (action_task_open_cb) }, + + { "task-open-url", + "applications-internet", + N_("Open _Web Page"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_task_open_url_cb) }, + + { "task-purge", + NULL, + N_("Purg_e"), + "e", + N_("Delete completed tasks"), + G_CALLBACK (action_task_purge_cb) }, + + { "task-save-as", + GTK_STOCK_SAVE_AS, + N_("_Save as iCalendar..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_task_save_as_cb) }, + + /*** Menus ***/ + + { "task-actions-menu", + NULL, + N_("_Actions"), + NULL, + NULL, + NULL } +}; + +static EPopupActionEntry task_popup_entries[] = { + + { "task-list-popup-copy", + NULL, + "task-list-copy" }, + + { "task-list-popup-delete", + NULL, + "task-list-delete" }, + + { "task-list-popup-properties", + NULL, + "task-list-properties" }, + + { "task-list-popup-rename", + NULL, + "task-list-rename" }, + + { "task-list-popup-select-one", + NULL, + "task-list-select-one" }, + + { "task-popup-assign", + NULL, + "task-assign" }, + + { "task-popup-clipboard-copy", + NULL, + "task-clipboard-copy" }, + + { "task-popup-clipboard-cut", + NULL, + "task-clipboard-cut" }, + + { "task-popup-clipboard-paste", + NULL, + "task-clipboard-paste" }, + + { "task-popup-delete", + NULL, + "task-delete" }, + + { "task-popup-forward", + NULL, + "task-forward" }, + + { "task-popup-mark-complete", + NULL, + "task-mark-complete" }, + + { "task-popup-mark-incomplete", + NULL, + "task-mark-incomplete" }, + + { "task-popup-open", + NULL, + "task-open" }, + + { "task-popup-open-url", + NULL, + "task-open-url" }, + + { "task-popup-save-as", + NULL, + "task-save-as" }, +}; + +static GtkToggleActionEntry task_toggle_entries[] = { + + { "task-preview", + NULL, + N_("Task _Preview"), + "m", + N_("Show task preview pane"), + G_CALLBACK (action_task_preview_cb), + TRUE } +}; + +static GtkRadioActionEntry task_filter_entries[] = { + + { "task-filter-active-tasks", + NULL, + N_("Active Tasks"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_FILTER_ACTIVE_TASKS }, + + { "task-filter-any-category", + NULL, + N_("Any Category"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_FILTER_ANY_CATEGORY }, + + { "task-filter-completed-tasks", + NULL, + N_("Completed Tasks"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_FILTER_COMPLETED_TASKS }, + + { "task-filter-next-7-days-tasks", + NULL, + N_("Next 7 Days' Tasks"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_FILTER_NEXT_7_DAYS_TASKS }, + + { "task-filter-overdue-tasks", + NULL, + N_("Overdue Tasks"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_FILTER_OVERDUE_TASKS }, + + { "task-filter-tasks-with-attachments", + NULL, + N_("Tasks with Attachments"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_FILTER_TASKS_WITH_ATTACHMENTS }, + + { "task-filter-unmatched", + NULL, + N_("Unmatched"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_FILTER_UNMATCHED } +}; + +static GtkRadioActionEntry task_search_entries[] = { + + { "task-search-any-field-contains", + NULL, + N_("Any field contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_SEARCH_ANY_FIELD_CONTAINS }, + + { "task-search-description-contains", + NULL, + N_("Description contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_SEARCH_DESCRIPTION_CONTAINS }, + + { "task-search-summary-contains", + NULL, + N_("Summary contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + TASK_SEARCH_SUMMARY_CONTAINS } +}; + +static GtkActionEntry lockdown_printing_entries[] = { + + { "task-list-print", + GTK_STOCK_PRINT, + NULL, + "p", + N_("Print the list of tasks"), + G_CALLBACK (action_task_list_print_cb) }, + + { "task-list-print-preview", + GTK_STOCK_PRINT_PREVIEW, + NULL, + NULL, + N_("Preview the list of tasks to be printed"), + G_CALLBACK (action_task_list_print_preview_cb) }, + + { "task-print", + GTK_STOCK_PRINT, + NULL, + NULL, + N_("Print the selected task"), + G_CALLBACK (action_task_print_cb) } +}; + +static EPopupActionEntry lockdown_printing_popup_entries[] = { + + { "task-popup-print", + NULL, + "task-print" } +}; + +void +e_task_shell_view_actions_init (ETaskShellView *task_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkActionGroup *action_group; + GConfBridge *bridge; + GtkAction *action; + GObject *object; + const gchar *key; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + /* Task Actions */ + action_group = ACTION_GROUP (TASKS); + gtk_action_group_add_actions ( + action_group, task_entries, + G_N_ELEMENTS (task_entries), task_shell_view); + e_action_group_add_popup_actions ( + action_group, task_popup_entries, + G_N_ELEMENTS (task_popup_entries)); + gtk_action_group_add_toggle_actions ( + action_group, task_toggle_entries, + G_N_ELEMENTS (task_toggle_entries), task_shell_view); + gtk_action_group_add_radio_actions ( + action_group, task_search_entries, + G_N_ELEMENTS (task_search_entries), + TASK_SEARCH_SUMMARY_CONTAINS, + G_CALLBACK (action_task_search_cb), task_shell_view); + + /* Lockdown Printing Actions */ + action_group = ACTION_GROUP (LOCKDOWN_PRINTING); + gtk_action_group_add_actions ( + action_group, lockdown_printing_entries, + G_N_ELEMENTS (lockdown_printing_entries), task_shell_view); + e_action_group_add_popup_actions ( + action_group, lockdown_printing_popup_entries, + G_N_ELEMENTS (lockdown_printing_popup_entries)); + + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (ACTION (TASK_PREVIEW)); + key = "/apps/evolution/calendar/display/show_task_preview"; + gconf_bridge_bind_property (bridge, key, object, "active"); + + /* Fine tuning. */ + + action = ACTION (TASK_DELETE); + g_object_set (action, "short-label", _("Delete"), NULL); + + g_signal_connect ( + ACTION (GAL_SAVE_CUSTOM_VIEW), "activate", + G_CALLBACK (action_gal_save_custom_view_cb), task_shell_view); + + g_signal_connect ( + ACTION (SEARCH_EXECUTE), "activate", + G_CALLBACK (action_search_execute_cb), task_shell_view); +} + +void +e_task_shell_view_update_search_filter (ETaskShellView *task_shell_view) +{ + EShellContent *shell_content; + EShellWindow *shell_window; + EShellView *shell_view; + GtkActionGroup *action_group; + GtkRadioAction *radio_action; + GList *list, *iter; + GSList *group; + gint ii; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + action_group = ACTION_GROUP (TASKS_FILTER); + e_action_group_remove_all_actions (action_group); + + /* Add the standard filter actions. */ + gtk_action_group_add_radio_actions ( + action_group, task_filter_entries, + G_N_ELEMENTS (task_filter_entries), + TASK_FILTER_ANY_CATEGORY, + G_CALLBACK (action_search_filter_cb), + task_shell_view); + + /* Retrieve the radio group from an action we just added. */ + list = gtk_action_group_list_actions (action_group); + radio_action = GTK_RADIO_ACTION (list->data); + group = gtk_radio_action_get_group (radio_action); + g_list_free (list); + + /* Build the category actions. */ + + list = e_categories_get_list (); + for (iter = list, ii = 0; iter != NULL; iter = iter->next, ii++) { + const gchar *category_name = iter->data; + const gchar *filename; + GtkAction *action; + gchar *action_name; + + action_name = g_strdup_printf ( + "task-filter-category-%d", ii); + radio_action = gtk_radio_action_new ( + action_name, category_name, NULL, NULL, ii); + g_free (action_name); + + /* Convert the category icon file to a themed icon name. */ + filename = e_categories_get_icon_file_for (category_name); + if (filename != NULL && *filename != '\0') { + gchar *basename; + gchar *cp; + + basename = g_path_get_basename (filename); + + /* Lose the file extension. */ + if ((cp = strrchr (basename, '.')) != NULL) + *cp = '\0'; + + g_object_set ( + radio_action, "icon-name", basename, NULL); + + g_free (basename); + } + + gtk_radio_action_set_group (radio_action, group); + group = gtk_radio_action_get_group (radio_action); + + /* The action group takes ownership of the action. */ + action = GTK_ACTION (radio_action); + gtk_action_group_add_action (action_group, action); + g_object_unref (radio_action); + } + g_list_free (list); + + /* Use any action in the group; doesn't matter which. */ + e_shell_content_set_filter_action (shell_content, radio_action); + + ii = TASK_FILTER_UNMATCHED; + e_shell_content_add_filter_separator_after (shell_content, ii); + + ii = TASK_FILTER_TASKS_WITH_ATTACHMENTS; + e_shell_content_add_filter_separator_after (shell_content, ii); +} diff --git a/modules/calendar/e-task-shell-view-actions.h b/modules/calendar/e-task-shell-view-actions.h new file mode 100644 index 0000000000..d7db39bcc9 --- /dev/null +++ b/modules/calendar/e-task-shell-view-actions.h @@ -0,0 +1,105 @@ +/* + * e-task-shell-view-actions.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_TASK_SHELL_VIEW_ACTIONS_H +#define E_TASK_SHELL_VIEW_ACTIONS_H + +#include + +/* Task Actions */ +#define E_SHELL_WINDOW_ACTION_TASK_ASSIGN(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-assign") +#define E_SHELL_WINDOW_ACTION_TASK_CLIPBOARD_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-clipboard-copy") +#define E_SHELL_WINDOW_ACTION_TASK_CLIPBOARD_CUT(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-clipboard-cut") +#define E_SHELL_WINDOW_ACTION_TASK_CLIPBOARD_PASTE(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-clipboard-paste") +#define E_SHELL_WINDOW_ACTION_TASK_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-delete") +#define E_SHELL_WINDOW_ACTION_TASK_FORWARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-forward") +#define E_SHELL_WINDOW_ACTION_TASK_MARK_COMPLETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-mark-complete") +#define E_SHELL_WINDOW_ACTION_TASK_MARK_INCOMPLETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-mark-incomplete") +#define E_SHELL_WINDOW_ACTION_TASK_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-new") +#define E_SHELL_WINDOW_ACTION_TASK_OPEN(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-open") +#define E_SHELL_WINDOW_ACTION_TASK_OPEN_URL(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-open-url") +#define E_SHELL_WINDOW_ACTION_TASK_PREVIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-preview") +#define E_SHELL_WINDOW_ACTION_TASK_PRINT(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-print") +#define E_SHELL_WINDOW_ACTION_TASK_PURGE(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-purge") +#define E_SHELL_WINDOW_ACTION_TASK_SAVE_AS(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-save-as") + +/* Task List Actions */ +#define E_SHELL_WINDOW_ACTION_TASK_LIST_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-list-copy") +#define E_SHELL_WINDOW_ACTION_TASK_LIST_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-list-delete") +#define E_SHELL_WINDOW_ACTION_TASK_LIST_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-list-new") +#define E_SHELL_WINDOW_ACTION_TASK_LIST_PRINT(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-list-print") +#define E_SHELL_WINDOW_ACTION_TASK_LIST_PRINT_PREVIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-list-print-preview") +#define E_SHELL_WINDOW_ACTION_TASK_LIST_PROPERTIES(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-list-properties") +#define E_SHELL_WINDOW_ACTION_TASK_LIST_RENAME(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-list-rename") +#define E_SHELL_WINDOW_ACTION_TASK_LIST_SELECT_ONE(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-list-select-one") + +/* Task Query Actions */ +#define E_SHELL_WINDOW_ACTION_TASK_FILTER_ACTIVE_TASKS(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-filter-active-tasks") +#define E_SHELL_WINDOW_ACTION_TASK_FILTER_ANY_CATEGORY(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-filter-any-category") +#define E_SHELL_WINDOW_ACTION_TASK_FILTER_COMPLETED_TASKS(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-filter-completed-tasks") +#define E_SHELL_WINDOW_ACTION_TASK_FILTER_NEXT_7_DAYS_TASKS(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-filter-next-7-days-tasks") +#define E_SHELL_WINDOW_ACTION_TASK_FILTER_OVERDUE_TASKS(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-filter-overdue-tasks") +#define E_SHELL_WINDOW_ACTION_TASK_FILTER_TASKS_WITH_ATTACHMENTS(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-filter-tasks-with-attachments") +#define E_SHELL_WINDOW_ACTION_TASK_FILTER_UNMATCHED(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-filter-unmatched") +#define E_SHELL_WINDOW_ACTION_TASK_SEARCH_ANY_FIELD_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-search-any-field-contains") +#define E_SHELL_WINDOW_ACTION_TASK_SEARCH_DESCRIPTION_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-search-description-contains") +#define E_SHELL_WINDOW_ACTION_TASK_SEARCH_SUMMARY_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-search-summary-contains") + +/* Action Groups */ +#define E_SHELL_WINDOW_ACTION_GROUP_TASKS(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "tasks") +#define E_SHELL_WINDOW_ACTION_GROUP_TASKS_FILTER(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "tasks-filter") + +#endif /* E_TASK_SHELL_VIEW_ACTIONS_H */ diff --git a/modules/calendar/e-task-shell-view-private.c b/modules/calendar/e-task-shell-view-private.c new file mode 100644 index 0000000000..d6fd8e35aa --- /dev/null +++ b/modules/calendar/e-task-shell-view-private.c @@ -0,0 +1,744 @@ +/* + * e-task-shell-view-private.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-task-shell-view-private.h" + +#include "widgets/menus/gal-view-factory-etable.h" + +static void +task_shell_view_config_hide_completed_tasks_changed_cb (GConfClient *client, + guint id, + GConfEntry *entry, + gpointer user_data) +{ + ETaskShellView *task_shell_view = user_data; + ETaskShellContent *task_shell_content; + ETaskShellSidebar *task_shell_sidebar; + ECalendarTable *task_table; + GList *clients; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; + clients = e_task_shell_sidebar_get_clients (task_shell_sidebar); + + e_calendar_table_process_completed_tasks (task_table, clients, TRUE); + + /* Search query takes whether to show completed tasks into account, + * so if the preference has changed we need to update the query. */ + e_task_shell_view_execute_search (task_shell_view); + + g_list_free (clients); +} + +static void +task_shell_view_config_timezone_changed_cb (GConfClient *client, + guint id, + GConfEntry *entry, + gpointer user_data) +{ + ETaskShellView *task_shell_view = user_data; + + e_task_shell_view_update_timezone (task_shell_view); +} + +static void +task_shell_view_table_popup_event_cb (EShellView *shell_view, + GdkEventButton *event) +{ + const gchar *widget_path; + + widget_path = "/task-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); +} + +static void +task_shell_view_table_user_created_cb (ETaskShellView *task_shell_view, + ECalendarTable *task_table) +{ + ETaskShellSidebar *task_shell_sidebar; + ECalModel *model; + ECal *client; + ESource *source; + + /* This is the "Click to Add" handler. */ + + model = e_calendar_table_get_model (task_table); + client = e_cal_model_get_default_client (model); + source = e_cal_get_source (client); + + task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; + e_task_shell_sidebar_add_source (task_shell_sidebar, source); + + e_cal_model_add_client (model, client); +} + +static void +task_shell_view_selector_client_added_cb (ETaskShellView *task_shell_view, + ECal *client) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModel *model; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + model = e_calendar_table_get_model (task_table); + + e_cal_model_add_client (model, client); + e_task_shell_view_update_timezone (task_shell_view); +} + +static void +task_shell_view_selector_client_removed_cb (ETaskShellView *task_shell_view, + ECal *client) +{ + ETaskShellContent *task_shell_content; + ECalendarTable *task_table; + ECalModel *model; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + model = e_calendar_table_get_model (task_table); + + e_cal_model_remove_client (model, client); +} + +static gboolean +task_shell_view_selector_popup_event_cb (EShellView *shell_view, + ESource *primary_source, + GdkEventButton *event) +{ + const gchar *widget_path; + + widget_path = "/task-list-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); + + return TRUE; +} + +static gboolean +task_shell_view_update_timeout_cb (ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ETaskShellSidebar *task_shell_sidebar; + ECalendarTable *task_table; + ECalModel *model; + GList *clients; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + model = e_calendar_table_get_model (task_table); + + task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; + clients = e_task_shell_sidebar_get_clients (task_shell_sidebar); + + e_calendar_table_process_completed_tasks (task_table, clients, FALSE); + e_cal_model_tasks_update_due_tasks (E_CAL_MODEL_TASKS (model)); + + g_list_free (clients); + + return TRUE; +} + +static void +task_shell_view_load_view_collection (EShellViewClass *shell_view_class) +{ + GalViewCollection *collection; + GalViewFactory *factory; + ETableSpecification *spec; + const gchar *base_dir; + gchar *filename; + + collection = shell_view_class->view_collection; + + base_dir = EVOLUTION_ETSPECDIR; + spec = e_table_specification_new (); + filename = g_build_filename (base_dir, ETSPEC_FILENAME, NULL); + if (!e_table_specification_load_from_file (spec, filename)) + g_critical ("Unable to load ETable specification file " + "for tasks"); + g_free (filename); + + factory = gal_view_factory_etable_new (spec); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + g_object_unref (spec); + + gal_view_collection_load (collection); +} + +static void +task_shell_view_notify_view_id_cb (ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + GalViewInstance *view_instance; + const gchar *view_id; + + task_shell_content = task_shell_view->priv->task_shell_content; + view_instance = + e_task_shell_content_get_view_instance (task_shell_content); + view_id = e_shell_view_get_view_id (E_SHELL_VIEW (task_shell_view)); + + /* A NULL view ID implies we're in a custom view. But you can + * only get to a custom view via the "Define Views" dialog, which + * would have already modified the view instance appropriately. + * Furthermore, there's no way to refer to a custom view by ID + * anyway, since custom views have no IDs. */ + if (view_id == NULL) + return; + + gal_view_instance_set_current_view_id (view_instance, view_id); +} + +void +e_task_shell_view_private_init (ETaskShellView *task_shell_view, + EShellViewClass *shell_view_class) +{ + if (!gal_view_collection_loaded (shell_view_class->view_collection)) + task_shell_view_load_view_collection (shell_view_class); + + g_signal_connect ( + task_shell_view, "notify::view-id", + G_CALLBACK (task_shell_view_notify_view_id_cb), NULL); +} + +void +e_task_shell_view_private_constructed (ETaskShellView *task_shell_view) +{ + ETaskShellViewPrivate *priv = task_shell_view->priv; + ETaskShellContent *task_shell_content; + ETaskShellSidebar *task_shell_sidebar; + EShellView *shell_view; + EShellBackend *shell_backend; + EShellContent *shell_content; + EShellSidebar *shell_sidebar; + EShellWindow *shell_window; + ECalendarTable *task_table; + ECalModel *model; + ETable *table; + ESourceSelector *selector; + guint id; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + e_shell_window_add_action_group (shell_window, "tasks"); + e_shell_window_add_action_group (shell_window, "tasks-filter"); + + /* Cache these to avoid lots of awkward casting. */ + priv->task_shell_backend = g_object_ref (shell_backend); + priv->task_shell_content = g_object_ref (shell_content); + priv->task_shell_sidebar = g_object_ref (shell_sidebar); + + task_shell_content = E_TASK_SHELL_CONTENT (shell_content); + task_table = e_task_shell_content_get_task_table (task_shell_content); + model = e_calendar_table_get_model (task_table); + table = e_calendar_table_get_table (task_table); + + task_shell_sidebar = E_TASK_SHELL_SIDEBAR (shell_sidebar); + selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + + g_signal_connect_swapped ( + task_table, "open-component", + G_CALLBACK (e_task_shell_view_open_task), + task_shell_view); + + g_signal_connect_swapped ( + task_table, "popup-event", + G_CALLBACK (task_shell_view_table_popup_event_cb), + task_shell_view); + + g_signal_connect_swapped ( + task_table, "status-message", + G_CALLBACK (e_task_shell_view_set_status_message), + task_shell_view); + + g_signal_connect_swapped ( + task_table, "user-created", + G_CALLBACK (task_shell_view_table_user_created_cb), + task_shell_view); + + g_signal_connect_swapped ( + model, "model-changed", + G_CALLBACK (e_task_shell_view_update_sidebar), + task_shell_view); + + g_signal_connect_swapped ( + model, "model-rows-deleted", + G_CALLBACK (e_task_shell_view_update_sidebar), + task_shell_view); + + g_signal_connect_swapped ( + model, "model-rows-inserted", + G_CALLBACK (e_task_shell_view_update_sidebar), + task_shell_view); + + g_signal_connect_swapped ( + table, "selection-change", + G_CALLBACK (e_task_shell_view_update_sidebar), + task_shell_view); + + g_signal_connect_swapped ( + task_shell_sidebar, "client-added", + G_CALLBACK (task_shell_view_selector_client_added_cb), + task_shell_view); + + g_signal_connect_swapped ( + task_shell_sidebar, "client-removed", + G_CALLBACK (task_shell_view_selector_client_removed_cb), + task_shell_view); + + g_signal_connect_swapped ( + task_shell_sidebar, "status-message", + G_CALLBACK (e_task_shell_view_set_status_message), + task_shell_view); + + g_signal_connect_swapped ( + selector, "popup-event", + G_CALLBACK (task_shell_view_selector_popup_event_cb), + task_shell_view); + + g_signal_connect_swapped ( + selector, "primary-selection-changed", + G_CALLBACK (e_shell_view_update_actions), + task_shell_view); + + e_categories_register_change_listener ( + G_CALLBACK (e_task_shell_view_update_search_filter), + task_shell_view); + + task_shell_view_update_timeout_cb (task_shell_view); + priv->update_timeout = g_timeout_add_full ( + G_PRIORITY_LOW, 60000, (GSourceFunc) + task_shell_view_update_timeout_cb, + task_shell_view, NULL); + + /* Listen for configuration changes. */ + + /* Timezone */ + id = calendar_config_add_notification_timezone ( + task_shell_view_config_timezone_changed_cb, task_shell_view); + priv->notifications = g_list_prepend ( + priv->notifications, GUINT_TO_POINTER (id)); + + /* Hide Completed Tasks (enable/units/value) */ + id = calendar_config_add_notification_hide_completed_tasks ( + task_shell_view_config_hide_completed_tasks_changed_cb, + task_shell_view); + priv->notifications = g_list_prepend ( + priv->notifications, GUINT_TO_POINTER (id)); + id = calendar_config_add_notification_hide_completed_tasks_units ( + task_shell_view_config_hide_completed_tasks_changed_cb, + task_shell_view); + priv->notifications = g_list_prepend ( + priv->notifications, GUINT_TO_POINTER (id)); + id = calendar_config_add_notification_hide_completed_tasks_value ( + task_shell_view_config_hide_completed_tasks_changed_cb, + task_shell_view); + priv->notifications = g_list_prepend ( + priv->notifications, GUINT_TO_POINTER (id)); + + e_task_shell_view_actions_init (task_shell_view); + e_task_shell_view_update_sidebar (task_shell_view); + e_task_shell_view_update_search_filter (task_shell_view); + e_task_shell_view_update_timezone (task_shell_view); + + e_task_shell_view_execute_search (task_shell_view); +} + +void +e_task_shell_view_private_dispose (ETaskShellView *task_shell_view) +{ + ETaskShellViewPrivate *priv = task_shell_view->priv; + GList *iter; + + DISPOSE (priv->task_shell_backend); + DISPOSE (priv->task_shell_content); + DISPOSE (priv->task_shell_sidebar); + + if (task_shell_view->priv->activity != NULL) { + /* XXX Activity is no cancellable. */ + e_activity_complete (task_shell_view->priv->activity); + g_object_unref (task_shell_view->priv->activity); + task_shell_view->priv->activity = NULL; + } + + if (priv->update_timeout > 0) { + g_source_remove (priv->update_timeout); + priv->update_timeout = 0; + } + + for (iter = priv->notifications; iter != NULL; iter = iter->next) { + guint notification_id = GPOINTER_TO_UINT (iter->data); + calendar_config_remove_notification (notification_id); + } + g_list_free (priv->notifications); + priv->notifications = NULL; +} + +void +e_task_shell_view_private_finalize (ETaskShellView *task_shell_view) +{ + /* XXX Nothing to do? */ +} + +void +e_task_shell_view_execute_search (ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + EShellView *shell_view; + EShellWindow *shell_window; + EShellContent *shell_content; + GtkAction *action; + GString *string; + ECalComponentPreview *task_preview; + ECalendarTable *task_table; + ECalModel *model; + FilterRule *rule; + const gchar *format; + const gchar *text; + time_t start_range; + time_t end_range; + gchar *start, *end; + gchar *query; + gchar *temp; + gint value; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + text = e_shell_content_get_search_text (shell_content); + + shell_window = e_shell_view_get_shell_window (shell_view); + action = ACTION (TASK_SEARCH_ANY_FIELD_CONTAINS); + value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + + if (text == NULL || *text == '\0') { + text = ""; + value = TASK_SEARCH_SUMMARY_CONTAINS; + } + + switch (value) { + default: + text = ""; + /* fall through */ + + case TASK_SEARCH_SUMMARY_CONTAINS: + format = "(contains? \"summary\" %s)"; + break; + + case TASK_SEARCH_DESCRIPTION_CONTAINS: + format = "(contains? \"description\" %s)"; + break; + + case TASK_SEARCH_ANY_FIELD_CONTAINS: + format = "(contains? \"any\" %s)"; + break; + } + + /* Build the query. */ + string = g_string_new (""); + e_sexp_encode_string (string, text); + query = g_strdup_printf (format, string->str); + g_string_free (string, TRUE); + + /* Apply selected filter. */ + value = e_shell_content_get_filter_value (shell_content); + switch (value) { + case TASK_FILTER_ANY_CATEGORY: + break; + + case TASK_FILTER_UNMATCHED: + temp = g_strdup_printf ( + "(and (has-categories? #f) %s)", query); + g_free (query); + query = temp; + break; + + case TASK_FILTER_NEXT_7_DAYS_TASKS: + start_range = time (NULL); + end_range = time_add_day (start_range, 7); + start = isodate_from_time_t (start_range); + end = isodate_from_time_t (end_range); + + temp = g_strdup_printf ( + "(and %s (due-in-time-range? " + "(make-time \"%s\") (make-time \"%s\")))", + query, start, end); + g_free (query); + query = temp; + break; + + case TASK_FILTER_ACTIVE_TASKS: + start_range = time (NULL); + end_range = time_add_day (start_range, 365); + start = isodate_from_time_t (start_range); + end = isodate_from_time_t (end_range); + + temp = g_strdup_printf ( + "(and %s (due-in-time-range? " + "(make-time \"%s\") (make-time \"%s\")) " + "(not (is-completed?)))", + query, start, end); + g_free (query); + query = temp; + break; + + case TASK_FILTER_OVERDUE_TASKS: + start_range = 0; + end_range = time (NULL); + start = isodate_from_time_t (start_range); + end = isodate_from_time_t (end_range); + + temp = g_strdup_printf ( + "(and %s (due-in-time-range? " + "(make-time \"%s\") (make-time \"%s\")) " + "(not (is-completed?)))", + query, start, end); + g_free (query); + query = temp; + break; + + case TASK_FILTER_COMPLETED_TASKS: + temp = g_strdup_printf ( + "(and (is-completed?) %s)", query); + g_free (query); + query = temp; + break; + + case TASK_FILTER_TASKS_WITH_ATTACHMENTS: + temp = g_strdup_printf ( + "(and (has-attachments?) %s)", query); + g_free (query); + query = temp; + break; + + default: + { + GList *categories; + const gchar *category_name; + + categories = e_categories_get_list (); + category_name = g_list_nth_data (categories, value); + g_list_free (categories); + + temp = g_strdup_printf ( + "(and (has-categories? \"%s\") %s)", + category_name, query); + g_free (query); + query = temp; + break; + } + } + + /* Honor the user's preference to hide completed tasks. */ + temp = calendar_config_get_hide_completed_tasks_sexp (FALSE); + if (temp != NULL) { + gchar *temp2; + + temp2 = g_strdup_printf ("(and %s %s)", temp, query); + g_free (query); + g_free (temp); + query = temp2; + } + + /* XXX This is wrong. We need to programmatically construct a + * FilterRule, tell it to build code, and pass the resulting + * expression string to ECalModel. */ + rule = filter_rule_new (); + e_shell_content_set_search_rule (shell_content, rule); + g_object_unref (rule); + + /* Submit the query. */ + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + model = e_calendar_table_get_model (task_table); + e_cal_model_set_search_query (model, query); + g_free (query); + + task_preview = + e_task_shell_content_get_task_preview (task_shell_content); + e_cal_component_preview_clear (task_preview); +} + +void +e_task_shell_view_open_task (ETaskShellView *task_shell_view, + ECalModelComponent *comp_data) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + CompEditor *editor; + CompEditorFlags flags = 0; + ECalComponent *comp; + icalcomponent *clone; + icalproperty *prop; + const gchar *uid; + + g_return_if_fail (E_IS_TASK_SHELL_VIEW (task_shell_view)); + g_return_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data)); + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + + uid = icalcomponent_get_uid (comp_data->icalcomp); + editor = comp_editor_find_instance (uid); + + if (editor != NULL) + goto exit; + + comp = e_cal_component_new (); + clone = icalcomponent_new_clone (comp_data->icalcomp); + e_cal_component_set_icalcomponent (comp, clone); + + prop = icalcomponent_get_first_property ( + comp_data->icalcomp, ICAL_ATTENDEE_PROPERTY); + if (prop != NULL) + flags |= COMP_EDITOR_IS_ASSIGNED; + + if (itip_organizer_is_user (comp, comp_data->client)) + flags |= COMP_EDITOR_USER_ORG; + + if (!e_cal_component_has_attendees (comp)) + flags |= COMP_EDITOR_USER_ORG; + + editor = task_editor_new (comp_data->client, shell, flags); + comp_editor_edit_comp (editor, comp); + + g_object_ref (comp); + + if (flags & COMP_EDITOR_IS_ASSIGNED) + task_editor_show_assignment (TASK_EDITOR (editor)); + +exit: + gtk_window_present (GTK_WINDOW (editor)); +} + +void +e_task_shell_view_set_status_message (ETaskShellView *task_shell_view, + const gchar *status_message, + gdouble percent) +{ + EActivity *activity; + EShellView *shell_view; + EShellBackend *shell_backend; + + g_return_if_fail (E_IS_TASK_SHELL_VIEW (task_shell_view)); + + activity = task_shell_view->priv->activity; + shell_view = E_SHELL_VIEW (task_shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + if (status_message == NULL || *status_message == '\0') { + if (activity != NULL) { + e_activity_complete (activity); + g_object_unref (activity); + activity = NULL; + } + + } else if (activity == NULL) { + activity = e_activity_new (status_message); + e_activity_set_percent (activity, percent); + e_shell_backend_add_activity (shell_backend, activity); + + } else { + e_activity_set_percent (activity, percent); + e_activity_set_primary_text (activity, status_message); + } + + task_shell_view->priv->activity = activity; +} + +void +e_task_shell_view_update_sidebar (ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + EShellView *shell_view; + EShellSidebar *shell_sidebar; + ECalendarTable *task_table; + ECalModel *model; + ETable *table; + GString *string; + const gchar *format; + gint n_rows; + gint n_selected; + + shell_view = E_SHELL_VIEW (task_shell_view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + + task_shell_content = task_shell_view->priv->task_shell_content; + task_table = e_task_shell_content_get_task_table (task_shell_content); + + model = e_calendar_table_get_model (task_table); + table = e_calendar_table_get_table (task_table); + + n_rows = e_table_model_row_count (E_TABLE_MODEL (model)); + n_selected = e_table_selected_count (table); + + string = g_string_sized_new (64); + + format = ngettext ("%d task", "%d tasks", n_rows); + g_string_append_printf (string, format, n_rows); + + if (n_selected > 0) { + format = _("%d selected"); + g_string_append_len (string, ", ", 2); + g_string_append_printf (string, format, n_selected); + } + + e_shell_sidebar_set_secondary_text (shell_sidebar, string->str); + + g_string_free (string, TRUE); +} + +void +e_task_shell_view_update_timezone (ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + ETaskShellSidebar *task_shell_sidebar; + ECalComponentPreview *task_preview; + icaltimezone *timezone; + GList *clients, *iter; + + task_shell_content = task_shell_view->priv->task_shell_content; + task_preview = e_task_shell_content_get_task_preview (task_shell_content); + + task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; + clients = e_task_shell_sidebar_get_clients (task_shell_sidebar); + + timezone = calendar_config_get_icaltimezone (); + + for (iter = clients; iter != NULL; iter = iter->next) { + ECal *client = iter->data; + + if (e_cal_get_load_state (client) == E_CAL_LOAD_LOADED) + e_cal_set_default_timezone (client, timezone, NULL); + } + + e_cal_component_preview_set_default_timezone (task_preview, timezone); + + g_list_free (clients); +} diff --git a/modules/calendar/e-task-shell-view-private.h b/modules/calendar/e-task-shell-view-private.h new file mode 100644 index 0000000000..d3bb3cf086 --- /dev/null +++ b/modules/calendar/e-task-shell-view-private.h @@ -0,0 +1,141 @@ +/* + * e-task-shell-view-private.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_TASK_SHELL_VIEW_PRIVATE_H +#define E_TASK_SHELL_VIEW_PRIVATE_H + +#include "e-task-shell-view.h" + +#include +#include +#include +#include +#include + +#include "e-util/e-dialog-utils.h" +#include "e-util/e-error.h" +#include "e-util/e-util.h" +#include "e-util/gconf-bridge.h" +#include "widgets/misc/e-popup-action.h" + +#include "calendar/common/authentication.h" +#include "calendar/gui/calendar-config.h" +#include "calendar/gui/comp-util.h" +#include "calendar/gui/e-cal-component-preview.h" +#include "calendar/gui/e-cal-model-tasks.h" +#include "calendar/gui/e-calendar-selector.h" +#include "calendar/gui/print.h" +#include "calendar/gui/dialogs/calendar-setup.h" +#include "calendar/gui/dialogs/copy-source-dialog.h" +#include "calendar/gui/dialogs/task-editor.h" + +#include "e-task-shell-backend.h" +#include "e-task-shell-content.h" +#include "e-task-shell-sidebar.h" +#include "e-task-shell-view-actions.h" + +#define E_TASK_SHELL_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_TASK_SHELL_VIEW, ETaskShellViewPrivate)) + +/* Shorthand, requires a variable named "shell_window". */ +#define ACTION(name) \ + (E_SHELL_WINDOW_ACTION_##name (shell_window)) +#define ACTION_GROUP(name) \ + (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) + +/* For use in dispose() methods. */ +#define DISPOSE(obj) \ + G_STMT_START { \ + if ((obj) != NULL) { g_object_unref (obj); (obj) = NULL; } \ + } G_STMT_END + +/* ETable Specifications */ +#define ETSPEC_FILENAME "e-calendar-table.etspec" + +G_BEGIN_DECLS + +/* Filter items are displayed in ascending order. + * Non-negative values are reserved for categories. */ +enum { + TASK_FILTER_ANY_CATEGORY = -7, + TASK_FILTER_UNMATCHED = -6, + TASK_FILTER_NEXT_7_DAYS_TASKS = -5, + TASK_FILTER_ACTIVE_TASKS = -4, + TASK_FILTER_OVERDUE_TASKS = -3, + TASK_FILTER_COMPLETED_TASKS = -2, + TASK_FILTER_TASKS_WITH_ATTACHMENTS = -1 +}; + +/* Search items are displayed in ascending order. */ +enum { + TASK_SEARCH_SUMMARY_CONTAINS, + TASK_SEARCH_DESCRIPTION_CONTAINS, + TASK_SEARCH_ANY_FIELD_CONTAINS +}; + +struct _ETaskShellViewPrivate { + + /* These are just for convenience. */ + ETaskShellBackend *task_shell_backend; + ETaskShellContent *task_shell_content; + ETaskShellSidebar *task_shell_sidebar; + + EActivity *activity; + guint update_timeout; + + /* GConf notification IDs */ + GList *notifications; +}; + +void e_task_shell_view_private_init + (ETaskShellView *task_shell_view, + EShellViewClass *shell_view_class); +void e_task_shell_view_private_constructed + (ETaskShellView *task_shell_view); +void e_task_shell_view_private_dispose + (ETaskShellView *task_shell_view); +void e_task_shell_view_private_finalize + (ETaskShellView *task_shell_view); + +/* Private Utilities */ + +void e_task_shell_view_actions_init + (ETaskShellView *task_shell_view); +void e_task_shell_view_execute_search + (ETaskShellView *task_shell_view); +void e_task_shell_view_open_task + (ETaskShellView *task_shell_view, + ECalModelComponent *comp_data); +void e_task_shell_view_set_status_message + (ETaskShellView *task_shell_view, + const gchar *status_message, + gdouble percent); +void e_task_shell_view_update_sidebar + (ETaskShellView *task_shell_view); +void e_task_shell_view_update_search_filter + (ETaskShellView *task_shell_view); +void e_task_shell_view_update_timezone + (ETaskShellView *task_shell_view); + +G_END_DECLS + +#endif /* E_TASK_SHELL_VIEW_PRIVATE_H */ diff --git a/modules/calendar/e-task-shell-view.c b/modules/calendar/e-task-shell-view.c new file mode 100644 index 0000000000..ce1b53a43c --- /dev/null +++ b/modules/calendar/e-task-shell-view.c @@ -0,0 +1,255 @@ +/* + * e-task-shell-view.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-task-shell-view-private.h" + +static gpointer parent_class; +static GType task_shell_view_type; + +static void +task_shell_view_dispose (GObject *object) +{ + e_task_shell_view_private_dispose (E_TASK_SHELL_VIEW (object)); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +task_shell_view_finalize (GObject *object) +{ + e_task_shell_view_private_finalize (E_TASK_SHELL_VIEW (object)); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +task_shell_view_constructed (GObject *object) +{ + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + e_task_shell_view_private_constructed (E_TASK_SHELL_VIEW (object)); +} + +static void +task_shell_view_update_actions (EShellView *shell_view) +{ + ETaskShellViewPrivate *priv; + EShellContent *shell_content; + EShellSidebar *shell_sidebar; + EShellWindow *shell_window; + GtkAction *action; + const gchar *label; + gboolean sensitive; + guint32 state; + + /* Be descriptive. */ + gboolean any_tasks_selected; + gboolean has_primary_source; + gboolean multiple_tasks_selected; + gboolean primary_source_is_system; + gboolean selection_has_url; + gboolean selection_is_assignable; + gboolean single_task_selected; + gboolean some_tasks_complete; + gboolean some_tasks_incomplete; + gboolean sources_are_editable; + + priv = E_TASK_SHELL_VIEW_GET_PRIVATE (shell_view); + + shell_window = e_shell_view_get_shell_window (shell_view); + + shell_content = e_shell_view_get_shell_content (shell_view); + state = e_shell_content_check_state (shell_content); + + single_task_selected = + (state & E_TASK_SHELL_CONTENT_SELECTION_SINGLE); + multiple_tasks_selected = + (state & E_TASK_SHELL_CONTENT_SELECTION_MULTIPLE); + selection_is_assignable = + (state & E_TASK_SHELL_CONTENT_SELECTION_CAN_ASSIGN); + sources_are_editable = + (state & E_TASK_SHELL_CONTENT_SELECTION_CAN_EDIT); + some_tasks_complete = + (state & E_TASK_SHELL_CONTENT_SELECTION_HAS_COMPLETE); + some_tasks_incomplete = + (state & E_TASK_SHELL_CONTENT_SELECTION_HAS_INCOMPLETE); + selection_has_url = + (state & E_TASK_SHELL_CONTENT_SELECTION_HAS_URL); + + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + state = e_shell_sidebar_check_state (shell_sidebar); + + has_primary_source = + (state & E_TASK_SHELL_SIDEBAR_HAS_PRIMARY_SOURCE); + primary_source_is_system = + (state & E_TASK_SHELL_SIDEBAR_PRIMARY_SOURCE_IS_SYSTEM); + + any_tasks_selected = + (single_task_selected || multiple_tasks_selected); + + action = ACTION (TASK_ASSIGN); + sensitive = + single_task_selected && sources_are_editable && + selection_is_assignable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_CLIPBOARD_COPY); + sensitive = any_tasks_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_CLIPBOARD_CUT); + sensitive = any_tasks_selected && sources_are_editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_CLIPBOARD_PASTE); + sensitive = sources_are_editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_DELETE); + sensitive = any_tasks_selected && sources_are_editable; + gtk_action_set_sensitive (action, sensitive); + if (multiple_tasks_selected) + label = _("Delete Tasks"); + else + label = _("Delete Task"); + g_object_set (action, "label", label, NULL); + + action = ACTION (TASK_FORWARD); + sensitive = single_task_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_LIST_COPY); + sensitive = has_primary_source; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_LIST_DELETE); + sensitive = has_primary_source && !primary_source_is_system; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_LIST_PROPERTIES); + sensitive = has_primary_source; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_LIST_RENAME); + sensitive = has_primary_source; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_MARK_COMPLETE); + sensitive = + any_tasks_selected && + sources_are_editable && + some_tasks_incomplete; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_MARK_INCOMPLETE); + sensitive = + any_tasks_selected && + sources_are_editable && + some_tasks_complete; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_OPEN); + sensitive = single_task_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_OPEN_URL); + sensitive = single_task_selected && selection_has_url; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_PRINT); + sensitive = single_task_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_PURGE); + sensitive = sources_are_editable; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (TASK_SAVE_AS); + sensitive = single_task_selected; + gtk_action_set_sensitive (action, sensitive); +} + +static void +task_shell_view_class_init (ETaskShellViewClass *class, + GTypeModule *type_module) +{ + GObjectClass *object_class; + EShellViewClass *shell_view_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ETaskShellViewPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->dispose = task_shell_view_dispose; + object_class->finalize = task_shell_view_finalize; + object_class->constructed = task_shell_view_constructed; + + shell_view_class = E_SHELL_VIEW_CLASS (class); + shell_view_class->label = _("Tasks"); + shell_view_class->icon_name = "evolution-tasks"; + shell_view_class->ui_definition = "evolution-tasks.ui"; + shell_view_class->ui_manager_id = "org.gnome.evolution.tasks"; + shell_view_class->search_options = "/task-search-options"; + shell_view_class->search_rules = "tasktypes.xml"; + shell_view_class->new_shell_content = e_task_shell_content_new; + shell_view_class->new_shell_sidebar = e_task_shell_sidebar_new; + shell_view_class->update_actions = task_shell_view_update_actions; +} + +static void +task_shell_view_init (ETaskShellView *task_shell_view, + EShellViewClass *shell_view_class) +{ + task_shell_view->priv = + E_TASK_SHELL_VIEW_GET_PRIVATE (task_shell_view); + + e_task_shell_view_private_init (task_shell_view, shell_view_class); +} + +GType +e_task_shell_view_get_type (void) +{ + return task_shell_view_type; +} + +void +e_task_shell_view_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (ETaskShellViewClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) task_shell_view_class_init, + (GClassFinalizeFunc) NULL, + type_module, + sizeof (ETaskShellView), + 0, /* n_preallocs */ + (GInstanceInitFunc) task_shell_view_init, + NULL /* value_table */ + }; + + task_shell_view_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_VIEW, + "ETaskShellView", &type_info, 0); +} diff --git a/modules/calendar/e-task-shell-view.h b/modules/calendar/e-task-shell-view.h new file mode 100644 index 0000000000..8478e53cc2 --- /dev/null +++ b/modules/calendar/e-task-shell-view.h @@ -0,0 +1,67 @@ +/* + * e-task-shell-view.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_TASK_SHELL_VIEW_H +#define E_TASK_SHELL_VIEW_H + +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_TASK_SHELL_VIEW \ + (e_task_shell_view_get_type ()) +#define E_TASK_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_TASK_SHELL_VIEW, ETaskShellView)) +#define E_TASK_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_TASK_SHELL_VIEW, ETaskShellViewClass)) +#define E_IS_TASK_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_TASK_SHELL_VIEW)) +#define E_IS_TASK_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_TASK_SHELL_VIEW)) +#define E_TASK_SHELL_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_TASK_SHELL_VIEW, ETaskShellViewClass)) + +G_BEGIN_DECLS + +typedef struct _ETaskShellView ETaskShellView; +typedef struct _ETaskShellViewClass ETaskShellViewClass; +typedef struct _ETaskShellViewPrivate ETaskShellViewPrivate; + +struct _ETaskShellView { + EShellView parent; + ETaskShellViewPrivate *priv; +}; + +struct _ETaskShellViewClass { + EShellViewClass parent_class; +}; + +GType e_task_shell_view_get_type (void); +void e_task_shell_view_register_type (GTypeModule *type_module); + +G_END_DECLS + +#endif /* E_TASK_SHELL_VIEW_H */ diff --git a/modules/calendar/evolution-module-calendar.c b/modules/calendar/evolution-module-calendar.c new file mode 100644 index 0000000000..63bf98ead9 --- /dev/null +++ b/modules/calendar/evolution-module-calendar.c @@ -0,0 +1,65 @@ +/* + * evolution-module-calendar.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-shell-backend.h" +#include "e-cal-shell-content.h" +#include "e-cal-shell-sidebar.h" +#include "e-cal-shell-view.h" + +#include "e-memo-shell-backend.h" +#include "e-memo-shell-content.h" +#include "e-memo-shell-sidebar.h" +#include "e-memo-shell-view.h" + +#include "e-task-shell-backend.h" +#include "e-task-shell-content.h" +#include "e-task-shell-sidebar.h" +#include "e-task-shell-view.h" + +/* Module Entry Points */ +void e_module_load (GTypeModule *type_module); +void e_module_unload (GTypeModule *type_module); + +G_MODULE_EXPORT void +e_module_load (GTypeModule *type_module) +{ + /* Register dynamically loaded types. */ + + e_cal_shell_backend_register_type (type_module); + e_cal_shell_content_register_type (type_module); + e_cal_shell_sidebar_register_type (type_module); + e_cal_shell_view_register_type (type_module); + + e_memo_shell_backend_register_type (type_module); + e_memo_shell_content_register_type (type_module); + e_memo_shell_sidebar_register_type (type_module); + e_memo_shell_view_register_type (type_module); + + e_task_shell_backend_register_type (type_module); + e_task_shell_content_register_type (type_module); + e_task_shell_sidebar_register_type (type_module); + e_task_shell_view_register_type (type_module); +} + +G_MODULE_EXPORT void +e_module_unload (GTypeModule *type_module) +{ +} -- cgit v1.2.3 From bfc5ba2511dc5fd9f5aa9868946c8860afad81bf Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Tue, 30 Jun 2009 18:34:08 -0400 Subject: Fix "make distcheck" errors and other build cleanups. --- modules/calendar/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules/calendar') diff --git a/modules/calendar/Makefile.am b/modules/calendar/Makefile.am index 9c2d41dc38..fa63bf53e4 100644 --- a/modules/calendar/Makefile.am +++ b/modules/calendar/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = \ +AM_CPPFLAGS = \ -DG_LOG_DOMAIN=\"calendar-modules\" \ -I$(top_srcdir) \ -I$(top_srcdir)/widgets \ -- cgit v1.2.3 From 10eab2350036e1c36377c93d31472125b3e7c8c7 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Fri, 10 Jul 2009 18:36:49 -0400 Subject: Implement the shutdown protocol and stub in session management. The shutdown protocol is modelled after online/offline preparation. Session management code is copied from libegg. Not yet used. --- modules/calendar/e-cal-shell-backend.c | 2 -- modules/calendar/e-memo-shell-backend.c | 2 -- modules/calendar/e-task-shell-backend.c | 2 -- 3 files changed, 6 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-backend.c b/modules/calendar/e-cal-shell-backend.c index 675a3d4fa6..a914ae9e9e 100644 --- a/modules/calendar/e-cal-shell-backend.c +++ b/modules/calendar/e-cal-shell-backend.c @@ -607,8 +607,6 @@ cal_shell_backend_class_init (ECalShellBackendClass *class) shell_backend_class->schemes = "calendar"; shell_backend_class->sort_order = 400; shell_backend_class->start = NULL; - shell_backend_class->is_busy = NULL; - shell_backend_class->shutdown = NULL; shell_backend_class->migrate = e_cal_shell_backend_migrate; g_object_class_install_property ( diff --git a/modules/calendar/e-memo-shell-backend.c b/modules/calendar/e-memo-shell-backend.c index d2734e066a..dc072e3062 100644 --- a/modules/calendar/e-memo-shell-backend.c +++ b/modules/calendar/e-memo-shell-backend.c @@ -554,8 +554,6 @@ memo_shell_backend_class_init (EMemoShellBackendClass *class) shell_backend_class->schemes = "memo"; shell_backend_class->sort_order = 500; shell_backend_class->start = NULL; - shell_backend_class->is_busy = NULL; - shell_backend_class->shutdown = NULL; shell_backend_class->migrate = e_memo_shell_backend_migrate; g_object_class_install_property ( diff --git a/modules/calendar/e-task-shell-backend.c b/modules/calendar/e-task-shell-backend.c index 6bded3e412..b9280c7373 100644 --- a/modules/calendar/e-task-shell-backend.c +++ b/modules/calendar/e-task-shell-backend.c @@ -562,8 +562,6 @@ task_shell_backend_class_init (ETaskShellBackendClass *class) shell_backend_class->schemes = "task"; shell_backend_class->sort_order = 600; shell_backend_class->start = NULL; - shell_backend_class->is_busy = NULL; - shell_backend_class->shutdown = NULL; shell_backend_class->migrate = e_task_shell_backend_migrate; g_object_class_install_property ( -- cgit v1.2.3 From 374bd42f69aca2e132fd854c9619f3d7491f1f96 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Sun, 12 Jul 2009 23:33:07 -0400 Subject: Fix excessive whitespace. --- modules/calendar/e-cal-shell-migrate.c | 1 - modules/calendar/e-memo-shell-migrate.c | 1 - modules/calendar/e-task-shell-migrate.c | 1 - 3 files changed, 3 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-migrate.c b/modules/calendar/e-cal-shell-migrate.c index 9887a5332c..9f611f9944 100644 --- a/modules/calendar/e-cal-shell-migrate.c +++ b/modules/calendar/e-cal-shell-migrate.c @@ -231,7 +231,6 @@ get_source_name (ESourceGroup *group, const gchar *path) conflict = check_for_conflict (group, s->str); - /* if there was a conflict back up 2 levels (skipping the /subfolder/ element) */ if (conflict) starting_index -= 2; diff --git a/modules/calendar/e-memo-shell-migrate.c b/modules/calendar/e-memo-shell-migrate.c index d2e7df6d1b..20b9fea43e 100644 --- a/modules/calendar/e-memo-shell-migrate.c +++ b/modules/calendar/e-memo-shell-migrate.c @@ -153,7 +153,6 @@ add_gw_esource (ESourceList *source_list, const gchar *group_name, const gchar const gchar *poa_address; const gchar *offline_sync; - poa_address = url->host; if (!poa_address || strlen (poa_address) ==0) return; diff --git a/modules/calendar/e-task-shell-migrate.c b/modules/calendar/e-task-shell-migrate.c index ced54bafdf..2e7928fd14 100644 --- a/modules/calendar/e-task-shell-migrate.c +++ b/modules/calendar/e-task-shell-migrate.c @@ -197,7 +197,6 @@ get_source_name (ESourceGroup *group, const gchar *path) conflict = check_for_conflict (group, s->str); - /* if there was a conflict back up 2 levels (skipping the /subfolder/ element) */ if (conflict) starting_index -= 2; -- cgit v1.2.3 From c9e803d8e6d16134cb7feccd5686cff00e171b2b Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Thu, 23 Jul 2009 15:07:20 -0400 Subject: Some minor fixes before I dive into calendar again. --- modules/calendar/e-cal-shell-backend.c | 88 +++++++++++++++++++++++++++------- 1 file changed, 72 insertions(+), 16 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-backend.c b/modules/calendar/e-cal-shell-backend.c index a914ae9e9e..145bff6db5 100644 --- a/modules/calendar/e-cal-shell-backend.c +++ b/modules/calendar/e-cal-shell-backend.c @@ -326,35 +326,76 @@ cal_shell_backend_ensure_sources (EShellBackend *shell_backend) } static void -cal_shell_backend_cal_opened_cb (ECal *cal, +cal_shell_backend_event_new_cb (ECal *cal, ECalendarStatus status, - GtkAction *action) + EShell *shell) { - EShell *shell; ECalComponent *comp; CompEditor *editor; CompEditorFlags flags = 0; - const gchar *action_name; - gboolean all_day; - - /* FIXME Pass this in. */ - shell = e_shell_get_default (); /* XXX Handle errors better. */ if (status != E_CALENDAR_STATUS_OK) return; - action_name = gtk_action_get_name (action); + flags |= COMP_EDITOR_NEW_ITEM; + flags |= COMP_EDITOR_USER_ORG; + + editor = event_editor_new (cal, shell, flags); + comp = cal_comp_event_new_with_current_time (cal, FALSE); + comp_editor_edit_comp (editor, comp); + + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (comp); + g_object_unref (cal); +} + +static void +cal_shell_backend_event_all_day_new_cb (ECal *cal, + ECalendarStatus status, + EShell *shell) +{ + ECalComponent *comp; + CompEditor *editor; + CompEditorFlags flags = 0; + + /* XXX Handle errors better. */ + if (status != E_CALENDAR_STATUS_OK) + return; flags |= COMP_EDITOR_NEW_ITEM; flags |= COMP_EDITOR_USER_ORG; - if (strcmp (action_name, "event-meeting-new") == 0) - flags |= COMP_EDITOR_MEETING; - all_day = (strcmp (action_name, "event-all-day-new") == 0); + editor = event_editor_new (cal, shell, flags); + comp = cal_comp_event_new_with_current_time (cal, TRUE); + comp_editor_edit_comp (editor, comp); + + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (comp); + g_object_unref (cal); +} + +static void +cal_shell_backend_event_meeting_new_cb (ECal *cal, + ECalendarStatus status, + EShell *shell) +{ + ECalComponent *comp; + CompEditor *editor; + CompEditorFlags flags = 0; + + /* XXX Handle errors better. */ + if (status != E_CALENDAR_STATUS_OK) + return; + + flags |= COMP_EDITOR_NEW_ITEM; + flags |= COMP_EDITOR_USER_ORG; + flags |= COMP_EDITOR_MEETING; editor = event_editor_new (cal, shell, flags); - comp = cal_comp_event_new_with_current_time (cal, all_day); + comp = cal_comp_event_new_with_current_time (cal, FALSE); comp_editor_edit_comp (editor, comp); gtk_window_present (GTK_WINDOW (editor)); @@ -372,6 +413,7 @@ action_event_new_cb (GtkAction *action, ESourceList *source_list; EShellSettings *shell_settings; EShell *shell; + const gchar *action_name; gchar *uid; /* This callback is used for both appointments and meetings. */ @@ -403,9 +445,23 @@ action_event_new_cb (GtkAction *action, g_return_if_fail (cal != NULL); - g_signal_connect ( - cal, "cal-opened", - G_CALLBACK (cal_shell_backend_cal_opened_cb), action); + /* Connect the appropriate signal handler. */ + action_name = gtk_action_get_name (action); + if (strcmp (action_name, "event-all-day-new") == 0) + g_signal_connect ( + cal, "cal-opened", + G_CALLBACK (cal_shell_backend_event_all_day_new_cb), + shell); + else if (strcmp (action_name, "event-meeting-new") == 0) + g_signal_connect ( + cal, "cal-opened", + G_CALLBACK (cal_shell_backend_event_meeting_new_cb), + shell); + else + g_signal_connect ( + cal, "cal-opened", + G_CALLBACK (cal_shell_backend_event_new_cb), + shell); e_cal_open_async (cal, FALSE); } -- cgit v1.2.3 From 4c43a88975bfb4cbab2eb10c9e2de31acedf0a61 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Thu, 23 Jul 2009 22:24:39 -0400 Subject: Move "user_created" signal emission to ECalendarView. --- modules/calendar/e-cal-shell-view-private.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c index f681a2c2f3..9af8e98740 100644 --- a/modules/calendar/e-cal-shell-view-private.c +++ b/modules/calendar/e-cal-shell-view-private.c @@ -149,6 +149,25 @@ cal_shell_view_taskpad_popup_event_cb (EShellView *shell_view, e_shell_view_show_popup_menu (shell_view, widget_path, event); } +static void +cal_shell_view_user_created_cb (ECalShellView *cal_shell_view, + ECalendarView *calendar_view) +{ + ECalShellSidebar *cal_shell_sidebar; + ECalModel *model; + ECal *client; + ESource *source; + + model = e_calendar_view_get_model (calendar_view); + client = e_cal_model_get_default_client (model); + source = e_cal_get_source (client); + + cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; + e_cal_shell_sidebar_add_source (cal_shell_sidebar, source); + + e_cal_model_add_client (model, client); +} + static void cal_shell_view_load_view_collection (EShellViewClass *shell_view_class) { @@ -272,6 +291,9 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) mini_calendar->calitem, (ECalendarItemGetTimeCallback) cal_shell_view_get_current_time, cal_shell_view, NULL); + /* KILL-BONOBO FIXME -- Need to connect to the "user-created" + * signal for each ECalendarView. */ + #if 0 /* KILL-BONOBO */ g_signal_connect_swapped ( calendar, "dates-shown-changed", -- cgit v1.2.3 From ad465a7c1fbea59767741ae5e56a94b5f5f7c6a1 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Sat, 25 Jul 2009 15:26:03 -0400 Subject: Re-enable building GnomeCalendar, except it doesn't yet. Also, start trimming the API down a bit. Lots of redundancy there. --- modules/calendar/e-cal-shell-content.c | 187 ++++++---------------------- modules/calendar/e-cal-shell-view-actions.c | 28 +++-- modules/calendar/e-cal-shell-view.c | 10 +- 3 files changed, 61 insertions(+), 164 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c index 6afb40dce7..0f888c13e9 100644 --- a/modules/calendar/e-cal-shell-content.c +++ b/modules/calendar/e-cal-shell-content.c @@ -46,19 +46,10 @@ struct _ECalShellContentPrivate { GtkWidget *notebook; GtkWidget *vpaned; - GtkWidget *day_view; - GtkWidget *work_week_view; - GtkWidget *week_view; - GtkWidget *month_view; - GtkWidget *list_view; + GtkWidget *calendar; GtkWidget *task_table; GtkWidget *memo_table; - EDayViewConfig *day_view_config; - EDayViewConfig *work_week_view_config; - EWeekViewConfig *week_view_config; - EWeekViewConfig *month_view_config; - ECalListViewConfig *list_view_config; ECalendarTableConfig *task_table_config; EMemoTableConfig *memo_table_config; @@ -129,13 +120,15 @@ cal_shell_content_get_focus_location (ECalShellContent *cal_shell_content) #if 0 /* TEMPORARILY DISABLED */ GtkWidget *widget; GnomeCalendar *calendar; + GnomeCalendarViewType view_type; + ECalendarView calendar_view; ECalendarTable *task_table; EMemoTable *memo_table; ETable *table; - ECalendarView *calendar_view; calendar = GNOME_CALENDAR (cal_shell_content->priv->calendar); - widget = gnome_calendar_get_current_view_widget (calendar); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); memo_table = E_MEMO_TABLE (cal_shell_content->priv->memo_table); task_table = E_CALENDAR_TABLE (cal_shell_content->priv->task_table); @@ -148,34 +141,34 @@ cal_shell_content_get_focus_location (ECalShellContent *cal_shell_content) if (GTK_WIDGET_HAS_FOCUS (table->table_canvas)) return FOCUS_TASK_TABLE; - if (E_IS_DAY_VIEW (widget)) { - EDayView *view = E_DAY_VIEW (widget); + if (E_IS_DAY_VIEW (calendar_view)) { + EDayView *day_view = E_DAY_VIEW (calendar_view); - if (GTK_WIDGET_HAS_FOCUS (view->top_canvas)) + if (GTK_WIDGET_HAS_FOCUS (day_view->top_canvas)) return FOCUS_CALENDAR; - if (GNOME_CANVAS (view->top_canvas)->focused_item != NULL) + if (GNOME_CANVAS (day_view->top_canvas)->focused_item != NULL) return FOCUS_CALENDAR; - if (GTK_WIDGET_HAS_FOCUS (view->main_canvas)) + if (GTK_WIDGET_HAS_FOCUS (day_view->main_canvas)) return FOCUS_CALENDAR; - if (GNOME_CANVAS (view->main_canvas)->focused_item != NULL) + if (GNOME_CANVAS (day_view->main_canvas)->focused_item != NULL) return FOCUS_CALENDAR; - } else if (E_IS_WEEK_VIEW (widget)) { - EWeekView *view = E_WEEK_VIEW (widget); + } else if (E_IS_WEEK_VIEW (calendar_view)) { + EWeekView *week_view = E_WEEK_VIEW (calendar_view); - if (GTK_WIDGET_HAS_FOCUS (view->main_canvas)) + if (GTK_WIDGET_HAS_FOCUS (week_view->main_canvas)) return FOCUS_CALENDAR; - if (GNOME_CANVAS (view->main_canvas)->focused_item != NULL) + if (GNOME_CANVAS (week_view->main_canvas)->focused_item != NULL) return FOCUS_CALENDAR; - } else if (E_IS_CAL_LIST_VIEW (widget)) { - ECalListView *view = E_CAL_LIST_VIEW (widget); + } else if (E_IS_CAL_LIST_VIEW (calendar_view)) { + ECalListView *list_view = E_CAL_LIST_VIEW (widget); - table = e_table_scrolled_get_table (view->table_scrolled); + table = e_table_scrolled_get_table (list_view->table_scrolled); if (GTK_WIDGET_HAS_FOCUS (table)) return FOCUS_CALENDAR; } @@ -230,29 +223,9 @@ cal_shell_content_dispose (GObject *object) priv->vpaned = NULL; } - if (priv->day_view != NULL) { - g_object_unref (priv->day_view); - priv->day_view = NULL; - } - - if (priv->work_week_view != NULL) { - g_object_unref (priv->work_week_view); - priv->work_week_view = NULL; - } - - if (priv->week_view != NULL) { - g_object_unref (priv->week_view); - priv->week_view = NULL; - } - - if (priv->month_view != NULL) { - g_object_unref (priv->month_view); - priv->month_view = NULL; - } - - if (priv->list_view != NULL) { - g_object_unref (priv->list_view); - priv->list_view = NULL; + if (priv->calendar != NULL) { + g_object_unref (priv->calendar); + priv->calendar = NULL; } if (priv->task_table != NULL) { @@ -265,31 +238,6 @@ cal_shell_content_dispose (GObject *object) priv->memo_table = NULL; } - if (priv->day_view_config != NULL) { - g_object_unref (priv->day_view_config); - priv->day_view_config = NULL; - } - - if (priv->work_week_view_config != NULL) { - g_object_unref (priv->work_week_view_config); - priv->work_week_view_config = NULL; - } - - if (priv->week_view_config != NULL) { - g_object_unref (priv->week_view_config); - priv->week_view_config = NULL; - } - - if (priv->month_view_config != NULL) { - g_object_unref (priv->month_view_config); - priv->month_view_config = NULL; - } - - if (priv->list_view_config != NULL) { - g_object_unref (priv->list_view_config); - priv->list_view_config = NULL; - } - if (priv->task_table_config != NULL) { g_object_unref (priv->task_table_config); priv->task_table_config = NULL; @@ -342,6 +290,7 @@ cal_shell_content_constructed (GObject *object) gchar *filename; gchar *markup; gint page_num; + gint ii; priv = E_CAL_SHELL_CONTENT_GET_PRIVATE (object); @@ -402,74 +351,19 @@ cal_shell_content_constructed (GObject *object) container = priv->notebook; /* Add views in the order defined by GnomeCalendarViewType, such - * that the notebook page number corresponds to the view type. - * The assertions below ensure that stays true. */ - -#if 0 /* Not so fast... get the memo/task pads working first. */ - /* FIXME Need to establish a calendar and timezone first. */ - widget = e_day_view_new (E_CAL_MODEL (cal_model)); - e_calendar_view_set_calendar ( - E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); - e_calendar_view_set_timezone ( - E_CALENDAR_VIEW (widget), priv->timezone); - page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); - gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); - g_return_if_fail (page_num == GNOME_CAL_DAY_VIEW); - priv->day_view = g_object_ref (widget); - gtk_widget_show (widget); + * that the notebook page number corresponds to the view type. */ - /* FIXME Need to establish a calendar and timezone first. */ - widget = e_day_view_new (E_CAL_MODEL (cal_model)); - e_day_view_set_work_week_view (E_DAY_VIEW (widget), TRUE); - e_day_view_set_days_shown (E_DAY_VIEW (widget), 5); - e_calendar_view_set_calendar ( - E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); - e_calendar_view_set_timezone ( - E_CALENDAR_VIEW (widget), priv->timezone); - page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); - gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); - g_return_if_fail (page_num == GNOME_CAL_WORK_WEEK_VIEW); - priv->work_week_view = g_object_ref (widget); - gtk_widget_show (widget); + for (ii = 0; ii < GNOME_CAL_LAST_VIEW; ii++) { + GnomeCalendar *calendar; + ECalendarView *view; - /* FIXME Need to establish a calendar and timezone first. */ - widget = e_week_view_new (E_CAL_MODEL (cal_model)); - e_calendar_view_set_calendar ( - E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); - e_calendar_view_set_timezone ( - E_CALENDAR_VIEW (widget), priv->timezone); - page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); - gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); - g_return_if_fail (page_num == GNOME_CAL_WEEK_VIEW); - priv->week_view = g_object_ref (widget); - gtk_widget_show (widget); + calendar = GNOME_CALENDAR (priv->calendar); + view = gnome_calendar_get_calendar_view (calendar, ii); - /* FIXME Need to establish a calendar and timezone first. */ - widget = e_week_view_new (E_CAL_MODEL (cal_model)); - e_week_view_set_multi_week_view (E_WEEK_VIEW (widget), TRUE); - e_week_view_set_weeks_shown (E_WEEK_VIEW (widget), 6); - e_calendar_view_set_calendar ( - E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); - e_calendar_view_set_timezone ( - E_CALENDAR_VIEW (widget), priv->timezone); - page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); - gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); - g_return_if_fail (page_num == GNOME_CAL_MONTH_VIEW); - priv->month_view = g_object_ref (widget); - gtk_widget_show (widget); - - /* FIXME Need to establish a calendar and timezone first. */ - widget = e_cal_list_view_new (E_CAL_MODEL (cal_model)); - e_calendar_view_set_calendar ( - E_CALENDAR_VIEW (widget), GNOME_CALENDAR (priv->calendar)); - e_calendar_view_set_timezone ( - E_CALENDAR_VIEW (widget), priv->timezone); - page_num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (widget)); - gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL); - g_return_if_fail (page_num == GNOME_CAL_LIST_VIEW); - priv->list_view = g_object_ref (widget); - gtk_widget_show (widget); -#endif + gtk_notebook_append_page ( + GTK_NOTEBOOK (container), GTK_WIDGET (view), NULL); + gtk_widget_show (GTK_WIDGET (view)); + } container = priv->vpaned; @@ -523,17 +417,7 @@ cal_shell_content_constructed (GObject *object) e_memo_table_load_state (E_MEMO_TABLE (widget), filename); g_free (filename); - /* Configuration managers for views and tables. */ - priv->day_view_config = e_day_view_config_new ( - E_DAY_VIEW (priv->day_view)); - priv->work_week_view_config = e_day_view_config_new ( - E_DAY_VIEW (priv->work_week_view)); - priv->week_view_config = e_week_view_config_new ( - E_WEEK_VIEW (priv->week_view)); - priv->month_view_config = e_week_view_config_new ( - E_WEEK_VIEW (priv->month_view)); - priv->list_view_config = e_cal_list_view_config_new ( - E_CAL_LIST_VIEW (priv->list_view)); + /* Configuration managers for task and memo tables. */ priv->task_table_config = e_calendar_table_config_new ( E_CALENDAR_TABLE (priv->task_table)); priv->memo_table_config = e_memo_table_config_new ( @@ -588,6 +472,11 @@ cal_shell_content_init (ECalShellContent *cal_shell_content) cal_shell_content->priv = E_CAL_SHELL_CONTENT_GET_PRIVATE (cal_shell_content); + /* XXX GnomeCalendar is a widget, but we don't pack it. + * Maybe it should just be a GObject instead? */ + cal_shell_content->priv->calendar = gnome_calendar_new (); + g_object_ref_sink (cal_shell_content->priv->calendar); + /* Postpone widget construction until we have a shell view. */ } diff --git a/modules/calendar/e-cal-shell-view-actions.c b/modules/calendar/e-cal-shell-view-actions.c index 02b7af609e..1358a0615c 100644 --- a/modules/calendar/e-cal-shell-view-actions.c +++ b/modules/calendar/e-cal-shell-view-actions.c @@ -197,20 +197,22 @@ action_calendar_print_cb (GtkAction *action, { #if 0 ECalShellContent *cal_shell_content; + GnomeCalendarViewType view_type; GnomeCalendar *calendar; + ECalendarView *view; GtkPrintOperationAction print_action; cal_shell_content = cal_shell_view->priv->cal_shell_content; calendar = e_cal_shell_content_get_calendar (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + view = gnome_calendar_get_calendar_view (calendar, view_type); print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; - if (gnome_calendar_get_view (calendar) == GNOME_CAL_LIST_VIEW) { + if (E_IS_CAL_LIST_VIEW (view)) { ECalListView *list_view; - GtkWidget *widget; ETable *table; - widget = gnome_calendar_get_current_view_widget (calendar); - list_view = E_CAL_LIST_VIEW (widget); + list_view = E_CAL_LIST_VIEW (view); table = e_table_scrolled_get_table (list_view->table_scrolled); print_table (table, _("Print"), _("Calendar"), action); } else { @@ -228,20 +230,22 @@ action_calendar_print_preview_cb (GtkAction *action, { #if 0 ECalShellContent *cal_shell_content; + GnomeCalendarViewType view_type; GnomeCalendar *calendar; + ECalendarView *view; GtkPrintOperationAction print_action; cal_shell_content = cal_shell_view->priv->cal_shell_content; calendar = e_cal_shell_content_get_calendar (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + view = gnome_calendar_get_calendar_view (calendar, view_type); print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW; - if (gnome_calendar_get_view (calendar) == GNOME_CAL_LIST_VIEW) { + if (E_IS_CAL_LIST_VIEW (view)) { ECalListView *list_view; - GtkWidget *widget; ETable *table; - widget = gnome_calendar_get_current_view_widget (calendar); - list_view = E_CAL_LIST_VIEW (widget); + list_view = E_CAL_LIST_VIEW (view); table = e_table_scrolled_get_table (list_view->table_scrolled); print_table (table, _("Print"), _("Calendar"), action); } else { @@ -512,14 +516,16 @@ action_event_open_cb (GtkAction *action, { #if 0 ECalShellContent *cal_shell_content; + GnomeCalendarViewType view_type; GnomeCalendar *calendar; - GtkWidget *widget; + ECalendarView *view; cal_shell_content = cal_shell_view->priv->cal_shell_content; calendar = e_cal_shell_content_get_calendar (cal_shell_content); - widget = gnome_calendar_get_current_view_widget (calendar); + view_type = gnome_calendar_get_view (calendar); + view = gnome_calendar_get_calendar_view (calendar, view_type); - e_calendar_view_open_event (E_CALENDAR_VIEW (widget)); + e_calendar_view_open_event (view); #endif } diff --git a/modules/calendar/e-cal-shell-view.c b/modules/calendar/e-cal-shell-view.c index 5bf1c749a1..2c977e7553 100644 --- a/modules/calendar/e-cal-shell-view.c +++ b/modules/calendar/e-cal-shell-view.c @@ -59,12 +59,13 @@ cal_shell_view_update_actions (EShellView *shell_view) ECalShellContent *cal_shell_content; ECalShellSidebar *cal_shell_sidebar; EShellWindow *shell_window; + GnomeCalendarViewType view_type; GnomeCalendar *calendar; + ECalendarView *view; ECalModel *model; ESourceSelector *selector; ESource *source; GtkAction *action; - GtkWidget *widget; GList *list, *iter; const gchar *uri = NULL; gboolean user_created_source; @@ -79,13 +80,14 @@ cal_shell_view_update_actions (EShellView *shell_view) cal_shell_content = priv->cal_shell_content; calendar = e_cal_shell_content_get_calendar (cal_shell_content); - widget = gnome_calendar_get_current_view_widget (calendar); - model = e_calendar_view_get_model (E_CALENDAR_VIEW (widget)); + view_type = gnome_calendar_get_view (calendar); + view = gnome_calendar_get_calendar_view (calendar, view_type); + model = e_calendar_view_get_model (view); cal_shell_sidebar = priv->cal_shell_sidebar; selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); - list = e_calendar_view_get_selected_events (E_CALENDAR_VIEW (widget)); + list = e_calendar_view_get_selected_events (view); n_selected = g_list_length (list); for (iter = list; iter != NULL; iter = iter->next) { -- cgit v1.2.3 From b4c93f77e655cfd0a2a740502d7b67bc60df4523 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Mon, 27 Jul 2009 13:26:13 -0400 Subject: Kill CalSearchBar. Move calendar search logic to ECalShellView. --- modules/calendar/e-cal-shell-view-private.c | 151 ++++++++++++++++++++++++++- modules/calendar/e-memo-shell-view-private.c | 6 +- modules/calendar/e-task-shell-view-private.c | 6 +- 3 files changed, 156 insertions(+), 7 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c index 9af8e98740..19d29a05fb 100644 --- a/modules/calendar/e-cal-shell-view-private.c +++ b/modules/calendar/e-cal-shell-view-private.c @@ -417,7 +417,156 @@ e_cal_shell_view_private_finalize (ECalShellView *cal_shell_view) void e_cal_shell_view_execute_search (ECalShellView *cal_shell_view) { - /* FIXME */ + ECalShellContent *cal_shell_content; + ECalShellSidebar *cal_shell_sidebar; + EShellView *shell_view; + EShellWindow *shell_window; + EShellContent *shell_content; + GnomeCalendar *calendar; + ECalendar *mini_calendar; + GtkRadioAction *action; + GString *string; + FilterRule *rule; + const gchar *format; + const gchar *text; + time_t start_range; + time_t end_range; + gboolean range_search; + gchar *start, *end; + gchar *query; + gchar *temp; + gint value; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + text = e_shell_content_get_search_text (shell_content); + + shell_window = e_shell_view_get_shell_window (shell_view); + action = GTK_RADIO_ACTION (ACTION (CAL_SEARCH_ANY_FIELD_CONTAINS)); + value = gtk_radio_action_get_current_value (action); + + if (text == NULL || *text == '\0') { + text = ""; + value = CALENDAR_SEARCH_SUMMARY_CONTAINS; + } + + switch (value) { + default: + text = ""; + /* fall through */ + + case CALENDAR_SEARCH_SUMMARY_CONTAINS: + format = "(contains? \"summary\" %s)"; + break; + + case CALENDAR_SEARCH_DESCRIPTION_CONTAINS: + format = "(contains? \"description\" %s)"; + break; + + case CALENDAR_SEARCH_ANY_FIELD_CONTAINS: + format = "(contains? \"any\" %s)"; + break; + } + + /* Build the query. */ + string = g_string_new (""); + e_sexp_encode_string (string, text); + query = g_strdup_printf (format, string->str); + g_string_free (string, TRUE); + + range_search = FALSE; + range_start = range_end = 0; + + /* Apply selected filter. */ + value = e_shell_content_get_filter_value (shell_content); + switch (value) { + case CALENDAR_FILTER_ANY_CATEGORY: + break; + + case CALENDAR_FILTER_UNMATCHED: + temp = g_strdup_printf ( + "(and (has-categories? #f) %s)", query); + g_free (query); + query = temp; + break; + + case CALENDAR_FILTER_ACTIVE_APPOINTMENTS: + /* Show a year's worth of appointments. */ + start_range = time (NULL); + end_range = time_add_day (start_range, 365); + start = isodate_from_time_t (start_range); + end = isodate_from_time_t (end_range); + + temp = g_strdup_printf ( + "(and %s (occur-in-time-range? " + "(make-time \"%s\") (make-time \"%s\")))", + query, start, end); + g_free (query); + query = temp; + + range_search = TRUE; + break; + + case CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS: + start_range = time (NULL); + end_range = time_add_day (start_range, 7); + start = isodate_from_time_t (start_range); + end = isodate_from_time_t (end_range); + + temp = g_strdup_printf ( + "(and %s (occur-in-time-range? " + "(make-time \"%s\") (make-time \"%s\")))", + query, start, end); + g_free (query); + query = temp; + + range_search = TRUE; + break; + + default: + { + GList *categories; + const gchar *category_name; + + categories = e_categories_get_list (); + category_name = g_list_nth_data (categories, value); + g_list_free (categories); + + temp = g_strdup_printf ( + "(and (has-categories? \"%s\") %s)", + category_name, query); + g_free (query); + query = temp; + break; + } + } + + /* XXX This is wrong. We need to programmatically construct a + * FilterRule, tell it to build code, and pass the resulting + * expressing string to ECalModel. */ + rule = filter_rule_new (); + e_shell_content_set_search_rule (shell_content, rule); + g_object_unref (rule); + + cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; + mini_calendar = e_cal_shell_sidebar_get_mini_calendar (cal_shell_sidebar); + + if (range_search) { + /* Switch to list view and hide the mini calendar. */ + action = GTK_RADIO_ACTION (ACTION (CALENDAR_VIEW_LIST)); + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); + gtk_widget_hide (GTK_WIDGET (mini_calendar)); + } else { + /* Ensure the mini calendar is visible. */ + gtk_widget_show (GTK_WIDGET (mini_calendar)); + } + + /* Submit the query. */ + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + gnome_calendar_set_search_query ( + calendar, query, range_search, start_range, end_range); + g_free (query); } void diff --git a/modules/calendar/e-memo-shell-view-private.c b/modules/calendar/e-memo-shell-view-private.c index 69d6c0afe2..4953a388d3 100644 --- a/modules/calendar/e-memo-shell-view-private.c +++ b/modules/calendar/e-memo-shell-view-private.c @@ -303,7 +303,7 @@ e_memo_shell_view_execute_search (EMemoShellView *memo_shell_view) EShellView *shell_view; EShellWindow *shell_window; EShellContent *shell_content; - GtkAction *action; + GtkRadioAction *action; GString *string; ECalComponentPreview *memo_preview; EMemoTable *memo_table; @@ -320,8 +320,8 @@ e_memo_shell_view_execute_search (EMemoShellView *memo_shell_view) text = e_shell_content_get_search_text (shell_content); shell_window = e_shell_view_get_shell_window (shell_view); - action = ACTION (MEMO_SEARCH_ANY_FIELD_CONTAINS); - value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + action = GTK_RADIO_ACTION (ACTION (MEMO_SEARCH_ANY_FIELD_CONTAINS)); + value = gtk_radio_action_get_current_value (action); if (text == NULL || *text == '\0') { text = ""; diff --git a/modules/calendar/e-task-shell-view-private.c b/modules/calendar/e-task-shell-view-private.c index d6fd8e35aa..be281f1c6e 100644 --- a/modules/calendar/e-task-shell-view-private.c +++ b/modules/calendar/e-task-shell-view-private.c @@ -412,7 +412,7 @@ e_task_shell_view_execute_search (ETaskShellView *task_shell_view) EShellView *shell_view; EShellWindow *shell_window; EShellContent *shell_content; - GtkAction *action; + GtkRadioAction *action; GString *string; ECalComponentPreview *task_preview; ECalendarTable *task_table; @@ -432,8 +432,8 @@ e_task_shell_view_execute_search (ETaskShellView *task_shell_view) text = e_shell_content_get_search_text (shell_content); shell_window = e_shell_view_get_shell_window (shell_view); - action = ACTION (TASK_SEARCH_ANY_FIELD_CONTAINS); - value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + action = GTK_RADIO_ACTION (ACTION (TASK_SEARCH_ANY_FIELD_CONTAINS)); + value = gtk_radio_action_get_current_value (action); if (text == NULL || *text == '\0') { text = ""; -- cgit v1.2.3 From bfd6635397f29dc7b0ad6b6a27101c241a7287b6 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Mon, 27 Jul 2009 15:41:54 -0400 Subject: Get GnomeCalendar and the a11y stuff building. --- modules/calendar/e-cal-shell-view-actions.c | 48 +++++++++++++++++++++++++++-- modules/calendar/e-cal-shell-view-private.c | 4 +-- 2 files changed, 47 insertions(+), 5 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-view-actions.c b/modules/calendar/e-cal-shell-view-actions.c index 1358a0615c..f3ed11e33d 100644 --- a/modules/calendar/e-cal-shell-view-actions.c +++ b/modules/calendar/e-cal-shell-view-actions.c @@ -397,7 +397,23 @@ static void action_event_all_day_new_cb (GtkAction *action, ECalShellView *cal_shell_view) { - /* FIXME */ + ECalShellContent *cal_shell_content; + GnomeCalendarViewType view_type; + ECalendarView *calendar_view; + GnomeCalendar *calendar; + + /* These are just for readability. */ + gboolean all_day = TRUE; + gboolean meeting = FALSE; + gboolean no_past_date = FALSE; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + + e_calendar_view_new_appointment_full ( + calendar_view, all_day, meeting, no_past_date); } static void @@ -486,7 +502,23 @@ static void action_event_meeting_new_cb (GtkAction *action, ECalShellView *cal_shell_view) { - /* FIXME */ + ECalShellContent *cal_shell_content; + GnomeCalendarViewType view_type; + ECalendarView *calendar_view; + GnomeCalendar *calendar; + + /* These are just for readability. */ + gboolean all_day = FALSE; + gboolean meeting = TRUE; + gboolean no_past_date = FALSE; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + + e_calendar_view_new_appointment_full ( + calendar_view, all_day, meeting, no_past_date); } static void @@ -500,7 +532,17 @@ static void action_event_new_cb (GtkAction *action, ECalShellView *cal_shell_view) { - /* FIXME */ + ECalShellContent *cal_shell_content; + GnomeCalendarViewType view_type; + ECalendarView *calendar_view; + GnomeCalendar *calendar; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + + e_calendar_view_new_appointment (calendar_view); } static void diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c index 19d29a05fb..c6d10292c3 100644 --- a/modules/calendar/e-cal-shell-view-private.c +++ b/modules/calendar/e-cal-shell-view-private.c @@ -442,7 +442,7 @@ e_cal_shell_view_execute_search (ECalShellView *cal_shell_view) text = e_shell_content_get_search_text (shell_content); shell_window = e_shell_view_get_shell_window (shell_view); - action = GTK_RADIO_ACTION (ACTION (CAL_SEARCH_ANY_FIELD_CONTAINS)); + action = GTK_RADIO_ACTION (ACTION (CALENDAR_SEARCH_ANY_FIELD_CONTAINS)); value = gtk_radio_action_get_current_value (action); if (text == NULL || *text == '\0') { @@ -475,7 +475,7 @@ e_cal_shell_view_execute_search (ECalShellView *cal_shell_view) g_string_free (string, TRUE); range_search = FALSE; - range_start = range_end = 0; + start_range = end_range = 0; /* Apply selected filter. */ value = e_shell_content_get_filter_value (shell_content); -- cgit v1.2.3 From 40a28eb4c0ea691e6cd9ce2531874bc4d9ac8839 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Mon, 27 Jul 2009 17:01:09 -0400 Subject: Start re-enabling parts of the calendar. --- modules/calendar/e-cal-shell-view-actions.c | 45 ++++++++++------------------- 1 file changed, 15 insertions(+), 30 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-view-actions.c b/modules/calendar/e-cal-shell-view-actions.c index f3ed11e33d..bb8ee69893 100644 --- a/modules/calendar/e-cal-shell-view-actions.c +++ b/modules/calendar/e-cal-shell-view-actions.c @@ -48,14 +48,16 @@ static void action_calendar_delete_cb (GtkAction *action, ECalShellView *cal_shell_view) { -#if 0 ECalShellContent *cal_shell_content; ECalShellSidebar *cal_shell_sidebar; + EShellBackend *shell_backend; EShellWindow *shell_window; EShellView *shell_view; ECalendarView *calendar_view; GnomeCalendarViewType view_type; + GnomeCalendar *calendar; ECalModel *model; + ECal *client; ESourceSelector *selector; ESourceGroup *source_group; ESourceList *source_list; @@ -66,14 +68,15 @@ action_calendar_delete_cb (GtkAction *action, shell_view = E_SHELL_VIEW (cal_shell_view); shell_window = e_shell_view_get_shell_window (shell_view); + shell_backend = e_shell_view_get_shell_backend (shell_view); - cal_shell_content = cal_shell_content->priv->cal_shell_content; - view_type = e_cal_shell_content_get_current_view (cal_shell_content); - calendar_view = e_cal_shell_content_get_calendar_view ( - cal_shell_content, view_type); + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); model = e_calendar_view_get_model (calendar_view); - cal_shell_sidebar = cal_shell_sidebar->priv->cal_shell_sidebar; + cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); source = e_source_selector_peek_primary_selection (selector); g_return_if_fail (E_IS_SOURCE (source)); @@ -109,19 +112,18 @@ action_calendar_delete_cb (GtkAction *action, source_group = e_source_peek_group (source); e_source_group_remove_source (source_group, source); - source_list = cal_shell_view->priv->source_list; + source_list = e_cal_shell_backend_get_source_list ( + E_CAL_SHELL_BACKEND (shell_backend)); if (!e_source_list_sync (source_list, &error)) { g_warning ("%s", error->message); g_error_free (error); } -#endif } static void action_calendar_go_back_cb (GtkAction *action, ECalShellView *cal_shell_view) { -#if 0 ECalShellContent *cal_shell_content; GnomeCalendar *calendar; @@ -129,14 +131,12 @@ action_calendar_go_back_cb (GtkAction *action, calendar = e_cal_shell_content_get_calendar (cal_shell_content); gnome_calendar_previous (calendar); -#endif } static void action_calendar_go_forward_cb (GtkAction *action, ECalShellView *cal_shell_view) { -#if 0 ECalShellContent *cal_shell_content; GnomeCalendar *calendar; @@ -144,14 +144,12 @@ action_calendar_go_forward_cb (GtkAction *action, calendar = e_cal_shell_content_get_calendar (cal_shell_content); gnome_calendar_next (calendar); -#endif } static void action_calendar_go_today_cb (GtkAction *action, ECalShellView *cal_shell_view) { -#if 0 ECalShellContent *cal_shell_content; GnomeCalendar *calendar; @@ -159,14 +157,12 @@ action_calendar_go_today_cb (GtkAction *action, calendar = e_cal_shell_content_get_calendar (cal_shell_content); gnome_calendar_goto_today (calendar); -#endif } static void action_calendar_jump_to_cb (GtkAction *action, ECalShellView *cal_shell_view) { -#if 0 ECalShellContent *cal_shell_content; GnomeCalendar *calendar; @@ -174,28 +170,24 @@ action_calendar_jump_to_cb (GtkAction *action, calendar = e_cal_shell_content_get_calendar (cal_shell_content); goto_dialog (calendar); -#endif } static void action_calendar_new_cb (GtkAction *action, ECalShellView *cal_shell_view) { -#if 0 EShellView *shell_view; EShellWindow *shell_window; shell_view = E_SHELL_VIEW (cal_shell_view); shell_window = e_shell_view_get_shell_window (shell_view); calendar_setup_new_calendar (GTK_WINDOW (shell_window)); -#endif } static void action_calendar_print_cb (GtkAction *action, ECalShellView *cal_shell_view) { -#if 0 ECalShellContent *cal_shell_content; GnomeCalendarViewType view_type; GnomeCalendar *calendar; @@ -214,21 +206,19 @@ action_calendar_print_cb (GtkAction *action, list_view = E_CAL_LIST_VIEW (view); table = e_table_scrolled_get_table (list_view->table_scrolled); - print_table (table, _("Print"), _("Calendar"), action); + print_table (table, _("Print"), _("Calendar"), print_action); } else { time_t start; gnome_calendar_get_current_time_range (calendar, &start, NULL); - print_calendar (calendar, action, start); + print_calendar (calendar, print_action, start); } -#endif } static void action_calendar_print_preview_cb (GtkAction *action, ECalShellView *cal_shell_view) { -#if 0 ECalShellContent *cal_shell_content; GnomeCalendarViewType view_type; GnomeCalendar *calendar; @@ -247,21 +237,19 @@ action_calendar_print_preview_cb (GtkAction *action, list_view = E_CAL_LIST_VIEW (view); table = e_table_scrolled_get_table (list_view->table_scrolled); - print_table (table, _("Print"), _("Calendar"), action); + print_table (table, _("Print"), _("Calendar"), print_action); } else { time_t start; gnome_calendar_get_current_time_range (calendar, &start, NULL); - print_calendar (calendar, action, start); + print_calendar (calendar, print_action, start); } -#endif } static void action_calendar_properties_cb (GtkAction *action, ECalShellView *cal_shell_view) { -#if 0 ECalShellSidebar *cal_shell_sidebar; EShellView *shell_view; EShellWindow *shell_window; @@ -277,7 +265,6 @@ action_calendar_properties_cb (GtkAction *action, g_return_if_fail (E_IS_SOURCE (source)); calendar_setup_edit_calendar (GTK_WINDOW (shell_window), source); -#endif } static void @@ -556,7 +543,6 @@ static void action_event_open_cb (GtkAction *action, ECalShellView *cal_shell_view) { -#if 0 ECalShellContent *cal_shell_content; GnomeCalendarViewType view_type; GnomeCalendar *calendar; @@ -568,7 +554,6 @@ action_event_open_cb (GtkAction *action, view = gnome_calendar_get_calendar_view (calendar, view_type); e_calendar_view_open_event (view); -#endif } static void -- cgit v1.2.3 From 41569bb778e228d4f5a04cb1e15bfa5b49bb044b Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Tue, 28 Jul 2009 21:01:08 -0400 Subject: Trimming redundancy. --- modules/calendar/e-cal-shell-content.c | 33 +++++++++++++++++++++++++++++---- modules/calendar/e-cal-shell-sidebar.c | 2 +- 2 files changed, 30 insertions(+), 5 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c index 0f888c13e9..1a55c74d35 100644 --- a/modules/calendar/e-cal-shell-content.c +++ b/modules/calendar/e-cal-shell-content.c @@ -27,13 +27,13 @@ #include "e-util/gconf-bridge.h" #include "calendar/gui/calendar-config.h" -#include "calendar/gui/e-cal-list-view-config.h" +#include "calendar/gui/calendar-view.h" +#include "calendar/gui/e-cal-list-view.h" #include "calendar/gui/e-cal-model-calendar.h" #include "calendar/gui/e-calendar-table.h" #include "calendar/gui/e-calendar-table-config.h" -#include "calendar/gui/e-day-view-config.h" +#include "calendar/gui/e-calendar-view.h" #include "calendar/gui/e-memo-table-config.h" -#include "calendar/gui/e-week-view-config.h" #include "widgets/menus/gal-view-etable.h" @@ -77,7 +77,32 @@ static void cal_shell_content_display_view_cb (ECalShellContent *cal_shell_content, GalView *gal_view) { - /* FIXME */ + GnomeCalendar *calendar; + CalendarView *gal_calendar_view; + GnomeCalendarViewType view_type; + + /* XXX This is confusing: we have CalendarView and ECalendarView. + * ECalendarView is an abstract base class for calendar view + * widgets (day view, week view, etc). CalendarView is a + * simple GalView subclass that represents a calendar view. */ + + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + + if (GAL_IS_VIEW_ETABLE (gal_view)) { + ECalendarView *calendar_view; + ETable *table; + + view_type = GNOME_CAL_LIST_VIEW; + calendar_view = gnome_calendar_get_calendar_view ( + calendar, view_type); + table = e_table_scrolled_get_table ( + E_CAL_LIST_VIEW (calendar_view)->table_scrolled); + gal_view_etable_attach_table ( + GAL_VIEW_ETABLE (gal_view), table); + } else { + view_type = calendar_view_get_view_type ( + CALENDAR_VIEW (gal_view)); + } } static void diff --git a/modules/calendar/e-cal-shell-sidebar.c b/modules/calendar/e-cal-shell-sidebar.c index dc7df596d6..dc618e2dda 100644 --- a/modules/calendar/e-cal-shell-sidebar.c +++ b/modules/calendar/e-cal-shell-sidebar.c @@ -349,7 +349,7 @@ cal_shell_sidebar_dispose (GObject *object) if (priv->mini_calendar_config != NULL) { g_object_unref (priv->mini_calendar_config); - priv->mini_calendar = NULL; + priv->mini_calendar_config = NULL; } /* Chain up to parent's dispose() method. */ -- cgit v1.2.3 From 2fe24b4c136b4d5f255af3571c3d6e1082071809 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Thu, 30 Jul 2009 12:38:24 -0400 Subject: Add properties to calendar classes. So we can bind them to EShellSettings and kill off EDayViewConfig and similar GConf notification classes. --- modules/calendar/e-cal-shell-content.c | 183 +++++++++++++++++++++++++++++--- modules/calendar/e-cal-shell-settings.c | 170 +++++++++++++++++++++++++++++ 2 files changed, 340 insertions(+), 13 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c index 1a55c74d35..4e6f871d67 100644 --- a/modules/calendar/e-cal-shell-content.c +++ b/modules/calendar/e-cal-shell-content.c @@ -24,6 +24,7 @@ #include #include +#include "e-util/e-binding.h" #include "e-util/gconf-bridge.h" #include "calendar/gui/calendar-config.h" @@ -73,6 +74,19 @@ typedef enum { static gpointer parent_class; static GType cal_shell_content_type; +static gboolean +transform_week_start_day (const GValue *src_value, + GValue *dst_value) +{ + gint v_int; + + /* Transform day numbering from 0 = Sunday to 0 = Monday. */ + v_int = g_value_get_int (src_value); + g_value_set_int (dst_value, (v_int + 6) % 7); + + return TRUE; +} + static void cal_shell_content_display_view_cb (ECalShellContent *cal_shell_content, GalView *gal_view) @@ -297,15 +311,20 @@ static void cal_shell_content_constructed (GObject *object) { ECalShellContentPrivate *priv; - ECalModelCalendar *cal_model; + ECalendarView *calendar_view; + ECalModel *calendar_model; ECalModel *memo_model; ECalModel *task_model; + EShell *shell; EShellContent *shell_content; EShellBackend *shell_backend; + EShellSettings *shell_settings; EShellView *shell_view; EShellWindow *shell_window; EShellContent *foreign_content; EShellView *foreign_view; + GnomeCalendar *calendar; + GnomeCalendarViewType view_type; GalViewInstance *view_instance; GConfBridge *bridge; GtkWidget *container; @@ -329,11 +348,8 @@ cal_shell_content_constructed (GObject *object) shell_backend = e_shell_view_get_shell_backend (shell_view); config_dir = e_shell_backend_get_config_dir (shell_backend); - /* Calendar model for the views. */ - cal_model = e_cal_model_calendar_new (); - e_cal_model_set_flags ( - E_CAL_MODEL (cal_model), - E_CAL_MODEL_FLAGS_EXPAND_RECURRENCES); + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); /* We borrow the memopad and taskpad models from the memo * and task views, loading the views if necessary. */ @@ -378,16 +394,15 @@ cal_shell_content_constructed (GObject *object) /* Add views in the order defined by GnomeCalendarViewType, such * that the notebook page number corresponds to the view type. */ - for (ii = 0; ii < GNOME_CAL_LAST_VIEW; ii++) { - GnomeCalendar *calendar; - ECalendarView *view; + calendar = GNOME_CALENDAR (priv->calendar); - calendar = GNOME_CALENDAR (priv->calendar); - view = gnome_calendar_get_calendar_view (calendar, ii); + for (ii = 0; ii < GNOME_CAL_LAST_VIEW; ii++) { + calendar_view = gnome_calendar_get_calendar_view (calendar, ii); gtk_notebook_append_page ( - GTK_NOTEBOOK (container), GTK_WIDGET (view), NULL); - gtk_widget_show (GTK_WIDGET (view)); + GTK_NOTEBOOK (container), + GTK_WIDGET (calendar_view), NULL); + gtk_widget_show (GTK_WIDGET (calendar_view)); } container = priv->vpaned; @@ -471,6 +486,148 @@ cal_shell_content_constructed (GObject *object) key = "/apps/evolution/calendar/display/vpane_position"; gconf_bridge_bind_property_delayed (bridge, key, object, "position"); + /* Bind day view properties to EShellSettings. */ + + view_type = GNOME_CAL_DAY_VIEW; + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-marcus-bains-show-line", + G_OBJECT (calendar_view), "marcus-bains-show-line"); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-marcus-bains-day-view-color", + G_OBJECT (calendar_view), "marcus-bains-day-view-color"); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-marcus-bains-time-bar-color", + G_OBJECT (calendar_view), "marcus-bains-time-bar-color"); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-time-divisions", + G_OBJECT (calendar_view), "mins-per-row"); + + e_binding_new_full ( + G_OBJECT (shell_settings), "cal-week-start-day", + G_OBJECT (calendar_view), "week-start-day", + (EBindingTransform) transform_week_start_day, + (GDestroyNotify) NULL, NULL); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-work-day-end-hour", + G_OBJECT (calendar_view), "work-day-end-hour"); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-work-day-end-minute", + G_OBJECT (calendar_view), "work-day-end-minute"); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-work-day-start-hour", + G_OBJECT (calendar_view), "work-day-start-hour"); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-work-day-start-minute", + G_OBJECT (calendar_view), "work-day-start-minute"); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-working-days", + G_OBJECT (calendar_view), "working-days"); + + /* Bind work week view properties to EShellSettings. */ + + view_type = GNOME_CAL_WORK_WEEK_VIEW; + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-marcus-bains-show-line", + G_OBJECT (calendar_view), "marcus-bains-show-line"); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-marcus-bains-day-view-color", + G_OBJECT (calendar_view), "marcus-bains-day-view-color"); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-marcus-bains-time-bar-color", + G_OBJECT (calendar_view), "marcus-bains-time-bar-color"); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-time-divisions", + G_OBJECT (calendar_view), "mins-per-row"); + + e_binding_new_full ( + G_OBJECT (shell_settings), "cal-week-start-day", + G_OBJECT (calendar_view), "week-start-day", + (EBindingTransform) transform_week_start_day, + (GDestroyNotify) NULL, NULL); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-work-day-end-hour", + G_OBJECT (calendar_view), "work-day-end-hour"); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-work-day-end-minute", + G_OBJECT (calendar_view), "work-day-end-minute"); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-work-day-start-hour", + G_OBJECT (calendar_view), "work-day-start-hour"); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-work-day-start-minute", + G_OBJECT (calendar_view), "work-day-start-minute"); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-working-days", + G_OBJECT (calendar_view), "working-days"); + + /* Bind week view properties to EShellSettings. */ + + view_type = GNOME_CAL_WEEK_VIEW; + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-compress-weekend", + G_OBJECT (calendar_view), "compress-weekend"); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-show-event-end-times", + G_OBJECT (calendar_view), "show-event-end-times"); + + e_binding_new_full ( + G_OBJECT (shell_settings), "cal-week-start-day", + G_OBJECT (calendar_view), "week-start-day", + (EBindingTransform) transform_week_start_day, + (GDestroyNotify) NULL, NULL); + + /* Bind month view properties to EShellSettings. */ + + view_type = GNOME_CAL_MONTH_VIEW; + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-compress-weekend", + G_OBJECT (calendar_view), "compress-weekend"); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-show-event-end-times", + G_OBJECT (calendar_view), "show-event-end-times"); + + e_binding_new_full ( + G_OBJECT (shell_settings), "cal-week-start-day", + G_OBJECT (calendar_view), "week-start-day", + (EBindingTransform) transform_week_start_day, + (GDestroyNotify) NULL, NULL); + + /* Bind calendar model properties to EShellSettings. + * Note, does not matter from which view we get the + * model, since it's shared across all of them. */ + + calendar_model = e_calendar_view_get_model (calendar_view); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-use-24-hour-format", + G_OBJECT (calendar_view), "use-24-hour-format"); + g_object_unref (memo_model); g_object_unref (task_model); } diff --git a/modules/calendar/e-cal-shell-settings.c b/modules/calendar/e-cal-shell-settings.c index 03af4aeebc..0379a659b4 100644 --- a/modules/calendar/e-cal-shell-settings.c +++ b/modules/calendar/e-cal-shell-settings.c @@ -33,6 +33,54 @@ e_cal_shell_backend_init_settings (EShell *shell) /* XXX Default values should match the GConf schema. * Yes it's redundant, but we're stuck with GConf. */ + e_shell_settings_install_property ( + g_param_spec_boolean ( + "cal-compress-weekend", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "cal-compress-weekend", + "/apps/evolution/calendar/display/compress_weekend"); + + e_shell_settings_install_property ( + g_param_spec_string ( + "cal-marcus-bains-day-view-color", + NULL, + NULL, + NULL, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "cal-marcus-bains-day-view-color", + "/apps/evolution/calendar/display/marcus_bains_color_dayview"); + + e_shell_settings_install_property ( + g_param_spec_string ( + "cal-marcus-bains-time-bar-color", + NULL, + NULL, + NULL, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "cal-marcus-bains-time-bar-color", + "/apps/evolution/calendar/display/marcus_bains_color_timebar"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "cal-marcus-bains-show-line", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "cal-marcus-bains-show-line", + "/apps/evolution/calendar/display/marcus_bains_line"); + e_shell_settings_install_property ( g_param_spec_string ( "cal-primary-calendar", @@ -45,6 +93,44 @@ e_cal_shell_backend_init_settings (EShell *shell) shell_settings, "cal-primary-calendar", "/apps/evolution/calendar/display/primary_calendar"); + e_shell_settings_install_property ( + g_param_spec_boolean ( + "cal-show-event-end-times", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "cal-show-event-end-times", + "/apps/evolution/calendar/display/show_event_end"); + + e_shell_settings_install_property ( + g_param_spec_int ( + "cal-time-divisions", + NULL, + NULL, + 5, + 60, + 30, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "cal-time-divisions", + "/apps/evolution/calendar/display/time_divisions"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "cal-use-24-hour-format", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "cal-use-24-hour-format", + "/apps/evolution/calendar/display/use_24hour_format"); + e_shell_settings_install_property ( g_param_spec_boolean ( "cal-use-system-timezone", @@ -56,4 +142,88 @@ e_cal_shell_backend_init_settings (EShell *shell) e_shell_settings_bind_to_gconf ( shell_settings, "cal-use-system-timezone", "/apps/evolution/calendar/display/use_system_timezone"); + + e_shell_settings_install_property ( + g_param_spec_int ( + "cal-week-start-day", + NULL, + NULL, + 0, /* Sunday */ + 6, /* Saturday */ + 0, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "cal-week-start-day", + "/apps/evolution/calendar/display/week_start_day"); + + e_shell_settings_install_property ( + g_param_spec_int ( + "cal-work-day-end-hour", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "cal-work-day-end-hour", + "/apps/evolution/calendar/display/day_end_hour"); + + e_shell_settings_install_property ( + g_param_spec_int ( + "cal-work-day-end-minute", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "cal-work-day-end-minute", + "/apps/evolution/calendar/display/day_end_minute"); + + e_shell_settings_install_property ( + g_param_spec_int ( + "cal-work-day-start-hour", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "cal-work-day-start-hour", + "/apps/evolution/calendar/display/day_start_hour"); + + e_shell_settings_install_property ( + g_param_spec_int ( + "cal-work-day-start-minute", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "cal-work-day-start-minute", + "/apps/evolution/calendar/display/day_start_minute"); + + e_shell_settings_install_property ( + g_param_spec_int ( + "cal-working-days", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "cal-working-days", + "/apps/evolution/calendar/display/working_days"); } -- cgit v1.2.3 From fac731e7359c978ff730d48f9ab88a5794450206 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Fri, 31 Jul 2009 00:45:38 -0400 Subject: Simplify binding EShellSettings properties to GConf keys. --- modules/calendar/e-cal-shell-content.c | 2 +- modules/calendar/e-cal-shell-settings.c | 197 +++++--------------------------- 2 files changed, 31 insertions(+), 168 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c index 4e6f871d67..a688c27d0e 100644 --- a/modules/calendar/e-cal-shell-content.c +++ b/modules/calendar/e-cal-shell-content.c @@ -626,7 +626,7 @@ cal_shell_content_constructed (GObject *object) e_binding_new ( G_OBJECT (shell_settings), "cal-use-24-hour-format", - G_OBJECT (calendar_view), "use-24-hour-format"); + G_OBJECT (calendar_model), "use-24-hour-format"); g_object_unref (memo_model); g_object_unref (task_model); diff --git a/modules/calendar/e-cal-shell-settings.c b/modules/calendar/e-cal-shell-settings.c index 0379a659b4..39581a5181 100644 --- a/modules/calendar/e-cal-shell-settings.c +++ b/modules/calendar/e-cal-shell-settings.c @@ -30,200 +30,63 @@ e_cal_shell_backend_init_settings (EShell *shell) shell_settings = e_shell_get_shell_settings (shell); - /* XXX Default values should match the GConf schema. - * Yes it's redundant, but we're stuck with GConf. */ - - e_shell_settings_install_property ( - g_param_spec_boolean ( - "cal-compress-weekend", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "cal-compress-weekend", + e_shell_settings_install_property_for_key ( + "cal-compress-weekend", "/apps/evolution/calendar/display/compress_weekend"); - e_shell_settings_install_property ( - g_param_spec_string ( - "cal-marcus-bains-day-view-color", - NULL, - NULL, - NULL, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "cal-marcus-bains-day-view-color", + e_shell_settings_install_property_for_key ( + "cal-marcus-bains-day-view-color", "/apps/evolution/calendar/display/marcus_bains_color_dayview"); - e_shell_settings_install_property ( - g_param_spec_string ( - "cal-marcus-bains-time-bar-color", - NULL, - NULL, - NULL, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "cal-marcus-bains-time-bar-color", + e_shell_settings_install_property_for_key ( + "cal-marcus-bains-time-bar-color", "/apps/evolution/calendar/display/marcus_bains_color_timebar"); - e_shell_settings_install_property ( - g_param_spec_boolean ( - "cal-marcus-bains-show-line", - NULL, - NULL, - TRUE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "cal-marcus-bains-show-line", + e_shell_settings_install_property_for_key ( + "cal-marcus-bains-show-line", "/apps/evolution/calendar/display/marcus_bains_line"); - e_shell_settings_install_property ( - g_param_spec_string ( - "cal-primary-calendar", - NULL, - NULL, - NULL, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "cal-primary-calendar", + e_shell_settings_install_property_for_key ( + "cal-primary-calendar", "/apps/evolution/calendar/display/primary_calendar"); - e_shell_settings_install_property ( - g_param_spec_boolean ( - "cal-show-event-end-times", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "cal-show-event-end-times", + e_shell_settings_install_property_for_key ( + "cal-show-event-end-times", "/apps/evolution/calendar/display/show_event_end"); - e_shell_settings_install_property ( - g_param_spec_int ( - "cal-time-divisions", - NULL, - NULL, - 5, - 60, - 30, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "cal-time-divisions", + e_shell_settings_install_property_for_key ( + "cal-time-divisions", "/apps/evolution/calendar/display/time_divisions"); - e_shell_settings_install_property ( - g_param_spec_boolean ( - "cal-use-24-hour-format", - NULL, - NULL, - TRUE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "cal-use-24-hour-format", + e_shell_settings_install_property_for_key ( + "cal-use-24-hour-format", "/apps/evolution/calendar/display/use_24hour_format"); - e_shell_settings_install_property ( - g_param_spec_boolean ( - "cal-use-system-timezone", - NULL, - NULL, - TRUE, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "cal-use-system-timezone", + e_shell_settings_install_property_for_key ( + "cal-use-system-timezone", "/apps/evolution/calendar/display/use_system_timezone"); - e_shell_settings_install_property ( - g_param_spec_int ( - "cal-week-start-day", - NULL, - NULL, - 0, /* Sunday */ - 6, /* Saturday */ - 0, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "cal-week-start-day", + e_shell_settings_install_property_for_key ( + "cal-week-start-day", "/apps/evolution/calendar/display/week_start_day"); - e_shell_settings_install_property ( - g_param_spec_int ( - "cal-work-day-end-hour", - NULL, - NULL, - G_MININT, - G_MAXINT, - 0, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "cal-work-day-end-hour", + e_shell_settings_install_property_for_key ( + "cal-work-day-end-hour", "/apps/evolution/calendar/display/day_end_hour"); - e_shell_settings_install_property ( - g_param_spec_int ( - "cal-work-day-end-minute", - NULL, - NULL, - G_MININT, - G_MAXINT, - 0, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "cal-work-day-end-minute", + e_shell_settings_install_property_for_key ( + "cal-work-day-end-minute", "/apps/evolution/calendar/display/day_end_minute"); - e_shell_settings_install_property ( - g_param_spec_int ( - "cal-work-day-start-hour", - NULL, - NULL, - G_MININT, - G_MAXINT, - 0, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "cal-work-day-start-hour", + e_shell_settings_install_property_for_key ( + "cal-work-day-start-hour", "/apps/evolution/calendar/display/day_start_hour"); - e_shell_settings_install_property ( - g_param_spec_int ( - "cal-work-day-start-minute", - NULL, - NULL, - G_MININT, - G_MAXINT, - 0, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "cal-work-day-start-minute", + e_shell_settings_install_property_for_key ( + "cal-work-day-start-minute", "/apps/evolution/calendar/display/day_start_minute"); - e_shell_settings_install_property ( - g_param_spec_int ( - "cal-working-days", - NULL, - NULL, - G_MININT, - G_MAXINT, - 0, - G_PARAM_READWRITE)); - - e_shell_settings_bind_to_gconf ( - shell_settings, "cal-working-days", + e_shell_settings_install_property_for_key ( + "cal-working-days", "/apps/evolution/calendar/display/working_days"); } -- cgit v1.2.3 From de85e3c7862100da10fe860aef2b651245a1fdbf Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Sat, 1 Aug 2009 07:29:41 -0400 Subject: Replace more "config" classes with property bindings. --- modules/calendar/e-cal-shell-content.c | 118 +---- modules/calendar/e-cal-shell-content.h | 4 +- modules/calendar/e-cal-shell-settings.c | 638 ++++++++++++++++++++++++++- modules/calendar/e-cal-shell-sidebar.c | 45 +- modules/calendar/e-cal-shell-sidebar.h | 2 +- modules/calendar/e-cal-shell-view-private.c | 92 ++-- modules/calendar/e-cal-shell-view-private.h | 3 - modules/calendar/e-memo-shell-content.c | 20 +- modules/calendar/e-task-shell-content.c | 21 +- modules/calendar/e-task-shell-view-actions.c | 6 +- modules/calendar/e-task-shell-view-private.c | 65 +-- modules/calendar/e-task-shell-view-private.h | 3 +- modules/calendar/e-task-shell-view.c | 70 +++ modules/calendar/e-task-shell-view.h | 5 + 14 files changed, 840 insertions(+), 252 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c index a688c27d0e..efc67af1fa 100644 --- a/modules/calendar/e-cal-shell-content.c +++ b/modules/calendar/e-cal-shell-content.c @@ -32,9 +32,7 @@ #include "calendar/gui/e-cal-list-view.h" #include "calendar/gui/e-cal-model-calendar.h" #include "calendar/gui/e-calendar-table.h" -#include "calendar/gui/e-calendar-table-config.h" #include "calendar/gui/e-calendar-view.h" -#include "calendar/gui/e-memo-table-config.h" #include "widgets/menus/gal-view-etable.h" @@ -51,9 +49,6 @@ struct _ECalShellContentPrivate { GtkWidget *task_table; GtkWidget *memo_table; - ECalendarTableConfig *task_table_config; - EMemoTableConfig *memo_table_config; - GalViewInstance *view_instance; guint paned_binding_id; @@ -74,19 +69,6 @@ typedef enum { static gpointer parent_class; static GType cal_shell_content_type; -static gboolean -transform_week_start_day (const GValue *src_value, - GValue *dst_value) -{ - gint v_int; - - /* Transform day numbering from 0 = Sunday to 0 = Monday. */ - v_int = g_value_get_int (src_value); - g_value_set_int (dst_value, (v_int + 6) % 7); - - return TRUE; -} - static void cal_shell_content_display_view_cb (ECalShellContent *cal_shell_content, GalView *gal_view) @@ -277,16 +259,6 @@ cal_shell_content_dispose (GObject *object) priv->memo_table = NULL; } - if (priv->task_table_config != NULL) { - g_object_unref (priv->task_table_config); - priv->task_table_config = NULL; - } - - if (priv->memo_table_config != NULL) { - g_object_unref (priv->memo_table_config); - priv->memo_table_config = NULL; - } - if (priv->view_instance != NULL) { g_object_unref (priv->view_instance); priv->view_instance = NULL; @@ -312,7 +284,6 @@ cal_shell_content_constructed (GObject *object) { ECalShellContentPrivate *priv; ECalendarView *calendar_view; - ECalModel *calendar_model; ECalModel *memo_model; ECalModel *task_model; EShell *shell; @@ -394,6 +365,10 @@ cal_shell_content_constructed (GObject *object) /* Add views in the order defined by GnomeCalendarViewType, such * that the notebook page number corresponds to the view type. */ + /* XXX GnomeCalendar is a widget, but we don't pack it. + * Maybe it should just be a GObject instead? */ + priv->calendar = gnome_calendar_new (shell_settings); + g_object_ref_sink (priv->calendar); calendar = GNOME_CALENDAR (priv->calendar); for (ii = 0; ii < GNOME_CAL_LAST_VIEW; ii++) { @@ -457,12 +432,6 @@ cal_shell_content_constructed (GObject *object) e_memo_table_load_state (E_MEMO_TABLE (widget), filename); g_free (filename); - /* Configuration managers for task and memo tables. */ - priv->task_table_config = e_calendar_table_config_new ( - E_CALENDAR_TABLE (priv->task_table)); - priv->memo_table_config = e_memo_table_config_new ( - E_MEMO_TABLE (priv->memo_table)); - /* Load the view instance. */ view_instance = e_shell_view_new_view_instance (shell_view, NULL); @@ -507,12 +476,6 @@ cal_shell_content_constructed (GObject *object) G_OBJECT (shell_settings), "cal-time-divisions", G_OBJECT (calendar_view), "mins-per-row"); - e_binding_new_full ( - G_OBJECT (shell_settings), "cal-week-start-day", - G_OBJECT (calendar_view), "week-start-day", - (EBindingTransform) transform_week_start_day, - (GDestroyNotify) NULL, NULL); - e_binding_new ( G_OBJECT (shell_settings), "cal-work-day-end-hour", G_OBJECT (calendar_view), "work-day-end-hour"); @@ -530,7 +493,7 @@ cal_shell_content_constructed (GObject *object) G_OBJECT (calendar_view), "work-day-start-minute"); e_binding_new ( - G_OBJECT (shell_settings), "cal-working-days", + G_OBJECT (shell_settings), "cal-working-days-bitset", G_OBJECT (calendar_view), "working-days"); /* Bind work week view properties to EShellSettings. */ @@ -554,12 +517,6 @@ cal_shell_content_constructed (GObject *object) G_OBJECT (shell_settings), "cal-time-divisions", G_OBJECT (calendar_view), "mins-per-row"); - e_binding_new_full ( - G_OBJECT (shell_settings), "cal-week-start-day", - G_OBJECT (calendar_view), "week-start-day", - (EBindingTransform) transform_week_start_day, - (GDestroyNotify) NULL, NULL); - e_binding_new ( G_OBJECT (shell_settings), "cal-work-day-end-hour", G_OBJECT (calendar_view), "work-day-end-hour"); @@ -593,12 +550,6 @@ cal_shell_content_constructed (GObject *object) G_OBJECT (shell_settings), "cal-show-event-end-times", G_OBJECT (calendar_view), "show-event-end-times"); - e_binding_new_full ( - G_OBJECT (shell_settings), "cal-week-start-day", - G_OBJECT (calendar_view), "week-start-day", - (EBindingTransform) transform_week_start_day, - (GDestroyNotify) NULL, NULL); - /* Bind month view properties to EShellSettings. */ view_type = GNOME_CAL_MONTH_VIEW; @@ -612,22 +563,6 @@ cal_shell_content_constructed (GObject *object) G_OBJECT (shell_settings), "cal-show-event-end-times", G_OBJECT (calendar_view), "show-event-end-times"); - e_binding_new_full ( - G_OBJECT (shell_settings), "cal-week-start-day", - G_OBJECT (calendar_view), "week-start-day", - (EBindingTransform) transform_week_start_day, - (GDestroyNotify) NULL, NULL); - - /* Bind calendar model properties to EShellSettings. - * Note, does not matter from which view we get the - * model, since it's shared across all of them. */ - - calendar_model = e_calendar_view_get_model (calendar_view); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-use-24-hour-format", - G_OBJECT (calendar_model), "use-24-hour-format"); - g_object_unref (memo_model); g_object_unref (task_model); } @@ -654,11 +589,6 @@ cal_shell_content_init (ECalShellContent *cal_shell_content) cal_shell_content->priv = E_CAL_SHELL_CONTENT_GET_PRIVATE (cal_shell_content); - /* XXX GnomeCalendar is a widget, but we don't pack it. - * Maybe it should just be a GObject instead? */ - cal_shell_content->priv->calendar = gnome_calendar_new (); - g_object_ref_sink (cal_shell_content->priv->calendar); - /* Postpone widget construction until we have a shell view. */ } @@ -699,15 +629,26 @@ e_cal_shell_content_new (EShellView *shell_view) "shell-view", shell_view, NULL); } +ECalModel * +e_cal_shell_content_get_model (ECalShellContent *cal_shell_content) +{ + GnomeCalendar *calendar; + + g_return_val_if_fail ( + E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL); + + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + + return gnome_calendar_get_calendar_model (calendar); +} + GnomeCalendar * e_cal_shell_content_get_calendar (ECalShellContent *cal_shell_content) { g_return_val_if_fail ( E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL); - /* FIXME */ - /*return GNOME_CALENDAR (cal_shell_content->priv->calendar);*/ - return NULL; + return GNOME_CALENDAR (cal_shell_content->priv->calendar); } EMemoTable * @@ -728,17 +669,6 @@ e_cal_shell_content_get_task_table (ECalShellContent *cal_shell_content) return E_CALENDAR_TABLE (cal_shell_content->priv->task_table); } -icaltimezone * -e_cal_shell_content_get_timezone (ECalShellContent *cal_shell_content) -{ - g_return_val_if_fail ( - E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL); - - /* FIXME */ - /*return cal_shell_content->priv->timezone;*/ - return NULL; -} - GalViewInstance * e_cal_shell_content_get_view_instance (ECalShellContent *cal_shell_content) { @@ -751,7 +681,6 @@ e_cal_shell_content_get_view_instance (ECalShellContent *cal_shell_content) void e_cal_shell_content_copy_clipboard (ECalShellContent *cal_shell_content) { -#if 0 GnomeCalendar *calendar; EMemoTable *memo_table; ECalendarTable *task_table; @@ -778,13 +707,11 @@ e_cal_shell_content_copy_clipboard (ECalShellContent *cal_shell_content) default: g_return_if_reached (); } -#endif } void e_cal_shell_content_cut_clipboard (ECalShellContent *cal_shell_content) { -#if 0 GnomeCalendar *calendar; EMemoTable *memo_table; ECalendarTable *task_table; @@ -811,13 +738,11 @@ e_cal_shell_content_cut_clipboard (ECalShellContent *cal_shell_content) default: g_return_if_reached (); } -#endif } void e_cal_shell_content_paste_clipboard (ECalShellContent *cal_shell_content) { -#if 0 GnomeCalendar *calendar; EMemoTable *memo_table; ECalendarTable *task_table; @@ -844,13 +769,11 @@ e_cal_shell_content_paste_clipboard (ECalShellContent *cal_shell_content) default: g_return_if_reached (); } -#endif } void e_cal_shell_content_delete_selection (ECalShellContent *cal_shell_content) { -#if 0 GnomeCalendar *calendar; EMemoTable *memo_table; ECalendarTable *task_table; @@ -877,13 +800,11 @@ e_cal_shell_content_delete_selection (ECalShellContent *cal_shell_content) default: g_return_if_reached (); } -#endif } void e_cal_shell_content_delete_selected_occurrence (ECalShellContent *cal_shell_content) { -#if 0 GnomeCalendar *calendar; FocusLocation focus; @@ -894,5 +815,4 @@ e_cal_shell_content_delete_selected_occurrence (ECalShellContent *cal_shell_cont if (focus == FOCUS_CALENDAR) gnome_calendar_delete_selected_occurrence (calendar); -#endif } diff --git a/modules/calendar/e-cal-shell-content.h b/modules/calendar/e-cal-shell-content.h index 44e13f733c..3db7d33260 100644 --- a/modules/calendar/e-cal-shell-content.h +++ b/modules/calendar/e-cal-shell-content.h @@ -81,14 +81,14 @@ GType e_cal_shell_content_get_type (void); void e_cal_shell_content_register_type (GTypeModule *type_module); GtkWidget * e_cal_shell_content_new (EShellView *shell_view); +ECalModel * e_cal_shell_content_get_model + (ECalShellContent *cal_shell_content); GnomeCalendar * e_cal_shell_content_get_calendar (ECalShellContent *cal_shell_content); EMemoTable * e_cal_shell_content_get_memo_table (ECalShellContent *cal_shell_content); ECalendarTable *e_cal_shell_content_get_task_table (ECalShellContent *cal_shell_content); -icaltimezone * e_cal_shell_content_get_timezone - (ECalShellContent *cal_shell_content); GalViewInstance * e_cal_shell_content_get_view_instance (ECalShellContent *cal_shell_content); diff --git a/modules/calendar/e-cal-shell-settings.c b/modules/calendar/e-cal-shell-settings.c index 39581a5181..dbb11ff0f9 100644 --- a/modules/calendar/e-cal-shell-settings.c +++ b/modules/calendar/e-cal-shell-settings.c @@ -22,6 +22,452 @@ #include "e-cal-shell-settings.h" #include +#include + +static gboolean +transform_string_to_icaltimezone (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + EShellSettings *shell_settings; + gboolean use_system_timezone; + const gchar *location = NULL; + icaltimezone *timezone = NULL; + + shell_settings = E_SHELL_SETTINGS (user_data); + + use_system_timezone = e_shell_settings_get_boolean ( + shell_settings, "cal-use-system-timezone"); + + if (use_system_timezone) + timezone = e_cal_util_get_system_timezone (); + else + location = g_value_get_string (src_value); + + if (location != NULL && *location != '\0') + timezone = icaltimezone_get_builtin_timezone (location); + + if (timezone == NULL) + timezone = icaltimezone_get_utc_timezone (); + + g_value_set_pointer (dst_value, timezone); + + return TRUE; +} + +static gboolean +transform_icaltimezone_to_string (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + const gchar *location = NULL; + icaltimezone *timezone; + + timezone = g_value_get_pointer (src_value); + + if (timezone != NULL) + location = icaltimezone_get_location (timezone); + + if (location == NULL) + location = "UTC"; + + g_value_set_string (dst_value, location); + + return TRUE; +} + +static gboolean +transform_weekdays_gconf_to_evolution (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + GDateWeekday weekday; + + /* XXX At some point, Evolution changed its weekday numbering + * from 0 = Sunday to 0 = Monday, but did not migrate the + * "week_start_day" key. Both enumerations are of course + * different from GDateWeekday. We should have saved the + * weekday as a string instead. */ + + /* This is purposefully verbose for better readability. */ + + /* GConf numbering */ + switch (g_value_get_int (src_value)) { + case 0: + weekday = G_DATE_SUNDAY; + break; + case 1: + weekday = G_DATE_MONDAY; + break; + case 2: + weekday = G_DATE_TUESDAY; + break; + case 3: + weekday = G_DATE_WEDNESDAY; + break; + case 4: + weekday = G_DATE_THURSDAY; + break; + case 5: + weekday = G_DATE_FRIDAY; + break; + case 6: + weekday = G_DATE_SATURDAY; + break; + default: + return FALSE; + } + + /* Evolution numbering */ + switch (weekday) { + case G_DATE_MONDAY: + g_value_set_int (dst_value, 0); + break; + case G_DATE_TUESDAY: + g_value_set_int (dst_value, 1); + break; + case G_DATE_WEDNESDAY: + g_value_set_int (dst_value, 2); + break; + case G_DATE_THURSDAY: + g_value_set_int (dst_value, 3); + break; + case G_DATE_FRIDAY: + g_value_set_int (dst_value, 4); + break; + case G_DATE_SATURDAY: + g_value_set_int (dst_value, 5); + break; + case G_DATE_SUNDAY: + g_value_set_int (dst_value, 6); + break; + default: + return FALSE; + } + + return TRUE; +} + +static gboolean +transform_weekdays_evolution_to_gconf (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + GDateWeekday weekday; + + /* XXX At some point, Evolution changed its weekday numbering + * from 0 = Sunday to 0 = Monday, but did not migrate the + * "week_start_day" key. Both enumerations are of course + * different from GDateWeekday. We should have saved the + * weekday as a string instead. */ + + /* This is purposefully verbose for better readability. */ + + /* GConf numbering */ + switch (g_value_get_int (src_value)) { + case 0: + weekday = G_DATE_MONDAY; + break; + case 1: + weekday = G_DATE_TUESDAY; + break; + case 2: + weekday = G_DATE_WEDNESDAY; + break; + case 3: + weekday = G_DATE_THURSDAY; + break; + case 4: + weekday = G_DATE_FRIDAY; + break; + case 5: + weekday = G_DATE_SATURDAY; + break; + case 6: + weekday = G_DATE_SUNDAY; + break; + default: + return FALSE; + } + + /* Evolution numbering */ + switch (weekday) { + case G_DATE_MONDAY: + g_value_set_int (dst_value, 1); + break; + case G_DATE_TUESDAY: + g_value_set_int (dst_value, 2); + break; + case G_DATE_WEDNESDAY: + g_value_set_int (dst_value, 3); + break; + case G_DATE_THURSDAY: + g_value_set_int (dst_value, 4); + break; + case G_DATE_FRIDAY: + g_value_set_int (dst_value, 5); + break; + case G_DATE_SATURDAY: + g_value_set_int (dst_value, 6); + break; + case G_DATE_SUNDAY: + g_value_set_int (dst_value, 0); + break; + default: + return FALSE; + } + + return TRUE; +} + +/* Working day flags */ +enum { + WORKING_DAY_SUNDAY = 1 << 0, + WORKING_DAY_MONDAY = 1 << 1, + WORKING_DAY_TUESDAY = 1 << 2, + WORKING_DAY_WEDNESDAY = 1 << 3, + WORKING_DAY_THURSDAY = 1 << 4, + WORKING_DAY_FRIDAY = 1 << 5, + WORKING_DAY_SATURDAY = 1 << 6 +}; + +static gboolean +transform_working_days_bitset_to_sunday (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + gint bitset; + gboolean working_day; + + bitset = g_value_get_int (src_value); + working_day = ((bitset & WORKING_DAY_SUNDAY) != 0); + g_value_set_boolean (dst_value, working_day); + + return TRUE; +} + +static gboolean +transform_working_days_sunday_to_bitset (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + EShellSettings *shell_settings; + gint bitset, bit; + + shell_settings = E_SHELL_SETTINGS (user_data); + + bitset = e_shell_settings_get_int ( + shell_settings, "cal-working-days-bitset"); + + bit = g_value_get_boolean (src_value) ? WORKING_DAY_SUNDAY : 0; + g_value_set_int (dst_value, (bitset & ~WORKING_DAY_SUNDAY) | bit); + + return TRUE; +} + +static gboolean +transform_working_days_bitset_to_monday (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + gint bitset; + gboolean working_day; + + bitset = g_value_get_int (src_value); + working_day = ((bitset & WORKING_DAY_MONDAY) != 0); + g_value_set_boolean (dst_value, working_day); + + return TRUE; +} + +static gboolean +transform_working_days_monday_to_bitset (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + EShellSettings *shell_settings; + gint bitset, bit; + + shell_settings = E_SHELL_SETTINGS (user_data); + + bitset = e_shell_settings_get_int ( + shell_settings, "cal-working-days-bitset"); + + bit = g_value_get_boolean (src_value) ? WORKING_DAY_MONDAY : 0; + g_value_set_int (dst_value, (bitset & ~WORKING_DAY_MONDAY) | bit); + + return TRUE; +} + +static gboolean +transform_working_days_bitset_to_tuesday (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + gint bitset; + gboolean working_day; + + bitset = g_value_get_int (src_value); + working_day = ((bitset & WORKING_DAY_TUESDAY) != 0); + g_value_set_boolean (dst_value, working_day); + + return TRUE; +} + +static gboolean +transform_working_days_tuesday_to_bitset (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + EShellSettings *shell_settings; + gint bitset, bit; + + shell_settings = E_SHELL_SETTINGS (user_data); + + bitset = e_shell_settings_get_int ( + shell_settings, "cal-working-days-bitset"); + + bit = g_value_get_boolean (src_value) ? WORKING_DAY_TUESDAY : 0; + g_value_set_int (dst_value, (bitset & ~WORKING_DAY_TUESDAY) | bit); + + return TRUE; +} + +static gboolean +transform_working_days_bitset_to_wednesday (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + gint bitset; + gboolean working_day; + + bitset = g_value_get_int (src_value); + working_day = ((bitset & WORKING_DAY_WEDNESDAY) != 0); + g_value_set_boolean (dst_value, working_day); + + return TRUE; +} + +static gboolean +transform_working_days_wednesday_to_bitset (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + EShellSettings *shell_settings; + gint bitset, bit; + + shell_settings = E_SHELL_SETTINGS (user_data); + + bitset = e_shell_settings_get_int ( + shell_settings, "cal-working-days-bitset"); + + bit = g_value_get_boolean (src_value) ? WORKING_DAY_WEDNESDAY : 0; + g_value_set_int (dst_value, (bitset & ~WORKING_DAY_WEDNESDAY) | bit); + + return TRUE; +} + +static gboolean +transform_working_days_bitset_to_thursday (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + gint bitset; + gboolean working_day; + + bitset = g_value_get_int (src_value); + working_day = ((bitset & WORKING_DAY_THURSDAY) != 0); + g_value_set_boolean (dst_value, working_day); + + return TRUE; +} + +static gboolean +transform_working_days_thursday_to_bitset (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + EShellSettings *shell_settings; + gint bitset, bit; + + shell_settings = E_SHELL_SETTINGS (user_data); + + bitset = e_shell_settings_get_int ( + shell_settings, "cal-working-days-bitset"); + + bit = g_value_get_boolean (src_value) ? WORKING_DAY_THURSDAY : 0; + g_value_set_int (dst_value, (bitset & ~WORKING_DAY_THURSDAY) | bit); + + return TRUE; +} + +static gboolean +transform_working_days_bitset_to_friday (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + gint bitset; + gboolean working_day; + + bitset = g_value_get_int (src_value); + working_day = ((bitset & WORKING_DAY_FRIDAY) != 0); + g_value_set_boolean (dst_value, working_day); + + return TRUE; +} + +static gboolean +transform_working_days_friday_to_bitset (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + EShellSettings *shell_settings; + gint bitset, bit; + + shell_settings = E_SHELL_SETTINGS (user_data); + + bitset = e_shell_settings_get_int ( + shell_settings, "cal-working-days-bitset"); + + bit = g_value_get_boolean (src_value) ? WORKING_DAY_FRIDAY : 0; + g_value_set_int (dst_value, (bitset & ~WORKING_DAY_FRIDAY) | bit); + + return TRUE; +} + +static gboolean +transform_working_days_bitset_to_saturday (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + gint bitset; + gboolean working_day; + + bitset = g_value_get_int (src_value); + working_day = ((bitset & WORKING_DAY_SATURDAY) != 0); + g_value_set_boolean (dst_value, working_day); + + return TRUE; +} + +static gboolean +transform_working_days_saturday_to_bitset (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + EShellSettings *shell_settings; + gint bitset, bit; + + shell_settings = E_SHELL_SETTINGS (user_data); + + bitset = e_shell_settings_get_int ( + shell_settings, "cal-working-days-bitset"); + + bit = g_value_get_boolean (src_value) ? WORKING_DAY_SATURDAY : 0; + g_value_set_int (dst_value, (bitset & ~WORKING_DAY_SATURDAY) | bit); + + return TRUE; +} void e_cal_shell_backend_init_settings (EShell *shell) @@ -34,6 +480,34 @@ e_cal_shell_backend_init_settings (EShell *shell) "cal-compress-weekend", "/apps/evolution/calendar/display/compress_weekend"); + e_shell_settings_install_property_for_key ( + "cal-confirm-delete", + "/apps/evolution/calendar/prompts/confirm_delete"); + + e_shell_settings_install_property_for_key ( + "cal-confirm-purge", + "/apps/evolution/calendar/prompts/confirm_purge"); + + e_shell_settings_install_property_for_key ( + "cal-date-navigator-show-week-numbers", + "/apps/evolution/calendar/date_navigator/show_week_numbers"); + + e_shell_settings_install_property_for_key ( + "cal-day-view-show-week-numbers", + "/apps/evolution/calendar/display/day_view_show_week_number"); + + e_shell_settings_install_property_for_key ( + "cal-hide-completed-tasks", + "/apps/evolution/calendar/tasks/hide_completed"); + + e_shell_settings_install_property_for_key ( + "cal-hide-completed-tasks-units", + "/apps/evolution/calendar/tasks/hide_completed_units"); + + e_shell_settings_install_property_for_key ( + "cal-hide-completed-tasks-value", + "/apps/evolution/calendar/tasks/hide_completed_value"); + e_shell_settings_install_property_for_key ( "cal-marcus-bains-day-view-color", "/apps/evolution/calendar/display/marcus_bains_color_dayview"); @@ -54,10 +528,23 @@ e_cal_shell_backend_init_settings (EShell *shell) "cal-show-event-end-times", "/apps/evolution/calendar/display/show_event_end"); + e_shell_settings_install_property_for_key ( + "cal-tasks-color-due-today", + "/apps/evolution/calendar/tasks/colors/due_today"); + + e_shell_settings_install_property_for_key ( + "cal-tasks-color-overdue", + "/apps/evolution/calendar/tasks/colors/overdue"); + e_shell_settings_install_property_for_key ( "cal-time-divisions", "/apps/evolution/calendar/display/time_divisions"); + /* Do not bind to this. Use "cal-timezone" instead. */ + e_shell_settings_install_property_for_key ( + "cal-timezone-string", + "/apps/evolution/calendar/display/timezone"); + e_shell_settings_install_property_for_key ( "cal-use-24-hour-format", "/apps/evolution/calendar/display/use_24hour_format"); @@ -66,8 +553,9 @@ e_cal_shell_backend_init_settings (EShell *shell) "cal-use-system-timezone", "/apps/evolution/calendar/display/use_system_timezone"); + /* Do not bind to this. Use "cal-week-start-day" instead. */ e_shell_settings_install_property_for_key ( - "cal-week-start-day", + "cal-week-start-day-gconf", "/apps/evolution/calendar/display/week_start_day"); e_shell_settings_install_property_for_key ( @@ -87,6 +575,152 @@ e_cal_shell_backend_init_settings (EShell *shell) "/apps/evolution/calendar/display/day_start_minute"); e_shell_settings_install_property_for_key ( - "cal-working-days", + "cal-working-days-bitset", "/apps/evolution/calendar/display/working_days"); + + /* These properties use transform functions to convert + * GConf values to forms more useful to Evolution. We + * have to use separate properties because GConfBridge + * does not support transform functions. Much of this + * is backward-compatibility cruft for poorly designed + * GConf schemas. */ + + e_shell_settings_install_property ( + g_param_spec_pointer ( + "cal-timezone", + NULL, + NULL, + G_PARAM_READWRITE)); + + e_mutual_binding_new_full ( + G_OBJECT (shell_settings), "cal-timezone-string", + G_OBJECT (shell_settings), "cal-timezone", + transform_string_to_icaltimezone, + transform_icaltimezone_to_string, + (GDestroyNotify) NULL, shell_settings); + + e_shell_settings_install_property ( + g_param_spec_int ( + "cal-week-start-day", + NULL, + NULL, + 0, /* Monday */ + 6, /* Sunday */ + 0, + G_PARAM_READWRITE)); + + e_mutual_binding_new_full ( + G_OBJECT (shell_settings), "cal-week-start-day-gconf", + G_OBJECT (shell_settings), "cal-week-start-day", + transform_weekdays_gconf_to_evolution, + transform_weekdays_evolution_to_gconf, + (GDestroyNotify) NULL, NULL); + + /* XXX These are my favorite. Storing a bit array in GConf + * instead of separate boolean keys. Brilliant move. */ + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "cal-working-days-sunday", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_mutual_binding_new_full ( + G_OBJECT (shell_settings), "cal-working-days-bitset", + G_OBJECT (shell_settings), "cal-working-days-sunday", + transform_working_days_bitset_to_sunday, + transform_working_days_sunday_to_bitset, + (GDestroyNotify) NULL, shell_settings); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "cal-working-days-monday", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE)); + + e_mutual_binding_new_full ( + G_OBJECT (shell_settings), "cal-working-days-bitset", + G_OBJECT (shell_settings), "cal-working-days-monday", + transform_working_days_bitset_to_monday, + transform_working_days_monday_to_bitset, + (GDestroyNotify) NULL, shell_settings); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "cal-working-days-tuesday", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE)); + + e_mutual_binding_new_full ( + G_OBJECT (shell_settings), "cal-working-days-bitset", + G_OBJECT (shell_settings), "cal-working-days-tuesday", + transform_working_days_bitset_to_tuesday, + transform_working_days_tuesday_to_bitset, + (GDestroyNotify) NULL, shell_settings); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "cal-working-days-wednesday", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE)); + + e_mutual_binding_new_full ( + G_OBJECT (shell_settings), "cal-working-days-bitset", + G_OBJECT (shell_settings), "cal-working-days-wednesday", + transform_working_days_bitset_to_wednesday, + transform_working_days_wednesday_to_bitset, + (GDestroyNotify) NULL, shell_settings); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "cal-working-days-thursday", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE)); + + e_mutual_binding_new_full ( + G_OBJECT (shell_settings), "cal-working-days-bitset", + G_OBJECT (shell_settings), "cal-working-days-thursday", + transform_working_days_bitset_to_thursday, + transform_working_days_thursday_to_bitset, + (GDestroyNotify) NULL, shell_settings); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "cal-working-days-friday", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE)); + + e_mutual_binding_new_full ( + G_OBJECT (shell_settings), "cal-working-days-bitset", + G_OBJECT (shell_settings), "cal-working-days-friday", + transform_working_days_bitset_to_friday, + transform_working_days_friday_to_bitset, + (GDestroyNotify) NULL, shell_settings); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "cal-working-days-saturday", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_mutual_binding_new_full ( + G_OBJECT (shell_settings), "cal-working-days-bitset", + G_OBJECT (shell_settings), "cal-working-days-saturday", + transform_working_days_bitset_to_saturday, + transform_working_days_saturday_to_bitset, + (GDestroyNotify) NULL, shell_settings); } diff --git a/modules/calendar/e-cal-shell-sidebar.c b/modules/calendar/e-cal-shell-sidebar.c index dc618e2dda..6fb35e1588 100644 --- a/modules/calendar/e-cal-shell-sidebar.c +++ b/modules/calendar/e-cal-shell-sidebar.c @@ -25,11 +25,11 @@ #include #include "e-util/e-error.h" +#include "e-util/e-binding.h" #include "e-util/gconf-bridge.h" #include "calendar/common/authentication.h" #include "calendar/gui/calendar-config.h" #include "calendar/gui/e-calendar-selector.h" -#include "calendar/gui/e-mini-calendar-config.h" #include "calendar/gui/misc.h" #include "e-cal-shell-backend.h" @@ -42,17 +42,15 @@ struct _ECalShellSidebarPrivate { GtkWidget *paned; GtkWidget *selector; - GtkWidget *mini_calendar; + GtkWidget *date_navigator; /* UID -> Client */ GHashTable *client_table; - - EMiniCalendarConfig *mini_calendar_config; }; enum { PROP_0, - PROP_MINI_CALENDAR, + PROP_DATE_NAVIGATOR, PROP_SELECTOR }; @@ -307,9 +305,9 @@ cal_shell_sidebar_get_property (GObject *object, GParamSpec *pspec) { switch (property_id) { - case PROP_MINI_CALENDAR: + case PROP_DATE_NAVIGATOR: g_value_set_object ( - value, e_cal_shell_sidebar_get_mini_calendar ( + value, e_cal_shell_sidebar_get_date_navigator ( E_CAL_SHELL_SIDEBAR (object))); return; @@ -340,18 +338,13 @@ cal_shell_sidebar_dispose (GObject *object) priv->selector = NULL; } - if (priv->mini_calendar != NULL) { - g_object_unref (priv->mini_calendar); - priv->mini_calendar = NULL; + if (priv->date_navigator != NULL) { + g_object_unref (priv->date_navigator); + priv->date_navigator = NULL; } g_hash_table_remove_all (priv->client_table); - if (priv->mini_calendar_config != NULL) { - g_object_unref (priv->mini_calendar_config); - priv->mini_calendar_config = NULL; - } - /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -443,11 +436,17 @@ cal_shell_sidebar_constructed (GObject *object) e_calendar_item_set_days_start_week_sel (calitem, 9); e_calendar_item_set_max_days_sel (calitem, 42); gtk_paned_add2 (GTK_PANED (container), widget); - priv->mini_calendar = g_object_ref (widget); + priv->date_navigator = g_object_ref (widget); gtk_widget_show (widget); - priv->mini_calendar_config = - e_mini_calendar_config_new (E_CALENDAR (widget)); + e_binding_new ( + G_OBJECT (shell_settings), + "cal-date-navigator-show-week-numbers", + G_OBJECT (calitem), "show-week-numbers"); + + e_binding_new ( + G_OBJECT (shell_settings), "cal-week-start-day", + G_OBJECT (calitem), "week-start-day"); /* Restore the selector state from the last session. */ @@ -547,10 +546,10 @@ cal_shell_sidebar_class_init (ECalShellSidebarClass *class) g_object_class_install_property ( object_class, - PROP_MINI_CALENDAR, + PROP_DATE_NAVIGATOR, g_param_spec_object ( - "mini-calendar", - _("Mini-Calendar Widget"), + "date-navigator", + _("Date Navigator Widget"), _("This widget displays a miniature calendar"), E_TYPE_CALENDAR, G_PARAM_READABLE)); @@ -665,12 +664,12 @@ e_cal_shell_sidebar_get_clients (ECalShellSidebar *cal_shell_sidebar) } ECalendar * -e_cal_shell_sidebar_get_mini_calendar (ECalShellSidebar *cal_shell_sidebar) +e_cal_shell_sidebar_get_date_navigator (ECalShellSidebar *cal_shell_sidebar) { g_return_val_if_fail ( E_IS_CAL_SHELL_SIDEBAR (cal_shell_sidebar), NULL); - return E_CALENDAR (cal_shell_sidebar->priv->mini_calendar); + return E_CALENDAR (cal_shell_sidebar->priv->date_navigator); } ESourceSelector * diff --git a/modules/calendar/e-cal-shell-sidebar.h b/modules/calendar/e-cal-shell-sidebar.h index c555537abf..3b7c0fd3b3 100644 --- a/modules/calendar/e-cal-shell-sidebar.h +++ b/modules/calendar/e-cal-shell-sidebar.h @@ -84,7 +84,7 @@ void e_cal_shell_sidebar_register_type GtkWidget * e_cal_shell_sidebar_new (EShellView *shell_view); GList * e_cal_shell_sidebar_get_clients (ECalShellSidebar *cal_shell_sidebar); -ECalendar * e_cal_shell_sidebar_get_mini_calendar +ECalendar * e_cal_shell_sidebar_get_date_navigator (ECalShellSidebar *cal_shell_sidebar); ESourceSelector * e_cal_shell_sidebar_get_selector diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c index c6d10292c3..44aad3db5e 100644 --- a/modules/calendar/e-cal-shell-view-private.c +++ b/modules/calendar/e-cal-shell-view-private.c @@ -58,9 +58,11 @@ cal_shell_view_get_current_time (ECalendarItem *calitem, ECalShellContent *cal_shell_content; struct icaltimetype tt; icaltimezone *timezone; + ECalModel *model; cal_shell_content = cal_shell_view->priv->cal_shell_content; - timezone = e_cal_shell_content_get_timezone (cal_shell_content); + model = e_cal_shell_content_get_model (cal_shell_content); + timezone = e_cal_model_get_timezone (model); tt = icaltime_from_timet_with_zone (time (NULL), FALSE, timezone); @@ -68,28 +70,28 @@ cal_shell_view_get_current_time (ECalendarItem *calitem, } static void -cal_shell_view_mini_calendar_date_range_changed_cb (ECalShellView *cal_shell_view, - ECalendarItem *calitem) +cal_shell_view_date_navigator_date_range_changed_cb (ECalShellView *cal_shell_view, + ECalendarItem *calitem) { /* FIXME gnome-calendar.c calls update_query() here. */ } static void -cal_shell_view_mini_calendar_selection_changed_cb (ECalShellView *cal_shell_view, - ECalendarItem *calitem) +cal_shell_view_date_navigator_selection_changed_cb (ECalShellView *cal_shell_view, + ECalendarItem *calitem) { /* FIXME */ } static void -cal_shell_view_mini_calendar_scroll_event_cb (ECalShellView *cal_shell_view, - GdkEventScroll *event, - ECalendar *mini_calendar) +cal_shell_view_date_navigator_scroll_event_cb (ECalShellView *cal_shell_view, + GdkEventScroll *event, + ECalendar *date_navigator) { ECalendarItem *calitem; GDate start_date, end_date; - calitem = mini_calendar->calitem; + calitem = date_navigator->calitem; if (!e_calendar_item_get_selection (calitem, &start_date, &end_date)) return; @@ -112,7 +114,7 @@ cal_shell_view_mini_calendar_scroll_event_cb (ECalShellView *cal_shell_view, * we could move this handler into ECalShellSidebar. */ e_calendar_item_set_selection (calitem, &start_date, &end_date); - cal_shell_view_mini_calendar_date_range_changed_cb ( + cal_shell_view_date_navigator_date_range_changed_cb ( cal_shell_view, calitem); } @@ -258,11 +260,11 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) EShellWindow *shell_window; EShellView *shell_view; GnomeCalendar *calendar; - ECalendar *mini_calendar; + ECalendar *date_navigator; EMemoTable *memo_table; ECalendarTable *task_table; ESourceSelector *selector; - guint id; + ECalModel *model; shell_view = E_SHELL_VIEW (cal_shell_view); shell_backend = e_shell_view_get_shell_backend (shell_view); @@ -279,16 +281,20 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) priv->cal_shell_sidebar = g_object_ref (shell_sidebar); cal_shell_content = E_CAL_SHELL_CONTENT (shell_content); + model = e_cal_shell_content_get_model (cal_shell_content); calendar = e_cal_shell_content_get_calendar (cal_shell_content); memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); task_table = e_cal_shell_content_get_task_table (cal_shell_content); cal_shell_sidebar = E_CAL_SHELL_SIDEBAR (shell_sidebar); selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar); - mini_calendar = e_cal_shell_sidebar_get_mini_calendar (cal_shell_sidebar); + date_navigator = e_cal_shell_sidebar_get_date_navigator (cal_shell_sidebar); + + /* Give GnomeCalendar a handle to the date navigator. */ + gnome_calendar_set_date_navigator (calendar, date_navigator); e_calendar_item_set_get_time_callback ( - mini_calendar->calitem, (ECalendarItemGetTimeCallback) + date_navigator->calitem, (ECalendarItemGetTimeCallback) cal_shell_view_get_current_time, cal_shell_view, NULL); /* KILL-BONOBO FIXME -- Need to connect to the "user-created" @@ -302,18 +308,23 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) #endif g_signal_connect_swapped ( - mini_calendar, "scroll-event", - G_CALLBACK (cal_shell_view_mini_calendar_scroll_event_cb), + model, "notify::timezone", + G_CALLBACK (e_cal_shell_view_update_timezone), cal_shell_view); g_signal_connect_swapped ( - mini_calendar->calitem, "date-range-changed", - G_CALLBACK (cal_shell_view_mini_calendar_date_range_changed_cb), + date_navigator, "scroll-event", + G_CALLBACK (cal_shell_view_date_navigator_scroll_event_cb), cal_shell_view); g_signal_connect_swapped ( - mini_calendar->calitem, "selection-changed", - G_CALLBACK (cal_shell_view_mini_calendar_selection_changed_cb), + date_navigator->calitem, "date-range-changed", + G_CALLBACK (cal_shell_view_date_navigator_date_range_changed_cb), + cal_shell_view); + + g_signal_connect_swapped ( + date_navigator->calitem, "selection-changed", + G_CALLBACK (cal_shell_view_date_navigator_selection_changed_cb), cal_shell_view); g_signal_connect_swapped ( @@ -355,14 +366,6 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) G_CALLBACK (e_cal_shell_view_update_search_filter), cal_shell_view); - /* Listen for configuration changes. */ - - /* Timezone */ - id = calendar_config_add_notification_timezone ( - cal_shell_view_config_timezone_changed_cb, cal_shell_view); - priv->notifications = g_list_prepend ( - priv->notifications, GUINT_TO_POINTER (id)); - e_cal_shell_view_actions_init (cal_shell_view); e_cal_shell_view_update_sidebar (cal_shell_view); e_cal_shell_view_update_search_filter (cal_shell_view); @@ -399,13 +402,6 @@ e_cal_shell_view_private_dispose (ECalShellView *cal_shell_view) g_object_unref (priv->taskpad_activity); priv->taskpad_activity = NULL; } - - for (iter = priv->notifications; iter != NULL; iter = iter->next) { - guint notification_id = GPOINTER_TO_UINT (iter->data); - calendar_config_remove_notification (notification_id); - } - g_list_free (priv->notifications); - priv->notifications = NULL; } void @@ -423,7 +419,7 @@ e_cal_shell_view_execute_search (ECalShellView *cal_shell_view) EShellWindow *shell_window; EShellContent *shell_content; GnomeCalendar *calendar; - ECalendar *mini_calendar; + ECalendar *date_navigator; GtkRadioAction *action; GString *string; FilterRule *rule; @@ -549,16 +545,16 @@ e_cal_shell_view_execute_search (ECalShellView *cal_shell_view) g_object_unref (rule); cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; - mini_calendar = e_cal_shell_sidebar_get_mini_calendar (cal_shell_sidebar); + date_navigator = e_cal_shell_sidebar_get_date_navigator (cal_shell_sidebar); if (range_search) { - /* Switch to list view and hide the mini calendar. */ + /* Switch to list view and hide the date navigator. */ action = GTK_RADIO_ACTION (ACTION (CALENDAR_VIEW_LIST)); gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); - gtk_widget_hide (GTK_WIDGET (mini_calendar)); + gtk_widget_hide (GTK_WIDGET (date_navigator)); } else { - /* Ensure the mini calendar is visible. */ - gtk_widget_show (GTK_WIDGET (mini_calendar)); + /* Ensure the date navigator is visible. */ + gtk_widget_show (GTK_WIDGET (date_navigator)); } /* Submit the query. */ @@ -789,24 +785,19 @@ e_cal_shell_view_update_sidebar (ECalShellView *cal_shell_view) void e_cal_shell_view_update_timezone (ECalShellView *cal_shell_view) { -#if 0 ECalShellContent *cal_shell_content; ECalShellSidebar *cal_shell_sidebar; - GnomeCalendarViewType view_type; - ECalendarView *calendar_view; icaltimezone *timezone; + ECalModel *model; GList *clients, *iter; cal_shell_content = cal_shell_view->priv->cal_shell_content; - view_type = e_cal_shell_content_get_current_view (cal_shell_content); - calendar_view = e_cal_shell_content_get_calendar_view ( - cal_shell_content, view_type); + model = e_cal_shell_content_get_model (cal_shell_content); + timezone = e_cal_model_get_timezone (model); cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; clients = e_cal_shell_sidebar_get_clients (cal_shell_sidebar); - timezone = calendar_config_get_icaltimezone (); - for (iter = clients; iter != NULL; iter = iter->next) { ECal *client = iter->data; @@ -814,8 +805,5 @@ e_cal_shell_view_update_timezone (ECalShellView *cal_shell_view) e_cal_set_default_timezone (client, timezone, NULL); } - e_calendar_view_set_icaltimezone (calendar_view, timezone); - g_list_free (clients); -#endif } diff --git a/modules/calendar/e-cal-shell-view-private.h b/modules/calendar/e-cal-shell-view-private.h index 8308e0bf7f..2e1388a50f 100644 --- a/modules/calendar/e-cal-shell-view-private.h +++ b/modules/calendar/e-cal-shell-view-private.h @@ -102,9 +102,6 @@ struct _ECalShellViewPrivate { EActivity *calendar_activity; EActivity *memopad_activity; EActivity *taskpad_activity; - - /* GConf notification IDs */ - GList *notifications; }; void e_cal_shell_view_private_init diff --git a/modules/calendar/e-memo-shell-content.c b/modules/calendar/e-memo-shell-content.c index ce020158ae..ece6eb694a 100644 --- a/modules/calendar/e-memo-shell-content.c +++ b/modules/calendar/e-memo-shell-content.c @@ -29,7 +29,6 @@ #include "calendar/gui/comp-util.h" #include "calendar/gui/e-cal-model-memos.h" #include "calendar/gui/e-memo-table.h" -#include "calendar/gui/e-memo-table-config.h" #include "widgets/menus/gal-view-etable.h" @@ -52,7 +51,6 @@ struct _EMemoShellContentPrivate { GtkWidget *memo_preview; ECalModel *memo_model; - EMemoTableConfig *table_config; GalViewInstance *view_instance; gchar *current_uid; @@ -328,11 +326,6 @@ memo_shell_content_dispose (GObject *object) priv->memo_model = NULL; } - if (priv->table_config != NULL) { - g_object_unref (priv->table_config); - priv->table_config = NULL; - } - if (priv->view_instance != NULL) { g_object_unref (priv->view_instance); priv->view_instance = NULL; @@ -359,7 +352,10 @@ static void memo_shell_content_constructed (GObject *object) { EMemoShellContentPrivate *priv; + EShell *shell; + EShellSettings *shell_settings; EShellContent *shell_content; + EShellWindow *shell_window; EShellView *shell_view; GalViewInstance *view_instance; ETable *table; @@ -375,6 +371,11 @@ memo_shell_content_constructed (GObject *object) shell_content = E_SHELL_CONTENT (object); shell_view = e_shell_content_get_shell_view (shell_content); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + priv->memo_model = e_cal_model_memos_new (shell_settings); /* Build content widgets. */ @@ -416,9 +417,6 @@ memo_shell_content_constructed (GObject *object) widget = E_MEMO_TABLE (priv->memo_table)->etable; table = e_table_scrolled_get_table (E_TABLE_SCROLLED (widget)); - priv->table_config = e_memo_table_config_new ( - E_MEMO_TABLE (priv->memo_table)); - e_table_set_state (table, E_MEMO_TABLE_DEFAULT_STATE); e_table_drag_source_set ( @@ -561,8 +559,6 @@ memo_shell_content_init (EMemoShellContent *memo_shell_content) memo_shell_content->priv = E_MEMO_SHELL_CONTENT_GET_PRIVATE (memo_shell_content); - memo_shell_content->priv->memo_model = e_cal_model_memos_new (); - /* Postpone widget construction until we have a shell view. */ } diff --git a/modules/calendar/e-task-shell-content.c b/modules/calendar/e-task-shell-content.c index 0177c6c3c3..8a4e0f1442 100644 --- a/modules/calendar/e-task-shell-content.c +++ b/modules/calendar/e-task-shell-content.c @@ -23,13 +23,13 @@ #include +#include "e-util/e-binding.h" #include "e-util/gconf-bridge.h" #include "calendar/gui/calendar-config.h" #include "calendar/gui/comp-util.h" #include "calendar/gui/e-cal-model-tasks.h" #include "calendar/gui/e-calendar-table.h" -#include "calendar/gui/e-calendar-table-config.h" #include "widgets/menus/gal-view-etable.h" @@ -53,7 +53,6 @@ struct _ETaskShellContentPrivate { GtkWidget *task_preview; ECalModel *task_model; - ECalendarTableConfig *table_config; GalViewInstance *view_instance; gchar *current_uid; @@ -327,11 +326,6 @@ task_shell_content_dispose (GObject *object) priv->task_model = NULL; } - if (priv->table_config != NULL) { - g_object_unref (priv->table_config); - priv->table_config = NULL; - } - if (priv->view_instance != NULL) { g_object_unref (priv->view_instance); priv->view_instance = NULL; @@ -358,7 +352,10 @@ static void task_shell_content_constructed (GObject *object) { ETaskShellContentPrivate *priv; + EShell *shell; + EShellSettings *shell_settings; EShellContent *shell_content; + EShellWindow *shell_window; EShellView *shell_view; GalViewInstance *view_instance; ETable *table; @@ -374,6 +371,11 @@ task_shell_content_constructed (GObject *object) shell_content = E_SHELL_CONTENT (object); shell_view = e_shell_content_get_shell_view (shell_content); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + priv->task_model = e_cal_model_tasks_new (shell_settings); /* Build content widgets. */ @@ -415,9 +417,6 @@ task_shell_content_constructed (GObject *object) widget = E_CALENDAR_TABLE (priv->task_table)->etable; table = e_table_scrolled_get_table (E_TABLE_SCROLLED (widget)); - priv->table_config = e_calendar_table_config_new ( - E_CALENDAR_TABLE (priv->task_table)); - e_table_set_state (table, E_CALENDAR_TABLE_DEFAULT_STATE); e_table_drag_source_set ( @@ -585,8 +584,6 @@ task_shell_content_init (ETaskShellContent *task_shell_content) task_shell_content->priv = E_TASK_SHELL_CONTENT_GET_PRIVATE (task_shell_content); - task_shell_content->priv->task_model = e_cal_model_tasks_new (); - /* Postpone widget construction until we have a shell view. */ } diff --git a/modules/calendar/e-task-shell-view-actions.c b/modules/calendar/e-task-shell-view-actions.c index 4deed9fdf0..eea80b77c6 100644 --- a/modules/calendar/e-task-shell-view-actions.c +++ b/modules/calendar/e-task-shell-view-actions.c @@ -579,7 +579,7 @@ action_task_purge_cb (GtkAction *action, shell_view = E_SHELL_VIEW (task_shell_view); shell_window = e_shell_view_get_shell_window (shell_view); - if (!calendar_config_get_confirm_purge ()) + if (!e_task_shell_view_get_confirm_purge (task_shell_view)) goto purge; /* XXX This needs reworked. The dialog looks like ass. */ @@ -608,11 +608,11 @@ action_task_purge_cb (GtkAction *action, return; if (active) - calendar_config_set_confirm_purge (FALSE); + e_task_shell_view_set_confirm_purge (task_shell_view, FALSE); purge: - /* FIXME */ + /* FIXME KILL-BONOBO */ ; } diff --git a/modules/calendar/e-task-shell-view-private.c b/modules/calendar/e-task-shell-view-private.c index be281f1c6e..1cbadcb53c 100644 --- a/modules/calendar/e-task-shell-view-private.c +++ b/modules/calendar/e-task-shell-view-private.c @@ -24,12 +24,8 @@ #include "widgets/menus/gal-view-factory-etable.h" static void -task_shell_view_config_hide_completed_tasks_changed_cb (GConfClient *client, - guint id, - GConfEntry *entry, - gpointer user_data) +task_shell_view_process_completed_tasks (ETaskShellView *task_shell_view) { - ETaskShellView *task_shell_view = user_data; ETaskShellContent *task_shell_content; ETaskShellSidebar *task_shell_sidebar; ECalendarTable *task_table; @@ -50,17 +46,6 @@ task_shell_view_config_hide_completed_tasks_changed_cb (GConfClient *client, g_list_free (clients); } -static void -task_shell_view_config_timezone_changed_cb (GConfClient *client, - guint id, - GConfEntry *entry, - gpointer user_data) -{ - ETaskShellView *task_shell_view = user_data; - - e_task_shell_view_update_timezone (task_shell_view); -} - static void task_shell_view_table_popup_event_cb (EShellView *shell_view, GdkEventButton *event) @@ -228,11 +213,13 @@ e_task_shell_view_private_constructed (ETaskShellView *task_shell_view) ETaskShellViewPrivate *priv = task_shell_view->priv; ETaskShellContent *task_shell_content; ETaskShellSidebar *task_shell_sidebar; - EShellView *shell_view; + EShell *shell; EShellBackend *shell_backend; EShellContent *shell_content; + EShellSettings *shell_settings; EShellSidebar *shell_sidebar; EShellWindow *shell_window; + EShellView *shell_view; ECalendarTable *task_table; ECalModel *model; ETable *table; @@ -245,6 +232,9 @@ e_task_shell_view_private_constructed (ETaskShellView *task_shell_view) shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + e_shell_window_add_action_group (shell_window, "tasks"); e_shell_window_add_action_group (shell_window, "tasks-filter"); @@ -261,6 +251,11 @@ e_task_shell_view_private_constructed (ETaskShellView *task_shell_view) task_shell_sidebar = E_TASK_SHELL_SIDEBAR (shell_sidebar); selector = e_task_shell_sidebar_get_selector (task_shell_sidebar); + g_signal_connect_swapped ( + model, "notify::timezone", + G_CALLBACK (e_task_shell_view_update_timezone), + task_shell_view); + g_signal_connect_swapped ( task_table, "open-component", G_CALLBACK (e_task_shell_view_open_task), @@ -338,28 +333,23 @@ e_task_shell_view_private_constructed (ETaskShellView *task_shell_view) /* Listen for configuration changes. */ - /* Timezone */ - id = calendar_config_add_notification_timezone ( - task_shell_view_config_timezone_changed_cb, task_shell_view); - priv->notifications = g_list_prepend ( - priv->notifications, GUINT_TO_POINTER (id)); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "cal-confirm-purge", + G_OBJECT (task_shell_view), "confirm-purge"); /* Hide Completed Tasks (enable/units/value) */ - id = calendar_config_add_notification_hide_completed_tasks ( - task_shell_view_config_hide_completed_tasks_changed_cb, + g_signal_connect_swapped ( + shell_settings, "notify::cal-hide-completed-tasks", + G_CALLBACK (task_shell_view_process_completed_tasks), task_shell_view); - priv->notifications = g_list_prepend ( - priv->notifications, GUINT_TO_POINTER (id)); - id = calendar_config_add_notification_hide_completed_tasks_units ( - task_shell_view_config_hide_completed_tasks_changed_cb, + g_signal_connect_swapped ( + shell_settings, "notify::cal-hide-completed-tasks-units", + G_CALLBACK (task_shell_view_process_completed_tasks), task_shell_view); - priv->notifications = g_list_prepend ( - priv->notifications, GUINT_TO_POINTER (id)); - id = calendar_config_add_notification_hide_completed_tasks_value ( - task_shell_view_config_hide_completed_tasks_changed_cb, + g_signal_connect_swapped ( + shell_settings, "notify::cal-hide-completed-tasks-value", + G_CALLBACK (task_shell_view_process_completed_tasks), task_shell_view); - priv->notifications = g_list_prepend ( - priv->notifications, GUINT_TO_POINTER (id)); e_task_shell_view_actions_init (task_shell_view); e_task_shell_view_update_sidebar (task_shell_view); @@ -390,13 +380,6 @@ e_task_shell_view_private_dispose (ETaskShellView *task_shell_view) g_source_remove (priv->update_timeout); priv->update_timeout = 0; } - - for (iter = priv->notifications; iter != NULL; iter = iter->next) { - guint notification_id = GPOINTER_TO_UINT (iter->data); - calendar_config_remove_notification (notification_id); - } - g_list_free (priv->notifications); - priv->notifications = NULL; } void diff --git a/modules/calendar/e-task-shell-view-private.h b/modules/calendar/e-task-shell-view-private.h index d3bb3cf086..50fa306696 100644 --- a/modules/calendar/e-task-shell-view-private.h +++ b/modules/calendar/e-task-shell-view-private.h @@ -102,8 +102,7 @@ struct _ETaskShellViewPrivate { EActivity *activity; guint update_timeout; - /* GConf notification IDs */ - GList *notifications; + guint confirm_purge : 1; }; void e_task_shell_view_private_init diff --git a/modules/calendar/e-task-shell-view.c b/modules/calendar/e-task-shell-view.c index ce1b53a43c..b1298eaa29 100644 --- a/modules/calendar/e-task-shell-view.c +++ b/modules/calendar/e-task-shell-view.c @@ -21,9 +21,48 @@ #include "e-task-shell-view-private.h" +enum { + PROP_0, + PROP_CONFIRM_PURGE +}; + static gpointer parent_class; static GType task_shell_view_type; +static void +task_shell_view_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CONFIRM_PURGE: + e_task_shell_view_set_confirm_purge ( + E_TASK_SHELL_VIEW (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +task_shell_view_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CONFIRM_PURGE: + g_value_set_boolean ( + value, e_task_shell_view_get_confirm_purge ( + E_TASK_SHELL_VIEW (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + static void task_shell_view_dispose (GObject *object) { @@ -201,6 +240,8 @@ task_shell_view_class_init (ETaskShellViewClass *class, g_type_class_add_private (class, sizeof (ETaskShellViewPrivate)); object_class = G_OBJECT_CLASS (class); + object_class->set_property = task_shell_view_set_property; + object_class->get_property = task_shell_view_get_property; object_class->dispose = task_shell_view_dispose; object_class->finalize = task_shell_view_finalize; object_class->constructed = task_shell_view_constructed; @@ -215,6 +256,16 @@ task_shell_view_class_init (ETaskShellViewClass *class, shell_view_class->new_shell_content = e_task_shell_content_new; shell_view_class->new_shell_sidebar = e_task_shell_sidebar_new; shell_view_class->update_actions = task_shell_view_update_actions; + + g_object_class_install_property ( + object_class, + PROP_CONFIRM_PURGE, + g_param_spec_boolean ( + "confirm-purge", + "Confirm Purge", + NULL, + TRUE, + G_PARAM_READWRITE)); } static void @@ -253,3 +304,22 @@ e_task_shell_view_register_type (GTypeModule *type_module) type_module, E_TYPE_SHELL_VIEW, "ETaskShellView", &type_info, 0); } + +gboolean +e_task_shell_view_get_confirm_purge (ETaskShellView *task_shell_view) +{ + g_return_val_if_fail (E_IS_TASK_SHELL_VIEW (task_shell_view), FALSE); + + return task_shell_view->priv->confirm_purge; +} + +void +e_task_shell_view_set_confirm_purge (ETaskShellView *task_shell_view, + gboolean confirm_purge) +{ + g_return_if_fail (E_IS_TASK_SHELL_VIEW (task_shell_view)); + + task_shell_view->priv->confirm_purge = confirm_purge; + + g_object_notify (G_OBJECT (task_shell_view), "confirm-purge"); +} diff --git a/modules/calendar/e-task-shell-view.h b/modules/calendar/e-task-shell-view.h index 8478e53cc2..853d90cac1 100644 --- a/modules/calendar/e-task-shell-view.h +++ b/modules/calendar/e-task-shell-view.h @@ -61,6 +61,11 @@ struct _ETaskShellViewClass { GType e_task_shell_view_get_type (void); void e_task_shell_view_register_type (GTypeModule *type_module); +gboolean e_task_shell_view_get_confirm_purge + (ETaskShellView *task_shell_view); +void e_task_shell_view_set_confirm_purge + (ETaskShellView *task_shell_view, + gboolean confirm_purge); G_END_DECLS -- cgit v1.2.3 From 609bd882de6cac5db7c65e00c2275f946f8f0c94 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Sat, 1 Aug 2009 07:29:41 -0400 Subject: Fix a typo. --- modules/calendar/e-cal-shell-content.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c index efc67af1fa..6e7269ecae 100644 --- a/modules/calendar/e-cal-shell-content.c +++ b/modules/calendar/e-cal-shell-content.c @@ -534,7 +534,7 @@ cal_shell_content_constructed (GObject *object) G_OBJECT (calendar_view), "work-day-start-minute"); e_binding_new ( - G_OBJECT (shell_settings), "cal-working-days", + G_OBJECT (shell_settings), "cal-working-days-bitset", G_OBJECT (calendar_view), "working-days"); /* Bind week view properties to EShellSettings. */ -- cgit v1.2.3 From 6a2b0904893199ceb5b291405721845fd17a08db Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Wed, 5 Aug 2009 21:24:53 -0400 Subject: More refactoring of settings management. --- modules/calendar/e-cal-shell-content.c | 108 ---------------------------- modules/calendar/e-cal-shell-view-private.c | 2 - 2 files changed, 110 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c index 6e7269ecae..7a8e659cbb 100644 --- a/modules/calendar/e-cal-shell-content.c +++ b/modules/calendar/e-cal-shell-content.c @@ -455,114 +455,6 @@ cal_shell_content_constructed (GObject *object) key = "/apps/evolution/calendar/display/vpane_position"; gconf_bridge_bind_property_delayed (bridge, key, object, "position"); - /* Bind day view properties to EShellSettings. */ - - view_type = GNOME_CAL_DAY_VIEW; - calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-marcus-bains-show-line", - G_OBJECT (calendar_view), "marcus-bains-show-line"); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-marcus-bains-day-view-color", - G_OBJECT (calendar_view), "marcus-bains-day-view-color"); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-marcus-bains-time-bar-color", - G_OBJECT (calendar_view), "marcus-bains-time-bar-color"); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-time-divisions", - G_OBJECT (calendar_view), "mins-per-row"); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-work-day-end-hour", - G_OBJECT (calendar_view), "work-day-end-hour"); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-work-day-end-minute", - G_OBJECT (calendar_view), "work-day-end-minute"); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-work-day-start-hour", - G_OBJECT (calendar_view), "work-day-start-hour"); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-work-day-start-minute", - G_OBJECT (calendar_view), "work-day-start-minute"); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-working-days-bitset", - G_OBJECT (calendar_view), "working-days"); - - /* Bind work week view properties to EShellSettings. */ - - view_type = GNOME_CAL_WORK_WEEK_VIEW; - calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-marcus-bains-show-line", - G_OBJECT (calendar_view), "marcus-bains-show-line"); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-marcus-bains-day-view-color", - G_OBJECT (calendar_view), "marcus-bains-day-view-color"); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-marcus-bains-time-bar-color", - G_OBJECT (calendar_view), "marcus-bains-time-bar-color"); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-time-divisions", - G_OBJECT (calendar_view), "mins-per-row"); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-work-day-end-hour", - G_OBJECT (calendar_view), "work-day-end-hour"); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-work-day-end-minute", - G_OBJECT (calendar_view), "work-day-end-minute"); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-work-day-start-hour", - G_OBJECT (calendar_view), "work-day-start-hour"); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-work-day-start-minute", - G_OBJECT (calendar_view), "work-day-start-minute"); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-working-days-bitset", - G_OBJECT (calendar_view), "working-days"); - - /* Bind week view properties to EShellSettings. */ - - view_type = GNOME_CAL_WEEK_VIEW; - calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-compress-weekend", - G_OBJECT (calendar_view), "compress-weekend"); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-show-event-end-times", - G_OBJECT (calendar_view), "show-event-end-times"); - - /* Bind month view properties to EShellSettings. */ - - view_type = GNOME_CAL_MONTH_VIEW; - calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-compress-weekend", - G_OBJECT (calendar_view), "compress-weekend"); - - e_binding_new ( - G_OBJECT (shell_settings), "cal-show-event-end-times", - G_OBJECT (calendar_view), "show-event-end-times"); - g_object_unref (memo_model); g_object_unref (task_model); } diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c index 44aad3db5e..49c07ca70f 100644 --- a/modules/calendar/e-cal-shell-view-private.c +++ b/modules/calendar/e-cal-shell-view-private.c @@ -300,12 +300,10 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) /* KILL-BONOBO FIXME -- Need to connect to the "user-created" * signal for each ECalendarView. */ -#if 0 /* KILL-BONOBO */ g_signal_connect_swapped ( calendar, "dates-shown-changed", G_CALLBACK (e_cal_shell_view_update_sidebar), cal_shell_view); -#endif g_signal_connect_swapped ( model, "notify::timezone", -- cgit v1.2.3 From 3b0699fc304d0f4aecb261d19869de221f5d6abf Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Fri, 7 Aug 2009 21:43:09 -0400 Subject: More refactoring of settings management. --- modules/calendar/e-cal-shell-settings.c | 18 ++++++---- modules/calendar/e-cal-shell-sidebar.c | 3 +- modules/calendar/e-memo-shell-content.c | 17 ++++++---- modules/calendar/e-memo-shell-sidebar.c | 50 +++++++++------------------- modules/calendar/e-memo-shell-sidebar.h | 2 ++ modules/calendar/e-memo-shell-view-private.c | 37 ++++++++++++++++++++ modules/calendar/e-memo-shell-view-private.h | 2 ++ modules/calendar/e-task-shell-content.c | 8 +++-- modules/calendar/e-task-shell-view-private.c | 5 +-- 9 files changed, 87 insertions(+), 55 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-settings.c b/modules/calendar/e-cal-shell-settings.c index dbb11ff0f9..4d75bae4e9 100644 --- a/modules/calendar/e-cal-shell-settings.c +++ b/modules/calendar/e-cal-shell-settings.c @@ -488,14 +488,14 @@ e_cal_shell_backend_init_settings (EShell *shell) "cal-confirm-purge", "/apps/evolution/calendar/prompts/confirm_purge"); - e_shell_settings_install_property_for_key ( - "cal-date-navigator-show-week-numbers", - "/apps/evolution/calendar/date_navigator/show_week_numbers"); - e_shell_settings_install_property_for_key ( "cal-day-view-show-week-numbers", "/apps/evolution/calendar/display/day_view_show_week_number"); + e_shell_settings_install_property_for_key ( + "cal-free-busy-template", + "/apps/evolution/calendar/publish/template"); + e_shell_settings_install_property_for_key ( "cal-hide-completed-tasks", "/apps/evolution/calendar/tasks/hide_completed"); @@ -528,6 +528,10 @@ e_cal_shell_backend_init_settings (EShell *shell) "cal-show-event-end-times", "/apps/evolution/calendar/display/show_event_end"); + e_shell_settings_install_property_for_key ( + "cal-show-week-numbers", + "/apps/evolution/calendar/date_navigator/show_week_numbers"); + e_shell_settings_install_property_for_key ( "cal-tasks-color-due-today", "/apps/evolution/calendar/tasks/colors/due_today"); @@ -597,7 +601,8 @@ e_cal_shell_backend_init_settings (EShell *shell) G_OBJECT (shell_settings), "cal-timezone", transform_string_to_icaltimezone, transform_icaltimezone_to_string, - (GDestroyNotify) NULL, shell_settings); + (GDestroyNotify) g_object_unref, + g_object_ref (shell_settings)); e_shell_settings_install_property ( g_param_spec_int ( @@ -722,5 +727,6 @@ e_cal_shell_backend_init_settings (EShell *shell) G_OBJECT (shell_settings), "cal-working-days-saturday", transform_working_days_bitset_to_saturday, transform_working_days_saturday_to_bitset, - (GDestroyNotify) NULL, shell_settings); + (GDestroyNotify) g_object_unref, + g_object_ref (shell_settings)); } diff --git a/modules/calendar/e-cal-shell-sidebar.c b/modules/calendar/e-cal-shell-sidebar.c index 6fb35e1588..28f96e553d 100644 --- a/modules/calendar/e-cal-shell-sidebar.c +++ b/modules/calendar/e-cal-shell-sidebar.c @@ -440,8 +440,7 @@ cal_shell_sidebar_constructed (GObject *object) gtk_widget_show (widget); e_binding_new ( - G_OBJECT (shell_settings), - "cal-date-navigator-show-week-numbers", + G_OBJECT (shell_settings), "cal-show-week-numbers", G_OBJECT (calitem), "show-week-numbers"); e_binding_new ( diff --git a/modules/calendar/e-memo-shell-content.c b/modules/calendar/e-memo-shell-content.c index ece6eb694a..3a7ee78718 100644 --- a/modules/calendar/e-memo-shell-content.c +++ b/modules/calendar/e-memo-shell-content.c @@ -25,7 +25,6 @@ #include "e-util/gconf-bridge.h" -#include "calendar/gui/calendar-config.h" #include "calendar/gui/comp-util.h" #include "calendar/gui/e-cal-model-memos.h" #include "calendar/gui/e-memo-table.h" @@ -353,11 +352,12 @@ memo_shell_content_constructed (GObject *object) { EMemoShellContentPrivate *priv; EShell *shell; + EShellView *shell_view; EShellSettings *shell_settings; + EShellBackend *shell_backend; EShellContent *shell_content; - EShellWindow *shell_window; - EShellView *shell_view; GalViewInstance *view_instance; + icaltimezone *timezone; ETable *table; GConfBridge *bridge; GtkWidget *container; @@ -371,12 +371,16 @@ memo_shell_content_constructed (GObject *object) shell_content = E_SHELL_CONTENT (object); shell_view = e_shell_content_get_shell_view (shell_content); - shell_window = e_shell_view_get_shell_window (shell_view); - shell = e_shell_window_get_shell (shell_window); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + shell = e_shell_backend_get_shell (shell_backend); shell_settings = e_shell_get_shell_settings (shell); priv->memo_model = e_cal_model_memos_new (shell_settings); + timezone = e_shell_settings_get_pointer ( + shell_settings, "cal-timezone"); + /* Build content widgets. */ container = GTK_WIDGET (object); @@ -406,8 +410,7 @@ memo_shell_content_constructed (GObject *object) widget = e_cal_component_preview_new (); e_cal_component_preview_set_default_timezone ( - E_CAL_COMPONENT_PREVIEW (widget), - calendar_config_get_icaltimezone ()); + E_CAL_COMPONENT_PREVIEW (widget), timezone); gtk_container_add (GTK_CONTAINER (container), widget); priv->memo_preview = g_object_ref (widget); gtk_widget_show (widget); diff --git a/modules/calendar/e-memo-shell-sidebar.c b/modules/calendar/e-memo-shell-sidebar.c index ca5d05c40b..0962a8a20d 100644 --- a/modules/calendar/e-memo-shell-sidebar.c +++ b/modules/calendar/e-memo-shell-sidebar.c @@ -25,6 +25,7 @@ #include #include +#include "e-util/e-binding.h" #include "e-util/e-error.h" #include "e-util/e-util.h" #include "calendar/common/authentication.h" @@ -41,6 +42,7 @@ struct _EMemoShellSidebarPrivate { GtkWidget *selector; + icaltimezone *timezone; /* UID -> Client */ GHashTable *client_table; @@ -89,33 +91,6 @@ memo_shell_sidebar_emit_status_message (EMemoShellSidebar *memo_shell_sidebar, g_signal_emit (memo_shell_sidebar, signal_id, 0, status_message, -1.0); } -static void -memo_shell_sidebar_update_timezone (EMemoShellSidebar *memo_shell_sidebar) -{ - GHashTable *client_table; - icaltimezone *zone; - GList *values; - - zone = calendar_config_get_icaltimezone (); - client_table = memo_shell_sidebar->priv->client_table; - values = g_hash_table_get_values (client_table); - - while (values != NULL) { - ECal *client = values->data; - - if (e_cal_get_load_state (client) == E_CAL_LOAD_LOADED) - e_cal_set_default_timezone (client, zone, NULL); - - values = g_list_delete_link (values, values); - } - - /* XXX Need to call e_cal_component_preview_set_default_timezone() - * here but the sidebar is not really supposed to access content - * stuff. I guess we could emit an "update-timezone" signal - * here, but that feels wrong. Maybe this whole thing should - * be in EMemoShellView instead. */ -} - static void memo_shell_sidebar_backend_died_cb (EMemoShellSidebar *memo_shell_sidebar, ECal *client) @@ -482,13 +457,6 @@ memo_shell_sidebar_check_state (EShellSidebar *shell_sidebar) return state; } -static void -memo_shell_sidebar_client_added (EMemoShellSidebar *memo_shell_sidebar, - ECal *client) -{ - memo_shell_sidebar_update_timezone (memo_shell_sidebar); -} - static void memo_shell_sidebar_client_removed (EMemoShellSidebar *memo_shell_sidebar, ECal *client) @@ -532,7 +500,6 @@ memo_shell_sidebar_class_init (EMemoShellSidebarClass *class) shell_sidebar_class = E_SHELL_SIDEBAR_CLASS (class); shell_sidebar_class->check_state = memo_shell_sidebar_check_state; - class->client_added = memo_shell_sidebar_client_added; class->client_removed = memo_shell_sidebar_client_removed; g_object_class_install_property ( @@ -632,6 +599,19 @@ e_memo_shell_sidebar_new (EShellView *shell_view) "shell-view", shell_view, NULL); } +GList * +e_memo_shell_sidebar_get_clients (EMemoShellSidebar *memo_shell_sidebar) +{ + GHashTable *client_table; + + g_return_val_if_fail ( + E_IS_MEMO_SHELL_SIDEBAR (memo_shell_sidebar), NULL); + + client_table = memo_shell_sidebar->priv->client_table; + + return g_hash_table_get_values (client_table); +} + ESourceSelector * e_memo_shell_sidebar_get_selector (EMemoShellSidebar *memo_shell_sidebar) { diff --git a/modules/calendar/e-memo-shell-sidebar.h b/modules/calendar/e-memo-shell-sidebar.h index 665c8f218a..068d7436bc 100644 --- a/modules/calendar/e-memo-shell-sidebar.h +++ b/modules/calendar/e-memo-shell-sidebar.h @@ -80,6 +80,8 @@ GType e_memo_shell_sidebar_get_type (void); void e_memo_shell_sidebar_register_type (GTypeModule *type_module); GtkWidget * e_memo_shell_sidebar_new(EShellView *shell_view); +GList * e_memo_shell_sidebar_get_clients + (EMemoShellSidebar *memo_shell_sidebar); ESourceSelector * e_memo_shell_sidebar_get_selector (EMemoShellSidebar *memo_shell_sidebar); diff --git a/modules/calendar/e-memo-shell-view-private.c b/modules/calendar/e-memo-shell-view-private.c index 4953a388d3..da321d5c19 100644 --- a/modules/calendar/e-memo-shell-view-private.c +++ b/modules/calendar/e-memo-shell-view-private.c @@ -67,6 +67,7 @@ memo_shell_view_selector_client_added_cb (EMemoShellView *memo_shell_view, model = e_memo_table_get_model (memo_table); e_cal_model_add_client (model, client); + e_memo_shell_view_update_timezone (memo_shell_view); } static void @@ -197,6 +198,11 @@ e_memo_shell_view_private_constructed (EMemoShellView *memo_shell_view) memo_shell_sidebar = E_MEMO_SHELL_SIDEBAR (shell_sidebar); selector = e_memo_shell_sidebar_get_selector (memo_shell_sidebar); + g_signal_connect_swapped ( + model, "notify::timezone", + G_CALLBACK (e_memo_shell_view_update_timezone), + memo_shell_view); + g_signal_connect_swapped ( memo_table, "open-component", G_CALLBACK (e_memo_shell_view_open_memo), @@ -269,6 +275,7 @@ e_memo_shell_view_private_constructed (EMemoShellView *memo_shell_view) e_memo_shell_view_actions_init (memo_shell_view); e_memo_shell_view_update_sidebar (memo_shell_view); e_memo_shell_view_update_search_filter (memo_shell_view); + e_memo_shell_view_update_timezone (memo_shell_view); e_memo_shell_view_execute_search (memo_shell_view); } @@ -522,3 +529,33 @@ e_memo_shell_view_update_sidebar (EMemoShellView *memo_shell_view) g_string_free (string, TRUE); } + +void +e_memo_shell_view_update_timezone (EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + EMemoShellSidebar *memo_shell_sidebar; + ECalComponentPreview *memo_preview; + icaltimezone *timezone; + ECalModel *model; + GList *clients, *iter; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + memo_preview = e_memo_shell_content_get_memo_preview (memo_shell_content); + model = e_memo_shell_content_get_memo_model (memo_shell_content); + timezone = e_cal_model_get_timezone (model); + + memo_shell_sidebar = memo_shell_view->priv->memo_shell_sidebar; + clients = e_memo_shell_sidebar_get_clients (memo_shell_sidebar); + + for (iter = clients; iter != NULL; iter = iter->next) { + ECal *client = iter->data; + + if (e_cal_get_load_state (client) == E_CAL_LOAD_LOADED) + e_cal_set_default_timezone (client, timezone, NULL); + } + + e_cal_component_preview_set_default_timezone (memo_preview, timezone); + + g_list_free (clients); +} diff --git a/modules/calendar/e-memo-shell-view-private.h b/modules/calendar/e-memo-shell-view-private.h index c41eaed7c0..c7ece91f68 100644 --- a/modules/calendar/e-memo-shell-view-private.h +++ b/modules/calendar/e-memo-shell-view-private.h @@ -120,6 +120,8 @@ void e_memo_shell_view_update_sidebar (EMemoShellView *memo_shell_view); void e_memo_shell_view_update_search_filter (EMemoShellView *memo_shell_view); +void e_memo_shell_view_update_timezone + (EMemoShellView *memo_shell_view); G_END_DECLS diff --git a/modules/calendar/e-task-shell-content.c b/modules/calendar/e-task-shell-content.c index 8a4e0f1442..88e5e4d856 100644 --- a/modules/calendar/e-task-shell-content.c +++ b/modules/calendar/e-task-shell-content.c @@ -26,7 +26,6 @@ #include "e-util/e-binding.h" #include "e-util/gconf-bridge.h" -#include "calendar/gui/calendar-config.h" #include "calendar/gui/comp-util.h" #include "calendar/gui/e-cal-model-tasks.h" #include "calendar/gui/e-calendar-table.h" @@ -358,6 +357,7 @@ task_shell_content_constructed (GObject *object) EShellWindow *shell_window; EShellView *shell_view; GalViewInstance *view_instance; + icaltimezone *timezone; ETable *table; GConfBridge *bridge; GtkWidget *container; @@ -377,6 +377,9 @@ task_shell_content_constructed (GObject *object) priv->task_model = e_cal_model_tasks_new (shell_settings); + timezone = e_shell_settings_get_pointer ( + shell_settings, "cal-timezone"); + /* Build content widgets. */ container = GTK_WIDGET (object); @@ -406,8 +409,7 @@ task_shell_content_constructed (GObject *object) widget = e_cal_component_preview_new (); e_cal_component_preview_set_default_timezone ( - E_CAL_COMPONENT_PREVIEW (widget), - calendar_config_get_icaltimezone ()); + E_CAL_COMPONENT_PREVIEW (widget), timezone); gtk_container_add (GTK_CONTAINER (container), widget); priv->task_preview = g_object_ref (widget); gtk_widget_show (widget); diff --git a/modules/calendar/e-task-shell-view-private.c b/modules/calendar/e-task-shell-view-private.c index 1cbadcb53c..38c5ab6033 100644 --- a/modules/calendar/e-task-shell-view-private.c +++ b/modules/calendar/e-task-shell-view-private.c @@ -704,16 +704,17 @@ e_task_shell_view_update_timezone (ETaskShellView *task_shell_view) ETaskShellSidebar *task_shell_sidebar; ECalComponentPreview *task_preview; icaltimezone *timezone; + ECalModel *model; GList *clients, *iter; task_shell_content = task_shell_view->priv->task_shell_content; task_preview = e_task_shell_content_get_task_preview (task_shell_content); + model = e_task_shell_content_get_task_model (task_shell_content); + timezone = e_cal_model_get_timezone (model); task_shell_sidebar = task_shell_view->priv->task_shell_sidebar; clients = e_task_shell_sidebar_get_clients (task_shell_sidebar); - timezone = calendar_config_get_icaltimezone (); - for (iter = clients; iter != NULL; iter = iter->next) { ECal *client = iter->data; -- cgit v1.2.3 From 5e5e1de764de6b705c12275dc652b1a36ba98fdd Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Mon, 27 Jul 2009 17:34:13 +0200 Subject: Bug #420513 - Be able to notify about meeting only new attendees --- modules/calendar/e-cal-shell-view-memopad.c | 2 +- modules/calendar/e-cal-shell-view-taskpad.c | 2 +- modules/calendar/e-memo-shell-view-actions.c | 2 +- modules/calendar/e-task-shell-view-actions.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-view-memopad.c b/modules/calendar/e-cal-shell-view-memopad.c index ecee72d8b5..1c4e863345 100644 --- a/modules/calendar/e-cal-shell-view-memopad.c +++ b/modules/calendar/e-cal-shell-view-memopad.c @@ -104,7 +104,7 @@ action_calendar_memopad_forward_cb (GtkAction *action, e_cal_component_set_icalcomponent (comp, clone); itip_send_comp ( E_CAL_COMPONENT_METHOD_PUBLISH, comp, - comp_data->client, NULL, NULL, NULL, TRUE); + comp_data->client, NULL, NULL, NULL, TRUE, FALSE); g_object_unref (comp); } diff --git a/modules/calendar/e-cal-shell-view-taskpad.c b/modules/calendar/e-cal-shell-view-taskpad.c index bdd136b6f7..965ec47c49 100644 --- a/modules/calendar/e-cal-shell-view-taskpad.c +++ b/modules/calendar/e-cal-shell-view-taskpad.c @@ -127,7 +127,7 @@ action_calendar_taskpad_forward_cb (GtkAction *action, e_cal_component_set_icalcomponent (comp, clone); itip_send_comp ( E_CAL_COMPONENT_METHOD_PUBLISH, comp, - comp_data->client, NULL, NULL, NULL, TRUE); + comp_data->client, NULL, NULL, NULL, TRUE, FALSE); g_object_unref (comp); } diff --git a/modules/calendar/e-memo-shell-view-actions.c b/modules/calendar/e-memo-shell-view-actions.c index 1736606abe..2d6713a7a8 100644 --- a/modules/calendar/e-memo-shell-view-actions.c +++ b/modules/calendar/e-memo-shell-view-actions.c @@ -125,7 +125,7 @@ action_memo_forward_cb (GtkAction *action, e_cal_component_set_icalcomponent (comp, clone); itip_send_comp ( E_CAL_COMPONENT_METHOD_PUBLISH, comp, - comp_data->client, NULL, NULL, NULL, TRUE); + comp_data->client, NULL, NULL, NULL, TRUE, FALSE); g_object_unref (comp); } diff --git a/modules/calendar/e-task-shell-view-actions.c b/modules/calendar/e-task-shell-view-actions.c index eea80b77c6..d1354026cb 100644 --- a/modules/calendar/e-task-shell-view-actions.c +++ b/modules/calendar/e-task-shell-view-actions.c @@ -178,7 +178,7 @@ action_task_forward_cb (GtkAction *action, e_cal_component_set_icalcomponent (comp, clone); itip_send_comp ( E_CAL_COMPONENT_METHOD_PUBLISH, comp, - comp_data->client, NULL, NULL, NULL, TRUE); + comp_data->client, NULL, NULL, NULL, TRUE, FALSE); g_object_unref (comp); } -- cgit v1.2.3 From 741d49c900ecc01002513060826b43dc26d4e55d Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Mon, 27 Jul 2009 17:43:02 +0200 Subject: Bug #203853 - Cut/Copy key bindings don't work in day and week views --- modules/calendar/e-cal-shell-content.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c index 7a8e659cbb..4409c1fc08 100644 --- a/modules/calendar/e-cal-shell-content.c +++ b/modules/calendar/e-cal-shell-content.c @@ -177,6 +177,9 @@ cal_shell_content_get_focus_location (ECalShellContent *cal_shell_content) if (GNOME_CANVAS (day_view->main_canvas)->focused_item != NULL) return FOCUS_CALENDAR; + if (GTK_WIDGET_HAS_FOCUS (day_view)) + return FOCUS_CALENDAR; + } else if (E_IS_WEEK_VIEW (calendar_view)) { EWeekView *week_view = E_WEEK_VIEW (calendar_view); @@ -186,12 +189,18 @@ cal_shell_content_get_focus_location (ECalShellContent *cal_shell_content) if (GNOME_CANVAS (week_view->main_canvas)->focused_item != NULL) return FOCUS_CALENDAR; + if (GTK_WIDGET_HAS_FOCUS (week_view)) + return FOCUS_CALENDAR; + } else if (E_IS_CAL_LIST_VIEW (calendar_view)) { ECalListView *list_view = E_CAL_LIST_VIEW (widget); table = e_table_scrolled_get_table (list_view->table_scrolled); if (GTK_WIDGET_HAS_FOCUS (table)) return FOCUS_CALENDAR; + + if (GTK_WIDGET_HAS_FOCUS (list_view)) + return FOCUS_CALENDAR; } return FOCUS_OTHER; -- cgit v1.2.3 From b5a2e47cb53aa92be37b469d3d9d625ea8477416 Mon Sep 17 00:00:00 2001 From: Srinivasa Ragavan Date: Fri, 7 Aug 2009 09:02:32 +0530 Subject: Allow calendar to be written as a external app and split the huge .so to a share private lib and component lib. --- modules/calendar/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules/calendar') diff --git a/modules/calendar/Makefile.am b/modules/calendar/Makefile.am index fa63bf53e4..8f771167d9 100644 --- a/modules/calendar/Makefile.am +++ b/modules/calendar/Makefile.am @@ -62,7 +62,7 @@ libevolution_module_calendar_la_SOURCES = \ libevolution_module_calendar_la_LIBADD = \ $(top_builddir)/shell/libeshell.la \ - $(top_builddir)/calendar/gui/libcal-gui.la \ + $(top_builddir)/calendar/gui/libevolution-calendar.la \ $(top_builddir)/calendar/importers/libevolution-calendar-importers.la \ $(top_builddir)/mail/libevolution-mail.la \ $(top_builddir)/addressbook/gui/contact-editor/libecontacteditor.la \ -- cgit v1.2.3 From e68456f60f37d5d6e18fac95a5a9ddea2e9627fa Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Tue, 11 Aug 2009 23:19:03 -0400 Subject: Get the calendar-weather plugin working. --- modules/calendar/e-cal-shell-migrate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-migrate.c b/modules/calendar/e-cal-shell-migrate.c index 8eb8e14575..bc17a90e9b 100644 --- a/modules/calendar/e-cal-shell-migrate.c +++ b/modules/calendar/e-cal-shell-migrate.c @@ -623,7 +623,7 @@ e_cal_shell_backend_migrate (EShellBackend *shell_backend, ESource *personal_source = NULL; ESourceList *source_list; ECalEvent *ece; - ECalEventTargetModule *target; + ECalEventTargetBackend *target; gboolean retval = FALSE; source_list = g_object_get_data ( -- cgit v1.2.3 From 9199f2c5b1925b6d1092738bf1a1c026e53d37f0 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Wed, 12 Aug 2009 09:29:44 -0400 Subject: Get the itip-formatter plugin working. --- modules/calendar/e-cal-shell-settings.c | 8 ++++ modules/calendar/e-cal-shell-sidebar.c | 4 +- modules/calendar/e-memo-shell-backend.c | 78 +++++++++++++++++++++++++-------- modules/calendar/e-memo-shell-migrate.c | 19 ++++++-- modules/calendar/e-memo-shell-sidebar.c | 26 +++++++++-- modules/calendar/e-task-shell-backend.c | 78 +++++++++++++++++++++++++-------- modules/calendar/e-task-shell-migrate.c | 17 ++++++- modules/calendar/e-task-shell-sidebar.c | 26 +++++++++-- 8 files changed, 202 insertions(+), 54 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-settings.c b/modules/calendar/e-cal-shell-settings.c index 4d75bae4e9..be50c8e7b3 100644 --- a/modules/calendar/e-cal-shell-settings.c +++ b/modules/calendar/e-cal-shell-settings.c @@ -524,6 +524,14 @@ e_cal_shell_backend_init_settings (EShell *shell) "cal-primary-calendar", "/apps/evolution/calendar/display/primary_calendar"); + e_shell_settings_install_property_for_key ( + "cal-primary-memo-list", + "/apps/evolution/calendar/memos/primary_memos"); + + e_shell_settings_install_property_for_key ( + "cal-primary-task-list", + "/apps/evolution/calendar/tasks/primary_tasks"); + e_shell_settings_install_property_for_key ( "cal-show-event-end-times", "/apps/evolution/calendar/display/show_event_end"); diff --git a/modules/calendar/e-cal-shell-sidebar.c b/modules/calendar/e-cal-shell-sidebar.c index 28f96e553d..f8f6acae9b 100644 --- a/modules/calendar/e-cal-shell-sidebar.c +++ b/modules/calendar/e-cal-shell-sidebar.c @@ -368,7 +368,6 @@ cal_shell_sidebar_constructed (GObject *object) ECalShellSidebarPrivate *priv; EShell *shell; EShellView *shell_view; - EShellWindow *shell_window; EShellBackend *shell_backend; EShellSidebar *shell_sidebar; EShellSettings *shell_settings; @@ -393,9 +392,8 @@ cal_shell_sidebar_constructed (GObject *object) shell_sidebar = E_SHELL_SIDEBAR (object); shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); shell_backend = e_shell_view_get_shell_backend (shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell = e_shell_window_get_shell (shell_window); + shell = e_shell_backend_get_shell (shell_backend); shell_settings = e_shell_get_shell_settings (shell); source_list = e_cal_shell_backend_get_source_list ( diff --git a/modules/calendar/e-memo-shell-backend.c b/modules/calendar/e-memo-shell-backend.c index dc072e3062..9642528b78 100644 --- a/modules/calendar/e-memo-shell-backend.c +++ b/modules/calendar/e-memo-shell-backend.c @@ -71,6 +71,8 @@ memo_module_ensure_sources (EShellBackend *shell_backend) ESourceGroup *on_this_computer; ESourceGroup *on_the_web; ESource *personal; + EShell *shell; + EShellSettings *shell_settings; GSList *groups, *iter; const gchar *data_dir; const gchar *name; @@ -83,6 +85,9 @@ memo_module_ensure_sources (EShellBackend *shell_backend) priv = E_MEMO_SHELL_BACKEND_GET_PRIVATE (shell_backend); + shell = e_shell_backend_get_shell (shell_backend); + shell_settings = e_shell_get_shell_settings (shell); + if (!e_cal_get_sources (&priv->source_list, E_CAL_SOURCE_TYPE_JOURNAL, NULL)) { g_warning ("Could not get memo sources from GConf!"); return; @@ -172,7 +177,9 @@ memo_module_ensure_sources (EShellBackend *shell_backend) e_source_group_add_source (on_this_computer, source, -1); g_object_unref (source); - primary = calendar_config_get_primary_memos (); + primary = e_shell_settings_get_string ( + shell_settings, "cal-primary-memo-list"); + selected = calendar_config_get_memos_selected (); if (primary == NULL && selected == NULL) { @@ -181,7 +188,8 @@ memo_module_ensure_sources (EShellBackend *shell_backend) uid = e_source_peek_uid (source); selected = g_slist_prepend (NULL, g_strdup (uid)); - calendar_config_set_primary_memos (uid); + e_shell_settings_set_string ( + shell_settings, "cal-primary-memo-list", uid); calendar_config_set_memos_selected (selected); } @@ -210,30 +218,46 @@ memo_module_ensure_sources (EShellBackend *shell_backend) } static void -memo_module_cal_opened_cb (ECal *cal, - ECalendarStatus status, - GtkAction *action) +memo_shell_backend_memo_new_cb (ECal *cal, + ECalendarStatus status, + EShell *shell) { - EShell *shell; ECalComponent *comp; CompEditor *editor; CompEditorFlags flags = 0; - const gchar *action_name; - - /* FIXME Pass this in. */ - shell = e_shell_get_default (); /* XXX Handle errors better. */ if (status != E_CALENDAR_STATUS_OK) return; - action_name = gtk_action_get_name (action); + flags |= COMP_EDITOR_NEW_ITEM; + + editor = memo_editor_new (cal, shell, flags); + comp = cal_comp_memo_new_with_defaults (cal); + comp_editor_edit_comp (editor, comp); + + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (comp); + g_object_unref (cal); +} + +static void +memo_shell_backend_memo_shared_new_cb (ECal *cal, + ECalendarStatus status, + EShell *shell) +{ + ECalComponent *comp; + CompEditor *editor; + CompEditorFlags flags = 0; + + /* XXX Handle errors better. */ + if (status != E_CALENDAR_STATUS_OK) + return; flags |= COMP_EDITOR_NEW_ITEM; - if (strcmp (action_name, "memo-shared-new") == 0) { - flags |= COMP_EDITOR_IS_SHARED; - flags |= COMP_EDITOR_USER_ORG; - } + flags |= COMP_EDITOR_IS_SHARED; + flags |= COMP_EDITOR_USER_ORG; editor = memo_editor_new (cal, shell, flags); comp = cal_comp_memo_new_with_defaults (cal); @@ -252,18 +276,25 @@ action_memo_new_cb (GtkAction *action, ECal *cal = NULL; ECalSourceType source_type; ESourceList *source_list; + EShellSettings *shell_settings; + EShell *shell; + const gchar *action_name; gchar *uid; /* This callback is used for both memos and shared memos. */ source_type = E_CAL_SOURCE_TYPE_JOURNAL; + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + if (!e_cal_get_sources (&source_list, source_type, NULL)) { g_warning ("Could not get memo sources from GConf!"); return; } - uid = calendar_config_get_primary_memos (); + uid = e_shell_settings_get_string ( + shell_settings, "cal-primary-memo-list"); if (uid != NULL) { ESource *source; @@ -279,9 +310,18 @@ action_memo_new_cb (GtkAction *action, g_return_if_fail (cal != NULL); - g_signal_connect ( - cal, "cal-opened", - G_CALLBACK (memo_module_cal_opened_cb), action); + /* Connect the appropriate signal handler. */ + action_name = gtk_action_get_name (action); + if (strcmp (action_name, "memo-shared-new") == 0) + g_signal_connect ( + cal, "cal-opened", + G_CALLBACK (memo_shell_backend_memo_shared_new_cb), + shell); + else + g_signal_connect ( + cal, "cal-opened", + G_CALLBACK (memo_shell_backend_memo_new_cb), + shell); e_cal_open_async (cal, FALSE); } diff --git a/modules/calendar/e-memo-shell-migrate.c b/modules/calendar/e-memo-shell-migrate.c index 20b9fea43e..d2dce309d7 100644 --- a/modules/calendar/e-memo-shell-migrate.c +++ b/modules/calendar/e-memo-shell-migrate.c @@ -32,6 +32,7 @@ #include "calendar/gui/calendar-config.h" #include "calendar/gui/calendar-config-keys.h" +#include "shell/e-shell.h" #define WEBCAL_BASE_URI "webcal://" #define PERSONAL_RELATIVE_URI "system" @@ -44,6 +45,8 @@ create_memo_sources (EShellBackend *shell_backend, ESourceGroup **on_the_web, ESource **personal_source) { + EShell *shell; + EShellSettings *shell_settings; GSList *groups; ESourceGroup *group; gchar *base_uri, *base_uri_proto; @@ -53,6 +56,9 @@ create_memo_sources (EShellBackend *shell_backend, *on_the_web = NULL; *personal_source = NULL; + shell = e_shell_backend_get_shell (shell_backend); + shell_settings = e_shell_get_shell_settings (shell); + base_dir = e_shell_backend_get_config_dir (shell_backend); base_uri = g_build_filename (base_dir, "local", NULL); @@ -100,14 +106,21 @@ create_memo_sources (EShellBackend *shell_backend, } if (!*personal_source) { - /* Create the default Person task list */ + gchar *primary_memo_list; + + /* Create the default Person memo list */ ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); e_source_group_add_source (*on_this_computer, source, -1); - if (!calendar_config_get_primary_memos () && !calendar_config_get_memos_selected ()) { + primary_memo_list = e_shell_settings_get_string ( + shell_settings, "cal-primary-memo-list"); + + if (!primary_memo_list && !calendar_config_get_memos_selected ()) { GSList selected; - calendar_config_set_primary_memos (e_source_peek_uid (source)); + e_shell_settings_set_string ( + shell_settings, "cal-primary-memo-list", + e_source_peek_uid (source)); selected.data = (gpointer)e_source_peek_uid (source); selected.next = NULL; diff --git a/modules/calendar/e-memo-shell-sidebar.c b/modules/calendar/e-memo-shell-sidebar.c index 0962a8a20d..33a2226c00 100644 --- a/modules/calendar/e-memo-shell-sidebar.c +++ b/modules/calendar/e-memo-shell-sidebar.c @@ -271,8 +271,12 @@ static void memo_shell_sidebar_primary_selection_changed_cb (EMemoShellSidebar *memo_shell_sidebar, ESourceSelector *selector) { + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + EShellSettings *shell_settings; ESource *source; - const gchar *uid; /* XXX ESourceSelector needs a "primary-selection-uid" property * so we can just bind the property with GConfBridge. */ @@ -281,8 +285,16 @@ memo_shell_sidebar_primary_selection_changed_cb (EMemoShellSidebar *memo_shell_s if (source == NULL) return; - uid = e_source_peek_uid (source); - calendar_config_set_primary_memos (uid); + shell_sidebar = E_SHELL_SIDEBAR (memo_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + e_shell_settings_set_string ( + shell_settings, "cal-primary-memo-list", + e_source_peek_uid (source)); } static void @@ -337,9 +349,11 @@ static void memo_shell_sidebar_constructed (GObject *object) { EMemoShellSidebarPrivate *priv; + EShell *shell; EShellView *shell_view; EShellBackend *shell_backend; EShellSidebar *shell_sidebar; + EShellSettings *shell_settings; ESourceSelector *selector; ESourceList *source_list; ESource *source; @@ -359,6 +373,9 @@ memo_shell_sidebar_constructed (GObject *object) shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); shell_backend = e_shell_view_get_shell_backend (shell_view); + shell = e_shell_backend_get_shell (shell_backend); + shell_settings = e_shell_get_shell_settings (shell); + source_list = e_memo_shell_backend_get_source_list ( E_MEMO_SHELL_BACKEND (shell_backend)); @@ -394,7 +411,8 @@ memo_shell_sidebar_constructed (GObject *object) object); source = NULL; - uid = calendar_config_get_primary_memos (); + uid = e_shell_settings_get_string ( + shell_settings, "cal-primary-memo-list"); if (uid != NULL) source = e_source_list_peek_source_by_uid (source_list, uid); if (source == NULL) diff --git a/modules/calendar/e-task-shell-backend.c b/modules/calendar/e-task-shell-backend.c index b9280c7373..23d5e35d7b 100644 --- a/modules/calendar/e-task-shell-backend.c +++ b/modules/calendar/e-task-shell-backend.c @@ -73,6 +73,8 @@ task_module_ensure_sources (EShellBackend *shell_backend) ESourceGroup *on_this_computer; ESourceGroup *on_the_web; ESource *personal; + EShell *shell; + EShellSettings *shell_settings; GSList *groups, *iter; const gchar *data_dir; const gchar *name; @@ -85,6 +87,9 @@ task_module_ensure_sources (EShellBackend *shell_backend) priv = E_TASK_SHELL_BACKEND_GET_PRIVATE (shell_backend); + shell = e_shell_backend_get_shell (shell_backend); + shell_settings = e_shell_get_shell_settings (shell); + if (!e_cal_get_sources (&priv->source_list, E_CAL_SOURCE_TYPE_TODO, NULL)) { g_warning ("Could not get task sources from GConf!"); return; @@ -174,7 +179,9 @@ task_module_ensure_sources (EShellBackend *shell_backend) e_source_group_add_source (on_this_computer, source, -1); g_object_unref (source); - primary = calendar_config_get_primary_tasks (); + primary = e_shell_settings_get_string ( + shell_settings, "cal-primary-task-list"); + selected = calendar_config_get_tasks_selected (); if (primary == NULL && selected == NULL) { @@ -183,7 +190,8 @@ task_module_ensure_sources (EShellBackend *shell_backend) uid = e_source_peek_uid (source); selected = g_slist_prepend (NULL, g_strdup (uid)); - calendar_config_set_primary_tasks (uid); + e_shell_settings_set_string ( + shell_settings, "cal-primary-task-list", uid); calendar_config_set_tasks_selected (selected); } @@ -212,30 +220,46 @@ task_module_ensure_sources (EShellBackend *shell_backend) } static void -task_module_cal_opened_cb (ECal *cal, - ECalendarStatus status, - GtkAction *action) +task_shell_backend_task_new_cb (ECal *cal, + ECalendarStatus status, + EShell *shell) { - EShell *shell; ECalComponent *comp; CompEditor *editor; CompEditorFlags flags = 0; - const gchar *action_name; - - /* FIXME Pass this in. */ - shell = e_shell_get_default (); /* XXX Handle errors better. */ if (status != E_CALENDAR_STATUS_OK) return; - action_name = gtk_action_get_name (action); + flags |= COMP_EDITOR_NEW_ITEM; + + editor = task_editor_new (cal, shell, flags); + comp = cal_comp_task_new_with_defaults (cal); + comp_editor_edit_comp (editor, comp); + + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (comp); + g_object_unref (cal); +} + +static void +task_shell_backend_task_assigned_new_cb (ECal *cal, + ECalendarStatus status, + EShell *shell) +{ + ECalComponent *comp; + CompEditor *editor; + CompEditorFlags flags = 0; + + /* XXX Handle errors better. */ + if (status != E_CALENDAR_STATUS_OK) + return; flags |= COMP_EDITOR_NEW_ITEM; - if (strcmp (action_name, "task-assigned-new") == 0) { - flags |= COMP_EDITOR_IS_ASSIGNED; - flags |= COMP_EDITOR_USER_ORG; - } + flags |= COMP_EDITOR_IS_ASSIGNED; + flags |= COMP_EDITOR_USER_ORG; editor = task_editor_new (cal, shell, flags); comp = cal_comp_task_new_with_defaults (cal); @@ -254,18 +278,25 @@ action_task_new_cb (GtkAction *action, ECal *cal = NULL; ECalSourceType source_type; ESourceList *source_list; + EShellSettings *shell_settings; + EShell *shell; + const gchar *action_name; gchar *uid; /* This callback is used for both tasks and assigned tasks. */ source_type = E_CAL_SOURCE_TYPE_TODO; + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + if (!e_cal_get_sources (&source_list, source_type, NULL)) { g_warning ("Could not get task sources from GConf!"); return; } - uid = calendar_config_get_primary_tasks (); + uid = e_shell_settings_get_string ( + shell_settings, "cal-primary-task-list"); if (uid != NULL) { ESource *source; @@ -281,9 +312,18 @@ action_task_new_cb (GtkAction *action, g_return_if_fail (cal != NULL); - g_signal_connect ( - cal, "cal-opened", - G_CALLBACK (task_module_cal_opened_cb), action); + /* Connect the appropriate signal handler. */ + action_name = gtk_action_get_name (action); + if (strcmp (action_name, "task-assigned-new") == 0) + g_signal_connect ( + cal, "cal-opened", + G_CALLBACK (task_shell_backend_task_assigned_new_cb), + shell); + else + g_signal_connect ( + cal, "cal-opened", + G_CALLBACK (task_shell_backend_task_new_cb), + shell); e_cal_open_async (cal, FALSE); } diff --git a/modules/calendar/e-task-shell-migrate.c b/modules/calendar/e-task-shell-migrate.c index 2e7928fd14..4bbaee65a6 100644 --- a/modules/calendar/e-task-shell-migrate.c +++ b/modules/calendar/e-task-shell-migrate.c @@ -42,6 +42,7 @@ #include "e-util/e-util-private.h" #include "calendar/gui/calendar-config.h" #include "calendar/gui/calendar-config-keys.h" +#include "shell/e-shell.h" #define WEBCAL_BASE_URI "webcal://" #define PERSONAL_RELATIVE_URI "system" @@ -443,6 +444,8 @@ create_task_sources (EShellBackend *shell_backend, ESourceGroup **on_the_web, ESource **personal_source) { + EShell *shell; + EShellSettings *shell_settings; GSList *groups; ESourceGroup *group; gchar *base_uri, *base_uri_proto; @@ -452,6 +455,9 @@ create_task_sources (EShellBackend *shell_backend, *on_the_web = NULL; *personal_source = NULL; + shell = e_shell_backend_get_shell (shell_backend); + shell_settings = e_shell_get_shell_settings (shell); + base_dir = e_shell_backend_get_config_dir (shell_backend); base_uri = g_build_filename (base_dir, "local", NULL); @@ -499,14 +505,21 @@ create_task_sources (EShellBackend *shell_backend, } if (!*personal_source) { + gchar *primary_task_list; + /* Create the default Person task list */ ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); e_source_group_add_source (*on_this_computer, source, -1); - if (!calendar_config_get_primary_tasks () && !calendar_config_get_tasks_selected ()) { + primary_task_list = e_shell_settings_get_string ( + shell_settings, "cal-primary-task-list"); + + if (!primary_task_list && !calendar_config_get_tasks_selected ()) { GSList selected; - calendar_config_set_primary_tasks (e_source_peek_uid (source)); + e_shell_settings_set_string ( + shell_settings, "cal-primary-task-list", + e_source_peek_uid (source)); selected.data = (gpointer)e_source_peek_uid (source); selected.next = NULL; diff --git a/modules/calendar/e-task-shell-sidebar.c b/modules/calendar/e-task-shell-sidebar.c index 827a0a037e..6bd7700fcf 100644 --- a/modules/calendar/e-task-shell-sidebar.c +++ b/modules/calendar/e-task-shell-sidebar.c @@ -269,8 +269,12 @@ static void task_shell_sidebar_primary_selection_changed_cb (ETaskShellSidebar *task_shell_sidebar, ESourceSelector *selector) { + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + EShellSidebar *shell_sidebar; + EShellSettings *shell_settings; ESource *source; - const gchar *uid; /* XXX ESourceSelector needs a "primary-selection-uid" property * so we can just bind the property with GConfBridge. */ @@ -279,8 +283,16 @@ task_shell_sidebar_primary_selection_changed_cb (ETaskShellSidebar *task_shell_s if (source == NULL) return; - uid = e_source_peek_uid (source); - calendar_config_set_primary_tasks (uid); + shell_sidebar = E_SHELL_SIDEBAR (task_shell_sidebar); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_window = e_shell_view_get_shell_window (shell_view); + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + e_shell_settings_set_string ( + shell_settings, "cal-primary-task-list", + e_source_peek_uid (source)); } static void @@ -335,9 +347,11 @@ static void task_shell_sidebar_constructed (GObject *object) { ETaskShellSidebarPrivate *priv; + EShell *shell; EShellView *shell_view; EShellBackend *shell_backend; EShellSidebar *shell_sidebar; + EShellSettings *shell_settings; ESourceSelector *selector; ESourceList *source_list; ESource *source; @@ -357,6 +371,9 @@ task_shell_sidebar_constructed (GObject *object) shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); shell_backend = e_shell_view_get_shell_backend (shell_view); + shell = e_shell_backend_get_shell (shell_backend); + shell_settings = e_shell_get_shell_settings (shell); + source_list = e_task_shell_backend_get_source_list ( E_TASK_SHELL_BACKEND (shell_backend)); @@ -392,7 +409,8 @@ task_shell_sidebar_constructed (GObject *object) object); source = NULL; - uid = calendar_config_get_primary_tasks (); + uid = e_shell_settings_get_string ( + shell_settings, "cal-primary-task-list"); if (uid != NULL) source = e_source_list_peek_source_by_uid (source_list, uid); if (source == NULL) -- cgit v1.2.3 From 2febb125d6abd0e9f485a13ae99281112a97416a Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Wed, 12 Aug 2009 11:37:59 -0400 Subject: Get the backup-restore plugin working. --- modules/calendar/e-cal-shell-view-private.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c index 49c07ca70f..063e7461ed 100644 --- a/modules/calendar/e-cal-shell-view-private.c +++ b/modules/calendar/e-cal-shell-view-private.c @@ -656,7 +656,6 @@ e_cal_shell_view_set_status_message (ECalShellView *cal_shell_view, void e_cal_shell_view_update_sidebar (ECalShellView *cal_shell_view) { -#if 0 /* KILL-BONOBO */ EShellView *shell_view; EShellSidebar *shell_sidebar; GnomeCalendar *calendar; @@ -777,7 +776,6 @@ e_cal_shell_view_update_sidebar (ECalShellView *cal_shell_view) } e_shell_sidebar_set_secondary_text (shell_sidebar, buffer); -#endif } void -- cgit v1.2.3 From 88aa930c58ad27858453a2109cc899f34df21056 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Wed, 12 Aug 2009 16:43:04 -0400 Subject: Make switching between calendar views work. --- modules/calendar/e-cal-shell-content.c | 33 +++++++++++++++++++++++++++-- modules/calendar/e-cal-shell-view-private.c | 9 +++++++- modules/calendar/e-cal-shell-view.c | 9 -------- modules/calendar/e-cal-shell-view.h | 3 --- 4 files changed, 39 insertions(+), 15 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c index 4409c1fc08..eccd146ba6 100644 --- a/modules/calendar/e-cal-shell-content.c +++ b/modules/calendar/e-cal-shell-content.c @@ -74,7 +74,6 @@ cal_shell_content_display_view_cb (ECalShellContent *cal_shell_content, GalView *gal_view) { GnomeCalendar *calendar; - CalendarView *gal_calendar_view; GnomeCalendarViewType view_type; /* XXX This is confusing: we have CalendarView and ECalendarView. @@ -99,6 +98,8 @@ cal_shell_content_display_view_cb (ECalShellContent *cal_shell_content, view_type = calendar_view_get_view_type ( CALENDAR_VIEW (gal_view)); } + + gnome_calendar_display_view (calendar, view_type); } static void @@ -389,6 +390,10 @@ cal_shell_content_constructed (GObject *object) gtk_widget_show (GTK_WIDGET (calendar_view)); } + e_binding_new ( + G_OBJECT (priv->calendar), "view", + G_OBJECT (priv->notebook), "page"); + container = priv->vpaned; widget = gtk_vbox_new (FALSE, 0); @@ -448,7 +453,8 @@ cal_shell_content_constructed (GObject *object) view_instance, "display-view", G_CALLBACK (cal_shell_content_display_view_cb), object); - gal_view_instance_load (view_instance); + /* XXX Actually, don't load the view instance just yet. + * The GtkWidget::map() callback below explains why. */ priv->view_instance = view_instance; g_signal_connect_swapped ( @@ -468,10 +474,30 @@ cal_shell_content_constructed (GObject *object) g_object_unref (task_model); } +static void +cal_shell_content_map (GtkWidget *widget) +{ + ECalShellContentPrivate *priv; + GalViewInstance *view_instance; + + /* XXX Delay loading the GalViewInstance until after ECalShellView + * has a chance to install the sidebar's date navigator into + * GnomeCalendar, since loading the GalViewInstance triggers a + * callback in GnomeCalendar that requires the date navigator. + * Ordinarily we would do this at the end of constructed(), but + * that's too soon in this case. (This feels kind of kludgy.) */ + priv = E_CAL_SHELL_CONTENT_GET_PRIVATE (widget); + gal_view_instance_load (priv->view_instance); + + /* Chain up to parent's map() method. */ + GTK_WIDGET_CLASS (parent_class)->map (widget); +} + static void cal_shell_content_class_init (ECalShellContentClass *class) { GObjectClass *object_class; + GtkWidgetClass *widget_class; parent_class = g_type_class_peek_parent (class); g_type_class_add_private (class, sizeof (ECalShellContentPrivate)); @@ -482,6 +508,9 @@ cal_shell_content_class_init (ECalShellContentClass *class) object_class->dispose = cal_shell_content_dispose; object_class->finalize = cal_shell_content_finalize; object_class->constructed = cal_shell_content_constructed; + + widget_class = GTK_WIDGET_CLASS (class); + widget_class->map = cal_shell_content_map; } static void diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c index 063e7461ed..60ec3c77ab 100644 --- a/modules/calendar/e-cal-shell-view-private.c +++ b/modules/calendar/e-cal-shell-view-private.c @@ -368,6 +368,11 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) e_cal_shell_view_update_sidebar (cal_shell_view); e_cal_shell_view_update_search_filter (cal_shell_view); e_cal_shell_view_update_timezone (cal_shell_view); + + /* Keep the toolbar view buttons in sync with the calendar. */ + e_mutual_binding_new ( + G_OBJECT (calendar), "view", + G_OBJECT (ACTION (CALENDAR_VIEW_DAY)), "current-value"); } void @@ -658,6 +663,7 @@ e_cal_shell_view_update_sidebar (ECalShellView *cal_shell_view) { EShellView *shell_view; EShellSidebar *shell_sidebar; + ECalShellContent *cal_shell_content; GnomeCalendar *calendar; GnomeCalendarViewType view; time_t start_time, end_time; @@ -672,7 +678,8 @@ e_cal_shell_view_update_sidebar (ECalShellView *cal_shell_view) shell_view = E_SHELL_VIEW (cal_shell_view); shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - calendar = e_cal_shell_view_get_calendar (cal_shell_view); + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); gnome_calendar_get_visible_time_range ( calendar, &start_time, &end_time); diff --git a/modules/calendar/e-cal-shell-view.c b/modules/calendar/e-cal-shell-view.c index 2c977e7553..d9d21799b9 100644 --- a/modules/calendar/e-cal-shell-view.c +++ b/modules/calendar/e-cal-shell-view.c @@ -217,12 +217,3 @@ e_cal_shell_view_register_type (GTypeModule *type_module) type_module, E_TYPE_SHELL_VIEW, "ECalShellView", &type_info, 0); } - -GnomeCalendar * -e_cal_shell_view_get_calendar (ECalShellView *cal_shell_view) -{ - g_return_val_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view), NULL); - - /* FIXME */ - return NULL; -} diff --git a/modules/calendar/e-cal-shell-view.h b/modules/calendar/e-cal-shell-view.h index 67fa15220c..0cd7382012 100644 --- a/modules/calendar/e-cal-shell-view.h +++ b/modules/calendar/e-cal-shell-view.h @@ -23,8 +23,6 @@ #define E_CAL_SHELL_VIEW_H #include -#include -#include /* Standard GObject macros */ #define E_TYPE_CAL_SHELL_VIEW \ @@ -62,7 +60,6 @@ struct _ECalShellViewClass { GType e_cal_shell_view_get_type (void); void e_cal_shell_view_register_type (GTypeModule *type_module); -GnomeCalendar * e_cal_shell_view_get_calendar (ECalShellView *cal_shell_view); G_END_DECLS -- cgit v1.2.3 From 311c8dd1226555f81c2eaca738969f5d9e123d1f Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Wed, 12 Aug 2009 22:27:13 -0400 Subject: Add new preferences missed during the 2.27.90 merge. --- modules/calendar/e-cal-shell-settings.c | 2 +- modules/calendar/e-cal-shell-settings.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-settings.c b/modules/calendar/e-cal-shell-settings.c index be50c8e7b3..c6d3c984fb 100644 --- a/modules/calendar/e-cal-shell-settings.c +++ b/modules/calendar/e-cal-shell-settings.c @@ -1,5 +1,5 @@ /* - * e-cal-shell-backend-settings.c + * e-cal-shell-settings.c * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/modules/calendar/e-cal-shell-settings.h b/modules/calendar/e-cal-shell-settings.h index de8b22888b..5f7293bbed 100644 --- a/modules/calendar/e-cal-shell-settings.h +++ b/modules/calendar/e-cal-shell-settings.h @@ -1,5 +1,5 @@ /* - * e-cal-shell-backend-settings.h + * e-cal-shell-settings.h * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,8 +19,8 @@ * */ -#ifndef E_CAL_SHELL_BACKEND_SETTINGS_H -#define E_CAL_SHELL_BACKEND_SETTINGS_H +#ifndef E_CAL_SHELL_SETTINGS_H +#define E_CAL_SHELL_SETTINGS_H #include @@ -30,4 +30,4 @@ void e_cal_shell_backend_init_settings (EShell *shell); G_END_DECLS -#endif /* E_CAL_SHELL_BACKEND_SETTINGS_H */ +#endif /* E_CAL_SHELL_SETTINGS_H */ -- cgit v1.2.3 From a44eac756d55b0210cc541e1d9b7138805a2133e Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Thu, 13 Aug 2009 10:36:32 -0400 Subject: Track the timezone in one place: ECalModel --- modules/calendar/e-cal-shell-view-private.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c index 60ec3c77ab..8c18176af5 100644 --- a/modules/calendar/e-cal-shell-view-private.c +++ b/modules/calendar/e-cal-shell-view-private.c @@ -40,17 +40,6 @@ cal_shell_view_process_completed_tasks (ECalShellView *cal_shell_view, #endif } -static void -cal_shell_view_config_timezone_changed_cb (GConfClient *client, - guint id, - GConfEntry *entry, - gpointer user_data) -{ - ECalShellView *cal_shell_view = user_data; - - e_cal_shell_view_update_timezone (cal_shell_view); -} - static struct tm cal_shell_view_get_current_time (ECalendarItem *calitem, ECalShellView *cal_shell_view) @@ -666,6 +655,7 @@ e_cal_shell_view_update_sidebar (ECalShellView *cal_shell_view) ECalShellContent *cal_shell_content; GnomeCalendar *calendar; GnomeCalendarViewType view; + ECalModel *model; time_t start_time, end_time; struct tm start_tm, end_tm; struct icaltimetype start_tt, end_tt; @@ -683,7 +673,8 @@ e_cal_shell_view_update_sidebar (ECalShellView *cal_shell_view) gnome_calendar_get_visible_time_range ( calendar, &start_time, &end_time); - timezone = gnome_calendar_get_timezone (calendar); + model = gnome_calendar_get_calendar_model (calendar); + timezone = e_cal_model_get_timezone (model); view = gnome_calendar_get_view (calendar); start_tt = icaltime_from_timet_with_zone (start_time, FALSE, timezone); -- cgit v1.2.3 From ad17dfabe588f03cc21e4ee5aca86f4c540e517e Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Fri, 14 Aug 2009 19:34:43 -0400 Subject: Get the calendar view popup menu working. --- modules/calendar/e-cal-shell-content.c | 7 +- modules/calendar/e-cal-shell-view-actions.c | 576 +++++++++++++++++++++++++++- modules/calendar/e-cal-shell-view-private.c | 135 +++++++ modules/calendar/e-cal-shell-view-private.h | 7 + 4 files changed, 710 insertions(+), 15 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c index eccd146ba6..0dd3ff1ece 100644 --- a/modules/calendar/e-cal-shell-content.c +++ b/modules/calendar/e-cal-shell-content.c @@ -33,6 +33,8 @@ #include "calendar/gui/e-cal-model-calendar.h" #include "calendar/gui/e-calendar-table.h" #include "calendar/gui/e-calendar-view.h" +#include "calendar/gui/e-day-view.h" +#include "calendar/gui/e-week-view.h" #include "widgets/menus/gal-view-etable.h" @@ -138,12 +140,10 @@ cal_shell_content_notify_view_id_cb (ECalShellContent *cal_shell_content) static FocusLocation cal_shell_content_get_focus_location (ECalShellContent *cal_shell_content) { - return FOCUS_OTHER; -#if 0 /* TEMPORARILY DISABLED */ GtkWidget *widget; GnomeCalendar *calendar; GnomeCalendarViewType view_type; - ECalendarView calendar_view; + ECalendarView *calendar_view; ECalendarTable *task_table; EMemoTable *memo_table; ETable *table; @@ -205,7 +205,6 @@ cal_shell_content_get_focus_location (ECalShellContent *cal_shell_content) } return FOCUS_OTHER; -#endif } static void diff --git a/modules/calendar/e-cal-shell-view-actions.c b/modules/calendar/e-cal-shell-view-actions.c index bb8ee69893..699cf2460c 100644 --- a/modules/calendar/e-cal-shell-view-actions.c +++ b/modules/calendar/e-cal-shell-view-actions.c @@ -271,7 +271,74 @@ static void action_calendar_purge_cb (GtkAction *action, ECalShellView *cal_shell_view) { - /* FIXME */ + EShellView *shell_view; + EShellWindow *shell_window; + ECalShellContent *cal_shell_content; + GnomeCalendar *calendar; + GtkSpinButton *spin_button; + GtkWidget *container; + GtkWidget *dialog; + GtkWidget *widget; + gint days; + time_t tt; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + + dialog = gtk_message_dialog_new ( + GTK_WINDOW (shell_window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK_CANCEL, + _("This operation will permanently erase all events older " + "than the selected amount of time. If you continue, you " + "will not be able to recover these events.")); + + gtk_dialog_set_default_response ( + GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL); + + container = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); + + widget = gtk_hbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, FALSE, 6); + gtk_widget_show (widget); + + container = widget; + + /* Translators: This is the first part of the sentence: + * "Purge events older than <> days" */ + widget = gtk_label_new (_("Purge events older than")); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, FALSE, 6); + gtk_widget_show (widget); + + widget = gtk_spin_button_new_with_range (0.0, 1000.0, 1.0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), 60.0); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 6); + gtk_widget_show (widget); + + spin_button = GTK_SPIN_BUTTON (widget); + + /* Translators: This is the last part of the sentence: + * "Purge events older than <> days" */ + widget = gtk_label_new (_("days")); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, FALSE, 6); + gtk_widget_show (widget); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) + goto exit; + + days = gtk_spin_button_get_value_as_int (spin_button); + + tt = time (NULL); + tt -= (days * (24 * 3600)); + + gnome_calendar_purge (calendar, tt); + +exit: + gtk_widget_destroy (dialog); } static void @@ -437,14 +504,157 @@ static void action_event_copy_cb (GtkAction *action, ECalShellView *cal_shell_view) { - /* FIXME */ + EShellView *shell_view; + EShellWindow *shell_window; + ECalShellContent *cal_shell_content; + GnomeCalendarViewType view_type; + GnomeCalendar *calendar; + ECalendarView *calendar_view; + ESource *destination_source = NULL; + ECal *destination_client = NULL; + GList *selected, *iter; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + + selected = e_calendar_view_get_selected_events (calendar_view); + g_return_if_fail (selected != NULL); + + /* Get a destination source from the user. */ + destination_source = select_source_dialog ( + GTK_WINDOW (shell_window), E_CAL_SOURCE_TYPE_EVENT); + if (destination_source == NULL) + return; + + /* Open the destination calendar. */ + destination_client = auth_new_cal_from_source ( + destination_source, E_CAL_SOURCE_TYPE_EVENT); + if (destination_client == NULL) + goto exit; + if (!e_cal_open (destination_client, FALSE, NULL)) + goto exit; + + e_cal_shell_view_set_status_message ( + cal_shell_view, _("Copying Items"), -1.0); + + for (iter = selected; iter != NULL; iter = iter->next) { + ECalendarViewEvent *event = iter->data; + gboolean remove = FALSE; + + e_cal_shell_view_transfer_item_to ( + cal_shell_view, event, destination_client, remove); + } + + e_cal_shell_view_set_status_message (cal_shell_view, NULL, -1.0); + +exit: + if (destination_client != NULL) + g_object_unref (destination_client); + if (destination_source != NULL) + g_object_unref (destination_source); + g_list_free (selected); } static void action_event_delegate_cb (GtkAction *action, ECalShellView *cal_shell_view) { - /* FIXME */ + ECalShellContent *cal_shell_content; + GnomeCalendarViewType view_type; + GnomeCalendar *calendar; + ECalendarView *calendar_view; + ECalendarViewEvent *event; + ECalComponent *component; + ECal *client; + GList *selected; + icalcomponent *clone; + icalproperty *property; + gboolean found = FALSE; + gchar *attendee; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + + selected = e_calendar_view_get_selected_events (calendar_view); + g_return_if_fail (g_list_length (selected) == 1); + + event = selected->data; + client = event->comp_data->client; + clone = icalcomponent_new_clone (event->comp_data->icalcomp); + + /* Set the attendee status for the delegate. */ + + component = e_cal_component_new (); + e_cal_component_set_icalcomponent ( + component, icalcomponent_new_clone (clone)); + + attendee = itip_get_comp_attendee (component, client); + property = icalcomponent_get_first_property ( + clone, ICAL_ATTENDEE_PROPERTY); + + while (property != NULL) { + const gchar *candidate; + + candidate = icalproperty_get_attendee (property); + candidate = itip_strip_mailto (candidate); + + if (g_ascii_strcasecmp (candidate, attendee) == 0) { + icalparameter *parameter; + + parameter = icalparameter_new_role ( + ICAL_ROLE_NONPARTICIPANT); + icalproperty_set_parameter (property, parameter); + + parameter = icalparameter_new_partstat ( + ICAL_PARTSTAT_DELEGATED); + icalproperty_set_parameter (property, parameter); + + found = TRUE; + break; + } + + property = icalcomponent_get_next_property ( + clone, ICAL_ATTENDEE_PROPERTY); + } + + /* If the attendee is not already in the component, add it. */ + if (!found) { + icalparameter *parameter; + gchar *address; + + address = g_strdup_printf ("MAILTO:%s", attendee); + + property = icalproperty_new_attendee (address); + icalcomponent_add_property (clone, property); + + parameter = icalparameter_new_role (ICAL_ROLE_NONPARTICIPANT); + icalproperty_add_parameter (property, parameter); + + parameter = icalparameter_new_cutype (ICAL_CUTYPE_INDIVIDUAL); + icalproperty_add_parameter (property, parameter); + + parameter = icalparameter_new_rsvp (ICAL_RSVP_TRUE); + icalproperty_add_parameter (property, parameter); + + g_free (address); + } + + g_free (attendee); + g_object_unref (component); + + e_calendar_view_open_event_with_flags ( + calendar_view, event->comp_data->client, clone, + COMP_EDITOR_MEETING | COMP_EDITOR_DELEGATE); + + icalcomponent_free (clone); + g_list_free (selected); } static void @@ -482,7 +692,39 @@ static void action_event_forward_cb (GtkAction *action, ECalShellView *cal_shell_view) { - /* FIXME */ + ECalShellContent *cal_shell_content; + GnomeCalendarViewType view_type; + ECalendarView *calendar_view; + GnomeCalendar *calendar; + ECalendarViewEvent *event; + ECalComponent *component; + ECal *client; + icalcomponent *icalcomp; + GList *selected; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + + selected = e_calendar_view_get_selected_events (calendar_view); + g_return_if_fail (g_list_length (selected) == 1); + + event = selected->data; + client = event->comp_data->client; + icalcomp = event->comp_data->icalcomp; + + component = e_cal_component_new (); + + e_cal_component_set_icalcomponent ( + component, icalcomponent_new_clone (icalcomp)); + itip_send_comp ( + E_CAL_COMPONENT_METHOD_PUBLISH, + component, client, NULL, NULL, NULL, TRUE, FALSE); + + g_object_unref (component); + + g_list_free (selected); } static void @@ -512,7 +754,60 @@ static void action_event_move_cb (GtkAction *action, ECalShellView *cal_shell_view) { - /* FIXME */ + EShellView *shell_view; + EShellWindow *shell_window; + ECalShellContent *cal_shell_content; + GnomeCalendarViewType view_type; + GnomeCalendar *calendar; + ECalendarView *calendar_view; + ESource *destination_source = NULL; + ECal *destination_client = NULL; + GList *selected, *iter; + + shell_view = E_SHELL_VIEW (cal_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + + selected = e_calendar_view_get_selected_events (calendar_view); + g_return_if_fail (selected != NULL); + + /* Get a destination source from the user. */ + destination_source = select_source_dialog ( + GTK_WINDOW (shell_window), E_CAL_SOURCE_TYPE_EVENT); + if (destination_source == NULL) + return; + + /* Open the destination calendar. */ + destination_client = auth_new_cal_from_source ( + destination_source, E_CAL_SOURCE_TYPE_EVENT); + if (destination_client == NULL) + goto exit; + if (!e_cal_open (destination_client, FALSE, NULL)) + goto exit; + + e_cal_shell_view_set_status_message ( + cal_shell_view, _("Moving Items"), -1.0); + + for (iter = selected; iter != NULL; iter = iter->next) { + ECalendarViewEvent *event = iter->data; + gboolean remove = TRUE; + + e_cal_shell_view_transfer_item_to ( + cal_shell_view, event, destination_client, remove); + } + + e_cal_shell_view_set_status_message (cal_shell_view, NULL, -1.0); + +exit: + if (destination_client != NULL) + g_object_unref (destination_client); + if (destination_source != NULL) + g_object_unref (destination_source); + g_list_free (selected); } static void @@ -536,7 +831,91 @@ static void action_event_occurrence_movable_cb (GtkAction *action, ECalShellView *cal_shell_view) { - /* FIXME */ + ECalShellContent *cal_shell_content; + GnomeCalendarViewType view_type; + GnomeCalendar *calendar; + ECalModel *model; + ECalendarView *calendar_view; + ECalendarViewEvent *event; + ECalComponent *exception_component; + ECalComponent *recurring_component; + ECalComponentDateTime date; + ECalComponentId *id; + ECal *client; + icalcomponent *icalcomp; + icaltimetype itt; + icaltimezone *timezone; + GList *selected; + gchar *uid; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + + model = e_calendar_view_get_model (calendar_view); + timezone = e_cal_model_get_timezone (model); + + selected = e_calendar_view_get_selected_events (calendar_view); + g_return_if_fail (g_list_length (selected) == 1); + + event = selected->data; + client = event->comp_data->client; + icalcomp = event->comp_data->icalcomp; + + /* For the recurring object, we add an exception + * to get rid of the instance. */ + + recurring_component = e_cal_component_new (); + e_cal_component_set_icalcomponent ( + recurring_component, icalcomponent_new_clone (icalcomp)); + id = e_cal_component_get_id (recurring_component); + + /* For the unrecurred instance, we duplicate the original object, + * create a new UID for it, get rid of the recurrence rules, and + * set the start and end times to the instance times. */ + + exception_component = e_cal_component_new (); + e_cal_component_set_icalcomponent ( + exception_component, icalcomponent_new_clone (icalcomp)); + + uid = e_cal_component_gen_uid (); + e_cal_component_set_uid (exception_component, uid); + g_free (uid); + + e_cal_component_set_recurid (exception_component, NULL); + e_cal_component_set_rdate_list (exception_component, NULL); + e_cal_component_set_rrule_list (exception_component, NULL); + e_cal_component_set_exdate_list (exception_component, NULL); + e_cal_component_set_exrule_list (exception_component, NULL); + + date.value = &itt; + date.tzid = icaltimezone_get_tzid (timezone); + *date.value = icaltime_from_timet_with_zone ( + event->comp_data->instance_start, FALSE, timezone); + cal_comp_set_dtstart_with_oldzone (client, exception_component, &date); + *date.value = icaltime_from_timet_with_zone ( + event->comp_data->instance_end, FALSE, timezone); + cal_comp_set_dtstart_with_oldzone (client, exception_component, &date); + e_cal_component_commit_sequence (exception_component); + + /* Now update both ECalComponents. Note that we do this last + * since at present the updates happend synchronously so our + * event may disappear. */ + + e_cal_remove_object_with_mod ( + client, id->uid, id->rid, CALOBJ_MOD_THIS, NULL); + + e_cal_component_free_id (id); + g_object_unref (recurring_component); + + icalcomp = e_cal_component_get_icalcomponent (exception_component); + if (e_cal_create_object (client, icalcomp, &uid, NULL)) + g_free (uid); + + g_object_unref (exception_component); + + g_list_free (selected); } static void @@ -560,35 +939,195 @@ static void action_event_print_cb (GtkAction *action, ECalShellView *cal_shell_view) { - /* FIXME */ + ECalShellContent *cal_shell_content; + GnomeCalendarViewType view_type; + GnomeCalendar *calendar; + ECalendarView *calendar_view; + ECalendarViewEvent *event; + ECalComponent *component; + ECal *client; + icalcomponent *icalcomp; + GList *selected; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + + selected = e_calendar_view_get_selected_events (calendar_view); + g_return_if_fail (g_list_length (selected) == 1); + + event = selected->data; + client = event->comp_data->client; + icalcomp = event->comp_data->icalcomp; + + component = e_cal_component_new (); + + e_cal_component_set_icalcomponent ( + component, icalcomponent_new_clone (icalcomp)); + print_comp ( + component, client, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG); + + g_object_unref (component); + + g_list_free (selected); } static void action_event_reply_cb (GtkAction *action, ECalShellView *cal_shell_view) { - /* FIXME */ + ECalShellContent *cal_shell_content; + GnomeCalendarViewType view_type; + ECalendarView *calendar_view; + GnomeCalendar *calendar; + ECalendarViewEvent *event; + ECalComponent *component; + ECal *client; + icalcomponent *icalcomp; + GList *selected; + gboolean reply_all = FALSE; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + + selected = e_calendar_view_get_selected_events (calendar_view); + g_return_if_fail (g_list_length (selected) == 1); + + event = selected->data; + client = event->comp_data->client; + icalcomp = event->comp_data->icalcomp; + + component = e_cal_component_new (); + + e_cal_component_set_icalcomponent ( + component, icalcomponent_new_clone (icalcomp)); + reply_to_calendar_comp ( + E_CAL_COMPONENT_METHOD_REPLY, + component, client, reply_all, NULL, NULL); + + g_object_unref (component); + + g_list_free (selected); } static void action_event_reply_all_cb (GtkAction *action, ECalShellView *cal_shell_view) { - /* FIXME */ + ECalShellContent *cal_shell_content; + GnomeCalendarViewType view_type; + ECalendarView *calendar_view; + GnomeCalendar *calendar; + ECalendarViewEvent *event; + ECalComponent *component; + ECal *client; + icalcomponent *icalcomp; + GList *selected; + gboolean reply_all = TRUE; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + + selected = e_calendar_view_get_selected_events (calendar_view); + g_return_if_fail (g_list_length (selected) == 1); + + event = selected->data; + client = event->comp_data->client; + icalcomp = event->comp_data->icalcomp; + + component = e_cal_component_new (); + + e_cal_component_set_icalcomponent ( + component, icalcomponent_new_clone (icalcomp)); + reply_to_calendar_comp ( + E_CAL_COMPONENT_METHOD_REPLY, + component, client, reply_all, NULL, NULL); + + g_object_unref (component); + + g_list_free (selected); } static void action_event_save_as_cb (GtkAction *action, ECalShellView *cal_shell_view) { - /* FIXME */ + ECalShellContent *cal_shell_content; + GnomeCalendarViewType view_type; + GnomeCalendar *calendar; + ECalendarView *calendar_view; + ECalendarViewEvent *event; + ECal *client; + icalcomponent *icalcomp; + GList *selected; + gchar *filename = NULL; + gchar *string = NULL; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + + selected = e_calendar_view_get_selected_events (calendar_view); + g_return_if_fail (g_list_length (selected) == 1); + + event = selected->data; + client = event->comp_data->client; + icalcomp = event->comp_data->icalcomp; + + filename = e_file_dialog_save (_("Save As..."), NULL); + if (filename == NULL) + goto exit; + + string = e_cal_get_component_as_string (client, icalcomp); + if (string == NULL) { + g_warning ("Could not convert item to a string"); + goto exit; + } + + e_write_file_uri (filename, string); + +exit: + g_free (filename); + g_free (string); + + g_list_free (selected); } static void action_event_schedule_cb (GtkAction *action, ECalShellView *cal_shell_view) { - /* FIXME */ + ECalShellContent *cal_shell_content; + GnomeCalendarViewType view_type; + GnomeCalendar *calendar; + ECalendarView *calendar_view; + ECalendarViewEvent *event; + ECal *client; + icalcomponent *icalcomp; + GList *selected; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + + selected = e_calendar_view_get_selected_events (calendar_view); + g_return_if_fail (g_list_length (selected) == 1); + + event = selected->data; + client = event->comp_data->client; + icalcomp = event->comp_data->icalcomp; + + e_calendar_view_edit_appointment ( + calendar_view, client, icalcomp, TRUE); + + g_list_free (selected); } static void @@ -1132,6 +1671,21 @@ e_cal_shell_view_actions_init (ECalShellView *cal_shell_view) action = ACTION (CALENDAR_JUMP_TO); g_object_set (action, "short-label", _("Go To"), NULL); + action = ACTION (CALENDAR_VIEW_DAY); + g_object_set (action, "is-important", TRUE, NULL); + + action = ACTION (CALENDAR_VIEW_LIST); + g_object_set (action, "is-important", TRUE, NULL); + + action = ACTION (CALENDAR_VIEW_MONTH); + g_object_set (action, "is-important", TRUE, NULL); + + action = ACTION (CALENDAR_VIEW_WEEK); + g_object_set (action, "is-important", TRUE, NULL); + + action = ACTION (CALENDAR_VIEW_WORKWEEK); + g_object_set (action, "is-important", TRUE, NULL); + action = ACTION (EVENT_DELETE); g_object_set (action, "short-label", _("Delete"), NULL); diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c index 8c18176af5..719e705382 100644 --- a/modules/calendar/e-cal-shell-view-private.c +++ b/modules/calendar/e-cal-shell-view-private.c @@ -107,6 +107,16 @@ cal_shell_view_date_navigator_scroll_event_cb (ECalShellView *cal_shell_view, cal_shell_view, calitem); } +static void +cal_shell_view_popup_event_cb (EShellView *shell_view, + GdkEventButton *event) +{ + const gchar *widget_path; + + widget_path = "/calendar-event-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); +} + static gboolean cal_shell_view_selector_popup_event_cb (EShellView *shell_view, ESource *primary_source, @@ -254,6 +264,7 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) ECalendarTable *task_table; ESourceSelector *selector; ECalModel *model; + gint ii; shell_view = E_SHELL_VIEW (cal_shell_view); shell_backend = e_shell_view_get_shell_backend (shell_view); @@ -288,6 +299,17 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) /* KILL-BONOBO FIXME -- Need to connect to the "user-created" * signal for each ECalendarView. */ + for (ii = 0; ii < GNOME_CAL_LAST_VIEW; ii++) { + ECalendarView *calendar_view; + + calendar_view = + gnome_calendar_get_calendar_view (calendar, ii); + + g_signal_connect_swapped ( + calendar_view, "popup-event", + G_CALLBACK (cal_shell_view_popup_event_cb), + cal_shell_view); + } g_signal_connect_swapped ( calendar, "dates-shown-changed", @@ -647,6 +669,119 @@ e_cal_shell_view_set_status_message (ECalShellView *cal_shell_view, cal_shell_view->priv->calendar_activity = activity; } +void +e_cal_shell_view_transfer_item_to (ECalShellView *cal_shell_view, + ECalendarViewEvent *event, + ECal *destination_client, + gboolean remove) +{ + icalcomponent *icalcomp; + icalcomponent *icalcomp_clone; + icalcomponent *icalcomp_event; + gboolean success; + const gchar *uid; + + /* XXX This function should be split up into + * smaller, more understandable pieces. */ + + g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); + g_return_if_fail (event != NULL); + g_return_if_fail (E_IS_CAL (destination_client)); + + icalcomp_event = event->comp_data->icalcomp; + uid = icalcomponent_get_uid (icalcomp_event); + + /* Put the new object into the destination calendar. */ + + success = e_cal_get_object ( + destination_client, uid, NULL, &icalcomp, NULL); + + if (success) { + icalcomponent_free (icalcomp); + success = e_cal_modify_object ( + destination_client, icalcomp_event, + CALOBJ_MOD_ALL, NULL); + if (!success) + return; + } else { + icalproperty *icalprop; + gchar *new_uid; + + if (e_cal_util_component_is_instance (icalcomp_event)) { + success = e_cal_get_object ( + event->comp_data->client, + uid, NULL, &icalcomp, NULL); + if (success) { + /* Use master object when working + * with a recurring event ... */ + icalcomp_clone = + icalcomponent_new_clone (icalcomp); + icalcomponent_free (icalcomp); + } else { + /* ... or remove the recurrence ID ... */ + icalcomp_clone = + icalcomponent_new_clone (icalcomp_event); + if (e_cal_util_component_has_recurrences (icalcomp_clone)) { + /* ... for non-detached instances, + * to make it a master object. */ + icalprop = icalcomponent_get_first_property ( + icalcomp_clone, ICAL_RECURRENCEID_PROPERTY); + if (icalprop != NULL) + icalcomponent_remove_property ( + icalcomp_clone, icalprop); + } + } + } else + icalcomp_clone = + icalcomponent_new_clone (icalcomp_event); + + icalprop = icalproperty_new_x ("1"); + icalproperty_set_x_name (icalprop, "X-EVOLUTION-MOVE-CALENDAR"); + icalcomponent_add_property (icalcomp_clone, icalprop); + + if (!remove) { + /* Change the UID to avoid problems with + * duplicated UIDs. */ + new_uid = e_cal_component_gen_uid (); + icalcomponent_set_uid (icalcomp_clone, new_uid); + g_free (new_uid); + } + + new_uid = NULL; + success = e_cal_create_object ( + destination_client, icalcomp_clone, &new_uid, NULL); + if (!success) { + icalcomponent_free (icalcomp_clone); + return; + } + + icalcomponent_free (icalcomp_clone); + g_free (new_uid); + } + + if (remove) { + ECal *source_client = event->comp_data->client; + + /* Remove the item from the source calendar. */ + if (e_cal_util_component_is_instance (icalcomp_event) || + e_cal_util_component_has_recurrences (icalcomp_event)) { + icaltimetype icaltime; + gchar *rid; + + icaltime = + icalcomponent_get_recurrenceid (icalcomp_event); + if (!icaltime_is_null_time (icaltime)) + rid = icaltime_as_ical_string_r (icaltime); + else + rid = NULL; + e_cal_remove_object_with_mod ( + source_client, uid, rid, CALOBJ_MOD_ALL, NULL); + g_free (rid); + } else + e_cal_remove_object (source_client, uid, NULL); + } +} + void e_cal_shell_view_update_sidebar (ECalShellView *cal_shell_view) { diff --git a/modules/calendar/e-cal-shell-view-private.h b/modules/calendar/e-cal-shell-view-private.h index 2e1388a50f..77f9e1b06b 100644 --- a/modules/calendar/e-cal-shell-view-private.h +++ b/modules/calendar/e-cal-shell-view-private.h @@ -34,6 +34,7 @@ #include "e-util/e-dialog-utils.h" #include "widgets/misc/e-popup-action.h" +#include "calendar/common/authentication.h" #include "calendar/gui/calendar-config.h" #include "calendar/gui/comp-util.h" #include "calendar/gui/e-cal-list-view.h" @@ -45,6 +46,7 @@ #include "calendar/gui/dialogs/copy-source-dialog.h" #include "calendar/gui/dialogs/event-editor.h" #include "calendar/gui/dialogs/memo-editor.h" +#include "calendar/gui/dialogs/select-source-dialog.h" #include "calendar/gui/dialogs/task-editor.h" #include "e-cal-shell-backend.h" @@ -127,6 +129,11 @@ void e_cal_shell_view_set_status_message (ECalShellView *cal_shell_view, const gchar *status_message, gdouble percent); +void e_cal_shell_view_transfer_item_to + (ECalShellView *cal_shell_view, + ECalendarViewEvent *event, + ECal *destination_client, + gboolean remove); void e_cal_shell_view_update_sidebar (ECalShellView *cal_shell_view); void e_cal_shell_view_update_search_filter -- cgit v1.2.3 From 672adf12a0923437e90d08ab7925bd9329fcce0d Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Sun, 16 Aug 2009 11:25:08 -0400 Subject: Fix compiler warnings and deprecated GTK+ API usage. --- modules/calendar/e-cal-shell-content.c | 3 --- modules/calendar/e-cal-shell-migrate.c | 8 ++++---- modules/calendar/e-cal-shell-settings.c | 2 ++ modules/calendar/e-cal-shell-view-actions.c | 5 ++++- modules/calendar/e-cal-shell-view-private.c | 1 - modules/calendar/e-cal-shell-view-private.h | 8 ++++++-- modules/calendar/e-task-shell-migrate.c | 8 ++++---- modules/calendar/e-task-shell-view-private.c | 2 -- modules/calendar/e-task-shell-view-private.h | 1 + 9 files changed, 21 insertions(+), 17 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c index 0dd3ff1ece..7d819d8d8b 100644 --- a/modules/calendar/e-cal-shell-content.c +++ b/modules/calendar/e-cal-shell-content.c @@ -304,7 +304,6 @@ cal_shell_content_constructed (GObject *object) EShellContent *foreign_content; EShellView *foreign_view; GnomeCalendar *calendar; - GnomeCalendarViewType view_type; GalViewInstance *view_instance; GConfBridge *bridge; GtkWidget *container; @@ -313,7 +312,6 @@ cal_shell_content_constructed (GObject *object) const gchar *key; gchar *filename; gchar *markup; - gint page_num; gint ii; priv = E_CAL_SHELL_CONTENT_GET_PRIVATE (object); @@ -477,7 +475,6 @@ static void cal_shell_content_map (GtkWidget *widget) { ECalShellContentPrivate *priv; - GalViewInstance *view_instance; /* XXX Delay loading the GalViewInstance until after ECalShellView * has a chance to install the sidebar's date navigator into diff --git a/modules/calendar/e-cal-shell-migrate.c b/modules/calendar/e-cal-shell-migrate.c index bc17a90e9b..f59b62597c 100644 --- a/modules/calendar/e-cal-shell-migrate.c +++ b/modules/calendar/e-cal-shell-migrate.c @@ -134,19 +134,19 @@ setup_progress_dialog (void) gtk_label_set_line_wrap ((GtkLabel *) w, TRUE); gtk_widget_show (w); - gtk_box_pack_start_defaults ((GtkBox *) vbox, w); + gtk_box_pack_start ((GtkBox *) vbox, w, TRUE, TRUE, 0); hbox = gtk_hbox_new (FALSE, 6); gtk_widget_show (hbox); - gtk_box_pack_start_defaults ((GtkBox *) vbox, hbox); + gtk_box_pack_start ((GtkBox *) vbox, hbox, TRUE, TRUE, 0); label = (GtkLabel *) gtk_label_new (""); gtk_widget_show ((GtkWidget *) label); - gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) label); + gtk_box_pack_start ((GtkBox *) hbox, (GtkWidget *) label, TRUE, TRUE, 0); progress = (GtkProgressBar *) gtk_progress_bar_new (); gtk_widget_show ((GtkWidget *) progress); - gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) progress); + gtk_box_pack_start ((GtkBox *) hbox, (GtkWidget *) progress, TRUE, TRUE, 0); gtk_widget_show (window); } diff --git a/modules/calendar/e-cal-shell-settings.c b/modules/calendar/e-cal-shell-settings.c index c6d3c984fb..4e6939c892 100644 --- a/modules/calendar/e-cal-shell-settings.c +++ b/modules/calendar/e-cal-shell-settings.c @@ -24,6 +24,8 @@ #include #include +#include "e-util/e-binding.h" + static gboolean transform_string_to_icaltimezone (const GValue *src_value, GValue *dst_value, diff --git a/modules/calendar/e-cal-shell-view-actions.c b/modules/calendar/e-cal-shell-view-actions.c index 699cf2460c..b36c94b8d1 100644 --- a/modules/calendar/e-cal-shell-view-actions.c +++ b/modules/calendar/e-cal-shell-view-actions.c @@ -264,7 +264,10 @@ action_calendar_properties_cb (GtkAction *action, source = e_source_selector_peek_primary_selection (selector); g_return_if_fail (E_IS_SOURCE (source)); - calendar_setup_edit_calendar (GTK_WINDOW (shell_window), source); + /* XXX Does this -really- need a source group parameter? */ + calendar_setup_edit_calendar ( + GTK_WINDOW (shell_window), source, + e_source_peek_group (source)); } static void diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c index 719e705382..a81b7cd866 100644 --- a/modules/calendar/e-cal-shell-view-private.c +++ b/modules/calendar/e-cal-shell-view-private.c @@ -390,7 +390,6 @@ void e_cal_shell_view_private_dispose (ECalShellView *cal_shell_view) { ECalShellViewPrivate *priv = cal_shell_view->priv; - GList *iter; DISPOSE (priv->cal_shell_backend); DISPOSE (priv->cal_shell_content); diff --git a/modules/calendar/e-cal-shell-view-private.h b/modules/calendar/e-cal-shell-view-private.h index 77f9e1b06b..f982e06a0f 100644 --- a/modules/calendar/e-cal-shell-view-private.h +++ b/modules/calendar/e-cal-shell-view-private.h @@ -29,9 +29,12 @@ #include #include #include +#include -#include "e-util/e-util.h" +#include "e-util/e-binding.h" #include "e-util/e-dialog-utils.h" +#include "e-util/e-error.h" +#include "e-util/e-util.h" #include "widgets/misc/e-popup-action.h" #include "calendar/common/authentication.h" @@ -41,8 +44,9 @@ #include "calendar/gui/e-cal-model-tasks.h" #include "calendar/gui/e-calendar-view.h" #include "calendar/gui/gnome-cal.h" -/*#include "calendar/gui/goto.h"*/ +#include "calendar/gui/goto.h" #include "calendar/gui/print.h" +#include "calendar/gui/dialogs/calendar-setup.h" #include "calendar/gui/dialogs/copy-source-dialog.h" #include "calendar/gui/dialogs/event-editor.h" #include "calendar/gui/dialogs/memo-editor.h" diff --git a/modules/calendar/e-task-shell-migrate.c b/modules/calendar/e-task-shell-migrate.c index 4bbaee65a6..ebc03e971d 100644 --- a/modules/calendar/e-task-shell-migrate.c +++ b/modules/calendar/e-task-shell-migrate.c @@ -101,19 +101,19 @@ setup_progress_dialog (void) gtk_label_set_line_wrap ((GtkLabel *) w, TRUE); gtk_widget_show (w); - gtk_box_pack_start_defaults ((GtkBox *) vbox, w); + gtk_box_pack_start ((GtkBox *) vbox, w, TRUE, TRUE, 0); hbox = gtk_hbox_new (FALSE, 6); gtk_widget_show (hbox); - gtk_box_pack_start_defaults ((GtkBox *) vbox, hbox); + gtk_box_pack_start ((GtkBox *) vbox, hbox, TRUE, TRUE, 0); label = (GtkLabel *) gtk_label_new (""); gtk_widget_show ((GtkWidget *) label); - gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) label); + gtk_box_pack_start ((GtkBox *) hbox, (GtkWidget *) label, TRUE, TRUE, 0); progress = (GtkProgressBar *) gtk_progress_bar_new (); gtk_widget_show ((GtkWidget *) progress); - gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) progress); + gtk_box_pack_start ((GtkBox *) hbox, (GtkWidget *) progress, TRUE, TRUE, 0); gtk_widget_show (window); } diff --git a/modules/calendar/e-task-shell-view-private.c b/modules/calendar/e-task-shell-view-private.c index 38c5ab6033..a0ca5ee978 100644 --- a/modules/calendar/e-task-shell-view-private.c +++ b/modules/calendar/e-task-shell-view-private.c @@ -224,7 +224,6 @@ e_task_shell_view_private_constructed (ETaskShellView *task_shell_view) ECalModel *model; ETable *table; ESourceSelector *selector; - guint id; shell_view = E_SHELL_VIEW (task_shell_view); shell_backend = e_shell_view_get_shell_backend (shell_view); @@ -363,7 +362,6 @@ void e_task_shell_view_private_dispose (ETaskShellView *task_shell_view) { ETaskShellViewPrivate *priv = task_shell_view->priv; - GList *iter; DISPOSE (priv->task_shell_backend); DISPOSE (priv->task_shell_content); diff --git a/modules/calendar/e-task-shell-view-private.h b/modules/calendar/e-task-shell-view-private.h index 50fa306696..e612069bed 100644 --- a/modules/calendar/e-task-shell-view-private.h +++ b/modules/calendar/e-task-shell-view-private.h @@ -30,6 +30,7 @@ #include #include +#include "e-util/e-binding.h" #include "e-util/e-dialog-utils.h" #include "e-util/e-error.h" #include "e-util/e-util.h" -- cgit v1.2.3 From b6724cafa4c4b86c6542dbcfa66680e1b7ad2285 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Tue, 18 Aug 2009 11:37:22 -0400 Subject: Remove duplicate handlers for date navigator signals. --- modules/calendar/e-cal-shell-view-private.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c index a81b7cd866..4573e5f4ea 100644 --- a/modules/calendar/e-cal-shell-view-private.c +++ b/modules/calendar/e-cal-shell-view-private.c @@ -62,7 +62,13 @@ static void cal_shell_view_date_navigator_date_range_changed_cb (ECalShellView *cal_shell_view, ECalendarItem *calitem) { - /* FIXME gnome-calendar.c calls update_query() here. */ + ECalShellContent *cal_shell_content; + GnomeCalendar *calendar; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + + gnome_calendar_update_query (calendar); } static void -- cgit v1.2.3 From 026e76465697c7a8df48af89f4b3845902219fe7 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Tue, 18 Aug 2009 22:47:49 -0400 Subject: Trim more fat off the GnomeCalendar API. Oh and hey look, I can see events now! --- modules/calendar/e-cal-shell-content.c | 2 +- modules/calendar/e-cal-shell-view-private.c | 166 ++++++++++++++++++++++++++-- modules/calendar/e-cal-shell-view-private.h | 2 + 3 files changed, 162 insertions(+), 8 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c index 7d819d8d8b..03d79470d6 100644 --- a/modules/calendar/e-cal-shell-content.c +++ b/modules/calendar/e-cal-shell-content.c @@ -565,7 +565,7 @@ e_cal_shell_content_get_model (ECalShellContent *cal_shell_content) calendar = e_cal_shell_content_get_calendar (cal_shell_content); - return gnome_calendar_get_calendar_model (calendar); + return gnome_calendar_get_model (calendar); } GnomeCalendar * diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c index 4573e5f4ea..d6771314df 100644 --- a/modules/calendar/e-cal-shell-view-private.c +++ b/modules/calendar/e-cal-shell-view-private.c @@ -75,7 +75,115 @@ static void cal_shell_view_date_navigator_selection_changed_cb (ECalShellView *cal_shell_view, ECalendarItem *calitem) { - /* FIXME */ + ECalShellContent *cal_shell_content; + GnomeCalendarViewType switch_to; + GnomeCalendarViewType view_type; + GnomeCalendar *calendar; + ECalModel *model; + GDate start_date, end_date; + GDate new_start_date, new_end_date; + icaltimetype tt; + icaltimezone *timezone; + time_t start, end, new_time; + gboolean starts_on_week_start_day; + gint new_days_shown; + gint week_start_day; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + + model = gnome_calendar_get_model (calendar); + view_type = gnome_calendar_get_view (calendar); + switch_to = view_type; + + timezone = e_cal_model_get_timezone (model); + week_start_day = e_cal_model_get_week_start_day (model); + e_cal_model_get_time_range (model, &start, &end); + + time_to_gdate_with_zone (&start_date, start, timezone); + time_to_gdate_with_zone (&end_date, end, timezone); + + if (view_type == GNOME_CAL_MONTH_VIEW) { + EWeekView *week_view; + ECalendarView *calendar_view; + gboolean multi_week_view; + gboolean compress_weekend; + + calendar_view = gnome_calendar_get_calendar_view ( + calendar, GNOME_CAL_MONTH_VIEW); + + week_view = E_WEEK_VIEW (calendar_view); + multi_week_view = e_week_view_get_multi_week_view (week_view); + compress_weekend = e_week_view_get_compress_weekend (week_view); + + if (week_start_day == 0 && (!multi_week_view || compress_weekend)) + g_date_add_days (&start_date, 1); + } + + g_date_subtract_days (&end_date, 1); + + e_calendar_item_get_selection ( + calitem, &new_start_date, &new_end_date); + + /* If the selection hasn't changed, just return. */ + if (g_date_compare (&start_date, &new_start_date) == 0 && + g_date_compare (&end_date, &new_end_date) == 0) + return; + + new_days_shown = + g_date_get_julian (&new_end_date) - + g_date_get_julian (&new_start_date) + 1; + + /* If a complete week is selected we show the week view. + * Note that if weekends are compressed and the week start + * day is set to Sunday, we don't actually show complete + * weeks in the week view, so this may need tweaking. */ + starts_on_week_start_day = + (g_date_get_weekday (&new_start_date) % 7 == week_start_day); + + /* Update selection to be in the new time range. */ + tt = icaltime_null_time (); + tt.year = g_date_get_year (&new_start_date); + tt.month = g_date_get_month (&new_start_date); + tt.day = g_date_get_day (&new_start_date); + new_time = icaltime_as_timet_with_zone (tt, timezone); + + /* Switch views as appropriate, and change the number of + * days or weeks shown. */ + if (new_days_shown > 9) { + if (view_type != GNOME_CAL_LIST_VIEW) { + ECalendarView *calendar_view; + + calendar_view = gnome_calendar_get_calendar_view ( + calendar, GNOME_CAL_MONTH_VIEW); + e_week_view_set_weeks_shown ( + E_WEEK_VIEW (calendar_view), + (new_days_shown + 6) / 7); + switch_to = GNOME_CAL_MONTH_VIEW; + } + } else if (new_days_shown == 7 && starts_on_week_start_day) + switch_to = GNOME_CAL_WEEK_VIEW; + else { + ECalendarView *calendar_view; + + calendar_view = gnome_calendar_get_calendar_view ( + calendar, GNOME_CAL_DAY_VIEW); + e_day_view_set_days_shown ( + E_DAY_VIEW (calendar_view), new_days_shown); + + if (new_days_shown != 5 || !starts_on_week_start_day) + switch_to = GNOME_CAL_DAY_VIEW; + + else if (view_type != GNOME_CAL_WORK_WEEK_VIEW) + switch_to = GNOME_CAL_DAY_VIEW; + } + + /* Make the views display things properly. */ + gnome_calendar_update_view_times (calendar, new_time); + gnome_calendar_set_view (calendar, switch_to); + gnome_calendar_set_range_selected (calendar, TRUE); + + gnome_calendar_notify_dates_shown_changed (calendar); } static void @@ -136,6 +244,36 @@ cal_shell_view_selector_popup_event_cb (EShellView *shell_view, return TRUE; } +static void +cal_shell_view_selector_client_added_cb (ECalShellView *cal_shell_view, + ECal *client) +{ + ECalShellContent *cal_shell_content; + GnomeCalendar *calendar; + ECalModel *model; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + model = gnome_calendar_get_model (calendar); + + e_cal_model_add_client (model, client); +} + +static void +cal_shell_view_selector_client_removed_cb (ECalShellView *cal_shell_view, + ECal *client) +{ + ECalShellContent *cal_shell_content; + GnomeCalendar *calendar; + ECalModel *model; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + model = gnome_calendar_get_model (calendar); + + e_cal_model_remove_client (model, client); +} + static void cal_shell_view_memopad_popup_event_cb (EShellView *shell_view, GdkEventButton *event) @@ -347,6 +485,16 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) G_CALLBACK (cal_shell_view_selector_popup_event_cb), cal_shell_view); + g_signal_connect_swapped ( + cal_shell_sidebar, "client-added", + G_CALLBACK (cal_shell_view_selector_client_added_cb), + cal_shell_view); + + g_signal_connect_swapped ( + cal_shell_sidebar, "client-removed", + G_CALLBACK (cal_shell_view_selector_client_removed_cb), + cal_shell_view); + g_signal_connect_swapped ( memo_table, "popup-event", G_CALLBACK (cal_shell_view_memopad_popup_event_cb), @@ -794,7 +942,8 @@ e_cal_shell_view_update_sidebar (ECalShellView *cal_shell_view) EShellSidebar *shell_sidebar; ECalShellContent *cal_shell_content; GnomeCalendar *calendar; - GnomeCalendarViewType view; + GnomeCalendarViewType view_type; + ECalendarView *calendar_view; ECalModel *model; time_t start_time, end_time; struct tm start_tm, end_tm; @@ -811,11 +960,14 @@ e_cal_shell_view_update_sidebar (ECalShellView *cal_shell_view) cal_shell_content = cal_shell_view->priv->cal_shell_content; calendar = e_cal_shell_content_get_calendar (cal_shell_content); - gnome_calendar_get_visible_time_range ( - calendar, &start_time, &end_time); - model = gnome_calendar_get_calendar_model (calendar); + model = gnome_calendar_get_model (calendar); timezone = e_cal_model_get_timezone (model); - view = gnome_calendar_get_view (calendar); + + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + + e_calendar_view_get_visible_time_range ( + calendar_view, &start_time, &end_time); start_tt = icaltime_from_timet_with_zone (start_time, FALSE, timezone); start_tm.tm_year = start_tt.year - 1900; @@ -840,7 +992,7 @@ e_cal_shell_view_update_sidebar (ECalShellView *cal_shell_view) end_tm.tm_wday = time_day_of_week ( end_tt.day, end_tt.month - 1, end_tt.year); - switch (view) { + switch (view_type) { case GNOME_CAL_DAY_VIEW: case GNOME_CAL_WORK_WEEK_VIEW: case GNOME_CAL_WEEK_VIEW: diff --git a/modules/calendar/e-cal-shell-view-private.h b/modules/calendar/e-cal-shell-view-private.h index f982e06a0f..690031198e 100644 --- a/modules/calendar/e-cal-shell-view-private.h +++ b/modules/calendar/e-cal-shell-view-private.h @@ -43,6 +43,8 @@ #include "calendar/gui/e-cal-list-view.h" #include "calendar/gui/e-cal-model-tasks.h" #include "calendar/gui/e-calendar-view.h" +#include "calendar/gui/e-day-view.h" +#include "calendar/gui/e-week-view.h" #include "calendar/gui/gnome-cal.h" #include "calendar/gui/goto.h" #include "calendar/gui/print.h" -- cgit v1.2.3 From 32d802c8ba01fcba9547d335f54cb87f0acb544d Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Tue, 18 Aug 2009 23:26:46 -0400 Subject: More GnomeCalendar cleanup. --- modules/calendar/e-cal-shell-content.c | 38 ++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c index 03d79470d6..9248ea8334 100644 --- a/modules/calendar/e-cal-shell-content.c +++ b/modules/calendar/e-cal-shell-content.c @@ -610,6 +610,8 @@ e_cal_shell_content_copy_clipboard (ECalShellContent *cal_shell_content) GnomeCalendar *calendar; EMemoTable *memo_table; ECalendarTable *task_table; + GnomeCalendarViewType view_type; + ECalendarView *calendar_view; g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); @@ -617,9 +619,12 @@ e_cal_shell_content_copy_clipboard (ECalShellContent *cal_shell_content) memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); task_table = e_cal_shell_content_get_task_table (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + switch (cal_shell_content_get_focus_location (cal_shell_content)) { case FOCUS_CALENDAR: - gnome_calendar_copy_clipboard (calendar); + e_calendar_view_copy_clipboard (calendar_view); break; case FOCUS_MEMO_TABLE: @@ -641,6 +646,8 @@ e_cal_shell_content_cut_clipboard (ECalShellContent *cal_shell_content) GnomeCalendar *calendar; EMemoTable *memo_table; ECalendarTable *task_table; + GnomeCalendarViewType view_type; + ECalendarView *calendar_view; g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); @@ -648,9 +655,12 @@ e_cal_shell_content_cut_clipboard (ECalShellContent *cal_shell_content) memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); task_table = e_cal_shell_content_get_task_table (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + switch (cal_shell_content_get_focus_location (cal_shell_content)) { case FOCUS_CALENDAR: - gnome_calendar_cut_clipboard (calendar); + e_calendar_view_cut_clipboard (calendar_view); break; case FOCUS_MEMO_TABLE: @@ -672,6 +682,8 @@ e_cal_shell_content_paste_clipboard (ECalShellContent *cal_shell_content) GnomeCalendar *calendar; EMemoTable *memo_table; ECalendarTable *task_table; + GnomeCalendarViewType view_type; + ECalendarView *calendar_view; g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); @@ -679,9 +691,12 @@ e_cal_shell_content_paste_clipboard (ECalShellContent *cal_shell_content) memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); task_table = e_cal_shell_content_get_task_table (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + switch (cal_shell_content_get_focus_location (cal_shell_content)) { case FOCUS_CALENDAR: - gnome_calendar_paste_clipboard (calendar); + e_calendar_view_paste_clipboard (calendar_view); break; case FOCUS_MEMO_TABLE: @@ -703,6 +718,8 @@ e_cal_shell_content_delete_selection (ECalShellContent *cal_shell_content) GnomeCalendar *calendar; EMemoTable *memo_table; ECalendarTable *task_table; + GnomeCalendarViewType view_type; + ECalendarView *calendar_view; g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); @@ -710,9 +727,12 @@ e_cal_shell_content_delete_selection (ECalShellContent *cal_shell_content) memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); task_table = e_cal_shell_content_get_task_table (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + switch (cal_shell_content_get_focus_location (cal_shell_content)) { case FOCUS_CALENDAR: - gnome_calendar_delete_selection (calendar); + e_calendar_view_delete_selected_events (calendar_view); break; case FOCUS_MEMO_TABLE: @@ -732,13 +752,19 @@ void e_cal_shell_content_delete_selected_occurrence (ECalShellContent *cal_shell_content) { GnomeCalendar *calendar; + GnomeCalendarViewType view_type; + ECalendarView *calendar_view; FocusLocation focus; g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); focus = cal_shell_content_get_focus_location (cal_shell_content); + if (focus != FOCUS_CALENDAR) + return; + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); - if (focus == FOCUS_CALENDAR) - gnome_calendar_delete_selected_occurrence (calendar); + e_calendar_view_delete_selected_occurrence (calendar_view); } -- cgit v1.2.3 From 4983883b466e1b513a322b0ba84e86b3376a0695 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Sat, 22 Aug 2009 21:15:15 -0400 Subject: Fix migration errors. --- modules/calendar/e-cal-shell-migrate.c | 3 +-- modules/calendar/e-memo-shell-migrate.c | 3 +-- modules/calendar/e-task-shell-migrate.c | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-migrate.c b/modules/calendar/e-cal-shell-migrate.c index f59b62597c..5ec9c99bf3 100644 --- a/modules/calendar/e-cal-shell-migrate.c +++ b/modules/calendar/e-cal-shell-migrate.c @@ -626,8 +626,7 @@ e_cal_shell_backend_migrate (EShellBackend *shell_backend, ECalEventTargetBackend *target; gboolean retval = FALSE; - source_list = g_object_get_data ( - G_OBJECT (shell_backend), "source-list"); + g_object_get (shell_backend, "source-list", &source_list, NULL); /* we call this unconditionally now - create_groups either creates the groups/sources or it finds the necessary diff --git a/modules/calendar/e-memo-shell-migrate.c b/modules/calendar/e-memo-shell-migrate.c index d2dce309d7..3bcf3156a5 100644 --- a/modules/calendar/e-memo-shell-migrate.c +++ b/modules/calendar/e-memo-shell-migrate.c @@ -223,8 +223,7 @@ e_memo_shell_backend_migrate (EShellBackend *shell_backend, ESourceList *source_list = NULL; gboolean retval = FALSE; - source_list = g_object_get_data ( - G_OBJECT (shell_backend), "source-list"); + g_object_get (shell_backend, "source-list", &source_list, NULL); /* we call this unconditionally now - create_groups either creates the groups/sources or it finds the necessary diff --git a/modules/calendar/e-task-shell-migrate.c b/modules/calendar/e-task-shell-migrate.c index ebc03e971d..799298f5a7 100644 --- a/modules/calendar/e-task-shell-migrate.c +++ b/modules/calendar/e-task-shell-migrate.c @@ -555,8 +555,7 @@ e_task_shell_backend_migrate (EShellBackend *shell_backend, ESourceList *source_list; gboolean retval = FALSE; - source_list = g_object_get_data ( - G_OBJECT (source_list), "source-list"); + g_object_get (shell_backend, "source-list", &source_list, NULL); /* we call this unconditionally now - create_groups either creates the groups/sources or it finds the necessary -- cgit v1.2.3 From f2b2d42471dc6a820c94f8888bd4f13a5c00a530 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Mon, 24 Aug 2009 21:29:25 -0400 Subject: Handle calendar URIs from the command line. --- modules/calendar/e-cal-shell-backend.c | 151 +++++++++++++++++++++++++++- modules/calendar/e-cal-shell-view-private.c | 2 +- modules/calendar/e-task-shell-backend.c | 2 +- 3 files changed, 151 insertions(+), 4 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-backend.c b/modules/calendar/e-cal-shell-backend.c index 145bff6db5..6d9c74411b 100644 --- a/modules/calendar/e-cal-shell-backend.c +++ b/modules/calendar/e-cal-shell-backend.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -552,8 +553,154 @@ static gboolean cal_shell_backend_handle_uri_cb (EShellBackend *shell_backend, const gchar *uri) { - /* FIXME */ - return FALSE; + EShell *shell; + CompEditor *editor; + CompEditorFlags flags = 0; + ECal *client; + ECalComponent *comp; + ESource *source; + ESourceList *source_list; + ECalSourceType source_type; + EUri *euri; + icalcomponent *icalcomp; + icalproperty *icalprop; + const gchar *cp; + gchar *source_uid = NULL; + gchar *comp_uid = NULL; + gchar *comp_rid = NULL; + time_t startdate = -1; + time_t enddate = -1; + gboolean handled = FALSE; + GError *error = NULL; + + source_type = E_CAL_SOURCE_TYPE_EVENT; + shell = e_shell_backend_get_shell (shell_backend); + + if (strncmp (uri, "calendar:", 9) != 0) + return FALSE; + + euri = e_uri_new (uri); + cp = euri->query; + if (cp == NULL) + goto exit; + + while (*cp != '\0') { + gchar *header; + gchar *content; + gsize header_len; + gsize content_len; + + header_len = strcspn (cp, "=&"); + + /* It it's malformed, give up. */ + if (cp[header_len] != '=') + break; + + header = (gchar *) cp; + header[header_len] = '\0'; + cp += header_len + 1; + + content_len = strcspn (cp, "&"); + + content = g_strndup (cp, content_len); + if (g_ascii_strcasecmp (header, "startdate") == 0) + startdate = time_from_isodate (content); + else if (g_ascii_strcasecmp (header, "enddate") == 0) + enddate = time_from_isodate (content); + else if (g_ascii_strcasecmp (header, "source-uid") == 0) + source_uid = g_strdup (content); + else if (g_ascii_strcasecmp (header, "comp-uid") == 0) + comp_uid = g_strdup (content); + else if (g_ascii_strcasecmp (header, "comp-rid") == 0) + comp_rid = g_strdup (content); + g_free (content); + + cp += content_len; + if (*cp == '&') { + cp++; + if (strcmp (cp, "amp;") == 0) + cp += 4; + } + } + + if (source_uid == NULL || comp_uid == NULL) + goto exit; + + /* URI is valid, so consider it handled. Whether + * we successfully open it is another matter... */ + handled = TRUE; + + if (!e_cal_get_sources (&source_list, source_type, NULL)) { + g_printerr ("Could not get calendar sources from GConf!\n"); + goto exit; + } + + source = e_source_list_peek_source_by_uid (source_list, source_uid); + if (source == NULL) { + g_printerr ("No source for UID `%s'\n", source_uid); + g_object_unref (source_list); + goto exit; + } + + client = auth_new_cal_from_source (source, source_type); + if (client == NULL || !e_cal_open (client, TRUE, &error)) { + g_printerr ("%s\n", error->message); + g_object_unref (source_list); + g_error_free (error); + goto exit; + } + + /* XXX Copied from e_cal_shell_view_open_event(). + * Clearly a new utility function is needed. */ + + editor = comp_editor_find_instance (comp_uid); + + if (editor != NULL) + goto present; + + if (!e_cal_get_object (client, comp_uid, comp_rid, &icalcomp, &error)) { + g_printerr ("%s\n", error->message); + g_object_unref (source_list); + g_error_free (error); + goto exit; + } + + comp = e_cal_component_new (); + e_cal_component_set_icalcomponent (comp, icalcomp); + + icalprop = icalcomponent_get_first_property ( + icalcomp, ICAL_ATTENDEE_PROPERTY); + if (icalprop != NULL) + flags |= COMP_EDITOR_MEETING; + + if (itip_organizer_is_user (comp, client)) + flags |= COMP_EDITOR_USER_ORG; + + if (itip_sentby_is_user (comp, client)) + flags |= COMP_EDITOR_USER_ORG; + + if (!e_cal_component_has_attendees (comp)) + flags |= COMP_EDITOR_USER_ORG; + + editor = event_editor_new (client, shell, flags); + comp_editor_edit_comp (editor, comp); + + g_object_unref (comp); + +present: + gtk_window_present (GTK_WINDOW (editor)); + + g_object_unref (source_list); + g_object_unref (client); + +exit: + g_free (source_uid); + g_free (comp_uid); + g_free (comp_rid); + + e_uri_free (euri); + + return handled; } static void diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c index d6771314df..6601228ad3 100644 --- a/modules/calendar/e-cal-shell-view-private.c +++ b/modules/calendar/e-cal-shell-view-private.c @@ -780,7 +780,7 @@ e_cal_shell_view_open_event (ECalShellView *cal_shell_view, editor = event_editor_new (comp_data->client, shell, flags); comp_editor_edit_comp (editor, comp); - g_object_ref (comp); + g_object_unref (comp); exit: gtk_window_present (GTK_WINDOW (editor)); diff --git a/modules/calendar/e-task-shell-backend.c b/modules/calendar/e-task-shell-backend.c index 23d5e35d7b..500dd30423 100644 --- a/modules/calendar/e-task-shell-backend.c +++ b/modules/calendar/e-task-shell-backend.c @@ -430,7 +430,7 @@ task_module_handle_uri_cb (EShellBackend *shell_backend, } } - if (source_uid != NULL || comp_uid != NULL) + if (source_uid == NULL || comp_uid == NULL) goto exit; /* URI is valid, so consider it handled. Whether -- cgit v1.2.3 From 2b8c7c62aa3d172e3530c0570be29dfaac501432 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Mon, 24 Aug 2009 23:08:13 -0400 Subject: Exit if no command-line URIs are handled. --- modules/calendar/e-memo-shell-backend.c | 18 ++++++++++-------- modules/calendar/e-task-shell-backend.c | 18 ++++++++++-------- 2 files changed, 20 insertions(+), 16 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-memo-shell-backend.c b/modules/calendar/e-memo-shell-backend.c index 9642528b78..6c6a36491c 100644 --- a/modules/calendar/e-memo-shell-backend.c +++ b/modules/calendar/e-memo-shell-backend.c @@ -62,7 +62,7 @@ static gpointer parent_class; static GType memo_shell_backend_type; static void -memo_module_ensure_sources (EShellBackend *shell_backend) +memo_shell_backend_ensure_sources (EShellBackend *shell_backend) { /* XXX This is basically the same algorithm across all modules. * Maybe we could somehow integrate this into EShellBackend? */ @@ -361,8 +361,8 @@ static GtkActionEntry source_entries[] = { }; static gboolean -memo_module_handle_uri_cb (EShellBackend *shell_backend, - const gchar *uri) +memo_shell_backend_handle_uri_cb (EShellBackend *shell_backend, + const gchar *uri) { EShell *shell; CompEditor *editor; @@ -500,8 +500,8 @@ exit: } static void -memo_module_window_created_cb (EShellBackend *shell_backend, - GtkWindow *window) +memo_shell_backend_window_created_cb (EShellBackend *shell_backend, + GtkWindow *window) { const gchar *module_name; @@ -562,15 +562,17 @@ memo_shell_backend_constructed (GObject *object) shell_backend = E_SHELL_BACKEND (object); shell = e_shell_backend_get_shell (shell_backend); - memo_module_ensure_sources (shell_backend); + memo_shell_backend_ensure_sources (shell_backend); g_signal_connect_swapped ( shell, "handle-uri", - G_CALLBACK (memo_module_handle_uri_cb), shell_backend); + G_CALLBACK (memo_shell_backend_handle_uri_cb), + shell_backend); g_signal_connect_swapped ( shell, "window-created", - G_CALLBACK (memo_module_window_created_cb), shell_backend); + G_CALLBACK (memo_shell_backend_window_created_cb), + shell_backend); } static void diff --git a/modules/calendar/e-task-shell-backend.c b/modules/calendar/e-task-shell-backend.c index 500dd30423..59a87e653c 100644 --- a/modules/calendar/e-task-shell-backend.c +++ b/modules/calendar/e-task-shell-backend.c @@ -64,7 +64,7 @@ static gpointer parent_class; static GType task_shell_backend_type; static void -task_module_ensure_sources (EShellBackend *shell_backend) +task_shell_backend_ensure_sources (EShellBackend *shell_backend) { /* XXX This is basically the same algorithm across all modules. * Maybe we could somehow integrate this into EShellBackend? */ @@ -363,8 +363,8 @@ static GtkActionEntry source_entries[] = { }; static gboolean -task_module_handle_uri_cb (EShellBackend *shell_backend, - const gchar *uri) +task_shell_backend_handle_uri_cb (EShellBackend *shell_backend, + const gchar *uri) { EShell *shell; CompEditor *editor; @@ -508,8 +508,8 @@ exit: } static void -task_module_window_created_cb (EShellBackend *shell_backend, - GtkWindow *window) +task_shell_backend_window_created_cb (EShellBackend *shell_backend, + GtkWindow *window) { const gchar *module_name; @@ -570,15 +570,17 @@ task_shell_backend_constructed (GObject *object) shell_backend = E_SHELL_BACKEND (object); shell = e_shell_backend_get_shell (shell_backend); - task_module_ensure_sources (shell_backend); + task_shell_backend_ensure_sources (shell_backend); g_signal_connect_swapped ( shell, "handle-uri", - G_CALLBACK (task_module_handle_uri_cb), shell_backend); + G_CALLBACK (task_shell_backend_handle_uri_cb), + shell_backend); g_signal_connect_swapped ( shell, "window-created", - G_CALLBACK (task_module_window_created_cb), shell_backend); + G_CALLBACK (task_shell_backend_window_created_cb), + shell_backend); } static void -- cgit v1.2.3 From d46710704af21108c5e38fc793dc1ba5a3f50390 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Wed, 26 Aug 2009 12:44:32 -0400 Subject: Fix resize behavior of main window panes. Now that I finally understand how the "resize" and "shrink" child properties in GtkPaned work. Was a real brain teaser for some reason. --- modules/calendar/e-cal-shell-content.c | 4 ++-- modules/calendar/e-memo-shell-content.c | 4 ++-- modules/calendar/e-task-shell-content.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c index 9248ea8334..6b1e857894 100644 --- a/modules/calendar/e-cal-shell-content.c +++ b/modules/calendar/e-cal-shell-content.c @@ -356,14 +356,14 @@ cal_shell_content_constructed (GObject *object) widget = gtk_notebook_new (); gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE); gtk_notebook_set_show_border (GTK_NOTEBOOK (widget), FALSE); - gtk_paned_pack1 (GTK_PANED (container), widget, FALSE, TRUE); + gtk_paned_pack1 (GTK_PANED (container), widget, TRUE, FALSE); priv->notebook = g_object_ref (widget); gtk_widget_show (widget); /* FIXME Need to deal with saving and restoring the position. * Month view has its own position. */ widget = gtk_vpaned_new (); - gtk_paned_pack2 (GTK_PANED (container), widget, TRUE, TRUE); + gtk_paned_pack2 (GTK_PANED (container), widget, FALSE, TRUE); priv->vpaned = g_object_ref (widget); gtk_widget_show (widget); diff --git a/modules/calendar/e-memo-shell-content.c b/modules/calendar/e-memo-shell-content.c index 3a7ee78718..7c7b84f3fb 100644 --- a/modules/calendar/e-memo-shell-content.c +++ b/modules/calendar/e-memo-shell-content.c @@ -393,7 +393,7 @@ memo_shell_content_constructed (GObject *object) container = widget; widget = e_memo_table_new (shell_view, priv->memo_model); - gtk_paned_add1 (GTK_PANED (container), widget); + gtk_paned_pack1 (GTK_PANED (container), widget, TRUE, FALSE); priv->memo_table = g_object_ref (widget); gtk_widget_show (widget); @@ -403,7 +403,7 @@ memo_shell_content_constructed (GObject *object) GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type ( GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); - gtk_paned_add2 (GTK_PANED (container), widget); + gtk_paned_pack2 (GTK_PANED (container), widget, FALSE, FALSE); gtk_widget_show (widget); container = widget; diff --git a/modules/calendar/e-task-shell-content.c b/modules/calendar/e-task-shell-content.c index 88e5e4d856..c1333727bf 100644 --- a/modules/calendar/e-task-shell-content.c +++ b/modules/calendar/e-task-shell-content.c @@ -392,7 +392,7 @@ task_shell_content_constructed (GObject *object) container = widget; widget = e_calendar_table_new (shell_view, priv->task_model); - gtk_paned_add1 (GTK_PANED (container), widget); + gtk_paned_pack1 (GTK_PANED (container), widget, TRUE, FALSE); priv->task_table = g_object_ref (widget); gtk_widget_show (widget); @@ -402,7 +402,7 @@ task_shell_content_constructed (GObject *object) GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type ( GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); - gtk_paned_add2 (GTK_PANED (container), widget); + gtk_paned_pack2 (GTK_PANED (container), widget, FALSE, FALSE); gtk_widget_show (widget); container = widget; -- cgit v1.2.3 From 8818c5e3334a6f2f16571b31a715cd9e0e1aa38a Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Wed, 26 Aug 2009 12:53:32 -0400 Subject: More panel resizing goodness. --- modules/calendar/e-cal-shell-content.c | 4 ++-- modules/calendar/e-cal-shell-sidebar.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c index 6b1e857894..408f07fdc6 100644 --- a/modules/calendar/e-cal-shell-content.c +++ b/modules/calendar/e-cal-shell-content.c @@ -394,7 +394,7 @@ cal_shell_content_constructed (GObject *object) container = priv->vpaned; widget = gtk_vbox_new (FALSE, 0); - gtk_paned_pack1 (GTK_PANED (container), widget, FALSE, FALSE); + gtk_paned_pack1 (GTK_PANED (container), widget, TRUE, TRUE); gtk_widget_show (widget); container = widget; @@ -422,7 +422,7 @@ cal_shell_content_constructed (GObject *object) container = priv->vpaned; widget = gtk_vbox_new (FALSE, 0); - gtk_paned_pack2 (GTK_PANED (container), widget, TRUE, FALSE); + gtk_paned_pack2 (GTK_PANED (container), widget, TRUE, TRUE); gtk_widget_show (widget); container = widget; diff --git a/modules/calendar/e-cal-shell-sidebar.c b/modules/calendar/e-cal-shell-sidebar.c index f8f6acae9b..c25b247f36 100644 --- a/modules/calendar/e-cal-shell-sidebar.c +++ b/modules/calendar/e-cal-shell-sidebar.c @@ -414,7 +414,7 @@ cal_shell_sidebar_constructed (GObject *object) GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type ( GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); - gtk_paned_add1 (GTK_PANED (container), widget); + gtk_paned_pack1 (GTK_PANED (container), widget, TRUE, TRUE); gtk_widget_show (widget); container = widget; @@ -433,7 +433,7 @@ cal_shell_sidebar_constructed (GObject *object) calitem = E_CALENDAR (widget)->calitem; e_calendar_item_set_days_start_week_sel (calitem, 9); e_calendar_item_set_max_days_sel (calitem, 42); - gtk_paned_add2 (GTK_PANED (container), widget); + gtk_paned_pack2 (GTK_PANED (container), widget, FALSE, TRUE); priv->date_navigator = g_object_ref (widget); gtk_widget_show (widget); -- cgit v1.2.3 From 7dc82b2dcbab7f85504c3061ef45cc4249821e42 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Thu, 27 Aug 2009 13:38:17 -0400 Subject: Add vertical view to Memos and Tasks. --- modules/calendar/e-memo-shell-content.c | 112 +++++++++++++++++++-------- modules/calendar/e-memo-shell-content.h | 6 +- modules/calendar/e-memo-shell-view-actions.c | 72 ++++++++++++++++- modules/calendar/e-memo-shell-view-actions.h | 4 + modules/calendar/e-task-shell-content.c | 111 ++++++++++++++++++-------- modules/calendar/e-task-shell-content.h | 6 +- modules/calendar/e-task-shell-view-actions.c | 68 ++++++++++++++++ modules/calendar/e-task-shell-view-actions.h | 4 + 8 files changed, 310 insertions(+), 73 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-memo-shell-content.c b/modules/calendar/e-memo-shell-content.c index 7c7b84f3fb..2f4e436056 100644 --- a/modules/calendar/e-memo-shell-content.c +++ b/modules/calendar/e-memo-shell-content.c @@ -23,14 +23,15 @@ #include +#include "e-util/e-binding.h" #include "e-util/gconf-bridge.h" +#include "widgets/menus/gal-view-etable.h" +#include "widgets/misc/e-paned.h" #include "calendar/gui/comp-util.h" #include "calendar/gui/e-cal-model-memos.h" #include "calendar/gui/e-memo-table.h" -#include "widgets/menus/gal-view-etable.h" - #define E_MEMO_SHELL_CONTENT_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE \ ((obj), E_TYPE_MEMO_SHELL_CONTENT, EMemoShellContentPrivate)) @@ -51,13 +52,17 @@ struct _EMemoShellContentPrivate { ECalModel *memo_model; GalViewInstance *view_instance; + GtkOrientation orientation; gchar *current_uid; + + guint preview_visible : 1; }; enum { PROP_0, PROP_MODEL, + PROP_ORIENTATION, PROP_PREVIEW_VISIBLE }; @@ -258,6 +263,21 @@ memo_shell_content_model_row_changed_cb (EMemoShellContent *memo_shell_content, memo_shell_content_cursor_change_cb (memo_shell_content, 0, table); } +static GtkOrientation +memo_shell_content_get_orientation (EMemoShellContent *memo_shell_content) +{ + return memo_shell_content->priv->orientation; +} + +static void +memo_shell_content_set_orientation (EMemoShellContent *memo_shell_content, + GtkOrientation orientation) +{ + memo_shell_content->priv->orientation = orientation; + + g_object_notify (G_OBJECT (memo_shell_content), "orientation"); +} + static void memo_shell_content_set_property (GObject *object, guint property_id, @@ -265,6 +285,12 @@ memo_shell_content_set_property (GObject *object, GParamSpec *pspec) { switch (property_id) { + case PROP_ORIENTATION: + memo_shell_content_set_orientation ( + E_MEMO_SHELL_CONTENT (object), + g_value_get_enum (value)); + return; + case PROP_PREVIEW_VISIBLE: e_memo_shell_content_set_preview_visible ( E_MEMO_SHELL_CONTENT (object), @@ -284,13 +310,22 @@ memo_shell_content_get_property (GObject *object, switch (property_id) { case PROP_MODEL: g_value_set_object ( - value, e_memo_shell_content_get_memo_model ( + value, + e_memo_shell_content_get_memo_model ( + E_MEMO_SHELL_CONTENT (object))); + return; + + case PROP_ORIENTATION: + g_value_set_enum ( + value, + memo_shell_content_get_orientation ( E_MEMO_SHELL_CONTENT (object))); return; case PROP_PREVIEW_VISIBLE: g_value_set_boolean ( - value, e_memo_shell_content_get_preview_visible ( + value, + e_memo_shell_content_get_preview_visible ( E_MEMO_SHELL_CONTENT (object))); return; } @@ -385,11 +420,15 @@ memo_shell_content_constructed (GObject *object) container = GTK_WIDGET (object); - widget = gtk_vpaned_new (); + widget = e_paned_new (GTK_ORIENTATION_VERTICAL); gtk_container_add (GTK_CONTAINER (container), widget); priv->paned = g_object_ref (widget); gtk_widget_show (widget); + e_binding_new ( + G_OBJECT (object), "orientation", + G_OBJECT (widget), "orientation"); + container = widget; widget = e_memo_table_new (shell_view, priv->memo_model); @@ -406,6 +445,10 @@ memo_shell_content_constructed (GObject *object) gtk_paned_pack2 (GTK_PANED (container), widget, FALSE, FALSE); gtk_widget_show (widget); + e_binding_new ( + G_OBJECT (object), "preview-visible", + G_OBJECT (widget), "visible"); + container = widget; widget = e_cal_component_preview_new (); @@ -466,9 +509,13 @@ memo_shell_content_constructed (GObject *object) bridge = gconf_bridge_get (); + object = G_OBJECT (priv->paned); + key = "/apps/evolution/calendar/display/memo_hpane_position"; + gconf_bridge_bind_property_delayed (bridge, key, object, "hposition"); + object = G_OBJECT (priv->paned); key = "/apps/evolution/calendar/display/memo_vpane_position"; - gconf_bridge_bind_property_delayed (bridge, key, object, "position"); + gconf_bridge_bind_property_delayed (bridge, key, object, "vposition"); } static guint32 @@ -553,7 +600,11 @@ memo_shell_content_class_init (EMemoShellContentClass *class) _("Preview is Visible"), _("Whether the preview pane is visible"), TRUE, - G_PARAM_READWRITE)); + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_override_property ( + object_class, PROP_ORIENTATION, "orientation"); } static void @@ -587,9 +638,19 @@ e_memo_shell_content_register_type (GTypeModule *type_module) NULL /* value_table */ }; + static const GInterfaceInfo orientable_info = { + (GInterfaceInitFunc) NULL, + (GInterfaceFinalizeFunc) NULL, + NULL /* interface_data */ + }; + memo_shell_content_type = g_type_module_register_type ( type_module, E_TYPE_SHELL_CONTENT, "EMemoShellContent", &type_info, 0); + + g_type_module_add_interface ( + type_module, memo_shell_content_type, + GTK_TYPE_ORIENTABLE, &orientable_info); } GtkWidget * @@ -630,46 +691,31 @@ e_memo_shell_content_get_memo_table (EMemoShellContent *memo_shell_content) return E_MEMO_TABLE (memo_shell_content->priv->memo_table); } -GalViewInstance * -e_memo_shell_content_get_view_instance (EMemoShellContent *memo_shell_content) -{ - g_return_val_if_fail ( - E_IS_MEMO_SHELL_CONTENT (memo_shell_content), NULL); - - return memo_shell_content->priv->view_instance; -} - gboolean e_memo_shell_content_get_preview_visible (EMemoShellContent *memo_shell_content) { - GtkPaned *paned; - GtkWidget *child; - g_return_val_if_fail ( E_IS_MEMO_SHELL_CONTENT (memo_shell_content), FALSE); - paned = GTK_PANED (memo_shell_content->priv->paned); - child = gtk_paned_get_child2 (paned); - - return GTK_WIDGET_VISIBLE (child); + return memo_shell_content->priv->preview_visible; } void e_memo_shell_content_set_preview_visible (EMemoShellContent *memo_shell_content, gboolean preview_visible) { - GtkPaned *paned; - GtkWidget *child; - g_return_if_fail (E_IS_MEMO_SHELL_CONTENT (memo_shell_content)); - paned = GTK_PANED (memo_shell_content->priv->paned); - child = gtk_paned_get_child2 (paned); - - if (preview_visible) - gtk_widget_show (child); - else - gtk_widget_hide (child); + memo_shell_content->priv->preview_visible = preview_visible; g_object_notify (G_OBJECT (memo_shell_content), "preview-visible"); } + +GalViewInstance * +e_memo_shell_content_get_view_instance (EMemoShellContent *memo_shell_content) +{ + g_return_val_if_fail ( + E_IS_MEMO_SHELL_CONTENT (memo_shell_content), NULL); + + return memo_shell_content->priv->view_instance; +} diff --git a/modules/calendar/e-memo-shell-content.h b/modules/calendar/e-memo-shell-content.h index 84c22d6ce4..ae2710e148 100644 --- a/modules/calendar/e-memo-shell-content.h +++ b/modules/calendar/e-memo-shell-content.h @@ -82,14 +82,14 @@ ECalComponentPreview * (EMemoShellContent *memo_shell_content); EMemoTable * e_memo_shell_content_get_memo_table (EMemoShellContent *memo_shell_content); -GalViewInstance * - e_memo_shell_content_get_view_instance - (EMemoShellContent *memo_shell_content); gboolean e_memo_shell_content_get_preview_visible (EMemoShellContent *memo_shell_content); void e_memo_shell_content_set_preview_visible (EMemoShellContent *memo_shell_content, gboolean preview_visible); +GalViewInstance * + e_memo_shell_content_get_view_instance + (EMemoShellContent *memo_shell_content); G_END_DECLS diff --git a/modules/calendar/e-memo-shell-view-actions.c b/modules/calendar/e-memo-shell-view-actions.c index 2d6713a7a8..0161eeb198 100644 --- a/modules/calendar/e-memo-shell-view-actions.c +++ b/modules/calendar/e-memo-shell-view-actions.c @@ -527,6 +527,32 @@ action_memo_search_cb (GtkRadioAction *action, e_shell_content_set_search_hint (shell_content, search_hint); } +static void +action_memo_view_cb (GtkRadioAction *action, + GtkRadioAction *current, + EMemoShellView *memo_shell_view) +{ + EMemoShellContent *memo_shell_content; + GtkOrientable *orientable; + GtkOrientation orientation; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + orientable = GTK_ORIENTABLE (memo_shell_content); + + switch (gtk_radio_action_get_current_value (action)) { + case 0: + orientation = GTK_ORIENTATION_VERTICAL; + break; + case 1: + orientation = GTK_ORIENTATION_HORIZONTAL; + break; + default: + g_return_if_reached (); + } + + gtk_orientable_set_orientation (orientable, orientation); +} + static void action_search_execute_cb (GtkAction *action, EMemoShellView *memo_shell_view) @@ -662,7 +688,16 @@ static GtkActionEntry memo_entries[] = { N_("_Save as iCalendar..."), NULL, NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_memo_save_as_cb) } + G_CALLBACK (action_memo_save_as_cb) }, + + /*** Menus ***/ + + { "memo-preview-menu", + NULL, + N_("_Preview"), + NULL, + NULL, + NULL } }; static EPopupActionEntry memo_popup_entries[] = { @@ -731,6 +766,33 @@ static GtkToggleActionEntry memo_toggle_entries[] = { TRUE } }; +static GtkRadioActionEntry memo_view_entries[] = { + + /* This action represents the initial active memo view. + * It should not be visible in the UI, nor should it be + * possible to switch to it from another shell view. */ + { "memo-view-initial", + NULL, + NULL, + NULL, + NULL, + -1 }, + + { "memo-view-classic", + NULL, + N_("_Classic View"), + NULL, + N_("Show memo preview below the memo list"), + 0 }, + + { "memo-view-vertical", + NULL, + N_("_Vertical View"), + NULL, + N_("Show memo preview alongside the memo list"), + 1 } +}; + static GtkRadioActionEntry memo_filter_entries[] = { { "memo-filter-any-category", @@ -828,6 +890,10 @@ e_memo_shell_view_actions_init (EMemoShellView *memo_shell_view) gtk_action_group_add_toggle_actions ( action_group, memo_toggle_entries, G_N_ELEMENTS (memo_toggle_entries), memo_shell_view); + gtk_action_group_add_radio_actions ( + action_group, memo_view_entries, + G_N_ELEMENTS (memo_view_entries), -1, + G_CALLBACK (action_memo_view_cb), memo_shell_view); gtk_action_group_add_radio_actions ( action_group, memo_search_entries, G_N_ELEMENTS (memo_search_entries), @@ -851,6 +917,10 @@ e_memo_shell_view_actions_init (EMemoShellView *memo_shell_view) key = "/apps/evolution/calendar/display/show_memo_preview"; gconf_bridge_bind_property (bridge, key, object, "active"); + object = G_OBJECT (ACTION (MEMO_VIEW_VERTICAL)); + key = "/apps/evolution/calendar/display/memo_layout"; + gconf_bridge_bind_property (bridge, key, object, "current-value"); + /* Fine tuning. */ action = ACTION (MEMO_DELETE); diff --git a/modules/calendar/e-memo-shell-view-actions.h b/modules/calendar/e-memo-shell-view-actions.h index d6fd3ca514..d43d0239d9 100644 --- a/modules/calendar/e-memo-shell-view-actions.h +++ b/modules/calendar/e-memo-shell-view-actions.h @@ -47,6 +47,10 @@ E_SHELL_WINDOW_ACTION ((window), "memo-print") #define E_SHELL_WINDOW_ACTION_MEMO_SAVE_AS(window) \ E_SHELL_WINDOW_ACTION ((window), "memo-save-as") +#define E_SHELL_WINDOW_ACTION_MEMO_VIEW_CLASSIC(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-view-classic") +#define E_SHELL_WINDOW_ACTION_MEMO_VIEW_VERTICAL(window) \ + E_SHELL_WINDOW_ACTION ((window), "memo-view-vertical") /* Memo List Actions */ #define E_SHELL_WINDOW_ACTION_MEMO_LIST_COPY(window) \ diff --git a/modules/calendar/e-task-shell-content.c b/modules/calendar/e-task-shell-content.c index c1333727bf..a095003978 100644 --- a/modules/calendar/e-task-shell-content.c +++ b/modules/calendar/e-task-shell-content.c @@ -25,13 +25,13 @@ #include "e-util/e-binding.h" #include "e-util/gconf-bridge.h" +#include "widgets/menus/gal-view-etable.h" +#include "widgets/misc/e-paned.h" #include "calendar/gui/comp-util.h" #include "calendar/gui/e-cal-model-tasks.h" #include "calendar/gui/e-calendar-table.h" -#include "widgets/menus/gal-view-etable.h" - #define E_TASK_SHELL_CONTENT_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE \ ((obj), E_TYPE_TASK_SHELL_CONTENT, ETaskShellContentPrivate)) @@ -53,13 +53,17 @@ struct _ETaskShellContentPrivate { ECalModel *task_model; GalViewInstance *view_instance; + GtkOrientation orientation; gchar *current_uid; + + guint preview_visible : 1; }; enum { PROP_0, PROP_MODEL, + PROP_ORIENTATION, PROP_PREVIEW_VISIBLE }; @@ -258,6 +262,21 @@ task_shell_content_model_row_changed_cb (ETaskShellContent *task_shell_content, task_shell_content_cursor_change_cb (task_shell_content, 0, table); } +static GtkOrientation +task_shell_content_get_orientation (ETaskShellContent *task_shell_content) +{ + return task_shell_content->priv->orientation; +} + +static void +task_shell_content_set_orientation (ETaskShellContent *task_shell_content, + GtkOrientation orientation) +{ + task_shell_content->priv->orientation = orientation; + + g_object_notify (G_OBJECT (task_shell_content), "orientation"); +} + static void task_shell_content_set_property (GObject *object, guint property_id, @@ -265,6 +284,12 @@ task_shell_content_set_property (GObject *object, GParamSpec *pspec) { switch (property_id) { + case PROP_ORIENTATION: + task_shell_content_set_orientation ( + E_TASK_SHELL_CONTENT (object), + g_value_get_enum (value)); + return; + case PROP_PREVIEW_VISIBLE: e_task_shell_content_set_preview_visible ( E_TASK_SHELL_CONTENT (object), @@ -284,13 +309,22 @@ task_shell_content_get_property (GObject *object, switch (property_id) { case PROP_MODEL: g_value_set_object ( - value, e_task_shell_content_get_task_model ( + value, + e_task_shell_content_get_task_model ( + E_TASK_SHELL_CONTENT (object))); + return; + + case PROP_ORIENTATION: + g_value_set_enum ( + value, + task_shell_content_get_orientation ( E_TASK_SHELL_CONTENT (object))); return; case PROP_PREVIEW_VISIBLE: g_value_set_boolean ( - value, e_task_shell_content_get_preview_visible ( + value, + e_task_shell_content_get_preview_visible ( E_TASK_SHELL_CONTENT (object))); return; } @@ -384,11 +418,15 @@ task_shell_content_constructed (GObject *object) container = GTK_WIDGET (object); - widget = gtk_vpaned_new (); + widget = e_paned_new (GTK_ORIENTATION_VERTICAL); gtk_container_add (GTK_CONTAINER (container), widget); priv->paned = g_object_ref (widget); gtk_widget_show (widget); + e_binding_new ( + G_OBJECT (object), "orientation", + G_OBJECT (widget), "orientation"); + container = widget; widget = e_calendar_table_new (shell_view, priv->task_model); @@ -405,6 +443,10 @@ task_shell_content_constructed (GObject *object) gtk_paned_pack2 (GTK_PANED (container), widget, FALSE, FALSE); gtk_widget_show (widget); + e_binding_new ( + G_OBJECT (object), "preview-visible", + G_OBJECT (widget), "visible"); + container = widget; widget = e_cal_component_preview_new (); @@ -465,9 +507,13 @@ task_shell_content_constructed (GObject *object) bridge = gconf_bridge_get (); + object = G_OBJECT (priv->paned); + key = "/apps/evolution/calendar/display/task_hpane_position"; + gconf_bridge_bind_property_delayed (bridge, key, object, "hposition"); + object = G_OBJECT (priv->paned); key = "/apps/evolution/calendar/display/task_vpane_position"; - gconf_bridge_bind_property_delayed (bridge, key, object, "position"); + gconf_bridge_bind_property_delayed (bridge, key, object, "vposition"); } static guint32 @@ -577,7 +623,11 @@ task_shell_content_class_init (ETaskShellContentClass *class) _("Preview is Visible"), _("Whether the preview pane is visible"), TRUE, - G_PARAM_READWRITE)); + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_override_property ( + object_class, PROP_ORIENTATION, "orientation"); } static void @@ -611,9 +661,19 @@ e_task_shell_content_register_type (GTypeModule *type_module) NULL /* value_table */ }; + static const GInterfaceInfo orientable_info = { + (GInterfaceInitFunc) NULL, + (GInterfaceFinalizeFunc) NULL, + NULL /* interface_data */ + }; + task_shell_content_type = g_type_module_register_type ( type_module, E_TYPE_SHELL_CONTENT, "ETaskShellContent", &type_info, 0); + + g_type_module_add_interface ( + type_module, task_shell_content_type, + GTK_TYPE_ORIENTABLE, &orientable_info); } GtkWidget * @@ -654,46 +714,31 @@ e_task_shell_content_get_task_table (ETaskShellContent *task_shell_content) return E_CALENDAR_TABLE (task_shell_content->priv->task_table); } -GalViewInstance * -e_task_shell_content_get_view_instance (ETaskShellContent *task_shell_content) -{ - g_return_val_if_fail ( - E_IS_TASK_SHELL_CONTENT (task_shell_content), NULL); - - return task_shell_content->priv->view_instance; -} - gboolean e_task_shell_content_get_preview_visible (ETaskShellContent *task_shell_content) { - GtkPaned *paned; - GtkWidget *child; - g_return_val_if_fail ( E_IS_TASK_SHELL_CONTENT (task_shell_content), FALSE); - paned = GTK_PANED (task_shell_content->priv->paned); - child = gtk_paned_get_child2 (paned); - - return GTK_WIDGET_VISIBLE (child); + return task_shell_content->priv->preview_visible; } void e_task_shell_content_set_preview_visible (ETaskShellContent *task_shell_content, gboolean preview_visible) { - GtkPaned *paned; - GtkWidget *child; - g_return_if_fail (E_IS_TASK_SHELL_CONTENT (task_shell_content)); - paned = GTK_PANED (task_shell_content->priv->paned); - child = gtk_paned_get_child2 (paned); - - if (preview_visible) - gtk_widget_show (child); - else - gtk_widget_hide (child); + task_shell_content->priv->preview_visible = preview_visible; g_object_notify (G_OBJECT (task_shell_content), "preview-visible"); } + +GalViewInstance * +e_task_shell_content_get_view_instance (ETaskShellContent *task_shell_content) +{ + g_return_val_if_fail ( + E_IS_TASK_SHELL_CONTENT (task_shell_content), NULL); + + return task_shell_content->priv->view_instance; +} diff --git a/modules/calendar/e-task-shell-content.h b/modules/calendar/e-task-shell-content.h index 7e0b2128a7..f5d4fc9665 100644 --- a/modules/calendar/e-task-shell-content.h +++ b/modules/calendar/e-task-shell-content.h @@ -86,14 +86,14 @@ ECalComponentPreview * (ETaskShellContent *task_shell_content); ECalendarTable *e_task_shell_content_get_task_table (ETaskShellContent *task_shell_content); -GalViewInstance * - e_task_shell_content_get_view_instance - (ETaskShellContent *task_shell_content); gboolean e_task_shell_content_get_preview_visible (ETaskShellContent *task_shell_content); void e_task_shell_content_set_preview_visible (ETaskShellContent *task_shell_content, gboolean preview_visible); +GalViewInstance * + e_task_shell_content_get_view_instance + (ETaskShellContent *task_shell_content); G_END_DECLS diff --git a/modules/calendar/e-task-shell-view-actions.c b/modules/calendar/e-task-shell-view-actions.c index d1354026cb..d4fb94c2e5 100644 --- a/modules/calendar/e-task-shell-view-actions.c +++ b/modules/calendar/e-task-shell-view-actions.c @@ -675,6 +675,32 @@ action_task_search_cb (GtkRadioAction *action, e_shell_content_set_search_hint (shell_content, search_hint); } +static void +action_task_view_cb (GtkRadioAction *action, + GtkRadioAction *current, + ETaskShellView *task_shell_view) +{ + ETaskShellContent *task_shell_content; + GtkOrientable *orientable; + GtkOrientation orientation; + + task_shell_content = task_shell_view->priv->task_shell_content; + orientable = GTK_ORIENTABLE (task_shell_content); + + switch (gtk_radio_action_get_current_value (action)) { + case 0: + orientation = GTK_ORIENTATION_VERTICAL; + break; + case 1: + orientation = GTK_ORIENTATION_HORIZONTAL; + break; + default: + g_return_if_reached (); + } + + gtk_orientable_set_orientation (orientable, orientation); +} + static GtkActionEntry task_entries[] = { { "task-assign", @@ -817,6 +843,13 @@ static GtkActionEntry task_entries[] = { N_("_Actions"), NULL, NULL, + NULL }, + + { "task-preview-menu", + NULL, + N_("_Preview"), + NULL, + NULL, NULL } }; @@ -898,6 +931,33 @@ static GtkToggleActionEntry task_toggle_entries[] = { TRUE } }; +static GtkRadioActionEntry task_view_entries[] = { + + /* This action represents the inital active memo view. + * It should not be visible in the UI, nor should it be + * possible to switch to it from another shell view. */ + { "task-view-initial", + NULL, + NULL, + NULL, + NULL, + -1 }, + + { "task-view-classic", + NULL, + N_("_Classic View"), + NULL, + N_("Show task preview below the task list"), + 0 }, + + { "task-view-vertical", + NULL, + N_("_Vertical View"), + NULL, + N_("Show task preview alongside the task list"), + 1 } +}; + static GtkRadioActionEntry task_filter_entries[] = { { "task-filter-active-tasks", @@ -1030,6 +1090,10 @@ e_task_shell_view_actions_init (ETaskShellView *task_shell_view) gtk_action_group_add_toggle_actions ( action_group, task_toggle_entries, G_N_ELEMENTS (task_toggle_entries), task_shell_view); + gtk_action_group_add_radio_actions ( + action_group, task_view_entries, + G_N_ELEMENTS (task_view_entries), -1, + G_CALLBACK (action_task_view_cb), task_shell_view); gtk_action_group_add_radio_actions ( action_group, task_search_entries, G_N_ELEMENTS (task_search_entries), @@ -1053,6 +1117,10 @@ e_task_shell_view_actions_init (ETaskShellView *task_shell_view) key = "/apps/evolution/calendar/display/show_task_preview"; gconf_bridge_bind_property (bridge, key, object, "active"); + object = G_OBJECT (ACTION (TASK_VIEW_VERTICAL)); + key = "/apps/evolution/calendar/display/task_layout"; + gconf_bridge_bind_property (bridge, key, object, "current-value"); + /* Fine tuning. */ action = ACTION (TASK_DELETE); diff --git a/modules/calendar/e-task-shell-view-actions.h b/modules/calendar/e-task-shell-view-actions.h index d7db39bcc9..daa70c36da 100644 --- a/modules/calendar/e-task-shell-view-actions.h +++ b/modules/calendar/e-task-shell-view-actions.h @@ -55,6 +55,10 @@ E_SHELL_WINDOW_ACTION ((window), "task-purge") #define E_SHELL_WINDOW_ACTION_TASK_SAVE_AS(window) \ E_SHELL_WINDOW_ACTION ((window), "task-save-as") +#define E_SHELL_WINDOW_ACTION_TASK_VIEW_CLASSIC(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-view-classic") +#define E_SHELL_WINDOW_ACTION_TASK_VIEW_VERTICAL(window) \ + E_SHELL_WINDOW_ACTION ((window), "task-view-vertical") /* Task List Actions */ #define E_SHELL_WINDOW_ACTION_TASK_LIST_COPY(window) \ -- cgit v1.2.3 From 0b293d6318db3c8a9f0de076eec5da2408888f6d Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Thu, 27 Aug 2009 18:39:38 -0400 Subject: Fix calendar pane positioning. --- modules/calendar/e-cal-shell-content.c | 10 ++++------ modules/calendar/e-cal-shell-sidebar.c | 6 ++++-- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c index 408f07fdc6..e199f0524d 100644 --- a/modules/calendar/e-cal-shell-content.c +++ b/modules/calendar/e-cal-shell-content.c @@ -26,6 +26,8 @@ #include "e-util/e-binding.h" #include "e-util/gconf-bridge.h" +#include "widgets/menus/gal-view-etable.h" +#include "widgets/misc/e-paned.h" #include "calendar/gui/calendar-config.h" #include "calendar/gui/calendar-view.h" @@ -36,8 +38,6 @@ #include "calendar/gui/e-day-view.h" #include "calendar/gui/e-week-view.h" -#include "widgets/menus/gal-view-etable.h" - #define E_CAL_SHELL_CONTENT_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE \ ((obj), E_TYPE_CAL_SHELL_CONTENT, ECalShellContentPrivate)) @@ -132,7 +132,7 @@ cal_shell_content_notify_view_id_cb (ECalShellContent *cal_shell_content) key = "/apps/evolution/calendar/display/hpane_position"; binding_id = gconf_bridge_bind_property_delayed ( - bridge, key, G_OBJECT (paned), "position"); + bridge, key, G_OBJECT (paned), "hposition"); cal_shell_content->priv->paned_binding_id = binding_id; } @@ -344,9 +344,7 @@ cal_shell_content_constructed (GObject *object) container = GTK_WIDGET (object); - /* FIXME Need to deal with saving and restoring the position. - * Month view has its own position. */ - widget = gtk_hpaned_new (); + widget = e_paned_new (GTK_ORIENTATION_HORIZONTAL); gtk_container_add (GTK_CONTAINER (container), widget); priv->hpaned = g_object_ref (widget); gtk_widget_show (widget); diff --git a/modules/calendar/e-cal-shell-sidebar.c b/modules/calendar/e-cal-shell-sidebar.c index c25b247f36..05b3a47d72 100644 --- a/modules/calendar/e-cal-shell-sidebar.c +++ b/modules/calendar/e-cal-shell-sidebar.c @@ -27,6 +27,8 @@ #include "e-util/e-error.h" #include "e-util/e-binding.h" #include "e-util/gconf-bridge.h" +#include "widgets/misc/e-paned.h" + #include "calendar/common/authentication.h" #include "calendar/gui/calendar-config.h" #include "calendar/gui/e-calendar-selector.h" @@ -401,7 +403,7 @@ cal_shell_sidebar_constructed (GObject *object) container = GTK_WIDGET (shell_sidebar); - widget = gtk_vpaned_new (); + widget = e_paned_new (GTK_ORIENTATION_VERTICAL); gtk_container_add (GTK_CONTAINER (container), widget); priv->paned = g_object_ref (widget); gtk_widget_show (widget); @@ -497,7 +499,7 @@ cal_shell_sidebar_constructed (GObject *object) object = G_OBJECT (priv->paned); key = "/apps/evolution/calendar/display/date_navigator_vpane_position"; - gconf_bridge_bind_property_delayed (bridge, key, object, "position"); + gconf_bridge_bind_property_delayed (bridge, key, object, "vposition"); } static void -- cgit v1.2.3 From e8382099228d46ebef684c5384bab6ec710283ce Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Fri, 28 Aug 2009 09:12:46 -0400 Subject: Re-enable more calendar code. --- modules/calendar/e-cal-shell-view-private.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c index 6601228ad3..1b9c8d367a 100644 --- a/modules/calendar/e-cal-shell-view-private.c +++ b/modules/calendar/e-cal-shell-view-private.c @@ -441,8 +441,6 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) date_navigator->calitem, (ECalendarItemGetTimeCallback) cal_shell_view_get_current_time, cal_shell_view, NULL); - /* KILL-BONOBO FIXME -- Need to connect to the "user-created" - * signal for each ECalendarView. */ for (ii = 0; ii < GNOME_CAL_LAST_VIEW; ii++) { ECalendarView *calendar_view; @@ -453,6 +451,11 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) calendar_view, "popup-event", G_CALLBACK (cal_shell_view_popup_event_cb), cal_shell_view); + + g_signal_connect_swapped ( + calendar_view, "user-created", + G_CALLBACK (cal_shell_view_user_created_cb), + cal_shell_view); } g_signal_connect_swapped ( -- cgit v1.2.3 From 32f545cdf031ebe3718791f18e8fb6b6141fd081 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Fri, 28 Aug 2009 20:21:54 -0400 Subject: Simplify EPlugin loading at startup. - Require all EPlugin and EPluginHook subtypes be registered before loading plugins. This drastically simplifies the EPlugin/EPluginHook negotiation. - Turn most EPluginHook subtypes into GTypeModules and register their types from an e_module_load() function (does not include shell hooks). - Convert EPluginLib and the Mono and Python bindings to GTypeModules and register their types from an e_module_load() function, and kill EPluginTypeHook. --- modules/calendar/Makefile.am | 9 +- modules/calendar/e-cal-attachment-handler.c | 512 +++++++++++++++++++++++++++ modules/calendar/e-cal-attachment-handler.h | 67 ++++ modules/calendar/e-cal-config-hook.c | 68 ++++ modules/calendar/e-cal-config-hook.h | 33 ++ modules/calendar/e-cal-event-hook.c | 72 ++++ modules/calendar/e-cal-event-hook.h | 33 ++ modules/calendar/e-cal-shell-backend.c | 13 - modules/calendar/evolution-module-calendar.c | 10 + 9 files changed, 801 insertions(+), 16 deletions(-) create mode 100644 modules/calendar/e-cal-attachment-handler.c create mode 100644 modules/calendar/e-cal-attachment-handler.h create mode 100644 modules/calendar/e-cal-config-hook.c create mode 100644 modules/calendar/e-cal-config-hook.h create mode 100644 modules/calendar/e-cal-event-hook.c create mode 100644 modules/calendar/e-cal-event-hook.h (limited to 'modules/calendar') diff --git a/modules/calendar/Makefile.am b/modules/calendar/Makefile.am index 8f771167d9..490d42a05e 100644 --- a/modules/calendar/Makefile.am +++ b/modules/calendar/Makefile.am @@ -10,6 +10,12 @@ module_LTLIBRARIES = \ libevolution_module_calendar_la_SOURCES = \ evolution-module-calendar.c \ + e-cal-attachment-handler.c \ + e-cal-attachment-handler.h \ + e-cal-config-hook.c \ + e-cal-config-hook.h \ + e-cal-event-hook.c \ + e-cal-event-hook.h \ e-cal-shell-backend.c \ e-cal-shell-backend.h \ e-cal-shell-content.c \ @@ -57,9 +63,6 @@ libevolution_module_calendar_la_SOURCES = \ e-task-shell-view-private.c \ e-task-shell-view-private.h -# Removed from all three -# $(top_builddir)/a11y/calendar/libevolution-calendar-a11y.la - libevolution_module_calendar_la_LIBADD = \ $(top_builddir)/shell/libeshell.la \ $(top_builddir)/calendar/gui/libevolution-calendar.la \ diff --git a/modules/calendar/e-cal-attachment-handler.c b/modules/calendar/e-cal-attachment-handler.c new file mode 100644 index 0000000000..dd95cc5d08 --- /dev/null +++ b/modules/calendar/e-cal-attachment-handler.c @@ -0,0 +1,512 @@ +/* + * e-cal-attachment-handler.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-attachment-handler.h" + +#include +#include +#include +#include +#include + +#include "calendar/common/authentication.h" + +#define E_CAL_ATTACHMENT_HANDLER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_CAL_ATTACHMENT_HANDLER, ECalAttachmentHandlerPrivate)) + +typedef struct _ImportContext ImportContext; + +struct _ECalAttachmentHandlerPrivate { + gint placeholder; +}; + +struct _ImportContext { + ECal *client; + icalcomponent *component; + ECalSourceType source_type; +}; + +static gpointer parent_class; +static GType cal_attachment_handler_type; + +static const gchar *ui = +"" +" " +" " +" " +" " +" " +" " +""; + +static icalcomponent * +attachment_handler_get_component (EAttachment *attachment) +{ + CamelDataWrapper *wrapper; + CamelMimePart *mime_part; + CamelStream *stream; + GByteArray *buffer; + icalcomponent *component; + const gchar *key = "__icalcomponent__"; + + component = g_object_get_data (G_OBJECT (attachment), key); + if (component != NULL) + return component; + + mime_part = e_attachment_get_mime_part (attachment); + if (!CAMEL_IS_MIME_PART (mime_part)) + return NULL; + + buffer = g_byte_array_new (); + stream = camel_stream_mem_new (); + camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (stream), buffer); + wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); + camel_data_wrapper_decode_to_stream (wrapper, stream); + camel_object_unref (stream); + + component = e_cal_util_parse_ics_string ((gchar *) buffer->data); + + g_byte_array_free (buffer, TRUE); + + if (component == NULL) + return NULL; + + g_object_set_data_full ( + G_OBJECT (attachment), key, component, + (GDestroyNotify) icalcomponent_free); + + return component; +} + +static gboolean +attachment_handler_update_objects (ECal *client, + icalcomponent *component) +{ + icalcomponent_kind kind; + icalcomponent *vcalendar; + gboolean success; + + kind = icalcomponent_isa (component); + + switch (kind) { + case ICAL_VTODO_COMPONENT: + case ICAL_VEVENT_COMPONENT: + vcalendar = e_cal_util_new_top_level (); + if (icalcomponent_get_method (component) == ICAL_METHOD_CANCEL) + icalcomponent_set_method (vcalendar, ICAL_METHOD_CANCEL); + else + icalcomponent_set_method (vcalendar, ICAL_METHOD_PUBLISH); + icalcomponent_add_component ( + vcalendar, icalcomponent_new_clone (component)); + break; + + case ICAL_VCALENDAR_COMPONENT: + vcalendar = icalcomponent_new_clone (component); + if (!icalcomponent_get_first_property (vcalendar, ICAL_METHOD_PROPERTY)) + icalcomponent_set_method (vcalendar, ICAL_METHOD_PUBLISH); + break; + + default: + return FALSE; + } + + success = e_cal_receive_objects (client, vcalendar, NULL); + + icalcomponent_free (vcalendar); + + return success; +} + +static void +attachment_handler_import_event (ECal *client, + ECalendarStatus status, + EAttachment *attachment) +{ + icalcomponent *component; + icalcomponent *subcomponent; + icalcompiter iter; + + /* FIXME Notify the user somehow. */ + g_return_if_fail (status == E_CALENDAR_STATUS_OK); + + component = attachment_handler_get_component (attachment); + g_return_if_fail (component != NULL); + + iter = icalcomponent_begin_component (component, ICAL_ANY_COMPONENT); + + while ((subcomponent = icalcompiter_deref (&iter)) != NULL) { + icalcomponent_kind kind; + + kind = icalcomponent_isa (subcomponent); + icalcompiter_next (&iter); + + if (kind == ICAL_VEVENT_COMPONENT) + continue; + + if (kind == ICAL_VTIMEZONE_COMPONENT) + continue; + + icalcomponent_remove_component (component, subcomponent); + icalcomponent_free (subcomponent); + } + + /* XXX Do something with the return value. */ + attachment_handler_update_objects (client, component); + + g_object_unref (attachment); + g_object_unref (client); +} + +static void +attachment_handler_import_todo (ECal *client, + ECalendarStatus status, + EAttachment *attachment) +{ + icalcomponent *component; + icalcomponent *subcomponent; + icalcompiter iter; + + /* FIXME Notify the user somehow. */ + g_return_if_fail (status == E_CALENDAR_STATUS_OK); + + component = attachment_handler_get_component (attachment); + g_return_if_fail (component != NULL); + + iter = icalcomponent_begin_component (component, ICAL_ANY_COMPONENT); + + while ((subcomponent = icalcompiter_deref (&iter)) != NULL) { + icalcomponent_kind kind; + + kind = icalcomponent_isa (subcomponent); + icalcompiter_next (&iter); + + if (kind == ICAL_VTODO_COMPONENT) + continue; + + if (kind == ICAL_VTIMEZONE_COMPONENT) + continue; + + icalcomponent_remove_component (component, subcomponent); + icalcomponent_free (subcomponent); + } + + /* XXX Do something with the return value. */ + attachment_handler_update_objects (client, component); + + g_object_unref (attachment); + g_object_unref (client); +} + +static void +attachment_handler_row_activated_cb (GtkDialog *dialog) +{ + gtk_dialog_response (dialog, GTK_RESPONSE_OK); +} + +static void +attachment_handler_run_dialog (GtkWindow *parent, + EAttachment *attachment, + ECalSourceType source_type, + const gchar *title) +{ + GtkWidget *dialog; + GtkWidget *container; + GtkWidget *widget; + GCallback callback; + ESourceSelector *selector; + ESourceList *source_list; + ESource *source; + ECal *client; + icalcomponent *component; + GError *error = NULL; + + component = attachment_handler_get_component (attachment); + g_return_if_fail (component != NULL); + + e_cal_get_sources (&source_list, source_type, &error); + if (error != NULL) { + g_warning ("%s", error->message); + g_error_free (error); + return; + } + + source = e_source_list_peek_source_any (source_list); + g_return_if_fail (source != NULL); + + dialog = gtk_dialog_new_with_buttons ( + title, parent, GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL); + + widget = gtk_button_new_with_mnemonic (_("I_mport")); + gtk_button_set_image ( + GTK_BUTTON (widget), gtk_image_new_from_icon_name ( + "stock_mail-import", GTK_ICON_SIZE_MENU)); + gtk_dialog_add_action_widget ( + GTK_DIALOG (dialog), widget, GTK_RESPONSE_OK); + gtk_widget_show (widget); + + gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); + gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 400); + + container = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + gtk_widget_show (widget); + + container = widget; + + widget = e_source_selector_new (source_list); + selector = E_SOURCE_SELECTOR (widget); + e_source_selector_set_primary_selection (selector, source); + e_source_selector_show_selection (selector, FALSE); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "row-activated", + G_CALLBACK (attachment_handler_row_activated_cb), dialog); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) + goto exit; + + source = e_source_selector_peek_primary_selection (selector); + if (source == NULL) + goto exit; + + client = auth_new_cal_from_source (source, source_type); + if (client == NULL) + goto exit; + + if (source_type == E_CAL_SOURCE_TYPE_EVENT) + callback = G_CALLBACK (attachment_handler_import_event); + else if (source_type == E_CAL_SOURCE_TYPE_TODO) + callback = G_CALLBACK (attachment_handler_import_todo); + else + goto exit; + + g_object_ref (attachment); + g_signal_connect (client, "cal-opened", callback, attachment); + e_cal_open_async (client, FALSE); + +exit: + gtk_widget_destroy (dialog); +} + +static void +attachment_handler_import_to_calendar (GtkAction *action, + EAttachmentHandler *handler) +{ + EAttachment *attachment; + EAttachmentView *view; + GList *selected; + gpointer parent; + + view = e_attachment_handler_get_view (handler); + + parent = gtk_widget_get_toplevel (GTK_WIDGET (view)); + parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; + + selected = e_attachment_view_get_selected_attachments (view); + g_return_if_fail (g_list_length (selected) == 1); + attachment = E_ATTACHMENT (selected->data); + + attachment_handler_run_dialog ( + parent, attachment, + E_CAL_SOURCE_TYPE_EVENT, + _("Select a Calendar")); + + g_object_unref (attachment); + g_list_free (selected); +} + +static void +attachment_handler_import_to_tasks (GtkAction *action, + EAttachmentHandler *handler) +{ + EAttachment *attachment; + EAttachmentView *view; + GList *selected; + gpointer parent; + + view = e_attachment_handler_get_view (handler); + + parent = gtk_widget_get_toplevel (GTK_WIDGET (view)); + parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; + + selected = e_attachment_view_get_selected_attachments (view); + g_return_if_fail (g_list_length (selected) == 1); + attachment = E_ATTACHMENT (selected->data); + + attachment_handler_run_dialog ( + parent, attachment, + E_CAL_SOURCE_TYPE_TODO, + _("Select a Task List")); + + g_object_unref (attachment); + g_list_free (selected); +} + +static GtkActionEntry standard_entries[] = { + + { "import-to-calendar", + "stock_mail-import", + N_("I_mport to Calendar"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (attachment_handler_import_to_calendar) }, + + { "import-to-tasks", + "stock_mail-import", + N_("I_mport to Tasks"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (attachment_handler_import_to_tasks) } +}; + +static void +cal_attachment_handler_update_actions (EAttachmentView *view) +{ + EAttachment *attachment; + GtkAction *action; + GList *selected; + icalcomponent *component; + icalcomponent *subcomponent; + icalcomponent_kind kind; + gboolean is_vevent = FALSE; + gboolean is_vtodo = FALSE; + + selected = e_attachment_view_get_selected_attachments (view); + + if (g_list_length (selected) != 1) + goto exit; + + attachment = E_ATTACHMENT (selected->data); + component = attachment_handler_get_component (attachment); + + if (component == NULL) + goto exit; + + subcomponent = icalcomponent_get_inner (component); + + if (subcomponent == NULL) + goto exit; + + kind = icalcomponent_isa (subcomponent); + is_vevent = (kind == ICAL_VEVENT_COMPONENT); + is_vtodo = (kind == ICAL_VTODO_COMPONENT); + +exit: + action = e_attachment_view_get_action (view, "import-to-calendar"); + gtk_action_set_visible (action, is_vevent); + + action = e_attachment_view_get_action (view, "import-to-tasks"); + gtk_action_set_visible (action, is_vtodo); + + g_list_foreach (selected, (GFunc) g_object_unref, NULL); + g_list_free (selected); +} + +static void +cal_attachment_handler_constructed (GObject *object) +{ + EAttachmentHandler *handler; + EAttachmentView *view; + GtkActionGroup *action_group; + GtkUIManager *ui_manager; + GError *error = NULL; + + handler = E_ATTACHMENT_HANDLER (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + view = e_attachment_handler_get_view (handler); + + action_group = e_attachment_view_add_action_group (view, "calendar"); + gtk_action_group_add_actions ( + action_group, standard_entries, + G_N_ELEMENTS (standard_entries), handler); + + ui_manager = e_attachment_view_get_ui_manager (view); + gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); + + if (error != NULL) { + g_warning ("%s", error->message); + g_error_free (error); + } + + g_signal_connect ( + view, "update_actions", + G_CALLBACK (cal_attachment_handler_update_actions), + NULL); +} + +static void +cal_attachment_handler_class_init (ECalAttachmentHandlerClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ECalAttachmentHandlerPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->constructed = cal_attachment_handler_constructed; +} + +static void +cal_attachment_handler_init (ECalAttachmentHandler *handler) +{ + handler->priv = E_CAL_ATTACHMENT_HANDLER_GET_PRIVATE (handler); +} + +GType +e_cal_attachment_handler_get_type (void) +{ + return cal_attachment_handler_type; +} + +void +e_cal_attachment_handler_register_type (GTypeModule *type_module) +{ + static const GTypeInfo type_info = { + sizeof (ECalAttachmentHandlerClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) cal_attachment_handler_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ECalAttachmentHandler), + 0, /* n_preallocs */ + (GInstanceInitFunc) cal_attachment_handler_init, + NULL /* value_table */ + }; + + cal_attachment_handler_type = g_type_module_register_type ( + type_module, E_TYPE_ATTACHMENT_HANDLER, + "ECalAttachmentHandler", &type_info, 0); +} diff --git a/modules/calendar/e-cal-attachment-handler.h b/modules/calendar/e-cal-attachment-handler.h new file mode 100644 index 0000000000..b792fbf765 --- /dev/null +++ b/modules/calendar/e-cal-attachment-handler.h @@ -0,0 +1,67 @@ +/* + * e-cal-attachment-handler.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_CAL_ATTACHMENT_HANDLER_H +#define E_CAL_ATTACHMENT_HANDLER_H + +#include + +/* Standard GObject macros */ +#define E_TYPE_CAL_ATTACHMENT_HANDLER \ + (e_cal_attachment_handler_get_type ()) +#define E_CAL_ATTACHMENT_HANDLER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_CAL_ATTACHMENT_HANDLER, ECalAttachmentHandler)) +#define E_CAL_ATTACHMENT_HANDLER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_CAL_ATTACHMENT_HANDLER, ECalAttachmentHandlerClass)) +#define E_IS_CAL_ATTACHMENT_HANDLER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_CAL_ATTACHMENT_HANDLER)) +#define E_IS_CAL_ATTACHMENT_HANDLER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_CAL_ATTACHMENT_HANDLER)) +#define E_CAL_ATTACHMENT_HANDLER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_CAL_ATTACHMENT_HANDLER, ECalAttachmentHandlerClass)) + +G_BEGIN_DECLS + +typedef struct _ECalAttachmentHandler ECalAttachmentHandler; +typedef struct _ECalAttachmentHandlerClass ECalAttachmentHandlerClass; +typedef struct _ECalAttachmentHandlerPrivate ECalAttachmentHandlerPrivate; + +struct _ECalAttachmentHandler { + EAttachmentHandler parent; + ECalAttachmentHandlerPrivate *priv; +}; + +struct _ECalAttachmentHandlerClass { + EAttachmentHandlerClass parent_class; +}; + +GType e_cal_attachment_handler_get_type (void); +void e_cal_attachment_handler_register_type + (GTypeModule *type_module); + +G_END_DECLS + +#endif /* E_CAL_ATTACHMENT_HANDLER_H */ diff --git a/modules/calendar/e-cal-config-hook.c b/modules/calendar/e-cal-config-hook.c new file mode 100644 index 0000000000..4a0522460c --- /dev/null +++ b/modules/calendar/e-cal-config-hook.c @@ -0,0 +1,68 @@ +/* + * e-cal-config-hook.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-config-hook.h" + +#include "e-util/e-config.h" +#include "calendar/gui/e-cal-config.h" + +static const EConfigHookTargetMask no_masks[] = { + { NULL } +}; + +static const EConfigHookTargetMap targets[] = { + { "source", EC_CONFIG_TARGET_SOURCE, no_masks }, + { "prefs", EC_CONFIG_TARGET_PREFS, no_masks }, + { NULL } +}; + +static void +cal_config_hook_class_init (EPluginHookClass *class) +{ + gint ii; + + class->id = "org.gnome.evolution.calendar.config:1.0"; + + for (ii = 0; targets[ii].type != NULL; ii++) + e_config_hook_class_add_target_map ( + (EConfigHookClass *) class, &targets[ii]); +} + +void +e_cal_config_hook_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (EConfigHookClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) cal_config_hook_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EConfigHook), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + NULL /* value_table */ + }; + + g_type_module_register_type ( + type_module, e_config_hook_get_type (), + "ECalConfigHook", &type_info, 0); +} diff --git a/modules/calendar/e-cal-config-hook.h b/modules/calendar/e-cal-config-hook.h new file mode 100644 index 0000000000..a22ec56bbc --- /dev/null +++ b/modules/calendar/e-cal-config-hook.h @@ -0,0 +1,33 @@ +/* + * e-cal-config-hook.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_CAL_CONFIG_HOOK_H +#define E_CAL_CONFIG_HOOK_H + +#include + +G_BEGIN_DECLS + +void e_cal_config_hook_register_type (GTypeModule *type_module); + +G_END_DECLS + +#endif /* E_CAL_CONFIG_HOOK_H */ diff --git a/modules/calendar/e-cal-event-hook.c b/modules/calendar/e-cal-event-hook.c new file mode 100644 index 0000000000..b263727107 --- /dev/null +++ b/modules/calendar/e-cal-event-hook.c @@ -0,0 +1,72 @@ +/* + * e-cal-event-hook.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-cal-event-hook.h" + +#include "e-util/e-event.h" +#include "calendar/gui/e-cal-event.h" + +static const EEventHookTargetMask masks[] = { + { "migration", E_CAL_EVENT_MODULE_MIGRATION }, + { NULL } +}; + +static const EEventHookTargetMap targets[] = { + { "module", E_CAL_EVENT_TARGET_BACKEND, masks }, + { NULL } +}; + +static void +cal_event_hook_class_init (EPluginHookClass *class) +{ + EEventHookClass *event_hook_class; + gint ii; + + event_hook_class = (EEventHookClass *) class; + event_hook_class->event = (EEvent *) e_cal_event_peek (); + + class->id = "org.gnome.evolution.calendar.events:1.0"; + + for (ii = 0; targets[ii].type != NULL; ii++) + e_event_hook_class_add_target_map ( + (EEventHookClass *) class, &targets[ii]); +} + +void +e_cal_event_hook_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (EEventHookClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) cal_event_hook_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EEventHook), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + NULL /* value_table */ + }; + + g_type_module_register_type ( + type_module, e_event_hook_get_type (), + "ECalEventHook", &type_info, 0); +} diff --git a/modules/calendar/e-cal-event-hook.h b/modules/calendar/e-cal-event-hook.h new file mode 100644 index 0000000000..9dde31f900 --- /dev/null +++ b/modules/calendar/e-cal-event-hook.h @@ -0,0 +1,33 @@ +/* + * e-cal-event-hook.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_CAL_EVENT_HOOK_H +#define E_CAL_EVENT_HOOK_H + +#include + +G_BEGIN_DECLS + +void e_cal_event_hook_register_type (GTypeModule *type_module); + +G_END_DECLS + +#endif /* E_CAL_EVENT_HOOK_H */ diff --git a/modules/calendar/e-cal-shell-backend.c b/modules/calendar/e-cal-shell-backend.c index 6d9c74411b..5149574323 100644 --- a/modules/calendar/e-cal-shell-backend.c +++ b/modules/calendar/e-cal-shell-backend.c @@ -38,9 +38,6 @@ #include "calendar/common/authentication.h" #include "calendar/gui/calendar-config.h" #include "calendar/gui/comp-util.h" -#include "calendar/gui/e-attachment-handler-calendar.h" -#include "calendar/gui/e-cal-config.h" -#include "calendar/gui/e-cal-event.h" #include "calendar/gui/dialogs/cal-prefs-dialog.h" #include "calendar/gui/dialogs/calendar-setup.h" #include "calendar/gui/dialogs/event-editor.h" @@ -508,13 +505,6 @@ static GtkActionEntry source_entries[] = { G_CALLBACK (action_calendar_new_cb) } }; -static void -cal_shell_backend_init_hooks (void) -{ - e_plugin_hook_register_type (e_cal_config_hook_get_type ()); - e_plugin_hook_register_type (e_cal_event_hook_get_type ()); -} - static void cal_shell_backend_init_importers (void) { @@ -778,15 +768,12 @@ cal_shell_backend_constructed (GObject *object) G_CALLBACK (cal_shell_backend_window_created_cb), shell_backend); - cal_shell_backend_init_hooks (); cal_shell_backend_init_importers (); /* Initialize settings before initializing preferences, * since the preferences bind to the shell settings. */ e_cal_shell_backend_init_settings (shell); cal_shell_backend_init_preferences (shell); - - e_attachment_handler_calendar_get_type (); } static void diff --git a/modules/calendar/evolution-module-calendar.c b/modules/calendar/evolution-module-calendar.c index 63bf98ead9..f72e8a97e4 100644 --- a/modules/calendar/evolution-module-calendar.c +++ b/modules/calendar/evolution-module-calendar.c @@ -19,6 +19,11 @@ * */ +#include "e-cal-attachment-handler.h" + +#include "e-cal-config-hook.h" +#include "e-cal-event-hook.h" + #include "e-cal-shell-backend.h" #include "e-cal-shell-content.h" #include "e-cal-shell-sidebar.h" @@ -43,6 +48,11 @@ e_module_load (GTypeModule *type_module) { /* Register dynamically loaded types. */ + e_cal_attachment_handler_register_type (type_module); + + e_cal_config_hook_register_type (type_module); + e_cal_event_hook_register_type (type_module); + e_cal_shell_backend_register_type (type_module); e_cal_shell_content_register_type (type_module); e_cal_shell_sidebar_register_type (type_module); -- cgit v1.2.3