From bbb6a6942fdfbb2684c37ee6aa55f8c6e5b5a9f2 Mon Sep 17 00:00:00 2001 From: Ettore Perazzoli Date: Sat, 10 Jun 2000 17:56:46 +0000 Subject: Implemented folder creation dialog (File -> New -> Folder). To make it really work though, the components should implement creation functionality by passing an appropriate function pointer in `e_shell_component_new()' for @create_folder_fn. svn path=/trunk/; revision=3504 --- mail/ChangeLog | 7 + mail/component-factory.c | 26 ++- shell/ChangeLog | 76 +++++++++ shell/e-folder.c | 1 - shell/e-local-folder.c | 50 +++++- shell/e-local-folder.h | 13 +- shell/e-local-storage.c | 277 +++++++++++++++++++++++++++---- shell/e-local-storage.h | 8 +- shell/e-shell-folder-creation-dialog.c | 207 ++++++++++++++++++++--- shell/e-shell.c | 2 +- shell/e-storage-set-view.c | 31 ++++ shell/e-storage-set-view.h | 13 +- shell/e-storage-set.c | 95 +++++++++-- shell/e-storage-set.h | 45 +++-- shell/e-storage.c | 88 +++++++--- shell/e-storage.h | 49 +++--- shell/evolution-shell-component-client.c | 43 ++--- shell/evolution-shell-component.h | 29 ++-- 18 files changed, 864 insertions(+), 196 deletions(-) diff --git a/mail/ChangeLog b/mail/ChangeLog index 555a156f2a..e5a7cac760 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,10 @@ +2000-06-10 Ettore Perazzoli + + * component-factory.c (create_folder): New stub implementation for + the folder creation function in the EvolutionShellComponent we + expose [it simply returns success all the time]. + (factory_fn): Pass this function to `evolution_shell_component_new'. + 2000-06-09 Dan Winship * folder-browser.c (folder_browser_new): Add a serial number to diff --git a/mail/component-factory.c b/mail/component-factory.c index 0452efb846..ee69f0da84 100644 --- a/mail/component-factory.c +++ b/mail/component-factory.c @@ -93,6 +93,26 @@ create_view (EvolutionShellComponent *shell_component, return EVOLUTION_SHELL_COMPONENT_OK; } +static void +create_folder (EvolutionShellComponent *shell_component, + const char *physical_uri, + const char *type, + const Evolution_ShellComponentListener listener, + void *closure) +{ + CORBA_Environment ev; + + /* FIXME: Implement. */ + + CORBA_exception_init (&ev); + + Evolution_ShellComponentListener_report_result (listener, + Evolution_ShellComponentListener_OK, + &ev); + + CORBA_exception_free (&ev); +} + static void owner_set_cb (EvolutionShellComponent *shell_component, Evolution_Shell shell_interface, @@ -130,7 +150,11 @@ factory_fn (BonoboGenericFactory *factory, { EvolutionShellComponent *shell_component; - shell_component = evolution_shell_component_new (folder_types, create_view, NULL, NULL, NULL); + shell_component = evolution_shell_component_new (folder_types, + create_view, + create_folder, + NULL, + NULL); gtk_signal_connect (GTK_OBJECT (shell_component), "owner_set", GTK_SIGNAL_FUNC (owner_set_cb), NULL); diff --git a/shell/ChangeLog b/shell/ChangeLog index 84edb7c42a..0b3897756a 100644 --- a/shell/ChangeLog +++ b/shell/ChangeLog @@ -1,3 +1,79 @@ +2000-06-10 Ettore Perazzoli + + * e-local-folder.c (save_metadata): Don't set the description in + the XML file if null. Compute the physical path correctly. + + * e-folder.c (e_folder_construct): Allow NULL description. + + * evolution-shell-component-client.c (init): Initalize + `listener_interface' to `CORBA_OBJECT_NIL' and `listener_servant' + to NULL. + (create_listener_interface): Return void and set the `servant' and + `listener_servant' fields directly. + (evolution_shell_component_client_async_create_folder): Updated + accordingly. + + * e-shell-folder-creation-dialog.c: New struct `DialogData' to be + passed to the dialog's callbacks. + (dialog_data_destroy): New. + (e_shell_show_folder_creation_dialog): Set up a `DialogData' + object and pass it as the data for the signals. + (shell_destroy_cb): New handler for the "destroy" signal on the + shell. + (e_shell_show_folder_creation_dialog): Connect it. + (dialog_destroy_cb): New handler for the "destroy" signal on the + dialog; it frees the associated `DialogData'. + (e_shell_show_folder_creation_dialog): Connect it. + (async_create_cb): New function, callback for the async folder + creation function. + (entry_name_is_valid): New function to check if the entered folder + name is valid. + (dialog_clicked_cb): Check if the specified folder name is valid + and, if so, asynchronously create the new folder. + (add_folder_types): Set "type_name" data on each menu item. + + * e-storage-set-view.c (e_storage_set_view_get_current_folder): + New function. + + * e-storage-set.c (get_storage_for_path): New helper function. + (e_storage_set_get_folder): Use it. + + * e-storage.c (e_storage_async_create_folder): Renamed from + `e_storage_create_folder'. + (e_storage_remove_folder): Renamed from `e_storage_remove_folder'. + (impl_create_create_folder): Renamed from `impl_create_folder'. + (impl_create_remove_folder): Renamed from `impl_remove_folder'. + (class_init): Updated accordingly. + (e_storage_result_to_string): New function. + + * e-storage.h: `::create_folder' renamed to + `::async_create_folder'. `::remove_folder' renamed to + `::async_remove_folder'. + + * evolution-shell-component.h: Return type of + `EvolutionShellComponentCreateFolderFn' and + `EvolutionShellComponentRemoveFolderFn' changed to `void'. + + * e-local-storage.c: `EComponentRegistry component_registry' + replaced with `EFolderTypeRegistry folder_type_registry' in + `ELocalStoragePrivate' + (component_async_create_folder_callback): New function, to handle + the callback from EvolutionShellComponent. + (construct): Likewise. + (e_local_storage_open): Replaced @component_registry with + @folder_type_registry. + (impl_create_folder): Implemented. + + * e-local-folder.c (e_local_folder_new): New. + (e_local_folder_construct): New. + (e_local_folder_save): Precondition: physical URI is not NULL. + (save_metadata): Unlink the metadata file if `xmlSaveFile()' + fails. + + * e-storage.c (e_storage_create_folder): Precondition: @path is + absolute. + (e_storage_remove_folder): Likewise. + 2000-06-09 Ettore Perazzoli * e-shell-view-menu.c: Removed folder menu and "save as..." command. diff --git a/shell/e-folder.c b/shell/e-folder.c index 2e16c0896e..90bd886352 100644 --- a/shell/e-folder.c +++ b/shell/e-folder.c @@ -162,7 +162,6 @@ e_folder_construct (EFolder *folder, 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); GTK_OBJECT_UNSET_FLAGS (GTK_OBJECT (folder), GTK_FLOATING); diff --git a/shell/e-local-folder.c b/shell/e-local-folder.c index 23cd106390..80cee7d7bc 100644 --- a/shell/e-local-folder.c +++ b/shell/e-local-folder.c @@ -138,7 +138,8 @@ save_metadata (ELocalFolder *local_folder) EFolder *folder; xmlDoc *doc; xmlNode *root; - const char *physical_path; + const char *physical_directory; + char *physical_path; folder = E_FOLDER (local_folder); @@ -146,16 +147,25 @@ save_metadata (ELocalFolder *local_folder) 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)); + xmlNewChild (root, NULL, (xmlChar *) "type", + (xmlChar *) e_folder_get_type_string (folder)); - physical_path = e_folder_get_physical_uri (folder) + URI_PREFIX_LEN - 1; + if (e_folder_get_description (folder) != NULL) + xmlNewChild (root, NULL, (xmlChar *) "description", + (xmlChar *) e_folder_get_description (folder)); + + physical_directory = e_folder_get_physical_uri (folder) + URI_PREFIX_LEN - 1; + physical_path = g_concat_dir_and_file (physical_directory, METADATA_FILE_NAME); if (xmlSaveFile (physical_path, doc) < 0) { + unlink (physical_path); + g_free (physical_path); xmlFreeDoc (doc); return FALSE; } + g_free (physical_path); + xmlFreeDoc (doc); return TRUE; } @@ -189,6 +199,37 @@ init (ELocalFolder *local_folder) } +void +e_local_folder_construct (ELocalFolder *local_folder, + const char *name, + const char *type, + const char *description) +{ + g_return_if_fail (local_folder != NULL); + g_return_if_fail (E_IS_LOCAL_FOLDER (local_folder)); + g_return_if_fail (name != NULL); + g_return_if_fail (type != NULL); + + e_folder_construct (E_FOLDER (local_folder), name, type, description); +} + +EFolder * +e_local_folder_new (const char *name, + const char *type, + const char *description) +{ + ELocalFolder *local_folder; + + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (type != NULL, NULL); + + local_folder = gtk_type_new (e_local_folder_get_type ()); + + e_local_folder_construct (local_folder, name, type, description); + + return E_FOLDER (local_folder); +} + EFolder * e_local_folder_new_from_path (const char *path) { @@ -211,6 +252,7 @@ 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); + g_return_val_if_fail (e_folder_get_physical_uri (E_FOLDER (local_folder)) != NULL, FALSE); return save_metadata (local_folder); } diff --git a/shell/e-local-folder.h b/shell/e-local-folder.h index b30a9f2a5c..aa9e79a990 100644 --- a/shell/e-local-folder.h +++ b/shell/e-local-folder.h @@ -55,9 +55,16 @@ struct _ELocalFolderClass { }; -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); +GtkType e_local_folder_get_type (void); +void e_local_folder_construct (ELocalFolder *local_folder, + const char *name, + const char *type, + const char *description); +EFolder *e_local_folder_new (const char *name, + const char *type, + const char *description); +EFolder *e_local_folder_new_from_path (const char *physical_path); +gboolean e_local_folder_save (ELocalFolder *local_folder); #ifdef __cplusplus } diff --git a/shell/e-local-storage.c b/shell/e-local-storage.c index b97b25b8ec..05a142152e 100644 --- a/shell/e-local-storage.c +++ b/shell/e-local-storage.c @@ -25,6 +25,9 @@ * * - If we have `.' or `..' as path elements, we lose. * + * - If the LocalStorage is destroyed and an async operation on a shell component is + * pending, we get a callback on a bogus object. We need support for cancelling + * operations on the shell component. */ #ifdef HAVE_CONFIG_H @@ -34,6 +37,7 @@ #define _POSIX_SOURCE /* Yuck. */ #include +#include #include #include #include @@ -54,18 +58,17 @@ static EStorageClass *parent_class = NULL; #define SUBFOLDER_DIR_NAME_LEN 10 struct _ELocalStoragePrivate { - EComponentRegistry *component_registry; + EFolderTypeRegistry *folder_type_registry; char *base_path; }; /* Utility functions. */ -#if 0 -/* Translate a storage path into a real path on the file system. */ +/* Translate a storage path into a physical path on the file system. */ static char * -get_real_path (ELocalStorage *local_storage, - const char *path) +get_physical_path (ELocalStorage *local_storage, + const char *path) { EStorage *storage; ELocalStoragePrivate *priv; @@ -80,7 +83,7 @@ get_real_path (ELocalStorage *local_storage, /* @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); + g_assert (*path == G_DIR_SEPARATOR); path++; /* Calculate the length of the real path. */ @@ -93,7 +96,7 @@ get_real_path (ELocalStorage *local_storage, real_path_len++; /* For the separating slash. */ /* Take account for the fact that we need to translate every separator into - `children/'. */ + `subfolders/'. */ p = path; while (1) { newp = strchr (p, G_DIR_SEPARATOR); @@ -121,8 +124,10 @@ get_real_path (ELocalStorage *local_storage, p = path; while (1) { newp = strchr (p, G_DIR_SEPARATOR); - if (newp == NULL) + if (newp == NULL) { + strcpy (dp, p); break; + } memcpy (dp, p, newp - p + 1); /* `+ 1' to copy the slash too. */ dp += newp - p + 1; @@ -141,7 +146,6 @@ get_real_path (ELocalStorage *local_storage, return real_path; } -#endif static gboolean load_folders (ELocalStorage *local_storage, @@ -230,6 +234,127 @@ load_all_folders (ELocalStorage *local_storage) return load_folders (local_storage, NULL, G_DIR_SEPARATOR_S, base_path); } +static EStorageResult +errno_to_storage_result (void) +{ + EStorageResult storage_result; + + switch (errno) { + case EACCES: + case EROFS: + storage_result = E_STORAGE_PERMISSIONDENIED; + break; + case EEXIST: + storage_result = E_STORAGE_EXISTS; + break; + case ENOSPC: + storage_result = E_STORAGE_NOSPACE; + break; + default: + storage_result = E_STORAGE_GENERICERROR; + } + + return storage_result; +} + +static EStorageResult +shell_component_result_to_storage_result (EvolutionShellComponentResult result) +{ + /* FIXME: Maybe we need better mapping here. */ + switch (result) { + case EVOLUTION_SHELL_COMPONENT_OK: + return E_STORAGE_OK; + case EVOLUTION_SHELL_COMPONENT_NOTFOUND: + return E_STORAGE_NOTFOUND; + case EVOLUTION_SHELL_COMPONENT_UNSUPPORTEDTYPE: + return E_STORAGE_UNSUPPORTEDTYPE; + case EVOLUTION_SHELL_COMPONENT_UNSUPPORTEDOPERATION: + return E_STORAGE_UNSUPPORTEDOPERATION; + case EVOLUTION_SHELL_COMPONENT_EXISTS: + return E_STORAGE_EXISTS; + case EVOLUTION_SHELL_COMPONENT_PERMISSIONDENIED: + return E_STORAGE_PERMISSIONDENIED; + case EVOLUTION_SHELL_COMPONENT_ALREADYOWNED: + case EVOLUTION_SHELL_COMPONENT_BUSY: + case EVOLUTION_SHELL_COMPONENT_CORBAERROR: + case EVOLUTION_SHELL_COMPONENT_HASSUBFOLDERS: + case EVOLUTION_SHELL_COMPONENT_INTERNALERROR: + case EVOLUTION_SHELL_COMPONENT_INTERRUPTED: + case EVOLUTION_SHELL_COMPONENT_INVALIDARG: + case EVOLUTION_SHELL_COMPONENT_INVALIDURI: + case EVOLUTION_SHELL_COMPONENT_NOSPACE: + case EVOLUTION_SHELL_COMPONENT_NOTOWNED: + case EVOLUTION_SHELL_COMPONENT_UNKNOWNERROR: + default: + return E_STORAGE_GENERICERROR; + } +} + + +/* Callbacks for the async methods invoked on the `Evolution::ShellComponent's. */ + +struct _AsyncCreateFolderCallbackData { + EStorage *storage; + + char *parent_path; + char *name; + char *type; + char *description; + char *physical_uri; + char *physical_path; + + EStorageResultCallback callback; + void *callback_data; +}; +typedef struct _AsyncCreateFolderCallbackData AsyncCreateFolderCallbackData; + +static void +component_async_create_folder_callback (EvolutionShellComponentClient *shell_component_client, + EvolutionShellComponentResult result, + void *data) +{ + AsyncCreateFolderCallbackData *callback_data; + + callback_data = (AsyncCreateFolderCallbackData *) data; + + if (result != EVOLUTION_SHELL_COMPONENT_OK) { + /* XXX: This assumes the component won't leave any files in the directory. */ + rmdir (callback_data->physical_path); + } else { + EFolder *folder; + + folder = e_local_folder_new (callback_data->name, + callback_data->type, + callback_data->description); + + e_folder_set_physical_uri (folder, callback_data->physical_uri); + + if (e_local_folder_save (E_LOCAL_FOLDER (folder))) { + e_storage_new_folder (callback_data->storage, + callback_data->parent_path, + folder); + } else { + rmdir (callback_data->physical_path); + gtk_object_unref (GTK_OBJECT (folder)); + result = E_STORAGE_IOERROR; + } + } + + bonobo_object_unref (BONOBO_OBJECT (shell_component_client)); + + (* callback_data->callback) (callback_data->storage, + shell_component_result_to_storage_result (result), + callback_data->callback_data); + + g_free (callback_data->parent_path); + g_free (callback_data->name); + g_free (callback_data->type); + g_free (callback_data->description); + g_free (callback_data->physical_uri); + g_free (callback_data->physical_path); + g_free (callback_data); +} + /* GtkObject methods. */ @@ -244,8 +369,8 @@ impl_destroy (GtkObject *object) g_free (priv->base_path); - if (priv->component_registry != NULL) - gtk_object_unref (GTK_OBJECT (priv->component_registry)); + if (priv->folder_type_registry != NULL) + gtk_object_unref (GTK_OBJECT (priv->folder_type_registry)); g_free (priv); @@ -263,23 +388,107 @@ impl_get_name (EStorage *storage) } static void -impl_create_folder (EStorage *storage, - const char *path, - const char *type, - const char *description, - EStorageResultCallback callback, - void *data) +impl_async_create_folder (EStorage *storage, + const char *path, + const char *type, + const char *description, + EStorageResultCallback callback, + void *data) { ELocalStorage *local_storage; + ELocalStoragePrivate *priv; + EvolutionShellComponentClient *component_client; + const char *folder_name; + AsyncCreateFolderCallbackData *callback_data; + char *physical_path; + char *physical_uri; + char *parent_path; local_storage = E_LOCAL_STORAGE (storage); + priv = local_storage->priv; + + component_client = e_folder_type_registry_get_handler_for_type (priv->folder_type_registry, + type); + if (component_client == NULL) { + (* callback) (storage, E_STORAGE_INVALIDTYPE, data); + return; + } + + g_assert (g_path_is_absolute (path)); + + folder_name = g_basename (path); + if (folder_name == path + 1) { + /* We want a direct child of the root, so we don't need to create a + `subfolders' directory. */ + physical_path = get_physical_path (local_storage, path); + parent_path = g_strdup (G_DIR_SEPARATOR_S); + } else { + char *parent_physical_path; + char *subfolders_directory_physical_path; + + /* Create the `subfolders' subdirectory under the parent. */ + + parent_path = g_strndup (path, folder_name - path - 1); + parent_physical_path = get_physical_path (local_storage, parent_path); + subfolders_directory_physical_path = g_concat_dir_and_file (parent_physical_path, + SUBFOLDER_DIR_NAME); + + if (! g_file_exists (subfolders_directory_physical_path) + && mkdir (subfolders_directory_physical_path, 0700) == -1) { + g_free (parent_path); + g_free (subfolders_directory_physical_path); + g_free (parent_physical_path); + + (* callback) (storage, errno_to_storage_result (), data); + return; + } + + physical_path = g_concat_dir_and_file (subfolders_directory_physical_path, + folder_name); + g_free (subfolders_directory_physical_path); + g_free (parent_physical_path); + } + + /* Create the directory that holds the folder. */ + + if (mkdir (physical_path, 0700) == -1) { + g_free (physical_path); + (* callback) (storage, errno_to_storage_result (), data); + return; + } + + /* Finally tell the component to do the job of creating the physical files in + it. */ + /* FIXME: We should put the operations on a queue so that we can cancel them when + the ELocalStorage is destroyed. */ + + physical_uri = g_strconcat ("file://", physical_path, NULL); + + callback_data = g_new (AsyncCreateFolderCallbackData, 1); + callback_data->storage = storage; + callback_data->parent_path = parent_path; + callback_data->name = g_strdup (folder_name); + callback_data->type = g_strdup (type); + callback_data->description = g_strdup (description); + callback_data->physical_uri = physical_uri; + callback_data->physical_path = physical_path; + callback_data->callback = callback; + callback_data->callback_data = data; + + bonobo_object_ref (BONOBO_OBJECT (component_client)); + + evolution_shell_component_client_async_create_folder (component_client, + physical_path, + type, + component_async_create_folder_callback, + callback_data); } static void -impl_remove_folder (EStorage *storage, - const char *path, - EStorageResultCallback callback, - void *data) +impl_async_remove_folder (EStorage *storage, + const char *path, + EStorageResultCallback callback, + void *data) { ELocalStorage *local_storage; @@ -299,11 +508,11 @@ class_init (ELocalStorageClass *class) object_class = GTK_OBJECT_CLASS (class); storage_class = E_STORAGE_CLASS (class); - object_class->destroy = impl_destroy; + object_class->destroy = impl_destroy; - storage_class->get_name = impl_get_name; - storage_class->create_folder = impl_create_folder; - storage_class->remove_folder = impl_remove_folder; + storage_class->get_name = impl_get_name; + storage_class->async_create_folder = impl_async_create_folder; + storage_class->async_remove_folder = impl_async_remove_folder; } static void @@ -314,7 +523,7 @@ init (ELocalStorage *local_storage) priv = g_new (ELocalStoragePrivate, 1); priv->base_path = NULL; - priv->component_registry = NULL; + priv->folder_type_registry = NULL; local_storage->priv = priv; } @@ -322,7 +531,7 @@ init (ELocalStorage *local_storage) static gboolean construct (ELocalStorage *local_storage, - EComponentRegistry *component_registry, + EFolderTypeRegistry *folder_type_registry, const char *base_path) { ELocalStoragePrivate *priv; @@ -338,9 +547,9 @@ construct (ELocalStorage *local_storage, g_return_val_if_fail (base_path_len != 0, FALSE); - g_assert (priv->component_registry == NULL); - gtk_object_ref (GTK_OBJECT (component_registry)); - priv->component_registry = component_registry; + g_assert (priv->folder_type_registry == NULL); + gtk_object_ref (GTK_OBJECT (folder_type_registry)); + priv->folder_type_registry = folder_type_registry; g_assert (priv->base_path == NULL); priv->base_path = g_strndup (base_path, base_path_len); @@ -349,18 +558,18 @@ construct (ELocalStorage *local_storage, } EStorage * -e_local_storage_open (EComponentRegistry *component_registry, +e_local_storage_open (EFolderTypeRegistry *folder_type_registry, const char *base_path) { EStorage *new; - g_return_val_if_fail (component_registry != NULL, NULL); - g_return_val_if_fail (E_IS_COMPONENT_REGISTRY (component_registry), NULL); + g_return_val_if_fail (folder_type_registry != NULL, NULL); + g_return_val_if_fail (E_IS_FOLDER_TYPE_REGISTRY (folder_type_registry), NULL); g_return_val_if_fail (base_path != NULL, NULL); new = gtk_type_new (e_local_storage_get_type ()); - if (! construct (E_LOCAL_STORAGE (new), component_registry, base_path)) { + if (! construct (E_LOCAL_STORAGE (new), folder_type_registry, base_path)) { gtk_object_unref (GTK_OBJECT (new)); return NULL; } diff --git a/shell/e-local-storage.h b/shell/e-local-storage.h index feecda75a7..14a48cbdd4 100644 --- a/shell/e-local-storage.h +++ b/shell/e-local-storage.h @@ -28,7 +28,7 @@ #include #endif -#include "e-component-registry.h" +#include "e-folder-type-registry.h" #include "e-storage.h" #ifdef __cplusplus @@ -58,9 +58,9 @@ struct _ELocalStorageClass { GtkType e_local_storage_get_type (void); -EStorage *e_local_storage_open (EComponentRegistry *component_registry, - const char *base_path); -const char *e_local_storage_get_base_path (ELocalStorage *storage); +EStorage *e_local_storage_open (EFolderTypeRegistry *folder_type_registry, + const char *base_path); +const char *e_local_storage_get_base_path (ELocalStorage *storage); #ifdef __cplusplus } diff --git a/shell/e-shell-folder-creation-dialog.c b/shell/e-shell-folder-creation-dialog.c index 6879922be1..342f65ff39 100644 --- a/shell/e-shell-folder-creation-dialog.c +++ b/shell/e-shell-folder-creation-dialog.c @@ -28,7 +28,9 @@ #include #include +#include "e-util/e-gui-utils.h" #include "e-util/e-util.h" + #include "widgets/misc/e-scroll-frame.h" #include "e-storage-set.h" @@ -37,28 +39,145 @@ #include "e-shell-folder-creation-dialog.h" -#define GLADE_FILE_NAME E_GLADEDIR "/e-shell-folder-creation-dialog.glade" +#define GLADE_FILE_NAME E_GLADEDIR "/e-shell-folder-creation-dialog.glade" + + +/* Data for the callbacks. */ +struct _DialogData { + GtkWidget *dialog; + EShell *shell; + GtkWidget *folder_name_entry; + GtkWidget *storage_set_view; + GtkWidget *folder_type_option_menu; + GList *folder_types; +}; +typedef struct _DialogData DialogData; + +static void +dialog_data_destroy (DialogData *dialog_data) +{ + e_free_string_list (dialog_data->folder_types); + g_free (dialog_data); +} + + +/* Callback for the asynchronous folder creation function. */ + +static void +async_create_cb (EStorage *storage, + EStorageResult result, + void *data) +{ + DialogData *dialog_data; + + dialog_data = (DialogData *) data; + + if (result == E_STORAGE_OK) { + gtk_widget_destroy (dialog_data->dialog); + return; + } + + e_notice (GTK_WINDOW (dialog_data->dialog), GNOME_MESSAGE_BOX_ERROR, + _("Cannot create the specified folder:\n%s"), + e_storage_result_to_string (result)); +} + + +/* Sanity check for the user-specified folder name. */ +/* FIXME in the future we would like not to have the `G_DIR_SEPARATOR' limitation. */ +static gboolean +entry_name_is_valid (GtkEntry *entry) +{ + const char *name; + + name = gtk_entry_get_text (entry); + + if (name == NULL || *name == '\0') + return FALSE; + + if (strchr (name, G_DIR_SEPARATOR) != NULL) + return FALSE; + + if (strcmp (name, ".") == 0 || strcmp (name, "..") == 0) + return FALSE; + + return TRUE; +} -/* Dialog callbacks. */ +/* Dialog signal callbacks. */ static void dialog_clicked_cb (GnomeDialog *dialog, int button_number, void *data) { - g_print ("Clicked -- %d\n", button_number); - gnome_dialog_close (dialog); + DialogData *dialog_data; + EStorageSet *storage_set; + GtkWidget *folder_type_menu_item; + const char *folder_type; + const char *parent_path; + const char *folder_name; + char *path; + + if (button_number != 0) { + gnome_dialog_close (dialog); + return; + } + + dialog_data = (DialogData *) data; + + if (! entry_name_is_valid (GTK_ENTRY (dialog_data->folder_name_entry))) { + /* FIXME: Explain better. */ + e_notice (GTK_WINDOW (dialog), GNOME_MESSAGE_BOX_ERROR, + _("The specified folder name is not valid.")); + return; + } + + parent_path = e_storage_set_view_get_current_folder + (E_STORAGE_SET_VIEW (dialog_data->storage_set_view)); + if (parent_path == NULL) { + gnome_dialog_close (dialog); + return; + } + + folder_name = gtk_entry_get_text (GTK_ENTRY (dialog_data->folder_name_entry)); + path = g_concat_dir_and_file (parent_path, folder_name); + + storage_set = e_shell_get_storage_set (dialog_data->shell); + + folder_type_menu_item = GTK_OPTION_MENU (dialog_data->folder_type_option_menu)->menu_item; + folder_type = gtk_object_get_data (GTK_OBJECT (folder_type_menu_item), "folder_type"); + + if (folder_type == NULL) { + g_warning ("Cannot get folder type for selected GtkOptionMenu item."); + return; + } + + e_storage_set_async_create_folder (storage_set, + path, + folder_type, + NULL, /* description */ + async_create_cb, dialog_data); } static void dialog_close_cb (GnomeDialog *dialog, void *data) { - g_print ("Closed\n"); gtk_widget_destroy (GTK_WIDGET (dialog)); } +static void +dialog_destroy_cb (GtkObject *object, + void *data) +{ + DialogData *dialog_data; + + dialog_data = (DialogData *) data; + dialog_data_destroy (dialog_data); +} + static void folder_name_entry_changed_cb (GtkEditable *editable, void *data) @@ -75,6 +194,19 @@ folder_name_entry_changed_cb (GtkEditable *editable, gnome_dialog_set_sensitive (dialog, 0, FALSE); } + +/* Shell signal callbacks. */ + +static void +shell_destroy_cb (GtkObject *object, + void *data) +{ + GnomeDialog *dialog; + + dialog = GNOME_DIALOG (data); + gtk_widget_destroy (GTK_WIDGET (dialog)); +} + /* Dialog setup. */ @@ -82,10 +214,10 @@ static void setup_dialog (GtkWidget *dialog, GladeXML *gui, EShell *shell, - GtkWindow *parent) + GtkWindow *parent_window) { - if (parent != NULL) - gtk_window_set_transient_for (GTK_WINDOW (dialog), parent); + if (parent_window != NULL) + gtk_window_set_transient_for (GTK_WINDOW (dialog), parent_window); gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); gtk_window_set_title (GTK_WINDOW (dialog), _("Evolution - Create new folder")); @@ -93,11 +225,6 @@ setup_dialog (GtkWidget *dialog, gnome_dialog_set_default (GNOME_DIALOG (dialog), 0); gnome_dialog_set_sensitive (GNOME_DIALOG (dialog), 0, FALSE); - gtk_signal_connect (GTK_OBJECT (dialog), "clicked", - GTK_SIGNAL_FUNC (dialog_clicked_cb), shell); - gtk_signal_connect (GTK_OBJECT (dialog), "close", - GTK_SIGNAL_FUNC (dialog_close_cb), shell); - gtk_widget_show (dialog); } @@ -116,7 +243,7 @@ setup_folder_name_entry (GtkWidget *dialog, GTK_SIGNAL_FUNC (folder_name_entry_changed_cb), dialog); } -static void +static GtkWidget * add_storage_set_view (GtkWidget *dialog, GladeXML *gui, EShell *shell, @@ -146,9 +273,11 @@ add_storage_set_view (GtkWidget *dialog, gtk_widget_show (scroll_frame); gtk_widget_show (storage_set_view); + + return storage_set_view; } -static void +static GList * add_folder_types (GtkWidget *dialog, GladeXML *gui, EShell *shell) @@ -156,7 +285,7 @@ add_folder_types (GtkWidget *dialog, EFolderTypeRegistry *folder_type_registry; GtkWidget *folder_type_option_menu; GtkWidget *menu; - GList *types; + GList *folder_types; GList *p; int default_item; int i; @@ -170,17 +299,17 @@ add_folder_types (GtkWidget *dialog, folder_type_registry = e_shell_get_folder_type_registry (shell); g_assert (folder_type_registry != NULL); - types = e_folder_type_registry_get_type_names (folder_type_registry); - if (types == NULL) - return; /* Uh? */ + folder_types = e_folder_type_registry_get_type_names (folder_type_registry); + if (folder_types == NULL) + return NULL; /* Uh? */ - types = g_list_sort (types, (GCompareFunc) g_strcasecmp); + folder_types = g_list_sort (folder_types, (GCompareFunc) g_strcasecmp); /* FIXME: Use descriptive name (not in the registry's implementation yet). */ /* FIXME: Add icon (I don't feel like writing an alpha-capable thingie again). */ default_item = 0; - for (p = types, i = 0; p != NULL; p = p->next, i++) { + for (p = folder_types, i = 0; p != NULL; p = p->next, i++) { const char *type_name; GtkWidget *menu_item; @@ -190,13 +319,15 @@ add_folder_types (GtkWidget *dialog, gtk_menu_append (GTK_MENU (menu), menu_item); gtk_widget_show (menu_item); + gtk_object_set_data (GTK_OBJECT (menu_item), "folder_type", (void *) type_name); + if (strcmp (type_name, "mail") == 0) default_item = i; } - e_free_string_list (types); - gtk_option_menu_set_history (GTK_OPTION_MENU (folder_type_option_menu), default_item); + + return folder_types; } @@ -205,11 +336,14 @@ add_folder_types (GtkWidget *dialog, open at once. Currently it relies on modality for this. */ void e_shell_show_folder_creation_dialog (EShell *shell, - GtkWindow *parent, + GtkWindow *parent_window, const char *default_parent_folder) { GladeXML *gui; GtkWidget *dialog; + GtkWidget *storage_set_view; + GList *folder_types; + DialogData *dialog_data; g_return_if_fail (shell != NULL); g_return_if_fail (E_IS_SHELL (shell)); @@ -223,11 +357,30 @@ e_shell_show_folder_creation_dialog (EShell *shell, dialog = glade_xml_get_widget (gui, "create_folder_dialog"); - setup_dialog (dialog, gui, shell, parent); + setup_dialog (dialog, gui, shell, parent_window); setup_folder_name_entry (dialog, gui, shell); - add_storage_set_view (dialog, gui, shell, default_parent_folder); - add_folder_types (dialog, gui, shell); + storage_set_view = add_storage_set_view (dialog, gui, shell, default_parent_folder); + folder_types = add_folder_types (dialog, gui, shell); + + dialog_data = g_new (DialogData, 1); + dialog_data->dialog = dialog; + dialog_data->shell = shell; + dialog_data->folder_name_entry = glade_xml_get_widget (gui, "folder_name_entry"); + dialog_data->storage_set_view = storage_set_view; + dialog_data->folder_type_option_menu = glade_xml_get_widget (gui, "folder_type_option_menu"); + dialog_data->folder_types = folder_types; + + gtk_signal_connect (GTK_OBJECT (dialog), "clicked", + GTK_SIGNAL_FUNC (dialog_clicked_cb), dialog_data); + gtk_signal_connect (GTK_OBJECT (dialog), "close", + GTK_SIGNAL_FUNC (dialog_close_cb), dialog_data); + gtk_signal_connect (GTK_OBJECT (dialog), "destroy", + GTK_SIGNAL_FUNC (dialog_destroy_cb), dialog_data); + + gtk_signal_connect_while_alive (GTK_OBJECT (shell), "destroy", + GTK_SIGNAL_FUNC (shell_destroy_cb), dialog_data, + GTK_OBJECT (dialog)); gtk_object_unref (GTK_OBJECT (gui)); } diff --git a/shell/e-shell.c b/shell/e-shell.c index 03ae95c863..fcaa592a32 100644 --- a/shell/e-shell.c +++ b/shell/e-shell.c @@ -171,7 +171,7 @@ setup_local_storage (EShell *shell) local_storage_path = g_concat_dir_and_file (priv->local_directory, LOCAL_STORAGE_DIRECTORY); - local_storage = e_local_storage_open (shell->priv->component_registry, + local_storage = e_local_storage_open (priv->folder_type_registry, local_storage_path); if (local_storage == NULL) { g_warning (_("Cannot set up local storage -- %s"), local_storage_path); diff --git a/shell/e-storage-set-view.c b/shell/e-storage-set-view.c index 989f6c5f62..88e70e4f78 100644 --- a/shell/e-storage-set-view.c +++ b/shell/e-storage-set-view.c @@ -856,5 +856,36 @@ e_storage_set_view_set_current_folder (EStorageSetView *storage_set_view, gtk_signal_emit (GTK_OBJECT (storage_set_view), signals[FOLDER_SELECTED], path); } +const char * +e_storage_set_view_get_current_folder (EStorageSetView *storage_set_view) +{ + EStorageSetViewPrivate *priv; + GtkCList *clist; + GtkCTree *ctree; + GtkCTreeRow *ctree_row; + GtkCTreeNode *ctree_node; + const char *path; + + g_return_val_if_fail (storage_set_view != NULL, NULL); + g_return_val_if_fail (E_IS_STORAGE_SET_VIEW (storage_set_view), NULL); + + priv = storage_set_view->priv; + + clist = GTK_CLIST (storage_set_view); + ctree = GTK_CTREE (storage_set_view); + + if (clist->selection == NULL) + return NULL; + + ctree_row = GTK_CTREE_ROW (clist->selection->data); + ctree_node = gtk_ctree_find_node_ptr (ctree, ctree_row); + if (ctree_node == NULL) + return NULL; /* Mmh? */ + + path = g_hash_table_lookup (priv->ctree_node_to_path, ctree_node); + + return path; +} + E_MAKE_TYPE (e_storage_set_view, "EStorageSetView", EStorageSetView, class_init, init, PARENT_TYPE) diff --git a/shell/e-storage-set-view.h b/shell/e-storage-set-view.h index d865eb426c..098de0d2a7 100644 --- a/shell/e-storage-set-view.h +++ b/shell/e-storage-set-view.h @@ -63,12 +63,13 @@ struct _EStorageSetViewClass { }; -GtkType e_storage_set_view_get_type (void); -GtkWidget *e_storage_set_view_new (EStorageSet *storage_set); -void e_storage_set_view_construct (EStorageSetView *storage_set_view, - EStorageSet *storage_set); -void e_storage_set_view_set_current_folder (EStorageSetView *storage_set_view, - const char *path); +GtkType e_storage_set_view_get_type (void); +GtkWidget *e_storage_set_view_new (EStorageSet *storage_set); +void e_storage_set_view_construct (EStorageSetView *storage_set_view, + EStorageSet *storage_set); +void e_storage_set_view_set_current_folder (EStorageSetView *storage_set_view, + const char *path); +const char *e_storage_set_view_get_current_folder (EStorageSetView *storage_set_view); #ifdef __cplusplus } diff --git a/shell/e-storage-set.c b/shell/e-storage-set.c index 33dc366afe..a779023bab 100644 --- a/shell/e-storage-set.c +++ b/shell/e-storage-set.c @@ -152,6 +152,37 @@ storage_removed_folder_cb (EStorage *storage, g_free (full_path); } + +static EStorage * +get_storage_for_path (EStorageSet *storage_set, + const char *path, + const char **subpath_return) +{ + EStorage *storage; + char *storage_name; + const char *first_separator; + + 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) { + *subpath_return = NULL; + return NULL; + } + + storage_name = g_strndup (path, first_separator - path); + storage = e_storage_set_get_storage (storage_set, storage_name); + g_free (storage_name); + + *subpath_return = first_separator; + + return storage; +} + /* GtkObject methods. */ @@ -412,30 +443,16 @@ e_storage_set_get_folder (EStorageSet *storage_set, const char *path) { EStorage *storage; - const char *first_separator; - char *storage_name; + const char *subpath; 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; + storage = get_storage_for_path (storage_set, path, &subpath); - return e_storage_get_folder (storage, first_separator); + return e_storage_get_folder (storage, subpath); } @@ -452,6 +469,50 @@ e_storage_set_new_view (EStorageSet *storage_set) return storage_set_view; } + +void +e_storage_set_async_create_folder (EStorageSet *storage_set, + const char *path, + const char *type, + const char *description, + EStorageResultCallback callback, + void *data) +{ + EStorage *storage; + const char *subpath; + + g_return_if_fail (storage_set != NULL); + g_return_if_fail (E_IS_STORAGE_SET (storage_set)); + g_return_if_fail (path != NULL); + g_return_if_fail (g_path_is_absolute (path)); + g_return_if_fail (type != NULL); + g_return_if_fail (callback != NULL); + + storage = get_storage_for_path (storage_set, path, &subpath); + + e_storage_async_create_folder (storage, subpath, type, description, callback, data); +} + +void +e_storage_set_async_remove_folder (EStorageSet *storage_set, + const char *path, + EStorageResultCallback callback, + void *data) +{ + EStorage *storage; + const char *subpath; + + g_return_if_fail (storage_set != NULL); + g_return_if_fail (E_IS_STORAGE_SET (storage_set)); + g_return_if_fail (path != NULL); + g_return_if_fail (g_path_is_absolute (path)); + g_return_if_fail (callback != NULL); + + storage = get_storage_for_path (storage_set, path, &subpath); + + e_storage_async_remove_folder (storage, path, callback, data); +} + EFolderTypeRegistry * e_storage_set_get_folder_type_registry (EStorageSet *storage_set) diff --git a/shell/e-storage-set.h b/shell/e-storage-set.h index 9f9b38ac64..7731b5cafc 100644 --- a/shell/e-storage-set.h +++ b/shell/e-storage-set.h @@ -69,23 +69,34 @@ struct _EStorageSetClass { GtkType e_storage_set_get_type (void); -void e_storage_set_construct (EStorageSet *storage_set, - EFolderTypeRegistry *folder_type_registry); -EStorageSet *e_storage_set_new (EFolderTypeRegistry *folder_type_registry); - -gboolean e_storage_set_add_storage (EStorageSet *storage_set, - EStorage *storage); -gboolean e_storage_set_remove_storage (EStorageSet *storage_set, - EStorage *storage); -void e_storage_set_remove_all_storages (EStorageSet *storage_set); - -GList *e_storage_set_get_storage_list (EStorageSet *storage_set); -EStorage *e_storage_set_get_storage (EStorageSet *storage_set, - const char *storage_name); -EFolder *e_storage_set_get_folder (EStorageSet *storage_set, - const char *path); - -GtkWidget *e_storage_set_new_view (EStorageSet *storage_set); +void e_storage_set_construct (EStorageSet *storage_set, + EFolderTypeRegistry *folder_type_registry); +EStorageSet *e_storage_set_new (EFolderTypeRegistry *folder_type_registry); + +gboolean e_storage_set_add_storage (EStorageSet *storage_set, + EStorage *storage); +gboolean e_storage_set_remove_storage (EStorageSet *storage_set, + EStorage *storage); +void e_storage_set_remove_all_storages (EStorageSet *storage_set); + +GList *e_storage_set_get_storage_list (EStorageSet *storage_set); +EStorage *e_storage_set_get_storage (EStorageSet *storage_set, + const char *storage_name); +EFolder *e_storage_set_get_folder (EStorageSet *storage_set, + const char *path); + +GtkWidget *e_storage_set_new_view (EStorageSet *storage_set); + +void e_storage_set_async_create_folder (EStorageSet *storage_set, + const char *path, + const char *type, + const char *description, + EStorageResultCallback callback, + void *data); +void e_storage_set_async_remove_folder (EStorageSet *storage_set, + const char *path, + EStorageResultCallback callback, + void *data); EFolderTypeRegistry *e_storage_set_get_folder_type_registry (EStorageSet *storage_set); diff --git a/shell/e-storage.c b/shell/e-storage.c index b50a080fc4..30c0c6d667 100644 --- a/shell/e-storage.c +++ b/shell/e-storage.c @@ -218,21 +218,21 @@ impl_get_name (EStorage *storage) } static void -impl_create_folder (EStorage *storage, - const char *path, - const char *type, - const char *description, - EStorageResultCallback callback, - void *data) +impl_async_create_folder (EStorage *storage, + const char *path, + const char *type, + const char *description, + EStorageResultCallback callback, + void *data) { (* callback) (storage, E_STORAGE_NOTIMPLEMENTED, data); } static void -impl_remove_folder (EStorage *storage, - const char *path, - EStorageResultCallback callback, - void *data) +impl_async_remove_folder (EStorage *storage, + const char *path, + EStorageResultCallback callback, + void *data) { (* callback) (storage, E_STORAGE_NOTIMPLEMENTED, data); } @@ -250,11 +250,11 @@ class_init (EStorageClass *class) object_class->destroy = destroy; - class->list_folders = impl_list_folders; - class->get_folder = impl_get_folder; - class->get_name = impl_get_name; - class->create_folder = impl_create_folder; - class->remove_folder = impl_remove_folder; + class->list_folders = impl_list_folders; + class->get_folder = impl_get_folder; + class->get_name = impl_get_name; + class->async_create_folder = impl_async_create_folder; + class->async_remove_folder = impl_async_remove_folder; signals[NEW_FOLDER] = gtk_signal_new ("new_folder", @@ -371,34 +371,68 @@ e_storage_get_name (EStorage *storage) /* Folder operations. */ void -e_storage_create_folder (EStorage *storage, - const char *path, - const char *type, - const char *description, - EStorageResultCallback callback, - void *data) +e_storage_async_create_folder (EStorage *storage, + const char *path, + const char *type, + const char *description, + EStorageResultCallback callback, + void *data) { 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 (type != NULL); g_return_if_fail (callback != NULL); - (* ES_CLASS (storage)->create_folder) (storage, path, type, description, callback, data); + (* ES_CLASS (storage)->async_create_folder) (storage, path, type, description, callback, data); } void -e_storage_remove_folder (EStorage *storage, - const char *path, - EStorageResultCallback callback, - void *data) +e_storage_async_remove_folder (EStorage *storage, + const char *path, + EStorageResultCallback callback, + void *data) { 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 (callback != NULL); - (* ES_CLASS (storage)->remove_folder) (storage, path, callback, data); + (* ES_CLASS (storage)->async_remove_folder) (storage, path, callback, data); +} + + +const char * +e_storage_result_to_string (EStorageResult result) +{ + switch (result) { + case E_STORAGE_OK: + return _("No error"); + case E_STORAGE_GENERICERROR: + return _("Generic error"); + case E_STORAGE_EXISTS: + return _("A folder with the same name already exists"); + case E_STORAGE_INVALIDTYPE: + return _("The specified folder type is not valid"); + case E_STORAGE_IOERROR: + return _("I/O error"); + case E_STORAGE_NOSPACE: + return _("Not enough space to create the folder"); + case E_STORAGE_NOTFOUND: + return _("The specified folder was not found"); + case E_STORAGE_NOTIMPLEMENTED: + return _("Function not implemented in this storage"); + case E_STORAGE_PERMISSIONDENIED: + return _("Permission denied"); + case E_STORAGE_UNSUPPORTEDOPERATION: + return _("Operation not supported"); + case E_STORAGE_UNSUPPORTEDTYPE: + return _("The specified type is not supported in this storage"); + default: + return _("Unknown error"); + } } diff --git a/shell/e-storage.h b/shell/e-storage.h index b144d0af5a..5422d6a9b4 100644 --- a/shell/e-storage.h +++ b/shell/e-storage.h @@ -48,10 +48,15 @@ typedef struct _EStorageClass EStorageClass; enum _EStorageResult { E_STORAGE_OK, - E_STORAGE_NOTIMPLEMENTED, - E_STORAGE_NOTFOUND, + E_STORAGE_GENERICERROR, E_STORAGE_EXISTS, - E_STORAGE_IO, + E_STORAGE_INVALIDTYPE, + E_STORAGE_IOERROR, + E_STORAGE_NOSPACE, + E_STORAGE_NOTFOUND, + E_STORAGE_NOTIMPLEMENTED, + E_STORAGE_PERMISSIONDENIED, + E_STORAGE_UNSUPPORTEDOPERATION, E_STORAGE_UNSUPPORTEDTYPE }; typedef enum _EStorageResult EStorageResult; @@ -76,15 +81,15 @@ struct _EStorageClass { /* Virtual methods. */ - GList * (* list_folders) (EStorage *storage, const char *path); - EFolder * (* get_folder) (EStorage *storage, const char *path); - const char * (* get_name) (EStorage *storage); + GList * (* list_folders) (EStorage *storage, const char *path); + EFolder * (* get_folder) (EStorage *storage, const char *path); + const char * (* get_name) (EStorage *storage); - void (* create_folder) (EStorage *storage, const char *path, - const char *type, const char *description, - EStorageResultCallback callback, void *data); - void (* remove_folder) (EStorage *storage, const char *path, - EStorageResultCallback callback, void *data); + void (* async_create_folder) (EStorage *storage, const char *path, + const char *type, const char *description, + EStorageResultCallback callback, void *data); + void (* async_remove_folder) (EStorage *storage, const char *path, + EStorageResultCallback callback, void *data); }; @@ -101,16 +106,18 @@ const char *e_storage_get_name (EStorage *storage); /* Folder operations. */ -void e_storage_create_folder (EStorage *storage, - const char *path, - const char *type, - const char *description, - EStorageResultCallback callback, - void *data); -void e_storage_remove_folder (EStorage *storage, - const char *path, - EStorageResultCallback callback, - void *data); +void e_storage_async_create_folder (EStorage *storage, + const char *path, + const char *type, + const char *description, + EStorageResultCallback callback, + void *data); +void e_storage_async_remove_folder (EStorage *storage, + const char *path, + EStorageResultCallback callback, + void *data); + +const char *e_storage_result_to_string (EStorageResult result); /* Protected. C++ anyone? */ gboolean e_storage_new_folder (EStorage *storage, const char *path, EFolder *folder); diff --git a/shell/evolution-shell-component-client.c b/shell/evolution-shell-component-client.c index 53a4933142..29427501ab 100644 --- a/shell/evolution-shell-component-client.c +++ b/shell/evolution-shell-component-client.c @@ -137,13 +137,13 @@ dispatch_callback (EvolutionShellComponentClient *shell_component_client, CORBA_exception_init (&ev); - CORBA_Object_release (priv->listener_interface, &ev); - oid = PortableServer_POA_servant_to_id (bonobo_poa (), priv->listener_servant, &ev); PortableServer_POA_deactivate_object (bonobo_poa (), oid, &ev); POA_Evolution_ShellComponentListener__fini (priv->listener_servant, &ev); CORBA_free (oid); + CORBA_Object_release (priv->listener_interface, &ev); + CORBA_exception_free (&ev); priv->listener_servant = NULL; @@ -251,34 +251,38 @@ free_ShellComponentListener_servant (PortableServer_Servant servant) g_free (servant); } -static CORBA_Object +static void create_listener_interface (EvolutionShellComponentClient *shell_component_client) { - PortableServer_Servant servant; + EvolutionShellComponentClientPrivate *priv; + PortableServer_Servant listener_servant; Evolution_ShellComponentListener corba_interface; CORBA_Environment ev; - servant = create_ShellComponentListener_servant (shell_component_client); + priv = shell_component_client->priv; + + listener_servant = create_ShellComponentListener_servant (shell_component_client); CORBA_exception_init (&ev); - POA_Evolution_ShellComponentListener__init (servant, &ev); + POA_Evolution_ShellComponentListener__init (listener_servant, &ev); if (ev._major != CORBA_NO_EXCEPTION) { - free_ShellComponentListener_servant (servant); - return CORBA_OBJECT_NIL; + free_ShellComponentListener_servant (listener_servant); + return; } - CORBA_free (PortableServer_POA_activate_object (bonobo_poa (), servant, &ev)); + CORBA_free (PortableServer_POA_activate_object (bonobo_poa (), listener_servant, &ev)); - corba_interface = PortableServer_POA_servant_to_reference (bonobo_poa (), servant, &ev); + corba_interface = PortableServer_POA_servant_to_reference (bonobo_poa (), listener_servant, &ev); if (ev._major != CORBA_NO_EXCEPTION) { corba_interface = CORBA_OBJECT_NIL; - free_ShellComponentListener_servant (servant); + free_ShellComponentListener_servant (listener_servant); } CORBA_exception_free (&ev); - return corba_interface; + priv->listener_servant = listener_servant; + priv->listener_interface = corba_interface; } @@ -319,8 +323,10 @@ init (EvolutionShellComponentClient *shell_component_client) EvolutionShellComponentClientPrivate *priv; priv = g_new (EvolutionShellComponentClientPrivate, 1); - priv->callback = NULL; - priv->callback_data = NULL; + priv->listener_interface = CORBA_OBJECT_NIL; + priv->listener_servant = NULL; + priv->callback = NULL; + priv->callback_data = NULL; shell_component_client->priv = priv; } @@ -476,21 +482,20 @@ evolution_shell_component_client_async_create_folder (EvolutionShellComponentCli return; } - priv->listener_interface = create_listener_interface (shell_component_client); + create_listener_interface (shell_component_client); CORBA_exception_init (&ev); corba_shell_component = bonobo_object_corba_objref (BONOBO_OBJECT (shell_component_client)); + priv->callback = callback; + priv->callback_data = data; + Evolution_ShellComponent_async_create_folder (corba_shell_component, priv->listener_interface, physical_uri, type, &ev); - /* FIXME merge with create_listener_interface into separate init_for_callback() func. */ - priv->callback = callback; - priv->callback_data = data; - CORBA_exception_free (&ev); } diff --git a/shell/evolution-shell-component.h b/shell/evolution-shell-component.h index ec049fbd94..a1a70ebafa 100644 --- a/shell/evolution-shell-component.h +++ b/shell/evolution-shell-component.h @@ -70,20 +70,21 @@ enum _EvolutionShellComponentResult { }; typedef enum _EvolutionShellComponentResult EvolutionShellComponentResult; -typedef EvolutionShellComponentResult (* EvolutionShellComponentCreateViewFn) (EvolutionShellComponent *shell_component, - const char *physical_uri, - const char *type, - BonoboControl **control_return, - void *closure); -typedef EvolutionShellComponentResult (* EvolutionShellComponentCreateFolderFn) (EvolutionShellComponent *shell_component, - const char *physical_uri, - const char *type, - const Evolution_ShellComponentListener listener, - void *closure); -typedef EvolutionShellComponentResult (* EvolutionShellComponentRemoveFolderFn) (EvolutionShellComponent *shell_component, - const char *physical_uri, - const Evolution_ShellComponentListener listener, - void *closure); +typedef EvolutionShellComponentResult (* EvolutionShellComponentCreateViewFn) + (EvolutionShellComponent *shell_component, + const char *physical_uri, + const char *type, + BonoboControl **control_return, + void *closure); +typedef void (* EvolutionShellComponentCreateFolderFn) (EvolutionShellComponent *shell_component, + const char *physical_uri, + const char *type, + const Evolution_ShellComponentListener listener, + void *closure); +typedef void (* EvolutionShellComponentRemoveFolderFn) (EvolutionShellComponent *shell_component, + const char *physical_uri, + const Evolution_ShellComponentListener listener, + void *closure); struct _EvolutionShellComponentFolderType { char *name; -- cgit v1.2.3