diff options
Diffstat (limited to 'shell')
30 files changed, 4474 insertions, 1270 deletions
diff --git a/shell/ChangeLog b/shell/ChangeLog index 18833542b1..d117aecebf 100644 --- a/shell/ChangeLog +++ b/shell/ChangeLog @@ -1,3 +1,9 @@ +2000-05-06 Ettore Perazzoli <ettore@helixcode.com> + + * All files: Reorganized and redone a lot of the shell. New + features: internal URI namespace, extensible storage/folder + mechanism, configurable shortcuts. + 2000-05-03 Damon Chaplin <damon@helixcode.com> * e-shell-view.c (e_shell_view_new): turned the notebook border off. diff --git a/shell/Makefile.am b/shell/Makefile.am index d7b69b32e5..f49b4a72e5 100644 --- a/shell/Makefile.am +++ b/shell/Makefile.am @@ -9,6 +9,7 @@ INCLUDES = \ -DEVOLUTION_IMAGES=\""$(imagesdir)"\" \ -DEVOLUTION_VERSION=\""$(VERSION)"\" \ -DEVOLUTION_LOCALEDIR=\""$(datadir)/locale"\" \ + -DEVOLUTION_DATADIR=\""$(datadir)"\" \ -DG_LOG_DOMAIN=\"evolution-shell\" EVOLUTION_CORBA_GENERATED = \ @@ -19,30 +20,37 @@ EVOLUTION_CORBA_GENERATED = \ CLEANFILES = $(EVOLUTION_CORBA_GENERATED) -evolution_SOURCES = \ +evolution_SOURCES = \ $(EVOLUTION_CORBA_GENERATED) \ - main.c \ - e-folder.c \ - e-folder.h \ - e-init.c \ - e-init.h \ - e-shell.c \ - e-shell.h \ - e-shell-shortcut.c \ - e-shell-shortcut.h \ - e-shell-view.c \ - e-shell-view.h \ - e-shell-view-menu.c \ - e-shell-view-menu.h \ - e-shortcut.c \ - e-shortcut.h \ + e-folder-type-repository.c \ + e-folder-type-repository.h \ + e-folder.c \ + e-folder.h \ + e-local-folder.c \ + e-local-folder.h \ + e-local-storage.c \ + e-local-storage.h \ + e-setup.c \ + e-setup.h \ + e-shell-view-menu.c \ + e-shell-view-menu.h \ + e-shell-view.c \ + e-shell-view.h \ + e-shell.c \ + e-shell.h \ + e-shortcuts-view.c \ + e-shortcuts-view.h \ + e-shortcuts.c \ + e-shortcuts.h \ + e-storage-set.c \ + e-storage-set.h \ + e-storage-watcher.c \ + e-storage-watcher.h \ + e-storage.c \ + e-storage.h \ evolution-service-repository.c \ - evolution-service-repository.h - -Evolution-impl.o: Evolution.h - -$(EVOLUTION_CORBA_GENERATED): Evolution.idl evolution-service-repository.idl - $(ORBIT_IDL) -I$(datadir)/idl -I`$(GNOME_CONFIG) --datadir`/idl -I$(srcdir) $(srcdir)/Evolution.idl + evolution-service-repository.h \ + main.c evolution_LDADD = \ ../widgets/shortcut-bar/libshortcut-bar.a \ @@ -50,6 +58,17 @@ evolution_LDADD = \ ../e-util/libeutil.la \ $(BONOBO_GNOME_LIBS) +Evolution-impl.o: Evolution.h + +$(EVOLUTION_CORBA_GENERATED): Evolution.idl evolution-service-repository.idl + $(ORBIT_IDL) -I$(datadir)/idl -I`$(GNOME_CONFIG) --datadir`/idl -I$(srcdir) $(srcdir)/Evolution.idl + +evolution_LDADD = \ + $(top_builddir)/widgets/shortcut-bar/libshortcut-bar.a \ + $(top_builddir)/widgets/e-text/libetext.a \ + $(top_builddir)/e-util/libeutil.la \ + $(BONOBO_GNOME_LIBS) + EXTRA_DIST = Evolution.idl \ Shell.idl \ evolution-service-repository.idl diff --git a/shell/e-folder-type-repository.c b/shell/e-folder-type-repository.c new file mode 100644 index 0000000000..748918886c --- /dev/null +++ b/shell/e-folder-type-repository.c @@ -0,0 +1,241 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-folder-type-repository.c + * + + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <glib.h> +#include <gtk/gtktypeutils.h> + +#include "e-util/e-util.h" + +#include "e-folder-type-repository.h" + + +#define PARENT_TYPE GTK_TYPE_OBJECT +static GtkObjectClass *parent_class = NULL; + +struct _FolderType { + char *name; + char *icon_name; + char *control_id; +}; +typedef struct _FolderType FolderType; + +struct _EFolderTypeRepositoryPrivate { + GHashTable *name_to_type; +}; + + +/* FIXME these are hardcoded for now. */ + +#ifdef USING_OAF +# define CALENDAR_CONTROL_ID "OAFIID:control:calendar:dd34ddae-25c6-486b-a8a8-3e8f0286b54c" +# define CONTACTS_CONTROL_ID "OAFIID:control:addressbook:851f883b-2fe7-4c94-a1e3-a1f2a7a03c49" +# define MAIL_CONTROL_ID "OAFIID:control:evolution-mail:833d5a71-a201-4a0e-b7e6-5475c5c4cb45" +#else +# define CALENDAR_CONTROL_ID "control:calendar" +# define CONTACTS_CONTROL_ID "control:addressbook" +# define MAIL_CONTROL_ID "control:evolution-mail" +#endif + + +/* FolderType handling. */ + +static FolderType * +folder_type_new (const char *name, + const char *icon_name, + const char *control_id) +{ + FolderType *new; + + new = g_new (FolderType, 1); + + new->name = g_strdup (name); + new->icon_name = g_strdup (icon_name); + new->control_id = g_strdup (control_id); + + return new; +} + +static void +folder_type_free (FolderType *folder_type) +{ + g_free (folder_type->name); + g_free (folder_type->icon_name); + g_free (folder_type->control_id); + + g_free (folder_type); +} + +static const FolderType * +get_folder_type (EFolderTypeRepository *folder_type_repository, + const char *type_name) +{ + EFolderTypeRepositoryPrivate *priv; + + priv = folder_type_repository->priv; + + return g_hash_table_lookup (priv->name_to_type, type_name); +} + +static gboolean +add_folder_type (EFolderTypeRepository *folder_type_repository, + const char *name, + const char *icon_name, + const char *control_id) +{ + EFolderTypeRepositoryPrivate *priv; + FolderType *folder_type; + + priv = folder_type_repository->priv; + + /* Make sure we don't add the same type twice. */ + if (get_folder_type (folder_type_repository, name) != NULL) + return FALSE; + + folder_type = folder_type_new (name, icon_name, control_id); + g_hash_table_insert (priv->name_to_type, folder_type->name, folder_type); + + return TRUE; +} + + +/* GtkObject methods. */ + +static void +hash_forall_free_folder_type (gpointer key, + gpointer value, + gpointer data) +{ + FolderType *folder_type; + + folder_type = (FolderType *) value; + folder_type_free (folder_type); +} + +static void +destroy (GtkObject *object) +{ + EFolderTypeRepository *folder_type_repository; + EFolderTypeRepositoryPrivate *priv; + + folder_type_repository = E_FOLDER_TYPE_REPOSITORY (object); + priv = folder_type_repository->priv; + + g_hash_table_foreach (priv->name_to_type, hash_forall_free_folder_type, NULL); + g_hash_table_destroy (priv->name_to_type); + + g_free (priv); + + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + + +static void +class_init (EFolderTypeRepositoryClass *class) +{ + GtkObjectClass *object_class; + + object_class = GTK_OBJECT_CLASS (class); + object_class->destroy = destroy; + + parent_class = gtk_type_class (gtk_object_get_type ()); +} + +static void +init (EFolderTypeRepository *folder_type_repository) +{ + EFolderTypeRepositoryPrivate *priv; + + priv = g_new (EFolderTypeRepositoryPrivate, 1); + priv->name_to_type = g_hash_table_new (g_str_hash, g_str_equal); + + folder_type_repository->priv = priv; +} + + +void +e_folder_type_repository_construct (EFolderTypeRepository *folder_type_repository) +{ + g_return_if_fail (folder_type_repository != NULL); + g_return_if_fail (E_IS_FOLDER_TYPE_REPOSITORY (folder_type_repository)); + + GTK_OBJECT_UNSET_FLAGS (GTK_OBJECT (folder_type_repository), GTK_FLOATING); + + /* FIXME these are hardcoded for now. */ + + add_folder_type (folder_type_repository, + "mail", "evolution-inbox.png", MAIL_CONTROL_ID); + add_folder_type (folder_type_repository, + "calendar", "evolution-calendar.png", CALENDAR_CONTROL_ID); + add_folder_type (folder_type_repository, + "contacts", "evolution-contacts.png", CONTACTS_CONTROL_ID); +} + +EFolderTypeRepository * +e_folder_type_repository_new (void) +{ + EFolderTypeRepository *new; + + new = gtk_type_new (e_folder_type_repository_get_type ()); + + e_folder_type_repository_construct (new); + + return new; +} + + +const char * +e_folder_type_repository_get_icon_for_type (EFolderTypeRepository *folder_type_repository, + const char *type_name) +{ + const FolderType *folder_type; + + g_return_val_if_fail (folder_type_repository != NULL, NULL); + g_return_val_if_fail (E_IS_FOLDER_TYPE_REPOSITORY (folder_type_repository), NULL); + g_return_val_if_fail (type_name != NULL, NULL); + + folder_type = get_folder_type (folder_type_repository, type_name); + return folder_type->icon_name; +} + +const char * +e_folder_type_repository_get_control_id_for_type (EFolderTypeRepository *folder_type_repository, + const char *type_name) +{ + const FolderType *folder_type; + + g_return_val_if_fail (folder_type_repository != NULL, NULL); + g_return_val_if_fail (E_IS_FOLDER_TYPE_REPOSITORY (folder_type_repository), NULL); + g_return_val_if_fail (type_name != NULL, NULL); + + folder_type = get_folder_type (folder_type_repository, type_name); + return folder_type->control_id; +} + + +E_MAKE_TYPE (e_folder_type_repository, "EFolderTypeRepository", EFolderTypeRepository, + class_init, init, PARENT_TYPE) diff --git a/shell/e-folder-type-repository.h b/shell/e-folder-type-repository.h new file mode 100644 index 0000000000..cdc72e3540 --- /dev/null +++ b/shell/e-folder-type-repository.h @@ -0,0 +1,73 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-folder-type-repository.h + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +#ifndef _E_FOLDER_TYPE_REPOSITORY_H_ +#define _E_FOLDER_TYPE_REPOSITORY_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gtk/gtkobject.h> + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define E_TYPE_FOLDER_TYPE_REPOSITORY (e_folder_type_repository_get_type ()) +#define E_FOLDER_TYPE_REPOSITORY(obj) (GTK_CHECK_CAST ((obj), E_TYPE_FOLDER_TYPE_REPOSITORY, EFolderTypeRepository)) +#define E_FOLDER_TYPE_REPOSITORY_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_FOLDER_TYPE_REPOSITORY, EFolderTypeRepositoryClass)) +#define E_IS_FOLDER_TYPE_REPOSITORY(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_FOLDER_TYPE_REPOSITORY)) +#define E_IS_FOLDER_TYPE_REPOSITORY_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_FOLDER_TYPE_REPOSITORY)) + + +typedef struct _EFolderTypeRepository EFolderTypeRepository; +typedef struct _EFolderTypeRepositoryPrivate EFolderTypeRepositoryPrivate; +typedef struct _EFolderTypeRepositoryClass EFolderTypeRepositoryClass; + +struct _EFolderTypeRepository { + GtkObject parent; + + EFolderTypeRepositoryPrivate *priv; +}; + +struct _EFolderTypeRepositoryClass { + GtkObjectClass parent_class; +}; + + +GtkType e_folder_type_repository_get_type (void); +void e_folder_type_repository_construct (EFolderTypeRepository *folder_type_repository); +EFolderTypeRepository *e_folder_type_repository_new (void); + +const char *e_folder_type_repository_get_icon_for_type (EFolderTypeRepository *folder_type_repository, + const char *type_name); +const char *e_folder_type_repository_get_control_id_for_type (EFolderTypeRepository *folder_type_repository, + const char *type_name); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _E_FOLDER_TYPE_REPOSITORY_H_ */ diff --git a/shell/e-folder.c b/shell/e-folder.c index ba6e10b22e..c5be881180 100644 --- a/shell/e-folder.c +++ b/shell/e-folder.c @@ -1,266 +1,275 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - -/* - * e-folder.c: Abstract class for Evolution folders +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-folder.c + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. * - * Author: - * Miguel de Icaza (miguel@helixcode.com) + * 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. * - * (C) 2000 Helix Code, Inc. + * Author: Ettore Perazzoli */ - +#ifdef HAVE_CONFIG_H #include <config.h> +#endif + +#include <gtk/gtkobject.h> #include <gtk/gtksignal.h> -#include <libgnome/libgnome.h> + #include "e-util/e-util.h" + #include "e-folder.h" -#define PARENT_TYPE gtk_object_get_type () + +#define PARENT_TYPE GTK_TYPE_OBJECT +static GtkObjectClass *parent_class = NULL; -static GtkObjectClass *parent_class; +struct _EFolderPrivate { + char *name; + char *type; + char *description; +}; -#define EFC(o) E_FOLDER_CLASS (GTK_OBJECT (o)->klass) +#define EF_CLASS(obj) \ + E_FOLDER_CLASS (GTK_OBJECT (obj)->klass) + enum { CHANGED, LAST_SIGNAL }; -static guint efolder_signals [LAST_SIGNAL] = { 0, }; -static void -e_folder_destroy (GtkObject *object) +static guint signals[LAST_SIGNAL] = { 0 }; + + +/* EFolder methods. */ + +static gboolean +save_info (EFolder *folder) { - EFolder *efolder = E_FOLDER (object); - - if (efolder->uri) - g_free (efolder->uri); - - if (efolder->desc) - g_free (efolder->desc); - - if (efolder->home_page) - g_free (efolder->home_page); - - parent_class->destroy (object); + g_warning ("`%s' does not implement `EFolder::save_info()'", + gtk_type_name (GTK_OBJECT_TYPE (folder))); + return FALSE; } -static void -e_folder_class_init (GtkObjectClass *object_class) +static gboolean +load_info (EFolder *folder) { - parent_class = gtk_type_class (PARENT_TYPE); - - object_class->destroy = e_folder_destroy; - - efolder_signals [CHANGED] = - gtk_signal_new ("changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EFolderClass, changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, - 0); - - /* Register our signals */ - gtk_object_class_add_signals ( - object_class, efolder_signals, LAST_SIGNAL); + g_warning ("`%s' does not implement `EFolder::load_info()'", + gtk_type_name (GTK_OBJECT_TYPE (folder))); + return FALSE; } -static void -e_folder_init (GtkObject *object) +static gboolean +remove (EFolder *folder) { + g_warning ("`%s' does not implement `EFolder::remove()'", + gtk_type_name (GTK_OBJECT_TYPE (folder))); + return FALSE; } -E_MAKE_TYPE (e_folder, "EFolder", EFolder, e_folder_class_init, e_folder_init, PARENT_TYPE) - -void -e_folder_set_uri (EFolder *efolder, const char *uri) +static const char * +get_physical_uri (EFolder *folder) { - g_return_if_fail (efolder != NULL); - g_return_if_fail (E_IS_FOLDER (efolder)); - g_return_if_fail (uri != NULL); - - if (efolder->uri) - g_free (efolder->uri); - - efolder->uri = g_strdup (uri); + g_warning ("`%s' does not implement `EFolder::remove()'", + gtk_type_name (GTK_OBJECT_TYPE (folder))); + return NULL; } -const char * -e_folder_get_uri (EFolder *efolder) + +/* GtkObject methods. */ + +static void +destroy (GtkObject *object) { - g_return_val_if_fail (efolder != NULL, NULL); - g_return_val_if_fail (E_IS_FOLDER (efolder), NULL); + EFolder *folder; + EFolderPrivate *priv; + + folder = E_FOLDER (object); + priv = folder->priv; + + g_free (priv->name); + g_free (priv->type); + g_free (priv->description); - return efolder->uri; + g_free (priv); + + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); } -void -e_folder_set_description (EFolder *efolder, const char *desc) + +static void +class_init (EFolderClass *klass) { - g_return_if_fail (efolder != NULL); - g_return_if_fail (E_IS_FOLDER (efolder)); - g_return_if_fail (desc != NULL); - - if (efolder->desc) - g_free (efolder->desc); - - efolder->desc = g_strdup (desc); + GtkObjectClass *object_class; + + parent_class = gtk_type_class (gtk_object_get_type ()); + + object_class = GTK_OBJECT_CLASS (klass); + object_class->destroy = destroy; + + signals[CHANGED] = gtk_signal_new ("changed", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (EFolderClass, changed), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); + + klass->save_info = save_info; + klass->load_info = load_info; + klass->remove = remove; + klass->get_physical_uri = get_physical_uri; } -const char * -e_folder_get_description (EFolder *efolder) +static void +init (EFolder *folder) { - g_return_val_if_fail (efolder != NULL, NULL); - g_return_val_if_fail (E_IS_FOLDER (efolder), NULL); + EFolderPrivate *priv; + + priv = g_new (EFolderPrivate, 1); + priv->type = NULL; + priv->name = NULL; + priv->description = NULL; - return efolder->desc; + folder->priv = priv; } + void -e_folder_set_home_page (EFolder *efolder, const char *home_page) +e_folder_construct (EFolder *folder, + const char *name, + const char *type, + const char *description) { - g_return_if_fail (efolder != NULL); - g_return_if_fail (E_IS_FOLDER (efolder)); - g_return_if_fail (home_page != NULL); - - if (efolder->home_page) - g_free (efolder->home_page); - - efolder->home_page = g_strdup (home_page); -} + EFolderPrivate *priv; -const char * -e_folder_get_home_page (EFolder *efolder) -{ - g_return_val_if_fail (efolder != NULL, NULL); - g_return_val_if_fail (E_IS_FOLDER (efolder), NULL); + g_return_if_fail (folder != NULL); + g_return_if_fail (E_IS_FOLDER (folder)); + g_return_if_fail (name != NULL); + g_return_if_fail (type != NULL); + g_return_if_fail (description != NULL); - return efolder->home_page; -} + GTK_OBJECT_UNSET_FLAGS (GTK_OBJECT (folder), GTK_FLOATING); -const char * -e_folder_get_type_name (EFolder *efolder) -{ - g_return_val_if_fail (efolder != NULL, NULL); - g_return_val_if_fail (E_IS_FOLDER (efolder), NULL); - - switch (efolder->type){ - case E_FOLDER_MAIL: - return _("A folder containing mail items"); - - case E_FOLDER_CONTACTS: - return _("A folder containing contacts"); - - case E_FOLDER_CALENDAR: - return _("A folder containing calendar entries"); - - case E_FOLDER_TASKS: - return _("A folder containing tasks"); - - default: - g_assert_not_reached (); - } + priv = folder->priv; - return NULL; + priv->name = g_strdup (name); + priv->type = g_strdup (type); + priv->description = g_strdup (description); } - -EFolderType -e_folder_get_folder_type (EFolder *efolder) +EFolder * +e_folder_new (const char *name, + const char *type, + const char *description) { - g_return_val_if_fail (efolder != NULL, E_FOLDER_OTHER); - g_return_val_if_fail (E_IS_FOLDER (efolder), E_FOLDER_OTHER); - - return (efolder->type); -} + EFolder *folder; + 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 = gtk_type_new (E_TYPE_FOLDER); + e_folder_construct (folder, name, type, description); -void -e_folder_construct (EFolder *efolder, EFolderType type, - const char *uri, const char *name, - const char *desc, const char *home_page, - const char *view_name) + return folder; +} + + +const char * +e_folder_get_name (EFolder *folder) { - g_return_if_fail (efolder != NULL); - g_return_if_fail (E_IS_FOLDER (efolder)); - - /* EFolders are self-owned */ - GTK_OBJECT_UNSET_FLAGS (GTK_OBJECT (efolder), GTK_FLOATING); - - if (uri) - efolder->uri = g_strdup (uri); - if (name) - efolder->name = g_strdup (name); - if (desc) - efolder->desc = g_strdup (desc); - if (home_page) - efolder->home_page = g_strdup (home_page); - if (view_name) - efolder->view_name = g_strdup (view_name); - - efolder->type = type; + g_return_val_if_fail (folder != NULL, NULL); + g_return_val_if_fail (E_IS_FOLDER (folder), NULL); + + return folder->priv->name; } -EFolder * -e_folder_new (EFolderType type, - const char *uri, const char *name, - const char *desc, const char *home_page, - const char *view_name) +const char * +e_folder_get_type_string (EFolder *folder) { - EFolder *efolder; - - efolder = gtk_type_new (e_folder_get_type ()); + g_return_val_if_fail (folder != NULL, NULL); + g_return_val_if_fail (E_IS_FOLDER (folder), NULL); - e_folder_construct (efolder, type, uri, name, desc, home_page, view_name); - return efolder; + return folder->priv->type; } const char * -e_folder_get_name (EFolder *efolder) +e_folder_get_description (EFolder *folder) { - g_return_val_if_fail (efolder != NULL, NULL); - g_return_val_if_fail (E_IS_FOLDER (efolder), NULL); + g_return_val_if_fail (folder != NULL, NULL); + g_return_val_if_fail (E_IS_FOLDER (folder), NULL); - return efolder->name; + return folder->priv->description; } + void -e_folder_set_name (EFolder *efolder, const char *name) +e_folder_set_name (EFolder *folder, + const char *name) { - g_return_if_fail (efolder != NULL); - g_return_if_fail (E_IS_FOLDER (efolder)); + g_return_if_fail (folder != NULL); + g_return_if_fail (E_IS_FOLDER (folder)); + g_return_if_fail (name != NULL); - if (efolder->name) - g_free (efolder->name); + g_free (folder->priv->name); + folder->priv->name = g_strdup (name); - efolder->name = g_strdup (name); + gtk_signal_emit (GTK_OBJECT (folder), signals[CHANGED]); } -const char * -e_folder_get_view_name (EFolder *efolder) +void +e_folder_set_type_string (EFolder *folder, + const char *type) { - g_return_val_if_fail (efolder != NULL, NULL); - g_return_val_if_fail (E_IS_FOLDER (efolder), NULL); + g_return_if_fail (folder != NULL); + g_return_if_fail (E_IS_FOLDER (folder)); + g_return_if_fail (type != NULL); + + g_free (folder->priv->type); + folder->priv->type = g_strdup (type); - return efolder->view_name; + gtk_signal_emit (GTK_OBJECT (folder), signals[CHANGED]); } void -e_folder_set_view_name (EFolder *efolder, const char *view_name) +e_folder_set_description (EFolder *folder, + const char *description) { - g_return_if_fail (efolder != NULL); - g_return_if_fail (E_IS_FOLDER (efolder)); + g_return_if_fail (folder != NULL); + g_return_if_fail (E_IS_FOLDER (folder)); + g_return_if_fail (description != NULL); - if (efolder->view_name) - g_free (efolder->view_name); + g_free (folder->priv->description); + folder->priv->description = g_strdup (description); - efolder->view_name = g_strdup (view_name); - - gtk_signal_emit (GTK_OBJECT (efolder), - efolder_signals [CHANGED]); + gtk_signal_emit (GTK_OBJECT (folder), signals[CHANGED]); } + +const char * +e_folder_get_physical_uri (EFolder *folder) +{ + g_return_val_if_fail (folder != NULL, NULL); + g_return_val_if_fail (E_IS_FOLDER (folder), NULL); + + return (* EF_CLASS (folder)->get_physical_uri) (folder); +} + +E_MAKE_TYPE (e_folder, "EFolder", EFolder, class_init, init, PARENT_TYPE) diff --git a/shell/e-folder.h b/shell/e-folder.h index fe5e2d6cd1..cf49c68864 100644 --- a/shell/e-folder.h +++ b/shell/e-folder.h @@ -1,93 +1,92 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - - + /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-folder.h + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ #ifndef _E_FOLDER_H_ #define _E_FOLDER_H_ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif #include <gtk/gtkobject.h> -#include <gdk-pixbuf/gdk-pixbuf.h> - -#define E_FOLDER_TYPE (e_folder_get_type ()) -#define E_FOLDER(o) (GTK_CHECK_CAST ((o), E_FOLDER_TYPE, EFolder)) -#define E_FOLDER_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_FOLDER_TYPE, EFolderClass)) -#define E_IS_FOLDER(o) (GTK_CHECK_TYPE ((o), E_FOLDER_TYPE)) -#define E_IS_FOLDER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_FOLDER_TYPE)) +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ -typedef enum { - E_FOLDER_DND_AS_FORWARD, - E_FOLDER_DND_AS_MOVE_COPY -} EFolderDragDropAction; +#define E_TYPE_FOLDER (e_folder_get_type ()) +#define E_FOLDER(obj) (GTK_CHECK_CAST ((obj), E_TYPE_FOLDER, EFolder)) +#define E_FOLDER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_FOLDER, EFolderClass)) +#define E_IS_FOLDER(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_FOLDER)) +#define E_IS_FOLDER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_FOLDER)) -typedef enum { - E_FOLDER_SUMMARY, - E_FOLDER_MAIL, - E_FOLDER_CONTACTS, - E_FOLDER_CALENDAR, - E_FOLDER_TASKS, - E_FOLDER_OTHER -} EFolderType; + +typedef struct _EFolder EFolder; +typedef struct _EFolderPrivate EFolderPrivate; +typedef struct _EFolderClass EFolderClass; struct _EFolder { - GtkObject parent_object; - - EFolderType type; - - /* - * General properties - */ - char *uri; /* Location */ - char *name; /* Short name */ - char *desc; /* Full description */ - char *home_page; /* Home page for this folder */ - - /* - * Administration properties - */ - char *view_name; /* View name */ -}; -typedef struct _EFolder EFolder; - -struct _EFolderClass { - GtkObjectClass parent_class; + GtkObject parent; - /* - * Notifies views of visible changes in the Efolder - */ - void (*changed) (EFolder *efolder); + EFolderPrivate *priv; }; -typedef struct _EFolderClass EFolderClass; -GtkType e_folder_get_type (void); -void e_folder_construct (EFolder *efolder, EFolderType type, - const char *uri, const char *name, - const char *desc, const char *home_page, - const char *view_name); -EFolder *e_folder_new (EFolderType type, - const char *uri, const char *name, - const char *desc, const char *home_page, - const char *view_name); +struct _EFolderClass { + GtkObjectClass parent_class; -void e_folder_set_uri (EFolder *efolder, const char *uri); -const char *e_folder_get_uri (EFolder *efolder); + /* Virtual methods. */ + gboolean (* save_info) (EFolder *folder); + gboolean (* load_info) (EFolder *folder); + gboolean (* remove) (EFolder *folder); + const char * (* get_physical_uri) (EFolder *folder); -void e_folder_set_description (EFolder *efolder, const char *desc); -const char *e_folder_get_description (EFolder *efolder); + /* Signals. */ + void (* changed) (EFolder *folder); +}; -void e_folder_set_home_page (EFolder *efolder, const char *desc); -const char *e_folder_get_home_page (EFolder *efolder); + +GtkType e_folder_get_type (void); +void e_folder_construct (EFolder *folder, + const char *name, + const char *type, + const char *description); +EFolder *e_folder_new (const char *name, + const char *type, + const char *description); -const char *e_folder_get_name (EFolder *efolder); -void e_folder_set_name (EFolder *efolder, const char *name); +const char *e_folder_get_physical_uri (EFolder *folder); -const char *e_folder_get_view_name (EFolder *efolder); -void e_folder_set_view_name (EFolder *efolder, const char *view_name); +const char *e_folder_get_name (EFolder *folder); +const char *e_folder_get_type_string (EFolder *folder); +const char *e_folder_get_description (EFolder *folder); -const char *e_folder_get_type_name (EFolder *efolder); +void e_folder_set_name (EFolder *folder, const char *name); +void e_folder_set_type_string (EFolder *folder, const char *type); +void e_folder_set_description (EFolder *folder, const char *description); -EFolderType e_folder_get_folder_type (EFolder *efolder); +#ifdef __cplusplus +} +#endif /* __cplusplus */ #endif /* _E_FOLDER_H_ */ - diff --git a/shell/e-local-folder.c b/shell/e-local-folder.c new file mode 100644 index 0000000000..8ff2a2eb96 --- /dev/null +++ b/shell/e-local-folder.c @@ -0,0 +1,223 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-local-folder.c + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +/* The metafile goes like this: + + <?xml version="1.0"?> + <efolder> + <type>mail</type> + <description>This is the folder where I store mail from my gf</description> + <homepage>http://www.somewhere.net</homepage> + </efolder> + + FIXME: Do we want to use a namespace for this? + FIXME: Do we want to have an internationalized description? + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gnome-xml/parser.h> + +#include "e-util/e-util.h" +#include "e-util/e-xml-utils.h" + +#include "e-local-folder.h" + + +#define PARENT_TYPE E_TYPE_FOLDER +static EFolderClass *parent_class = NULL; + +#define URI_PREFIX "file://" +#define URI_PREFIX_LEN 7 + +#define METADATA_FILE_NAME "folder-metadata.xml" +#define METADATA_FILE_NAME_LEN 19 + + +static const char * +get_string_value (xmlNode *node, + const char *name) +{ + xmlNode *p; + + p = e_xml_get_child_by_name (node, (xmlChar *) name); + if (p == NULL) + return NULL; + + p = e_xml_get_child_by_name (p, (xmlChar *) "text"); + if (p == NULL) + return NULL; + + return (const char *) p->content; +} + +static gboolean +construct_loading_metadata (ELocalFolder *local_folder, + const char *path) +{ + EFolder *folder; + xmlDoc *doc; + xmlNode *root; + const char *type; + const char *description; + char *metadata_path; + + folder = E_FOLDER (local_folder); + + metadata_path = g_concat_dir_and_file (path, METADATA_FILE_NAME); + + doc = xmlParseFile (metadata_path); + if (doc == NULL) { + g_free (metadata_path); + return FALSE; + } + + root = xmlDocGetRootElement (doc); + if (root == NULL || strcmp (root->name, "efolder") != 0) { + g_free (metadata_path); + xmlFreeDoc (doc); + return FALSE; + } + + type = get_string_value (root, "type"); + description = get_string_value (root, "description"); + + e_folder_construct (folder, g_basename (path), type, description); + + xmlFreeDoc (doc); + + local_folder->physical_uri = g_strconcat (URI_PREFIX, path, NULL); + + g_free (metadata_path); + + return TRUE; +} + +static gboolean +save_metadata (ELocalFolder *local_folder) +{ + EFolder *folder; + xmlDoc *doc; + xmlNode *root; + const char *physical_path; + + folder = E_FOLDER (local_folder); + + doc = xmlNewDoc ((xmlChar *) "1.0"); + root = xmlNewDocNode (doc, NULL, (xmlChar *) "efolder", NULL); + xmlDocSetRootElement (doc, root); + + xmlNewChild (root, NULL, (xmlChar *) "type", (xmlChar *) e_folder_get_type_string (folder)); + xmlNewChild (root, NULL, (xmlChar *) "description", (xmlChar *) e_folder_get_description (folder)); + + physical_path = local_folder->physical_uri + URI_PREFIX_LEN - 1; + + if (xmlSaveFile (physical_path, doc) < 0) { + xmlFreeDoc (doc); + return FALSE; + } + + xmlFreeDoc (doc); + return TRUE; +} + + +/* EFolder methods. */ + +static const char * +get_physical_uri (EFolder *folder) +{ + ELocalFolder *local_folder; + + local_folder = E_LOCAL_FOLDER (folder); + return local_folder->physical_uri; +} + + +/* GtkObject methods. */ + +static void +destroy (GtkObject *object) +{ + ELocalFolder *folder; + + folder = E_LOCAL_FOLDER (object); + + g_free (folder->physical_uri); + + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + + +static void +class_init (ELocalFolderClass *klass) +{ + GtkObjectClass *object_class; + EFolderClass *folder_class; + + parent_class = gtk_type_class (e_folder_get_type ()); + + object_class = GTK_OBJECT_CLASS (klass); + object_class->destroy = destroy; + + folder_class = E_FOLDER_CLASS (klass); + folder_class->get_physical_uri = get_physical_uri; +} + +static void +init (ELocalFolder *local_folder) +{ + local_folder->physical_uri = NULL; +} + + +EFolder * +e_local_folder_new_from_path (const char *path) +{ + EFolder *folder; + + g_return_val_if_fail (g_path_is_absolute (path), NULL); + + folder = gtk_type_new (e_local_folder_get_type ()); + + if (! construct_loading_metadata (E_LOCAL_FOLDER (folder), path)) { + gtk_object_unref (GTK_OBJECT (folder)); + return NULL; + } + + return folder; +} + +gboolean +e_local_folder_save (ELocalFolder *local_folder) +{ + g_return_val_if_fail (local_folder != NULL, FALSE); + g_return_val_if_fail (E_IS_LOCAL_FOLDER (local_folder), FALSE); + + return save_metadata (local_folder); +} + + +E_MAKE_TYPE (e_local_folder, "ELocalFolder", ELocalFolder, class_init, init, PARENT_TYPE) diff --git a/shell/e-local-folder.h b/shell/e-local-folder.h new file mode 100644 index 0000000000..6092532791 --- /dev/null +++ b/shell/e-local-folder.h @@ -0,0 +1,68 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-local-folder.h + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +#ifndef _E_LOCAL_FOLDER_H_ +#define _E_LOCAL_FOLDER_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gtk/gtkobject.h> + +#include "e-folder.h" + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define E_TYPE_LOCAL_FOLDER (e_local_folder_get_type ()) +#define E_LOCAL_FOLDER(obj) (GTK_CHECK_CAST ((obj), E_TYPE_LOCAL_FOLDER, ELocalFolder)) +#define E_LOCAL_FOLDER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_LOCAL_FOLDER, ELocalFolderClass)) +#define E_IS_LOCAL_FOLDER(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_LOCAL_FOLDER)) +#define E_IS_LOCAL_FOLDER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_LOCAL_FOLDER)) + +typedef struct _ELocalFolder ELocalFolder; +typedef struct _ELocalFolderClass ELocalFolderClass; + +struct _ELocalFolder { + EFolder parent; + + char *physical_uri; +}; + +struct _ELocalFolderClass { + EFolderClass parent_class; +}; + + +GtkType e_local_folder_get_type (void); +EFolder *e_local_folder_new_from_path (const char *physical_path); +gboolean e_local_folder_save (ELocalFolder *local_folder); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __E_LOCAL_FOLDER_H__ */ diff --git a/shell/e-local-storage.c b/shell/e-local-storage.c new file mode 100644 index 0000000000..d4d30d67c5 --- /dev/null +++ b/shell/e-local-storage.c @@ -0,0 +1,342 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-local-storage.c + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +/* FIXMEs: + * + * - If we have `.' or `..' as path elements, we lose. + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#define _POSIX_SOURCE /* Yuck. */ +#include <dirent.h> + +#include <string.h> +#include <sys/param.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <gnome.h> + +#include "e-util/e-util.h" +#include "e-local-folder.h" + +#include "e-local-storage.h" + + +#define PARENT_TYPE E_TYPE_STORAGE +static EStorageClass *parent_class = NULL; + +#define SUBFOLDER_DIR_NAME "subfolders" +#define SUBFOLDER_DIR_NAME_LEN 10 + +struct _ELocalStoragePrivate { + char *base_path; +}; + + +/* Utility functions. */ + +#if 0 +/* Translate a storage path into a real path on the file system. */ +static char * +get_real_path (ELocalStorage *local_storage, + const char *path) +{ + EStorage *storage; + ELocalStoragePrivate *priv; + const char *p, *newp; + char *dp; + char *real_path; + int real_path_len; + int base_path_len; + + storage = E_STORAGE (local_storage); + priv = local_storage->priv; + + /* @path is always absolute, so it starts with a slash. The base class should + make sure this is the case; if not, it's broken. */ + g_assert (*path != G_DIR_SEPARATOR); + path++; + + /* Calculate the length of the real path. */ + + real_path_len = strlen (path); + real_path_len++; /* For the ending zero. */ + + base_path_len = strlen (priv->base_path); + real_path_len += base_path_len; + real_path_len++; /* For the separating slash. */ + + /* Take account for the fact that we need to translate every separator into + `children/'. */ + p = path; + while (1) { + newp = strchr (p, G_DIR_SEPARATOR); + if (newp == NULL) + break; + + real_path_len += SUBFOLDER_DIR_NAME_LEN; + real_path_len++; /* For the separating slash. */ + + /* Skip consecutive slashes. */ + while (*newp == G_DIR_SEPARATOR) + newp++; + + p = newp; + }; + + real_path = g_malloc (real_path_len); + dp = real_path; + + memcpy (dp, priv->base_path, base_path_len); + dp += base_path_len; + *(dp++) = G_DIR_SEPARATOR; + + /* Copy the mangled path. */ + p = path; + while (1) { + newp = strchr (p, G_DIR_SEPARATOR); + if (newp == NULL) + break; + + memcpy (dp, p, newp - p + 1); /* `+ 1' to copy the slash too. */ + dp += newp - p + 1; + + memcpy (dp, SUBFOLDER_DIR_NAME, SUBFOLDER_DIR_NAME_LEN); + dp += SUBFOLDER_DIR_NAME_LEN; + + *(dp++) = G_DIR_SEPARATOR; + + /* Skip consecutive slashes. */ + while (*newp == G_DIR_SEPARATOR) + newp++; + + p = newp; + } + + return real_path; +} +#endif + +static gboolean +load_folders (ELocalStorage *local_storage, + const char *parent_path, + const char *path, + const char *physical_path) +{ + DIR *dir; + char *subfolder_directory_path; + struct dirent *dirent; + + if (parent_path == NULL) { + /* On the top level, we don't have any folders and, consequently, no + subfolder directory. */ + + subfolder_directory_path = g_strdup (physical_path); + } else { + EFolder *folder; + + /* Otherwise, we have to load the corresponding folder. */ + + folder = e_local_folder_new_from_path (physical_path); + if (folder == NULL) + return FALSE; + + e_storage_new_folder (E_STORAGE (local_storage), parent_path, folder); + + subfolder_directory_path = g_concat_dir_and_file (physical_path, SUBFOLDER_DIR_NAME); + } + + /* Now scan the subfolders and load them. The subfolders are represented by + directories under the "SUBFOLDER_DIR_NAME" directory. */ + + dir = opendir (subfolder_directory_path); + + if (dir == NULL) { + g_free (subfolder_directory_path); + return FALSE; + } + + dirent = g_malloc (sizeof (struct dirent) + MAXPATHLEN + 1); + + while (1) { + struct stat file_stat; + struct dirent *result; + char *file_path; + char *new_path; + + if (readdir_r (dir, dirent, &result) != 0) + break; + if (result == NULL) + break; + + if (strcmp (result->d_name, ".") == 0 || strcmp (result->d_name, "..") == 0) + continue; + + file_path = g_concat_dir_and_file (subfolder_directory_path, + result->d_name); + + if (stat (file_path, &file_stat) < 0) { + g_free (file_path); + continue; + } + if (! S_ISDIR (file_stat.st_mode)) { + g_free (file_path); + continue; + } + + new_path = g_concat_dir_and_file (path, result->d_name); + + load_folders (local_storage, path, new_path, file_path); + + g_free (file_path); + g_free (new_path); + } + + g_free (dirent); + closedir (dir); + g_free (subfolder_directory_path); + + return TRUE; +} + +static gboolean +load_all_folders (ELocalStorage *local_storage) +{ + const char *base_path; + + base_path = e_local_storage_get_base_path (local_storage); + + return load_folders (local_storage, NULL, G_DIR_SEPARATOR_S, base_path); +} + + +/* GtkObject methods. */ + +static void +destroy (GtkObject *object) +{ + ELocalStorage *local_storage; + ELocalStoragePrivate *priv; + + local_storage = E_LOCAL_STORAGE (object); + priv = local_storage->priv; + + g_free (priv->base_path); + g_free (priv); + + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + + +/* EStorage methods. */ + +static const char * +get_name (EStorage *storage) +{ + /* FIXME this sucks. */ + return "local"; +} + + +/* Initialization. */ + +static void +class_init (ELocalStorageClass *class) +{ + EStorageClass *storage_class; + GtkObjectClass *object_class; + + parent_class = gtk_type_class (e_storage_get_type ()); + + object_class = GTK_OBJECT_CLASS (class); + object_class->destroy = destroy; + + storage_class = E_STORAGE_CLASS (class); + storage_class->get_name = get_name; +} + +static void +init (ELocalStorage *local_storage) +{ + ELocalStoragePrivate *priv; + + priv = g_new (ELocalStoragePrivate, 1); + + priv->base_path = NULL; + + local_storage->priv = priv; +} + + +static gboolean +construct (ELocalStorage *local_storage, + const char *base_path) +{ + int base_path_len; + + e_storage_construct (E_STORAGE (local_storage)); + + base_path_len = strlen (base_path); + while (base_path_len > 0 && base_path[base_path_len - 1] == G_DIR_SEPARATOR) + base_path_len--; + + g_return_val_if_fail (base_path_len != 0, FALSE); + + local_storage->priv->base_path = g_strndup (base_path, base_path_len); + + return load_all_folders (local_storage); +} + +EStorage * +e_local_storage_open (const char *base_path) +{ + EStorage *new; + + g_return_val_if_fail (base_path != NULL, NULL); + + new = gtk_type_new (e_local_storage_get_type ()); + + if (! construct (E_LOCAL_STORAGE (new), base_path)) { + gtk_object_unref (GTK_OBJECT (new)); + return NULL; + } + + return new; +} + +const char * +e_local_storage_get_base_path (ELocalStorage *local_storage) +{ + g_return_val_if_fail (local_storage != NULL, NULL); + g_return_val_if_fail (E_IS_LOCAL_STORAGE (local_storage), NULL); + + return local_storage->priv->base_path; +} + + +E_MAKE_TYPE (e_local_storage, "ELocalStorage", ELocalStorage, class_init, init, PARENT_TYPE) diff --git a/shell/e-local-storage.h b/shell/e-local-storage.h new file mode 100644 index 0000000000..569216941e --- /dev/null +++ b/shell/e-local-storage.h @@ -0,0 +1,67 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-local-storage.h + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +#ifndef _E_LOCAL_STORAGE_H_ +#define _E_LOCAL_STORAGE_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "e-storage.h" + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define E_TYPE_LOCAL_STORAGE (e_local_storage_get_type ()) +#define E_LOCAL_STORAGE(obj) (GTK_CHECK_CAST ((obj), E_TYPE_LOCAL_STORAGE, ELocalStorage)) +#define E_LOCAL_STORAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_LOCAL_STORAGE, ELocalStorageClass)) +#define E_IS_LOCAL_STORAGE(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_LOCAL_STORAGE)) +#define E_IS_LOCAL_STORAGE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_LOCAL_STORAGE)) + +typedef struct _ELocalStorage ELocalStorage; +typedef struct _ELocalStoragePrivate ELocalStoragePrivate; +typedef struct _ELocalStorageClass ELocalStorageClass; + +struct _ELocalStorage { + EStorage parent; + + ELocalStoragePrivate *priv; +}; + +struct _ELocalStorageClass { + EStorageClass parent_class; +}; + + +GtkType e_local_storage_get_type (void); +EStorage *e_local_storage_open (const char *base_path); +const char *e_local_storage_get_base_path (ELocalStorage *storage); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __E_LOCAL_STORAGE_H__ */ diff --git a/shell/e-setup.c b/shell/e-setup.c new file mode 100644 index 0000000000..366022493e --- /dev/null +++ b/shell/e-setup.c @@ -0,0 +1,115 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-setup.c + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/* This needs to be a lot better. */ + +#include <glib.h> +#include <gnome.h> + +#include <errno.h> +#include <sys/stat.h> + +#include "e-util/e-gui-utils.h" + +#include "e-setup.h" + + +static gboolean +copy_default_stuff (const char *evolution_directory) +{ + GtkWidget *dialog; + GtkWidget *label1; + GtkWidget *label2; + GtkWidget *label3; + gboolean retval; + char *command; + int result; + + dialog = gnome_dialog_new (_("Evolution installation"), + GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, + NULL); + + label1 = gtk_label_new (_("This seems to be the first time you run Evolution.")); + label2 = gtk_label_new (_("Please click \"OK\" to install the Evolution user files under")); + label3 = gtk_label_new (evolution_directory); + + gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), label1, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), label2, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), label3, TRUE, TRUE, 0); + + gtk_widget_show (label1); + gtk_widget_show (label2); + gtk_widget_show (label3); + + result = gnome_dialog_run_and_close (GNOME_DIALOG (dialog)); + if (result != 0) + return FALSE; + + if (mkdir (evolution_directory, 0700)) { + e_notice (NULL, GNOME_MESSAGE_BOX_ERROR, + _("Cannot create the directory\n%s\nError: %s"), + evolution_directory, + g_strerror (errno)); + return FALSE; + } + + command = g_strconcat ("cp -r ", + EVOLUTION_DATADIR, + "/evolution/default_user/* ", + evolution_directory, + NULL); + + if (system (command) != 0) { + /* FIXME: Give more help. */ + e_notice (NULL, GNOME_MESSAGE_BOX_ERROR, + _("Cannot copy files into\n`%s'."), evolution_directory); + retval = FALSE; + } else { + e_notice (NULL, GNOME_MESSAGE_BOX_INFO, + _("Evolution files successfully installed.")); + retval = TRUE; + } + + g_free (command); + + return retval; +} + + +gboolean +e_setup (const char *evolution_directory) +{ + struct stat statinfo; + + if (stat (evolution_directory, &statinfo) != 0) + return copy_default_stuff (evolution_directory); + + if (! S_ISDIR (statinfo.st_mode)) { + e_notice (NULL, GNOME_MESSAGE_BOX_ERROR, + _("The file `%s' is not a directory.\n" + "Please remove it in order to allow installation\n" + "of the Evolution user files.")); + return FALSE; + } + + return TRUE; +} diff --git a/shell/e-setup.h b/shell/e-setup.h new file mode 100644 index 0000000000..a69d216b94 --- /dev/null +++ b/shell/e-setup.h @@ -0,0 +1,31 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-setup.h + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +#ifndef _E_SETUP_H +#define _E_SETUP_H + +#include <glib.h> + +gboolean e_setup (const char *evolution_directory); + +#endif /* _E_SETUP_H */ diff --git a/shell/e-shell-view-menu.c b/shell/e-shell-view-menu.c index 29f3db1376..d1fe6e959f 100644 --- a/shell/e-shell-view-menu.c +++ b/shell/e-shell-view-menu.c @@ -1,153 +1,100 @@ -/* - * E-shell-view-menu.c: Controls the shell view's menus. +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shell-view.c * - * This file provides API entry points for changing and updating - * the menus to reflect the status of Evolution. + * Copyright (C) 2000 Helix Code, Inc. * - * Authors: - * Miguel de Icaza (miguel@helixcode.com) + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. * - * (C) 2000 Helix Code, Inc. + * Authors: + * Miguel de Icaza + * Ettore Perazzoli */ #include <config.h> #include <gnome.h> + #include "e-shell-view.h" #include "e-shell-view-menu.h" -static void -esv_cmd_new_folder (GtkWidget *widget, EShellView *esv) -{ - e_shell_view_new_folder (esv); -} - -static void -esv_cmd_new_shortcut (GtkWidget *widget, EShellView *esv) -{ - e_shell_view_new_shortcut (esv); -} - -static void -esv_cmd_new_mail_message (GtkWidget *widget, EShellView *esv) -{ - e_shell_new_mail_message (esv->eshell); -} - -static void -esv_cmd_new_meeting_request (GtkWidget *widget, EShellView *esv) -{ - e_shell_new_meeting_request (esv->eshell); -} - -static void -esv_cmd_new_contact (GtkWidget *widget, EShellView *esv) -{ - e_shell_new_contact (esv->eshell); -} - -static void -esv_cmd_new_task (GtkWidget *widget, EShellView *esv) -{ - e_shell_new_task (esv->eshell); -} - -static void -esv_cmd_new_task_request (GtkWidget *widget, EShellView *esv) -{ - e_shell_new_task_request (esv->eshell); -} - -static void -esv_cmd_new_journal_entry (GtkWidget *widget, EShellView *esv) -{ - e_shell_new_journal_entry (esv->eshell); -} - -static void -esv_cmd_new_note (GtkWidget *widget, EShellView *esv) -{ - e_shell_new_note (esv->eshell); -} - -static void -esv_cmd_open_selected_items (GtkWidget *widget, EShellView *esv) -{ - printf ("Unimplemented open selected items\n"); -} - -static void -esv_cmd_save_as (GtkWidget *widget, EShellView *esv) -{ -} - -static void -quit_cmd (GtkWidget *widget, EShellView *esv) -{ - e_shell_quit (esv->eshell); -} - -static void -esv_cmd_close_open_items (GtkWidget *widget, EShellView *esv) -{ - printf ("Unimplemented function"); -} - -static void -esv_cmd_toggle_shortcut_bar (GtkWidget *widget, EShellView *esv) -{ - e_shell_view_toggle_shortcut_bar (esv); -} - -static void -esv_cmd_toggle_treeview (GtkWidget *widget, EShellView *esv) -{ - e_shell_view_toggle_treeview (esv); -} - +#define DEFINE_UNIMPLEMENTED(func) \ +static void \ +func (GtkWidget *widget, gpointer data) \ +{ \ + g_warning ("EShellView: %s: not implemented.", __FUNCTION__); \ +} \ + +DEFINE_UNIMPLEMENTED (command_new_folder) +DEFINE_UNIMPLEMENTED (command_new_shortcut) +DEFINE_UNIMPLEMENTED (command_new_mail_message) +DEFINE_UNIMPLEMENTED (command_new_meeting_request) +DEFINE_UNIMPLEMENTED (command_new_contact) +DEFINE_UNIMPLEMENTED (command_new_task) +DEFINE_UNIMPLEMENTED (command_new_task_request) +DEFINE_UNIMPLEMENTED (command_new_journal_entry) +DEFINE_UNIMPLEMENTED (command_new_note) +DEFINE_UNIMPLEMENTED (command_open_selected_items) +DEFINE_UNIMPLEMENTED (command_save_as) +DEFINE_UNIMPLEMENTED (command_quit) +DEFINE_UNIMPLEMENTED (command_close_open_items) +DEFINE_UNIMPLEMENTED (command_toggle_shortcut_bar) +DEFINE_UNIMPLEMENTED (command_toggle_treeview) /* - * Fixme + * FIXME * * This menu is actually pretty dynamic, it changes de values of various entries * depending on the current data being displayed * * This is currently only a placeholder. We need to figure what to do about this. */ -static GnomeUIInfo esv_menu_file_new [] = { +static GnomeUIInfo menu_file_new [] = { { GNOME_APP_UI_ITEM, N_("_Folder"), - NULL, esv_cmd_new_folder, NULL, + NULL, command_new_folder, NULL, NULL, 0, 0, 'e', GDK_CONTROL_MASK | GDK_SHIFT_MASK }, { GNOME_APP_UI_ITEM, N_("Evolution _Bar Shortcut"), - NULL, esv_cmd_new_shortcut, NULL, + NULL, command_new_shortcut, NULL, NULL, 0, 0, 'e', GDK_CONTROL_MASK | GDK_SHIFT_MASK }, GNOMEUIINFO_SEPARATOR, { GNOME_APP_UI_ITEM, N_("_Mail message"), - N_("Composes a new mail message"), esv_cmd_new_mail_message, NULL, + N_("Composes a new mail message"), command_new_mail_message, NULL, NULL, 0, 0, 'n', GDK_CONTROL_MASK | GDK_SHIFT_MASK }, { GNOME_APP_UI_ITEM, N_("_Appointment"), - N_("Composes a new mail message"), esv_cmd_new_mail_message, NULL, + N_("Composes a new mail message"), command_new_mail_message, NULL, NULL, 0, 0, 'a', GDK_CONTROL_MASK | GDK_SHIFT_MASK }, { GNOME_APP_UI_ITEM, N_("Meeting Re_quest"), NULL, - esv_cmd_new_meeting_request, NULL, + command_new_meeting_request, NULL, NULL, 0, 0, 'q', GDK_CONTROL_MASK | GDK_SHIFT_MASK }, { GNOME_APP_UI_ITEM, N_("_Contact"), NULL, - esv_cmd_new_contact, NULL, + command_new_contact, NULL, NULL, 0, 0, 'c', GDK_CONTROL_MASK | GDK_SHIFT_MASK }, { GNOME_APP_UI_ITEM, N_("_Task"), NULL, - esv_cmd_new_task, NULL, + command_new_task, NULL, NULL, 0, 0, 'k', GDK_CONTROL_MASK | GDK_SHIFT_MASK }, { GNOME_APP_UI_ITEM, N_("Task _Request"), NULL, - esv_cmd_new_task_request, NULL, + command_new_task_request, NULL, NULL, 0, 0, 'u', GDK_CONTROL_MASK | GDK_SHIFT_MASK }, { GNOME_APP_UI_ITEM, N_("_Journal Entry"), NULL, - esv_cmd_new_journal_entry, NULL, + command_new_journal_entry, NULL, NULL, 0, 0, 'j', GDK_CONTROL_MASK | GDK_SHIFT_MASK }, { GNOME_APP_UI_ITEM, N_("_Note"), NULL, - esv_cmd_new_note, NULL, + command_new_note, NULL, NULL, 0, 0, 'o', GDK_CONTROL_MASK | GDK_SHIFT_MASK }, GNOMEUIINFO_SEPARATOR, @@ -155,92 +102,77 @@ static GnomeUIInfo esv_menu_file_new [] = { GNOMEUIINFO_END }; -static GnomeUIInfo esv_menu_file_open [] = { +static GnomeUIInfo menu_file_open [] = { { GNOME_APP_UI_ITEM, N_("_Selected Items"), NULL, - esv_cmd_open_selected_items, NULL, + command_open_selected_items, NULL, NULL, 0, 0, 'o', GDK_CONTROL_MASK }, GNOMEUIINFO_END }; -static GnomeUIInfo esv_menu_folder [] = { +static GnomeUIInfo menu_folder [] = { { GNOME_APP_UI_ITEM, N_("_New Folder"), NULL, - esv_cmd_new_folder, NULL, + command_new_folder, NULL, NULL, 0, 0, 'e', GDK_CONTROL_MASK | GDK_SHIFT_MASK }, GNOMEUIINFO_END }; -static GnomeUIInfo esv_menu_file [] = { - GNOMEUIINFO_SUBTREE_STOCK (N_("_New"), esv_menu_file_new, GNOME_STOCK_MENU_NEW), - GNOMEUIINFO_SUBTREE_STOCK (N_("_Open"), esv_menu_file_open, GNOME_STOCK_MENU_NEW), - GNOMEUIINFO_ITEM_NONE (N_("Clos_e All Items"), N_("Closes all the open items"), esv_cmd_close_open_items), +static GnomeUIInfo menu_file [] = { + GNOMEUIINFO_SUBTREE_STOCK (N_("_New"), menu_file_new, GNOME_STOCK_MENU_NEW), + GNOMEUIINFO_SUBTREE_STOCK (N_("_Open"), menu_file_open, GNOME_STOCK_MENU_NEW), + GNOMEUIINFO_ITEM_NONE (N_("Clos_e All Items"), N_("Closes all the open items"), command_close_open_items), GNOMEUIINFO_SEPARATOR, - GNOMEUIINFO_MENU_SAVE_AS_ITEM (esv_cmd_save_as, NULL), + GNOMEUIINFO_MENU_SAVE_AS_ITEM (command_save_as, NULL), GNOMEUIINFO_SEPARATOR, - GNOMEUIINFO_SUBTREE (N_("_Folder"), esv_menu_folder), + GNOMEUIINFO_SUBTREE (N_("_Folder"), menu_folder), GNOMEUIINFO_SEPARATOR, - GNOMEUIINFO_MENU_EXIT_ITEM(quit_cmd, NULL), + GNOMEUIINFO_MENU_EXIT_ITEM(command_quit, NULL), GNOMEUIINFO_END }; -static GnomeUIInfo esv_menu_edit [] = { +static GnomeUIInfo menu_edit [] = { GNOMEUIINFO_END }; -static GnomeUIInfo esv_menu_view [] = { +static GnomeUIInfo menu_view [] = { { GNOME_APP_UI_ITEM, N_("_Toggle Shortcut Bar"), - N_("Toggles the shortcut bar"), esv_cmd_toggle_shortcut_bar, NULL, + N_("Toggles the shortcut bar"), command_toggle_shortcut_bar, NULL, NULL, 0, 0, 'n', GDK_CONTROL_MASK | GDK_SHIFT_MASK }, { GNOME_APP_UI_ITEM, N_("_Toggle Treeview"), - N_("Toggles the tree view"), esv_cmd_toggle_treeview, NULL, + N_("Toggles the tree view"), command_toggle_treeview, NULL, NULL, 0, 0, 'n', GDK_CONTROL_MASK | GDK_SHIFT_MASK }, GNOMEUIINFO_END }; -static GnomeUIInfo esv_menu_tools [] = { +static GnomeUIInfo menu_tools [] = { GNOMEUIINFO_END }; -static GnomeUIInfo esv_menu_actions [] = { +static GnomeUIInfo menu_actions [] = { GNOMEUIINFO_END }; -static GnomeUIInfo esv_menu [] = { - GNOMEUIINFO_MENU_FILE_TREE (esv_menu_file), - GNOMEUIINFO_MENU_EDIT_TREE (esv_menu_edit), - GNOMEUIINFO_MENU_VIEW_TREE (esv_menu_view), + +/* Menu bar. */ + +GnomeUIInfo e_shell_view_menu [] = { + GNOMEUIINFO_MENU_FILE_TREE (menu_file), + GNOMEUIINFO_MENU_EDIT_TREE (menu_edit), + GNOMEUIINFO_MENU_VIEW_TREE (menu_view), /* FIXME: add Favorites here */ - { GNOME_APP_UI_SUBTREE, N_("_Tools"), NULL, esv_menu_tools }, - { GNOME_APP_UI_SUBTREE, N_("_Actions"), NULL, esv_menu_actions }, + { GNOME_APP_UI_SUBTREE, N_("_Tools"), NULL, menu_tools }, + { GNOME_APP_UI_SUBTREE, N_("_Actions"), NULL, menu_actions }, + #warning Should provide a help menu here; Bonobo needs it + GNOMEUIINFO_END }; - -/* - * Sets up the menus for the EShellView. - * - * Creates the Bonobo UI Handler, and then loads the menus from our - * GnomeUIInfo definitions - */ -void -e_shell_view_setup_menus (EShellView *eshell_view) -{ - BonoboUIHandlerMenuItem *list; - - eshell_view->uih = bonobo_ui_handler_new (); - bonobo_ui_handler_set_app (eshell_view->uih, GNOME_APP (eshell_view)); - bonobo_ui_handler_create_menubar (eshell_view->uih); - - list = bonobo_ui_handler_menu_parse_uiinfo_list_with_data (esv_menu, eshell_view); - bonobo_ui_handler_menu_add_list (eshell_view->uih, "/", list); - bonobo_ui_handler_menu_free_list (list); -} diff --git a/shell/e-shell-view-menu.h b/shell/e-shell-view-menu.h index f198efb806..52526c4187 100644 --- a/shell/e-shell-view-menu.h +++ b/shell/e-shell-view-menu.h @@ -1,6 +1,33 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shell-view.c + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: + * Miguel de Icaza + * Ettore Perazzoli + */ + #ifndef E_SHELL_VIEW_MENU_H #define E_SHELL_VIEW_MENU_H -void e_shell_view_setup_menus (EShellView *eshell_view); +#include <gnome.h> + +extern GnomeUIInfo e_shell_view_menu[]; -#endif /* E_SHELL_VIEW_MENU_H */ +#endif diff --git a/shell/e-shell-view.c b/shell/e-shell-view.c index 763359fd35..9651cce08c 100644 --- a/shell/e-shell-view.c +++ b/shell/e-shell-view.c @@ -1,461 +1,527 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - -/* - * E-shell-view.c: Implements a Shell View of Evolution +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shell-view.c * - * Authors: - * Miguel de Icaza (miguel@helixcode.com) + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. * - * (C) 2000 Helix Code, Inc. + * 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. + * + * Authors: + * Ettore Perazzoli <ettore@helixcode.com> + * Miguel de Icaza <miguel@helixcode.com> + * Matt Loper <matt@helixcode.com> */ + +#ifdef HAVE_CONFIG_H #include <config.h> +#endif + #include <gnome.h> +#include <bonobo.h> -#include "shortcut-bar/e-shortcut-bar.h" +#include "e-shell.h" +#include "e-shortcuts-view.h" #include "e-util/e-util.h" + #include "e-shell-view.h" #include "e-shell-view-menu.h" -#include "e-shell-shortcut.h" -#include "Evolution.h" -#include <bonobo.h> -#include <libgnorba/gnorba.h> -#include <gtk/gtkprivate.h> + + +#define PARENT_TYPE gnome_app_get_type () /* Losing GnomeApp does not define GNOME_TYPE_APP. */ +static GnomeAppClass *parent_class = NULL; -#ifdef USING_OAF +struct _EShellViewPrivate { + /* The shell. */ + EShell *shell; -# define MAIL_CONTROL_ID "OAFIID:control:evolution-mail:833d5a71-a201-4a0e-b7e6-5475c5c4cb45" -# define ADDRESSBOOK_CONTROL_ID "OAFIID:control:addressbook:851f883b-2fe7-4c94-a1e3-a1f2a7a03c49" -# define CALENDAR_CONTROL_ID "OAFIID:control:calendar:dd34ddae-25c6-486b-a8a8-3e8f0286b54c" + /* The UI handler. */ + BonoboUIHandler *uih; -#else + /* Currently displayed URI. */ + char *uri; -# define MAIL_CONTROL_ID "control:evolution-mail" -# define ADDRESSBOOK_CONTROL_ID "control:addressbook" -# define CALENDAR_CONTROL_ID "control:calendar" + /* The widgetry. */ + GtkWidget *hpaned; + GtkWidget *shortcut_bar; + GtkWidget *contents; + GtkWidget *notebook; -#endif + /* The view we have already open. */ + GHashTable *uri_to_control; +}; -#define PARENT_TYPE gnome_app_get_type () +#define DEFAULT_SHORTCUT_BAR_WIDTH 100 -static GtkObjectClass *parent_class; +#define DEFAULT_WIDTH 600 +#define DEFAULT_HEIGHT 600 -struct _EShellViewPrivate { - /* a hashtable of e-folders -> widgets */ - GHashTable *folder_views; - GtkWidget *notebook; -}; + +static GtkWidget * +create_label_for_empty_page (void) +{ + GtkWidget *label; + + label = gtk_label_new (_("(No folder displayed)")); + gtk_widget_show (label); + + return label; +} static void -destroy_folder_view (gpointer unused, gpointer pfolder_view, gpointer unused2) +setup_menus (EShellView *shell_view) { - GtkWidget *folder_view = GTK_WIDGET (pfolder_view); - BonoboWidget *bonobo_widget; - BonoboObject *bonobo_object; - CORBA_Object corba_control; - CORBA_Environment ev; + BonoboUIHandlerMenuItem *list; + EShellViewPrivate *priv; - g_print ("%s: %s entered\n", - __FILE__, __FUNCTION__); - - g_return_if_fail (BONOBO_IS_WIDGET (folder_view)); + priv = shell_view->priv; - bonobo_widget = BONOBO_WIDGET (folder_view); - - bonobo_object = BONOBO_OBJECT ( - bonobo_widget_get_server (bonobo_widget)); + priv->uih = bonobo_ui_handler_new (); + bonobo_ui_handler_set_app (priv->uih, GNOME_APP (shell_view)); + bonobo_ui_handler_create_menubar (priv->uih); - corba_control = bonobo_object_corba_objref (bonobo_object); - - g_return_if_fail (corba_control != NULL); + list = bonobo_ui_handler_menu_parse_uiinfo_list_with_data (e_shell_view_menu, shell_view); + bonobo_ui_handler_menu_add_list (priv->uih, "/", list); + bonobo_ui_handler_menu_free_list (list); +} + +static gboolean +bonobo_widget_is_dead (BonoboWidget *bw) +{ + BonoboObject *boc = BONOBO_OBJECT (bonobo_widget_get_server (bw)); + CORBA_Object obj = bonobo_object_corba_objref (boc); + + CORBA_Environment ev; - CORBA_exception_init (&ev); + gboolean is_dead = FALSE; - /* hangs on this! */ - Bonobo_Unknown_unref (corba_control, &ev); + CORBA_exception_init (&ev); + if (CORBA_Object_non_existent(obj, &ev)) + is_dead = TRUE; CORBA_exception_free (&ev); - g_print ("%s: %s exited\n", - __FILE__, __FUNCTION__); + return is_dead; } - + static void -esv_destroy (GtkObject *object) +activate_shortcut_cb (EShortcutsView *shortcut_view, + EShortcuts *shortcuts, + const char *uri, + gpointer data) { - EShellView *eshell_view = E_SHELL_VIEW (object); + EShellView *shell_view; - e_shell_unregister_view (eshell_view->eshell, eshell_view); + shell_view = E_SHELL_VIEW (data); - g_hash_table_foreach (eshell_view->priv->folder_views, - destroy_folder_view, NULL); - - g_hash_table_destroy (eshell_view->priv->folder_views); - g_free (eshell_view->priv); - parent_class->destroy (object); + e_shell_view_display_uri (shell_view, uri); } static void -e_shell_view_class_init (GtkObjectClass *object_class) +setup_widgets (EShellView *shell_view) { - object_class->destroy = esv_destroy; + EShellViewPrivate *priv; - parent_class = gtk_type_class (PARENT_TYPE); + priv = shell_view->priv; + + priv->hpaned = gtk_hpaned_new (); + gnome_app_set_contents (GNOME_APP (shell_view), priv->hpaned); + + /* The shortcut bar. */ + + priv->shortcut_bar = e_shortcuts_new_view (e_shell_get_shortcuts (priv->shell)); + gtk_paned_add1 (GTK_PANED (priv->hpaned), priv->shortcut_bar); + gtk_paned_set_position (GTK_PANED (priv->hpaned), DEFAULT_SHORTCUT_BAR_WIDTH); + gtk_signal_connect (GTK_OBJECT (priv->shortcut_bar), "activate_shortcut", + GTK_SIGNAL_FUNC (activate_shortcut_cb), shell_view); + + /* The tabless notebook which we used to contain the views. */ + + priv->notebook = gtk_notebook_new (); + gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->notebook), FALSE); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), FALSE); + gtk_paned_add2 (GTK_PANED (priv->hpaned), priv->notebook); + + /* Page for "No URL displayed" message. */ + + gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), create_label_for_empty_page (), NULL); + + /* Show stuff. */ + + gtk_widget_show (priv->shortcut_bar); + gtk_widget_show (priv->notebook); + + /* FIXME: Session management and stuff? */ + gtk_window_set_default_size (GTK_WINDOW (shell_view), DEFAULT_WIDTH, DEFAULT_HEIGHT); } + +/* GtkObject methods. */ + static void -e_shell_view_setup (EShellView *eshell_view) +hash_forall_destroy_control (gpointer name, + gpointer value, + gpointer data) { - /* - * FIXME, should load the config if (load_config).... - */ - gtk_window_set_default_size (GTK_WINDOW (eshell_view), 600, 600); -} + CORBA_Object corba_control; + CORBA_Environment ev; + BonoboObject *bonobo_object; + BonoboWidget *bonobo_widget; + bonobo_widget = BONOBO_WIDGET (value); + bonobo_object = BONOBO_OBJECT (bonobo_widget_get_server (bonobo_widget)); + corba_control = bonobo_object_corba_objref (bonobo_object); + + g_return_if_fail (corba_control != CORBA_OBJECT_NIL); + CORBA_exception_init (&ev); + Bonobo_Unknown_unref (corba_control, &ev); + CORBA_exception_free (&ev); + g_free (name); +} static void -e_shell_view_setup_shortcut_display (EShellView *eshell_view) +destroy (GtkObject *object) { - eshell_view->shortcut_bar = - e_shortcut_bar_view_new (eshell_view->eshell->shortcut_bar); - - eshell_view->hpaned = e_paned_new (TRUE); + EShellView *shell_view; + EShellViewPrivate *priv; - e_paned_insert (E_PANED (eshell_view->hpaned), 0, - eshell_view->shortcut_bar, - 100); + shell_view = E_SHELL_VIEW (object); + priv = shell_view->priv; - gtk_widget_show_all (eshell_view->hpaned); - - gnome_app_set_contents (GNOME_APP (eshell_view), - eshell_view->hpaned); + g_hash_table_foreach (priv->uri_to_control, hash_forall_destroy_control, NULL); + g_hash_table_destroy (priv->uri_to_control); + + g_free (priv); - gtk_signal_connect ( - GTK_OBJECT (eshell_view->shortcut_bar), "item_selected", - GTK_SIGNAL_FUNC (shortcut_bar_item_selected), eshell_view); + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); } -static GtkWidget * -get_view (EShellView *eshell_view, EFolder *efolder, Bonobo_UIHandler uih) + +/* Initialization. */ + +static void +class_init (EShellViewClass *klass) { - GtkWidget *w = NULL; - Evolution_Shell corba_shell = CORBA_OBJECT_NIL; - EShell *shell_model = eshell_view->eshell; + GtkObjectClass *object_class; - /* This type could be E_FOLDER_MAIL, E_FOLDER_CONTACTS, etc */ - EFolderType e_folder_type; + object_class = GTK_OBJECT_CLASS (klass); + object_class->destroy = destroy; - g_assert (efolder); - g_assert (eshell_view); - - e_folder_type = e_folder_get_folder_type (efolder); - - if (shell_model) - corba_shell = bonobo_object_corba_objref ( - BONOBO_OBJECT (shell_model)); - else - g_warning ("The shell Bonobo object does not have " - "an associated CORBA object\n"); - - /* depending on the type of folder, - * we launch a different bonobo component */ - switch (e_folder_type) { - - case E_FOLDER_MAIL : - w = bonobo_widget_new_control (MAIL_CONTROL_ID, uih); - break; - - case E_FOLDER_CONTACTS : - w = bonobo_widget_new_control (ADDRESSBOOK_CONTROL_ID, uih); - break; - - case E_FOLDER_CALENDAR : { - gchar *user_cal_file; - BonoboPropertyBagClient *pbc; - BonoboControlFrame *cf; - - w = bonobo_widget_new_control (CALENDAR_CONTROL_ID, uih); - - if (w) { - cf = bonobo_widget_get_control_frame (BONOBO_WIDGET (w)); - pbc = bonobo_control_frame_get_control_property_bag (cf); - /*pbc = bonobo_control_get_property_bag (w);*/ - - user_cal_file = - g_concat_dir_and_file (gnome_util_user_home (), - ".gnome/user-cal.vcf"); - - bonobo_property_bag_client_set_value_string (pbc, - "calendar_uri", - user_cal_file); - } - - break; - } + parent_class = gtk_type_class (gnome_app_get_type ()); +} - case E_FOLDER_TASKS : - case E_FOLDER_OTHER : - default : - printf ("%s: %s: No bonobo component associated with %s\n", - __FILE__, - __FUNCTION__, - e_folder_get_description (efolder)); - return NULL; - } +static void +init (EShellView *shell_view) +{ + EShellViewPrivate *priv; - if (w) { - Evolution_ServiceRepository corba_sr; - BonoboObjectClient *server = - bonobo_widget_get_server (BONOBO_WIDGET (w)); - CORBA_Environment ev; - CORBA_exception_init (&ev); - - /* Does this control have the "ServiceRepository" interface? */ - corba_sr = (Evolution_ServiceRepository) - bonobo_object_client_query_interface ( - server, - "IDL:Evolution/ServiceRepository:1.0", - NULL); - - /* If it does, pass our shell interface to it */ - if (corba_sr != CORBA_OBJECT_NIL) { - - Evolution_ServiceRepository_set_shell (corba_sr, - corba_shell, - &ev); - /* We're done with the service repository interface, - so now let's get rid of it */ - Bonobo_Unknown_unref (corba_sr, &ev); - - } else { - - g_print ("The bonobo component for \"%s\" doesn't " - "seem to implement the " - "Evolution::ServiceRepository interface\n", - e_folder_get_description (efolder)); - } + priv = g_new (EShellViewPrivate, 1); - CORBA_exception_free (&ev); + priv->shell = NULL; + priv->uih = NULL; + priv->uri = NULL; + priv->hpaned = NULL; + priv->shortcut_bar = NULL; + priv->contents = NULL; + priv->notebook = NULL; - gtk_widget_show (w); - } - - return w; -} + priv->uri_to_control = g_hash_table_new (g_str_hash, g_str_equal); -void e_shell_view_toggle_shortcut_bar (EShellView *eshell_view) -{ - GtkWidget *shortcut_bar = eshell_view->shortcut_bar; - GtkWidget *hpaned = eshell_view->hpaned; - - if (shortcut_bar->parent) { - gtk_widget_ref (shortcut_bar); - e_paned_remove (E_PANED (hpaned), shortcut_bar); - } - else - e_paned_insert (E_PANED (hpaned), 0, shortcut_bar, - 100); - gtk_widget_show_all (GTK_WIDGET (hpaned)); + shell_view->priv = priv; } -void e_shell_view_toggle_treeview (EShellView *eshell_view) + +void +e_shell_view_construct (EShellView *shell_view, + EShell *shell, + const char *uri) { - + EShellViewPrivate *priv; + + g_return_if_fail (shell_view != NULL); + g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); + g_return_if_fail (shell != NULL); + g_return_if_fail (E_IS_SHELL (shell)); + g_return_if_fail (uri == NULL || ! g_path_is_absolute (uri)); + + gnome_app_construct (GNOME_APP (shell_view), "evolution", "Evolution"); + + priv = shell_view->priv; + + priv->shell = shell; + priv->uri = g_strdup (uri); + + setup_widgets (shell_view); + setup_menus (shell_view); } -static gboolean -bonobo_widget_is_dead (BonoboWidget *bw) +GtkWidget * +e_shell_view_new (EShell *shell, + const char *uri) { - BonoboObject *boc = BONOBO_OBJECT (bonobo_widget_get_server (bw)); - CORBA_Object obj = bonobo_object_corba_objref (boc); + GtkWidget *new; - CORBA_Environment ev; - - gboolean is_dead = FALSE; + g_return_val_if_fail (shell != NULL, NULL); + g_return_val_if_fail (E_IS_SHELL (shell), NULL); + g_return_val_if_fail (uri == NULL || ! g_path_is_absolute (uri), NULL); - CORBA_exception_init (&ev); - if (CORBA_Object_non_existent(obj, &ev)) - is_dead = TRUE; - CORBA_exception_free (&ev); + new = gtk_type_new (e_shell_view_get_type ()); + e_shell_view_construct (E_SHELL_VIEW (new), shell, uri); - return is_dead; + return new; } - -void -e_shell_view_set_view (EShellView *eshell_view, EFolder *efolder) + +/* This displays the specified page, doing the appropriate Bonobo + activation/deactivation magic to make sure things work nicely. + FIXME: Crappy way to solve the issue. */ +static void +set_current_notebook_page (EShellView *shell_view, + int page_num) { + EShellViewPrivate *priv; GtkNotebook *notebook; - GtkWidget *folder_view; - int current_page; + GtkWidget *current; BonoboControlFrame *control_frame; + int current_page; - g_assert (eshell_view); - g_assert (efolder); + priv = shell_view->priv; + notebook = GTK_NOTEBOOK (priv->notebook); - notebook = GTK_NOTEBOOK (eshell_view->priv->notebook); current_page = gtk_notebook_get_current_page (notebook); + if (current_page == page_num) + return; - if (current_page != -1) { - GtkWidget *current; - + if (current_page != -1 && current_page != 0) { current = gtk_notebook_get_nth_page (notebook, current_page); - control_frame = bonobo_widget_get_control_frame ( - BONOBO_WIDGET (current)); - } else - control_frame = NULL; - - /* If there's a notebook page in our hash that represents this - * efolder, switch to it. - */ - folder_view = g_hash_table_lookup (eshell_view->priv->folder_views, - efolder); - if (folder_view) { - int notebook_page; - - g_assert (GTK_IS_NOTEBOOK (notebook)); - g_assert (GTK_IS_WIDGET (folder_view)); - - notebook_page = gtk_notebook_page_num (notebook, - folder_view); - g_assert (notebook_page != -1); - - /* a BonoboWidget can be a "zombie" in the sense that its - actual control is dead; if it's zombie, let's recreate it*/ - if (bonobo_widget_is_dead (BONOBO_WIDGET (folder_view))) { - - GtkWidget *parent = folder_view->parent; - Bonobo_UIHandler uih = - bonobo_object_corba_objref ( - BONOBO_OBJECT (eshell_view->uih)); - - /* out with the old */ - gtk_container_remove (GTK_CONTAINER (parent), folder_view); - - /* in with the new */ - folder_view = get_view (eshell_view, efolder, uih); - gtk_container_add (GTK_CONTAINER (parent), folder_view); - - /* make sure it's in our hashtable, so we can get to - it from the shortcut bar */ - g_hash_table_insert (eshell_view->priv->folder_views, - efolder, folder_view); - gtk_widget_show_all (folder_view); - } - - - gtk_notebook_set_page (notebook, notebook_page); + control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (current)); - return; - - } else { - /* Get a new control that represents this efolder, - * append it to our notebook, and put it in our hash. - */ - Bonobo_UIHandler uih = - bonobo_object_corba_objref ( - BONOBO_OBJECT (eshell_view->uih)); - int new_page_index; - - folder_view = get_view (eshell_view, efolder, uih); - if (!folder_view) { - /* FIXME: Report failure. */ - return; - } - - gtk_notebook_append_page (notebook, folder_view, NULL); - new_page_index = gtk_notebook_page_num (notebook, - folder_view); - g_hash_table_insert (eshell_view->priv->folder_views, - efolder, folder_view); - gtk_notebook_set_page (notebook, new_page_index); + bonobo_control_frame_set_autoactivate (control_frame, FALSE); + bonobo_control_frame_control_deactivate (control_frame); } - if (control_frame) - bonobo_control_frame_control_deactivate (control_frame); + gtk_notebook_set_page (notebook, page_num); + + if (page_num == -1 || page_num == 0) + return; + + current = gtk_notebook_get_nth_page (notebook, page_num); + control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (current)); - control_frame = - bonobo_widget_get_control_frame (BONOBO_WIDGET (folder_view)); bonobo_control_frame_set_autoactivate (control_frame, FALSE); bonobo_control_frame_control_activate (control_frame); } -GtkWidget * -e_shell_view_new (EShell *eshell, EFolder *efolder, gboolean show_shortcut_bar) +static void +show_error (EShellView *shell_view, + const char *uri) { - EShellView *eshell_view; + EShellViewPrivate *priv; + GtkWidget *label; + char *s; - g_return_val_if_fail (eshell != NULL, NULL); - g_return_val_if_fail (efolder != NULL, NULL); - - eshell_view = gtk_type_new (e_shell_view_get_type ()); - - eshell_view->priv = g_new (EShellViewPrivate, 1); - eshell_view->priv->folder_views = - g_hash_table_new (g_direct_hash, g_direct_equal); - eshell_view->priv->notebook = NULL; - - gnome_app_construct (GNOME_APP (eshell_view), - "Evolution", "Evolution"); - - eshell_view->eshell = eshell; - e_shell_view_setup (eshell_view); - e_shell_view_setup_menus (eshell_view); - - e_shell_register_view (eshell, eshell_view); - eshell_view->shortcut_displayed = show_shortcut_bar; - e_shell_view_setup_shortcut_display (eshell_view); - - /* create our notebook, if it hasn't been created already */ - if (!eshell_view->priv->notebook) { - eshell_view->priv->notebook = gtk_notebook_new(); - - gtk_notebook_set_show_border ( - GTK_NOTEBOOK (eshell_view->priv->notebook), - FALSE); - gtk_notebook_set_show_tabs ( - GTK_NOTEBOOK (eshell_view->priv->notebook), - FALSE); - - gtk_widget_show (eshell_view->priv->notebook); - - e_paned_insert (E_PANED (eshell_view->hpaned), - 1, - eshell_view->priv->notebook, -// gtk_button_new_with_label ("foobar"), - 500); - - gtk_widget_show_all (GTK_WIDGET (eshell_view->hpaned)); - } + priv = shell_view->priv; - e_shell_view_set_view (eshell_view, efolder); - - return (GtkWidget *) eshell_view; + s = g_strdup_printf (_("Cannot open location: %s\n"), uri); + label = gtk_label_new (s); + g_free (s); + + gtk_widget_show (label); + + gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook), 0); + gtk_notebook_prepend_page (GTK_NOTEBOOK (priv->notebook), label, NULL); } -void -e_shell_view_display_shortcut_bar (EShellView *eshell_view, gboolean display) +/* Create a new view for @uri with @control. It assumes a view for @uri does + not exist yet. */ +static GtkWidget * +get_control_for_uri (EShellView *shell_view, + const char *uri) { - g_return_if_fail (eshell_view != NULL); - g_return_if_fail (E_IS_SHELL_VIEW (eshell_view)); + EShellViewPrivate *priv; + EFolderTypeRepository *folder_type_repository; + EStorageSet *storage_set; + EFolder *folder; + Bonobo_UIHandler corba_uih; + const char *control_id; + const char *path; + const char *folder_type; + GtkWidget *control; + + priv = shell_view->priv; + + path = strchr (uri, ':'); + if (path == NULL) + return NULL; + + path++; + if (*path == '\0') + return NULL; + + storage_set = e_shell_get_storage_set (priv->shell); + folder_type_repository = e_shell_get_folder_type_repository (priv->shell); + + folder = e_storage_set_get_folder (storage_set, path); + if (folder == NULL) + return NULL; + + folder_type = e_folder_get_type_string (folder); + if (folder_type == NULL) + return NULL; - g_error ("Switching code for the shortcut bar is not written yet"); + control_id = e_folder_type_repository_get_control_id_for_type (folder_type_repository, + folder_type); + if (control_id == NULL) + return NULL; + + corba_uih = bonobo_object_corba_objref (BONOBO_OBJECT (priv->uih)); + control = bonobo_widget_new_control (control_id, corba_uih); + + if (control == NULL) + return NULL; + + bonobo_widget_set_property (BONOBO_WIDGET (control), + "folder_uri", e_folder_get_physical_uri (folder), + NULL); + + return control; } -E_MAKE_TYPE (e_shell_view, "EShellView", EShellView, e_shell_view_class_init, NULL, PARENT_TYPE); +static gboolean +show_existing_view (EShellView *shell_view, + const char *uri, + GtkWidget *control) +{ + EShellViewPrivate *priv; + int notebook_page; -void -e_shell_view_new_folder (EShellView *esv) + priv = shell_view->priv; + + notebook_page = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), control); + g_assert (notebook_page != -1); + + /* A BonoboWidget can be a "zombie" in the sense that its actual + control is dead; if it's zombie, we have to recreate it. */ + if (bonobo_widget_is_dead (BONOBO_WIDGET (control))) { + GtkWidget *parent; + Bonobo_UIHandler uih; + + parent = control->parent; + uih = bonobo_object_corba_objref (BONOBO_OBJECT (priv->uih)); + + /* Out with the old. */ + gtk_container_remove (GTK_CONTAINER (parent), control); + g_hash_table_remove (priv->uri_to_control, uri); + + /* In with the new. */ + control = get_control_for_uri (shell_view, uri); + if (control == NULL) + return FALSE; + + gtk_container_add (GTK_CONTAINER (parent), control); + g_hash_table_insert (priv->uri_to_control, g_strdup (uri), control); + + /* Show. */ + gtk_widget_show (control); + } + + set_current_notebook_page (shell_view, notebook_page); + + return TRUE; +} + +static gboolean +create_new_view_for_uri (EShellView *shell_view, + const char *uri) { - g_return_if_fail (esv != NULL); - g_return_if_fail (E_IS_SHELL_VIEW (esv)); + GtkWidget *control; + EShellViewPrivate *priv; + int page_num; + + priv = shell_view->priv; + + control = get_control_for_uri (shell_view, uri); + if (control == NULL) { + show_error (shell_view, uri); + return FALSE; + } + + gtk_widget_show (control); + + gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), control, NULL); + + page_num = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), control); + g_assert (page_num != -1); + set_current_notebook_page (shell_view, page_num); + + g_hash_table_insert (priv->uri_to_control, g_strdup (uri), control); + + return TRUE; } -void -e_shell_view_new_shortcut (EShellView *esv) +gboolean +e_shell_view_display_uri (EShellView *shell_view, + const char *uri) { - g_return_if_fail (esv != NULL); - g_return_if_fail (E_IS_SHELL_VIEW (esv)); + EShellViewPrivate *priv; + GtkWidget *control; + + g_return_val_if_fail (shell_view != NULL, FALSE); + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), FALSE); + + priv = shell_view->priv; + + if (uri == NULL) { + gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook), 0); + gtk_notebook_prepend_page (GTK_NOTEBOOK (priv->notebook), + create_label_for_empty_page (), NULL); + + set_current_notebook_page (shell_view, 0); + + if (priv->uri != NULL) { + g_free (priv->uri); + priv->uri = NULL; + } + + return TRUE; + } + + g_free (priv->uri); + priv->uri = g_strdup (uri); + + if (strncmp (uri, "evolution:", 10) != 0) { + show_error (shell_view, uri); + return FALSE; + } + + control = g_hash_table_lookup (priv->uri_to_control, uri); + if (control != NULL) { + g_assert (GTK_IS_WIDGET (control)); + show_existing_view (shell_view, uri, control); + return TRUE; + } + + if (! create_new_view_for_uri (shell_view, uri)) { + show_error (shell_view, uri); + return FALSE; + } + + return TRUE; } + + +E_MAKE_TYPE (e_shell_view, "EShellView", EShellView, class_init, init, PARENT_TYPE) diff --git a/shell/e-shell-view.h b/shell/e-shell-view.h index 97e5f41742..0ca2f19eae 100644 --- a/shell/e-shell-view.h +++ b/shell/e-shell-view.h @@ -1,57 +1,75 @@ -#ifndef E_SHELL_VIEW_H -#define E_SHELL_VIEW_H +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shell-view.h + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +#ifndef _E_SHELL_VIEW_H_ +#define _E_SHELL_VIEW_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gnome.h> -#include <bonobo/bonobo-object.h> -#include <bonobo/bonobo-ui-handler.h> #include "e-shell.h" -#include "e-util/e-paned.h" -#define E_SHELL_VIEW_TYPE (e_shell_view_get_type ()) -#define E_SHELL_VIEW(o) (GTK_CHECK_CAST ((o), E_SHELL_VIEW_TYPE, EShellView)) -#define E_SHELL_VIEW_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_SHELL_VIEW_TYPE, EShellViewClass)) -#define E_IS_SHELL_VIEW(o) (GTK_CHECK_TYPE ((o), E_SHELL_VIEW_TYPE)) -#define E_IS_SHELL_VIEW_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_SHELL_VIEW_TYPE)) +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define E_TYPE_SHELL_VIEW (e_shell_view_get_type ()) +#define E_SHELL_VIEW(obj) (GTK_CHECK_CAST ((obj), E_TYPE_SHELL_VIEW, EShellView)) +#define E_SHELL_VIEW_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_SHELL_VIEW, EShellViewClass)) +#define E_IS_SHELL_VIEW(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_SHELL_VIEW)) +#define E_IS_SHELL_VIEW_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_SHELL_VIEW)) + +typedef struct _EShellView EShellView; typedef struct _EShellViewPrivate EShellViewPrivate; +typedef struct _EShellViewClass EShellViewClass; struct _EShellView { GnomeApp parent; - /* Pointer to our model */ - EShell *eshell; - - /* Our user interface handler */ - BonoboUIHandler *uih; - - - EFolder *efolder; - - gboolean shortcut_displayed; - GtkWidget *hpaned; - GtkWidget *shortcut_bar; - GtkWidget *treeview; - GtkWidget *contents; - EShellViewPrivate *priv; }; -typedef struct { +struct _EShellViewClass { GnomeAppClass parent_class; -} EShellViewClass; +}; -GtkWidget *e_shell_view_new (EShell *eshell, EFolder *folder, - gboolean show_shortcut_bar); + GtkType e_shell_view_get_type (void); - -void e_shell_view_new_folder (EShellView *esv); -void e_shell_view_new_shortcut (EShellView *esv); - -void e_shell_view_set_view (EShellView *eshell_view, - EFolder *efolder); - -void e_shell_view_toggle_shortcut_bar (EShellView *eshell_view); -void e_shell_view_toggle_treeview (EShellView *eshell_view); - -void e_shell_view_display_shortcut_bar (EShellView *eshell_view, gboolean display); - -#endif /* E_SHELL_VIEW_H */ +void e_shell_view_construct (EShellView *shell_view, + EShell *shell, + const char *uri); +GtkWidget *e_shell_view_new (EShell *shell, + const char *uri); +gboolean e_shell_view_display_uri (EShellView *shell, + const char *uri); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _E_SHELL_VIEW_H_ */ diff --git a/shell/e-shell.c b/shell/e-shell.c index 2713df3921..6c225cdf49 100644 --- a/shell/e-shell.c +++ b/shell/e-shell.c @@ -1,377 +1,233 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - -/* - * E-shell.c: Shell object for Evolution +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shell.c + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. * - * Authors: - * Miguel de Icaza (miguel@helixcode.com) + * 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. * - * (C) 1999 Miguel de Icaza - * (C) 2000 Helix Code, Inc. + * 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 */ +#ifdef HAVE_CONFIG_H #include <config.h> -#include <gtk/gtkmain.h> -#include <libgnome/libgnome.h> -#include "Evolution.h" -#include "e-util/e-util.h" -#include "e-shell.h" +#endif -#define PARENT_TYPE (bonobo_object_get_type ()) +#include <gtk/gtkobject.h> +#include <gtk/gtktypeutils.h> -static BonoboObjectClass *e_shell_parent_class; -POA_Evolution_Shell__vepv eshell_vepv; +#include "e-util/e-util.h" -GtkType e_shell_get_type (void); +#include "e-folder-type-repository.h" +#include "e-local-storage.h" +#include "e-shell-view.h" +#include "e-shortcuts.h" +#include "e-storage-set.h" -void -e_shell_new_appointment (EShell *eshell) -{ - printf ("Unimplemented function invoked: %s\n", __FUNCTION__); -} +#include "e-shell.h" -void -e_shell_new_meeting_request (EShell *eshell) -{ - printf ("Unimplemented function invoked: %s\n", __FUNCTION__); -} + +#define PARENT_TYPE GTK_TYPE_OBJECT +static GtkObjectClass *parent_class = NULL; -void -e_shell_new_task (EShell *eshell) -{ - printf ("Unimplemented function invoked: %s\n", __FUNCTION__); -} +struct _EShellPrivate { + char *local_directory; -void -e_shell_new_task_request (EShell *eshell) -{ - printf ("Unimplemented function invoked: %s\n", __FUNCTION__); -} + EStorageSet *storage_set; + EShortcuts *shortcuts; + EFolderTypeRepository *folder_type_repository; +}; -void -e_shell_new_contact (EShell *eshell) -{ - printf ("Unimplemented function invoked: %s\n", __FUNCTION__); -} +#define SHORTCUTS_FILE_NAME "shortcuts.xml" +#define LOCAL_STORAGE_DIRECTORY "local" -void -e_shell_new_mail_message (EShell *eshell) -{ - printf ("Unimplemented function invoked: %s\n", __FUNCTION__); -} + +/* Initialization of the storages. */ -void -e_shell_new_distribution_list (EShell *eshell) +static gboolean +setup_storages (EShell *shell) { - printf ("Unimplemented function invoked: %s\n", __FUNCTION__); -} + EStorage *local_storage; + EShellPrivate *priv; + gchar *local_storage_path; -void -e_shell_new_journal_entry (EShell *eshell) -{ - printf ("Unimplemented function invoked: %s\n", __FUNCTION__); -} + priv = shell->priv; -void -e_shell_new_note (EShell *eshell) -{ - printf ("Unimplemented function invoked: %s\n", __FUNCTION__); -} + local_storage_path = g_concat_dir_and_file (priv->local_directory, + LOCAL_STORAGE_DIRECTORY); + local_storage = e_local_storage_open (local_storage_path); + g_free (local_storage_path); -static void -EShell_cmd_new (PortableServer_Servant servant, - const Evolution_Shell_NewType type, - CORBA_Environment *ev) -{ - EShell *eshell = E_SHELL (bonobo_object_from_servant (servant)); - - switch (type){ - case Evolution_Shell_APPOINTMENT: - e_shell_new_appointment (eshell); - break; - - case Evolution_Shell_MEETING_REQUEST: - e_shell_new_meeting_request (eshell); - break; - - case Evolution_Shell_TASK: - e_shell_new_task (eshell); - break; - - case Evolution_Shell_TASK_REQUEST: - e_shell_new_task_request (eshell); - break; - - case Evolution_Shell_CONTACT: - e_shell_new_contact (eshell); - break; - - case Evolution_Shell_MAIL_MESSAGE: - e_shell_new_mail_message (eshell); - break; - - case Evolution_Shell_DISTRIBUTION_LIST: - e_shell_new_distribution_list (eshell); - break; - - case Evolution_Shell_JOURNAL_ENTRY: - e_shell_new_journal_entry (eshell); - break; - - case Evolution_Shell_NOTE: - e_shell_new_note (eshell); - break; - - default: - } -} + if (local_storage == NULL) + return FALSE; -static void -EShell_register_service (PortableServer_Servant servant, - const Evolution_Shell_ServiceType type, - const CORBA_char *uri, - CORBA_Environment *ev) -{ - char *service_type_desc = NULL; - - switch (type) { - - case Evolution_Shell_MAIL_STORE : - service_type_desc = "store"; - break; - case Evolution_Shell_MAIL_TRANSPORT : - service_type_desc = "transport"; - break; - default : - service_type_desc = "service of unknown type"; - } - - printf ("A component has registered a %s with uri \"%s\"\n", service_type_desc, uri); + priv->storage_set = e_storage_set_new (); + e_storage_set_add_storage (priv->storage_set, local_storage); + return TRUE; } + +/* GtkObject methods. */ -static POA_Evolution_Shell__epv * -e_shell_get_epv (void) +static void +destroy (GtkObject *object) { - POA_Evolution_Shell__epv *epv; - - epv = g_new0 (POA_Evolution_Shell__epv, 1); + EShell *shell; + EShellPrivate *priv; - epv->new = EShell_cmd_new; - epv->register_service = EShell_register_service; + shell = E_SHELL (object); + priv = shell->priv; - return epv; -} + gtk_object_unref (GTK_OBJECT (priv->storage_set)); + gtk_object_unref (GTK_OBJECT (priv->shortcuts)); + gtk_object_unref (GTK_OBJECT (priv->folder_type_repository)); -static void -init_e_shell_corba_class (void) -{ - eshell_vepv.Bonobo_Unknown_epv = bonobo_object_get_epv (); - eshell_vepv.Evolution_Shell_epv = e_shell_get_epv (); -} + g_free (priv); -static void -es_destroy_default_folders (EShell *eshell) -{ - gtk_object_unref (GTK_OBJECT (eshell->default_folders.inbox)); - gtk_object_unref (GTK_OBJECT (eshell->default_folders.outbox)); - gtk_object_unref (GTK_OBJECT (eshell->default_folders.drafts)); - gtk_object_unref (GTK_OBJECT (eshell->default_folders.calendar)); - gtk_object_unref (GTK_OBJECT (eshell->default_folders.tasks)); + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); } + static void -e_shell_destroy (GtkObject *object) +class_init (EShellClass *klass) { - EShell *eshell = E_SHELL (object); + GtkObjectClass *object_class; - gtk_object_unref (GTK_OBJECT (eshell->shortcut_bar)); - es_destroy_default_folders (eshell); - - GTK_OBJECT_CLASS (e_shell_parent_class)->destroy (object); -} + object_class = GTK_OBJECT_CLASS (klass); + object_class->destroy = destroy; -static void -e_shell_class_init (GtkObjectClass *object_class) -{ - e_shell_parent_class = gtk_type_class (PARENT_TYPE); - init_e_shell_corba_class (); + parent_class = gtk_type_class (gtk_object_get_type ()); - object_class->destroy = e_shell_destroy; } static void -e_shell_destroy_views (EShell *eshell) +init (EShell *shell) { + EShellPrivate *priv; - /* - * Notice that eshell->views is updated by the various views - * during unregistration - */ - while (eshell->views){ - EShellView *view = eshell->views->data; + priv = g_new (EShellPrivate, 1); - gtk_object_destroy (GTK_OBJECT (view)); - } -} + priv->local_directory = NULL; + priv->storage_set = NULL; + priv->shortcuts = NULL; + priv->folder_type_repository = NULL; -void -e_shell_quit (EShell *eshell) -{ - g_return_if_fail (eshell != NULL); - g_return_if_fail (E_IS_SHELL (eshell)); - - e_shell_destroy_views (eshell); - - gtk_main_quit (); + shell->priv = priv; } -static CORBA_Object -create_corba_eshell (BonoboObject *object) + +void +e_shell_construct (EShell *shell, + const char *local_directory) { - POA_Evolution_Shell *servant; - CORBA_Environment ev; + EShellPrivate *priv; + gchar *shortcut_path; - servant = (POA_Evolution_Shell *)g_new0 (BonoboObjectServant, 1); - servant->vepv = &eshell_vepv; + g_return_if_fail (shell != NULL); + g_return_if_fail (E_IS_SHELL (shell)); + g_return_if_fail (local_directory != NULL); + g_return_if_fail (g_path_is_absolute (local_directory)); - CORBA_exception_init (&ev); + GTK_OBJECT_UNSET_FLAGS (shell, GTK_FLOATING); - POA_Evolution_Shell__init ((PortableServer_Servant) servant, &ev); - if (ev._major != CORBA_NO_EXCEPTION){ - CORBA_exception_free (&ev); - g_free (servant); - return CORBA_OBJECT_NIL; - } + priv = shell->priv; - CORBA_exception_free (&ev); + priv->local_directory = g_strdup (local_directory); - return bonobo_object_activate_servant (object, servant); -} + if (! setup_storages (shell)) + return; -static void -e_shell_setup_default_folders (EShell *eshell) -{ - eshell->default_folders.summary = e_folder_new ( - E_FOLDER_SUMMARY, "internal:summary", _("Today"), _("Executive Summary"), - NULL, "internal:"); - eshell->default_folders.inbox = e_folder_new ( - E_FOLDER_MAIL, "internal:inbox", _("Inbox"), _("New mail messages"), - NULL, "internal:mail_view"); - eshell->default_folders.outbox = e_folder_new ( - E_FOLDER_MAIL, "internal:outbox", _("Sent messages"), _("Sent mail messages"), - NULL, "internal:mail_view"); - eshell->default_folders.drafts = e_folder_new ( - E_FOLDER_MAIL, "internal:drafts", _("Drafts"), _("Draft mail messages"), - NULL, "internal:mail_view"); - eshell->default_folders.calendar = e_folder_new ( - E_FOLDER_CALENDAR, "internal:personal_calendar", _("Calendar"), _("Your calendar"), - NULL, "internal:calendar_daily"); - eshell->default_folders.contacts = e_folder_new ( - E_FOLDER_CONTACTS, "internal:personal_contacts", _("Contacts"), _("Your contacts list"), - NULL, "internal:contact_view"); - eshell->default_folders.tasks = e_folder_new ( - E_FOLDER_TASKS, "internal:personal_calendar", _("Tasks"), _("Tasks list"), - NULL, "internal:tasks_view"); -} + priv->folder_type_repository = e_folder_type_repository_new (); + priv->shortcuts = e_shortcuts_new (priv->storage_set, priv->folder_type_repository); -static EShortcutGroup * -setup_main_shortcuts (EShell *eshell) -{ - EShortcutGroup *m; + shortcut_path = g_concat_dir_and_file (local_directory, "shortcuts.xml"); - m = e_shortcut_group_new (_("Main Shortcuts"), FALSE); - e_shortcut_group_append (m, e_shortcut_new (eshell->default_folders.summary)); - e_shortcut_group_append (m, e_shortcut_new (eshell->default_folders.inbox)); - e_shortcut_group_append (m, e_shortcut_new (eshell->default_folders.calendar)); - e_shortcut_group_append (m, e_shortcut_new (eshell->default_folders.contacts)); - e_shortcut_group_append (m, e_shortcut_new (eshell->default_folders.tasks)); + if (! e_shortcuts_load (priv->shortcuts, shortcut_path)) { + gtk_object_unref (GTK_OBJECT (priv->shortcuts)); + priv->shortcuts = NULL; + } - return m; + g_free (shortcut_path); } -static EShortcutGroup * -setup_secondary_shortcuts (EShell *eshell) +EShell * +e_shell_new (const char *local_directory) { - EShortcutGroup *sec; + EShell *new; + EShellPrivate *priv; - sec = e_shortcut_group_new (_("Other Shortcuts"), TRUE); - - e_shortcut_group_append (sec, e_shortcut_new (eshell->default_folders.drafts)); - e_shortcut_group_append (sec, e_shortcut_new (eshell->default_folders.outbox)); + new = gtk_type_new (e_shell_get_type ()); + e_shell_construct (new, local_directory); - return sec; -} + priv = new->priv; -static void -e_shell_setup_default_shortcuts (EShell *eshell) -{ - eshell->shortcut_bar = e_shortcut_bar_model_new (); - e_shortcut_bar_model_append ( - eshell->shortcut_bar, - setup_main_shortcuts (eshell)); - e_shortcut_bar_model_append ( - eshell->shortcut_bar, - setup_secondary_shortcuts (eshell)); -} + if (priv->shortcuts == NULL || priv->storage_set == NULL) { + gtk_object_unref (GTK_OBJECT (new)); + return NULL; + } -static void -e_shell_init (GtkObject *object) -{ - EShell *eshell = E_SHELL (object); - - e_shell_setup_default_folders (eshell); - e_shell_setup_default_shortcuts (eshell); + return new; } -static void -e_shell_construct (EShell *eshell, Evolution_Shell corba_eshell) + +GtkWidget * +e_shell_new_view (EShell *shell, + const char *uri) { - bonobo_object_construct (BONOBO_OBJECT (eshell), corba_eshell); -} + GtkWidget *view_widget; + EShellView *shell_view; -EShell * -e_shell_new (void) -{ - Evolution_Shell corba_eshell; - EShell *eshell; + g_return_val_if_fail (shell != NULL, NULL); + g_return_val_if_fail (E_IS_SHELL (shell), NULL); - eshell = gtk_type_new (e_shell_get_type ()); + view_widget = e_shell_view_new (shell, uri); + shell_view = E_SHELL_VIEW (view_widget); - corba_eshell = create_corba_eshell (BONOBO_OBJECT (eshell)); - if (corba_eshell == CORBA_OBJECT_NIL){ - gtk_object_destroy (GTK_OBJECT (eshell)); - return NULL; - } - - e_shell_construct (eshell, corba_eshell); + gtk_widget_show (view_widget); - return eshell; + return view_widget; } -void -e_shell_register_view (EShell *eshell, EShellView *eshell_view) + +EShortcuts * +e_shell_get_shortcuts (EShell *shell) { - g_return_if_fail (eshell != NULL); - g_return_if_fail (E_IS_SHELL (eshell)); - g_return_if_fail (eshell_view != NULL); + g_return_val_if_fail (shell != NULL, NULL); + g_return_val_if_fail (E_IS_SHELL (shell), NULL); - eshell->views = g_slist_prepend (eshell->views, eshell_view); + return shell->priv->shortcuts; } -void -e_shell_unregister_view (EShell *eshell, EShellView *eshell_view) +EStorageSet * +e_shell_get_storage_set (EShell *shell) { - g_return_if_fail (eshell != NULL); - g_return_if_fail (E_IS_SHELL (eshell)); - g_return_if_fail (eshell_view != NULL); + g_return_val_if_fail (shell != NULL, NULL); + g_return_val_if_fail (E_IS_SHELL (shell), NULL); - eshell->views = g_slist_remove (eshell->views, eshell_view); + return shell->priv->storage_set; } -E_MAKE_TYPE (e_shell, "EShell", EShell, e_shell_class_init, e_shell_init, PARENT_TYPE); - +EFolderTypeRepository * +e_shell_get_folder_type_repository (EShell *shell) +{ + g_return_val_if_fail (shell != NULL, NULL); + g_return_val_if_fail (E_IS_SHELL (shell), NULL); + return shell->priv->folder_type_repository; +} - + +E_MAKE_TYPE (e_shell, "EShell", EShell, class_init, init, PARENT_TYPE) diff --git a/shell/e-shell.h b/shell/e-shell.h index 64de044fb4..fd82b6b862 100644 --- a/shell/e-shell.h +++ b/shell/e-shell.h @@ -1,60 +1,78 @@ -#ifndef E_SHELL_H -#define E_SHELL_H +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shell.h + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +#ifndef _E_SHELL_H_ +#define _E_SHELL_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif -#include <bonobo/bonobo-object.h> -#include "evolution.h" -#include "e-folder.h" -#include "e-shortcut.h" +#include <gtk/gtkobject.h> -#define E_SHELL_GOAD_ID "GOADID:GNOME:Evolution:Shell:1.0" -#define E_SHELL_FACTORY_GOAD_ID "GOADID:GNOME:Evolution:ShellFactory:1.0" +#include "e-shortcuts.h" -#define E_SHELL_TYPE (e_shell_get_type ()) -#define E_SHELL(o) (GTK_CHECK_CAST ((o), E_SHELL_TYPE, EShell)) -#define E_SHELL_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_SHELL_TYPE, EShellClass)) -#define E_IS_SHELL(o) (GTK_CHECK_TYPE ((o), E_SHELL_TYPE)) -#define E_IS_SHELL_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_SHELL_TYPE)) +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define E_TYPE_SHELL (e_shell_get_type ()) +#define E_SHELL(obj) (GTK_CHECK_CAST ((obj), E_TYPE_SHELL, EShell)) +#define E_SHELL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_SHELL, EShellClass)) +#define E_IS_SHELL(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_SHELL)) +#define E_IS_SHELL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_SHELL)) + + +typedef struct _EShell EShell; +typedef struct _EShellPrivate EShellPrivate; +typedef struct _EShellClass EShellClass; struct _EShell { - BonoboObject base_object; - - /* A list of EShellViews */ - GSList *views; - - struct { - EFolder *inbox; - EFolder *outbox; - EFolder *drafts; - EFolder *calendar; - EFolder *tasks; - EFolder *summary; - EFolder *contacts; - } default_folders; - - EShortcutBarModel *shortcut_bar; + GtkObject parent; + + EShellPrivate *priv; }; -typedef struct { - BonoboObjectClass parent_class; -} EShellClass; +struct _EShellClass { + GtkObjectClass parent_class; +}; -EShell *e_shell_new (void); -void e_shell_register_view (EShell *eshell, EShellView *eshell_view); -void e_shell_unregister_view (EShell *eshell, EShellView *eshell_view); + +GtkType e_shell_get_type (void); +void e_shell_construct (EShell *shell, + const char *local_directory); +EShell *e_shell_new (const char *local_directory); -/* - * New - */ -void e_shell_new_appointment (EShell *eshell); -void e_shell_new_meeting_request (EShell *eshell); -void e_shell_new_task (EShell *eshell); -void e_shell_new_task_request (EShell *eshell); -void e_shell_new_contact (EShell *eshell); -void e_shell_new_mail_message (EShell *eshell); -void e_shell_new_distribution_list (EShell *eshell); -void e_shell_new_journal_entry (EShell *eshell); -void e_shell_new_note (EShell *eshell); - -void e_shell_quit (EShell *eshell); - -#endif /* EVOLUTION_SHELL_H */ +GtkWidget *e_shell_new_view (EShell *shell, + const char *uri); + +EShortcuts *e_shell_get_shortcuts (EShell *shell); +EStorageSet *e_shell_get_storage_set (EShell *shell); +EFolderTypeRepository *e_shell_get_folder_type_repository (EShell *shell); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _E_SHELL_H_ */ diff --git a/shell/e-shortcuts-view.c b/shell/e-shortcuts-view.c new file mode 100644 index 0000000000..8de29c49ce --- /dev/null +++ b/shell/e-shortcuts-view.c @@ -0,0 +1,154 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shortcuts-view.c + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gnome.h> + +#include "e-util/e-util.h" + +#include "e-shortcuts-view.h" + + +#define PARENT_TYPE E_TYPE_SHORTCUT_BAR +static EShortcutBarClass *parent_class = NULL; + +struct _EShortcutsViewPrivate { + EShortcuts *shortcuts; +}; + +enum { + ACTIVATE_SHORTCUT, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + + +static void +destroy (GtkObject *object) +{ + EShortcutsViewPrivate *priv; + EShortcutsView *shortcuts_view; + + shortcuts_view = E_SHORTCUTS_VIEW (object); + + priv = shortcuts_view->priv; + g_free (priv); + + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + + +static void +selected_item (EShortcutBar *shortcut_bar, + GdkEvent *event, + int group_num, + int item_num) +{ + EShortcuts *shortcuts; + const char *uri; + + shortcuts = E_SHORTCUTS_VIEW (shortcut_bar)->priv->shortcuts; + + uri = e_shortcuts_get_uri (shortcuts, group_num, item_num); + + /* Lame EShortcutBar. This can happen. */ + if (uri == NULL) + return; + + gtk_signal_emit (GTK_OBJECT (shortcut_bar), signals[ACTIVATE_SHORTCUT], + shortcuts, uri); +} + + +static void +class_init (EShortcutsViewClass *klass) +{ + GtkObjectClass *object_class; + EShortcutBarClass *shortcut_bar_class; + + object_class = GTK_OBJECT_CLASS (klass); + object_class->destroy = destroy; + + shortcut_bar_class = E_SHORTCUT_BAR_CLASS (klass); + shortcut_bar_class->selected_item = selected_item; + + parent_class = gtk_type_class (e_shortcut_bar_get_type ()); + + signals[ACTIVATE_SHORTCUT] = + gtk_signal_new ("activate_shortcut", + GTK_RUN_LAST | GTK_RUN_ACTION, + object_class->type, + GTK_SIGNAL_OFFSET (EShortcutsViewClass, activate_shortcut), + gtk_marshal_NONE__POINTER_POINTER, + GTK_TYPE_NONE, 2, + GTK_TYPE_POINTER, + GTK_TYPE_STRING); + + gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); +} + +static void +init (EShortcutsView *shortcuts_view) +{ + EShortcutsViewPrivate *priv; + + priv = g_new (EShortcutsViewPrivate, 1); + priv->shortcuts = NULL; + + shortcuts_view->priv = priv; +} + + +void +e_shortcuts_view_construct (EShortcutsView *shortcuts_view, + EShortcuts *shortcuts) +{ + EShortcutsViewPrivate *priv; + + g_return_if_fail (shortcuts != NULL); + g_return_if_fail (E_IS_SHORTCUTS (shortcuts)); + + priv = shortcuts_view->priv; + priv->shortcuts = shortcuts; +} + +GtkWidget * +e_shortcuts_view_new (EShortcuts *shortcuts) +{ + GtkWidget *new; + + g_return_val_if_fail (shortcuts != NULL, NULL); + g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), NULL); + + new = gtk_type_new (e_shortcuts_view_get_type ()); + e_shortcuts_view_construct (E_SHORTCUTS_VIEW (new), shortcuts); + + return new; +} + + +E_MAKE_TYPE (e_shortcuts_view, "EShortcutsView", EShortcutsView, class_init, init, PARENT_TYPE) diff --git a/shell/e-shortcuts-view.h b/shell/e-shortcuts-view.h new file mode 100644 index 0000000000..8f6f8cb0af --- /dev/null +++ b/shell/e-shortcuts-view.h @@ -0,0 +1,76 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shortcuts-view.h + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +#ifndef _E_SHORTCUTS_VIEW_H_ +#define _E_SHORTCUTS_VIEW_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gnome.h> + +#include "shortcut-bar/e-shortcut-bar.h" +#include "e-shortcuts.h" + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define E_TYPE_SHORTCUTS_VIEW (e_shortcuts_view_get_type ()) +#define E_SHORTCUTS_VIEW(obj) (GTK_CHECK_CAST ((obj), E_TYPE_SHORTCUTS_VIEW, EShortcutsView)) +#define E_SHORTCUTS_VIEW_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_SHORTCUTS_VIEW, EShortcutsViewClass)) +#define E_IS_SHORTCUTS_VIEW(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_SHORTCUTS_VIEW)) +#define E_IS_SHORTCUTS_VIEW_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_SHORTCUTS_VIEW)) + + +typedef struct _EShortcutsView EShortcutsView; +typedef struct _EShortcutsViewPrivate EShortcutsViewPrivate; +typedef struct _EShortcutsViewClass EShortcutsViewClass; + +struct _EShortcutsView { + EShortcutBar parent; + + EShortcutsViewPrivate *priv; +}; + +struct _EShortcutsViewClass { + EShortcutBarClass parent_class; + + void (* activate_shortcut) (EShortcutsView *view, + EShortcuts *shortcuts, + const char *uri); +}; + + +GtkType e_shortcuts_view_get_type (void); +void e_shortcuts_view_construct (EShortcutsView *shortcuts_view, + EShortcuts *shortcuts); +GtkWidget *e_shortcuts_view_new (EShortcuts *shortcuts); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _E_SHORTCUTS_VIEW_H_ */ diff --git a/shell/e-shortcuts.c b/shell/e-shortcuts.c new file mode 100644 index 0000000000..09474e9491 --- /dev/null +++ b/shell/e-shortcuts.c @@ -0,0 +1,530 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shortcuts.c + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +/* The shortcut list goes this: + + <?xml version="1.0"?> + <shortcuts> + <group title="Evolution shortcuts"> + <item>evolution:/local/Inbox</item> + <item>evolution:/local/Trash</item> + <item>evolution:/local/Calendar</item> + </group> + + <group title="Personal shortcuts"> + <item>evolution:/local/Personal</item> + </group> + </shortcuts> + + FIXME: Do we want to use a namespace for this? + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gtk/gtkobject.h> +#include <gtk/gtktypeutils.h> + +#include <gnome-xml/parser.h> + +#include <string.h> + +#include "e-util/e-util.h" +#include "e-util/e-xml-utils.h" + +#include "shortcut-bar/e-shortcut-bar.h" +#include "e-shortcuts-view.h" + +#include "e-shortcuts.h" + + +#define PARENT_TYPE GTK_TYPE_OBJECT +static GtkObjectClass *parent_class = NULL; + +struct _ShortcutGroup { + /* Title of the group. */ + char *title; + + /* A list of strings with the URI for the shortcut. */ + GList *shortcuts; +}; +typedef struct _ShortcutGroup ShortcutGroup; + +struct _EShortcutsPrivate { + /* The storage set to which these shortcuts are associated. */ + EStorageSet *storage_set; + + /* The folder type repository. */ + EFolderTypeRepository *folder_type_repository; + + /* A list of ShortcutGroups. */ + GList *groups; + + /* A list of ShortcutViews. */ + GList *views; +}; + + +static void +unload_shortcuts (EShortcuts *shortcuts) +{ + EShortcutsPrivate *priv; + GList *p, *q; + + priv = shortcuts->priv; + + for (p = priv->groups; p != NULL; p = p->next) { + ShortcutGroup *group; + + group = (ShortcutGroup *) p->data; + g_free (group->title); + + for (q = group->shortcuts; q != NULL; q = q->next) + g_free (q->data); + + g_list_free (group->shortcuts); + } + + if (priv->groups != NULL) + g_list_free (priv->groups); + + priv->groups = NULL; + + /* FIXME update the views. */ +} + +static gboolean +load_shortcuts (EShortcuts *shortcuts, + const char *path) +{ + EShortcutsPrivate *priv; + xmlDoc *doc; + xmlNode *root; + xmlNode *p, *q; + + priv = shortcuts->priv; + + doc = xmlParseFile (path); + if (doc == NULL) + return FALSE; + + root = xmlDocGetRootElement (doc); + if (root == NULL || strcmp (root->name, "shortcuts") != 0) { + xmlFreeDoc (doc); + return FALSE; + } + + unload_shortcuts (shortcuts); + + for (p = root->childs; p != NULL; p = p->next) { + ShortcutGroup *shortcut_group; + const char *shortcut_group_title; + + if (strcmp ((char *) p->name, "group") != 0) + continue; + + shortcut_group_title = (const char *) xmlGetProp (p, "title"); + if (shortcut_group_title == NULL) + continue; + + shortcut_group = g_new (ShortcutGroup, 1); + shortcut_group->title = g_strdup (shortcut_group_title); + shortcut_group->shortcuts = NULL; + + for (q = p->childs; q != NULL; q = q->next) { + xmlNode *link_node; + + if (strcmp ((char *) q->name, "item") != 0) + continue; + + link_node = e_xml_get_child_by_name (q, (xmlChar *) "text"); + if (link_node == NULL) + continue; + + shortcut_group->shortcuts = g_list_prepend (shortcut_group->shortcuts, + g_strdup (link_node->content)); + } + + shortcut_group->shortcuts = g_list_reverse (shortcut_group->shortcuts); + + priv->groups = g_list_prepend (priv->groups, shortcut_group); + } + + priv->groups = g_list_reverse (priv->groups); + + xmlFreeDoc (doc); + + return TRUE; +} + +static gboolean +save_shortcuts (EShortcuts *shortcuts, + const char *path) +{ + EShortcutsPrivate *priv; + xmlDoc *doc; + xmlNode *root; + GList *p, *q; + + priv = shortcuts->priv; + + doc = xmlNewDoc ((xmlChar *) "1.0"); + root = xmlNewDocNode (doc, NULL, (xmlChar *) "shortcuts", NULL); + xmlDocSetRootElement (doc, root); + + for (p = priv->groups; p != NULL; p = p->next) { + ShortcutGroup *group; + xmlNode *group_node; + + group = (ShortcutGroup *) p->data; + group_node = xmlNewChild (root, NULL, (xmlChar *) "group", NULL); + + xmlSetProp (group_node, (xmlChar *) "title", group->title); + + for (q = group->shortcuts; q != NULL; q = q->next) { + const char *shortcut; + + shortcut = (const char *) q->data; + xmlNewChild (group_node, NULL, (xmlChar *) "item", (xmlChar *) shortcut); + } + } + + if (xmlSaveFile (path, doc) < 0) { + xmlFreeDoc (doc); + return FALSE; + } + + xmlFreeDoc (doc); + return TRUE; +} + + +/* View initialization. */ + +static const char * +get_storage_set_path_from_uri (const char *uri) +{ + const char *colon; + + if (g_path_is_absolute (uri)) + return NULL; + + colon = strchr (uri, ':'); + if (colon == NULL || colon == uri || colon[1] == '\0') + return NULL; + + if (! g_path_is_absolute (colon + 1)) + return NULL; + + if (g_strncasecmp (uri, "evolution", colon - uri) != 0) + return NULL; + + return colon + 1; +} + +static void +load_folders_into_view (EShortcuts *shortcuts, + EShortcutBar *view, + ShortcutGroup *group, + int group_num) +{ + EStorageSet *storage_set; + GList *p; + + storage_set = shortcuts->priv->storage_set; + + for (p = group->shortcuts; p != NULL; p = p->next) { + EFolder *folder; + const char *path; + const char *uri; + const char *name; + + uri = (const char *) p->data; + path = get_storage_set_path_from_uri (uri); + if (path != NULL) + folder = e_storage_set_get_folder (storage_set, path); + + if (path == NULL || folder == NULL) { + /* FIXME */ + g_warning ("Invalid link while loading shortcut bar view -- %s\n", + uri); + continue; + } + + name = e_folder_get_name (folder); + e_shortcut_bar_add_item (view, group_num, uri, name); + } +} + +static void +load_shortcuts_into_view (EShortcuts *shortcuts, + EShortcutBar *view) +{ + EShortcutsPrivate *priv; + GList *p; + int group_num; + + priv = shortcuts->priv; + + for (p = priv->groups; p != NULL; p = p->next) { + ShortcutGroup *group; + + group = (ShortcutGroup *) p->data; + group_num = e_shortcut_bar_add_group (view, group->title); + + load_folders_into_view (shortcuts, view, group, group_num); + } +} + +/* Icon callback for the shortcut bar. */ +static GdkPixbuf * +icon_callback (EShortcutBar *shortcut_bar, + const char *uri, + gpointer data) +{ + EFolderTypeRepository *folder_type_repository; + EShortcuts *shortcuts; + EStorageSet *storage_set; + EFolder *folder; + GdkPixbuf *pixbuf; + const char *type; + const char *icon_name; + char *icon_path; + + shortcuts = E_SHORTCUTS (data); + + storage_set = shortcuts->priv->storage_set; + folder_type_repository = shortcuts->priv->folder_type_repository; + + folder = e_storage_set_get_folder (storage_set, + get_storage_set_path_from_uri (uri)); + + if (folder == NULL) + return NULL; + + type = e_folder_get_type_string (folder); + if (type == NULL) + return NULL; + + icon_name = e_folder_type_repository_get_icon_for_type (folder_type_repository, type); + if (icon_name == NULL) + return NULL; + + if (g_path_is_absolute (icon_name)) + icon_path = g_strdup (icon_name); + else { + icon_path = gnome_pixmap_file (icon_name); + if (icon_path == NULL) + icon_path = g_concat_dir_and_file (EVOLUTION_IMAGES, icon_name); + } + + if (icon_path == NULL) + return NULL; + + /* FIXME this sucks sucks sucks sucks. We need some caching. Probably + it's better if EFolderTypeRepository returns a GdkPixbuf directly. */ + pixbuf = gdk_pixbuf_new_from_file (icon_path); + + g_free (icon_path); + + return pixbuf; +} + + +/* Signal handlers for the views. */ + +static void +view_destroyed_cb (GtkObject *object, + gpointer data) +{ + EShortcuts *shortcuts; + EShortcutsPrivate *priv; + + shortcuts = E_SHORTCUTS (data); + priv = shortcuts->priv; + + priv->views = g_list_remove (priv->views, object); +} + + +/* GtkObject methods. */ + +static void +destroy (GtkObject *object) +{ + EShortcuts *shortcuts; + EShortcutsPrivate *priv; + + shortcuts = E_SHORTCUTS (object); + priv = shortcuts->priv; + + gtk_object_unref (GTK_OBJECT (priv->storage_set)); + gtk_object_unref (GTK_OBJECT (priv->folder_type_repository)); + + unload_shortcuts (shortcuts); + + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + + +static void +class_init (EShortcutsClass *klass) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass*) klass; + object_class->destroy = destroy; + + parent_class = gtk_type_class (gtk_object_get_type ()); +} + + +static void +init (EShortcuts *shortcuts) +{ + EShortcutsPrivate *priv; + + priv = g_new (EShortcutsPrivate, 1); + priv->storage_set = NULL; + priv->groups = NULL; + priv->views = NULL; + + shortcuts->priv = priv; +} + + +void +e_shortcuts_construct (EShortcuts *shortcuts, + EStorageSet *storage_set, + EFolderTypeRepository *folder_type_repository) +{ + EShortcutsPrivate *priv; + + g_return_if_fail (shortcuts != NULL); + g_return_if_fail (E_IS_SHORTCUTS (shortcuts)); + g_return_if_fail (storage_set != NULL); + g_return_if_fail (E_IS_STORAGE_SET (storage_set)); + + GTK_OBJECT_UNSET_FLAGS (GTK_OBJECT (storage_set), GTK_FLOATING); + + priv = shortcuts->priv; + + gtk_object_ref (GTK_OBJECT (storage_set)); + priv->storage_set = storage_set; + + gtk_object_ref (GTK_OBJECT (folder_type_repository)); + priv->folder_type_repository = folder_type_repository; +} + +EShortcuts * +e_shortcuts_new (EStorageSet *storage_set, + EFolderTypeRepository *folder_type_repository) +{ + EShortcuts *new; + + g_return_val_if_fail (storage_set != NULL, NULL); + g_return_val_if_fail (E_IS_STORAGE_SET (storage_set), NULL); + + new = gtk_type_new (e_shortcuts_get_type ()); + e_shortcuts_construct (new, storage_set, folder_type_repository); + + return new; +} + + +GtkWidget * +e_shortcuts_new_view (EShortcuts *shortcuts) +{ + EShortcutsPrivate *priv; + GtkWidget *new; + + g_return_val_if_fail (shortcuts != NULL, NULL); + g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), NULL); + + priv = shortcuts->priv; + + new = e_shortcuts_view_new (shortcuts); + priv->views = g_list_prepend (priv->views, new); + + e_shortcut_bar_set_icon_callback (E_SHORTCUT_BAR (new), + icon_callback, shortcuts); + + load_shortcuts_into_view (shortcuts, E_SHORTCUT_BAR (new)); + + gtk_signal_connect (GTK_OBJECT (new), "destroy", view_destroyed_cb, shortcuts); + + return new; +} + + +gboolean +e_shortcuts_load (EShortcuts *shortcuts, + const char *path) +{ + g_return_val_if_fail (shortcuts != NULL, FALSE); + g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), FALSE); + g_return_val_if_fail (path != NULL, FALSE); + g_return_val_if_fail (g_path_is_absolute (path), FALSE); + + return load_shortcuts (shortcuts, path); +} + +gboolean +e_shortcuts_save (EShortcuts *shortcuts, + const char *path) +{ + g_return_val_if_fail (shortcuts != NULL, FALSE); + g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), FALSE); + g_return_val_if_fail (path != NULL, FALSE); + g_return_val_if_fail (g_path_is_absolute (path), FALSE); + + return save_shortcuts (shortcuts, path); +} + + +const char * +e_shortcuts_get_uri (EShortcuts *shortcuts, int group_num, int num) +{ + EShortcutsPrivate *priv; + ShortcutGroup *group; + GList *shortcut_element; + + g_return_val_if_fail (shortcuts != NULL, NULL); + g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), NULL); + + priv = shortcuts->priv; + + group = g_list_nth (priv->groups, group_num)->data; + if (group == NULL) + return NULL; + + shortcut_element = g_list_nth (group->shortcuts, num); + if (shortcut_element == NULL) + return NULL; + + return shortcut_element->data; +} + + +E_MAKE_TYPE (e_shortcuts, "EShortcuts", EShortcuts, class_init, init, PARENT_TYPE) diff --git a/shell/e-shortcuts.h b/shell/e-shortcuts.h new file mode 100644 index 0000000000..569ff9ead5 --- /dev/null +++ b/shell/e-shortcuts.h @@ -0,0 +1,85 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shortcuts.h + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +#ifndef _E_SHORTCUTS_H_ +#define _E_SHORTCUTS_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gtk/gtkwidget.h> + +#include "e-folder-type-repository.h" +#include "e-storage-set.h" + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define E_TYPE_SHORTCUTS (e_shortcuts_get_type ()) +#define E_SHORTCUTS(obj) (GTK_CHECK_CAST ((obj), E_TYPE_SHORTCUTS, EShortcuts)) +#define E_SHORTCUTS_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_SHORTCUTS, EShortcutsClass)) +#define E_IS_SHORTCUTS(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_SHORTCUTS)) +#define E_IS_SHORTCUTS_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_SHORTCUTS)) + + +typedef struct _EShortcuts EShortcuts; +typedef struct _EShortcutsPrivate EShortcutsPrivate; +typedef struct _EShortcutsClass EShortcutsClass; + +struct _EShortcuts { + GtkObject parent; + + EShortcutsPrivate *priv; +}; + +struct _EShortcutsClass { + GtkObjectClass parent_class; +}; + + +GtkType e_shortcuts_get_type (void); +void e_shortcuts_construct (EShortcuts *shortcuts, + EStorageSet *storage_set, + EFolderTypeRepository *folder_type_repository); +EShortcuts *e_shortcuts_new (EStorageSet *storage_set, + EFolderTypeRepository *folder_type_repository); + +GtkWidget *e_shortcuts_new_view (EShortcuts *shortcuts); + +gboolean e_shortcuts_load (EShortcuts *shortcuts, + const char *path); +gboolean e_shortcuts_save (EShortcuts *shortcuts, + const char *path); + +const char *e_shortcuts_get_uri (EShortcuts *shortcuts, + int group_num, + int num); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _E_SHORTCUTS_H_ */ diff --git a/shell/e-storage-set.c b/shell/e-storage-set.c new file mode 100644 index 0000000000..df1096695d --- /dev/null +++ b/shell/e-storage-set.c @@ -0,0 +1,266 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-storage-set.c + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gtk/gtkobject.h> +#include <gtk/gtksignal.h> +#include <gtk/gtktypeutils.h> + +#include <string.h> + +#include "e-util/e-util.h" + +#include "e-storage-set.h" + + +enum { + NEW_STORAGE, + REMOVED_STORAGE, + LAST_SIGNAL +}; + + +#define PARENT_TYPE GTK_TYPE_OBJECT + +static GtkObjectClass *parent_class = NULL; +static guint signals[LAST_SIGNAL] = { 0 }; + +struct _EStorageSetPrivate { + GList *storages; +}; + + +/* GtkObject methods. */ + +static void +destroy (GtkObject *object) +{ + EStorageSet *storage_set; + EStorageSetPrivate *priv; + + storage_set = E_STORAGE_SET (object); + priv = storage_set->priv; + + e_free_object_list (priv->storages); + + g_free (priv); + + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + + +static void +class_init (EStorageSetClass *klass) +{ + GtkObjectClass *object_class; + + parent_class = gtk_type_class (gtk_object_get_type ()); + + object_class = (GtkObjectClass*) klass; + + object_class->destroy = destroy; + + signals[NEW_STORAGE] = + gtk_signal_new ("new_storage", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (EStorageSetClass, new_storage), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, + GTK_TYPE_POINTER); + signals[REMOVED_STORAGE] = + gtk_signal_new ("removed_storage", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (EStorageSetClass, removed_storage), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, + GTK_TYPE_POINTER); + + gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); +} + +static void +init (EStorageSet *storage_set) +{ + EStorageSetPrivate *priv; + + priv = g_new (EStorageSetPrivate, 1); + + priv->storages = NULL; + + storage_set->priv = priv; +} + + +void +e_storage_set_construct (EStorageSet *storage_set) +{ + g_return_if_fail (storage_set != NULL); + g_return_if_fail (E_IS_STORAGE_SET (storage_set)); + + GTK_OBJECT_UNSET_FLAGS (storage_set, GTK_FLOATING); +} + +EStorageSet * +e_storage_set_new (void) +{ + EStorageSet *new; + + new = gtk_type_new (e_storage_set_get_type ()); + + e_storage_set_construct (new); + + return new; +} + + +GList * +e_storage_set_get_storage_list (EStorageSet *storage_set) +{ + EStorageSetPrivate *priv; + GList *list; + GList *p; + + g_return_val_if_fail (storage_set != NULL, NULL); + g_return_val_if_fail (E_IS_STORAGE_SET (storage_set), NULL); + + priv = storage_set->priv; + + list = NULL; + for (p = priv->storages; p != NULL; p = p->next) { + gtk_object_ref (GTK_OBJECT (p->data)); + list = g_list_prepend (list, p->data); + } + + return g_list_reverse (list); /* Lame. */ +} + +/** + * e_storage_set_add_storage: + * @storage_set: + * @storage: + * + * Add @storage to @storage_set. Notice that this won't ref the @storage, so + * after the call @storage_set actually owns @storage. + **/ +void +e_storage_set_add_storage (EStorageSet *storage_set, + EStorage *storage) +{ + EStorageSetPrivate *priv; + + g_return_if_fail (storage_set != NULL); + g_return_if_fail (E_IS_STORAGE_SET (storage_set)); + g_return_if_fail (storage != NULL); + g_return_if_fail (E_IS_STORAGE (storage)); + + priv = storage_set->priv; + + priv->storages = g_list_append (priv->storages, storage); + + gtk_signal_emit (GTK_OBJECT (storage_set), signals[NEW_STORAGE], storage); +} + +void +e_storage_set_remove_storage (EStorageSet *storage_set, + EStorage *storage) +{ + EStorageSetPrivate *priv; + + g_return_if_fail (storage_set != NULL); + g_return_if_fail (E_IS_STORAGE_SET (storage_set)); + g_return_if_fail (storage != NULL); + g_return_if_fail (E_IS_STORAGE (storage)); + + priv = storage_set->priv; + + priv->storages = g_list_remove (priv->storages, storage); + + gtk_signal_emit (GTK_OBJECT (storage_set), signals[REMOVED_STORAGE], storage); + + gtk_object_unref (GTK_OBJECT (storage)); +} + +EStorage * +e_storage_set_get_storage (EStorageSet *storage_set, + const char *name) +{ + EStorageSetPrivate *priv; + GList *p; + + g_return_val_if_fail (storage_set != NULL, NULL); + g_return_val_if_fail (E_IS_STORAGE_SET (storage_set), NULL); + g_return_val_if_fail (name != NULL, NULL); + + priv = storage_set->priv; + + for (p = priv->storages; p != NULL; p = p->next) { + const char *storage_name; + EStorage *storage; + + storage = E_STORAGE (p->data); + storage_name = e_storage_get_name (storage); + if (strcmp (storage_name, name) == 0) + return storage; + } + + return NULL; +} + +EFolder * +e_storage_set_get_folder (EStorageSet *storage_set, + const char *path) +{ + EStorage *storage; + const char *first_separator; + char *storage_name; + + g_return_val_if_fail (storage_set != NULL, NULL); + g_return_val_if_fail (E_IS_STORAGE_SET (storage_set), NULL); + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (g_path_is_absolute (path), NULL); + + /* Skip initial separator. */ + path++; + + first_separator = strchr (path, G_DIR_SEPARATOR); + + if (first_separator == NULL || first_separator == path || first_separator[1] == 0) + return NULL; + + storage_name = g_strndup (path, first_separator - path); + storage = e_storage_set_get_storage (storage_set, storage_name); + g_free (storage_name); + + if (storage == NULL) + return NULL; + + return e_storage_get_folder (storage, first_separator); +} + + +E_MAKE_TYPE (e_storage_set, "EStorageSet", EStorageSet, class_init, init, PARENT_TYPE) diff --git a/shell/e-storage-set.h b/shell/e-storage-set.h new file mode 100644 index 0000000000..1131a7e0f7 --- /dev/null +++ b/shell/e-storage-set.h @@ -0,0 +1,87 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-storage-set.h + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +#ifndef _E_STORAGE_SET_H_ +#define _E_STORAGE_SET_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "e-storage.h" + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define E_TYPE_STORAGE_SET (e_storage_set_get_type ()) +#define E_STORAGE_SET(obj) (GTK_CHECK_CAST ((obj), E_TYPE_STORAGE_SET, EStorageSet)) +#define E_STORAGE_SET_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_STORAGE_SET, EStorageSetClass)) +#define E_IS_STORAGE_SET(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_STORAGE_SET)) +#define E_IS_STORAGE_SET_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_STORAGE_SET)) + + +typedef struct _EStorageSet EStorageSet; +typedef struct _EStorageSetPrivate EStorageSetPrivate; +typedef struct _EStorageSetClass EStorageSetClass; + +struct _EStorageSet { + GtkObject parent; + + EStorageSetPrivate *priv; +}; + +struct _EStorageSetClass { + GtkObjectClass parent_class; + + /* Virtual methods. */ + + void (* add_storage) (EStorageSet *storage_set, EStorage *storage); + void (* remove_storage) (EStorageSet *storage_set, EStorage *storage); + + /* Signals. */ + + void (* new_storage) (EStorageSet *storage_set, EStorage *storage); + void (* removed_storage) (EStorageSet *storage_set, EStorage *storage); +}; + + +GtkType e_storage_set_get_type (void); +void e_storage_set_construct (EStorageSet *storage_set); +EStorageSet *e_storage_set_new (void); + +GList *e_storage_set_get_storage_list (EStorageSet *storage_set); +EStorage *e_storage_set_get_storage (EStorageSet *storage_set, const char *name); + +void e_storage_set_add_storage (EStorageSet *storage_set, EStorage *storage); +void e_storage_set_remove_storage (EStorageSet *storage_set, EStorage *storage); + +EStorage *e_storage_get_storage (EStorageSet *storage_set, const char *storage_name); +EFolder *e_storage_set_get_folder (EStorageSet *storage_set, const char *path); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _E_STORAGE_SET_H_ */ diff --git a/shell/e-storage-watcher.c b/shell/e-storage-watcher.c new file mode 100644 index 0000000000..8312273d27 --- /dev/null +++ b/shell/e-storage-watcher.c @@ -0,0 +1,188 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-storage-watcher.c + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gtk/gtk.h> + +#include "e-util/e-util.h" + +#include "e-storage-watcher.h" + + +#define PARENT_TYPE gtk_object_get_type () +static GtkObjectClass *parent_class = NULL; + +struct _EStorageWatcherPrivate { + EStorage *storage; + char *path; +}; + + +enum { + NEW_FOLDER, + REMOVED_FOLDER, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + + +/* GtkObject methods. */ + +static void +destroy (GtkObject *object) +{ + EStorageWatcher *storage_watcher; + EStorageWatcherPrivate *priv; + + storage_watcher = E_STORAGE_WATCHER (object); + priv = storage_watcher->priv; + + g_free (priv->path); + g_free (priv); + + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + + +/* Initialization. */ + +static void +class_init (EStorageWatcherClass *klass) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass*) klass; + object_class->destroy = destroy; + + parent_class = gtk_type_class (gtk_object_get_type ()); + + signals[NEW_FOLDER] = + gtk_signal_new ("new_folder", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (EStorageWatcherClass, new_folder), + gtk_marshal_NONE__POINTER_STRING_STRING, + GTK_TYPE_NONE, 2, + GTK_TYPE_STRING, + GTK_TYPE_STRING); + signals[REMOVED_FOLDER] = + gtk_signal_new ("removed_folder", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (EStorageWatcherClass, removed_folder), + gtk_marshal_NONE__POINTER_STRING_STRING, + GTK_TYPE_NONE, 2, + GTK_TYPE_STRING, + GTK_TYPE_STRING); + + gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); +} + +static void +init (EStorageWatcher *storage_watcher) +{ + EStorageWatcherPrivate *priv; + + priv = g_new (EStorageWatcherPrivate, 1); + priv->storage = NULL; + priv->path = NULL; + + storage_watcher->priv = priv; +} + + +/* Initialization. */ + +void +e_storage_watcher_construct (EStorageWatcher *watcher, + EStorage *storage, + const char *path) +{ + EStorageWatcherPrivate *priv; + + g_return_if_fail (watcher != NULL); + g_return_if_fail (E_IS_STORAGE_WATCHER (watcher)); + g_return_if_fail (path != NULL); + + GTK_OBJECT_UNSET_FLAGS (GTK_OBJECT (watcher), GTK_FLOATING); + + priv = watcher->priv; + + priv->storage = storage; + priv->path = g_strdup (path); +} + +EStorageWatcher * +e_storage_watcher_new (EStorage *storage, + const char *path) +{ + EStorageWatcher *watcher; + + g_return_val_if_fail (path != NULL, NULL); + + watcher = gtk_type_new (e_storage_watcher_get_type ()); + + e_storage_watcher_construct (watcher, storage, path); + + return watcher; +} + + +const char * +e_storage_watcher_get_path (EStorageWatcher *storage_watcher) +{ + g_return_val_if_fail (storage_watcher != NULL, NULL); + g_return_val_if_fail (E_IS_STORAGE_WATCHER (storage_watcher), NULL); + + return storage_watcher->priv->path; +} + + +void +e_storage_watcher_emit_new_folder (EStorageWatcher *storage_watcher, + const char *name) +{ + g_return_if_fail (storage_watcher != NULL); + g_return_if_fail (E_IS_STORAGE_WATCHER (storage_watcher)); + g_return_if_fail (name != NULL); + + gtk_signal_emit (GTK_OBJECT (storage_watcher), signals[NEW_FOLDER], name); +} + +void +e_storage_watcher_emit_removed_folder (EStorageWatcher *storage_watcher, + const char *name) +{ + g_return_if_fail (storage_watcher != NULL); + g_return_if_fail (E_IS_STORAGE_WATCHER (storage_watcher)); + g_return_if_fail (name != NULL); + + gtk_signal_emit (GTK_OBJECT (storage_watcher), signals[REMOVED_FOLDER], name); +} + + +E_MAKE_TYPE (e_storage_watcher, "EStorageWatcher", EStorageWatcher, class_init, init, PARENT_TYPE) diff --git a/shell/e-storage-watcher.h b/shell/e-storage-watcher.h new file mode 100644 index 0000000000..26c6edffaf --- /dev/null +++ b/shell/e-storage-watcher.h @@ -0,0 +1,93 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-storage-watcher.h + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +#ifndef _E_STORAGE_WATCHER_H_ +#define _E_STORAGE_WATCHER_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gtk/gtkobject.h> + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define E_TYPE_STORAGE_WATCHER (e_storage_watcher_get_type ()) +#define E_STORAGE_WATCHER(obj) (GTK_CHECK_CAST ((obj), E_TYPE_STORAGE_WATCHER, EStorageWatcher)) +#define E_STORAGE_WATCHER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_STORAGE_WATCHER, EStorageWatcherClass)) +#define E_IS_STORAGE_WATCHER(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_STORAGE_WATCHER)) +#define E_IS_STORAGE_WATCHER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_STORAGE_WATCHER)) + + +typedef struct _EStorageWatcher EStorageWatcher; +typedef struct _EStorageWatcherPrivate EStorageWatcherPrivate; +typedef struct _EStorageWatcherClass EStorageWatcherClass; + +#include "e-storage.h" + +struct _EStorageWatcher { + GtkObject parent; + + EStorageWatcherPrivate *priv; +}; + +struct _EStorageWatcherClass +{ + GtkObjectClass parent_class; + + /* Signals. */ + + void (* new_folder) (EStorageWatcher *storage_watcher, + EStorage *storage, + const char *path, + const char *name); + + void (* removed_folder) (EStorageWatcher *storage_watcher, + EStorage *storage, + const char *path, + const char *name); +}; + + +GtkType e_storage_watcher_get_type (void); +void e_storage_watcher_construct (EStorageWatcher *watcher, + EStorage *storage, + const char *path); +EStorageWatcher *e_storage_watcher_new (EStorage *storage, + const char *path); + +const char *e_storage_watcher_get_path (EStorageWatcher *storage_watcher); + +void e_storage_watcher_emit_new_folder (EStorageWatcher *storage_watcher, + const char *name); +void e_storage_watcher_emit_removed_folder (EStorageWatcher *storage_watcher, + const char *name); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __E_STORAGE_WATCHER_H__ */ diff --git a/shell/e-storage.c b/shell/e-storage.c new file mode 100644 index 0000000000..5d5b1dd7a8 --- /dev/null +++ b/shell/e-storage.c @@ -0,0 +1,473 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-storage.c + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gtk/gtkobject.h> +#include <gtk/gtksignal.h> + +#include <gnome.h> + +#include "e-util/e-util.h" + +#include "e-storage.h" + + +#define PARENT_TYPE GTK_TYPE_OBJECT +static GtkObjectClass *parent_class = NULL; + +#define ES_CLASS(obj) \ + E_STORAGE_CLASS (GTK_OBJECT (obj)->klass) + +struct _WatcherList { + char *path; + GList *watchers; +}; +typedef struct _WatcherList WatcherList; + +/* This describes a folder and its children. */ +struct _Folder { + struct _Folder *parent; + EFolder *e_folder; + GList *subfolders; +}; +typedef struct _Folder Folder; + +struct _EStoragePrivate { + GHashTable *path_to_watcher_list; + GHashTable *watcher_to_watcher_list; + + /* Every element here is a list of subfolders, hashed to the path of the parent. */ + GHashTable *path_to_folder; +}; + + +static Folder * +folder_new (EFolder *e_folder) +{ + Folder *folder; + + folder = g_new (Folder, 1); + folder->parent = NULL; + folder->e_folder = e_folder; + folder->subfolders = NULL; + + return folder; +} + +static void +folder_remove_subfolder (Folder *folder, Folder *subfolder) +{ + g_list_remove (folder->subfolders, folder); +} + +static void +folder_add_subfolder (Folder *folder, Folder *subfolder) +{ + folder->subfolders = g_list_prepend (folder->subfolders, subfolder); + subfolder->parent = folder; +} + +static void +folder_destroy (Folder *folder) +{ + GList *p; + + if (folder->parent != NULL) + folder_remove_subfolder (folder->parent, folder); + + gtk_object_unref (GTK_OBJECT (folder->e_folder)); + + for (p = folder->subfolders; p != NULL; p = p->next) + folder_destroy (p->data); + + g_free (folder); +} + + +/* Watcher management. */ + +static void +watcher_destroyed_cb (GtkObject *object, + gpointer data) +{ + EStorageWatcher *watcher; + EStorage *storage; + EStoragePrivate *priv; + WatcherList *list; + + watcher = E_STORAGE_WATCHER (object); + storage = E_STORAGE (data); + priv = storage->priv; + + list = g_hash_table_lookup (priv->watcher_to_watcher_list, watcher); + g_return_if_fail (list != NULL); + + list->watchers = g_list_remove (list->watchers, watcher); +} + +static void +free_watcher_list (EStorage *storage, + WatcherList *watcher_list) +{ + GtkObject *watcher_object; + GList *p; + + for (p = watcher_list->watchers; p != NULL; p = p->next) { + watcher_object = GTK_OBJECT (p->data); + gtk_signal_disconnect_by_func (watcher_object, watcher_destroyed_cb, storage); + + gtk_object_destroy (watcher_object); /* Make sure it does not live when we are dead. */ + gtk_object_unref (watcher_object); + } + + g_free (watcher_list->path); + + g_free (watcher_list); +} + +static void +hash_foreach_free_watcher_list (gpointer key, + gpointer value, + gpointer data) +{ + WatcherList *watcher_list; + EStorage *storage; + + storage = E_STORAGE (data); + watcher_list = (WatcherList *) value; + + free_watcher_list (storage, watcher_list); +} + +static void +free_private (EStorage *storage) +{ + EStoragePrivate *priv; + + priv = storage->priv; + + g_hash_table_foreach (priv->path_to_watcher_list, hash_foreach_free_watcher_list, storage); + g_hash_table_destroy (priv->path_to_watcher_list); + + g_hash_table_destroy (priv->watcher_to_watcher_list); + + g_free (priv); +} + + +/* EStorage methods. */ + +static GList * +list_folders (EStorage *storage, + const char *path) +{ + Folder *folder; + Folder *subfolder; + GList *list; + GList *p; + + folder = g_hash_table_lookup (storage->priv->path_to_folder, path); + if (folder == NULL) + return NULL; + + list = NULL; + for (p = folder->subfolders; p != NULL; p = p->next) { + subfolder = (Folder *) p->data; + + gtk_object_ref (GTK_OBJECT (subfolder->e_folder)); + list = g_list_prepend (list, subfolder->e_folder); + } + + return list; +} + +static EStorageWatcher * +get_watcher_for_path (EStorage *storage, + const char *path) +{ + EStoragePrivate *priv; + EStorageWatcher *watcher; + WatcherList *watcher_list; + + priv = storage->priv; + + watcher = e_storage_watcher_new (storage, path); + + watcher_list = g_hash_table_lookup (priv->path_to_watcher_list, path); + if (watcher_list == NULL) { + watcher_list = g_new (WatcherList, 1); + watcher_list->path = g_strdup (path); + watcher_list->watchers = NULL; + + g_hash_table_insert (priv->path_to_watcher_list, watcher_list->path, watcher_list); + } + + g_hash_table_insert (priv->watcher_to_watcher_list, watcher, watcher_list); + + watcher_list->watchers = g_list_prepend (watcher_list->watchers, watcher); + + gtk_signal_connect (GTK_OBJECT (watcher), "destroy", + GTK_SIGNAL_FUNC (watcher_destroyed_cb), storage); + + return watcher; +} + +static EFolder * +get_folder (EStorage *storage, + const char *path) +{ + EStoragePrivate *priv; + Folder *folder; + + priv = storage->priv; + + folder = g_hash_table_lookup (priv->path_to_folder, path); + if (folder == NULL) + return NULL; + + return folder->e_folder; +} + +static const char * +get_name (EStorage *storage) +{ + return "(No name)"; +} + + +/* GtkObject methods. */ + +static void +destroy (GtkObject *object) +{ + EStorage *storage; + + storage = E_STORAGE (object); + + free_private (storage); + + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + + +/* Initialization. */ + +static void +class_init (EStorageClass *class) +{ + GtkObjectClass *object_class; + + object_class = GTK_OBJECT_CLASS (class); + parent_class = gtk_type_class (gtk_object_get_type ()); + + object_class->destroy = destroy; + + class->list_folders = list_folders; + class->get_watcher_for_path = get_watcher_for_path; + class->get_folder = get_folder; + class->get_name = get_name; +} + +static void +init (EStorage *storage) +{ + EStoragePrivate *priv; + + priv = g_new (EStoragePrivate, 1); + + priv->path_to_watcher_list = g_hash_table_new (g_str_hash, g_str_equal); + priv->watcher_to_watcher_list = g_hash_table_new (g_direct_hash, g_direct_equal); + priv->path_to_folder = g_hash_table_new (g_str_hash, g_str_equal); + + storage->priv = priv; +} + + +/* Creation. */ + +void +e_storage_construct (EStorage *storage) +{ + Folder *root_folder; + + g_return_if_fail (storage != NULL); + g_return_if_fail (E_IS_STORAGE (storage)); + + GTK_OBJECT_UNSET_FLAGS (GTK_OBJECT (storage), GTK_FLOATING); + + root_folder = folder_new (NULL); + g_hash_table_insert (storage->priv->path_to_folder, G_DIR_SEPARATOR_S, root_folder); +} + +EStorage * +e_storage_new (void) +{ + EStorage *new; + + new = gtk_type_new (e_storage_get_type ()); + + e_storage_construct (new); + + return new; +} + + +gboolean +e_storage_path_is_absolute (const char *path) +{ + g_return_val_if_fail (path != NULL, FALSE); + + return *path == G_DIR_SEPARATOR; +} + +gboolean +e_storage_path_is_relative (const char *path) +{ + g_return_val_if_fail (path != NULL, FALSE); + + return *path != G_DIR_SEPARATOR; +} + + +GList * +e_storage_list_folders (EStorage *storage, + const char *path) +{ + g_return_val_if_fail (storage != NULL, NULL); + g_return_val_if_fail (E_IS_STORAGE (storage), NULL); + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (g_path_is_absolute (path), NULL); + + return (* ES_CLASS (storage)->list_folders) (storage, path); +} + +EStorageWatcher * +e_storage_get_watcher_for_path (EStorage *storage, const char *path) +{ + g_return_val_if_fail (storage != NULL, NULL); + g_return_val_if_fail (E_IS_STORAGE (storage), NULL); + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (e_storage_path_is_absolute (path), NULL); + + return (* ES_CLASS (storage)->get_watcher_for_path) (storage, path); +} + +EFolder * +e_storage_get_folder (EStorage *storage, + const char *path) +{ + g_return_val_if_fail (storage != NULL, NULL); + g_return_val_if_fail (E_IS_STORAGE (storage), NULL); + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (e_storage_path_is_absolute (path), NULL); + + return (* ES_CLASS (storage)->get_folder) (storage, path); +} + +const char * +e_storage_get_name (EStorage *storage) +{ + g_return_val_if_fail (storage != NULL, NULL); + g_return_val_if_fail (E_IS_STORAGE (storage), NULL); + + return (* ES_CLASS (storage)->get_name) (storage); +} + + +/* These functions are used by subclasses to add and remove folders from the + state stored in the storage object. */ + +void +e_storage_new_folder (EStorage *storage, + const char *path, + EFolder *e_folder) +{ + EStoragePrivate *priv; + Folder *folder; + Folder *parent_folder; + const char *name; + char *full_path; + + g_return_if_fail (storage != NULL); + g_return_if_fail (E_IS_STORAGE (storage)); + g_return_if_fail (path != NULL); + g_return_if_fail (g_path_is_absolute (path)); + g_return_if_fail (e_folder != NULL); + g_return_if_fail (E_IS_FOLDER (e_folder)); + + priv = storage->priv; + + parent_folder = g_hash_table_lookup (priv->path_to_folder, path); + if (parent_folder == NULL) { + g_warning ("%s: Trying to add a subfolder to a path that does not exist yet -- %s", + __FUNCTION__, path); + return; + } + + name = e_folder_get_name (e_folder); + g_assert (name != NULL); + g_return_if_fail (*name != G_DIR_SEPARATOR); + + full_path = g_concat_dir_and_file (path, name); + + folder = g_hash_table_lookup (priv->path_to_folder, full_path); + if (folder != NULL) { + g_warning ("%s: Trying to add a subfolder for a path that already exists -- %s", + __FUNCTION__, full_path); + return; + } + + folder = folder_new (e_folder); + folder_add_subfolder (parent_folder, folder); + + g_hash_table_insert (priv->path_to_folder, full_path, folder); +} + +void +e_storage_remove_folder (EStorage *storage, + const char *path) +{ + EStoragePrivate *priv; + Folder *folder; + + g_return_if_fail (storage != NULL); + g_return_if_fail (E_IS_STORAGE (storage)); + g_return_if_fail (path != NULL); + g_return_if_fail (g_path_is_absolute (path)); + + priv = storage->priv; + + folder = g_hash_table_lookup (priv->path_to_folder, path); + if (folder == NULL) { + g_warning ("%s: Folder not found -- %s", __FUNCTION__, path); + return; + } + + folder_destroy (folder); +} + + +E_MAKE_TYPE (e_storage, "EStorage", EStorage, class_init, init, PARENT_TYPE) diff --git a/shell/e-storage.h b/shell/e-storage.h new file mode 100644 index 0000000000..9c54f05eb8 --- /dev/null +++ b/shell/e-storage.h @@ -0,0 +1,93 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-storage.h + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +#ifndef _E_STORAGE_H_ +#define _E_STORAGE_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gtk/gtkobject.h> + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define E_TYPE_STORAGE (e_storage_get_type ()) +#define E_STORAGE(obj) (GTK_CHECK_CAST ((obj), E_TYPE_STORAGE, EStorage)) +#define E_STORAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_STORAGE, EStorageClass)) +#define E_IS_STORAGE(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_STORAGE)) +#define E_IS_STORAGE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_STORAGE)) + + +typedef struct _EStorage EStorage; +typedef struct _EStoragePrivate EStoragePrivate; +typedef struct _EStorageClass EStorageClass; + +#include "e-folder.h" +#include "e-storage-watcher.h" + +struct _EStorage { + GtkObject parent; + + EStoragePrivate *priv; +}; + +struct _EStorageClass { + GtkObjectClass parent_class; + + /* Virtual methods. */ + GList * (* list_folders) (EStorage *storage, const char *path); + EStorageWatcher * (* get_watcher_for_path) (EStorage *storage, const char *path); + EFolder * (* get_folder) (EStorage *storage, const char *path); + const char * (* get_name) (EStorage *storage); +}; + + +GtkType e_storage_get_type (void); +void e_storage_construct (EStorage *storage); +EStorage *e_storage_new (void); + +gboolean e_storage_path_is_relative (const char *path); +gboolean e_storage_path_is_absolute (const char *path); + +GList *e_storage_list_folders (EStorage *storage, + const char *path); +EStorageWatcher *e_storage_get_watcher_for_path (EStorage *storage, + const char *path); +EFolder *e_storage_get_folder (EStorage *storage, + const char *path); + +const char *e_storage_get_name (EStorage *storage); + +/* Protected. C++ anyone? */ +void e_storage_new_folder (EStorage *storage, const char *path, EFolder *folder); +void e_storage_remove_folder (EStorage *storage, const char *path); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _E_STORAGE_H_ */ diff --git a/shell/evolution-directory.idl b/shell/evolution-directory.idl new file mode 100644 index 0000000000..76dc184528 --- /dev/null +++ b/shell/evolution-directory.idl @@ -0,0 +1,89 @@ +/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * evolution-directory.idl + * + * Copyright (C) 1999 Helix Code, Inc. + * + * This interface is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +module Evolution { + struct FolderInfo { + /* Name of the folder, i.e. the last part of the path. */ + string name; + + /* Name of the service handling this folder, e.g. "mail" + or "calendar" or "contacts". */ + string service_name; + }; + + /* Listener interface associated to the directory. */ + interface DirectoryListener { + enum Result { + SUCCESS, + IN_PROGRESS, + NOT_FOUND, + OVERWRITING + }; + + typedef int ListenerHandle; + + /* You get this when you first open a path in the directory. */ + void open_result (in string path, in ListenerHandle handle); + + /* This is called to inform the listener that there is a new folder in the + specified path. */ + void new_folder (in string path, in FolderInfo info); + + /* This informs the listener that a folder does not exist anymore. */ + void removed_folder (in string path, in string name); + + /* These report result of the corresponding operation. If this implies a + change in the directory, the listener will also get `new_folder' and + `removed_folder' calls appropriately. */ + void remove_folder_result (in string path, in Result result); + void create_folder_result (in string path, in Result result); + void copy_folder_result (in string old_path, in string new_path, in Result result); + void move_folder_result (in string old_path, in string new_path, in Result result); + + /* This reports the result for a `get_folder' operation. */ + void get_folder_result (in string path, in Result, in FolderInfo info); + }; + + interface Directory { + /* Open a subpath in the directory. @listener will be updated of all the + changes in it. */ + void open (in string path, in DirectoryListener listener); + + /* This removes a listener. @handle is passed through `open_result' after + the initial `open' call. */ + void close (in ListenerHandle handle); + + /* These calls create/remove a folder in the folder specified by @path. + An empty @path corresponds to the root of the directory. */ + void create_folder (in string path, in FolderInfo info); + void remove_folder (in string path, in string name); + + /* These are used to copy or move folders around. */ + void copy_folder (in string old_path, in string new_path); + void move_folder (in string old_path, in string new_path); + + /* This call retrieves information for a folder. */ + void get_folder (in string path); + }; +}; diff --git a/shell/main.c b/shell/main.c index 9fa59a6ee0..eda9f10b23 100644 --- a/shell/main.c +++ b/shell/main.c @@ -1,139 +1,99 @@ -/* - * Main evolution shell application +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* .c * - * Authors: - * Miguel de Icaza (miguel@helixcode.com) + * Copyright (C) 2000 Helix Code, Inc. * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli */ -#include <config.h> - #include <gnome.h> #include <bonobo.h> -#include <e-util/e-gui-utils.h> -#include <e-util/e-cursors.h> -#include <e-util/e-setup.h> /* for e_setup_base_dir */ -#include <glade/glade.h> -#include <glade/glade-xml.h> -#ifdef USING_OAF -#include <liboaf/liboaf.h> -#else -#include <libgnorba/gnorba.h> -#endif +#include "e-util/e-gui-utils.h" +#include "e-setup.h" #include "e-shell.h" -#include "e-shell-view.h" - -int shell_debugging = 0; - -poptContext ctx; - -EShell *eshell; - -const struct poptOption shell_popt_options [] = { - { "debug", '\0', POPT_ARG_INT, &shell_debugging, 0, - N_("Enables some debugging functions"), N_("LEVEL") }, - { NULL, '\0', 0, NULL, 0 } -}; #ifdef USING_OAF +#include <liboaf/liboaf.h> + static void -corba_init (int *argc, char *argv []) +init_corba (int *argc, char **argv) { - gnomelib_register_popt_table (shell_popt_options, "Evolution shell options"); - - gnome_init_with_popt_table ("Evolution", VERSION, *argc, argv, - oaf_popt_options, 0, NULL); + gnome_init_with_popt_table ("Evolution", VERSION, *argc, argv, oaf_popt_options, 0, NULL); oaf_init (*argc, argv); } #else /* USING_OAF */ +#include <libgnorba/gnorba.h> + static void -corba_init (int *argc, char *argv []) +init_corba (int *argc, char **argv) { CORBA_Environment ev; CORBA_exception_init (&ev); - gnome_CORBA_init_with_popt_table ( - "Evolution", VERSION, argc, argv, - shell_popt_options, 0, &ctx, GNORBA_INIT_SERVER_FUNC, &ev); + + gnome_CORBA_init_with_popt_table ("Evolution", VERSION, argc, argv, + shell_popt_options, 0, &ctx, + GNORBA_INIT_SERVER_FUNC, &ev); + + if (ev._major != CORBA_NO_EXCEPTION) + g_error ("Cannot initialize GNOME"); + CORBA_exception_free (&ev); } #endif /* USING_OAF */ -static void -init_bonobo (void) + +int +main (int argc, char **argv) { - if (bonobo_init (CORBA_OBJECT_NIL, CORBA_OBJECT_NIL, CORBA_OBJECT_NIL) == FALSE){ + EShell *shell; + char *evolution_directory; + + init_corba (&argc, argv); + + if (! bonobo_init (CORBA_OBJECT_NIL, CORBA_OBJECT_NIL, CORBA_OBJECT_NIL)) { e_notice (NULL, GNOME_MESSAGE_BOX_ERROR, - _("Failed to initialize the Bonobo component system")); + _("Cannot initialize the Bonobo component system.")); exit (1); } -} - -static void -gui_init (void) -{ - e_cursors_init (); - - glade_gnome_init (); - bonobo_activate (); -} - -static void -gui_shutdown (void) -{ - /* shutdown */ - e_cursors_shutdown (); -} + /* FIXME */ + evolution_directory = g_concat_dir_and_file (g_get_home_dir (), "evolution"); -static void -evolution_boot (void) -{ - EShellView *e_shell_view; - - if (!e_setup_base_dir ()){ - e_notice ( - NULL, GNOME_MESSAGE_BOX_ERROR, - _("It was not possible to setup the Evolution startup files. Please\n" - "fix the problem, and restart Evolution")); - exit (0); + if (! e_setup (evolution_directory)) { + g_free (evolution_directory); + exit (1); } - - eshell = e_shell_new (); - e_shell_view = E_SHELL_VIEW ( - e_shell_view_new (eshell, - eshell->default_folders.inbox, - TRUE)); - gtk_signal_connect (GTK_OBJECT (e_shell_view), "destroy", - GTK_SIGNAL_FUNC(gtk_main_quit), - NULL); - - gtk_widget_show (GTK_WIDGET (e_shell_view)); -} -int -main (int argc, char *argv []) -{ - bindtextdomain (PACKAGE, EVOLUTION_LOCALEDIR); - textdomain (PACKAGE); + shell = e_shell_new (evolution_directory); - corba_init (&argc, argv); - init_bonobo (); + e_shell_new_view (shell, NULL); - gui_init (); - - evolution_boot (); - - gtk_main (); + bonobo_main (); - gui_shutdown (); + g_free (evolution_directory); return 0; } |