diff options
author | Matthew Barnes <mbarnes@src.gnome.org> | 2008-09-09 04:37:00 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@src.gnome.org> | 2008-09-09 04:37:00 +0800 |
commit | 5350eebb5ef8c07e69110616ce1662e0e92bea16 (patch) | |
tree | d1d822ed1af3c92168b04780cfb6ac48a18b5996 /shell | |
parent | 52d683e48cf1103a9806da95c72abce2db3ae1f4 (diff) | |
download | gsoc2013-evolution-5350eebb5ef8c07e69110616ce1662e0e92bea16.tar.gz gsoc2013-evolution-5350eebb5ef8c07e69110616ce1662e0e92bea16.tar.zst gsoc2013-evolution-5350eebb5ef8c07e69110616ce1662e0e92bea16.zip |
Progress update:
- Merge ETaskBar into EShellTaskbar.
- Remember the last view, and make --component work.
svn path=/branches/kill-bonobo/; revision=36278
Diffstat (limited to 'shell')
-rw-r--r-- | shell/Makefile.am | 8 | ||||
-rw-r--r-- | shell/e-activity-handler.c | 682 | ||||
-rw-r--r-- | shell/e-activity-handler.h | 107 | ||||
-rw-r--r-- | shell/e-shell-content.c | 916 | ||||
-rw-r--r-- | shell/e-shell-content.h | 57 | ||||
-rw-r--r-- | shell/e-shell-registry.c | 4 | ||||
-rw-r--r-- | shell/e-shell-sidebar.c | 100 | ||||
-rw-r--r-- | shell/e-shell-sidebar.h | 7 | ||||
-rw-r--r-- | shell/e-shell-view.c | 193 | ||||
-rw-r--r-- | shell/e-shell-view.h | 11 | ||||
-rw-r--r-- | shell/e-shell-window-actions.c | 65 | ||||
-rw-r--r-- | shell/e-shell-window-private.c | 4 | ||||
-rw-r--r-- | shell/e-shell-window.c | 11 | ||||
-rw-r--r-- | shell/main.c | 29 | ||||
-rw-r--r-- | shell/test/e-test-shell-view.c | 44 |
15 files changed, 2016 insertions, 222 deletions
diff --git a/shell/Makefile.am b/shell/Makefile.am index c593548b6d..12900aac3f 100644 --- a/shell/Makefile.am +++ b/shell/Makefile.am @@ -58,10 +58,13 @@ privsolib_LTLIBRARIES = \ eshellincludedir = $(privincludedir)/shell eshellinclude_HEADERS = \ + e-activity-handler.h \ e-shell-common.h \ e-shell-content.h \ e-shell-module.h \ + e-shell-sidebar.h \ e-shell-switcher.h \ + e-shell-taskbar.h \ e-shell-view.h \ e-shell-window.h \ e-shell-window-actions.h \ @@ -70,9 +73,12 @@ eshellinclude_HEADERS = \ libeshell_la_SOURCES = \ $(IDL_GENERATED) \ $(MARSHAL_GENERATED) \ + e-activity-handler.c \ e-shell-content.c \ e-shell-module.c \ + e-shell-sidebar.c \ e-shell-switcher.c \ + e-shell-taskbar.c \ e-shell-view.c \ e-shell-window.c \ e-shell-window-actions.c \ @@ -99,8 +105,6 @@ evolution_SOURCES = \ e-shell-importer.h \ e-shell-registry.c \ e-shell-registry.h \ - e-shell-sidebar.c \ - e-shell-sidebar.h \ e-shell-window-private.c \ e-shell-window-private.h \ es-event.c \ diff --git a/shell/e-activity-handler.c b/shell/e-activity-handler.c new file mode 100644 index 0000000000..27f17a75bb --- /dev/null +++ b/shell/e-activity-handler.c @@ -0,0 +1,682 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-activity-handler.c + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * Author: Ettore Perazzoli <ettore@ximian.com> + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "e-activity-handler.h" + +#include <glib/gi18n.h> +#include <gtk/gtksignal.h> +#include <gdk-pixbuf/gdk-pixbuf.h> + +struct _ActivityInfo { + int error_type; + guint id; + char *information; + gboolean cancellable; + double progress; + GtkWidget *menu; + void (*cancel_func) (gpointer data); + gpointer data; + gpointer error; + time_t error_time; +}; +typedef struct _ActivityInfo ActivityInfo; + +struct _EActivityHandlerPrivate { + guint next_activity_id; + GList *activity_infos; + GSList *task_bars; + ELogger *logger; + guint error_timer; + guint error_flush_interval; + +}; + +/* In the status bar, we show only errors and info. Errors are pictured as warnings. */ +const char *icon_data [] = {"stock_dialog-warning", "stock_dialog-info"}; + +G_DEFINE_TYPE (EActivityHandler, e_activity_handler, G_TYPE_OBJECT) + +/* Utility functions. */ + +static void handle_error (ETaskWidget *task); + +static unsigned int +get_new_activity_id (EActivityHandler *activity_handler) +{ + EActivityHandlerPrivate *priv; + + priv = activity_handler->priv; + + return priv->next_activity_id ++; +} + +static GList * +lookup_activity (GList *list, + guint activity_id, + int *order_number_return) +{ + GList *p; + int i; + + for (p = list, i = 0; p != NULL; p = p->next, i ++) { + ActivityInfo *activity_info; + + activity_info = (ActivityInfo *) p->data; + if (activity_info->id == activity_id) { + *order_number_return = i; + return p; + } + } + + *order_number_return = -1; + return NULL; +} + + +/* ETaskWidget actions. */ + +static int +task_widget_button_press_event_callback (GtkWidget *widget, + GdkEventButton *button_event, + void *data) +{ + ActivityInfo *activity_info; + + activity_info = (ActivityInfo *) data; + + if (button_event->button == 3) + return activity_info->cancellable; + + if (button_event->button != 1) + return FALSE; + + return TRUE; +} + + +/* Creating and destroying ActivityInfos. */ + +static ActivityInfo * +activity_info_new (guint id, + const char *information, + gboolean cancellable) +{ + ActivityInfo *info; + + info = g_new (ActivityInfo, 1); + info->id = id; + info->information = g_strdup (information); + info->cancellable = cancellable; + info->progress = -1.0; /* (Unknown) */ + info->menu = NULL; + info->error = NULL; + info->cancel_func = NULL; + + return info; +} + +static void +activity_info_free (ActivityInfo *info) +{ + g_free (info->information); + + if (info->menu != NULL) + gtk_widget_destroy (info->menu); + + g_free (info); +} + +static ETaskWidget * +task_widget_new_from_activity_info (ActivityInfo *activity_info) +{ + GtkWidget *widget; + ETaskWidget *etw; + + widget = e_task_widget_new_with_cancel ( + activity_info->information, + activity_info->cancel_func, + activity_info->data); + etw = (ETaskWidget *) widget; + etw->id = activity_info->id; + gtk_widget_show (widget); + + g_signal_connect (widget, "button_press_event", + G_CALLBACK (task_widget_button_press_event_callback), + activity_info); + + return E_TASK_WIDGET (widget); +} + + +/* Task Bar handling. */ + +static void +setup_task_bar (EActivityHandler *activity_handler, + EShellTaskbar *shell_taskbar) +{ + EActivityHandlerPrivate *priv; + GList *p; + + priv = activity_handler->priv; + + for (p = g_list_last (priv->activity_infos); p != NULL; p = p->prev) { + ActivityInfo *info = p->data; + ETaskWidget *task_widget = task_widget_new_from_activity_info (info); + task_widget->id = info->id; + e_shell_taskbar_prepend_task (shell_taskbar, task_widget); + if (info->error) { + /* Prepare to handle existing errors*/ + GtkWidget *tool; + const char *stock; + + stock = info->error_type ? icon_data [1] : icon_data[0]; + tool = e_task_widget_update_image (task_widget, (char *)stock, info->information); + g_object_set_data ((GObject *) task_widget, "tool", tool); + g_object_set_data ((GObject *) task_widget, "error", info->error); + g_object_set_data ((GObject *) task_widget, "activity-handler", activity_handler); + g_object_set_data ((GObject *) task_widget, "activity", GINT_TO_POINTER(info->id)); + g_object_set_data ((GObject *) task_widget, "error-type", GINT_TO_POINTER(info->error_type)); + g_signal_connect_swapped (tool, "clicked", G_CALLBACK(handle_error), task_widget); + } + } +} + +static void +task_bar_destroy_notify (void *data, + GObject *shell_taskbar_instance) +{ + EActivityHandler *activity_handler; + EActivityHandlerPrivate *priv; + + activity_handler = E_ACTIVITY_HANDLER (data); + priv = activity_handler->priv; + + priv->task_bars = g_slist_remove (priv->task_bars, shell_taskbar_instance); +} + + +/* GObject methods. */ + +static void +impl_dispose (GObject *object) +{ + EActivityHandler *handler; + EActivityHandlerPrivate *priv; + GList *p; + GSList *sp; + + handler = E_ACTIVITY_HANDLER (object); + priv = handler->priv; + + for (p = priv->activity_infos; p != NULL; p = p->next) { + ActivityInfo *info; + + info = (ActivityInfo *) p->data; + activity_info_free (info); + } + + g_list_free (priv->activity_infos); + priv->activity_infos = NULL; + + for (sp = priv->task_bars; sp != NULL; sp = sp->next) + g_object_weak_unref (G_OBJECT (sp->data), task_bar_destroy_notify, handler); + priv->task_bars = NULL; + + (* G_OBJECT_CLASS (e_activity_handler_parent_class)->dispose) (object); +} + +static void +impl_finalize (GObject *object) +{ + EActivityHandler *handler; + EActivityHandlerPrivate *priv; + + handler = E_ACTIVITY_HANDLER (object); + priv = handler->priv; + + g_free (priv); + + (* G_OBJECT_CLASS (e_activity_handler_parent_class)->finalize) (object); +} + +static void +e_activity_handler_class_init (EActivityHandlerClass *activity_handler_class) +{ + GObjectClass *object_class = (GObjectClass *) activity_handler_class; + + object_class->dispose = impl_dispose; + object_class->finalize = impl_finalize; +} + +static void +e_activity_handler_init (EActivityHandler *activity_handler) +{ + EActivityHandlerPrivate *priv; + + priv = g_new (EActivityHandlerPrivate, 1); + priv->next_activity_id = 1; + priv->activity_infos = NULL; + priv->task_bars = NULL; + priv->logger = NULL; + priv->error_timer = 0; + priv->error_flush_interval = 0; + activity_handler->priv = priv; +} + + +EActivityHandler * +e_activity_handler_new (void) +{ + return g_object_new (e_activity_handler_get_type (), NULL); +} + +void +e_activity_handler_set_error_flush_time (EActivityHandler *handler, int time) +{ + handler->priv->error_flush_interval = time; +} +void +e_activity_handler_set_logger (EActivityHandler *handler, ELogger *logger) +{ + handler->priv->logger = logger; +} + +void +e_activity_handler_set_message (EActivityHandler *activity_handler, + const char *message) +{ + EActivityHandlerPrivate *priv; + GSList *i; + + priv = activity_handler->priv; + + for (i = priv->task_bars; i; i = i->next) + e_shell_taskbar_set_message (E_SHELL_TASKBAR (i->data), message); +} + +void +e_activity_handler_unset_message (EActivityHandler *activity_handler) +{ + EActivityHandlerPrivate *priv; + GSList *i; + + priv = activity_handler->priv; + + for (i = priv->task_bars; i; i = i->next) + e_shell_taskbar_unset_message (E_SHELL_TASKBAR (i->data)); +} + +void +e_activity_handler_attach_task_bar (EActivityHandler *activity_handler, + EShellTaskbar *shell_taskbar) +{ + EActivityHandlerPrivate *priv; + + g_return_if_fail (activity_handler != NULL); + g_return_if_fail (E_IS_ACTIVITY_HANDLER (activity_handler)); + g_return_if_fail (shell_taskbar != NULL); + g_return_if_fail (E_IS_SHELL_TASKBAR (shell_taskbar)); + + priv = activity_handler->priv; + + g_object_weak_ref (G_OBJECT (shell_taskbar), task_bar_destroy_notify, activity_handler); + + priv->task_bars = g_slist_prepend (priv->task_bars, shell_taskbar); + + setup_task_bar (activity_handler, shell_taskbar); +} + +struct _cancel_wdata { + EActivityHandler *handler; + ActivityInfo *info; + guint id; + void (*cancel)(gpointer); + gpointer data; +}; + +static void +cancel_wrapper (gpointer pdata) +{ + struct _cancel_wdata *data = (struct _cancel_wdata *) pdata; + /* This can be invoked in two scenario. Either to cancel or to hide error */ + if (data->info->error) { + /* Hide the error */ + EActivityHandler *handler = data->handler; + ActivityInfo *info; + int order, len; + GSList *sp; + GList *p = lookup_activity (handler->priv->activity_infos, data->id, &order); + e_logger_log (handler->priv->logger, E_LOG_ERROR, g_object_get_data (data->info->error, "primary"), + g_object_get_data (data->info->error, "secondary")); + gtk_widget_destroy (data->info->error); + data->info->error = NULL; + info = data->info; + for (sp = handler->priv->task_bars; sp != NULL; sp = sp->next) { + EShellTaskbar *shell_taskbar; + + shell_taskbar = E_SHELL_TASKBAR (sp->data); + e_shell_taskbar_remove_task_from_id (shell_taskbar, info->id); + } + activity_info_free (info); + len = g_list_length (handler->priv->activity_infos); + handler->priv->activity_infos = g_list_remove_link (handler->priv->activity_infos, p); + if (len == 1) + handler->priv->activity_infos = NULL; + } else { + /* Cancel the operation */ + data->cancel (data->data); + } + /* No need to free the data. It will be freed as part of the task widget destroy */ +} + +/* CORBA methods. */ +guint e_activity_handler_cancelable_operation_started (EActivityHandler *activity_handler, + const char *information, + gboolean cancellable, + void (*cancel_func)(gpointer), + gpointer user_data) +{ + EActivityHandlerPrivate *priv; + ActivityInfo *activity_info; + unsigned int activity_id; + GSList *p; + struct _cancel_wdata *data; + gboolean bfree = FALSE; + priv = activity_handler->priv; + + activity_id = get_new_activity_id (activity_handler); + activity_info = activity_info_new (activity_id, information, cancellable); + + data = g_new(struct _cancel_wdata, 1); + data->handler = activity_handler; + data->id = activity_id; + data->info = activity_info; + data->cancel = cancel_func; + data->data = user_data; + + activity_info->cancel_func = cancel_wrapper; + activity_info->data = data; + for (p = priv->task_bars; p != NULL; p = p->next) { + ETaskWidget *tw = task_widget_new_from_activity_info (activity_info); + tw->id = activity_id; + if (!bfree) { + /* The data will be freed part of the widget destroy */ + g_object_set_data_full ((GObject *) tw, "free-data", data, g_free); + bfree = TRUE; + } + e_shell_taskbar_prepend_task (E_SHELL_TASKBAR (p->data), tw); + } + + priv->activity_infos = g_list_prepend (priv->activity_infos, activity_info); + + return activity_id; + +} + +guint +e_activity_handler_operation_started (EActivityHandler *activity_handler, + const char *information, + gboolean cancellable) +{ + EActivityHandlerPrivate *priv; + ActivityInfo *activity_info; + unsigned int activity_id; + GSList *p; + + priv = activity_handler->priv; + + activity_id = get_new_activity_id (activity_handler); + + activity_info = activity_info_new (activity_id, information, cancellable); + + for (p = priv->task_bars; p != NULL; p = p->next) { + ETaskWidget *tw = task_widget_new_from_activity_info (activity_info); + tw->id = activity_id; + e_shell_taskbar_prepend_task (E_SHELL_TASKBAR (p->data), tw); + } + + priv->activity_infos = g_list_prepend (priv->activity_infos, activity_info); + + return activity_id; +} + +static void +handle_error (ETaskWidget *task) +{ + GtkWidget *tool, *error; + EActivityHandler *activity_handler; + guint id; + int error_type = GPOINTER_TO_INT((g_object_get_data ((GObject *) task, "error-type"))); + tool = g_object_get_data ((GObject *) task, "tool"); + error = g_object_get_data ((GObject *) task, "error"); + activity_handler = g_object_get_data ((GObject *) task, "activity-handler"); + id = GPOINTER_TO_UINT (g_object_get_data ((GObject *) task, "activity")); + e_activity_handler_operation_finished (activity_handler, id); + gtk_widget_show (error); + e_logger_log (activity_handler->priv->logger, error_type, + g_object_get_data ((GObject *) error, "primary"), + g_object_get_data ((GObject *) error, "secondary")); +} + +static gboolean +error_cleanup (EActivityHandler *activity_handler) +{ + EActivityHandlerPrivate *priv = activity_handler->priv; + GList *p, *node; + GSList *sp; + int i; + time_t now = time (NULL); + gboolean berror = FALSE; + + for (p = priv->activity_infos, i = 0; p != NULL; i++) { + ActivityInfo *info; + + info = (ActivityInfo *) p->data; + if (info->error) + berror = TRUE; + if (info->error && info->error_time && (now - info->error_time) > 5 ) { + /* Error older than wanted time. So cleanup */ + e_logger_log (priv->logger, info->error_type, g_object_get_data (info->error, "primary"), + g_object_get_data (info->error, "secondary")); + gtk_widget_destroy (info->error); + node = p; + p = p->next; + + for (sp = priv->task_bars; sp != NULL; sp = sp->next) { + EShellTaskbar *task_bar; + + task_bar = E_SHELL_TASKBAR (sp->data); + e_shell_taskbar_remove_task_from_id (task_bar, info->id); + } + activity_info_free (info); + priv->activity_infos = g_list_remove_link (priv->activity_infos, node); + + } else + p = p->next; + } + if (!berror) + priv->error_timer = 0; + return berror; +} + +guint +e_activity_handler_make_error (EActivityHandler *activity_handler, + int error_type, + GtkWidget *error) +{ + EActivityHandlerPrivate *priv; + ActivityInfo *activity_info; + unsigned int activity_id; + GSList *p; + char *information = g_object_get_data((GObject *) error, "primary"); + const char *img; + + priv = activity_handler->priv; + activity_id = get_new_activity_id (activity_handler); + + activity_info = activity_info_new (activity_id, information, TRUE); + activity_info->error = error; + activity_info->error_time = time (NULL); + activity_info->error_type = error_type; + + img = error_type ? icon_data[1] : icon_data[0]; + for (p = priv->task_bars; p != NULL; p = p->next) { + EShellTaskbar *task_bar; + ETaskWidget *task_widget; + GtkWidget *tool; + + task_bar = E_SHELL_TASKBAR (p->data); + task_widget = task_widget_new_from_activity_info (activity_info); + task_widget->id = activity_id; + e_shell_taskbar_prepend_task (E_SHELL_TASKBAR (p->data), task_widget); + + tool = e_task_widget_update_image (task_widget, (char *)img, information); + g_object_set_data ((GObject *) task_widget, "tool", tool); + g_object_set_data ((GObject *) task_widget, "error", error); + g_object_set_data ((GObject *) task_widget, "activity-handler", activity_handler); + g_object_set_data ((GObject *) task_widget, "activity", GINT_TO_POINTER(activity_id)); + g_object_set_data ((GObject *) task_widget, "error-type", GINT_TO_POINTER(error_type)); + g_signal_connect_swapped (tool, "clicked", G_CALLBACK(handle_error), task_widget); + } + + priv->activity_infos = g_list_prepend (priv->activity_infos, activity_info); + + if (!activity_handler->priv->error_timer) + activity_handler->priv->error_timer = g_timeout_add (activity_handler->priv->error_flush_interval, (GSourceFunc)error_cleanup, activity_handler); + + return activity_id; +} + +void +e_activity_handler_operation_set_error(EActivityHandler *activity_handler, + guint activity_id, + GtkWidget *error) +{ + EActivityHandlerPrivate *priv = activity_handler->priv; + ActivityInfo *activity_info; + GList *p; + GSList *sp; + int order_number; + + p = lookup_activity (priv->activity_infos, activity_id, &order_number); + if (p == NULL) { + g_warning ("EActivityHandler: unknown operation %d", activity_id); + return; + } + + activity_info = (ActivityInfo *) p->data; + activity_info->error = error; + activity_info->error_time = time (NULL); + activity_info->error_type = E_LOG_ERROR; + g_free (activity_info->information); + activity_info->information = g_strdup (g_object_get_data ((GObject *) error, "primary")); + for (sp = priv->task_bars; sp != NULL; sp = sp->next) { + EShellTaskbar *task_bar; + ETaskWidget *task_widget; + GtkWidget *tool; + + task_bar = E_SHELL_TASKBAR (sp->data); + task_widget = e_shell_taskbar_get_task_widget_from_id (task_bar, activity_info->id); + if (!task_widget) + continue; + + tool = e_task_widget_update_image (task_widget, (char *)icon_data[0], g_object_get_data ((GObject *) error, "primary")); + g_object_set_data ((GObject *) task_widget, "tool", tool); + g_object_set_data ((GObject *) task_widget, "error", error); + g_object_set_data ((GObject *) task_widget, "activity-handler", activity_handler); + g_object_set_data ((GObject *) task_widget, "activity", GINT_TO_POINTER(activity_id)); + g_object_set_data ((GObject *) task_widget, "error-type", GINT_TO_POINTER(E_LOG_ERROR)); + g_signal_connect_swapped (tool, "clicked", G_CALLBACK(handle_error), task_widget); + } + + if (!activity_handler->priv->error_timer) + activity_handler->priv->error_timer = g_timeout_add (activity_handler->priv->error_flush_interval, (GSourceFunc) error_cleanup, activity_handler); +} + +void +e_activity_handler_operation_progressing (EActivityHandler *activity_handler, + guint activity_id, + const char *information, + double progress) +{ + EActivityHandlerPrivate *priv = activity_handler->priv; + ActivityInfo *activity_info; + GList *p; + GSList *sp; + int order_number; + + p = lookup_activity (priv->activity_infos, activity_id, &order_number); + if (p == NULL) { + g_warning ("EActivityHandler: unknown operation %d", activity_id); + return; + } + + activity_info = (ActivityInfo *) p->data; + + g_free (activity_info->information); + activity_info->information = g_strdup (information); + + activity_info->progress = progress; + + for (sp = priv->task_bars; sp != NULL; sp = sp->next) { + EShellTaskbar *task_bar; + ETaskWidget *task_widget; + + task_bar = E_SHELL_TASKBAR (sp->data); + task_widget = e_shell_taskbar_get_task_widget_from_id (task_bar, activity_info->id); + if (!task_widget) + continue; + + e_task_widget_update (task_widget, information, progress); + } +} + +void +e_activity_handler_operation_finished (EActivityHandler *activity_handler, + guint activity_id) +{ + EActivityHandlerPrivate *priv = activity_handler->priv; + GList *p; + GSList *sp; + int order_number; + + p = lookup_activity (priv->activity_infos, activity_id, &order_number); + if (p == NULL) { + g_warning ("e_activity_handler_operation_finished: Unknown activity %d\n", activity_id); + return; + } + + activity_info_free ((ActivityInfo *) p->data); + priv->activity_infos = g_list_remove_link (priv->activity_infos, p); + + for (sp = priv->task_bars; sp != NULL; sp = sp->next) { + EShellTaskbar *task_bar; + + task_bar = E_SHELL_TASKBAR (sp->data); + e_shell_taskbar_remove_task_from_id (task_bar, activity_id); + } +} + diff --git a/shell/e-activity-handler.h b/shell/e-activity-handler.h new file mode 100644 index 0000000000..ae0fd7decb --- /dev/null +++ b/shell/e-activity-handler.h @@ -0,0 +1,107 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-activity-handler.h + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * Author: Ettore Perazzoli <ettore@ximian.com> + */ + +#ifndef _E_ACTIVITY_HANDLER_H_ +#define _E_ACTIVITY_HANDLER_H_ + +#include "e-shell-taskbar.h" +#include "e-util/e-logger.h" +#include <glib-object.h> + +/* XXX Merge this into EShellTaskbar and rethink the API. */ + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define E_TYPE_ACTIVITY_HANDLER (e_activity_handler_get_type ()) +#define E_ACTIVITY_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_ACTIVITY_HANDLER, EActivityHandler)) +#define E_ACTIVITY_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_ACTIVITY_HANDLER, EActivityHandlerClass)) +#define E_IS_ACTIVITY_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_ACTIVITY_HANDLER)) +#define E_IS_ACTIVITY_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_ACTIVITY_HANDLER)) + + +typedef struct _EActivityHandler EActivityHandler; +typedef struct _EActivityHandlerPrivate EActivityHandlerPrivate; +typedef struct _EActivityHandlerClass EActivityHandlerClass; + +#define EAH_ICON_INFO "stock_dialog-info" +#define EAH_ICON_ERROR "stock_dialog-warning" + +struct _EActivityHandler { + GObject parent; + + EActivityHandlerPrivate *priv; +}; + +struct _EActivityHandlerClass { + GObjectClass parent_class; +}; + + +GType e_activity_handler_get_type (void); + +EActivityHandler *e_activity_handler_new (void); + +void e_activity_handler_attach_task_bar (EActivityHandler *activity_hanlder, + EShellTaskbar *shell_taskbar); + +void e_activity_handler_set_message (EActivityHandler *activity_handler, + const char *message); + +void e_activity_handler_unset_message (EActivityHandler *activity_handler); + +guint e_activity_handler_operation_started (EActivityHandler *activity_handler, + const char *information, + gboolean cancellable); +guint e_activity_handler_cancelable_operation_started (EActivityHandler *activity_handler, + const char *information, + gboolean cancellable, + void (*cancel_func)(gpointer), + gpointer user_data); + +void e_activity_handler_operation_progressing (EActivityHandler *activity_handler, + guint activity_id, + const char *information, + double progress); + +void e_activity_handler_operation_finished (EActivityHandler *activity_handler, + guint activity_id); + +void e_activity_handler_set_logger (EActivityHandler *handler, ELogger *logger); +guint e_activity_handler_make_error (EActivityHandler *activity_handler, + int error_type, + GtkWidget *error); +void +e_activity_handler_operation_set_error (EActivityHandler *activity_handler, + guint activity_id, + GtkWidget *error); + +void +e_activity_handler_set_error_flush_time (EActivityHandler *handler, int time); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _E_ACTIVITY_HANDLER_H_ */ diff --git a/shell/e-shell-content.c b/shell/e-shell-content.c index 6671e5505e..7ee7711b7e 100644 --- a/shell/e-shell-content.c +++ b/shell/e-shell-content.c @@ -20,35 +20,442 @@ #include "e-shell-content.h" -#include <e-search-bar.h> +#include <glib/gi18n.h> + +#include <widgets/misc/e-action-combo-box.h> +#include <widgets/misc/e-icon-entry.h> + +#include <e-shell-module.h> +#include <e-shell-view.h> +#include <e-shell-window-actions.h> #define E_SHELL_CONTENT_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE \ ((obj), E_TYPE_SHELL_CONTENT, EShellContentPrivate)) struct _EShellContentPrivate { + + gpointer shell_view; /* weak pointer */ + + RuleContext *search_context; + FilterRule *current_query; + + /* Container for the following widgets */ GtkWidget *search_bar; + + /* Search bar widgets */ + GtkWidget *filter_label; + GtkWidget *filter_combo_box; + GtkWidget *search_label; + GtkWidget *search_entry; + GtkWidget *scope_label; + GtkWidget *scope_combo_box; + + GtkStateType search_state; + + GtkRadioAction *search_action; + GtkWidget *search_popup_menu; +}; + +enum { + PROP_0, + PROP_FILTER_ACTION, + PROP_FILTER_VALUE, + PROP_FILTER_VISIBLE, + PROP_SEARCH_ACTION, + PROP_SEARCH_CONTEXT, + PROP_SEARCH_TEXT, + PROP_SEARCH_VALUE, + PROP_SEARCH_VISIBLE, + PROP_SCOPE_ACTION, + PROP_SCOPE_VALUE, + PROP_SCOPE_VISIBLE, + PROP_SHELL_VIEW }; static gpointer parent_class; static void +shell_content_entry_activated_cb (EShellContent *shell_content, + GtkWidget *entry) +{ + EShellWindow *shell_window; + EShellView *shell_view; + GtkAction *action; + + shell_view = e_shell_content_get_shell_view (shell_content); + shell_window = e_shell_view_get_shell_window (shell_view); + + /* Verify the shell view is selected before proceeding. */ + if (!e_shell_view_is_selected (shell_view)) + return; + + action = E_SHELL_WINDOW_ACTION_SEARCH_EXECUTE (shell_window); + gtk_action_activate (action); +} + +static void +shell_content_entry_changed_cb (EShellContent *shell_content, + GtkWidget *entry) +{ + EShellWindow *shell_window; + EShellView *shell_view; + GtkStateType state; + GtkAction *action; + gboolean sensitive; + const gchar *text; + + text = gtk_entry_get_text (GTK_ENTRY (entry)); + state = shell_content->priv->search_state; + + if (text != NULL && *text != '\0') + sensitive = (state != GTK_STATE_INSENSITIVE); + else + sensitive = (state == GTK_STATE_SELECTED); + + shell_view = e_shell_content_get_shell_view (shell_content); + shell_window = e_shell_view_get_shell_window (shell_view); + + /* Verify the shell view is selected before proceeding. */ + if (!e_shell_view_is_selected (shell_view)) + return; + + action = E_SHELL_WINDOW_ACTION_SEARCH_CLEAR (shell_window); + gtk_action_set_sensitive (action, sensitive); +} + +static gboolean +shell_content_entry_focus_in_cb (EShellContent *shell_content, + GdkEventFocus *focus_event, + GtkWidget *entry) +{ + if (shell_content->priv->search_state == GTK_STATE_INSENSITIVE) { + gtk_entry_set_text (GTK_ENTRY (entry), ""); + gtk_widget_modify_text (entry, GTK_STATE_NORMAL, NULL); + shell_content->priv->search_state = GTK_STATE_NORMAL; + } + + return FALSE; +} + +static gboolean +shell_content_entry_focus_out_cb (EShellContent *shell_content, + GdkEventFocus *focus_event, + GtkWidget *entry) +{ + /* FIXME */ + return FALSE; +} + +static gboolean +shell_content_entry_key_press_cb (EShellContent *shell_content, + GdkEventKey *key_event, + GtkWidget *entry) +{ + /* FIXME */ + return FALSE; +} + +static void +shell_content_init_search_context (EShellContent *shell_content) +{ + EShellView *shell_view; + EShellModule *shell_module; + EShellViewClass *shell_view_class; + RuleContext *context; + FilterRule *rule; + FilterPart *part; + gchar *system_filename; + gchar *user_filename; + + shell_view = e_shell_content_get_shell_view (shell_content); + shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); + shell_module = E_SHELL_MODULE (shell_view_class->type_module); + + /* The filename for built-in searches is specified in a + * module's EShellModuleInfo. All built-in search rules + * live in the same directory. */ + system_filename = g_build_filename ( + EVOLUTION_RULEDIR, + e_shell_module_get_searches (shell_module), NULL); + + /* The filename for custom saved searches is always of + * the form "$(shell_module_data_dir)/searches.xml". */ + user_filename = g_build_filename ( + e_shell_module_get_data_dir (shell_module), + "searches.xml", NULL); + + context = rule_context_new (); + rule_context_add_part_set ( + context, "partset", FILTER_TYPE_PART, + rule_context_add_part, rule_context_next_part); + rule_context_add_rule_set ( + context, "ruleset", FILTER_TYPE_RULE, + rule_context_add_rule, rule_context_next_rule); + rule_context_load (context, system_filename, user_filename); + + /* XXX Not sure why this is necessary. */ + g_object_set_data_full ( + G_OBJECT (context), "system", system_filename, g_free); + g_object_set_data_full ( + G_OBJECT (context), "user", user_filename, g_free); + + /* XXX I don't really understand what this does. */ + rule = filter_rule_new (); + part = rule_context_next_part (context, NULL); + if (part == NULL) + g_warning ( + "Could not load %s search: no parts", + shell_view_class->type_module->name); + else + filter_rule_add_part (rule, filter_part_clone (part)); + + g_free (system_filename); + g_free (user_filename); + + shell_content->priv->search_context = context; +} + +static void +shell_content_set_shell_view (EShellContent *shell_content, + EShellView *shell_view) +{ + g_return_if_fail (shell_content->priv->shell_view == NULL); + + shell_content->priv->shell_view = shell_view; + + g_object_add_weak_pointer ( + G_OBJECT (shell_view), + &shell_content->priv->shell_view); +} + +static void +shell_content_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_FILTER_ACTION: + e_shell_content_set_filter_action ( + E_SHELL_CONTENT (object), + g_value_get_object (value)); + return; + + case PROP_FILTER_VALUE: + e_shell_content_set_filter_value ( + E_SHELL_CONTENT (object), + g_value_get_int (value)); + return; + + case PROP_FILTER_VISIBLE: + e_shell_content_set_filter_visible ( + E_SHELL_CONTENT (object), + g_value_get_boolean (value)); + return; + + case PROP_SEARCH_ACTION: + e_shell_content_set_search_action ( + E_SHELL_CONTENT (object), + g_value_get_object (value)); + return; + + case PROP_SEARCH_TEXT: + e_shell_content_set_search_text ( + E_SHELL_CONTENT (object), + g_value_get_string (value)); + return; + + case PROP_SEARCH_VALUE: + e_shell_content_set_search_value ( + E_SHELL_CONTENT (object), + g_value_get_int (value)); + return; + + case PROP_SEARCH_VISIBLE: + e_shell_content_set_search_visible ( + E_SHELL_CONTENT (object), + g_value_get_boolean (value)); + return; + + case PROP_SCOPE_ACTION: + e_shell_content_set_scope_action ( + E_SHELL_CONTENT (object), + g_value_get_object (value)); + return; + + case PROP_SCOPE_VALUE: + e_shell_content_set_scope_value ( + E_SHELL_CONTENT (object), + g_value_get_int (value)); + return; + + case PROP_SCOPE_VISIBLE: + e_shell_content_set_scope_visible ( + E_SHELL_CONTENT (object), + g_value_get_boolean (value)); + return; + + case PROP_SHELL_VIEW: + shell_content_set_shell_view ( + E_SHELL_CONTENT (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +shell_content_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_FILTER_ACTION: + g_value_set_object ( + value, e_shell_content_get_filter_action ( + E_SHELL_CONTENT (object))); + return; + + case PROP_FILTER_VALUE: + g_value_set_int ( + value, e_shell_content_get_filter_value ( + E_SHELL_CONTENT (object))); + return; + + case PROP_FILTER_VISIBLE: + g_value_set_boolean ( + value, e_shell_content_get_filter_visible ( + E_SHELL_CONTENT (object))); + return; + + case PROP_SEARCH_ACTION: + g_value_set_object ( + value, e_shell_content_get_search_action ( + E_SHELL_CONTENT (object))); + return; + + case PROP_SEARCH_CONTEXT: + g_value_set_object ( + value, e_shell_content_get_search_context ( + E_SHELL_CONTENT (object))); + return; + + case PROP_SEARCH_TEXT: + g_value_set_string ( + value, e_shell_content_get_search_text ( + E_SHELL_CONTENT (object))); + return; + + case PROP_SEARCH_VALUE: + g_value_set_int ( + value, e_shell_content_get_search_value ( + E_SHELL_CONTENT (object))); + return; + + case PROP_SEARCH_VISIBLE: + g_value_set_boolean ( + value, e_shell_content_get_search_visible ( + E_SHELL_CONTENT (object))); + return; + + case PROP_SCOPE_ACTION: + g_value_set_object ( + value, e_shell_content_get_scope_action ( + E_SHELL_CONTENT (object))); + return; + + case PROP_SCOPE_VALUE: + g_value_set_int ( + value, e_shell_content_get_scope_value ( + E_SHELL_CONTENT (object))); + return; + + case PROP_SCOPE_VISIBLE: + g_value_set_boolean ( + value, e_shell_content_get_scope_visible ( + E_SHELL_CONTENT (object))); + return; + + case PROP_SHELL_VIEW: + g_value_set_object ( + value, e_shell_content_get_shell_view ( + E_SHELL_CONTENT (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void shell_content_dispose (GObject *object) { EShellContentPrivate *priv; priv = E_SHELL_CONTENT_GET_PRIVATE (object); - if (priv->search_bar != NULL) { - g_object_unref (priv->search_bar); - priv->search_bar = NULL; + if (priv->shell_view != NULL) { + g_object_remove_weak_pointer ( + G_OBJECT (priv->shell_view), &priv->shell_view); + priv->shell_view = NULL; + } + + if (priv->filter_label != NULL) { + g_object_unref (priv->filter_label); + priv->filter_label = NULL; + } + + if (priv->filter_combo_box != NULL) { + g_object_unref (priv->filter_combo_box); + priv->filter_combo_box = NULL; + } + + if (priv->search_context != NULL) { + g_object_unref (priv->search_context); + priv->search_context = NULL; } + if (priv->search_label != NULL) { + g_object_unref (priv->search_label); + priv->search_label = NULL; + } + + if (priv->search_entry != NULL) { + g_object_unref (priv->search_entry); + priv->search_entry = NULL; + } + + if (priv->scope_label != NULL) { + g_object_unref (priv->scope_label); + priv->scope_label = NULL; + } + + if (priv->scope_combo_box != NULL) { + g_object_unref (priv->scope_combo_box); + priv->scope_combo_box = NULL; + } + + if (priv->search_action != NULL) { + g_object_unref (priv->search_action); + priv->search_action = NULL; + } + /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (parent_class)->dispose (object); } static void +shell_content_constructed (GObject *object) +{ + EShellContent *shell_content; + + shell_content = E_SHELL_CONTENT (object); + shell_content_init_search_context (shell_content); +} + +static void shell_content_size_request (GtkWidget *widget, GtkRequisition *requisition) { @@ -72,7 +479,7 @@ shell_content_size_request (GtkWidget *widget, static void shell_content_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) + GtkAllocation *allocation) { EShellContentPrivate *priv; GtkAllocation child_allocation; @@ -104,7 +511,7 @@ shell_content_size_allocate (GtkWidget *widget, static void shell_content_remove (GtkContainer *container, - GtkWidget *widget) + GtkWidget *widget) { EShellContentPrivate *priv; @@ -124,9 +531,9 @@ shell_content_remove (GtkContainer *container, static void shell_content_forall (GtkContainer *container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data) + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) { EShellContentPrivate *priv; @@ -151,7 +558,10 @@ shell_content_class_init (EShellContentClass *class) g_type_class_add_private (class, sizeof (EShellContentPrivate)); object_class = G_OBJECT_CLASS (class); + object_class->set_property = shell_content_set_property; + object_class->get_property = shell_content_get_property; object_class->dispose = shell_content_dispose; + object_class->constructed = shell_content_constructed; widget_class = GTK_WIDGET_CLASS (class); widget_class->size_request = shell_content_size_request; @@ -160,21 +570,232 @@ shell_content_class_init (EShellContentClass *class) container_class = GTK_CONTAINER_CLASS (class); container_class->remove = shell_content_remove; container_class->forall = shell_content_forall; + + g_object_class_install_property ( + object_class, + PROP_FILTER_ACTION, + g_param_spec_object ( + "filter-action", + NULL, + NULL, + GTK_TYPE_RADIO_ACTION, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_FILTER_VALUE, + g_param_spec_int ( + "filter-value", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_FILTER_VISIBLE, + g_param_spec_boolean ( + "filter-visible", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_SEARCH_ACTION, + g_param_spec_object ( + "search-action", + NULL, + NULL, + GTK_TYPE_RADIO_ACTION, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SEARCH_CONTEXT, + g_param_spec_object ( + "search-context", + NULL, + NULL, + RULE_TYPE_CONTEXT, + G_PARAM_READABLE)); + + g_object_class_install_property ( + object_class, + PROP_SEARCH_TEXT, + g_param_spec_string ( + "search-text", + NULL, + NULL, + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SEARCH_VALUE, + g_param_spec_int ( + "search-value", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SEARCH_VISIBLE, + g_param_spec_boolean ( + "search-visible", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_SCOPE_ACTION, + g_param_spec_object ( + "scope-action", + NULL, + NULL, + GTK_TYPE_RADIO_ACTION, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SCOPE_VALUE, + g_param_spec_int ( + "scope-value", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SCOPE_VISIBLE, + g_param_spec_boolean ( + "scope-visible", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_SHELL_VIEW, + g_param_spec_object ( + "shell-view", + NULL, + NULL, + E_TYPE_SHELL_VIEW, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); } static void shell_content_init (EShellContent *shell_content) { + GtkBox *box; + GtkLabel *label; + GtkWidget *mnemonic; GtkWidget *widget; + EIconEntry *icon_entry; shell_content->priv = E_SHELL_CONTENT_GET_PRIVATE (shell_content); GTK_WIDGET_SET_FLAGS (shell_content, GTK_NO_WINDOW); - widget = e_search_bar_new (); + /*** Build the Search Bar ***/ + + widget = gtk_hbox_new (FALSE, 3); gtk_widget_set_parent (widget, GTK_WIDGET (shell_content)); - shell_content->priv->search_bar = g_object_ref (widget); + shell_content->priv->search_bar = g_object_ref_sink (widget); + gtk_widget_show (widget); + + box = GTK_BOX (widget); + + /* Filter Combo Widgets */ + + /* Translators: The "Show:" label precedes a combo box that + * allows the user to filter the current view. Examples of + * items that appear in the combo box are "Unread Messages", + * "Important Messages", or "Active Appointments". */ + widget = gtk_label_new_with_mnemonic (_("Sho_w:")); + gtk_box_pack_start (box, widget, FALSE, FALSE, 0); + shell_content->priv->filter_label = g_object_ref (widget); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = e_action_combo_box_new (); + gtk_label_set_mnemonic_widget (label, widget); + gtk_box_pack_start (box, widget, FALSE, FALSE, 0); + shell_content->priv->filter_combo_box = g_object_ref (widget); gtk_widget_show (widget); + + /* Scope Combo Widgets */ + + widget = e_action_combo_box_new (); + gtk_box_pack_end (box, widget, FALSE, FALSE, 0); + shell_content->priv->scope_combo_box = g_object_ref (widget); + gtk_widget_show (widget); + + mnemonic = widget; + + /* Translators: This is part of the quick search interface. + * example: Search: [_______________] in [ Current Folder ] */ + widget = gtk_label_new_with_mnemonic (_("i_n")); + gtk_label_set_mnemonic_widget (GTK_LABEL (widget), mnemonic); + gtk_box_pack_end (box, widget, FALSE, FALSE, 0); + shell_content->priv->scope_label = g_object_ref (widget); + gtk_widget_show (widget); + + /* Search Entry Widgets */ + + widget = e_icon_entry_new (); + gtk_box_pack_end (box, widget, FALSE, FALSE, 0); + shell_content->priv->search_entry = g_object_ref (widget); + shell_content->priv->search_state = GTK_STATE_NORMAL; + gtk_widget_show (widget); + + icon_entry = E_ICON_ENTRY (widget); + + /* Translators: This is part of the quick search interface. + * example: Search: [_______________] in [ Current Folder ] */ + widget = gtk_label_new_with_mnemonic (_("Sear_ch:")); + gtk_box_pack_end (box, widget, FALSE, FALSE, 0); + shell_content->priv->search_label = g_object_ref (widget); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = e_icon_entry_get_entry (icon_entry); + gtk_label_set_mnemonic_widget (label, widget); + g_signal_connect_swapped ( + widget, "activate", + G_CALLBACK (shell_content_entry_activated_cb), shell_content); + g_signal_connect_swapped ( + widget, "changed", + G_CALLBACK (shell_content_entry_changed_cb), shell_content); + g_signal_connect_swapped ( + widget, "focus-in-event", + G_CALLBACK (shell_content_entry_focus_in_cb), shell_content); + g_signal_connect_swapped ( + widget, "focus-out-event", + G_CALLBACK (shell_content_entry_focus_out_cb), shell_content); + g_signal_connect_swapped ( + widget, "key-press-event", + G_CALLBACK (shell_content_entry_key_press_cb), shell_content); } GType @@ -204,15 +825,278 @@ e_shell_content_get_type (void) } GtkWidget * -e_shell_content_new (void) +e_shell_content_new (EShellView *shell_view) { - return g_object_new (E_TYPE_SHELL_CONTENT, NULL); + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_SHELL_CONTENT, "shell-view", shell_view, NULL); } -GtkWidget * -e_shell_content_get_search_bar (EShellContent *shell_content) +EShellView * +e_shell_content_get_shell_view (EShellContent *shell_content) +{ + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL); + + return E_SHELL_VIEW (shell_content->priv->shell_view); +} + +GtkRadioAction * +e_shell_content_get_filter_action (EShellContent *shell_content) +{ + EActionComboBox *combo_box; + + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL); + + combo_box = E_ACTION_COMBO_BOX (shell_content->priv->filter_combo_box); + + return e_action_combo_box_get_action (combo_box); +} + +void +e_shell_content_set_filter_action (EShellContent *shell_content, + GtkRadioAction *filter_action) +{ + EActionComboBox *combo_box; + + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + combo_box = E_ACTION_COMBO_BOX (shell_content->priv->filter_combo_box); + + e_action_combo_box_set_action (combo_box, filter_action); + g_object_notify (G_OBJECT (shell_content), "filter-action"); +} + +gint +e_shell_content_get_filter_value (EShellContent *shell_content) +{ + EActionComboBox *combo_box; + + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), 0); + + combo_box = E_ACTION_COMBO_BOX (shell_content->priv->filter_combo_box); + + return e_action_combo_box_get_current_value (combo_box); +} + +void +e_shell_content_set_filter_value (EShellContent *shell_content, + gint filter_value) +{ + EActionComboBox *combo_box; + + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + combo_box = E_ACTION_COMBO_BOX (shell_content->priv->filter_combo_box); + + e_action_combo_box_set_current_value (combo_box, filter_value); + g_object_notify (G_OBJECT (shell_content), "filter-value"); +} + +gboolean +e_shell_content_get_filter_visible (EShellContent *shell_content) +{ + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), FALSE); + + return GTK_WIDGET_VISIBLE (shell_content->priv->filter_combo_box); +} + +void +e_shell_content_set_filter_visible (EShellContent *shell_content, + gboolean filter_visible) +{ + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + if (filter_visible) { + gtk_widget_show (shell_content->priv->filter_label); + gtk_widget_show (shell_content->priv->filter_combo_box); + } else { + gtk_widget_hide (shell_content->priv->filter_label); + gtk_widget_hide (shell_content->priv->filter_combo_box); + } +} + +GtkRadioAction * +e_shell_content_get_search_action (EShellContent *shell_content) +{ + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL); + + return shell_content->priv->search_action; +} + +void +e_shell_content_set_search_action (EShellContent *shell_content, + GtkRadioAction *search_action) +{ + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + if (search_action != NULL) { + g_return_if_fail (GTK_IS_RADIO_ACTION (search_action)); + g_object_ref (search_action); + } + + shell_content->priv->search_action = search_action; + g_object_notify (G_OBJECT (shell_content), "search-action"); +} + +RuleContext * +e_shell_content_get_search_context (EShellContent *shell_content) +{ + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL); + + return shell_content->priv->search_context; +} + +const gchar * +e_shell_content_get_search_text (EShellContent *shell_content) +{ + EIconEntry *icon_entry; + GtkWidget *text_entry; + + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL); + + if (shell_content->priv->search_state == GTK_STATE_INSENSITIVE) + return ""; + + icon_entry = E_ICON_ENTRY (shell_content->priv->search_entry); + text_entry = e_icon_entry_get_entry (icon_entry); + + return gtk_entry_get_text (GTK_ENTRY (text_entry)); +} + +void +e_shell_content_set_search_text (EShellContent *shell_content, + const gchar *search_text) +{ + EIconEntry *icon_entry; + GtkWidget *text_entry; + + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + icon_entry = E_ICON_ENTRY (shell_content->priv->search_entry); + text_entry = e_icon_entry_get_entry (icon_entry); + + search_text = (search_text != NULL) ? search_text : ""; + gtk_entry_set_text (GTK_ENTRY (text_entry), search_text); + g_object_notify (G_OBJECT (shell_content), "search-text"); +} + +gint +e_shell_content_get_search_value (EShellContent *shell_content) +{ + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), 0); + + /* FIXME */ + return 0; +} + +void +e_shell_content_set_search_value (EShellContent *shell_content, + gint search_value) +{ + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + /* FIXME */ + + g_object_notify (G_OBJECT (shell_content), "search-value"); +} + +gboolean +e_shell_content_get_search_visible (EShellContent *shell_content) +{ + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), FALSE); + + return GTK_WIDGET_VISIBLE (shell_content->priv->search_entry); +} + +void +e_shell_content_set_search_visible (EShellContent *shell_content, + gboolean search_visible) +{ + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + if (search_visible) { + gtk_widget_show (shell_content->priv->search_label); + gtk_widget_show (shell_content->priv->search_entry); + } else { + gtk_widget_hide (shell_content->priv->search_label); + gtk_widget_hide (shell_content->priv->search_entry); + } +} + +GtkRadioAction * +e_shell_content_get_scope_action (EShellContent *shell_content) { + EActionComboBox *combo_box; + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL); - return shell_content->priv->search_bar; + combo_box = E_ACTION_COMBO_BOX (shell_content->priv->scope_combo_box); + + return e_action_combo_box_get_action (combo_box); +} + +void +e_shell_content_set_scope_action (EShellContent *shell_content, + GtkRadioAction *scope_action) +{ + EActionComboBox *combo_box; + + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + combo_box = E_ACTION_COMBO_BOX (shell_content->priv->scope_combo_box); + + e_action_combo_box_set_action (combo_box, scope_action); + g_object_notify (G_OBJECT (shell_content), "scope-action"); +} + +gint +e_shell_content_get_scope_value (EShellContent *shell_content) +{ + EActionComboBox *combo_box; + + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), 0); + + combo_box = E_ACTION_COMBO_BOX (shell_content->priv->scope_combo_box); + + return e_action_combo_box_get_current_value (combo_box); +} + +void +e_shell_content_set_scope_value (EShellContent *shell_content, + gint scope_value) +{ + EActionComboBox *combo_box; + + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + combo_box = E_ACTION_COMBO_BOX (shell_content->priv->scope_combo_box); + + e_action_combo_box_set_current_value (combo_box, scope_value); + g_object_notify (G_OBJECT (shell_content), "scope-value"); +} + +gboolean +e_shell_content_get_scope_visible (EShellContent *shell_content) +{ + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), FALSE); + + return GTK_WIDGET_VISIBLE (shell_content->priv->scope_combo_box); +} + +void +e_shell_content_set_scope_visible (EShellContent *shell_content, + gboolean scope_visible) +{ + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + if (scope_visible) { + gtk_widget_show (shell_content->priv->scope_label); + gtk_widget_show (shell_content->priv->scope_combo_box); + } else { + gtk_widget_hide (shell_content->priv->scope_label); + gtk_widget_hide (shell_content->priv->scope_combo_box); + } + + g_object_notify (G_OBJECT (shell_content), "scope-visible"); } diff --git a/shell/e-shell-content.h b/shell/e-shell-content.h index ce521d501f..3685a76639 100644 --- a/shell/e-shell-content.h +++ b/shell/e-shell-content.h @@ -22,6 +22,7 @@ #define E_SHELL_CONTENT_H #include <gtk/gtk.h> +#include <filter/rule-context.h> /* Standard GObject macros */ #define E_TYPE_SHELL_CONTENT \ @@ -44,6 +45,9 @@ G_BEGIN_DECLS +/* Avoid including <e-shell-view.h> */ +struct _EShellView; + typedef struct _EShellContent EShellContent; typedef struct _EShellContentClass EShellContentClass; typedef struct _EShellContentPrivate EShellContentPrivate; @@ -58,8 +62,57 @@ struct _EShellContentClass { }; GType e_shell_content_get_type (void); -GtkWidget * e_shell_content_new (void); -GtkWidget * e_shell_content_get_search_bar (EShellContent *shell_content); +GtkWidget * e_shell_content_new (struct _EShellView *shell_view); +struct _EShellView * + e_shell_content_get_shell_view (EShellContent *shell_content); +RuleContext * e_shell_content_get_context (EShellContent *shell_content); +void e_shell_content_set_context (EShellContent *shell_content, + RuleContext *context); +GtkRadioAction *e_shell_content_get_filter_action + (EShellContent *shell_content); +void e_shell_content_set_filter_action + (EShellContent *shell_content, + GtkRadioAction *filter_action); +gint e_shell_content_get_filter_value(EShellContent *shell_content); +void e_shell_content_set_filter_value(EShellContent *shell_content, + gint filter_value); +gboolean e_shell_content_get_filter_visible + (EShellContent *shell_content); +void e_shell_content_set_filter_visible + (EShellContent *shell_content, + gboolean filter_visible); +GtkRadioAction *e_shell_content_get_search_action + (EShellContent *shell_content); +void e_shell_content_set_search_action + (EShellContent *shell_content, + GtkRadioAction *search_action); +RuleContext * e_shell_content_get_search_context + (EShellContent *shell_content); +const gchar * e_shell_content_get_search_text (EShellContent *shell_content); +void e_shell_content_set_search_text (EShellContent *shell_content, + const gchar *search_text); +gint e_shell_content_get_search_value(EShellContent *shell_content); +void e_shell_content_set_search_value(EShellContent *shell_content, + gint search_value); +gboolean e_shell_content_get_search_visible + (EShellContent *shell_content); +void e_shell_content_set_search_visible + (EShellContent *shell_content, + gboolean search_visible); +GtkRadioAction *e_shell_content_get_scope_action(EShellContent *shell_content); +void e_shell_content_set_scope_action(EShellContent *shell_content, + GtkRadioAction *scope_action); +gint e_shell_content_get_scope_value (EShellContent *shell_content); +void e_shell_content_set_scope_value (EShellContent *shell_content, + gint scope_value); +gboolean e_shell_content_get_scope_visible + (EShellContent *shell_content); +void e_shell_content_set_scope_visible + (EShellContent *shell_content, + gboolean scope_visible); +void e_shell_content_save_search_dialog + (EShellContent *shell_content, + const gchar *filename); G_END_DECLS diff --git a/shell/e-shell-registry.c b/shell/e-shell-registry.c index dfab78da83..af95b0adad 100644 --- a/shell/e-shell-registry.c +++ b/shell/e-shell-registry.c @@ -129,7 +129,9 @@ e_shell_registry_get_canonical_name (const gchar *name) { EShellModule *shell_module; - g_return_val_if_fail (name != NULL, NULL); + /* Handle NULL arguments silently. */ + if (name == NULL) + return NULL; shell_module = e_shell_registry_get_module_by_name (name); diff --git a/shell/e-shell-sidebar.c b/shell/e-shell-sidebar.c index 32b31a83c9..4a83b3462a 100644 --- a/shell/e-shell-sidebar.c +++ b/shell/e-shell-sidebar.c @@ -20,11 +20,16 @@ #include "e-shell-sidebar.h" +#include <e-shell-view.h> + #define E_SHELL_SIDEBAR_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE \ ((obj), E_TYPE_SHELL_SIDEBAR, EShellSidebarPrivate)) struct _EShellSidebarPrivate { + + gpointer shell_view; /* weak pointer */ + GtkWidget *event_box; GtkWidget *image; GtkWidget *primary_label; @@ -37,12 +42,44 @@ enum { PROP_0, PROP_ICON_NAME, PROP_PRIMARY_TEXT, - PROP_SECONDARY_TEXT + PROP_SECONDARY_TEXT, + PROP_SHELL_VIEW }; static gpointer parent_class; static void +shell_sidebar_init_icon_and_text (EShellSidebar *shell_sidebar) +{ + EShellView *shell_view; + EShellViewClass *shell_view_class; + const gchar *icon_name; + const gchar *primary_text; + + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); + + icon_name = shell_view_class->icon_name; + e_shell_sidebar_set_icon_name (shell_sidebar, icon_name); + + primary_text = shell_view_class->label; + e_shell_sidebar_set_primary_text (shell_sidebar, primary_text); +} + +static void +shell_sidebar_set_shell_view (EShellSidebar *shell_sidebar, + EShellView *shell_view) +{ + g_return_if_fail (shell_sidebar->priv->shell_view == NULL); + + shell_sidebar->priv->shell_view = shell_view; + + g_object_add_weak_pointer ( + G_OBJECT (shell_view), + &shell_sidebar->priv->shell_view); +} + +static void shell_sidebar_set_property (GObject *object, guint property_id, const GValue *value, @@ -66,6 +103,12 @@ shell_sidebar_set_property (GObject *object, E_SHELL_SIDEBAR (object), g_value_get_string (value)); return; + + case PROP_SHELL_VIEW: + shell_sidebar_set_shell_view ( + E_SHELL_SIDEBAR (object), + g_value_get_object (value)); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -95,6 +138,12 @@ shell_sidebar_get_property (GObject *object, value, e_shell_sidebar_get_secondary_text ( E_SHELL_SIDEBAR (object))); return; + + case PROP_SHELL_VIEW: + g_value_set_object ( + value, e_shell_sidebar_get_shell_view ( + E_SHELL_SIDEBAR (object))); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -107,6 +156,12 @@ shell_sidebar_dispose (GObject *object) priv = E_SHELL_SIDEBAR_GET_PRIVATE (object); + if (priv->shell_view != NULL) { + g_object_remove_weak_pointer ( + G_OBJECT (priv->shell_view), &priv->shell_view); + priv->shell_view = NULL; + } + if (priv->event_box != NULL) { g_object_unref (priv->event_box); priv->event_box = NULL; @@ -146,6 +201,15 @@ shell_sidebar_finalize (GObject *object) } static void +shell_sidebar_constructed (GObject *object) +{ + EShellSidebar *shell_sidebar; + + shell_sidebar = E_SHELL_SIDEBAR (object); + shell_sidebar_init_icon_and_text (shell_sidebar); +} + +static void shell_sidebar_size_request (GtkWidget *widget, GtkRequisition *requisition) { @@ -252,6 +316,7 @@ shell_sidebar_class_init (EShellSidebarClass *class) object_class->get_property = shell_sidebar_get_property; object_class->dispose = shell_sidebar_dispose; object_class->finalize = shell_sidebar_finalize; + object_class->constructed = shell_sidebar_constructed; widget_class = GTK_WIDGET_CLASS (class); widget_class->size_request = shell_sidebar_size_request; @@ -269,8 +334,7 @@ shell_sidebar_class_init (EShellSidebarClass *class) NULL, NULL, NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); + G_PARAM_READWRITE)); g_object_class_install_property ( object_class, @@ -280,8 +344,7 @@ shell_sidebar_class_init (EShellSidebarClass *class) NULL, NULL, NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); + G_PARAM_READWRITE)); g_object_class_install_property ( object_class, @@ -291,8 +354,18 @@ shell_sidebar_class_init (EShellSidebarClass *class) NULL, NULL, NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SHELL_VIEW, + g_param_spec_object ( + "shell-view", + NULL, + NULL, + E_TYPE_SHELL_VIEW, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); + G_PARAM_CONSTRUCT_ONLY)); } static void @@ -372,9 +445,20 @@ e_shell_sidebar_get_type (void) } GtkWidget * -e_shell_sidebar_new (void) +e_shell_sidebar_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_SHELL_SIDEBAR, "shell-view", shell_view, NULL); +} + +EShellView * +e_shell_sidebar_get_shell_view (EShellSidebar *shell_sidebar) { - return g_object_new (E_TYPE_SHELL_SIDEBAR, NULL); + g_return_val_if_fail (E_IS_SHELL_SIDEBAR (shell_sidebar), NULL); + + return E_SHELL_VIEW (shell_sidebar->priv->shell_view); } const gchar * diff --git a/shell/e-shell-sidebar.h b/shell/e-shell-sidebar.h index 70777b80fd..498f48c7f4 100644 --- a/shell/e-shell-sidebar.h +++ b/shell/e-shell-sidebar.h @@ -46,6 +46,9 @@ G_BEGIN_DECLS +/* Avoid including <e-shell-view.h> */ +struct _EShellView; + typedef struct _EShellSidebar EShellSidebar; typedef struct _EShellSidebarClass EShellSidebarClass; typedef struct _EShellSidebarPrivate EShellSidebarPrivate; @@ -60,7 +63,9 @@ struct _EShellSidebarClass { }; GType e_shell_sidebar_get_type (void); -GtkWidget * e_shell_sidebar_new (void); +GtkWidget * e_shell_sidebar_new (struct _EShellView *shell_view); +struct _EShellView * + e_shell_sidebar_get_shell_view (EShellSidebar *shell_sidebar); const gchar * e_shell_sidebar_get_icon_name (EShellSidebar *shell_sidebar); void e_shell_sidebar_set_icon_name (EShellSidebar *shell_sidebar, const gchar *icon_name); diff --git a/shell/e-shell-view.c b/shell/e-shell-view.c index 7620cb92a7..f069a33567 100644 --- a/shell/e-shell-view.c +++ b/shell/e-shell-view.c @@ -23,10 +23,6 @@ #include <string.h> #include <glib/gi18n.h> -#include <filter/rule-context.h> -#include <widgets/misc/e-search-bar.h> -#include <widgets/misc/e-task-bar.h> - #include <e-shell-content.h> #include <e-shell-module.h> #include <e-shell-sidebar.h> @@ -38,9 +34,11 @@ ((obj), E_TYPE_SHELL_VIEW, EShellViewPrivate)) struct _EShellViewPrivate { + + gpointer shell_window; /* weak pointer */ + gchar *title; gint page_num; - gpointer window; /* weak pointer */ GtkWidget *content; GtkWidget *sidebar; @@ -53,8 +51,8 @@ enum { PROP_0, PROP_PAGE_NUM, PROP_TITLE, - PROP_VIEW_INSTANCE, - PROP_WINDOW + PROP_SHELL_WINDOW, + PROP_VIEW_INSTANCE }; enum { @@ -66,70 +64,6 @@ static gpointer parent_class; static gulong signals[LAST_SIGNAL]; static void -shell_view_setup_search_context (EShellView *shell_view) -{ - RuleContext *context; - EShellViewClass *class; - EShellModule *shell_module; - FilterRule *rule; - FilterPart *part; - GtkWidget *widget; - gchar *system_filename; - gchar *user_filename; - - class = E_SHELL_VIEW_GET_CLASS (shell_view); - shell_module = E_SHELL_MODULE (class->type_module); - - /* The filename for built-in searches is specified in a - * module's EShellModuleInfo. All built-in search rules - * live in the same directory. */ - system_filename = g_build_filename ( - EVOLUTION_RULEDIR, - e_shell_module_get_searches (shell_module), NULL); - - /* The filename for custom saved searches is always of - * the form "$(shell_module_data_dir)/searches.xml". */ - user_filename = g_build_filename ( - e_shell_module_get_data_dir (shell_module), - "searches.xml", NULL); - - context = rule_context_new (); - rule_context_add_part_set ( - context, "partset", FILTER_TYPE_PART, - rule_context_add_part, rule_context_next_part); - rule_context_add_rule_set ( - context, "ruleset", FILTER_TYPE_RULE, - rule_context_add_rule, rule_context_next_rule); - rule_context_load (context, system_filename, user_filename); - - /* XXX Not sure why this is necessary. */ - g_object_set_data_full ( - G_OBJECT (context), "system", system_filename, g_free); - g_object_set_data_full ( - G_OBJECT (context), "user", user_filename, g_free); - - /* XXX I don't really understand what this does. */ - rule = filter_rule_new (); - part = rule_context_next_part (context, NULL); - if (part == NULL) - g_warning ( - "Could not load %s search; no parts.", - class->type_module->name); - else - filter_rule_add_part (rule, filter_part_clone (part)); - - g_free (system_filename); - g_free (user_filename); - - /* Hand the context off to the search bar. */ - widget = e_shell_view_get_content_widget (shell_view); - widget = e_shell_content_get_search_bar (E_SHELL_CONTENT (widget)); - e_search_bar_set_context (E_SEARCH_BAR (widget), context); - - g_object_unref (context); -} - -static void shell_view_set_page_num (EShellView *shell_view, gint page_num) { @@ -137,15 +71,16 @@ shell_view_set_page_num (EShellView *shell_view, } static void -shell_view_set_window (EShellView *shell_view, - GtkWidget *window) +shell_view_set_shell_window (EShellView *shell_view, + GtkWidget *shell_window) { - g_return_if_fail (GTK_IS_WINDOW (window)); + g_return_if_fail (shell_view->priv->shell_window == NULL); - shell_view->priv->window = window; + shell_view->priv->shell_window = shell_window; g_object_add_weak_pointer ( - G_OBJECT (window), &shell_view->priv->window); + G_OBJECT (shell_window), + &shell_view->priv->shell_window); } static void @@ -167,14 +102,14 @@ shell_view_set_property (GObject *object, g_value_get_string (value)); return; - case PROP_VIEW_INSTANCE: - e_shell_view_set_view_instance ( + case PROP_SHELL_WINDOW: + shell_view_set_shell_window ( E_SHELL_VIEW (object), g_value_get_object (value)); return; - case PROP_WINDOW: - shell_view_set_window ( + case PROP_VIEW_INSTANCE: + e_shell_view_set_view_instance ( E_SHELL_VIEW (object), g_value_get_object (value)); return; @@ -202,15 +137,15 @@ shell_view_get_property (GObject *object, E_SHELL_VIEW (object))); return; - case PROP_VIEW_INSTANCE: + case PROP_SHELL_WINDOW: g_value_set_object ( - value, e_shell_view_get_view_instance ( + value, e_shell_view_get_shell_window ( E_SHELL_VIEW (object))); return; - case PROP_WINDOW: + case PROP_VIEW_INSTANCE: g_value_set_object ( - value, e_shell_view_get_window ( + value, e_shell_view_get_view_instance ( E_SHELL_VIEW (object))); return; } @@ -225,10 +160,10 @@ shell_view_dispose (GObject *object) priv = E_SHELL_VIEW_GET_PRIVATE (object); - if (priv->window != NULL) { + if (priv->shell_window != NULL) { g_object_remove_weak_pointer ( - G_OBJECT (priv->window), &priv->window); - priv->window = NULL; + G_OBJECT (priv->shell_window), &priv->shell_window); + priv->shell_window = NULL; } if (priv->content != NULL) { @@ -271,19 +206,25 @@ shell_view_finalize (GObject *object) static void shell_view_constructed (GObject *object) { - EShellViewClass *class; EShellView *shell_view; - GtkWidget *sidebar; + GtkWidget *widget; shell_view = E_SHELL_VIEW (object); - class = E_SHELL_VIEW_GET_CLASS (object); - sidebar = e_shell_view_get_sidebar_widget (shell_view); - e_shell_sidebar_set_icon_name ( - E_SHELL_SIDEBAR (sidebar), class->icon_name); - e_shell_sidebar_set_primary_text ( - E_SHELL_SIDEBAR (sidebar), class->label); - shell_view_setup_search_context (shell_view); + /* We do this AFTER instance initialization so the + * E_SHELL_VIEW_GET_CLASS() macro works properly. */ + + widget = e_shell_content_new (shell_view); + shell_view->priv->content = g_object_ref_sink (widget); + gtk_widget_show (widget); + + widget = e_shell_sidebar_new (shell_view); + shell_view->priv->sidebar = g_object_ref_sink (widget); + gtk_widget_show (widget); + + widget = e_shell_taskbar_new (shell_view); + shell_view->priv->taskbar = g_object_ref_sink (widget); + gtk_widget_show (widget); /* XXX GObjectClass doesn't implement constructed(), so we will. * Then subclasses won't have to check the function pointer @@ -333,6 +274,17 @@ shell_view_class_init (EShellViewClass *class) g_object_class_install_property ( object_class, + PROP_SHELL_WINDOW, + g_param_spec_object ( + "shell-window", + _("Shell Window"), + _("The window to which the shell view belongs"), + E_TYPE_SHELL_WINDOW, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property ( + object_class, PROP_VIEW_INSTANCE, g_param_spec_object ( "view-instance", @@ -341,17 +293,6 @@ shell_view_class_init (EShellViewClass *class) GAL_VIEW_INSTANCE_TYPE, G_PARAM_READWRITE)); - g_object_class_install_property ( - object_class, - PROP_WINDOW, - g_param_spec_object ( - "window", - _("Window"), - _("The window to which the shell view belongs"), - GTK_TYPE_WINDOW, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY)); - signals[CHANGED] = g_signal_new ( "changed", G_OBJECT_CLASS_TYPE (object_class), @@ -365,21 +306,7 @@ shell_view_class_init (EShellViewClass *class) static void shell_view_init (EShellView *shell_view) { - GtkWidget *widget; - shell_view->priv = E_SHELL_VIEW_GET_PRIVATE (shell_view); - - widget = e_shell_content_new (); - shell_view->priv->content = g_object_ref_sink (widget); - gtk_widget_show (widget); - - widget = e_shell_sidebar_new (); - shell_view->priv->sidebar = g_object_ref_sink (widget); - gtk_widget_show (widget); - - widget = e_task_bar_new (); - shell_view->priv->taskbar = g_object_ref_sink (widget); - gtk_widget_show (widget); } GType @@ -478,11 +405,11 @@ e_shell_view_set_view_instance (EShellView *shell_view, } EShellWindow * -e_shell_view_get_window (EShellView *shell_view) +e_shell_view_get_shell_window (EShellView *shell_view) { g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - return E_SHELL_WINDOW (shell_view->priv->window); + return E_SHELL_WINDOW (shell_view->priv->shell_window); } gboolean @@ -496,7 +423,7 @@ e_shell_view_is_selected (EShellView *shell_view) g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), FALSE); class = E_SHELL_VIEW_GET_CLASS (shell_view); - shell_window = e_shell_view_get_window (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); this_view_name = e_shell_view_get_name (shell_view); curr_view_name = e_shell_window_get_current_view (shell_window); g_return_val_if_fail (curr_view_name != NULL, FALSE); @@ -512,28 +439,28 @@ e_shell_view_get_page_num (EShellView *shell_view) return shell_view->priv->page_num; } -GtkWidget * -e_shell_view_get_content_widget (EShellView *shell_view) +EShellContent * +e_shell_view_get_content (EShellView *shell_view) { g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - return shell_view->priv->content; + return E_SHELL_CONTENT (shell_view->priv->content); } -GtkWidget * -e_shell_view_get_sidebar_widget (EShellView *shell_view) +EShellSidebar * +e_shell_view_get_sidebar (EShellView *shell_view) { g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - return shell_view->priv->sidebar; + return E_SHELL_SIDEBAR (shell_view->priv->sidebar); } -GtkWidget * -e_shell_view_get_taskbar_widget (EShellView *shell_view) +EShellTaskbar * +e_shell_view_get_taskbar (EShellView *shell_view) { g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - return shell_view->priv->taskbar; + return E_SHELL_TASKBAR (shell_view->priv->taskbar); } void diff --git a/shell/e-shell-view.h b/shell/e-shell-view.h index 5deeac0f31..1654b9c6c6 100644 --- a/shell/e-shell-view.h +++ b/shell/e-shell-view.h @@ -22,6 +22,9 @@ #define E_SHELL_VIEW_H #include <e-shell-common.h> +#include <e-shell-content.h> +#include <e-shell-sidebar.h> +#include <e-shell-taskbar.h> #include <e-shell-window.h> #include <gal-view-instance.h> @@ -89,12 +92,12 @@ GalViewInstance * e_shell_view_get_view_instance (EShellView *shell_view); void e_shell_view_set_view_instance (EShellView *shell_view, GalViewInstance *instance); -EShellWindow * e_shell_view_get_window (EShellView *shell_view); +EShellWindow * e_shell_view_get_shell_window (EShellView *shell_view); gboolean e_shell_view_is_selected (EShellView *shell_view); gint e_shell_view_get_page_num (EShellView *shell_view); -GtkWidget * e_shell_view_get_content_widget (EShellView *shell_view); -GtkWidget * e_shell_view_get_sidebar_widget (EShellView *shell_view); -GtkWidget * e_shell_view_get_taskbar_widget (EShellView *shell_view); +EShellContent * e_shell_view_get_content (EShellView *shell_view); +EShellSidebar * e_shell_view_get_sidebar (EShellView *shell_view); +EShellTaskbar * e_shell_view_get_taskbar (EShellView *shell_view); void e_shell_view_changed (EShellView *shell_view); G_END_DECLS diff --git a/shell/e-shell-window-actions.c b/shell/e-shell-window-actions.c index 9983d77f36..aa14ec44eb 100644 --- a/shell/e-shell-window-actions.c +++ b/shell/e-shell-window-actions.c @@ -868,37 +868,31 @@ static void action_search_clear_cb (GtkAction *action, EShellWindow *shell_window) { + EShellContent *shell_content; EShellView *shell_view; - GtkWidget *widget; const gchar *view_name; - /* Dig up the search bar. */ view_name = e_shell_window_get_current_view (shell_window); shell_view = e_shell_window_get_view (shell_window, view_name); - widget = e_shell_view_get_content_widget (shell_view); - widget = e_shell_content_get_search_bar (E_SHELL_CONTENT (widget)); - - e_search_bar_set_search_text (E_SEARCH_BAR (widget), NULL); + shell_content = e_shell_view_get_content (shell_view); + e_shell_content_set_search_text (shell_content, ""); } static void action_search_edit_cb (GtkAction *action, EShellWindow *shell_window) { + EShellContent *shell_content; EShellView *shell_view; RuleContext *context; RuleEditor *editor; - GtkWidget *widget; const gchar *filename; const gchar *view_name; - /* Dig up the search bar. */ view_name = e_shell_window_get_current_view (shell_window); shell_view = e_shell_window_get_view (shell_window, view_name); - widget = e_shell_view_get_content_widget (shell_view); - widget = e_shell_content_get_search_bar (E_SHELL_CONTENT (widget)); - - context = e_search_bar_get_context (E_SEARCH_BAR (widget)); + shell_content = e_shell_view_get_content (shell_view); + context = e_shell_content_get_search_context (shell_content); g_return_if_fail (context != NULL); /* XXX I don't know why the RuleContext can't just store @@ -1621,12 +1615,16 @@ e_shell_window_create_shell_view_actions (EShellWindow *shell_window) GtkActionGroup *action_group; GtkUIManager *ui_manager; EShellSwitcher *switcher; + GList *list; + const gchar *current_view; + gint current_value = 0; guint n_children, ii; guint merge_id; g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); action_group = shell_window->priv->shell_view_actions; + current_view = e_shell_window_get_current_view (shell_window); children = g_type_children (E_TYPE_SHELL_VIEW, &n_children); switcher = E_SHELL_SWITCHER (shell_window->priv->switcher); ui_manager = e_shell_window_get_ui_manager (shell_window); @@ -1634,7 +1632,12 @@ e_shell_window_create_shell_view_actions (EShellWindow *shell_window) /* Construct a group of radio actions from the various EShellView * subclasses and register them with our ESidebar. These actions - * are manifested as switcher buttons and View->Window menu items. */ + * are manifested as switcher buttons and View->Window menu items. + * + * Note: The shell window has already selected a view by now, + * so we have to be careful not to overwrite that when setting + * up the radio action group. That means not connecting to any + * "changed" signals until after the group is built. */ for (ii = 0; ii < n_children; ii++) { EShellViewClass *class; @@ -1664,6 +1667,10 @@ e_shell_window_create_shell_view_actions (EShellWindow *shell_window) action_name = g_strdup_printf ("shell-view-%s", view_name); tooltip = g_strdup_printf (_("Switch to %s"), class->label); + /* Does this action represent the current view? */ + if (strcmp (view_name, current_view) == 0) + current_value = ii; + /* Note, we have to set "icon-name" separately because * gtk_radio_action_new() expects a "stock-id". Sadly, * GTK+ still distinguishes between the two. */ @@ -1680,18 +1687,6 @@ e_shell_window_create_shell_view_actions (EShellWindow *shell_window) G_OBJECT (action), "view-name", (gpointer) view_name); - if (group == NULL) { - - /* First view is the default. */ - shell_window->priv->default_view = view_name; - - /* Only listen to the first action. */ - g_signal_connect ( - action, "changed", - G_CALLBACK (action_shell_view_cb), - shell_window); - } - gtk_radio_action_set_group (action, group); group = gtk_radio_action_get_group (action); @@ -1719,6 +1714,26 @@ e_shell_window_create_shell_view_actions (EShellWindow *shell_window) g_type_class_unref (class); } + list = gtk_action_group_list_actions (action_group); + if (list != NULL) { + GObject *object = list->data; + const gchar *view_name; + + /* First view is the default. */ + view_name = g_object_get_data (object, "view-name"); + shell_window->priv->default_view = view_name; + + g_signal_connect ( + object, "changed", + G_CALLBACK (action_shell_view_cb), + shell_window); + + /* Sync up with the current shell view. */ + gtk_radio_action_set_current_value ( + GTK_RADIO_ACTION (object), current_value); + } + g_list_free (list); + g_free (children); } diff --git a/shell/e-shell-window-private.c b/shell/e-shell-window-private.c index 8224ee901a..e3c515b4b4 100644 --- a/shell/e-shell-window-private.c +++ b/shell/e-shell-window-private.c @@ -340,6 +340,10 @@ e_shell_window_private_init (EShellWindow *shell_window) gconf_bridge_bind_window ( bridge, key, GTK_WINDOW (shell_window), TRUE, FALSE); + object = G_OBJECT (shell_window); + key = "/apps/evolution/shell/view_defaults/component_id"; + gconf_bridge_bind_property (bridge, key, object, "current-view"); + object = G_OBJECT (priv->content_pane); key = "/apps/evolution/shell/view_defaults/folder_bar/width"; gconf_bridge_bind_property_delayed (bridge, key, object, "position"); diff --git a/shell/e-shell-window.c b/shell/e-shell-window.c index 8d2e3c1180..218f4f599d 100644 --- a/shell/e-shell-window.c +++ b/shell/e-shell-window.c @@ -79,7 +79,7 @@ shell_window_new_view (EShellWindow *shell_window, shell_view = g_object_new ( shell_view_type, "page-num", page_num, - "title", title, "window", shell_window, NULL); + "title", title, "shell-window", shell_window, NULL); name = e_shell_view_get_name (shell_view); loaded_views = shell_window->priv->loaded_views; @@ -88,15 +88,15 @@ shell_window_new_view (EShellWindow *shell_window, /* Add pages to the various shell window notebooks. */ notebook = GTK_NOTEBOOK (shell_window->priv->content_notebook); - widget = e_shell_view_get_content_widget (shell_view); + widget = GTK_WIDGET (e_shell_view_get_content (shell_view)); gtk_notebook_append_page (notebook, widget, NULL); notebook = GTK_NOTEBOOK (shell_window->priv->sidebar_notebook); - widget = e_shell_view_get_sidebar_widget (shell_view); + widget = GTK_WIDGET (e_shell_view_get_sidebar (shell_view)); gtk_notebook_append_page (notebook, widget, NULL); notebook = GTK_NOTEBOOK (shell_window->priv->status_notebook); - widget = e_shell_view_get_taskbar_widget (shell_view); + widget = GTK_WIDGET (e_shell_view_get_taskbar (shell_view)); gtk_notebook_append_page (notebook, widget, NULL); g_signal_connect_swapped ( @@ -242,8 +242,7 @@ shell_window_class_init (EShellWindowClass *class) NULL, NULL, NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); + G_PARAM_READWRITE)); g_object_class_install_property ( object_class, diff --git a/shell/main.c b/shell/main.c index 9f729a7bf9..1ed06c611a 100644 --- a/shell/main.c +++ b/shell/main.c @@ -34,7 +34,6 @@ #include "e-util/e-bconf-map.h" #include <e-util/e-icon-factory.h> -#include "e-shell-constants.h" #include "e-shell-registry.h" #include "e-util/e-profile-event.h" #include "e-util/e-util.h" @@ -99,7 +98,7 @@ static gboolean disable_preview = FALSE; static gboolean idle_cb (gchar **uris); static EShell *global_shell; -static char *default_component_id = NULL; +static char *requested_view = NULL; static char *evolution_debug_log = NULL; static gchar **remaining_args; @@ -281,21 +280,35 @@ open_uris (gchar **uris) static gboolean idle_cb (gchar **uris) { + GtkWidget *shell_window; + const gchar *initial_view; + g_return_val_if_fail (uris == NULL || g_strv_length (uris) > 0, FALSE); #ifdef KILL_PROCESS_CMD kill_old_dataserver (); #endif - if (uris != NULL) + if (uris != NULL) { open_uris (uris); - else { - GtkWidget *shell_window; + return FALSE; + } + + initial_view = e_shell_registry_get_canonical_name (requested_view); - shell_window = e_shell_create_window (global_shell); - /* XXX Switch to default_component_id. */ + if (initial_view != NULL) { + GConfClient *client; + const gchar *key; + + client = gconf_client_get_default (); + key = "/apps/evolution/shell/view_defaults/component_id"; + requested_view = gconf_client_set_string ( + client, key, initial_view, NULL); + g_object_unref (client); } + shell_window = e_shell_create_window (global_shell); + #if 0 /* MBARNES */ if (shell == NULL) { /*there is another instance but because we don't open any windows @@ -366,7 +379,7 @@ setup_segv_redirect (void) #endif static const GOptionEntry options[] = { - { "component", 'c', 0, G_OPTION_ARG_STRING, &default_component_id, + { "component", 'c', 0, G_OPTION_ARG_STRING, &requested_view, N_("Start Evolution activating the specified component"), NULL }, { "offline", '\0', 0, G_OPTION_ARG_NONE, &start_offline, N_("Start in offline mode"), NULL }, diff --git a/shell/test/e-test-shell-view.c b/shell/test/e-test-shell-view.c index e88df99d96..be2a747354 100644 --- a/shell/test/e-test-shell-view.c +++ b/shell/test/e-test-shell-view.c @@ -43,14 +43,42 @@ test_shell_view_changed (EShellView *shell_view) } static void +test_shell_view_constructed (GObject *object) +{ + EShellContent *shell_content; + EShellSidebar *shell_sidebar; + EShellView *shell_view; + GtkWidget *widget; + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + shell_view = E_SHELL_VIEW (object); + shell_content = e_shell_view_get_content (shell_view); + shell_sidebar = e_shell_view_get_sidebar (shell_view); + + widget = gtk_label_new ("Content Widget"); + gtk_container_add (GTK_CONTAINER (shell_content), widget); + gtk_widget_show (widget); + + widget = gtk_label_new ("Sidebar Widget"); + gtk_container_add (GTK_CONTAINER (shell_sidebar), widget); + gtk_widget_show (widget); +} + +static void test_shell_view_class_init (ETestShellViewClass *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 (ETestShellViewPrivate)); + object_class = G_OBJECT_CLASS (class); + object_class->constructed = test_shell_view_constructed; + shell_view_class = E_SHELL_VIEW_CLASS (class); shell_view_class->label = "Test"; shell_view_class->icon_name = "face-monkey"; @@ -61,24 +89,8 @@ test_shell_view_class_init (ETestShellViewClass *class, static void test_shell_view_init (ETestShellView *test_shell_view) { - EShellView *shell_view; - GtkWidget *container; - GtkWidget *widget; - test_shell_view->priv = E_TEST_SHELL_VIEW_GET_PRIVATE (test_shell_view); - - shell_view = E_SHELL_VIEW (test_shell_view); - - container = e_shell_view_get_content_widget (shell_view); - widget = gtk_label_new ("Content Widget"); - gtk_container_add (GTK_CONTAINER (container), widget); - gtk_widget_show (widget); - - container = e_shell_view_get_sidebar_widget (shell_view); - widget = gtk_label_new ("Sidebar Widget"); - gtk_container_add (GTK_CONTAINER (container), widget); - gtk_widget_show (widget); } GType |