diff options
Diffstat (limited to 'shell/e-shell.c')
-rw-r--r-- | shell/e-shell.c | 322 |
1 files changed, 254 insertions, 68 deletions
diff --git a/shell/e-shell.c b/shell/e-shell.c index 9678790d72..6ef5de27c5 100644 --- a/shell/e-shell.c +++ b/shell/e-shell.c @@ -24,37 +24,74 @@ #include <e-preferences-window.h> #include <e-util/e-util.h> +#include "e-shell-marshal.h" #include "e-shell-module.h" #include "e-shell-registry.h" +#include "e-shell-window.h" #define SHUTDOWN_TIMEOUT 500 /* milliseconds */ -static GList *active_windows; +#define E_SHELL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SHELL, EShellPrivate)) + +struct _EShellPrivate { + GList *active_windows; + EShellLineStatus line_status; + + guint online : 1; + guint safe_mode : 1; +}; + +enum { + PROP_0, + PROP_ONLINE +}; + +enum { + HANDLE_URI, + SEND_RECEIVE, + WINDOW_CREATED, + WINDOW_DESTROYED, + LAST_SIGNAL +}; + +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; + +#if NM_SUPPORT +void e_shell_dbus_initialize (EShell *shell); +#endif static gboolean -shell_window_delete_event_cb (EShellWindow *shell_window) +shell_window_delete_event_cb (EShell *shell, + EShellWindow *shell_window) { /* If other windows are open we can safely close this one. */ - if (g_list_length (active_windows) > 1) + if (g_list_length (shell->priv->active_windows) > 1) return FALSE; /* Otherwise we initiate application shutdown. */ - return !e_shell_quit (); + return !e_shell_quit (shell); } static void -shell_window_weak_notify_cb (gpointer unused, +shell_window_weak_notify_cb (EShell *shell, GObject *where_the_object_was) { + GList *active_windows; + gboolean last_window; + + active_windows = shell->priv->active_windows; active_windows = g_list_remove (active_windows, where_the_object_was); + shell->priv->active_windows = active_windows; - /* If that was the last window, we're done. */ - if (active_windows == NULL) - gtk_main_quit (); + last_window = (shell->priv->active_windows == NULL); + g_signal_emit (shell, signals[WINDOW_DESTROYED], 0, last_window); } static gboolean -shell_shutdown_timeout (void) +shell_shutdown_timeout (EShell *shell) { GList *list, *iter; gboolean proceed = TRUE; @@ -86,7 +123,7 @@ shell_shutdown_timeout (void) * the act of destroying a shell window will modify the active * windows list, which would otherwise derail the iteration. */ if (proceed) { - list = g_list_copy (active_windows); + list = g_list_copy (shell->priv->active_windows); g_list_foreach (list, (GFunc) gtk_widget_destroy, NULL); g_list_free (list); @@ -94,105 +131,254 @@ shell_shutdown_timeout (void) } else if (source_id == 0) source_id = g_timeout_add ( SHUTDOWN_TIMEOUT, (GSourceFunc) - shell_shutdown_timeout, NULL); + shell_shutdown_timeout, shell); /* Return TRUE to repeat the timeout, FALSE to stop it. This * may seem backwards if the function was called directly. */ return !proceed; } -EShellWindow * -e_shell_create_window (void) +static void +shell_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ONLINE: + e_shell_set_online ( + E_SHELL (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +shell_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { + switch (property_id) { + case PROP_ONLINE: + g_value_set_boolean ( + value, e_shell_get_online ( + E_SHELL (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +shell_dispose (GObject *object) +{ + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +shell_finalize (GObject *object) +{ + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +shell_class_init (EShellClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EShellPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = shell_set_property; + object_class->get_property = shell_get_property; + object_class->dispose = shell_dispose; + object_class->finalize = shell_finalize; + + g_object_class_install_property ( + object_class, + PROP_ONLINE, + g_param_spec_boolean ( + "online", + _("Online"), + _("Whether the shell is online"), + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + signals[HANDLE_URI] = g_signal_new ( + "handle-uri", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, g_signal_accumulator_true_handled, NULL, + e_shell_marshal_BOOLEAN__STRING, + G_TYPE_BOOLEAN, 1, + G_TYPE_STRING); + + signals[SEND_RECEIVE] = g_signal_new ( + "send-receive", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + GTK_TYPE_WINDOW); + + signals[WINDOW_CREATED] = g_signal_new ( + "window-created", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_SHELL_WINDOW); + + signals[WINDOW_DESTROYED] = g_signal_new ( + "window-destroyed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, + G_TYPE_BOOLEAN); +} + +static void +shell_init (EShell *shell) +{ + shell->priv = E_SHELL_GET_PRIVATE (shell); + + shell->priv->safe_mode = e_file_lock_exists (); + +#if NM_SUPPORT + e_shell_dbus_initialize (shell); +#endif + + e_file_lock_create (); + e_shell_registry_init (shell); +} + +GType +e_shell_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + const GTypeInfo type_info = { + sizeof (EShellClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) shell_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EShell), + 0, /* n_preallocs */ + (GInstanceInitFunc) shell_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + G_TYPE_OBJECT, "EShell", &type_info, 0); + } + + return type; +} + +EShell * +e_shell_new (gboolean online) +{ + return g_object_new (E_TYPE_SHELL, "online", online, NULL); +} + +GtkWidget * +e_shell_create_window (EShell *shell) +{ + GList *active_windows; GtkWidget *shell_window; - gboolean safe_mode; - /* Put the first window into safe mode if we detect the previous - * session did not shut down cleanly, perhaps due to a crash. */ - safe_mode = (active_windows == NULL) && e_file_lock_exists (); + g_return_val_if_fail (E_IS_SHELL (shell), NULL); - shell_window = e_shell_window_new (safe_mode); + shell_window = e_shell_window_new (shell, shell->priv->safe_mode); + active_windows = shell->priv->active_windows; active_windows = g_list_prepend (active_windows, shell_window); + shell->priv->active_windows = active_windows; - g_signal_connect ( + g_signal_connect_swapped ( shell_window, "delete-event", - G_CALLBACK (shell_window_delete_event_cb), NULL); + G_CALLBACK (shell_window_delete_event_cb), shell); g_object_weak_ref ( G_OBJECT (shell_window), (GWeakNotify) - shell_window_weak_notify_cb, NULL); + shell_window_weak_notify_cb, shell); - g_list_foreach ( - e_shell_registry_list_modules (), - (GFunc) e_shell_module_window_created, shell_window); + g_signal_emit (shell, signals[WINDOW_CREATED], 0, shell_window); gtk_widget_show (shell_window); - return E_SHELL_WINDOW (shell_window); + return shell_window; } gboolean -e_shell_handle_uri (const gchar *uri) +e_shell_handle_uri (EShell *shell, + const gchar *uri) { - EShellModule *shell_module; - GFile *file; - gchar *scheme; + gboolean handled; + g_return_val_if_fail (E_IS_SHELL (shell), FALSE); g_return_val_if_fail (uri != NULL, FALSE); - file = g_file_new_for_uri (uri); - scheme = g_file_get_uri_scheme (file); - g_object_unref (file); - - if (scheme == NULL) - return FALSE; - - shell_module = e_shell_registry_get_module_by_scheme (scheme); - - /* Scheme lookup failed so try looking up the shell module by - * name. Note, we only open a shell window if the URI refers - * to a shell module by name, not by scheme. */ - if (shell_module == NULL) { - EShellWindow *shell_window; - - shell_module = e_shell_registry_get_module_by_name (scheme); + g_signal_emit (shell, signals[HANDLE_URI], 0, uri, &handled); - if (shell_module == NULL) - return FALSE; - - shell_window = e_shell_create_window (); - /* FIXME Set window to appropriate view. */ - } - - return e_shell_module_handle_uri (shell_module, uri); + return handled; } void -e_shell_send_receive (GtkWindow *parent) +e_shell_send_receive (EShell *shell, + GtkWindow *parent) { - g_list_foreach ( - e_shell_registry_list_modules (), - (GFunc) e_shell_module_send_and_receive, NULL); + g_return_if_fail (E_IS_SHELL (shell)); + g_return_if_fail (GTK_IS_WINDOW (parent)); + + g_signal_emit (shell, signals[SEND_RECEIVE], 0, parent); } -void -e_shell_go_offline (void) +gboolean +e_shell_get_online (EShell *shell) { - /* FIXME */ + g_return_val_if_fail (E_IS_SHELL (shell), FALSE); + + return shell->priv->online; } void -e_shell_go_online (void) +e_shell_set_online (EShell *shell, + gboolean online) { - /* FIXME */ + g_return_if_fail (E_IS_SHELL (shell)); + + shell->priv->online = online; + + g_object_notify (G_OBJECT (shell), "online"); } EShellLineStatus -e_shell_get_line_status (void) +e_shell_get_line_status (EShell *shell) +{ + g_return_val_if_fail (E_IS_SHELL (shell), E_SHELL_LINE_STATUS_OFFLINE); + + return shell->priv->line_status; +} + +void +e_shell_set_line_status (EShell *shell, + EShellLineStatus status) { - /* FIXME */ - return E_SHELL_LINE_STATUS_ONLINE; } GtkWidget * @@ -207,21 +393,21 @@ e_shell_get_preferences_window (void) } gboolean -e_shell_is_busy (void) +e_shell_is_busy (EShell *shell) { /* FIXME */ return FALSE; } gboolean -e_shell_do_quit (void) +e_shell_do_quit (EShell *shell) { /* FIXME */ return TRUE; } gboolean -e_shell_quit (void) +e_shell_quit (EShell *shell) { /* FIXME */ return TRUE; |