aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--shell/ChangeLog56
-rw-r--r--shell/Evolution-Storage.idl16
-rw-r--r--shell/e-corba-storage.c40
-rw-r--r--shell/e-shell.c5
-rw-r--r--shell/e-storage-set-view.c58
-rw-r--r--shell/e-storage-set-view.h2
-rw-r--r--shell/e-storage-set.c49
-rw-r--r--shell/e-storage-set.h1
-rw-r--r--shell/e-storage.c110
-rw-r--r--shell/e-storage.h7
-rw-r--r--shell/evolution-storage-listener.c26
-rw-r--r--shell/evolution-storage-listener.h3
-rw-r--r--shell/evolution-storage.c78
-rw-r--r--shell/evolution-storage.h6
14 files changed, 447 insertions, 10 deletions
diff --git a/shell/ChangeLog b/shell/ChangeLog
index c302cd1380..3b869920bd 100644
--- a/shell/ChangeLog
+++ b/shell/ChangeLog
@@ -1,3 +1,59 @@
+2002-03-14 Dan Winship <danw@ximian.com>
+
+ Support for delayed filling-in of storages/folders.
+
+ * Evolution-Storage.idl (StorageListener): add
+ notifyHasSubfolders, to announce that a folder has currently-
+ unknown subfolders.
+ (Storage): add asyncOpenFolder, to request that previously-
+ announced subfolders be filled in.
+
+ * evolution-storage.c (impl_Storage_async_open_folder): emit
+ OPEN_FOLDER.
+ (evolution_storage_has_subfolders): Implement by calling
+ notifyHasSubfolders on all of its listeners.
+
+ * evolution-storage-listener.c
+ (impl_GNOME_Evolution_StorageListener_notifyHasSubfolders): emit
+ HAS_SUBFOLDERS.
+
+ * e-corba-storage.c (impl_StorageListener_notifyHasSubfolders):
+ Implement by calling e_storage_has_subfolders.
+ (async_open_folder): Implement by calling asyncOpenFolder on the
+ CORBA storage.
+
+ * e-storage.c (EStoragePrivate, init, destroy): Keep a list of
+ pseudofolders representing un-filled-in subtrees.
+ (impl_async_open_folder): No-op default implementation
+ (e_storage_async_open_folder): New function to request that
+ un-filled-in subtrees be filled in.
+ (e_storage_new_folder): If the new folder's parent has an
+ "un-filled-in children" pseudofolder, remove it.
+ (e_storage_has_subfolders): New function to note that a folder has
+ unknown children. If the folder previously was marked as having
+ real children, remove them, and emit CLOSE_FOLDER to reset it back
+ to an a "unknown subfolders" state.
+
+ * e-storage-set.c (make_full_path): Make this deal with path being
+ "/", since that case gets used from storage_close_folder_cb
+ sometimes.
+ (storage_close_folder_cb): Proxy EStorage's CLOSE_FOLDER signal.
+ (storage_set_view_folder_opened): Handle EStorageSetView's
+ FOLDER_OPENED signal by calling e_storage_async_open_folder.
+
+ * e-storage-set-view.c (etree_fill_in_children): If the given node
+ is its parent's first child, emit FOLDER_OPENED for the parent.
+ (close_folder_cb): Handler for EStorageSet's CLOSE_FOLDER signal.
+ Ask the model to close that node.
+ (e_storage_set_view_construct): Set the default expanded state for
+ the tree to FALSE rather than TRUE, to prevent unwanted expansion
+ of delayed nodes. (This only affects the very first time the tree
+ is displayed anyway: after that its state is loaded off disk.)
+
+ * e-shell.c (e_shell_construct): Register the "noselect" type with
+ the folder type registry, so icon lookups on placeholder folders
+ will work.
+
2002-03-13 Ettore Perazzoli <ettore@ximian.com>
* e-shell-settings-dialog.c (load_pages): Use
diff --git a/shell/Evolution-Storage.idl b/shell/Evolution-Storage.idl
index 82e93f4d6f..f7d9ad1e7b 100644
--- a/shell/Evolution-Storage.idl
+++ b/shell/Evolution-Storage.idl
@@ -54,6 +54,8 @@ module Evolution {
in boolean remove_source,
in Bonobo::Listener listener);
+ void asyncOpenFolder (in string path);
+
void updateFolder (in string path,
in long unread_count);
@@ -72,15 +74,19 @@ module Evolution {
/* FIXME exceptions don't make much sense here... */
- void notifyFolderCreated (in string path,
- in Folder folder)
+ void notifyFolderCreated (in string path,
+ in Folder folder)
raises (Exists);
- void notifyFolderUpdated (in string path,
- in long unread_count)
+ void notifyFolderUpdated (in string path,
+ in long unread_count)
+ raises (NotFound);
+
+ void notifyFolderRemoved (in string path)
raises (NotFound);
- void notifyFolderRemoved (in string path)
+ void notifyHasSubfolders (in string path,
+ in string message)
raises (NotFound);
};
diff --git a/shell/e-corba-storage.c b/shell/e-corba-storage.c
index 28238b68d6..96a981b859 100644
--- a/shell/e-corba-storage.c
+++ b/shell/e-corba-storage.c
@@ -163,6 +163,27 @@ impl_StorageListener_notifyFolderRemoved (PortableServer_Servant servant,
NULL);
}
+static void
+impl_StorageListener_notifyHasSubfolders (PortableServer_Servant servant,
+ const CORBA_char *path,
+ const CORBA_char *message,
+ CORBA_Environment *ev)
+{
+ StorageListenerServant *storage_listener_servant;
+ EStorage *storage;
+
+ storage_listener_servant = (StorageListenerServant *) servant;
+ storage = storage_listener_servant->storage;
+
+ if (! e_storage_has_subfolders (storage, path, message)) {
+ g_warning ("Cannot register subfolder tree -- %s\n", path);
+ CORBA_exception_set (ev,
+ CORBA_USER_EXCEPTION,
+ ex_GNOME_Evolution_StorageListener_Exists,
+ NULL);
+ }
+}
+
static gboolean
setup_storage_listener (ECorbaStorage *corba_storage)
@@ -433,6 +454,23 @@ async_xfer_folder (EStorage *storage,
CORBA_exception_free (&ev);
}
+static void
+async_open_folder (EStorage *storage,
+ const char *path)
+{
+ ECorbaStorage *corba_storage;
+ ECorbaStoragePrivate *priv;
+ CORBA_Environment ev;
+
+ corba_storage = E_CORBA_STORAGE (storage);
+ priv = corba_storage->priv;
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_Storage_asyncOpenFolder (priv->storage_interface,
+ path, &ev);
+ CORBA_exception_free (&ev);
+}
+
static void
corba_class_init (void)
@@ -450,6 +488,7 @@ corba_class_init (void)
epv->notifyFolderCreated = impl_StorageListener_notifyFolderCreated;
epv->notifyFolderUpdated = impl_StorageListener_notifyFolderUpdated;
epv->notifyFolderRemoved = impl_StorageListener_notifyFolderRemoved;
+ epv->notifyHasSubfolders = impl_StorageListener_notifyHasSubfolders;
vepv = &storage_listener_vepv;
vepv->_base_epv = base_epv;
@@ -469,6 +508,7 @@ class_init (ECorbaStorageClass *klass)
storage_class->async_create_folder = async_create_folder;
storage_class->async_remove_folder = async_remove_folder;
storage_class->async_xfer_folder = async_xfer_folder;
+ storage_class->async_open_folder = async_open_folder;
corba_class_init ();
diff --git a/shell/e-shell.c b/shell/e-shell.c
index 29340d41cd..ccab2004d5 100644
--- a/shell/e-shell.c
+++ b/shell/e-shell.c
@@ -1097,6 +1097,11 @@ e_shell_construct (EShell *shell,
priv->uri_schema_registry = e_uri_schema_registry_new ();
priv->storage_set = e_storage_set_new (priv->folder_type_registry);
+ e_folder_type_registry_register_type (priv->folder_type_registry,
+ "noselect", "empty.gif",
+ "noselect", "", FALSE,
+ 0, NULL, 0, NULL);
+
/* CORBA storages must be set up before the components, because otherwise components
cannot register their own storages. */
if (! setup_corba_storages (shell))
diff --git a/shell/e-storage-set-view.c b/shell/e-storage-set-view.c
index b6755370c4..7d88ff2897 100644
--- a/shell/e-storage-set-view.c
+++ b/shell/e-storage-set-view.c
@@ -101,6 +101,7 @@ struct _EStorageSetViewPrivate {
enum {
FOLDER_SELECTED,
+ FOLDER_OPENED,
DND_ACTION,
FOLDER_CONTEXT_MENU_POPPING_UP,
FOLDER_CONTEXT_MENU_POPPED_DOWN,
@@ -1474,6 +1475,27 @@ etree_value_at (ETreeModel *etree,
}
static void
+etree_fill_in_children (ETreeModel *etree,
+ ETreePath tree_path,
+ void *model_data)
+{
+ EStorageSetView *storage_set_view;
+ EStorageSet *storage_set;
+ ETreePath *parent;
+ char *path;
+
+ storage_set_view = E_STORAGE_SET_VIEW (model_data);
+ storage_set = storage_set_view->priv->storage_set;
+
+ parent = e_tree_model_node_get_parent (etree, tree_path);
+ path = (char *) e_tree_memory_node_get_data (E_TREE_MEMORY(etree), parent);
+ if (tree_path == e_tree_model_node_get_first_child (etree, parent)) {
+ gtk_signal_emit (GTK_OBJECT (storage_set_view),
+ signals[FOLDER_OPENED], path);
+ }
+}
+
+static void
etree_set_value_at (ETreeModel *etree,
ETreePath path,
int col,
@@ -1699,6 +1721,24 @@ removed_folder_cb (EStorageSet *storage_set,
e_tree_memory_node_remove (E_TREE_MEMORY(etree), node);
}
+static void
+close_folder_cb (EStorageSet *storage_set,
+ const char *path,
+ void *data)
+{
+ EStorageSetView *storage_set_view;
+ EStorageSetViewPrivate *priv;
+ ETreeModel *etree;
+ ETreePath node;
+
+ storage_set_view = E_STORAGE_SET_VIEW (data);
+ priv = storage_set_view->priv;
+ etree = priv->etree_model;
+
+ node = lookup_node_in_hash (storage_set_view, path);
+ e_tree_model_node_request_collapse (priv->etree_model, node);
+}
+
static void
class_init (EStorageSetViewClass *klass)
@@ -1733,6 +1773,15 @@ class_init (EStorageSetViewClass *klass)
GTK_TYPE_NONE, 1,
GTK_TYPE_STRING);
+ signals[FOLDER_OPENED]
+ = gtk_signal_new ("folder_opened",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EStorageSetViewClass, folder_opened),
+ gtk_marshal_NONE__STRING,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_STRING);
+
signals[DND_ACTION]
= gtk_signal_new ("dnd_action",
GTK_RUN_FIRST,
@@ -1969,7 +2018,7 @@ e_storage_set_view_construct (EStorageSetView *storage_set_view,
e_tree_memory_set_node_destroy_func (E_TREE_MEMORY (priv->etree_model),
etree_node_destroy_func, storage_set_view);
- e_tree_memory_set_expanded_default (E_TREE_MEMORY (priv->etree_model), TRUE);
+ e_tree_memory_set_expanded_default (E_TREE_MEMORY (priv->etree_model), FALSE);
priv->root_node = e_tree_memory_node_insert (E_TREE_MEMORY(priv->etree_model), NULL, -1,
g_strdup (ROOT_NODE_NAME));
@@ -2008,6 +2057,13 @@ e_storage_set_view_construct (EStorageSetView *storage_set_view,
gtk_signal_connect_while_alive (GTK_OBJECT (storage_set), "removed_folder",
GTK_SIGNAL_FUNC (removed_folder_cb), storage_set_view,
GTK_OBJECT (storage_set_view));
+ gtk_signal_connect_while_alive (GTK_OBJECT (storage_set), "close_folder",
+ GTK_SIGNAL_FUNC (close_folder_cb), storage_set_view,
+ GTK_OBJECT (storage_set_view));
+
+ gtk_signal_connect_while_alive (GTK_OBJECT (priv->etree_model), "fill_in_children",
+ GTK_SIGNAL_FUNC (etree_fill_in_children), storage_set_view,
+ GTK_OBJECT (storage_set_view));
insert_storages (storage_set_view);
}
diff --git a/shell/e-storage-set-view.h b/shell/e-storage-set-view.h
index 0cb2be8a3f..f0913a9558 100644
--- a/shell/e-storage-set-view.h
+++ b/shell/e-storage-set-view.h
@@ -56,6 +56,8 @@ struct _EStorageSetViewClass {
void (* folder_selected) (EStorageSetView *storage_set_view,
const char *path);
+ void (* folder_opened) (EStorageSetView *storage_set_view,
+ const char *path);
void (* dnd_action) (EStorageSetView *storage_set_view,
GdkDragContext *context,
diff --git a/shell/e-storage-set.c b/shell/e-storage-set.c
index bbe9f5a718..0eb7b48014 100644
--- a/shell/e-storage-set.c
+++ b/shell/e-storage-set.c
@@ -61,6 +61,7 @@ enum {
NEW_FOLDER,
UPDATED_FOLDER,
REMOVED_FOLDER,
+ CLOSE_FOLDER,
LAST_SIGNAL
};
@@ -153,7 +154,10 @@ make_full_path (EStorage *storage,
storage_name = e_storage_get_name (storage);
- if (! g_path_is_absolute (path))
+ if (strcmp (path, G_DIR_SEPARATOR_S) == 0)
+ full_path = g_strconcat (G_DIR_SEPARATOR_S, storage_name,
+ NULL);
+ else if (! g_path_is_absolute (path))
full_path = g_strconcat (G_DIR_SEPARATOR_S, storage_name,
G_DIR_SEPARATOR_S, path, NULL);
else
@@ -208,6 +212,21 @@ storage_removed_folder_cb (EStorage *storage,
g_free (full_path);
}
+static void
+storage_close_folder_cb (EStorage *storage,
+ const char *path,
+ void *data)
+{
+ EStorageSet *storage_set;
+ char *full_path;
+
+ storage_set = E_STORAGE_SET (data);
+
+ full_path = make_full_path (storage, path);
+ gtk_signal_emit (GTK_OBJECT (storage_set), signals[CLOSE_FOLDER], full_path);
+ g_free (full_path);
+}
+
static EStorage *
get_storage_for_path (EStorageSet *storage_set,
@@ -355,6 +374,14 @@ class_init (EStorageSetClass *klass)
gtk_marshal_NONE__STRING,
GTK_TYPE_NONE, 1,
GTK_TYPE_STRING);
+ signals[CLOSE_FOLDER] =
+ gtk_signal_new ("close_folder",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EStorageSetClass, close_folder),
+ gtk_marshal_NONE__STRING,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_STRING);
gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
}
@@ -456,6 +483,8 @@ e_storage_set_add_storage (EStorageSet *storage_set,
GTK_SIGNAL_FUNC (storage_updated_folder_cb), storage_set);
gtk_signal_connect (GTK_OBJECT (storage), "removed_folder",
GTK_SIGNAL_FUNC (storage_removed_folder_cb), storage_set);
+ gtk_signal_connect (GTK_OBJECT (storage), "close_folder",
+ GTK_SIGNAL_FUNC (storage_close_folder_cb), storage_set);
priv->storages = g_list_append (priv->storages, storage);
@@ -568,6 +597,21 @@ e_storage_set_get_folder (EStorageSet *storage_set,
}
+static void
+storage_set_view_folder_opened (EStorageSetView *storage_set_view,
+ const char *path,
+ EStorageSet *storage_set)
+{
+ EStorage *storage;
+ const char *subpath;
+
+ storage = get_storage_for_path (storage_set, path, &subpath);
+ if (storage == NULL)
+ return;
+
+ e_storage_async_open_folder (storage, subpath);
+}
+
GtkWidget *
e_storage_set_new_view (EStorageSet *storage_set, BonoboUIContainer *container)
{
@@ -577,6 +621,9 @@ e_storage_set_new_view (EStorageSet *storage_set, BonoboUIContainer *container)
g_return_val_if_fail (E_IS_STORAGE_SET (storage_set), NULL);
storage_set_view = e_storage_set_view_new (storage_set, container);
+ gtk_signal_connect (GTK_OBJECT (storage_set_view), "folder_opened",
+ GTK_SIGNAL_FUNC (storage_set_view_folder_opened),
+ storage_set);
return storage_set_view;
}
diff --git a/shell/e-storage-set.h b/shell/e-storage-set.h
index 16e717df16..6bfa1129e5 100644
--- a/shell/e-storage-set.h
+++ b/shell/e-storage-set.h
@@ -65,6 +65,7 @@ struct _EStorageSetClass {
void (* new_folder) (EStorageSet *storage_set, const char *path);
void (* updated_folder) (EStorageSet *storage_set, const char *path);
void (* removed_folder) (EStorageSet *storage_set, const char *path);
+ void (* close_folder) (EStorageSet *storage_set, const char *path);
};
diff --git a/shell/e-storage.c b/shell/e-storage.c
index 4efc069193..fa32203d7f 100644
--- a/shell/e-storage.c
+++ b/shell/e-storage.c
@@ -50,6 +50,9 @@ struct _EStoragePrivate {
/* The set of folders we have in this storage. */
EFolderTree *folder_tree;
+ /* The pseudofolders representing un-filled-in subtrees */
+ GHashTable *pseudofolders;
+
/* Internal name of the storage */
char *name;
};
@@ -58,6 +61,7 @@ enum {
NEW_FOLDER,
UPDATED_FOLDER,
REMOVED_FOLDER,
+ CLOSE_FOLDER,
LAST_SIGNAL
};
@@ -127,6 +131,13 @@ folder_changed_cb (EFolder *folder,
/* GtkObject methods. */
static void
+free_folder (gpointer path, gpointer folder, gpointer user_data)
+{
+ g_free (path);
+ /* folders will have been freed by e_folder_tree_destroy */
+}
+
+static void
destroy (GtkObject *object)
{
EStorage *storage;
@@ -137,6 +148,10 @@ destroy (GtkObject *object)
if (priv->folder_tree != NULL)
e_folder_tree_destroy (priv->folder_tree);
+ if (priv->pseudofolders) {
+ g_hash_table_foreach (priv->pseudofolders, free_folder, NULL);
+ g_hash_table_destroy (priv->pseudofolders);
+ }
g_free (priv->name);
@@ -208,6 +223,13 @@ impl_async_xfer_folder (EStorage *storage,
(* callback) (storage, E_STORAGE_NOTIMPLEMENTED, data);
}
+static void
+impl_async_open_folder (EStorage *storage,
+ const char *path)
+{
+ ;
+}
+
/* Initialization. */
@@ -227,6 +249,7 @@ class_init (EStorageClass *class)
class->async_create_folder = impl_async_create_folder;
class->async_remove_folder = impl_async_remove_folder;
class->async_xfer_folder = impl_async_xfer_folder;
+ class->async_open_folder = impl_async_open_folder;
signals[NEW_FOLDER] =
gtk_signal_new ("new_folder",
@@ -252,6 +275,14 @@ class_init (EStorageClass *class)
gtk_marshal_NONE__STRING,
GTK_TYPE_NONE, 1,
GTK_TYPE_STRING);
+ signals[CLOSE_FOLDER] =
+ gtk_signal_new ("close_folder",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EStorageClass, close_folder),
+ gtk_marshal_NONE__STRING,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_STRING);
gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
}
@@ -263,8 +294,9 @@ init (EStorage *storage)
priv = g_new (EStoragePrivate, 1);
- priv->folder_tree = e_folder_tree_new (folder_destroy_notify, NULL);
- priv->name = NULL;
+ priv->folder_tree = e_folder_tree_new (folder_destroy_notify, NULL);
+ priv->pseudofolders = g_hash_table_new (g_str_hash, g_str_equal);
+ priv->name = NULL;
storage->priv = priv;
}
@@ -429,6 +461,21 @@ e_storage_async_xfer_folder (EStorage *storage,
(* ES_CLASS (storage)->async_xfer_folder) (storage, source_path, destination_path, remove_source, callback, data);
}
+void
+e_storage_async_open_folder (EStorage *storage,
+ const char *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));
+
+ if (g_hash_table_lookup (storage->priv->pseudofolders, path) == NULL)
+ return;
+
+ (* ES_CLASS (storage)->async_open_folder) (storage, path);
+}
+
const char *
e_storage_result_to_string (EStorageResult result)
@@ -546,6 +593,8 @@ e_storage_new_folder (EStorage *storage,
EFolder *e_folder)
{
EStoragePrivate *priv;
+ char *parent_path, *p;
+ gpointer stored_path, pseudofolder;
g_return_val_if_fail (storage != NULL, FALSE);
g_return_val_if_fail (E_IS_STORAGE (storage), FALSE);
@@ -559,6 +608,20 @@ e_storage_new_folder (EStorage *storage,
if (! e_folder_tree_add (priv->folder_tree, path, e_folder))
return FALSE;
+ p = strrchr (path, '/');
+ if (p && p != path)
+ parent_path = g_strndup (path, p - path);
+ else
+ parent_path = g_strdup ("/");
+ if (g_hash_table_lookup_extended (priv->pseudofolders, parent_path,
+ &stored_path, &pseudofolder) &&
+ pseudofolder != e_folder) {
+ g_hash_table_remove (priv->pseudofolders, parent_path);
+ g_free (stored_path);
+ e_storage_removed_folder (storage, e_folder_get_physical_uri (pseudofolder));
+ }
+ g_free (parent_path);
+
gtk_signal_connect_while_alive (GTK_OBJECT (e_folder), "changed", folder_changed_cb,
storage, GTK_OBJECT (storage));
@@ -570,6 +633,49 @@ e_storage_new_folder (EStorage *storage,
}
gboolean
+e_storage_has_subfolders (EStorage *storage,
+ const char *path,
+ const char *message)
+{
+ EStoragePrivate *priv;
+ GList *subfolders, *f;
+ EFolder *pseudofolder;
+ char *pseudofolder_path;
+
+ g_return_val_if_fail (storage != NULL, FALSE);
+ g_return_val_if_fail (E_IS_STORAGE (storage), FALSE);
+ g_return_val_if_fail (path != NULL, FALSE);
+ g_return_val_if_fail (g_path_is_absolute (path), FALSE);
+ g_return_val_if_fail (message != NULL, FALSE);
+
+ priv = storage->priv;
+
+ gtk_signal_emit (GTK_OBJECT (storage), signals[CLOSE_FOLDER], path);
+
+ if (g_hash_table_lookup (priv->pseudofolders, path))
+ return TRUE;
+
+ subfolders = e_folder_tree_get_subfolders (priv->folder_tree, path);
+ if (subfolders != NULL) {
+ for (f = subfolders; f; f = f->next)
+ e_storage_removed_folder (storage, f->data);
+ g_list_free (subfolders);
+ /* FIXME: close parent */
+ }
+
+ pseudofolder = e_folder_new (message, "noselect", "");
+ if (strcmp (path, "/") == 0)
+ pseudofolder_path = g_strdup_printf ("/%s", message);
+ else
+ pseudofolder_path = g_strdup_printf ("%s/%s", path, message);
+ e_folder_set_physical_uri (pseudofolder, pseudofolder_path);
+
+ g_hash_table_insert (priv->pseudofolders, g_strdup (path), pseudofolder);
+
+ return e_storage_new_folder (storage, pseudofolder_path, pseudofolder);
+}
+
+gboolean
e_storage_removed_folder (EStorage *storage,
const char *path)
{
diff --git a/shell/e-storage.h b/shell/e-storage.h
index 878aabeee5..0213653408 100644
--- a/shell/e-storage.h
+++ b/shell/e-storage.h
@@ -80,6 +80,7 @@ struct _EStorageClass {
void * (* new_folder) (EStorage *storage, const char *path);
void * (* updated_folder) (EStorage *storage, const char *path);
void * (* removed_folder) (EStorage *storage, const char *path);
+ void * (* close_folder) (EStorage *storage, const char *path);
/* Virtual methods. */
@@ -105,6 +106,9 @@ struct _EStorageClass {
const gboolean remove_source,
EStorageResultCallback callback,
void *data);
+
+ void (* async_open_folder) (EStorage *storage,
+ const char *path);
};
@@ -143,6 +147,8 @@ void e_storage_async_xfer_folder (EStorage *storage,
const gboolean remove_source,
EStorageResultCallback callback,
void *data);
+void e_storage_async_open_folder (EStorage *storage,
+ const char *path);
const char *e_storage_result_to_string (EStorageResult result);
@@ -153,6 +159,7 @@ char *e_storage_get_path_for_physical_uri (EStorage *storage,
/* Protected. C++ anyone? */
gboolean e_storage_new_folder (EStorage *storage, const char *path, EFolder *folder);
+gboolean e_storage_has_subfolders (EStorage *storage, const char *path, const char *message);
gboolean e_storage_removed_folder (EStorage *storage, const char *path);
#ifdef __cplusplus
diff --git a/shell/evolution-storage-listener.c b/shell/evolution-storage-listener.c
index ede46a2f2d..1f08f5fff8 100644
--- a/shell/evolution-storage-listener.c
+++ b/shell/evolution-storage-listener.c
@@ -45,6 +45,7 @@ enum {
NEW_FOLDER,
UPDATE_FOLDER,
REMOVED_FOLDER,
+ HAS_SUBFOLDERS,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
@@ -121,6 +122,21 @@ impl_GNOME_Evolution_StorageListener_notifyFolderRemoved (PortableServer_Servant
gtk_signal_emit (GTK_OBJECT (listener), signals[REMOVED_FOLDER], path);
}
+static void
+impl_GNOME_Evolution_StorageListener_notifyHasSubfolders (PortableServer_Servant servant,
+ const CORBA_char *path,
+ const CORBA_char *message,
+ CORBA_Environment *ev)
+{
+ EvolutionStorageListener *listener;
+ EvolutionStorageListenerPrivate *priv;
+
+ listener = gtk_object_from_servant (servant);
+ priv = listener->priv;
+
+ gtk_signal_emit (GTK_OBJECT (listener), signals[HAS_SUBFOLDERS], path, message);
+}
+
static EvolutionStorageListenerServant *
create_servant (EvolutionStorageListener *listener)
{
@@ -224,6 +240,7 @@ corba_class_init (void)
epv->notifyFolderCreated = impl_GNOME_Evolution_StorageListener_notifyFolderCreated;
epv->notifyFolderUpdated = impl_GNOME_Evolution_StorageListener_notifyFolderUpdated;
epv->notifyFolderRemoved = impl_GNOME_Evolution_StorageListener_notifyFolderRemoved;
+ epv->notifyHasSubfolders = impl_GNOME_Evolution_StorageListener_notifyHasSubfolders;
vepv = & my_GNOME_Evolution_StorageListener_vepv;
vepv->_base_epv = base_epv;
@@ -273,6 +290,15 @@ class_init (EvolutionStorageListenerClass *klass)
GTK_TYPE_NONE, 1,
GTK_TYPE_STRING);
+ signals[HAS_SUBFOLDERS] = gtk_signal_new ("has_subfolders",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EvolutionStorageListenerClass, has_subfolders),
+ gtk_marshal_NONE__POINTER_POINTER,
+ GTK_TYPE_NONE, 2,
+ GTK_TYPE_STRING,
+ GTK_TYPE_STRING);
+
gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
corba_class_init ();
diff --git a/shell/evolution-storage-listener.h b/shell/evolution-storage-listener.h
index 5e13435411..8e9bee5df7 100644
--- a/shell/evolution-storage-listener.h
+++ b/shell/evolution-storage-listener.h
@@ -61,6 +61,9 @@ struct _EvolutionStorageListenerClass {
int unread_count);
void (* removed_folder) (EvolutionStorageListener *storage_listener,
const char *path);
+ void (* has_subfolders) (EvolutionStorageListener *storage_listener,
+ const char *path,
+ const char *message);
};
diff --git a/shell/evolution-storage.c b/shell/evolution-storage.c
index 313e4fb2a6..75d6935f1f 100644
--- a/shell/evolution-storage.c
+++ b/shell/evolution-storage.c
@@ -61,8 +61,9 @@ struct _EvolutionStoragePrivate {
enum {
CREATE_FOLDER,
REMOVE_FOLDER,
- UPDATE_FOLDER,
XFER_FOLDER,
+ UPDATE_FOLDER,
+ OPEN_FOLDER,
LAST_SIGNAL
};
@@ -354,6 +355,20 @@ impl_Storage_updateFolder (PortableServer_Servant servant,
}
static void
+impl_Storage_async_open_folder (PortableServer_Servant servant,
+ const CORBA_char *path,
+ CORBA_Environment *ev)
+{
+ BonoboObject *bonobo_object;
+ EvolutionStorage *storage;
+
+ bonobo_object = bonobo_object_from_servant (servant);
+ storage = EVOLUTION_STORAGE (bonobo_object);
+
+ gtk_signal_emit (GTK_OBJECT (storage), signals[OPEN_FOLDER], path);
+}
+
+static void
impl_Storage_add_listener (PortableServer_Servant servant,
const GNOME_Evolution_StorageListener listener,
CORBA_Environment *ev)
@@ -552,6 +567,15 @@ class_init (EvolutionStorageClass *klass)
GTK_TYPE_STRING,
GTK_TYPE_INT);
+ signals[OPEN_FOLDER] = gtk_signal_new ("open_folder",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EvolutionStorageClass,
+ open_folder),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_STRING);
+
gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
corba_class_init ();
@@ -582,6 +606,7 @@ evolution_storage_get_epv (void)
epv->asyncCreateFolder = impl_Storage_async_create_folder;
epv->asyncRemoveFolder = impl_Storage_async_remove_folder;
epv->asyncXferFolder = impl_Storage_async_xfer_folder;
+ epv->asyncOpenFolder = impl_Storage_async_open_folder;
epv->updateFolder = impl_Storage_updateFolder;
epv->addListener = impl_Storage_add_listener;
epv->removeListener = impl_Storage_remove_listener;
@@ -1008,5 +1033,56 @@ evolution_storage_folder_exists (EvolutionStorage *evolution_storage,
return e_folder_tree_get_folder (priv->folder_tree, path) != NULL;
}
+EvolutionStorageResult
+evolution_storage_has_subfolders (EvolutionStorage *evolution_storage,
+ const char *path,
+ const char *message)
+{
+ EvolutionStorageResult result;
+ EvolutionStoragePrivate *priv;
+ CORBA_Environment ev;
+ GList *p;
+
+ g_return_val_if_fail (evolution_storage != NULL,
+ EVOLUTION_STORAGE_ERROR_INVALIDPARAMETER);
+ g_return_val_if_fail (EVOLUTION_IS_STORAGE (evolution_storage),
+ EVOLUTION_STORAGE_ERROR_INVALIDPARAMETER);
+ g_return_val_if_fail (path != NULL, EVOLUTION_STORAGE_ERROR_INVALIDPARAMETER);
+ g_return_val_if_fail (g_path_is_absolute (path), EVOLUTION_STORAGE_ERROR_INVALIDPARAMETER);
+ g_return_val_if_fail (message != NULL, EVOLUTION_STORAGE_ERROR_INVALIDPARAMETER);
+
+ priv = evolution_storage->priv;
+
+ if (priv->corba_storage_listeners == NULL)
+ return EVOLUTION_STORAGE_ERROR_NOTREGISTERED;
+
+ CORBA_exception_init (&ev);
+
+ result = EVOLUTION_STORAGE_OK;
+
+ for (p = priv->corba_storage_listeners; p != NULL; p = p->next) {
+ GNOME_Evolution_StorageListener listener;
+
+ listener = p->data;
+ GNOME_Evolution_StorageListener_notifyHasSubfolders (listener, path, message, &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION)
+ continue;
+ if (ev._major != CORBA_USER_EXCEPTION)
+ result = EVOLUTION_STORAGE_ERROR_CORBA;
+ else if (strcmp (CORBA_exception_id (&ev), ex_GNOME_Evolution_StorageListener_NotFound) == 0)
+ result = EVOLUTION_STORAGE_ERROR_NOTFOUND;
+ else
+ result = EVOLUTION_STORAGE_ERROR_GENERIC;
+
+ break;
+ }
+
+ CORBA_exception_free (&ev);
+
+ return result;
+}
+
+
E_MAKE_TYPE (evolution_storage, "EvolutionStorage", EvolutionStorage, class_init, init, PARENT_TYPE)
diff --git a/shell/evolution-storage.h b/shell/evolution-storage.h
index aec35e15d8..c039a38e64 100644
--- a/shell/evolution-storage.h
+++ b/shell/evolution-storage.h
@@ -99,6 +99,9 @@ struct _EvolutionStorageClass {
const char *destination_path,
gboolean remove_source);
+ void (*open_folder) (EvolutionStorage *storage,
+ const char *path);
+
void (*update_folder) (EvolutionStorage *storage,
const char *path,
int unread_count);
@@ -139,6 +142,9 @@ EvolutionStorageResult evolution_storage_removed_folder (EvolutionStorage
const char *path);
gboolean evolution_storage_folder_exists (EvolutionStorage *evolution_storage,
const char *path);
+EvolutionStorageResult evolution_storage_has_subfolders (EvolutionStorage *evolution_storage,
+ const char *path,
+ const char *message);
#ifdef __cplusplus
}