diff options
-rw-r--r-- | shell/ChangeLog | 56 | ||||
-rw-r--r-- | shell/Evolution-Storage.idl | 16 | ||||
-rw-r--r-- | shell/e-corba-storage.c | 40 | ||||
-rw-r--r-- | shell/e-shell.c | 5 | ||||
-rw-r--r-- | shell/e-storage-set-view.c | 58 | ||||
-rw-r--r-- | shell/e-storage-set-view.h | 2 | ||||
-rw-r--r-- | shell/e-storage-set.c | 49 | ||||
-rw-r--r-- | shell/e-storage-set.h | 1 | ||||
-rw-r--r-- | shell/e-storage.c | 110 | ||||
-rw-r--r-- | shell/e-storage.h | 7 | ||||
-rw-r--r-- | shell/evolution-storage-listener.c | 26 | ||||
-rw-r--r-- | shell/evolution-storage-listener.h | 3 | ||||
-rw-r--r-- | shell/evolution-storage.c | 78 | ||||
-rw-r--r-- | shell/evolution-storage.h | 6 |
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 } |