aboutsummaryrefslogtreecommitdiffstats
path: root/calendar
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@src.gnome.org>2008-10-07 01:41:31 +0800
committerMatthew Barnes <mbarnes@src.gnome.org>2008-10-07 01:41:31 +0800
commit1bed00795bf092ad6e9e076eccf7cc2a8c20cb27 (patch)
tree1479219994e81557af0c8041fa170f95064e541f /calendar
parent3c9c7a2ac1864cd7cf3b72737e0577612e672b01 (diff)
downloadgsoc2013-evolution-1bed00795bf092ad6e9e076eccf7cc2a8c20cb27.tar
gsoc2013-evolution-1bed00795bf092ad6e9e076eccf7cc2a8c20cb27.tar.gz
gsoc2013-evolution-1bed00795bf092ad6e9e076eccf7cc2a8c20cb27.tar.bz2
gsoc2013-evolution-1bed00795bf092ad6e9e076eccf7cc2a8c20cb27.tar.lz
gsoc2013-evolution-1bed00795bf092ad6e9e076eccf7cc2a8c20cb27.tar.xz
gsoc2013-evolution-1bed00795bf092ad6e9e076eccf7cc2a8c20cb27.tar.zst
gsoc2013-evolution-1bed00795bf092ad6e9e076eccf7cc2a8c20cb27.zip
Baseline cut at the Calendar sidebar and module. Pretty much identical
to Tasks and Memos so far. Now for the interesting part... svn path=/branches/kill-bonobo/; revision=36573
Diffstat (limited to 'calendar')
-rw-r--r--calendar/gui/calendar-component.c258
-rw-r--r--calendar/gui/gnome-cal.c56
-rw-r--r--calendar/gui/memos-component.c23
-rw-r--r--calendar/modules/e-cal-shell-module.c87
-rw-r--r--calendar/modules/e-cal-shell-sidebar.c483
-rw-r--r--calendar/modules/e-cal-shell-sidebar.h19
6 files changed, 569 insertions, 357 deletions
diff --git a/calendar/gui/calendar-component.c b/calendar/gui/calendar-component.c
index cdec256ac3..f2896a5990 100644
--- a/calendar/gui/calendar-component.c
+++ b/calendar/gui/calendar-component.c
@@ -87,16 +87,11 @@ typedef struct
GList *notifications;
- EUserCreatableItemsHandler *creatable_items_handler;
-
- EActivityHandler *activity_handler;
-
float vpane_pos;
} CalendarComponentView;
struct _CalendarComponentPrivate {
- GConfClient *gconf_client;
int gconf_notify_id;
ESourceList *source_list;
@@ -160,54 +155,6 @@ is_in_uids (GSList *uids, ESource *source)
}
static void
-update_uris_for_selection (CalendarComponentView *component_view)
-{
- GSList *selection, *l, *uids_selected = NULL;
-
- selection = e_source_selector_get_selection (E_SOURCE_SELECTOR (component_view->source_selector));
-
- for (l = component_view->source_selection; l; l = l->next) {
- ESource *old_selected_source = l->data;
-
- if (!is_in_selection (selection, old_selected_source))
- gnome_calendar_remove_source (component_view->calendar, E_CAL_SOURCE_TYPE_EVENT, old_selected_source);
- }
-
- for (l = selection; l; l = l->next) {
- ESource *selected_source = l->data;
-
- if (gnome_calendar_add_source (component_view->calendar, E_CAL_SOURCE_TYPE_EVENT, selected_source))
- uids_selected = g_slist_append (uids_selected, (char *) e_source_peek_uid (selected_source));
- }
-
- e_source_selector_free_selection (component_view->source_selection);
- component_view->source_selection = selection;
-
- /* Save the selection for next time we start up */
- calendar_config_set_calendars_selected (uids_selected);
- g_slist_free (uids_selected);
-}
-
-static void
-update_uri_for_primary_selection (CalendarComponentView *component_view)
-{
- ESource *source;
-
- source = e_source_selector_peek_primary_selection (E_SOURCE_SELECTOR (component_view->source_selector));
- if (!source)
- return;
-
- /* Set the default */
- gnome_calendar_set_default_source (component_view->calendar, E_CAL_SOURCE_TYPE_EVENT, source);
-
- /* Make sure we are embedded first */
- calendar_control_sensitize_calendar_commands (component_view->view_control, component_view->calendar, TRUE);
-
- /* Save the selection for next time we start up */
- calendar_config_set_primary_calendar (e_source_peek_uid (source));
-}
-
-static void
update_selection (CalendarComponentView *component_view)
{
GSList *selection, *uids_selected, *l;
@@ -455,18 +402,6 @@ popup_event_cb(ESourceSelector *selector, ESource *insource, GdkEventButton *eve
}
static void
-source_selection_changed_cb (ESourceSelector *selector, CalendarComponentView *component_view)
-{
- update_uris_for_selection (component_view);
-}
-
-static void
-primary_source_selection_changed_cb (ESourceSelector *selector, CalendarComponentView *component_view)
-{
- update_uri_for_primary_selection (component_view);
-}
-
-static void
source_changed_cb (ESource *source, GnomeCalendar *calendar)
{
if (calendar) {
@@ -625,29 +560,6 @@ impl_handleURI (PortableServer_Servant servant, const char *uri, CORBA_Environme
}
static void
-impl_upgradeFromVersion (PortableServer_Servant servant,
- CORBA_short major,
- CORBA_short minor,
- CORBA_short revision,
- CORBA_Environment *ev)
-{
- GError *err = NULL;
- CalendarComponent *calendar_component = CALENDAR_COMPONENT (bonobo_object_from_servant (servant));
-
- if (!migrate_calendars (calendar_component, major, minor, revision, &err)) {
- GNOME_Evolution_Component_UpgradeFailed *failedex;
-
- failedex = GNOME_Evolution_Component_UpgradeFailed__alloc();
- failedex->what = CORBA_string_dup(_("Failed upgrading calendars."));
- failedex->why = CORBA_string_dup(err->message);
- CORBA_exception_set(ev, CORBA_USER_EXCEPTION, ex_GNOME_Evolution_Component_UpgradeFailed, failedex);
- }
-
- if (err)
- g_error_free(err);
-}
-
-static void
config_create_ecal_changed_cb (GConfClient *client, guint id, GConfEntry *entry, gpointer data)
{
CalendarComponent *calendar_component = data;
@@ -745,70 +657,6 @@ setup_create_ecal (CalendarComponent *calendar_component, CalendarComponentView
return priv->create_ecal;
}
-static gboolean
-create_new_event (CalendarComponent *calendar_component, CalendarComponentView *component_view, gboolean is_allday, gboolean is_meeting)
-{
- ECal *ecal;
- ECalendarView *view;
-
- ecal = setup_create_ecal (calendar_component, component_view);
- if (!ecal)
- return FALSE;
-
- if (component_view && (view = E_CALENDAR_VIEW (gnome_calendar_get_current_view_widget (component_view->calendar)))) {
- e_calendar_view_new_appointment_full (view, is_allday, is_meeting, TRUE);
- } else {
- ECalComponent *comp;
- CompEditor *editor;
- CompEditorFlags flags;
-
- flags = COMP_EDITOR_USER_ORG | COMP_EDITOR_NEW_ITEM;
- if (is_meeting)
- flags |= COMP_EDITOR_MEETING;
- comp = cal_comp_event_new_with_current_time (ecal, is_allday);
- editor = event_editor_new (ecal, flags);
- e_cal_component_commit_sequence (comp);
-
- comp_editor_edit_comp (editor, comp);
- if (is_meeting)
- event_editor_show_meeting (EVENT_EDITOR (editor));
- gtk_window_present (GTK_WINDOW (editor));
-
- e_comp_editor_registry_add (comp_editor_registry, editor, TRUE);
- }
-
- return TRUE;
-}
-
-static void
-create_local_item_cb (EUserCreatableItemsHandler *handler, const char *item_type_name, void *data)
-{
- CalendarComponent *calendar_component = data;
- CalendarComponentPrivate *priv;
- CalendarComponentView *component_view = NULL;
- GList *l;
-
- priv = calendar_component->priv;
-
- for (l = priv->views; l; l = l->next) {
- component_view = l->data;
-
- if (component_view->creatable_items_handler == handler)
- break;
-
- component_view = NULL;
- }
-
- if (strcmp (item_type_name, CREATE_EVENT_ID) == 0)
- create_new_event (calendar_component, component_view, FALSE, FALSE);
- else if (strcmp (item_type_name, CREATE_ALLDAY_EVENT_ID) == 0)
- create_new_event (calendar_component, component_view, TRUE, FALSE);
- else if (strcmp (item_type_name, CREATE_MEETING_ID) == 0)
- create_new_event (calendar_component, component_view, FALSE, TRUE);
- else if (strcmp (item_type_name, CREATE_CALENDAR_ID) == 0)
- calendar_setup_new_calendar (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (component_view->calendar))));
-}
-
static CalendarComponentView *
create_component_view (CalendarComponent *calendar_component)
{
@@ -881,25 +729,16 @@ create_component_view (CalendarComponent *calendar_component)
/* Create status bar */
statusbar_widget = e_task_bar_new ();
- component_view->activity_handler = e_activity_handler_new ();
- e_activity_handler_attach_task_bar (component_view->activity_handler, E_TASK_BAR (statusbar_widget));
gtk_widget_show (statusbar_widget);
component_view->statusbar_control = bonobo_control_new (statusbar_widget);
- gnome_calendar_set_activity_handler (component_view->calendar, component_view->activity_handler);
-
/* connect after setting the initial selections, or we'll get unwanted calls
to calendar_control_sensitize_calendar_commands */
- g_signal_connect (component_view->source_selector, "selection_changed",
- G_CALLBACK (source_selection_changed_cb), component_view);
- g_signal_connect (component_view->source_selector, "primary_selection_changed",
- G_CALLBACK (primary_source_selection_changed_cb), component_view);
g_signal_connect (component_view->source_selector, "popup_event",
G_CALLBACK (popup_event_cb), component_view);
/* Set up the "new" item handler */
- component_view->creatable_items_handler = e_user_creatable_items_handler_new ("calendar", create_local_item_cb, calendar_component);
g_signal_connect (component_view->view_control, "activate", G_CALLBACK (control_activate_cb), component_view);
/* Load the selection from the last run */
@@ -952,12 +791,6 @@ destroy_component_view (CalendarComponentView *component_view)
calendar_config_remove_notification (GPOINTER_TO_UINT (l->data));
g_list_free (component_view->notifications);
- if (component_view->creatable_items_handler)
- g_object_unref (component_view->creatable_items_handler);
-
- if (component_view->activity_handler)
- g_object_unref (component_view->activity_handler);
-
if (component_view->task_source_selection) {
g_slist_foreach (component_view->task_source_selection, (GFunc) g_free, NULL);
g_slist_free (component_view->task_source_selection);
@@ -992,62 +825,6 @@ view_destroyed_cb (gpointer data, GObject *where_the_object_was)
}
}
-static GNOME_Evolution_ComponentView
-impl_createView (PortableServer_Servant servant,
- GNOME_Evolution_ShellView parent,
- CORBA_boolean select_item,
- CORBA_Environment *ev)
-{
- CalendarComponent *calendar_component = CALENDAR_COMPONENT (bonobo_object_from_servant (servant));
- CalendarComponentPrivate *priv;
- CalendarComponentView *component_view;
- EComponentView *ecv;
-
- priv = calendar_component->priv;
-
- /* Create the calendar component view */
- component_view = create_component_view (calendar_component);
- if (!component_view) {
- /* FIXME Should we describe the problem in a control? */
- bonobo_exception_set (ev, ex_GNOME_Evolution_Component_Failed);
-
- return CORBA_OBJECT_NIL;
- }
-
- g_object_weak_ref (G_OBJECT (component_view->view_control), view_destroyed_cb, calendar_component);
- priv->views = g_list_append (priv->views, component_view);
-
- /* TODO: Make CalendarComponentView just subclass EComponentView */
- ecv = e_component_view_new_controls (parent, "calendar", component_view->sidebar_control,
- component_view->view_control, component_view->statusbar_control);
-
- return BONOBO_OBJREF(ecv);
-}
-
-
-static void
-impl_requestCreateItem (PortableServer_Servant servant,
- const CORBA_char *item_type_name,
- CORBA_Environment *ev)
-{
- CalendarComponent *calendar_component = CALENDAR_COMPONENT (bonobo_object_from_servant (servant));
- gboolean result = FALSE;
-
- if (strcmp (item_type_name, CREATE_EVENT_ID) == 0)
- result = create_new_event (calendar_component, NULL, FALSE, FALSE);
- else if (strcmp (item_type_name, CREATE_ALLDAY_EVENT_ID) == 0)
- result = create_new_event (calendar_component, NULL, TRUE, FALSE);
- else if (strcmp (item_type_name, CREATE_MEETING_ID) == 0)
- result = create_new_event (calendar_component, NULL, FALSE, TRUE);
- else if (strcmp (item_type_name, CREATE_CALENDAR_ID) == 0)
- /* FIXME Should we use the last opened window? */
- calendar_setup_new_calendar (NULL);
- else
- bonobo_exception_set (ev, ex_GNOME_Evolution_Component_UnknownType);
-
- if (!result)
- bonobo_exception_set (ev, ex_GNOME_Evolution_Component_Failed);
-}
/* GObject methods. */
@@ -1063,11 +840,6 @@ impl_dispose (GObject *object)
priv->source_list = NULL;
}
- if (priv->gconf_client != NULL) {
- g_object_unref (priv->gconf_client);
- priv->gconf_client = NULL;
- }
-
if (priv->create_ecal) {
g_object_unref (priv->create_ecal);
priv->create_ecal = NULL;
@@ -1090,24 +862,6 @@ impl_dispose (GObject *object)
}
static void
-impl_finalize (GObject *object)
-{
- CalendarComponentPrivate *priv = CALENDAR_COMPONENT (object)->priv;
- GList *l;
-
- for (l = priv->views; l; l = l->next) {
- CalendarComponentView *component_view = l->data;
-
- destroy_component_view (component_view);
- }
- g_list_free (priv->views);
-
- g_free (priv);
-
- (* G_OBJECT_CLASS (parent_class)->finalize) (object);
-}
-
-static void
calendar_component_class_init (CalendarComponentClass *class)
{
POA_GNOME_Evolution_Component__epv *epv = &class->epv;
@@ -1115,13 +869,9 @@ calendar_component_class_init (CalendarComponentClass *class)
parent_class = g_type_class_peek_parent (class);
- epv->upgradeFromVersion = impl_upgradeFromVersion;
- epv->createView = impl_createView;
- epv->requestCreateItem = impl_requestCreateItem;
epv->handleURI = impl_handleURI;
object_class->dispose = impl_dispose;
- object_class->finalize = impl_finalize;
}
static void
@@ -1130,12 +880,6 @@ calendar_component_init (CalendarComponent *component)
CalendarComponentPrivate *priv;
guint not;
- priv = g_new0 (CalendarComponentPrivate, 1);
-
- /* EPFIXME: Should use a custom one instead? Also we should add
- * calendar_component_peek_gconf_client(). */
- priv->gconf_client = gconf_client_get_default ();
-
not = calendar_config_add_notification_primary_calendar (config_primary_selection_changed_cb,
component);
priv->notifications = g_list_prepend (priv->notifications, GUINT_TO_POINTER (not));
@@ -1147,5 +891,3 @@ calendar_component_init (CalendarComponent *component)
if (!e_cal_get_sources (&priv->memo_source_list, E_CAL_SOURCE_TYPE_JOURNAL, NULL))
;
}
-
-BONOBO_TYPE_FUNC_FULL (CalendarComponent, GNOME_Evolution_Component, PARENT_TYPE, calendar_component)
diff --git a/calendar/gui/gnome-cal.c b/calendar/gui/gnome-cal.c
index 1fc02bd1ac..0bea1e472a 100644
--- a/calendar/gui/gnome-cal.c
+++ b/calendar/gui/gnome-cal.c
@@ -1319,37 +1319,6 @@ working_days_changed_cb (GConfClient *client, guint id, GConfEntry *entry, gpoin
}
static void
-set_timezone (GnomeCalendar *calendar)
-{
- GnomeCalendarPrivate *priv;
- int i;
-
- priv = calendar->priv;
-
- priv->zone = calendar_config_get_icaltimezone ();
-
- for (i = 0; i < E_CAL_SOURCE_TYPE_LAST; i++) {
- GList *l;
-
- for (l = priv->clients_list[i]; l != NULL; l = l->next) {
- ECal *client = l->data;
-
- if (e_cal_get_load_state (client) == E_CAL_LOAD_LOADED)
- /* FIXME Error checking */
- e_cal_set_default_timezone (client, priv->zone, NULL);
- }
-
- if (priv->default_client[i]
- && e_cal_get_load_state (priv->default_client[i]) == E_CAL_LOAD_LOADED)
- /* FIXME Error checking */
- e_cal_set_default_timezone (priv->default_client[i], priv->zone, NULL);
- }
-
- if (priv->views [priv->current_view_type])
- e_calendar_view_set_timezone (priv->views [priv->current_view_type], priv->zone);
-}
-
-static void
timezone_changed_cb (GConfClient *client, guint id, GConfEntry *entry, gpointer data)
{
GnomeCalendar *calendar = data;
@@ -2993,31 +2962,6 @@ open_ecal (GnomeCalendar *gcal, ECal *cal, gboolean only_if_exists, open_func of
return TRUE;
}
-/* Callback when we get an error message from the backend */
-static void
-backend_error_cb (ECal *client, const char *message, gpointer data)
-{
- GnomeCalendar *gcal;
- GtkDialog *dialog;
- char *uristr;
-
- gcal = GNOME_CALENDAR (data);
-
- uristr = get_uri_without_password (e_cal_get_uri (client));
-
- dialog = GTK_DIALOG (gtk_message_dialog_new (
- GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (gcal))),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_OK,
- _("Error on %s:\n %s"),
- uristr, message));
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (GTK_WIDGET (dialog));
-
- g_free (uristr);
-}
-
/* Callback when the backend dies */
static void
backend_died_cb (ECal *ecal, gpointer data)
diff --git a/calendar/gui/memos-component.c b/calendar/gui/memos-component.c
index 310e8d4351..51afab099f 100644
--- a/calendar/gui/memos-component.c
+++ b/calendar/gui/memos-component.c
@@ -157,29 +157,6 @@ source_selection_changed_cb (ESourceSelector *selector, MemosComponentView *comp
/* Evolution::Component CORBA methods */
-static void
-impl_upgradeFromVersion (PortableServer_Servant servant,
- CORBA_short major,
- CORBA_short minor,
- CORBA_short revision,
- CORBA_Environment *ev)
-{
- GError *err = NULL;
- MemosComponent *component = MEMOS_COMPONENT (bonobo_object_from_servant (servant));
-
- if (!migrate_memos(component, major, minor, revision, &err)) {
- GNOME_Evolution_Component_UpgradeFailed *failedex;
-
- failedex = GNOME_Evolution_Component_UpgradeFailed__alloc();
- failedex->what = CORBA_string_dup(_("Failed upgrading memos."));
- failedex->why = CORBA_string_dup(err->message);
- CORBA_exception_set(ev, CORBA_USER_EXCEPTION, ex_GNOME_Evolution_Component_UpgradeFailed, failedex);
- }
-
- if (err)
- g_error_free(err);
-}
-
static gboolean
update_single_object (ECal *client, icalcomponent *icalcomp, gboolean fail_on_modify)
{
diff --git a/calendar/modules/e-cal-shell-module.c b/calendar/modules/e-cal-shell-module.c
index 1dff363a0f..17c4b2152b 100644
--- a/calendar/modules/e-cal-shell-module.c
+++ b/calendar/modules/e-cal-shell-module.c
@@ -22,6 +22,7 @@
#include <string.h>
#include <glib/gi18n.h>
#include <libecal/e-cal.h>
+#include <libedataserver/e-url.h>
#include <libedataserver/e-source.h>
#include <libedataserver/e-source-list.h>
#include <libedataserver/e-source-group.h>
@@ -30,7 +31,11 @@
#include "shell/e-shell-module.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/event-editor.h"
#include "e-cal-shell-view.h"
#include "e-cal-shell-module-migrate.h"
@@ -284,27 +289,85 @@ cal_module_ensure_sources (EShellModule *shell_module)
}
static void
-action_appointment_new_cb (GtkAction *action,
- EShellWindow *shell_window)
+cal_module_cal_opened_cb (ECal *cal,
+ ECalendarStatus status,
+ GtkAction *action)
{
-}
+ ECalComponent *comp;
+ CompEditor *editor;
+ CompEditorFlags flags = 0;
+ const gchar *action_name;
+ gboolean all_day;
+
+ /* XXX Handle errors better. */
+ if (status != E_CALENDAR_STATUS_OK)
+ return;
-static void
-action_appointment_all_day_new_cb (GtkAction *action,
- EShellWindow *shell_window)
-{
+ action_name = gtk_action_get_name (action);
+
+ flags |= COMP_EDITOR_NEW_ITEM;
+ flags |= COMP_EDITOR_USER_ORG;
+ if (strcmp (action_name, "meeting-new") == 0)
+ flags |= COMP_EDITOR_MEETING;
+
+ all_day = (strcmp (action_name, "appointment-all-day-new") == 0);
+
+ editor = event_editor_new (cal, 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_meeting_new_cb (GtkAction *action,
- EShellWindow *shell_window)
+action_event_new_cb (GtkAction *action,
+ EShellWindow *shell_window)
{
+ ECal *cal = NULL;
+ ECalSourceType source_type;
+ ESourceList *source_list;
+ gchar *uid;
+
+ /* This callback is used for both appointments and meetings. */
+
+ source_type = E_CAL_SOURCE_TYPE_EVENT;
+
+ if (!e_cal_get_sources (&source_list, source_type, NULL)) {
+ g_warning ("Could not get calendar sources from GConf!");
+ return;
+ }
+
+ uid = calendar_config_get_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_module_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[] = {
@@ -314,21 +377,21 @@ static GtkActionEntry item_entries[] = {
N_("_Appointment"), /* XXX Need C_() here */
"<Control>a",
N_("Create a new appointment"),
- G_CALLBACK (action_appointment_new_cb) },
+ G_CALLBACK (action_event_new_cb) },
{ "appointment-all-day-new",
"stock_new-24h-appointment",
N_("All Day A_ppointment"),
NULL,
N_("Create a new all-day appointment"),
- G_CALLBACK (action_appointment_all_day_new_cb) },
+ G_CALLBACK (action_event_new_cb) },
{ "meeting-new",
"stock_new-meeting",
N_("M_eeting"),
"<Control>e",
N_("Create a new meeting request"),
- G_CALLBACK (action_meeting_new_cb) }
+ G_CALLBACK (action_event_new_cb) }
};
static GtkActionEntry source_entries[] = {
diff --git a/calendar/modules/e-cal-shell-sidebar.c b/calendar/modules/e-cal-shell-sidebar.c
index b60d1660d1..bbe0c15caf 100644
--- a/calendar/modules/e-cal-shell-sidebar.c
+++ b/calendar/modules/e-cal-shell-sidebar.c
@@ -24,9 +24,11 @@
#include <string.h>
#include <glib/gi18n.h>
-#include "e-util/e-util.h"
-#include "calendar/gui/gnome-cal.h"
+#include "e-util/e-error.h"
+#include "calendar/common/authentication.h"
+#include "calendar/gui/calendar-config.h"
#include "calendar/gui/e-calendar-selector.h"
+#include "calendar/gui/misc.h"
#include "e-cal-shell-view.h"
@@ -36,6 +38,9 @@
struct _ECalShellSidebarPrivate {
GtkWidget *selector;
+
+ /* UID -> Client */
+ GHashTable *client_table;
};
enum {
@@ -43,13 +48,261 @@ enum {
PROP_SELECTOR
};
+enum {
+ CLIENT_ADDED,
+ CLIENT_REMOVED,
+ STATUS_MESSAGE,
+ LAST_SIGNAL
+};
+
static gpointer parent_class;
+static guint signals[LAST_SIGNAL];
+
+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_update_timezone (ECalShellSidebar *cal_shell_sidebar)
+{
+ GHashTable *client_table;
+ icaltimezone *zone;
+ GList *values;
+
+ zone = calendar_config_get_icaltimezone ();
+ client_table = cal_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_calendar_view_set_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 ECalShellView instead. */
+}
+
+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);
+
+ 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_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)
+{
+ 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_calendar (uid);
+}
static void
cal_shell_sidebar_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
{
switch (property_id) {
case PROP_SELECTOR:
@@ -74,20 +327,40 @@ cal_shell_sidebar_dispose (GObject *object)
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
+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;
EShellView *shell_view;
EShellSidebar *shell_sidebar;
ECalShellView *cal_shell_view;
+ ESourceSelector *selector;
ESourceList *source_list;
+ ESource *source;
GtkContainer *container;
+ GtkTreeModel *model;
GtkWidget *widget;
+ GSList *list, *iter;
+ gchar *uid;
priv = E_CAL_SHELL_SIDEBAR_GET_PRIVATE (object);
@@ -117,6 +390,83 @@ cal_shell_sidebar_constructed (GObject *object)
gtk_container_add (container, widget);
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 (cal_shell_sidebar_row_changed_cb),
+ object);
+
+ source = NULL;
+ uid = calendar_config_get_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_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 (cal_shell_sidebar_selection_changed_cb),
+ object);
+
+ g_signal_connect_swapped (
+ widget, "primary-selection-changed",
+ G_CALLBACK (cal_shell_sidebar_primary_selection_changed_cb),
+ object);
+}
+
+static void
+cal_shell_sidebar_client_added (ECalShellSidebar *cal_shell_sidebar,
+ ECal *client)
+{
+ cal_shell_sidebar_update_timezone (cal_shell_sidebar);
+}
+
+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
@@ -130,8 +480,12 @@ cal_shell_sidebar_class_init (ECalShellSidebarClass *class)
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_added = cal_shell_sidebar_client_added;
+ class->client_removed = cal_shell_sidebar_client_removed;
+
g_object_class_install_property (
object_class,
PROP_SELECTOR,
@@ -141,14 +495,53 @@ cal_shell_sidebar_class_init (ECalShellSidebarClass *class)
_("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. */
}
@@ -189,11 +582,87 @@ e_cal_shell_sidebar_new (EShellView *shell_view)
"shell-view", shell_view, NULL);
}
-GtkWidget *
+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 cal_shell_sidebar->priv->selector;
+ 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/calendar/modules/e-cal-shell-sidebar.h b/calendar/modules/e-cal-shell-sidebar.h
index 6a7bccac3c..49b89c556e 100644
--- a/calendar/modules/e-cal-shell-sidebar.h
+++ b/calendar/modules/e-cal-shell-sidebar.h
@@ -22,6 +22,9 @@
#ifndef E_CAL_SHELL_SIDEBAR_H
#define E_CAL_SHELL_SIDEBAR_H
+#include <libecal/e-cal.h>
+#include <libedataserverui/e-source-selector.h>
+
#include <shell/e-shell-sidebar.h>
#include <shell/e-shell-view.h>
@@ -57,11 +60,25 @@ struct _ECalShellSidebar {
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);
GtkWidget * e_cal_shell_sidebar_new (EShellView *shell_view);
-GtkWidget * e_cal_shell_sidebar_get_selector(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