aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--po/POTFILES.in2
-rw-r--r--shell/ChangeLog6
-rw-r--r--shell/Makefile.am63
-rw-r--r--shell/e-folder-type-repository.c241
-rw-r--r--shell/e-folder-type-repository.h73
-rw-r--r--shell/e-folder.c377
-rw-r--r--shell/e-folder.h139
-rw-r--r--shell/e-local-folder.c223
-rw-r--r--shell/e-local-folder.h68
-rw-r--r--shell/e-local-storage.c342
-rw-r--r--shell/e-local-storage.h67
-rw-r--r--shell/e-setup.c115
-rw-r--r--shell/e-setup.h31
-rw-r--r--shell/e-shell-view-menu.c234
-rw-r--r--shell/e-shell-view-menu.h31
-rw-r--r--shell/e-shell-view.c780
-rw-r--r--shell/e-shell-view.h102
-rw-r--r--shell/e-shell.c448
-rw-r--r--shell/e-shell.h120
-rw-r--r--shell/e-shortcuts-view.c154
-rw-r--r--shell/e-shortcuts-view.h76
-rw-r--r--shell/e-shortcuts.c530
-rw-r--r--shell/e-shortcuts.h85
-rw-r--r--shell/e-storage-set.c266
-rw-r--r--shell/e-storage-set.h87
-rw-r--r--shell/e-storage-watcher.c188
-rw-r--r--shell/e-storage-watcher.h93
-rw-r--r--shell/e-storage.c473
-rw-r--r--shell/e-storage.h93
-rw-r--r--shell/evolution-directory.idl89
-rw-r--r--shell/main.c150
31 files changed, 4474 insertions, 1272 deletions
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 87c65c765d..68f667be58 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -11,9 +11,7 @@ mail/mail-display.c
mail/main.c
mail/message-list.c
shell/e-folder.c
-shell/e-init.c
shell/e-shell-shortcut.c
shell/e-shell-view-menu.c
shell/e-shell.c
-shell/e-shortcut.c
shell/main.c
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;
}