aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEttore Perazzoli <ettore@src.gnome.org>2001-05-03 09:10:46 +0800
committerEttore Perazzoli <ettore@src.gnome.org>2001-05-03 09:10:46 +0800
commit483ebae5399d6aa7d63e471ea6000021a4be94fb (patch)
tree8de0a4611e800febfffa59c25d3b9d806d380757
parent0ac06ee5b0cf27803e037b8bb5f3998898200bd1 (diff)
downloadgsoc2013-evolution-483ebae5399d6aa7d63e471ea6000021a4be94fb.tar.gz
gsoc2013-evolution-483ebae5399d6aa7d63e471ea6000021a4be94fb.tar.zst
gsoc2013-evolution-483ebae5399d6aa7d63e471ea6000021a4be94fb.zip
Add interfaces to the shell to handle off-line operation, as well as a
first (unfinished/untested) implementation for them. svn path=/trunk/; revision=9653
-rw-r--r--shell/ChangeLog20
-rw-r--r--shell/Evolution-Offline.idl48
-rw-r--r--shell/Evolution.idl1
-rw-r--r--shell/Makefile.am3
-rw-r--r--shell/e-shell-offline-handler.c646
-rw-r--r--shell/e-shell-offline-handler.h86
-rw-r--r--shell/e-shell.c105
-rw-r--r--shell/e-shell.h4
-rw-r--r--shell/evolution-shell-component-client.c37
-rw-r--r--shell/evolution-shell-component-client.h6
10 files changed, 955 insertions, 1 deletions
diff --git a/shell/ChangeLog b/shell/ChangeLog
index 7caa04b1f4..b765ad249b 100644
--- a/shell/ChangeLog
+++ b/shell/ChangeLog
@@ -1,3 +1,23 @@
+2001-05-02 Ettore Perazzoli <ettore@ximian.com>
+
+ * e-shell.c: New members `is_offline' and `offline_handler' in
+ `EShellPrivate'.
+ (init): Init `is_offline' to %FALSE, `offline_handler' to %NULL.
+ (e_shell_is_offline): New.
+ (e_shell_go_online): New.
+ (e_shell_go_offline): New.
+
+ * e-shell-offline-handler.c: New.
+ * e-shell-offline-handler.h: New.
+
+ * evolution-shell-component-client.c: New member
+ `offline_interface' in `EvolutionShellComponentClientPrivate'.
+ (init): Init to `CORBA_OBJECT_NIL'.
+ (impl_destroy): Unref/release if not NIL.
+ (evolution_shell_component_client_get_offline_interface): New.
+
+ * Evolution-Offline.idl: New.
+
2001-05-02 Chris Toshok <toshok@ximian.com>
* evolution-shell-component-dnd.c: new file.
diff --git a/shell/Evolution-Offline.idl b/shell/Evolution-Offline.idl
new file mode 100644
index 0000000000..54bee91023
--- /dev/null
+++ b/shell/Evolution-Offline.idl
@@ -0,0 +1,48 @@
+/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Interface to allow components to switch between on-line and off-line mode.
+ *
+ * Authors:
+ * Ettore Perazzoli <ettore@ximian.com>
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ */
+
+#include <Bonobo.h>
+
+module GNOME {
+module Evolution {
+
+struct Connection {
+ string hostName;
+ short portNumber;
+};
+typedef sequence<Connection> ConnectionList;
+
+interface OfflineProgressListener : Bonobo::Unknown {
+ /* Update the shell about the progress of going off-line. The
+ operation is considered completed when the ConnectionList is empty. */
+ void updateProgress (in ConnectionList current_active_connections);
+};
+
+interface Offline : Bonobo::Unknown {
+ /* Whether the component is currently off-line. */
+ attribute boolean isOffline;
+
+ /* Ask the component to prepare to go into off-line mode. The
+ component must return a list of the current active connections.
+ After this call, the shell is expected to either invoke
+ `::goOffline()' (actually complete the operation and go off-line) or
+ `::goOnline()' (operation cancelled). */
+ void prepareForOffline (out ConnectionList active_connection_list);
+
+ /* Ask the component to go into off-line mode. This always comes after
+ a `::prepareForOffline' only. */
+ void goOffline (in OfflineProgressListener listener);
+
+ /* Tell the component to go into on-line mode. */
+ void goOnline ();
+};
+
+};
+};
diff --git a/shell/Evolution.idl b/shell/Evolution.idl
index 3acd6dcca4..b7d0ccc67f 100644
--- a/shell/Evolution.idl
+++ b/shell/Evolution.idl
@@ -13,6 +13,7 @@
#include <Evolution-Session.idl>
#include <Evolution-ShellComponent.idl>
#include <Evolution-ShellComponentDnd.idl>
+#include <Evolution-Offline.idl>
#include <Evolution-ShellView.idl>
#include <Evolution-Storage.idl>
#include <Evolution-StorageSetView.idl>
diff --git a/shell/Makefile.am b/shell/Makefile.am
index c5c55b6d62..efd90a8f8e 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -17,6 +17,7 @@ INCLUDES = \
IDLS = \
Evolution-LocalStorage.idl \
+ Evolution-Offline.idl \
Evolution-Session.idl \
Evolution-Shell.idl \
Evolution-ShellComponent.idl \
@@ -102,6 +103,8 @@ evolution_SOURCES = \
e-shell-folder-selection-dialog.h \
e-shell-folder-title-bar.c \
e-shell-folder-title-bar.h \
+ e-shell-offline-handler.c \
+ e-shell-offline-handler.h \
e-shell-utils.c \
e-shell-utils.h \
e-shell-view-menu.c \
diff --git a/shell/e-shell-offline-handler.c b/shell/e-shell-offline-handler.c
new file mode 100644
index 0000000000..1967041a7e
--- /dev/null
+++ b/shell/e-shell-offline-handler.c
@@ -0,0 +1,646 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-shell-offline-handler.c
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ettore Perazzoli <ettore@ximian.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtktypeutils.h>
+#include <gtk/gtksignal.h>
+#include <gtk/gtkwidget.h>
+
+#include <gal/util/e-util.h>
+
+#include <bonobo/bonobo-main.h>
+
+#include "e-shell-offline-handler.h"
+
+
+#define PARENT_TYPE GTK_TYPE_OBJECT
+static GtkObjectClass *parent_class = NULL;
+
+
+/* Private part. */
+
+struct _OfflineProgressListenerServant {
+ POA_GNOME_Evolution_OfflineProgressListener servant;
+ EShellOfflineHandler *offline_handler;
+ char *component_id;
+};
+typedef struct _OfflineProgressListenerServant OfflineProgressListenerServant;
+
+struct _ComponentInfo {
+ /* Component ID. */
+ char *id;
+
+ /* The `Evolution::Offline' interface for this component (cached just
+ to avoid going through the EComponentRegistry all the time). */
+ GNOME_Evolution_Offline offline_interface;
+
+ /* The interface and servant for the
+ `Evolution::OfflineProgressListener' we have to implement to get
+ notifications about progress of the off-line process. */
+ GNOME_Evolution_OfflineProgressListener progress_listener_interface;
+ OfflineProgressListenerServant *progress_listener_servant;
+
+ /* The current active connections for this component. This is updated
+ by the component itself through the `::ProgressListener' interface;
+ when the count reaches zero, the off-line process is considered to
+ be complete. */
+ GNOME_Evolution_ConnectionList *active_connection_list;
+};
+typedef struct _ComponentInfo ComponentInfo;
+
+struct _EShellOfflineHandlerPrivate {
+ EComponentRegistry *component_registry;
+
+ EShellView *parent_shell_view;
+
+ int num_total_connections;
+ GHashTable *id_to_component_info;
+
+ gboolean procedure_in_progress : 1;
+};
+
+
+/* Signals. */
+
+enum {
+ OFFLINE_PROCEDURE_STARTED,
+ OFFLINE_PROCEDURE_FINISHED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+
+/* Implementation for the OfflineProgressListener interface. */
+
+static PortableServer_ServantBase__epv OfflineProgressListener_base_epv;
+static POA_GNOME_Evolution_OfflineProgressListener__epv OfflineProgressListener_epv;
+static POA_GNOME_Evolution_OfflineProgressListener__vepv OfflineProgressListener_vepv;
+
+static OfflineProgressListenerServant *
+progress_listener_servant_new (EShellOfflineHandler *offline_handler,
+ const char *id)
+{
+ OfflineProgressListenerServant *servant;
+
+ servant = g_new0 (OfflineProgressListenerServant, 1);
+
+ servant->servant.vepv = &OfflineProgressListener_vepv;
+ servant->offline_handler = offline_handler;
+ servant->component_id = g_strdup (id);
+
+ return servant;
+}
+
+static void
+progress_listener_servant_free (OfflineProgressListenerServant *servant)
+{
+ g_free (servant->component_id);
+ g_free (servant);
+}
+
+static GNOME_Evolution_ConnectionList *
+duplicate_connection_list (const GNOME_Evolution_ConnectionList *source)
+{
+ GNOME_Evolution_ConnectionList *copy;
+ int i;
+
+ copy = GNOME_Evolution_ConnectionList__alloc ();
+
+ copy->_length = source->_length;
+ copy->_maximum = source->_length;
+
+ copy->_buffer = CORBA_sequence_GNOME_Evolution_Connection_allocbuf (copy->_maximum);
+
+ for (i = 0; i < source->_length; i++) {
+ copy->_buffer[i].hostName = CORBA_string_dup (source->_buffer[i].hostName);
+ copy->_buffer[i].portNumber = source->_buffer[i].portNumber;
+ }
+
+ return copy;
+}
+
+static void
+impl_OfflineProgressListener_updateProgress (PortableServer_Servant servant,
+ const GNOME_Evolution_ConnectionList *current_active_connections,
+ CORBA_Environment *ev)
+{
+ EShellOfflineHandler *offline_handler;
+ EShellOfflineHandlerPrivate *priv;
+ ComponentInfo *component_info;
+ int connection_delta;
+ const char *component_id;
+
+ component_id = ((OfflineProgressListenerServant *) servant)->component_id;
+
+ offline_handler = ((OfflineProgressListenerServant *) servant)->offline_handler;
+ priv = offline_handler->priv;
+
+ component_info = g_hash_table_lookup (priv->id_to_component_info, component_id);
+ g_assert (component_info != NULL);
+
+ connection_delta = component_info->active_connection_list->_length - current_active_connections->_length;
+ if (connection_delta < 0) {
+ /* FIXME: Should raise an exception or something? */
+ g_warning ("Weird, buggy component increased number of connection when going off-line -- %s",
+ component_id);
+ }
+
+ g_assert (priv->num_total_connections >= connection_delta);
+ priv->num_total_connections -= connection_delta;
+
+ CORBA_free (component_info->active_connection_list);
+ component_info->active_connection_list = duplicate_connection_list (current_active_connections);
+
+ if (priv->num_total_connections == 0)
+ gtk_signal_emit (GTK_OBJECT (offline_handler), signals[OFFLINE_PROCEDURE_FINISHED], TRUE);
+
+ /* TODO: update the dialog. */
+}
+
+static gboolean
+create_progress_listener (EShellOfflineHandler *offline_handler,
+ const char *component_id,
+ GNOME_Evolution_OfflineProgressListener *objref_return,
+ OfflineProgressListenerServant **servant_return)
+{
+ OfflineProgressListenerServant *servant;
+ CORBA_Environment ev;
+
+ *servant_return = NULL;
+ *objref_return = CORBA_OBJECT_NIL;
+
+ OfflineProgressListener_base_epv._private = NULL;
+ OfflineProgressListener_base_epv.finalize = NULL;
+ OfflineProgressListener_base_epv.default_POA = NULL;
+
+ OfflineProgressListener_epv.updateProgress = impl_OfflineProgressListener_updateProgress;
+
+ OfflineProgressListener_vepv._base_epv = &OfflineProgressListener_base_epv;
+ OfflineProgressListener_vepv.GNOME_Evolution_OfflineProgressListener_epv = &OfflineProgressListener_epv;
+
+ servant = progress_listener_servant_new (offline_handler, component_id);
+
+ CORBA_exception_init (&ev);
+
+ POA_GNOME_Evolution_OfflineProgressListener__init ((PortableServer_Servant) servant, &ev);
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("Cannot initialize GNOME::Evolution::Offline::ProgressListener");
+ progress_listener_servant_free (servant);
+ CORBA_exception_free (&ev);
+ return FALSE;
+ }
+
+ CORBA_free (PortableServer_POA_activate_object (bonobo_poa (), servant, &ev));
+
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("Cannot activate GNOME::Evolution::Offline::ProgressListener");
+ progress_listener_servant_free (servant);
+ CORBA_exception_free (&ev);
+ return FALSE;
+ }
+
+ *servant_return = servant;
+ *objref_return = PortableServer_POA_servant_to_reference (bonobo_poa (), servant, &ev);
+
+ CORBA_exception_free (&ev);
+
+ return TRUE;
+}
+
+
+/* ComponentInfo handling. */
+
+static ComponentInfo *
+component_info_new (const char *id,
+ const GNOME_Evolution_Offline offline_interface,
+ GNOME_Evolution_OfflineProgressListener progress_listener_interface,
+ OfflineProgressListenerServant *progress_listener_servant,
+ GNOME_Evolution_ConnectionList *active_connection_list)
+{
+ ComponentInfo *new;
+ CORBA_Environment ev;
+
+ CORBA_exception_init (&ev);
+
+ new = g_new (ComponentInfo, 1);
+ new->id = g_strdup (id);
+ new->offline_interface = CORBA_Object_duplicate (offline_interface, &ev);
+ new->progress_listener_interface = progress_listener_interface;
+ new->progress_listener_servant = progress_listener_servant;
+ new->active_connection_list = active_connection_list;
+
+ CORBA_exception_free (&ev);
+
+ return new;
+}
+
+static void
+component_info_free (ComponentInfo *component_info)
+{
+ CORBA_Environment ev;
+
+ CORBA_exception_init (&ev);
+
+ g_free (component_info->id);
+
+ CORBA_Object_release (component_info->offline_interface, &ev);
+
+ POA_GNOME_Evolution_OfflineProgressListener__fini
+ ((POA_GNOME_Evolution_OfflineProgressListener *) component_info->progress_listener_servant, &ev);
+ progress_listener_servant_free (component_info->progress_listener_servant);
+
+ CORBA_Object_release (component_info->progress_listener_interface, &ev);
+
+ CORBA_free (component_info->active_connection_list);
+
+ g_free (component_info);
+
+ CORBA_exception_free (&ev);
+}
+
+
+/* Utility functions. */
+
+static void
+hash_foreach_free_component_info (void *key,
+ void *value,
+ void *user_data)
+{
+ ComponentInfo *component_info;
+
+ component_info = (ComponentInfo *) value;
+ component_info_free (component_info);
+}
+
+
+/* Cancelling the off-line procedure. */
+
+static void
+cancel_offline (EShellOfflineHandler *offline_handler)
+{
+ EShellOfflineHandlerPrivate *priv;
+ GList *component_ids;
+ GList *p;
+
+ priv = offline_handler->priv;
+
+ component_ids = e_component_registry_get_id_list (priv->component_registry);
+
+ for (p = component_ids; p != NULL; p = p->next) {
+ EvolutionShellComponentClient *shell_component_client;
+ GNOME_Evolution_Offline offline_interface;
+ CORBA_Environment ev;
+ const char *id;
+
+ id = (const char *) p->data;
+ shell_component_client = e_component_registry_get_component_by_id (priv->component_registry, id);
+
+ offline_interface = evolution_shell_component_client_get_offline_interface (shell_component_client);
+ if (offline_interface == CORBA_OBJECT_NIL)
+ continue;
+
+ CORBA_exception_init (&ev);
+
+ GNOME_Evolution_Offline_goOnline (offline_interface, &ev);
+ if (ev._major != CORBA_NO_EXCEPTION)
+ g_warning ("Error putting component `%s' on-line.", id);
+
+ CORBA_exception_free (&ev);
+ }
+
+ e_free_string_list (component_ids);
+
+ priv->num_total_connections = 0;
+}
+
+
+/* Preparing the off-line procedure. */
+
+static gboolean
+prepare_for_offline (EShellOfflineHandler *offline_handler)
+{
+ EShellOfflineHandlerPrivate *priv;
+ GList *component_ids;
+ GList *p;
+ gboolean error;
+
+ priv = offline_handler->priv;
+
+ component_ids = e_component_registry_get_id_list (priv->component_registry);
+
+ error = FALSE;
+ for (p = component_ids; p != NULL; p = p->next) {
+ EvolutionShellComponentClient *shell_component_client;
+ GNOME_Evolution_Offline offline_interface;
+ GNOME_Evolution_OfflineProgressListener progress_listener_interface;
+ GNOME_Evolution_ConnectionList *active_connection_list;
+ OfflineProgressListenerServant *progress_listener_servant;
+ ComponentInfo *component_info;
+ CORBA_Environment ev;
+ const char *id;
+
+ id = (const char *) p->data;
+ shell_component_client = e_component_registry_get_component_by_id (priv->component_registry, id);
+ offline_interface = evolution_shell_component_client_get_offline_interface (shell_component_client);
+ if (offline_interface == CORBA_OBJECT_NIL)
+ continue;
+
+ if (! create_progress_listener (offline_handler, id,
+ &progress_listener_interface,
+ &progress_listener_servant)) {
+ g_warning ("Cannot create the Evolution::OfflineProgressListener interface for `%s'", id);
+ continue;
+ }
+
+ CORBA_exception_init (&ev);
+
+ GNOME_Evolution_Offline_prepareForOffline (offline_interface, &active_connection_list, &ev);
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("Cannot prepare component component to go offline -- %s", id);
+
+ POA_GNOME_Evolution_OfflineProgressListener__fini
+ ((POA_GNOME_Evolution_OfflineProgressListener *) progress_listener_servant, &ev);
+ progress_listener_servant_free (progress_listener_servant);
+
+ CORBA_Object_release (progress_listener_interface, &ev);
+
+ CORBA_exception_free (&ev);
+
+ error = TRUE;
+ break;
+ }
+
+ CORBA_exception_free (&ev);
+
+ priv->num_total_connections += active_connection_list->_length;
+
+ component_info = component_info_new (id,
+ offline_interface,
+ progress_listener_interface,
+ progress_listener_servant,
+ active_connection_list);
+
+ g_assert (g_hash_table_lookup (priv->id_to_component_info, component_info->id) == NULL);
+ g_hash_table_insert (priv->id_to_component_info, component_info->id, component_info);
+ }
+
+ /* If an error occurred while preparing, just put all the components
+ on-line again. */
+ if (error)
+ cancel_offline (offline_handler);
+
+ e_free_string_list (component_ids);
+
+ return ! error;
+}
+
+
+/* Finalizing the off-line procedure. */
+
+static void
+finalize_offline_hash_foreach (void *key,
+ void *value,
+ void *user_data)
+{
+ EShellOfflineHandler *offline_handler;
+ EShellOfflineHandlerPrivate *priv;
+ ComponentInfo *component_info;
+ CORBA_Environment ev;
+
+ offline_handler = E_SHELL_OFFLINE_HANDLER (user_data);
+ priv = offline_handler->priv;
+
+ component_info = (ComponentInfo *) value;
+
+ CORBA_exception_init (&ev);
+
+ g_print ("Putting component off-line -- %s", component_info->id);
+
+ GNOME_Evolution_Offline_goOffline (component_info->offline_interface,
+ component_info->progress_listener_interface,
+ &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ /* FIXME: Should detect an error and put all the components
+ on-line again. */
+ g_warning ("Error putting component off-line -- %s", component_info->id);
+ }
+
+ CORBA_exception_free (&ev);
+}
+
+static void
+finalize_offline (EShellOfflineHandler *offline_handler)
+{
+ EShellOfflineHandlerPrivate *priv;
+
+ priv = offline_handler->priv;
+
+ g_hash_table_foreach (priv->id_to_component_info, finalize_offline_hash_foreach, offline_handler);
+
+ if (priv->num_total_connections == 0) {
+ /* Nothing else to do, we are all set. */
+ gtk_signal_emit (GTK_OBJECT (offline_handler), signals[OFFLINE_PROCEDURE_FINISHED], TRUE);
+ }
+}
+
+
+/* The confirmation dialog. */
+
+static void
+pop_up_confirmation_dialog (EShellOfflineHandler *offline_handler)
+{
+ EShellOfflineHandlerPrivate *priv;
+
+ priv = offline_handler->priv;
+
+ g_warning ("Should pop up dialog here");
+
+ finalize_offline (offline_handler);
+}
+
+
+/* GtkObject methods. */
+
+static void
+impl_destroy (GtkObject *object)
+{
+ EShellOfflineHandler *offline_handler;
+ EShellOfflineHandlerPrivate *priv;
+
+ offline_handler = E_SHELL_OFFLINE_HANDLER (object);
+ priv = offline_handler->priv;
+
+ if (priv->component_registry != NULL)
+ gtk_object_unref (GTK_OBJECT (priv->component_registry));
+
+ g_hash_table_foreach (priv->id_to_component_info, hash_foreach_free_component_info, NULL);
+ g_hash_table_destroy (priv->id_to_component_info);
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy != NULL)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+
+/* GTK type handling. */
+
+static void
+class_init (EShellOfflineHandlerClass *klass)
+{
+ GtkObjectClass *object_class;
+
+ object_class = GTK_OBJECT_CLASS (klass);
+ object_class->destroy = impl_destroy;
+
+ parent_class = gtk_type_class (gtk_object_get_type ());
+
+ signals[OFFLINE_PROCEDURE_STARTED]
+ = gtk_signal_new ("offline_procedure_started",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EShellOfflineHandlerClass, offline_procedure_started),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ signals[OFFLINE_PROCEDURE_FINISHED]
+ = gtk_signal_new ("offline_procedure_finished",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EShellOfflineHandlerClass, offline_procedure_finished),
+ gtk_marshal_NONE__BOOL,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_BOOL);
+
+ gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
+}
+
+
+static void
+init (EShellOfflineHandler *shell_offline_handler)
+{
+ EShellOfflineHandlerPrivate *priv;
+
+ priv = g_new (EShellOfflineHandlerPrivate, 1);
+
+ priv->component_registry = NULL;
+ priv->parent_shell_view = NULL;
+ priv->procedure_in_progress = TRUE;
+
+ priv->num_total_connections = 0;
+ priv->id_to_component_info = g_hash_table_new (g_str_hash, g_str_equal);
+
+ shell_offline_handler->priv = priv;
+}
+
+
+/**
+ * e_shell_offline_handler_construct:
+ * @offline_handler: A pointer to an EShellOfflineHandler to construct.
+ * @component_registry: The registry for the components that we want to put
+ * off-line.
+ *
+ * Construct the @offline_handler.
+ **/
+void
+e_shell_offline_handler_construct (EShellOfflineHandler *offline_handler,
+ EComponentRegistry *component_registry)
+{
+ EShellOfflineHandlerPrivate *priv;
+
+ g_return_if_fail (offline_handler != NULL);
+ g_return_if_fail (E_IS_SHELL_OFFLINE_HANDLER (offline_handler));
+ g_return_if_fail (component_registry != NULL);
+ g_return_if_fail (E_IS_COMPONENT_REGISTRY (component_registry));
+
+ g_assert (priv->component_registry == NULL);
+
+ gtk_object_ref (GTK_OBJECT (component_registry));
+ priv->component_registry = component_registry;
+}
+
+/**
+ * e_shell_offline_handler_new:
+ * @component_registry: The registry for the components that we want to put
+ * off-line.
+ *
+ * Create a new offline handler.
+ *
+ * Return value: A pointer to the newly created EShellOfflineHandler object.
+ **/
+EShellOfflineHandler *
+e_shell_offline_handler_new (EComponentRegistry *component_registry)
+{
+ EShellOfflineHandler *offline_handler;
+
+ g_return_val_if_fail (component_registry != NULL, NULL);
+ g_return_val_if_fail (E_IS_COMPONENT_REGISTRY (component_registry), NULL);
+
+ offline_handler = (EShellOfflineHandler *) gtk_type_new (e_shell_offline_handler_get_type ());
+ e_shell_offline_handler_construct (offline_handler, component_registry);
+
+ return offline_handler;
+}
+
+
+/**
+ * e_shell_offline_handler_put_components_offline:
+ * @offline_handler: A pointer to an EShellOfflineHandler object.
+ *
+ * Put the components offline.
+ **/
+void
+e_shell_offline_handler_put_components_offline (EShellOfflineHandler *offline_handler,
+ EShellView *parent_shell_view)
+{
+ EShellOfflineHandlerPrivate *priv;
+
+ g_return_if_fail (offline_handler != NULL);
+ g_return_if_fail (E_IS_SHELL_OFFLINE_HANDLER (offline_handler));
+ g_return_if_fail (parent_shell_view == NULL || E_IS_SHELL_VIEW (parent_shell_view));
+
+ priv = offline_handler->priv;
+
+ priv->procedure_in_progress = TRUE;
+ priv->parent_shell_view = parent_shell_view;
+
+ gtk_signal_emit (GTK_OBJECT (offline_handler), signals[OFFLINE_PROCEDURE_STARTED]);
+
+ if (! prepare_for_offline (offline_handler)) {
+ /* FIXME: Maybe do something smarter here. */
+ g_warning ("Couldn't put components off-line for some internal error");
+ gtk_signal_emit (GTK_OBJECT (offline_handler), signals[OFFLINE_PROCEDURE_FINISHED], FALSE);
+ return;
+ }
+
+ if (priv->num_total_connections == 0 && priv->parent_shell_view != NULL)
+ pop_up_confirmation_dialog (offline_handler);
+ else
+ finalize_offline (offline_handler);
+}
+
+
+E_MAKE_TYPE (e_shell_offline_handler, "EShellOfflineHandler", EShellOfflineHandler, class_init, init, PARENT_TYPE)
diff --git a/shell/e-shell-offline-handler.h b/shell/e-shell-offline-handler.h
new file mode 100644
index 0000000000..cbb726a057
--- /dev/null
+++ b/shell/e-shell-offline-handler.h
@@ -0,0 +1,86 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-shell-offline-handler.h
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ettore Perazzoli <ettore@ximian.com>
+ */
+
+#ifndef _E_SHELL_OFFLINE_HANDLER_H_
+#define _E_SHELL_OFFLINE_HANDLER_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtkobject.h>
+
+#include "e-component-registry.h"
+#include "e-shell-view.h"
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#define E_TYPE_SHELL_OFFLINE_HANDLER (e_shell_offline_handler_get_type ())
+#define E_SHELL_OFFLINE_HANDLER(obj) (GTK_CHECK_CAST ((obj), E_TYPE_SHELL_OFFLINE_HANDLER, EShellOfflineHandler))
+#define E_SHELL_OFFLINE_HANDLER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_SHELL_OFFLINE_HANDLER, EShellOfflineHandlerClass))
+#define E_IS_SHELL_OFFLINE_HANDLER(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_SHELL_OFFLINE_HANDLER))
+#define E_IS_SHELL_OFFLINE_HANDLER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_SHELL_OFFLINE_HANDLER))
+
+
+typedef struct _EShellOfflineHandler EShellOfflineHandler;
+typedef struct _EShellOfflineHandlerPrivate EShellOfflineHandlerPrivate;
+typedef struct _EShellOfflineHandlerClass EShellOfflineHandlerClass;
+
+struct _EShellOfflineHandler {
+ GtkObject parent;
+
+ EShellOfflineHandlerPrivate *priv;
+};
+
+struct _EShellOfflineHandlerClass {
+ GtkObjectClass parent_class;
+
+ /* This signal is emitted when the offline procedure starts, i.e. the
+ EShellOfflineHanlder starts contacting the components one-by-one
+ telling them to be prepared to go off-line. */
+ void (* offline_procedure_started) (EShellOfflineHandler *offline_handler);
+
+ /* This is emitted when the procedure is finished, and all the
+ components are all either off-line (@now_offline is %TRUE) or
+ on-line (@now_offline is %FALSE). */
+ void (* offline_procedure_finished) (EShellOfflineHandler *offline_hanlder,
+ gboolean now_offline);
+};
+
+
+GtkType e_shell_offline_handler_get_type (void);
+void e_shell_offline_handler_construct (EShellOfflineHandler *offline_handler,
+ EComponentRegistry *component_registry);
+EShellOfflineHandler *e_shell_offline_handler_new (EComponentRegistry *component_registry);
+
+void e_shell_offline_handler_put_components_offline (EShellOfflineHandler *offline_handler,
+ EShellView *parent_shell_view);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _E_SHELL_OFFLINE_HANDLER_H_ */
diff --git a/shell/e-shell.c b/shell/e-shell.c
index f9b38e666a..c2c5f39893 100644
--- a/shell/e-shell.c
+++ b/shell/e-shell.c
@@ -44,6 +44,7 @@
#include "e-local-storage.h"
#include "e-shell-constants.h"
#include "e-shell-folder-selection-dialog.h"
+#include "e-shell-offline-handler.h"
#include "e-shell-view.h"
#include "e-shortcuts.h"
#include "e-storage-set.h"
@@ -74,8 +75,15 @@ struct _EShellPrivate {
ECorbaStorageRegistry *corba_storage_registry;
+ /* This object handles going off-line. If the pointer is not NULL, it
+ means we have a going-off-line process in progress. */
+ EShellOfflineHandler *offline_handler;
+
/* Names for the types of the folders that have maybe crashed. */
GList *crash_type_names; /* char * */
+
+ /* Whether the shell is off-line or not. */
+ guint is_offline : 1;
};
@@ -606,6 +614,10 @@ destroy (GtkObject *object)
if (priv->corba_storage_registry != NULL)
bonobo_object_unref (BONOBO_OBJECT (priv->corba_storage_registry));
+ /* FIXME. Maybe we should do something special here. */
+ if (priv->offline_handler != NULL)
+ gtk_object_unref (GTK_OBJECT (priv->offline_handler));
+
e_free_string_list (priv->crash_type_names);
g_free (priv);
@@ -680,7 +692,9 @@ init (EShell *shell)
priv->component_registry = NULL;
priv->folder_type_registry = NULL;
priv->corba_storage_registry = NULL;
+ priv->offline_handler = NULL;
priv->crash_type_names = NULL;
+ priv->is_offline = FALSE;
shell->priv = priv;
}
@@ -1257,4 +1271,95 @@ e_shell_component_maybe_crashed (EShell *shell,
}
+/**
+ * e_shell_is_offline:
+ * @shell: A pointer to an EShell object.
+ *
+ * Return whether @shell is working in off-line mode.
+ *
+ * Return value: %TRUE if the @shell is working in off-line mode, %FALSE
+ * otherwise.
+ **/
+gboolean
+e_shell_is_offline (EShell *shell)
+{
+ g_return_val_if_fail (shell != NULL, FALSE);
+ g_return_val_if_fail (E_IS_SHELL (shell), FALSE);
+
+ return shell->priv->is_offline;
+}
+
+/**
+ * e_shell_go_offline:
+ * @shell:
+ * @action_view:
+ *
+ * Make the shell go into off-line mode.
+ **/
+void
+e_shell_go_offline (EShell *shell,
+ EShellView *action_view)
+{
+ EShellPrivate *priv;
+
+ g_return_if_fail (shell != NULL);
+ g_return_if_fail (E_IS_SHELL (shell));
+ g_return_if_fail (action_view != NULL);
+ g_return_if_fail (action_view == NULL || E_IS_SHELL_VIEW (action_view));
+
+ priv = shell->priv;
+}
+
+/**
+ * e_shell_go_online:
+ * @shell:
+ * @action_view:
+ *
+ * Make the shell go into on-line mode.
+ **/
+void
+e_shell_go_online (EShell *shell,
+ EShellView *action_view)
+{
+ EShellPrivate *priv;
+ GList *component_ids;
+ GList *p;
+
+ g_return_if_fail (shell != NULL);
+ g_return_if_fail (E_IS_SHELL (shell));
+ g_return_if_fail (action_view == NULL || E_IS_SHELL_VIEW (action_view));
+
+ priv = shell->priv;
+
+ component_ids = e_component_registry_get_id_list (priv->component_registry);
+
+ for (p = component_ids; p != NULL; p = p->next) {
+ CORBA_Environment ev;
+ EvolutionShellComponentClient *client;
+ GNOME_Evolution_Offline offline_interface;
+ const char *id;
+
+ id = (const char *) p->data;
+ client = e_component_registry_get_component_by_id (priv->component_registry, id);
+
+ CORBA_exception_init (&ev);
+
+ offline_interface = evolution_shell_component_client_get_offline_interface (client);
+
+ if (CORBA_Object_is_nil (offline_interface, &ev) || ev._major != CORBA_NO_EXCEPTION) {
+ CORBA_exception_free (&ev);
+ continue;
+ }
+
+ GNOME_Evolution_Offline_goOnline (offline_interface, &ev);
+ if (ev._major != CORBA_NO_EXCEPTION)
+ g_warning ("Error putting component `%s' online.", id);
+
+ CORBA_exception_free (&ev);
+ }
+
+ e_free_string_list (component_ids);
+}
+
+
E_MAKE_TYPE (e_shell, "EShell", EShell, class_init, init, PARENT_TYPE)
diff --git a/shell/e-shell.h b/shell/e-shell.h
index f4342988ce..b3226b50d6 100644
--- a/shell/e-shell.h
+++ b/shell/e-shell.h
@@ -94,6 +94,10 @@ void e_shell_component_maybe_crashed (EShell *shell,
const char *type_name,
EShellView *shell_view);
+gboolean e_shell_is_offline (EShell *shell);
+void e_shell_go_offline (EShell *shell, EShellView *action_view);
+void e_shell_go_online (EShell *shell, EShellView *action_view);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/shell/evolution-shell-component-client.c b/shell/evolution-shell-component-client.c
index 759e4f6ac4..db92d0efaf 100644
--- a/shell/evolution-shell-component-client.c
+++ b/shell/evolution-shell-component-client.c
@@ -53,6 +53,7 @@ struct _EvolutionShellComponentClientPrivate {
GNOME_Evolution_ShellComponentDnd_SourceFolder dnd_source_folder_interface;
GNOME_Evolution_ShellComponentDnd_DestinationFolder dnd_destination_folder_interface;
+ GNOME_Evolution_Offline offline_interface;
};
@@ -295,6 +296,11 @@ impl_destroy (GtkObject *object)
CORBA_Object_release (priv->dnd_destination_folder_interface, &ev);
}
+ if (priv->offline_interface != CORBA_OBJECT_NIL) {
+ Bonobo_Unknown_unref (priv->offline_interface, &ev);
+ CORBA_Object_release (priv->offline_interface, &ev);
+ }
+
CORBA_exception_free (&ev);
g_free (priv);
@@ -329,6 +335,7 @@ init (EvolutionShellComponentClient *shell_component_client)
priv->dnd_source_folder_interface = CORBA_OBJECT_NIL;
priv->dnd_destination_folder_interface = CORBA_OBJECT_NIL;
+ priv->offline_interface = CORBA_OBJECT_NIL;
shell_component_client->priv = priv;
}
@@ -453,6 +460,36 @@ evolution_shell_component_client_get_dnd_destination_interface (EvolutionShellCo
}
+/* Querying the offline interface. */
+
+GNOME_Evolution_Offline
+evolution_shell_component_client_get_offline_interface (EvolutionShellComponentClient *shell_component_client)
+{
+ EvolutionShellComponentClientPrivate *priv;
+ GNOME_Evolution_Offline interface;
+ CORBA_Environment ev;
+
+ priv = shell_component_client->priv;
+
+ if (priv->offline_interface != CORBA_OBJECT_NIL)
+ return priv->offline_interface;
+
+ CORBA_exception_init (&ev);
+
+ interface = Bonobo_Unknown_queryInterface (bonobo_object_corba_objref (BONOBO_OBJECT (shell_component_client)),
+ "IDL:GNOME/Evolution/ShellComponent/Offline:1.0",
+ &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION)
+ interface = CORBA_OBJECT_NIL;
+
+ CORBA_exception_free (&ev);
+
+ priv->offline_interface = interface;
+ return interface;
+}
+
+
/* Synchronous operations. */
EvolutionShellComponentResult
diff --git a/shell/evolution-shell-component-client.h b/shell/evolution-shell-component-client.h
index 579d830184..e781a0c74c 100644
--- a/shell/evolution-shell-component-client.h
+++ b/shell/evolution-shell-component-client.h
@@ -73,9 +73,13 @@ evolution_shell_component_client_get_dnd_source_interface (EvolutionShellCompone
GNOME_Evolution_ShellComponentDnd_DestinationFolder
evolution_shell_component_client_get_dnd_destination_interface (EvolutionShellComponentClient *shell_component_client);
+/* Querying the offline interface. */
+GNOME_Evolution_Offline
+evolution_shell_component_client_get_offline_interface (EvolutionShellComponentClient *shell_component_client);
+
/* Synchronous operations. */
EvolutionShellComponentResult evolution_shell_component_client_set_owner (EvolutionShellComponentClient *shell_component_client,
- GNOME_Evolution_Shell shell,
+ GNOME_Evolution_Shell shell,
const char *evolution_homedir);
EvolutionShellComponentResult evolution_shell_component_client_unset_owner (EvolutionShellComponentClient *shell_component_client,
GNOME_Evolution_Shell shell);