diff options
author | Ettore Perazzoli <ettore@src.gnome.org> | 2003-07-24 05:58:28 +0800 |
---|---|---|
committer | Ettore Perazzoli <ettore@src.gnome.org> | 2003-07-24 05:58:28 +0800 |
commit | a238c463ddea2a3ddb3a530c75a3a7e1083c9c2d (patch) | |
tree | 2b53e3235c7067bf8ab94dd3ede84f54cf811809 | |
parent | 0dd1d18f1ab6609c1c38f9e97a0702cc71ce2705 (diff) | |
download | gsoc2013-evolution-a238c463ddea2a3ddb3a530c75a3a7e1083c9c2d.tar gsoc2013-evolution-a238c463ddea2a3ddb3a530c75a3a7e1083c9c2d.tar.gz gsoc2013-evolution-a238c463ddea2a3ddb3a530c75a3a7e1083c9c2d.tar.bz2 gsoc2013-evolution-a238c463ddea2a3ddb3a530c75a3a7e1083c9c2d.tar.lz gsoc2013-evolution-a238c463ddea2a3ddb3a530c75a3a7e1083c9c2d.tar.xz gsoc2013-evolution-a238c463ddea2a3ddb3a530c75a3a7e1083c9c2d.tar.zst gsoc2013-evolution-a238c463ddea2a3ddb3a530c75a3a7e1083c9c2d.zip |
Create a new EShellWindow and show it.
* main.c (idle_cb): Create a new EShellWindow and show it.
* e-storage.c: New signal "async_open_folder".
(impl_async_open_folder): Removed.
(class_init): Declare new signal.
* e-shell.c (setup_components): Don't actually activate any
components.
* e-storage-browser.c, e-storage-browser.h: New.
* e-shell-window.c, e-shell-window.h: New.
* e-shell-marshal.list: Add an entry for
NONE:STRING,POINTER,POINTER.
* Evolution.idl: Include Evolution-Component.idl.
* Evolution-Component.idl: New interface for Evolution components.
svn path=/trunk/; revision=21925
-rw-r--r-- | shell/ChangeLog | 22 | ||||
-rw-r--r-- | shell/Evolution-Component.idl | 23 | ||||
-rw-r--r-- | shell/Evolution-ShellComponent.idl | 2 | ||||
-rw-r--r-- | shell/Evolution.idl | 1 | ||||
-rw-r--r-- | shell/Makefile.am | 43 | ||||
-rw-r--r-- | shell/e-folder.c | 1 | ||||
-rw-r--r-- | shell/e-shell-marshal.list | 1 | ||||
-rw-r--r-- | shell/e-shell-window.c | 381 | ||||
-rw-r--r-- | shell/e-shell-window.h | 58 | ||||
-rw-r--r-- | shell/e-shell.c | 3 | ||||
-rw-r--r-- | shell/e-storage-browser.c | 310 | ||||
-rw-r--r-- | shell/e-storage-browser.h | 79 | ||||
-rw-r--r-- | shell/e-storage.c | 27 | ||||
-rw-r--r-- | shell/e-storage.h | 15 | ||||
-rw-r--r-- | shell/main.c | 9 |
15 files changed, 934 insertions, 41 deletions
diff --git a/shell/ChangeLog b/shell/ChangeLog index 1836661ca9..93fd01791b 100644 --- a/shell/ChangeLog +++ b/shell/ChangeLog @@ -1,3 +1,25 @@ +2003-07-23 Ettore Perazzoli <ettore@ximian.com> + + * main.c (idle_cb): Create a new EShellWindow and show it. + + * e-storage.c: New signal "async_open_folder". + (impl_async_open_folder): Removed. + (class_init): Declare new signal. + + * e-shell.c (setup_components): Don't actually activate any + components. + + * e-storage-browser.c, e-storage-browser.h: New. + + * e-shell-window.c, e-shell-window.h: New. + + * e-shell-marshal.list: Add an entry for + NONE:STRING,POINTER,POINTER. + + * Evolution.idl: Include Evolution-Component.idl. + + * Evolution-Component.idl: New interface for Evolution components. + 2003-07-23 Dan Winship <danw@ximian.com> * Makefile.am: Use EVO_MARSHAL_RULE diff --git a/shell/Evolution-Component.idl b/shell/Evolution-Component.idl new file mode 100644 index 0000000000..665fa213b1 --- /dev/null +++ b/shell/Evolution-Component.idl @@ -0,0 +1,23 @@ +/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Interface for the Evolution components. + * + * Authors: + * Ettore Perazzoli <ettore@ximian.com> + * + * Copyright (C) 2003 Ximian, Inc. + */ + +#include <Bonobo.idl> + +module GNOME { +module Evolution { + + interface Component : Bonobo::Unknown { + /* Create the controls for embedding in the shell. */ + void createControls (out Bonobo::Control sidebar_control, + out Bonobo::Control view_control); + }; + +}; +}; diff --git a/shell/Evolution-ShellComponent.idl b/shell/Evolution-ShellComponent.idl index 90cd6fa57d..88a594853d 100644 --- a/shell/Evolution-ShellComponent.idl +++ b/shell/Evolution-ShellComponent.idl @@ -97,7 +97,7 @@ module Evolution { /* Send debugging output to the file specified. */ void debug (in string log_path); - /* Create a view for the specified @physical URI. */ + /* Create a view for the specified @physical URI. FIXME */ Bonobo::Control createView (in string physical_uri, in string type, in string view_info) diff --git a/shell/Evolution.idl b/shell/Evolution.idl index 6692bd028d..01ce673724 100644 --- a/shell/Evolution.idl +++ b/shell/Evolution.idl @@ -13,6 +13,7 @@ #include <Evolution-common.idl> #include <Evolution-Activity.idl> +#include <Evolution-Component.idl> #include <Evolution-ConfigControl.idl> #include <Evolution-Session.idl> #include <Evolution-ShellComponent.idl> diff --git a/shell/Makefile.am b/shell/Makefile.am index 1631ccdef0..27430babee 100644 --- a/shell/Makefile.am +++ b/shell/Makefile.am @@ -29,6 +29,7 @@ noinst_PROGRAMS = evolution evolution-test-component IDLS = \ Evolution-Activity.idl \ Evolution-ConfigControl.idl \ + Evolution-Component.idl \ Evolution-Offline.idl \ Evolution-Session.idl \ Evolution-Shell.idl \ @@ -113,19 +114,28 @@ eshellincludedir = $(privincludedir)/shell eshellinclude_HEADERS = \ Evolution.h \ - e-folder.h \ + e-corba-storage.h \ + e-folder-dnd-bridge.h \ e-folder-list.h \ e-folder-tree.h \ + e-folder-type-registry.h \ + e-folder.h \ + e-icon-factory.h \ e-shell-corba-icon-utils.h \ + e-shell-utils.h \ + e-storage-browser.h \ + e-storage-set-view.h \ + e-storage-set.h \ + e-storage.h \ evolution-activity-client.h \ evolution-config-control.h \ evolution-folder-selector-button.h \ evolution-session.h \ evolution-shell-client.h \ evolution-shell-component-client.h \ - evolution-shell-component.h \ evolution-shell-component-dnd.h \ evolution-shell-component-utils.h \ + evolution-shell-component.h \ evolution-shell-view.h \ evolution-storage-listener.h \ evolution-storage-set-view-listener.h \ @@ -134,25 +144,34 @@ eshellinclude_HEADERS = \ libeshell_la_SOURCES = \ $(IDL_GENERATED) \ - e-folder.c \ + e-corba-storage.c \ + e-folder-dnd-bridge.c \ e-folder-list.c \ e-folder-tree.c \ + e-folder-type-registry.c \ + e-folder.c \ + e-icon-factory.c \ e-shell-corba-icon-utils.c \ + e-shell-marshal.c \ + e-shell-utils.c \ + e-storage-browser.c \ + e-storage-set-view.c \ + e-storage-set.c \ + e-storage.c \ evolution-activity-client.c \ evolution-config-control.c \ evolution-folder-selector-button.c \ evolution-session.c \ evolution-shell-client.c \ evolution-shell-component-client.c \ - evolution-shell-component.c \ evolution-shell-component-dnd.c \ evolution-shell-component-utils.c \ + evolution-shell-component.c \ evolution-shell-view.c \ evolution-storage-listener.c \ evolution-storage-set-view-listener.c \ evolution-storage.c \ evolution-wizard.c \ - e-shell-marshal.c \ $(eshellinclude_HEADERS) libeshell_la_LIBADD = \ @@ -179,14 +198,8 @@ evolution_SOURCES = \ e-corba-storage-registry.h \ e-corba-storage.c \ e-corba-storage.h \ - e-folder-dnd-bridge.c \ - e-folder-dnd-bridge.h \ - e-folder-type-registry.c \ - e-folder-type-registry.h \ e-history.c \ e-history.h \ - e-icon-factory.c \ - e-icon-factory.h \ e-local-folder.c \ e-local-folder.h \ e-local-storage.c \ @@ -234,6 +247,8 @@ evolution_SOURCES = \ e-shell-view-menu.h \ e-shell-view.c \ e-shell-view.h \ + e-shell-window.c \ + e-shell-window.h \ e-shell.c \ e-shell.h \ e-shortcuts-view-model.c \ @@ -244,12 +259,6 @@ evolution_SOURCES = \ e-shortcuts.h \ e-splash.c \ e-splash.h \ - e-storage-set-view.c \ - e-storage-set-view.h \ - e-storage-set.c \ - e-storage-set.h \ - e-storage.c \ - e-storage.h \ e-task-bar.c \ e-task-bar.h \ e-task-widget.c \ diff --git a/shell/e-folder.c b/shell/e-folder.c index 8226170e92..adaa31f465 100644 --- a/shell/e-folder.c +++ b/shell/e-folder.c @@ -220,7 +220,6 @@ e_folder_new (const char *name, g_return_val_if_fail (name != NULL, NULL); g_return_val_if_fail (type != NULL, NULL); - g_return_val_if_fail (description != NULL, NULL); folder = g_object_new (E_TYPE_FOLDER, NULL); diff --git a/shell/e-shell-marshal.list b/shell/e-shell-marshal.list index f1ae29622d..d4076e2a6c 100644 --- a/shell/e-shell-marshal.list +++ b/shell/e-shell-marshal.list @@ -23,6 +23,7 @@ NONE:STRING,BOOL NONE:STRING,INT NONE:STRING,INT,INT NONE:STRING,POINTER +NONE:STRING,POINTER,POINTER NONE:STRING,STRING NONE:STRING,STRING,STRING NONE:STRING,STRING,STRING,STRING diff --git a/shell/e-shell-window.c b/shell/e-shell-window.c new file mode 100644 index 0000000000..5074668f92 --- /dev/null +++ b/shell/e-shell-window.c @@ -0,0 +1,381 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shell-window.c + * + * Copyright (C) 2003 Ettore Perazzoli + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli <ettore@ximian.com> + */ + +#include <config.h> + +#include "Evolution.h" + +#include <gal/util/e-util.h> + +#include <gtk/gtkbutton.h> +#include <gtk/gtkhpaned.h> +#include <gtk/gtknotebook.h> +#include <gtk/gtkvbox.h> + +#include <bonobo/bonobo-exception.h> +#include <bonobo/bonobo-object.h> +#include <bonobo/bonobo-ui-util.h> +#include <bonobo/bonobo-widget.h> + +#include <string.h> + +#include "e-shell-window.h" + + +#define PARENT_TYPE gtk_window_get_type () +static GtkWindowClass *parent_class = NULL; + + +/* A view for each component. These are all created when EShellWindow is + instantiated, but with the widget pointers to NULL and the page number set + to -1. When the views are created the first time, the widget pointers as + well as the notebook page value get set. */ +struct _ComponentView { + char *component_id; + + GNOME_Evolution_Component component_iface; + + GtkWidget *sidebar_widget; + GtkWidget *view_widget; + + int notebook_page_num; +}; +typedef struct _ComponentView ComponentView; + + +struct _EShellWindowPrivate { + EShell *shell; + + /* All the ComponentViews. */ + GSList *component_views; + + /* Notebooks used to switch between components. */ + GtkWidget *sidebar_notebook; + GtkWidget *view_notebook; + + /* Bonobo foo. */ + BonoboUIComponent *ui_component; + BonoboUIContainer *ui_container; +}; + + +/* ComponentView handling. */ + +static ComponentView * +component_view_new (const char *id) +{ + ComponentView *view = g_new0 (ComponentView, 1); + + view->component_id = g_strdup (id); + view->notebook_page_num = -1; + + return view; +} + +static void +component_view_free (ComponentView *view) +{ + g_free (view->component_id); + bonobo_object_release_unref (view->component_iface, NULL); + g_free (view); +} + + +/* Utility functions. */ + +static void +init_view (EShellWindow *window, + ComponentView *view) +{ + EShellWindowPrivate *priv = window->priv; + Bonobo_UIContainer container; + Bonobo_Control sidebar_control; + Bonobo_Control view_control; + CORBA_Environment ev; + int sidebar_notebook_page_num; + int view_notebook_page_num; + + g_assert (view->component_iface == CORBA_OBJECT_NIL); + g_assert (view->view_widget == NULL); + g_assert (view->sidebar_widget == NULL); + g_assert (view->notebook_page_num == -1); + + CORBA_exception_init (&ev); + + /* 1. Activate component. (FIXME: Shouldn't do this here.) */ + + view->component_iface = bonobo_activation_activate_from_id (view->component_id, 0, NULL, &ev); + if (BONOBO_EX (&ev) || view->component_iface == CORBA_OBJECT_NIL) { + char *ex_text = bonobo_exception_get_text (&ev); + g_warning ("Cannot activate component %s: %s", view->component_id, ex_text); + g_free (ex_text); + + view->component_iface = CORBA_OBJECT_NIL; + CORBA_exception_free (&ev); + return; + } + + /* 2. Set up view. */ + + GNOME_Evolution_Component_createControls (view->component_iface, &sidebar_control, &view_control, &ev); + if (BONOBO_EX (&ev)) { + g_warning ("Cannot create view for %s", view->component_id); + CORBA_exception_free (&ev); + return; + } + + CORBA_exception_free (&ev); + + container = bonobo_ui_component_get_container (priv->ui_component); + + view->sidebar_widget = bonobo_widget_new_control_from_objref (sidebar_control, container); + gtk_widget_show (view->sidebar_widget); + bonobo_object_release_unref (sidebar_control, NULL); + + view->view_widget = bonobo_widget_new_control_from_objref (view_control, container); + gtk_widget_show (view->view_widget); + bonobo_object_release_unref (view_control, NULL); + + gtk_notebook_append_page (GTK_NOTEBOOK (priv->sidebar_notebook), view->sidebar_widget, NULL); + gtk_notebook_append_page (GTK_NOTEBOOK (priv->view_notebook), view->view_widget, NULL); + + sidebar_notebook_page_num = gtk_notebook_page_num (GTK_NOTEBOOK (priv->sidebar_notebook), view->sidebar_widget); + view_notebook_page_num = gtk_notebook_page_num (GTK_NOTEBOOK (priv->view_notebook), view->view_widget); + + /* Since we always add a view page and a sidebar page at the same time... */ + g_assert (sidebar_notebook_page_num == view_notebook_page_num); + + view->notebook_page_num = view_notebook_page_num; +} + + +/* Callbacks. */ + +static void +component_button_clicked_callback (GtkButton *button, + EShellWindow *window) +{ + ComponentView *component_view = g_object_get_data (G_OBJECT (button), "ComponentView"); + EShellWindowPrivate *priv = window->priv; + + g_assert (component_view != NULL); + + if (component_view->sidebar_widget == NULL) { + init_view (window, component_view); + } else { + gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->view_notebook), component_view->notebook_page_num); + gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->sidebar_notebook), component_view->notebook_page_num); + } +} + + +/* Widget layout. */ + +static GtkWidget * +create_component_button (EShellWindow *window, + ComponentView *component_view) +{ + GtkWidget *button; + const char *id = component_view->component_id; + const char *p, *q; + char *label; + + /* FIXME: Need a "name" property on the component or somesuch. */ + + p = strrchr (id, '_'); + if (p == NULL || p == id) { + label = g_strdup (id); + } else { + for (q = p - 1; q != id; q--) { + if (*q == '_') + break; + } + + if (*q != '_') { + label = g_strdup (id); + } else { + label = g_strndup (q + 1, p - q - 1); + } + } + + button = gtk_button_new_with_label (label); + + g_object_set_data (G_OBJECT (button), "ComponentView", component_view); + g_signal_connect (button, "clicked", G_CALLBACK (component_button_clicked_callback), window); + + g_free (label); + + return button; +} + +static void +setup_widgets (EShellWindow *window) +{ + EShellWindowPrivate *priv = window->priv; + Bonobo_ServerInfoList *info_list; + CORBA_Environment ev; + GtkWidget *paned; + GtkWidget *sidebar_vbox; + GtkWidget *button_box; + int i; + + paned = gtk_hpaned_new (); + bonobo_window_set_contents (BONOBO_WINDOW (window), paned); + + sidebar_vbox = gtk_vbox_new (FALSE, 6); + gtk_paned_pack1 (GTK_PANED (paned), sidebar_vbox, FALSE, FALSE); + + priv->sidebar_notebook = gtk_notebook_new (); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->sidebar_notebook), FALSE); + gtk_box_pack_start (GTK_BOX (sidebar_vbox), priv->sidebar_notebook, TRUE, TRUE, 0); + + priv->view_notebook = gtk_notebook_new (); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->view_notebook), FALSE); + gtk_paned_pack2 (GTK_PANED (paned), priv->view_notebook, FALSE, FALSE); + + button_box = gtk_hbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (sidebar_vbox), button_box, FALSE, FALSE, 0); + + CORBA_exception_init (&ev); + + /* FIXME: Shouldn't be doing this here. */ + + info_list = bonobo_activation_query ("repo_ids.has ('IDL:GNOME/Evolution/Component:1.0')", NULL, &ev); + if (BONOBO_EX (&ev)) { + char *ex_text = bonobo_exception_get_text (&ev); + g_warning ("Cannot query for components: %s\n", ex_text); + g_free (ex_text); + CORBA_exception_free (&ev); + return; + } + + for (i = 0; i < info_list->_length; i++) { + ComponentView *component_view = component_view_new (info_list->_buffer[i].iid); + GtkWidget *component_button = create_component_button (window, component_view); + + priv->component_views = g_slist_prepend (priv->component_views, component_view); + + gtk_box_pack_start (GTK_BOX (button_box), component_button, FALSE, FALSE, 0); + } + + CORBA_free (info_list); + CORBA_exception_free (&ev); + + gtk_widget_show_all (paned); +} + + +/* GObject methods. */ + +static void +impl_dispose (GObject *object) +{ + EShellWindowPrivate *priv = E_SHELL_WINDOW (object)->priv; + + if (priv->shell != NULL) { + g_object_remove_weak_pointer (G_OBJECT (priv->shell), (void **) &priv->shell); + priv->shell = NULL; + } + + (* G_OBJECT_CLASS (parent_class)->dispose) (object); +} + +static void +impl_finalize (GObject *object) +{ + EShellWindowPrivate *priv = E_SHELL_WINDOW (object)->priv; + + g_slist_foreach (priv->component_views, (GFunc) component_view_free, NULL); + g_slist_free (priv->component_views); + + g_free (priv); + + (* G_OBJECT_CLASS (parent_class)->finalize) (object); +} + + +/* Initialization. */ + +static void +class_init (EShellWindowClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->dispose = impl_dispose; + object_class->finalize = impl_finalize; + + parent_class = g_type_class_peek_parent (class); +} + +static void +init (EShellWindow *shell_window) +{ + EShellWindowPrivate *priv; + + priv = g_new0 (EShellWindowPrivate, 1); + + shell_window->priv = priv; +} + + +/* Instantiation. */ + +GtkWidget * +e_shell_window_new (EShell *shell) +{ + EShellWindow *window = g_object_new (e_shell_window_get_type (), NULL); + EShellWindowPrivate *priv = window->priv; + + if (bonobo_window_construct (BONOBO_WINDOW (window), + bonobo_ui_container_new (), + "evolution", "Ximian Evolution") == NULL) { + g_object_unref (window); + return NULL; + } + + /* FIXME TODO: Add system_exception signal handling and all the other + stuff from e_shell_view_construct(). */ + + priv->ui_container = bonobo_window_get_ui_container (BONOBO_WINDOW (window)); + + priv->ui_component = bonobo_ui_component_new ("evolution"); + bonobo_ui_component_set_container (priv->ui_component, + bonobo_object_corba_objref (BONOBO_OBJECT (priv->ui_container)), + NULL); + + bonobo_ui_util_set_ui (priv->ui_component, + PREFIX, + EVOLUTION_UIDIR "/evolution.xml", + "evolution-1.4", NULL); + + window->priv->shell = shell; + g_object_add_weak_pointer (G_OBJECT (shell), (void **) &window->priv->shell); + + setup_widgets (window); + + gtk_window_set_default_size (GTK_WINDOW (window), 640, 480); + + return GTK_WIDGET (window); +} + + +E_MAKE_TYPE (e_shell_window, "EShellWindow", EShellWindow, class_init, init, BONOBO_TYPE_WINDOW) diff --git a/shell/e-shell-window.h b/shell/e-shell-window.h new file mode 100644 index 0000000000..602b030283 --- /dev/null +++ b/shell/e-shell-window.h @@ -0,0 +1,58 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shell-window.h + * + * Copyright (C) 2003 Ettore Perazzoli + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli <ettore@ximian.com> + */ + +#ifndef _E_SHELL_WINDOW_H_ +#define _E_SHELL_WINDOW_H_ + +#include <bonobo/bonobo-window.h> + +#define E_TYPE_SHELL_WINDOW (e_shell_window_get_type ()) +#define E_SHELL_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_SHELL_WINDOW, EShellWindow)) +#define E_SHELL_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_SHELL_WINDOW, EShellWindowClass)) +#define E_IS_SHELL_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_SHELL_WINDOW)) +#define E_IS_SHELL_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_SHELL_WINDOW)) + + +typedef struct _EShellWindow EShellWindow; +typedef struct _EShellWindowPrivate EShellWindowPrivate; +typedef struct _EShellWindowClass EShellWindowClass; + +struct _EShellWindow { + BonoboWindow parent; + + EShellWindowPrivate *priv; +}; + +struct _EShellWindowClass { + BonoboWindowClass parent_class; +}; + + +#include "e-shell.h" + + +GType e_shell_window_get_type (void); + +GtkWidget *e_shell_window_new (EShell *shell); + + +#endif /* _E_SHELL_WINDOW_H_ */ diff --git a/shell/e-shell.c b/shell/e-shell.c index 5dbf9f8666..8462042279 100644 --- a/shell/e-shell.c +++ b/shell/e-shell.c @@ -797,6 +797,7 @@ setup_components (EShell *shell, priv = shell->priv; priv->component_registry = e_component_registry_new (shell); +#if 0 /* FIXME */ info_list = bonobo_activation_query ("repo_ids.has ('IDL:GNOME/Evolution/ShellComponent:1.0')", selection_order, &ev); if (ev._major != CORBA_NO_EXCEPTION) @@ -852,8 +853,8 @@ setup_components (EShell *shell, while (gtk_events_pending ()) gtk_main_iteration (); } - CORBA_free (info_list); +#endif CORBA_exception_free (&ev); } diff --git a/shell/e-storage-browser.c b/shell/e-storage-browser.c new file mode 100644 index 0000000000..e1baf6bae9 --- /dev/null +++ b/shell/e-storage-browser.c @@ -0,0 +1,310 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-browser.c + * + * Copyright (C) 2003 Ximian, Inc. + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli <ettore@ximian.com> + */ + +/* TODO: + + - Currently it assumes that the starting path always exists, and you + can't remove it. It might be a limitation, but it makes the logic + very simple and robust. + + - Doesn't save expansion state for nodes. + + - Context menu handling? + +*/ + +#include <config.h> + +#include "e-storage-browser.h" + +#include "e-shell-marshal.h" +#include "e-storage-set-view.h" + +#include <gal/util/e-util.h> + +#include <gtk/gtknotebook.h> +#include <string.h> + + +#define PARENT_TYPE G_TYPE_OBJECT +static GObjectClass *parent_class = NULL; + + +struct _EStorageBrowserPrivate { + char *starting_path; + char *current_path; + + GtkWidget *view_notebook; + GtkWidget *storage_set_view; + + GHashTable *path_to_view; /* (char *, GtkWidget *) */ + + EStorageBrowserCreateViewCallback create_view_callback; + void *create_view_callback_data; +}; + + +enum { + WIDGETS_GONE, + NUM_SIGNALS +}; + +static unsigned int signals[NUM_SIGNALS] = { 0 }; + + +/* Callbacks. */ + +static void +storage_set_view_folder_selected_callback (EStorageSetView *storage_set_view, + const char *path, + EStorageBrowser *browser) +{ + if (! e_storage_browser_show_path (browser, path)) { + /* Make the selection go back to where it was. */ + e_storage_browser_show_path (browser, browser->priv->current_path); + } +} + +static void +storage_set_removed_folder_callback (EStorageSet *storage_set, + const char *path, + EStorageBrowser *browser) +{ + if (g_hash_table_lookup (browser->priv->path_to_view, path) != NULL) + e_storage_browser_remove_view_for_path (browser, path); +} + +static void +view_notebook_weak_notify (EStorageBrowser *browser) +{ + browser->priv->view_notebook = NULL; + + if (browser->priv->storage_set_view == NULL) + g_signal_emit (browser, signals[WIDGETS_GONE], 0); +} + +static void +storage_set_view_weak_notify (EStorageBrowser *browser) +{ + browser->priv->storage_set_view = NULL; + + if (browser->priv->view_notebook == NULL) + g_signal_emit (browser, signals[WIDGETS_GONE], 0); +} + + +/* GObject methods. */ + +static void +impl_dispose (GObject *object) +{ + EStorageBrowserPrivate *priv = E_STORAGE_BROWSER (object)->priv; + + if (priv->view_notebook != NULL) { + g_object_weak_unref (G_OBJECT (priv->view_notebook), + (GWeakNotify) view_notebook_weak_notify, + object); + priv->view_notebook = NULL; + } + + if (priv->storage_set_view != NULL) { + g_object_weak_unref (G_OBJECT (priv->storage_set_view), + (GWeakNotify) storage_set_view_weak_notify, + object); + priv->storage_set_view = NULL; + } + + (* G_OBJECT_CLASS (parent_class)->dispose) (object); +} + +static void +impl_finalize (GObject *object) +{ + EStorageBrowserPrivate *priv = E_STORAGE_BROWSER (object)->priv; + + g_free (priv->starting_path); + g_free (priv->current_path); + + g_hash_table_destroy (priv->path_to_view); + + g_free (priv); + + (* G_OBJECT_CLASS (parent_class)->finalize) (object); +} + + +/* Initialization. */ + +static void +class_init (EStorageBrowserClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->dispose = impl_dispose; + object_class->finalize = impl_finalize; + + parent_class = g_type_class_peek_parent (class); + + signals[WIDGETS_GONE] + = g_signal_new ("widgets_gone", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EStorageBrowserClass, widgets_gone), + NULL, NULL, + e_shell_marshal_NONE__NONE, + G_TYPE_NONE, 0); +} + +static void +init (EStorageBrowser *browser) +{ + EStorageBrowserPrivate *priv; + + priv = g_new0 (EStorageBrowserPrivate, 1); + + priv->path_to_view = g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_object_unref); + + priv->view_notebook = gtk_notebook_new (); + g_object_weak_ref (G_OBJECT (priv->view_notebook), (GWeakNotify) view_notebook_weak_notify, browser); + + gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->view_notebook), FALSE); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->view_notebook), FALSE); + + browser->priv = priv; +} + + +EStorageBrowser * +e_storage_browser_new (EStorageSet *storage_set, + const char *starting_path, + EStorageBrowserCreateViewCallback create_view_callback, + void *callback_data) +{ + EStorageBrowser *new; + + g_return_val_if_fail (create_view_callback != NULL, NULL); + + new = g_object_new (e_storage_browser_get_type (), NULL); + + new->priv->create_view_callback = create_view_callback; + new->priv->create_view_callback_data = callback_data; + new->priv->starting_path = g_strdup (starting_path); + new->priv->storage_set_view = e_storage_set_create_new_view (storage_set, NULL); + + g_object_weak_ref (G_OBJECT (new->priv->storage_set_view), (GWeakNotify) storage_set_view_weak_notify, new); + + g_signal_connect_object (new->priv->storage_set_view, + "folder_selected", G_CALLBACK (storage_set_view_folder_selected_callback), + G_OBJECT (new), 0); + g_signal_connect_object (e_storage_set_view_get_storage_set (E_STORAGE_SET_VIEW (new->priv->storage_set_view)), + "removed_folder", G_CALLBACK (storage_set_removed_folder_callback), + G_OBJECT (new), 0); + + if (! e_storage_browser_show_path (new, starting_path)) { + g_object_unref (new); + return NULL; + } + + return new; +} + + +GtkWidget * +e_storage_browser_peek_tree_widget (EStorageBrowser *browser) +{ + return browser->priv->storage_set_view; +} + +GtkWidget * +e_storage_browser_peek_view_widget (EStorageBrowser *browser) +{ + return browser->priv->view_notebook; +} + +EStorageSet * +e_storage_browser_peek_storage_set (EStorageBrowser *browser) +{ + return e_storage_set_view_get_storage_set (E_STORAGE_SET_VIEW (browser->priv->storage_set_view)); +} + +gboolean +e_storage_browser_show_path (EStorageBrowser *browser, + const char *path) +{ + EStorageBrowserPrivate *priv = browser->priv; + GtkWidget *existing_view; + GtkWidget *new_view; + GtkNotebook *notebook; + + notebook = GTK_NOTEBOOK (priv->view_notebook); + + existing_view = g_hash_table_lookup (priv->path_to_view, path); + if (existing_view != NULL) { + gtk_notebook_set_current_page (notebook, gtk_notebook_page_num (notebook, existing_view)); + return TRUE; + } + + new_view = (* priv->create_view_callback) (browser, path, priv->create_view_callback_data); + if (new_view == NULL) + return FALSE; + + gtk_widget_show (new_view); + gtk_notebook_append_page (notebook, new_view, NULL); + gtk_notebook_set_current_page (notebook, gtk_notebook_page_num (notebook, new_view)); + + g_hash_table_insert (priv->path_to_view, g_strdup (path), new_view); + + g_free (priv->current_path); + priv->current_path = g_strdup (path); + + e_storage_set_view_set_current_folder (E_STORAGE_SET_VIEW (priv->storage_set_view), path); + + return TRUE; +} + +void +e_storage_browser_remove_view_for_path (EStorageBrowser *browser, + const char *path) +{ + GtkWidget *view; + + if (strcmp (path, browser->priv->starting_path) == 0) { + g_warning (G_GNUC_FUNCTION ": cannot remove starting view"); + return; + } + + view = g_hash_table_lookup (browser->priv->path_to_view, path); + if (view == NULL) { + g_warning (G_GNUC_FUNCTION ": no view for %s", path); + return; + } + + g_hash_table_remove (browser->priv->path_to_view, path); + gtk_widget_destroy (view); + + e_storage_browser_show_path (browser, browser->priv->starting_path); +} + + +E_MAKE_TYPE (e_storage_browser, "EStorageBrowser", EStorageBrowser, class_init, init, PARENT_TYPE) diff --git a/shell/e-storage-browser.h b/shell/e-storage-browser.h new file mode 100644 index 0000000000..ddc0430ca9 --- /dev/null +++ b/shell/e-storage-browser.h @@ -0,0 +1,79 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-storage-browser.h + * + * Copyright (C) 2003 Ximian, Inc. + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli <ettore@ximian.com> + */ + +#ifndef _E_STORAGE_BROWSER_H_ +#define _E_STORAGE_BROWSER_H_ + +#include "e-storage-set.h" + +#include <glib-object.h> +#include <gtk/gtkwidget.h> + + +#define E_TYPE_STORAGE_BROWSER (e_storage_browser_get_type ()) +#define E_STORAGE_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_STORAGE_BROWSER, EStorageBrowser)) +#define E_STORAGE_BROWSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_STORAGE_BROWSER, EStorageBrowserClass)) +#define E_IS_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_STORAGE_BROWSER)) +#define E_IS_BROWSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_STORAGE_BROWSER)) + + +typedef struct _EStorageBrowser EStorageBrowser; +typedef struct _EStorageBrowserPrivate EStorageBrowserPrivate; +typedef struct _EStorageBrowserClass EStorageBrowserClass; + +/* FIXME: Use a GClosure instead of void *? */ +typedef GtkWidget * (* EStorageBrowserCreateViewCallback) (EStorageBrowser *browser, + const char *path, + void *data); + + +struct _EStorageBrowser { + GObject parent; + + EStorageBrowserPrivate *priv; +}; + +struct _EStorageBrowserClass { + GObjectClass parent_class; + + void (* widgets_gone) (EStorageBrowser *browser); +}; + + +GType e_storage_browser_get_type (void); + +EStorageBrowser *e_storage_browser_new (EStorageSet *storage_set, + const char *starting_path, + EStorageBrowserCreateViewCallback create_view_callback, + void *create_view_callback_data); + +GtkWidget *e_storage_browser_peek_tree_widget (EStorageBrowser *browser); +GtkWidget *e_storage_browser_peek_view_widget (EStorageBrowser *browser); +EStorageSet *e_storage_browser_peek_storage_set (EStorageBrowser *browser); + +gboolean e_storage_browser_show_path (EStorageBrowser *browser, + const char *path); +void e_storage_browser_remove_view_for_path (EStorageBrowser *browser, + const char *path); + + +#endif /* _E_STORAGE_BROWSER_H_ */ diff --git a/shell/e-storage.c b/shell/e-storage.c index f4a8e5ff26..0a56e3569f 100644 --- a/shell/e-storage.c +++ b/shell/e-storage.c @@ -61,6 +61,7 @@ enum { NEW_FOLDER, UPDATED_FOLDER, REMOVED_FOLDER, + ASYNC_OPEN_FOLDER, LAST_SIGNAL }; @@ -212,15 +213,6 @@ impl_async_xfer_folder (EStorage *storage, (* callback) (storage, E_STORAGE_NOTIMPLEMENTED, data); } -static void -impl_async_open_folder (EStorage *storage, - const char *path, - EStorageDiscoveryCallback callback, - void *data) -{ - (*callback) (storage, E_STORAGE_NOTIMPLEMENTED, path, data); -} - static gboolean impl_supports_shared_folders (EStorage *storage) { @@ -265,7 +257,6 @@ class_init (EStorageClass *class) class->async_create_folder = impl_async_create_folder; class->async_remove_folder = impl_async_remove_folder; class->async_xfer_folder = impl_async_xfer_folder; - class->async_open_folder = impl_async_open_folder; class->supports_shared_folders = impl_supports_shared_folders; class->async_discover_shared_folder = impl_async_discover_shared_folder; @@ -298,6 +289,17 @@ class_init (EStorageClass *class) e_shell_marshal_NONE__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); + signals[ASYNC_OPEN_FOLDER] = + g_signal_new ("async_open_folder", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EStorageClass, async_open_folder), + NULL, NULL, + e_shell_marshal_NONE__STRING_POINTER_POINTER, + G_TYPE_NONE, 3, + G_TYPE_STRING, + G_TYPE_POINTER, + G_TYPE_POINTER); } static void @@ -328,7 +330,7 @@ e_storage_construct (EStorage *storage, priv = storage->priv; - priv->name = g_strdup (name); + priv->name = g_strdup (name); e_storage_new_folder (storage, "/", root_folder); @@ -500,7 +502,8 @@ e_storage_async_open_folder (EStorage *storage, return; } - (* ES_CLASS (storage)->async_open_folder) (storage, path, callback, data); + g_signal_emit (storage, signals[ASYNC_OPEN_FOLDER], 0, + path, callback, data); } diff --git a/shell/e-storage.h b/shell/e-storage.h index bd0cc5da22..1015290b6a 100644 --- a/shell/e-storage.h +++ b/shell/e-storage.h @@ -82,7 +82,12 @@ struct _EStorageClass { void (* new_folder) (EStorage *storage, const char *path); void (* updated_folder) (EStorage *storage, const char *path); void (* removed_folder) (EStorage *storage, const char *path); - void (* close_folder) (EStorage *storage, const char *path); + + /* FIXME: This should NOT be a signal. */ + void (* async_open_folder) (EStorage *storage, + const char *path, + EStorageDiscoveryCallback callback, + void *data); /* Virtual methods. */ @@ -111,11 +116,6 @@ struct _EStorageClass { EStorageResultCallback callback, void *data); - void (* async_open_folder) (EStorage *storage, - const char *path, - EStorageDiscoveryCallback callback, - void *data); - gboolean (* supports_shared_folders) (EStorage *storage); void (* async_discover_shared_folder) (EStorage *storage, const char *owner, @@ -194,7 +194,8 @@ void e_storage_async_remove_shared_folder (EStorage *s char *e_storage_get_path_for_physical_uri (EStorage *storage, const char *physical_uri); -/* Protected. C++ anyone? */ +/* FIXME: Need to rename these. */ + gboolean e_storage_new_folder (EStorage *storage, const char *path, EFolder *folder); diff --git a/shell/main.c b/shell/main.c index 740eb091ca..8a729822da 100644 --- a/shell/main.c +++ b/shell/main.c @@ -29,6 +29,7 @@ #include "e-icon-factory.h" #include "e-shell-constants.h" #include "e-shell-config.h" +#include "e-shell-window.h" /* FIXME */ #include "e-setup.h" #include "e-shell.h" @@ -439,7 +440,7 @@ idle_cb (void *data) view, AND we can't load the user's previous settings, then show the default URI. */ if (! have_evolution_uri) { - e_shell_create_view (shell, NULL, NULL); + /* e_shell_create_view (shell, NULL, NULL); FIXME */ display_default = TRUE; displayed_any = TRUE; } else { @@ -476,8 +477,12 @@ idle_cb (void *data) CORBA_exception_free (&ev); - if (shell == NULL) + if (shell == NULL) { bonobo_main_quit (); + } else { + /* FIXME */ + gtk_widget_show (e_shell_window_new (shell)); + } return FALSE; } |