diff options
author | Ettore Perazzoli <ettore@src.gnome.org> | 2000-05-26 22:49:12 +0800 |
---|---|---|
committer | Ettore Perazzoli <ettore@src.gnome.org> | 2000-05-26 22:49:12 +0800 |
commit | 47ab2202ba161234ec2790290152f64be0163dd7 (patch) | |
tree | 3abf67438aeb9b509c589d489bb89fd1f90a8d60 /shell | |
parent | 3c89185e9f07621d4b516a8ee5dac9f2d267c87d (diff) | |
download | gsoc2013-evolution-47ab2202ba161234ec2790290152f64be0163dd7.tar.gz gsoc2013-evolution-47ab2202ba161234ec2790290152f64be0163dd7.tar.zst gsoc2013-evolution-47ab2202ba161234ec2790290152f64be0163dd7.zip |
Made the storage view update at changes in the storage, and
implemented a BonoboObject for wrapping the Evolution::Storage CORBA
interface. Also fixed a few bugs.
This makes the shell's storage extensibility usable for Evolution
components.
svn path=/trunk/; revision=3219
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ChangeLog | 102 | ||||
-rw-r--r-- | shell/Evolution-Storage.idl | 2 | ||||
-rw-r--r-- | shell/Makefile.am | 4 | ||||
-rw-r--r-- | shell/e-corba-storage-registry.c | 14 | ||||
-rw-r--r-- | shell/e-corba-storage.c | 5 | ||||
-rw-r--r-- | shell/e-folder.c | 29 | ||||
-rw-r--r-- | shell/e-folder.h | 1 | ||||
-rw-r--r-- | shell/e-local-folder.c | 34 | ||||
-rw-r--r-- | shell/e-local-folder.h | 2 | ||||
-rw-r--r-- | shell/e-shell.c | 2 | ||||
-rw-r--r-- | shell/e-storage-set-view.c | 319 | ||||
-rw-r--r-- | shell/e-storage-set.c | 194 | ||||
-rw-r--r-- | shell/e-storage-set.h | 16 | ||||
-rw-r--r-- | shell/e-storage.c | 170 | ||||
-rw-r--r-- | shell/e-storage.h | 13 | ||||
-rw-r--r-- | shell/evolution-shell-component.c | 12 | ||||
-rw-r--r-- | shell/evolution-shell-component.h | 2 | ||||
-rw-r--r-- | shell/evolution-storage.c | 395 | ||||
-rw-r--r-- | shell/evolution-storage.h | 96 |
19 files changed, 1137 insertions, 275 deletions
diff --git a/shell/ChangeLog b/shell/ChangeLog index e72c09712a..7f1746e625 100644 --- a/shell/ChangeLog +++ b/shell/ChangeLog @@ -1,3 +1,105 @@ +2000-05-26 Ettore Perazzoli <ettore@helixcode.com> + + * e-corba-storage.c (impl_StorageListener_new_folder): Set the + physical URI on the folder using `e_folder_set_physical_uri()'. + + * e-local-folder.c (get_physical_uri): Removed. + (construct_loading_metadata): Use EFolder's `physical_uri' field + instead of ours, which is gone. + (save_metadata): Likewise. + (destroy): Don't free. + + * e-local-folder.h: Removed `physical_uri' from `ELocalFolder'. + + * e-folder.c: New member `physical_uri' in `EFolderPrivate'. + (init): Initialize to NULL. + (destroy): Free it. + (get_physical_uri): Removed. + (e_folder_set_physical_uri): New function. + + * e-storage-set.c (e_storage_set_get_folder): Fix off-by-one error + in extracting the base name. + + * e-storage.c: New member `path' in `Folder'. + (folder_destroy): Free it. + (folder_new): New arg. Initialize `path' from it. + (e_storage_construct): Updated accordingly. + (e_storage_new_folder): Likewise. + (e_storage_remove_folder): Remove the folder from the hash. + + * e-storage-set-view.c (remove_node): New function. + (removed_storage_cb): Use it. + (new_folder_cb): New function, callback for the "new_folder" + signal on the EStorageSet. + (removed_folder_cb): New function, callback for the + "removed_folder" signal on the EStorageSet. + (e_storage_set_view_construct): Connect these signal handlers to + the respective signals on our model storage. + + * e-storage-set.c (storage_new_folder_cb): New function, callback + for the "new_folder" signal on the storages. + (storage_removed_folder_cb): New function, callback for the + "removed_folder" signal on the storages. + (e_storage_set_add_storage): Connect them to the signals of the + storage being added. + + * e-corba-storage-registry.c + (impl_StorageRegistry_register_storage): Throw an exception if + `e_storage_set_add_storage()' returns false. + + * e-shell.c (setup_storages): Unref the local storage after adding + to the storage set. + + * e-corba-storage-registry.c + (impl_StorageRegistry_register_storage): Unref the storage after + adding to the storage set. + + * e-storage-set.c: New hash table `name_to_named_storage' in + `EStorageSetPrivate'. + (named_storage_new): New helper function. + (named_storage_destroy): New helper function. + (e_storage_set_add_storage): Use the hash table. Return value + changed to `gboolean'. Return FALSE if there is a storage with + that name already. Also, ref the storage. + (e_storage_set_remove_storage): Likewise [but of course don't ref + the storage]. + (e_storage_set_get_storage): Use the `name_to_named_storage' hash + table. + (destroy): Destroy the `name_to_named_storage' hash. + + * e-storage-set.h: New signals "new_folder", "removed_folder". + + * e-storage.c (e_storage_get_watcher_for_path): Removed. + (get_watcher_for_path): Removed. + (class_init): Install signals "new_folder" and "removed_folder". + (e_storage_remove_folder): Emit "removed_folder". + (e_storage_new_folder): Emit "new_folder". + + * e-storage.h: Removed method `get_watcher_for_path'. New signals + "new_folder", "removed_folder". + + * e-storage-watcher.c: Removed. + * e-storage-watcher.h: Removed. + + * e-corba-storage-registry.c (corba_class_init): Set the + Bonobo_Unknown evp parts. + + * evolution-storage.c: New. + * evolution-storage.h: New. + + * evolution-shell-component.c + (evolution_shell_component_get_owner): New. + + * e-storage-set-view.c (new_storage_cb): New function. + (e_storage_set_view_construct): Connect to the "new_storage" + signal on the EStorageSet. + (removed_storage_cb): New function. + (e_storage_set_view_construct): Connect to the "removed_storage" + signal on the EStorageSet. + + * e-storage-set-view.c (e_storage_set_view_construct): Make this + always look pretty, with Helix GNOME or without. + 2000-05-25 Christopher James Lahey <clahey@helixcode.com> * e-storage-set-view.c: Make this always look pretty, with Helix diff --git a/shell/Evolution-Storage.idl b/shell/Evolution-Storage.idl index d88db2f152..4e35e859bf 100644 --- a/shell/Evolution-Storage.idl +++ b/shell/Evolution-Storage.idl @@ -23,8 +23,6 @@ module Evolution { interface Storage : Bonobo::Unknown { attribute string name; - - void set_listener (in StorageListener storage_listener); }; interface StorageListener { diff --git a/shell/Makefile.am b/shell/Makefile.am index d3f680b975..19134e59b8 100644 --- a/shell/Makefile.am +++ b/shell/Makefile.am @@ -62,12 +62,12 @@ evolution_SOURCES = \ e-storage-set-view.h \ e-storage-set.c \ e-storage-set.h \ - e-storage-watcher.c \ - e-storage-watcher.h \ e-storage.c \ e-storage.h \ evolution-shell-component.c \ evolution-shell-component.h \ + evolution-storage.c \ + evolution-storage.h \ main.c Evolution-impl.o: Evolution.h diff --git a/shell/e-corba-storage-registry.c b/shell/e-corba-storage-registry.c index 51f845ea38..c3b259bb71 100644 --- a/shell/e-corba-storage-registry.c +++ b/shell/e-corba-storage-registry.c @@ -79,14 +79,23 @@ impl_StorageRegistry_register_storage (PortableServer_Servant servant, EStorage *storage; Evolution_StorageListener listener_interface; + g_print ("Shell: Registering storage -- %s\n", name); + bonobo_object = bonobo_object_from_servant (servant); storage_registry = E_CORBA_STORAGE_REGISTRY (bonobo_object); priv = storage_registry->priv; storage = e_corba_storage_new (storage_interface, name); - /* FIXME check failure. */ - e_storage_set_add_storage (priv->storage_set, storage); + if (! e_storage_set_add_storage (priv->storage_set, storage)) { + CORBA_exception_set (ev, + CORBA_USER_EXCEPTION, + ex_Evolution_StorageRegistry_Exists, + NULL); + return CORBA_OBJECT_NIL; + } + + gtk_object_unref (GTK_OBJECT (storage)); listener_interface = CORBA_Object_duplicate (e_corba_storage_get_StorageListener (E_CORBA_STORAGE (storage)), ev); @@ -161,6 +170,7 @@ corba_class_init (void) vepv = &storage_registry_vepv; vepv->_base_epv = base_epv; + vepv->Bonobo_Unknown_epv = bonobo_object_get_epv (); vepv->Evolution_StorageRegistry_epv = epv; } diff --git a/shell/e-corba-storage.c b/shell/e-corba-storage.c index 4048a6d272..00f1c575b0 100644 --- a/shell/e-corba-storage.c +++ b/shell/e-corba-storage.c @@ -109,13 +109,18 @@ impl_StorageListener_new_folder (PortableServer_Servant servant, folder->type, folder->description); + e_folder_set_physical_uri (e_folder, folder->physical_uri); + if (! e_storage_new_folder (storage, path, e_folder)) { + g_print ("Cannot register folder -- %s %s\n", path, folder->name); CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_Evolution_StorageListener_Exists, NULL); gtk_object_unref (GTK_OBJECT (e_folder)); } + + g_print ("Folder registered successfully -- %s %s\n", path, folder->name); } static void diff --git a/shell/e-folder.c b/shell/e-folder.c index 722e865499..2e16c0896e 100644 --- a/shell/e-folder.c +++ b/shell/e-folder.c @@ -40,6 +40,7 @@ struct _EFolderPrivate { char *name; char *type; char *description; + char *physical_uri; }; #define EF_CLASS(obj) \ @@ -83,9 +84,7 @@ remove (EFolder *folder) static const char * get_physical_uri (EFolder *folder) { - g_warning ("`%s' does not implement `EFolder::get_physical_uri()'", - gtk_type_name (GTK_OBJECT_TYPE (folder))); - return NULL; + return folder->priv->physical_uri; } @@ -103,6 +102,7 @@ destroy (GtkObject *object) g_free (priv->name); g_free (priv->type); g_free (priv->description); + g_free (priv->physical_uri); g_free (priv); @@ -141,9 +141,10 @@ init (EFolder *folder) EFolderPrivate *priv; priv = g_new (EFolderPrivate, 1); - priv->type = NULL; - priv->name = NULL; - priv->description = NULL; + priv->type = NULL; + priv->name = NULL; + priv->description = NULL; + priv->physical_uri = NULL; folder->priv = priv; } @@ -261,6 +262,20 @@ e_folder_set_description (EFolder *folder, gtk_signal_emit (GTK_OBJECT (folder), signals[CHANGED]); } +void +e_folder_set_physical_uri (EFolder *folder, + const char *physical_uri) +{ + g_return_if_fail (folder != NULL); + g_return_if_fail (E_IS_FOLDER (folder)); + g_return_if_fail (physical_uri != NULL); + + g_free (folder->priv->physical_uri); + folder->priv->physical_uri = g_strdup (physical_uri); + + gtk_signal_emit (GTK_OBJECT (folder), signals[CHANGED]); +} + const char * e_folder_get_physical_uri (EFolder *folder) @@ -268,7 +283,7 @@ e_folder_get_physical_uri (EFolder *folder) g_return_val_if_fail (folder != NULL, NULL); g_return_val_if_fail (E_IS_FOLDER (folder), NULL); - return (* EF_CLASS (folder)->get_physical_uri) (folder); + return folder->priv->physical_uri; } diff --git a/shell/e-folder.h b/shell/e-folder.h index cf49c68864..d7bbd6ba9e 100644 --- a/shell/e-folder.h +++ b/shell/e-folder.h @@ -84,6 +84,7 @@ const char *e_folder_get_description (EFolder *folder); void e_folder_set_name (EFolder *folder, const char *name); void e_folder_set_type_string (EFolder *folder, const char *type); void e_folder_set_description (EFolder *folder, const char *description); +void e_folder_set_physical_uri (EFolder *folder, const char *physical_uri); #ifdef __cplusplus } diff --git a/shell/e-local-folder.c b/shell/e-local-folder.c index b164eb1e95..23cd106390 100644 --- a/shell/e-local-folder.c +++ b/shell/e-local-folder.c @@ -56,6 +56,10 @@ static EFolderClass *parent_class = NULL; #define METADATA_FILE_NAME "folder-metadata.xml" #define METADATA_FILE_NAME_LEN 19 +struct _ELocalFolderPrivate { + int dummy; +}; + static char * get_string_value (xmlNode *node, @@ -90,6 +94,7 @@ construct_loading_metadata (ELocalFolder *local_folder, char *type; char *description; char *metadata_path; + char *physical_uri; folder = E_FOLDER (local_folder); @@ -118,7 +123,9 @@ construct_loading_metadata (ELocalFolder *local_folder, xmlFreeDoc (doc); - local_folder->physical_uri = g_strconcat (URI_PREFIX, path, NULL); + physical_uri = g_strconcat (URI_PREFIX, path, NULL); + e_folder_set_physical_uri (folder, physical_uri); + g_free (physical_uri); g_free (metadata_path); @@ -142,7 +149,7 @@ save_metadata (ELocalFolder *local_folder) xmlNewChild (root, NULL, (xmlChar *) "type", (xmlChar *) e_folder_get_type_string (folder)); xmlNewChild (root, NULL, (xmlChar *) "description", (xmlChar *) e_folder_get_description (folder)); - physical_path = local_folder->physical_uri + URI_PREFIX_LEN - 1; + physical_path = e_folder_get_physical_uri (folder) + URI_PREFIX_LEN - 1; if (xmlSaveFile (physical_path, doc) < 0) { xmlFreeDoc (doc); @@ -154,28 +161,12 @@ save_metadata (ELocalFolder *local_folder) } -/* EFolder methods. */ - -static const char * -get_physical_uri (EFolder *folder) -{ - ELocalFolder *local_folder; - - local_folder = E_LOCAL_FOLDER (folder); - return local_folder->physical_uri; -} - - /* GtkObject methods. */ static void destroy (GtkObject *object) { - ELocalFolder *folder; - - folder = E_LOCAL_FOLDER (object); - - g_free (folder->physical_uri); + /* No ELocalFolder-specific data to free. */ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); } @@ -185,21 +176,16 @@ static void class_init (ELocalFolderClass *klass) { GtkObjectClass *object_class; - EFolderClass *folder_class; parent_class = gtk_type_class (e_folder_get_type ()); object_class = GTK_OBJECT_CLASS (klass); object_class->destroy = destroy; - - folder_class = E_FOLDER_CLASS (klass); - folder_class->get_physical_uri = get_physical_uri; } static void init (ELocalFolder *local_folder) { - local_folder->physical_uri = NULL; } diff --git a/shell/e-local-folder.h b/shell/e-local-folder.h index 6092532791..b30a9f2a5c 100644 --- a/shell/e-local-folder.h +++ b/shell/e-local-folder.h @@ -48,8 +48,6 @@ typedef struct _ELocalFolderClass ELocalFolderClass; struct _ELocalFolder { EFolder parent; - - char *physical_uri; }; struct _ELocalFolderClass { diff --git a/shell/e-shell.c b/shell/e-shell.c index ca1c44f576..ec61116534 100644 --- a/shell/e-shell.c +++ b/shell/e-shell.c @@ -165,6 +165,8 @@ setup_storages (EShell *shell) priv->storage_set = e_storage_set_new (shell->priv->folder_type_registry); e_storage_set_add_storage (priv->storage_set, local_storage); + gtk_object_unref (GTK_OBJECT (local_storage)); + return setup_corba_storages (shell); } diff --git a/shell/e-storage-set-view.c b/shell/e-storage-set-view.c index 5b5a11972a..95559e184a 100644 --- a/shell/e-storage-set-view.c +++ b/shell/e-storage-set-view.c @@ -90,6 +90,122 @@ static const int num_drag_types = sizeof (drag_types) / sizeof (drag_types[0]); static GtkTargetList *target_list; +/* Helper functions. */ + +static gboolean +add_node_to_hashes (EStorageSetView *storage_set_view, + const char *path, + GtkCTreeNode *node) +{ + EStorageSetViewPrivate *priv; + char *hash_path; + + g_return_val_if_fail (g_path_is_absolute (path), FALSE); + + priv = storage_set_view->priv; + + if (g_hash_table_lookup (priv->path_to_ctree_node, path) != NULL) { + g_warning ("EStorageSetView: Node already existing while adding -- %s", path); + return FALSE; + } + + g_print ("EStorageSetView: Adding -- %s\n", path); + + hash_path = g_strdup (path); + + g_hash_table_insert (priv->path_to_ctree_node, hash_path, node); + g_hash_table_insert (priv->ctree_node_to_path, node, hash_path); + + return TRUE; +} + +static GtkCTreeNode * +remove_node_from_hashes (EStorageSetView *storage_set_view, + const char *path) +{ + EStorageSetViewPrivate *priv; + GtkCTreeNode *node; + char *hash_path; + + priv = storage_set_view->priv; + + node = g_hash_table_lookup (priv->path_to_ctree_node, path); + if (node == NULL) { + g_warning ("EStorageSetView: Node not found while removing -- %s", path); + return NULL; + } + + g_print ("EStorageSetView: Removing -- %s\n", path); + + hash_path = g_hash_table_lookup (priv->ctree_node_to_path, node); + g_free (hash_path); + + g_hash_table_remove (priv->ctree_node_to_path, node); + g_hash_table_remove (priv->path_to_ctree_node, path); + + return node; +} + +static void +get_pixmap_and_mask_for_folder (EStorageSetView *storage_set_view, + EFolder *folder, + GdkPixmap **pixmap_return, + GdkBitmap **mask_return) +{ + EFolderTypeRegistry *folder_type_registry; + EStorageSet *storage_set; + const char *type_name; + GdkPixbuf *icon_pixbuf; + GdkPixbuf *scaled_pixbuf; + GdkVisual *visual; + GdkGC *gc; + + storage_set = storage_set_view->priv->storage_set; + folder_type_registry = e_storage_set_get_folder_type_registry (storage_set); + + type_name = e_folder_get_type_string (folder); + icon_pixbuf = e_folder_type_registry_get_icon_for_type (folder_type_registry, + type_name, TRUE); + + if (icon_pixbuf == NULL) { + *pixmap_return = NULL; + *mask_return = NULL; + return; + } + + scaled_pixbuf = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (icon_pixbuf), + gdk_pixbuf_get_has_alpha (icon_pixbuf), + gdk_pixbuf_get_bits_per_sample (icon_pixbuf), + E_SHELL_MINI_ICON_SIZE, E_SHELL_MINI_ICON_SIZE); + + gdk_pixbuf_scale (icon_pixbuf, scaled_pixbuf, + 0, 0, E_SHELL_MINI_ICON_SIZE, E_SHELL_MINI_ICON_SIZE, + 0.0, 0.0, + (double) E_SHELL_MINI_ICON_SIZE / gdk_pixbuf_get_width (icon_pixbuf), + (double) E_SHELL_MINI_ICON_SIZE / gdk_pixbuf_get_height (icon_pixbuf), + GDK_INTERP_HYPER); + + visual = gdk_rgb_get_visual (); + *pixmap_return = gdk_pixmap_new (NULL, + E_SHELL_MINI_ICON_SIZE, E_SHELL_MINI_ICON_SIZE, + visual->depth); + + gc = gdk_gc_new (*pixmap_return); + gdk_pixbuf_render_to_drawable (scaled_pixbuf, *pixmap_return, gc, 0, 0, 0, 0, + E_SHELL_MINI_ICON_SIZE, E_SHELL_MINI_ICON_SIZE, + GDK_RGB_DITHER_NORMAL, 0, 0); + gdk_gc_unref (gc); + + *mask_return = gdk_pixmap_new (NULL, E_SHELL_MINI_ICON_SIZE, E_SHELL_MINI_ICON_SIZE, 1); + gdk_pixbuf_render_threshold_alpha (scaled_pixbuf, *mask_return, + 0, 0, 0, 0, + E_SHELL_MINI_ICON_SIZE, E_SHELL_MINI_ICON_SIZE, + 0x7f); + + gdk_pixbuf_unref (scaled_pixbuf); +} + + /* GtkObject methods. */ static void @@ -317,6 +433,134 @@ drag_data_get (GtkWidget *widget, } +/* StorageSet signal handling. */ + +static void +new_storage_cb (EStorageSet *storage_set, + EStorage *storage, + void *data) +{ + EStorageSetView *storage_set_view; + EStorageSetViewPrivate *priv; + GtkCTreeNode *node; + char *text[2]; + char *path; + + storage_set_view = E_STORAGE_SET_VIEW (data); + priv = storage_set_view->priv; + + path = g_strconcat (G_DIR_SEPARATOR_S, e_storage_get_name (storage), NULL); + + text[0] = (char *) e_storage_get_name (storage); /* Yuck. */ + text[1] = NULL; + + node = gtk_ctree_insert_node (GTK_CTREE (storage_set_view), NULL, NULL, + text, 3, NULL, NULL, NULL, NULL, FALSE, TRUE); + + if (! add_node_to_hashes (storage_set_view, path, node)) { + g_free (path); + gtk_ctree_remove_node (GTK_CTREE (storage_set_view), node); + return; + } + + g_free (path); + + /* FIXME: We want a more specialized sort, e.g. the local folders should always be + on top. */ + gtk_ctree_sort_node (GTK_CTREE (storage_set_view), NULL); +} + +static void +removed_storage_cb (EStorageSet *storage_set, + EStorage *storage, + void *data) +{ + EStorageSetView *storage_set_view; + EStorageSetViewPrivate *priv; + GtkCTreeNode *node; + char *path; + + storage_set_view = E_STORAGE_SET_VIEW (data); + priv = storage_set_view->priv; + + path = g_strconcat (G_DIR_SEPARATOR_S, e_storage_get_name (storage), NULL); + node = remove_node_from_hashes (storage_set_view, path); + g_free (path); + + gtk_ctree_remove_node (GTK_CTREE (storage_set_view), node); +} + +static void +new_folder_cb (EStorageSet *storage_set, + const char *path, + void *data) +{ + EStorageSetView *storage_set_view; + EStorageSetViewPrivate *priv; + GtkCTreeNode *parent_node; + GtkCTreeNode *node; + GdkPixmap *pixmap; + GdkBitmap *mask; + char *text[2]; + const char *last_separator; + char *parent_path; + + g_return_if_fail (g_path_is_absolute (path)); + + storage_set_view = E_STORAGE_SET_VIEW (data); + priv = storage_set_view->priv; + + last_separator = strrchr (path, G_DIR_SEPARATOR); + + parent_path = g_strndup (path, last_separator - path); + parent_node = g_hash_table_lookup (priv->path_to_ctree_node, parent_path); + if (parent_node == NULL) { + g_print ("EStorageSetView: EStorageSet reported new subfolder for non-existing folder -- %s\n", + parent_path); + g_free (parent_path); + return; + } + + g_free (parent_path); + + if (parent_node == NULL) + return; + + text[0] = (char *) last_separator + 1; /* Yuck. */ + text[1] = NULL; + + get_pixmap_and_mask_for_folder (storage_set_view, + e_storage_set_get_folder (storage_set, path), + &pixmap, &mask); + node = gtk_ctree_insert_node (GTK_CTREE (storage_set_view), + parent_node, NULL, + text, 3, + pixmap, mask, pixmap, mask, + FALSE, TRUE); + + if (! add_node_to_hashes (storage_set_view, path, node)) { + gtk_ctree_remove_node (GTK_CTREE (storage_set_view), node); + return; + } + + gtk_ctree_sort_node (GTK_CTREE (storage_set_view), parent_node); +} + +static void +removed_folder_cb (EStorageSet *storage_set, + const char *path, + void *data) +{ + EStorageSetView *storage_set_view; + GtkCTreeNode *node; + + storage_set_view = E_STORAGE_SET_VIEW (data); + + node = remove_node_from_hashes (storage_set_view, path); + gtk_ctree_remove_node (GTK_CTREE (storage_set_view), node); +} + + /* GtkCTree methods. */ static void @@ -402,65 +646,6 @@ init (EStorageSetView *storage_set_view) } -static void -get_pixmap_and_mask_for_folder (EStorageSetView *storage_set_view, - EFolder *folder, - GdkPixmap **pixmap_return, - GdkBitmap **mask_return) -{ - EFolderTypeRegistry *folder_type_registry; - EStorageSet *storage_set; - const char *type_name; - GdkPixbuf *icon_pixbuf; - GdkPixbuf *scaled_pixbuf; - GdkVisual *visual; - GdkGC *gc; - - storage_set = storage_set_view->priv->storage_set; - folder_type_registry = e_storage_set_get_folder_type_registry (storage_set); - - type_name = e_folder_get_type_string (folder); - icon_pixbuf = e_folder_type_registry_get_icon_for_type (folder_type_registry, - type_name, TRUE); - - if (icon_pixbuf == NULL) { - *pixmap_return = NULL; - *mask_return = NULL; - return; - } - - scaled_pixbuf = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (icon_pixbuf), - gdk_pixbuf_get_has_alpha (icon_pixbuf), - gdk_pixbuf_get_bits_per_sample (icon_pixbuf), - E_SHELL_MINI_ICON_SIZE, E_SHELL_MINI_ICON_SIZE); - - gdk_pixbuf_scale (icon_pixbuf, scaled_pixbuf, - 0, 0, E_SHELL_MINI_ICON_SIZE, E_SHELL_MINI_ICON_SIZE, - 0.0, 0.0, - (double) E_SHELL_MINI_ICON_SIZE / gdk_pixbuf_get_width (icon_pixbuf), - (double) E_SHELL_MINI_ICON_SIZE / gdk_pixbuf_get_height (icon_pixbuf), - GDK_INTERP_HYPER); - - visual = gdk_rgb_get_visual (); - *pixmap_return = gdk_pixmap_new (NULL, - E_SHELL_MINI_ICON_SIZE, E_SHELL_MINI_ICON_SIZE, - visual->depth); - - gc = gdk_gc_new (*pixmap_return); - gdk_pixbuf_render_to_drawable (scaled_pixbuf, *pixmap_return, gc, 0, 0, 0, 0, - E_SHELL_MINI_ICON_SIZE, E_SHELL_MINI_ICON_SIZE, - GDK_RGB_DITHER_NORMAL, 0, 0); - gdk_gc_unref (gc); - - *mask_return = gdk_pixmap_new (NULL, E_SHELL_MINI_ICON_SIZE, E_SHELL_MINI_ICON_SIZE, 1); - gdk_pixbuf_render_threshold_alpha (scaled_pixbuf, *mask_return, - 0, 0, 0, 0, - E_SHELL_MINI_ICON_SIZE, E_SHELL_MINI_ICON_SIZE, - 0x7f); - - gdk_pixbuf_unref (scaled_pixbuf); -} - static int folder_compare_cb (gconstpointer a, gconstpointer b) { @@ -519,7 +704,6 @@ insert_folders (EStorageSetView *storage_set_view, text[1] = NULL; get_pixmap_and_mask_for_folder (storage_set_view, folder, &pixmap, &mask); - node = gtk_ctree_insert_node (ctree, parent, NULL, text, 3, pixmap, mask, pixmap, mask, @@ -561,9 +745,9 @@ e_storage_set_view_construct (EStorageSetView *storage_set_view, /* Set up GtkCTree/GtkCList parameters. */ gtk_ctree_construct (ctree, 1, 0, NULL); - /* This looks ugly with Helix GNOME unless we do this. */ - gtk_ctree_set_line_style (ctree, GTK_CTREE_LINES_NONE); - gtk_ctree_set_expander_style (ctree, GTK_CTREE_EXPANDER_TRIANGLE); + + gtk_ctree_set_line_style (ctree, GTK_CTREE_LINES_DOTTED); + gtk_ctree_set_expander_style (ctree, GTK_CTREE_EXPANDER_SQUARE); gtk_clist_set_selection_mode (GTK_CLIST (ctree), GTK_SELECTION_BROWSE); gtk_clist_set_row_height (GTK_CLIST (ctree), E_SHELL_MINI_ICON_SIZE); @@ -571,6 +755,15 @@ e_storage_set_view_construct (EStorageSetView *storage_set_view, gtk_object_ref (GTK_OBJECT (storage_set)); priv->storage_set = storage_set; + + gtk_signal_connect (GTK_OBJECT (storage_set), "new_storage", + GTK_SIGNAL_FUNC (new_storage_cb), storage_set_view); + gtk_signal_connect (GTK_OBJECT (storage_set), "removed_storage", + GTK_SIGNAL_FUNC (removed_storage_cb), storage_set_view); + gtk_signal_connect (GTK_OBJECT (storage_set), "new_folder", + GTK_SIGNAL_FUNC (new_folder_cb), storage_set_view); + gtk_signal_connect (GTK_OBJECT (storage_set), "removed_folder", + GTK_SIGNAL_FUNC (removed_folder_cb), storage_set_view); storage_list = e_storage_set_get_storage_list (storage_set); diff --git a/shell/e-storage-set.c b/shell/e-storage-set.c index d1adec19ce..7a71f518fe 100644 --- a/shell/e-storage-set.c +++ b/shell/e-storage-set.c @@ -37,23 +37,107 @@ #include "e-storage-set.h" +#define PARENT_TYPE GTK_TYPE_OBJECT + +static GtkObjectClass *parent_class = NULL; + +/* This is just to make GHashTable happy. */ +struct _NamedStorage { + char *name; + EStorage *storage; +}; +typedef struct _NamedStorage NamedStorage; + +struct _EStorageSetPrivate { + GList *storages; + GHashTable *name_to_named_storage; + + EFolderTypeRegistry *folder_type_registry; +}; + enum { NEW_STORAGE, REMOVED_STORAGE, + NEW_FOLDER, + REMOVED_FOLDER, LAST_SIGNAL }; +static guint signals[LAST_SIGNAL] = { 0 }; + -#define PARENT_TYPE GTK_TYPE_OBJECT +static NamedStorage * +named_storage_new (EStorage *storage) +{ + NamedStorage *new; -static GtkObjectClass *parent_class = NULL; -static guint signals[LAST_SIGNAL] = { 0 }; + new = g_new (NamedStorage, 1); + new->name = g_strdup (e_storage_get_name (storage)); + new->storage = storage; -struct _EStorageSetPrivate { - GList *storages; + return new; +} - EFolderTypeRegistry *folder_type_registry; -}; +static void +named_storage_destroy (NamedStorage *named_storage) +{ + g_free (named_storage->name); + g_free (named_storage); +} + + +/* Handling for signals coming from the EStorages. */ + +static char * +make_full_path (EStorage *storage, + const char *path) +{ + const char *storage_name; + char *full_path; + + storage_name = e_storage_get_name (storage); + + if (! g_path_is_absolute (path)) + full_path = g_strconcat (G_DIR_SEPARATOR_S, storage_name, + G_DIR_SEPARATOR_S, path, NULL); + else + full_path = g_strconcat (G_DIR_SEPARATOR_S, storage_name, + path, NULL); + + return full_path; +} + +static void +storage_new_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); + g_print ("EStorageSet: New folder -- %s\n", full_path); + gtk_signal_emit (GTK_OBJECT (storage_set), signals[NEW_FOLDER], full_path); + g_free (full_path); +} + +static void +storage_removed_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); + g_print ("EStorageSet: Removed folder -- %s\n", full_path); + gtk_signal_emit (GTK_OBJECT (storage_set), signals[REMOVED_FOLDER], full_path); + g_free (full_path); +} /* GtkObject methods. */ @@ -71,6 +155,9 @@ destroy (GtkObject *object) gtk_object_unref (GTK_OBJECT (priv->folder_type_registry)); + g_hash_table_foreach (priv->name_to_named_storage, (GHFunc) named_storage_destroy, NULL); + g_hash_table_destroy (priv->name_to_named_storage); + g_free (priv); (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); @@ -104,6 +191,22 @@ class_init (EStorageSetClass *klass) gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); + signals[NEW_FOLDER] = + gtk_signal_new ("new_folder", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (EStorageSetClass, new_folder), + gtk_marshal_NONE__STRING, + GTK_TYPE_NONE, 1, + GTK_TYPE_STRING); + signals[REMOVED_FOLDER] = + gtk_signal_new ("removed_folder", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (EStorageSetClass, removed_folder), + gtk_marshal_NONE__STRING, + GTK_TYPE_NONE, 1, + GTK_TYPE_STRING); gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); } @@ -114,9 +217,9 @@ init (EStorageSet *storage_set) EStorageSetPrivate *priv; priv = g_new (EStorageSetPrivate, 1); - - priv->storages = NULL; - priv->folder_type_registry = NULL; + priv->storages = NULL; + priv->name_to_named_storage = g_hash_table_new (g_str_hash, g_str_equal); + priv->folder_type_registry = NULL; storage_set->priv = priv; } @@ -174,45 +277,72 @@ e_storage_set_get_storage_list (EStorageSet *storage_set) * @storage_set: * @storage: * - * Add @storage to @storage_set. Notice that this won't ref the @storage, so - * after the call @storage_set actually owns @storage. + * Add @storage to @storage_set. Notice that will ref the storage. **/ -void +gboolean e_storage_set_add_storage (EStorageSet *storage_set, EStorage *storage) { EStorageSetPrivate *priv; + const char *storage_name; + NamedStorage *named_storage; - g_return_if_fail (storage_set != NULL); - g_return_if_fail (E_IS_STORAGE_SET (storage_set)); - g_return_if_fail (storage != NULL); - g_return_if_fail (E_IS_STORAGE (storage)); + g_return_val_if_fail (storage_set != NULL, FALSE); + g_return_val_if_fail (E_IS_STORAGE_SET (storage_set), FALSE); + g_return_val_if_fail (storage != NULL, FALSE); + g_return_val_if_fail (E_IS_STORAGE (storage), FALSE); priv = storage_set->priv; + storage_name = e_storage_get_name (storage); + if (g_hash_table_lookup (priv->name_to_named_storage, storage_name) != NULL) + return FALSE; + + gtk_object_ref (GTK_OBJECT (storage)); + + gtk_signal_connect (GTK_OBJECT (storage), "new_folder", + GTK_SIGNAL_FUNC (storage_new_folder_cb), storage_set); + gtk_signal_connect (GTK_OBJECT (storage), "removed_folder", + GTK_SIGNAL_FUNC (storage_removed_folder_cb), storage_set); + priv->storages = g_list_append (priv->storages, storage); + named_storage = named_storage_new (storage); + g_hash_table_insert (priv->name_to_named_storage, named_storage->name, named_storage); + gtk_signal_emit (GTK_OBJECT (storage_set), signals[NEW_STORAGE], storage); + + return TRUE; } -void +gboolean e_storage_set_remove_storage (EStorageSet *storage_set, EStorage *storage) { EStorageSetPrivate *priv; + NamedStorage *named_storage; - g_return_if_fail (storage_set != NULL); - g_return_if_fail (E_IS_STORAGE_SET (storage_set)); - g_return_if_fail (storage != NULL); - g_return_if_fail (E_IS_STORAGE (storage)); + g_return_val_if_fail (storage_set != NULL, FALSE); + g_return_val_if_fail (E_IS_STORAGE_SET (storage_set), FALSE); + g_return_val_if_fail (storage != NULL, FALSE); + g_return_val_if_fail (E_IS_STORAGE (storage), FALSE); priv = storage_set->priv; + named_storage = g_hash_table_lookup (priv->name_to_named_storage, + e_storage_get_name (storage)); + if (named_storage == NULL) + return FALSE; + + g_hash_table_remove (priv->name_to_named_storage, named_storage->name); + named_storage_destroy (named_storage); + priv->storages = g_list_remove (priv->storages, storage); gtk_signal_emit (GTK_OBJECT (storage_set), signals[REMOVED_STORAGE], storage); - gtk_object_unref (GTK_OBJECT (storage)); + + return TRUE; } EStorage * @@ -220,7 +350,7 @@ e_storage_set_get_storage (EStorageSet *storage_set, const char *name) { EStorageSetPrivate *priv; - GList *p; + NamedStorage *named_storage; g_return_val_if_fail (storage_set != NULL, NULL); g_return_val_if_fail (E_IS_STORAGE_SET (storage_set), NULL); @@ -228,17 +358,11 @@ e_storage_set_get_storage (EStorageSet *storage_set, priv = storage_set->priv; - for (p = priv->storages; p != NULL; p = p->next) { - const char *storage_name; - EStorage *storage; - - storage = E_STORAGE (p->data); - storage_name = e_storage_get_name (storage); - if (strcmp (storage_name, name) == 0) - return storage; - } - - return NULL; + named_storage = g_hash_table_lookup (priv->name_to_named_storage, name); + if (named_storage == NULL) + return NULL; + else + return named_storage->storage; } EFolder * diff --git a/shell/e-storage-set.h b/shell/e-storage-set.h index 500f3c31de..e41471764d 100644 --- a/shell/e-storage-set.h +++ b/shell/e-storage-set.h @@ -58,15 +58,13 @@ struct _EStorageSet { struct _EStorageSetClass { GtkObjectClass parent_class; - /* Virtual methods. */ - - void (* add_storage) (EStorageSet *storage_set, EStorage *storage); - void (* remove_storage) (EStorageSet *storage_set, EStorage *storage); - /* Signals. */ - void (* new_storage) (EStorageSet *storage_set, EStorage *storage); - void (* removed_storage) (EStorageSet *storage_set, EStorage *storage); + void (* new_storage) (EStorageSet *storage_set, EStorage *storage); + void (* removed_storage) (EStorageSet *storage_set, EStorage *storage); + /* FIXME? Inconsistency between storage and folders. */ + void (* new_folder) (EStorageSet *storage_set, const char *path); + void (* removed_folder) (EStorageSet *storage_set, const char *path); }; @@ -75,9 +73,9 @@ void e_storage_set_construct (EStorageSet *storage_set, EFolderTypeRegistry *folder_type_registry); EStorageSet *e_storage_set_new (EFolderTypeRegistry *folder_type_registry); -void e_storage_set_add_storage (EStorageSet *storage_set, +gboolean e_storage_set_add_storage (EStorageSet *storage_set, EStorage *storage); -void e_storage_set_remove_storage (EStorageSet *storage_set, +gboolean e_storage_set_remove_storage (EStorageSet *storage_set, EStorage *storage); GList *e_storage_set_get_storage_list (EStorageSet *storage_set); diff --git a/shell/e-storage.c b/shell/e-storage.c index 974626e7b8..98ce48da70 100644 --- a/shell/e-storage.c +++ b/shell/e-storage.c @@ -41,35 +41,37 @@ static GtkObjectClass *parent_class = NULL; #define ES_CLASS(obj) \ E_STORAGE_CLASS (GTK_OBJECT (obj)->klass) -struct _WatcherList { - char *path; - GList *watchers; -}; -typedef struct _WatcherList WatcherList; - /* This describes a folder and its children. */ struct _Folder { struct _Folder *parent; + + char *path; EFolder *e_folder; GList *subfolders; }; typedef struct _Folder Folder; struct _EStoragePrivate { - GHashTable *path_to_watcher_list; - GHashTable *watcher_to_watcher_list; + GHashTable *path_to_folder; /* Folder */ +}; - /* Every element here is a list of subfolders, hashed to the path of the parent. */ - GHashTable *path_to_folder; +enum { + NEW_FOLDER, + REMOVED_FOLDER, + LAST_SIGNAL }; +static guint signals[LAST_SIGNAL] = { 0 }; + static Folder * -folder_new (EFolder *e_folder) +folder_new (EFolder *e_folder, + const char *path) { Folder *folder; folder = g_new (Folder, 1); + folder->path = g_strdup (path); folder->parent = NULL; folder->e_folder = e_folder; folder->subfolders = NULL; @@ -98,6 +100,8 @@ folder_destroy (Folder *folder) if (folder->parent != NULL) folder_remove_subfolder (folder->parent, folder); + g_free (folder->path); + gtk_object_unref (GTK_OBJECT (folder->e_folder)); for (p = folder->subfolders; p != NULL; p = p->next) @@ -106,62 +110,6 @@ folder_destroy (Folder *folder) g_free (folder); } - -/* Watcher management. */ - -static void -watcher_destroyed_cb (GtkObject *object, - gpointer data) -{ - EStorageWatcher *watcher; - EStorage *storage; - EStoragePrivate *priv; - WatcherList *list; - - watcher = E_STORAGE_WATCHER (object); - storage = E_STORAGE (data); - priv = storage->priv; - - list = g_hash_table_lookup (priv->watcher_to_watcher_list, watcher); - g_return_if_fail (list != NULL); - - list->watchers = g_list_remove (list->watchers, watcher); -} - -static void -free_watcher_list (EStorage *storage, - WatcherList *watcher_list) -{ - GtkObject *watcher_object; - GList *p; - - for (p = watcher_list->watchers; p != NULL; p = p->next) { - watcher_object = GTK_OBJECT (p->data); - gtk_signal_disconnect_by_func (watcher_object, watcher_destroyed_cb, storage); - - gtk_object_destroy (watcher_object); /* Make sure it does not live when we are dead. */ - gtk_object_unref (watcher_object); - } - - g_free (watcher_list->path); - - g_free (watcher_list); -} - -static void -hash_foreach_free_watcher_list (gpointer key, - gpointer value, - gpointer data) -{ - WatcherList *watcher_list; - EStorage *storage; - - storage = E_STORAGE (data); - watcher_list = (WatcherList *) value; - - free_watcher_list (storage, watcher_list); -} - static void free_private (EStorage *storage) { @@ -169,10 +117,9 @@ free_private (EStorage *storage) priv = storage->priv; - g_hash_table_foreach (priv->path_to_watcher_list, hash_foreach_free_watcher_list, storage); - g_hash_table_destroy (priv->path_to_watcher_list); + g_hash_table_foreach (priv->path_to_folder, (GHFunc) folder_destroy, NULL); - g_hash_table_destroy (priv->watcher_to_watcher_list); + g_hash_table_destroy (priv->path_to_folder); g_free (priv); } @@ -204,37 +151,6 @@ list_folders (EStorage *storage, return list; } -static EStorageWatcher * -get_watcher_for_path (EStorage *storage, - const char *path) -{ - EStoragePrivate *priv; - EStorageWatcher *watcher; - WatcherList *watcher_list; - - priv = storage->priv; - - watcher = e_storage_watcher_new (storage, path); - - watcher_list = g_hash_table_lookup (priv->path_to_watcher_list, path); - if (watcher_list == NULL) { - watcher_list = g_new (WatcherList, 1); - watcher_list->path = g_strdup (path); - watcher_list->watchers = NULL; - - g_hash_table_insert (priv->path_to_watcher_list, watcher_list->path, watcher_list); - } - - g_hash_table_insert (priv->watcher_to_watcher_list, watcher, watcher_list); - - watcher_list->watchers = g_list_prepend (watcher_list->watchers, watcher); - - gtk_signal_connect (GTK_OBJECT (watcher), "destroy", - GTK_SIGNAL_FUNC (watcher_destroyed_cb), storage); - - return watcher; -} - static EFolder * get_folder (EStorage *storage, const char *path) @@ -286,9 +202,27 @@ class_init (EStorageClass *class) object_class->destroy = destroy; class->list_folders = list_folders; - class->get_watcher_for_path = get_watcher_for_path; class->get_folder = get_folder; class->get_name = get_name; + + signals[NEW_FOLDER] = + gtk_signal_new ("new_folder", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (EStorageClass, new_folder), + gtk_marshal_NONE__STRING, + GTK_TYPE_NONE, 1, + GTK_TYPE_STRING); + signals[REMOVED_FOLDER] = + gtk_signal_new ("removed_folder", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (EStorageClass, removed_folder), + gtk_marshal_NONE__STRING, + GTK_TYPE_NONE, 1, + GTK_TYPE_STRING); + + gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); } static void @@ -297,10 +231,7 @@ init (EStorage *storage) EStoragePrivate *priv; priv = g_new (EStoragePrivate, 1); - - priv->path_to_watcher_list = g_hash_table_new (g_str_hash, g_str_equal); - priv->watcher_to_watcher_list = g_hash_table_new (g_direct_hash, g_direct_equal); - priv->path_to_folder = g_hash_table_new (g_str_hash, g_str_equal); + priv->path_to_folder = g_hash_table_new (g_str_hash, g_str_equal); storage->priv = priv; } @@ -318,8 +249,8 @@ e_storage_construct (EStorage *storage) GTK_OBJECT_UNSET_FLAGS (GTK_OBJECT (storage), GTK_FLOATING); - root_folder = folder_new (NULL); - g_hash_table_insert (storage->priv->path_to_folder, G_DIR_SEPARATOR_S, root_folder); + root_folder = folder_new (NULL, G_DIR_SEPARATOR_S); + g_hash_table_insert (storage->priv->path_to_folder, root_folder->path, root_folder); } EStorage * @@ -364,17 +295,6 @@ e_storage_list_folders (EStorage *storage, return (* ES_CLASS (storage)->list_folders) (storage, path); } -EStorageWatcher * -e_storage_get_watcher_for_path (EStorage *storage, const char *path) -{ - g_return_val_if_fail (storage != NULL, NULL); - g_return_val_if_fail (E_IS_STORAGE (storage), NULL); - g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (e_storage_path_is_absolute (path), NULL); - - return (* ES_CLASS (storage)->get_watcher_for_path) (storage, path); -} - EFolder * e_storage_get_folder (EStorage *storage, const char *path) @@ -440,10 +360,15 @@ e_storage_new_folder (EStorage *storage, return FALSE; } - folder = folder_new (e_folder); + folder = folder_new (e_folder, full_path); folder_add_subfolder (parent_folder, folder); - g_hash_table_insert (priv->path_to_folder, full_path, folder); + g_hash_table_insert (priv->path_to_folder, folder->path, folder); + + g_print ("EStorage: New folder -- %s\n", folder->path); + gtk_signal_emit (GTK_OBJECT (storage), signals[NEW_FOLDER], folder->path); + + g_free (full_path); return TRUE; } @@ -468,6 +393,9 @@ e_storage_remove_folder (EStorage *storage, return FALSE; } + gtk_signal_emit (GTK_OBJECT (storage), signals[REMOVED_FOLDER], path); + + g_hash_table_remove (priv->path_to_folder, path); folder_destroy (folder); return TRUE; diff --git a/shell/e-storage.h b/shell/e-storage.h index 2639497854..478feef5a6 100644 --- a/shell/e-storage.h +++ b/shell/e-storage.h @@ -47,7 +47,6 @@ typedef struct _EStoragePrivate EStoragePrivate; typedef struct _EStorageClass EStorageClass; #include "e-folder.h" -#include "e-storage-watcher.h" struct _EStorage { GtkObject parent; @@ -58,11 +57,14 @@ struct _EStorage { struct _EStorageClass { GtkObjectClass parent_class; + /* Signals. */ + void * (* new_folder) (EStorage *storage, const char *path); + void * (* removed_folder) (EStorage *storage, const char *path); + /* Virtual methods. */ - GList * (* list_folders) (EStorage *storage, const char *path); - EStorageWatcher * (* get_watcher_for_path) (EStorage *storage, const char *path); - EFolder * (* get_folder) (EStorage *storage, const char *path); - const char * (* get_name) (EStorage *storage); + GList * (* list_folders) (EStorage *storage, const char *path); + EFolder * (* get_folder) (EStorage *storage, const char *path); + const char * (* get_name) (EStorage *storage); }; @@ -74,7 +76,6 @@ gboolean e_storage_path_is_relative (const char *path); gboolean e_storage_path_is_absolute (const char *path); GList *e_storage_list_folders (EStorage *storage, const char *path); -EStorageWatcher *e_storage_get_watcher_for_path (EStorage *storage, const char *path); EFolder *e_storage_get_folder (EStorage *storage, const char *path); const char *e_storage_get_name (EStorage *storage); diff --git a/shell/evolution-shell-component.c b/shell/evolution-shell-component.c index 9c0861e14a..71952d4300 100644 --- a/shell/evolution-shell-component.c +++ b/shell/evolution-shell-component.c @@ -224,7 +224,8 @@ corba_class_init (void) epv->create_view = impl_ShellComponent_create_view; vepv = &ShellComponent_vepv; - vepv->Bonobo_Unknown_epv = bonobo_object_get_epv (); + vepv->_base_epv = base_epv; + vepv->Bonobo_Unknown_epv = bonobo_object_get_epv (); vepv->Evolution_ShellComponent_epv = epv; } @@ -327,6 +328,15 @@ evolution_shell_component_new (const EvolutionShellComponentFolderType folder_ty return new; } +Evolution_Shell +evolution_shell_component_get_owner (EvolutionShellComponent *shell_component) +{ + g_return_val_if_fail (shell_component != NULL, CORBA_OBJECT_NIL); + g_return_val_if_fail (EVOLUTION_IS_SHELL_COMPONENT (shell_component), CORBA_OBJECT_NIL); + + return shell_component->priv->corba_owner; +} + E_MAKE_TYPE (evolution_shell_component, "EvolutionShellComponent", EvolutionShellComponent, class_init, init, PARENT_TYPE) diff --git a/shell/evolution-shell-component.h b/shell/evolution-shell-component.h index 0922124606..4b00f5df0a 100644 --- a/shell/evolution-shell-component.h +++ b/shell/evolution-shell-component.h @@ -82,7 +82,7 @@ void evolution_shell_component_construct (EvolutionShellCom EvolutionShellComponent *evolution_shell_component_new (const EvolutionShellComponentFolderType folder_types[], EvolutionShellComponentCreateViewFn create_view_fn, void *closure); -Evolution_Shell evolution_shell_component_get_shell (EvolutionShellComponent *shell_component); +Evolution_Shell evolution_shell_component_get_owner (EvolutionShellComponent *shell_component); #ifdef __cplusplus } diff --git a/shell/evolution-storage.c b/shell/evolution-storage.c new file mode 100644 index 0000000000..eab28ddfcb --- /dev/null +++ b/shell/evolution-storage.c @@ -0,0 +1,395 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* evolution-storage.c + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <bonobo.h> + +#include "Evolution.h" + +#include "e-util/e-util.h" + +#include "evolution-storage.h" + + +#define PARENT_TYPE BONOBO_OBJECT_TYPE +static BonoboObjectClass *parent_class = NULL; + +struct _EvolutionStoragePrivate { + char *name; + + Evolution_StorageRegistry corba_storage_registry; + Evolution_StorageListener corba_storage_listener; +}; + + +/* CORBA interface implementation. */ + +static POA_Evolution_Storage__vepv Storage_vepv; + +static POA_Evolution_Storage * +create_servant (void) +{ + POA_Evolution_Storage *servant; + CORBA_Environment ev; + + servant = (POA_Evolution_Storage *) g_new0 (BonoboObjectServant, 1); + servant->vepv = &Storage_vepv; + + CORBA_exception_init (&ev); + + POA_Evolution_Storage__init ((PortableServer_Servant) servant, &ev); + if (ev._major != CORBA_NO_EXCEPTION) { + g_free (servant); + CORBA_exception_free (&ev); + return NULL; + } + + CORBA_exception_free (&ev); + + return servant; +} + +static CORBA_char * +impl_Storage__get_name (PortableServer_Servant servant, + CORBA_Environment *ev) +{ + BonoboObject *bonobo_object; + EvolutionStorage *storage; + EvolutionStoragePrivate *priv; + + bonobo_object = bonobo_object_from_servant (servant); + storage = EVOLUTION_STORAGE (bonobo_object); + priv = storage->priv; + + return CORBA_string_dup (priv->name); +} + + +/* GtkObject methods. */ + +static void +destroy (GtkObject *object) +{ + EvolutionStorage *storage; + EvolutionStoragePrivate *priv; + CORBA_Environment ev; + + storage = EVOLUTION_STORAGE (object); + priv = storage->priv; + + g_free (priv->name); + + CORBA_exception_init (&ev); + + if (priv->corba_storage_registry != CORBA_OBJECT_NIL) { + Bonobo_Unknown_unref (priv->corba_storage_registry, &ev); + CORBA_Object_release (priv->corba_storage_registry, &ev); + } + + if (priv->corba_storage_listener != CORBA_OBJECT_NIL) { + /* (This is not a Bonobo object, so no unref.) */ + CORBA_Object_release (priv->corba_storage_listener, &ev); + } + + CORBA_exception_free (&ev); + + g_free (priv); +} + + +static void +corba_class_init (void) +{ + POA_Evolution_Storage__vepv *vepv; + POA_Evolution_Storage__epv *epv; + PortableServer_ServantBase__epv *base_epv; + + base_epv = g_new0 (PortableServer_ServantBase__epv, 1); + base_epv->_private = NULL; + base_epv->finalize = NULL; + base_epv->default_POA = NULL; + + epv = g_new0 (POA_Evolution_Storage__epv, 1); + epv->_get_name = impl_Storage__get_name; + + vepv = &Storage_vepv; + vepv->Bonobo_Unknown_epv = bonobo_object_get_epv (); + vepv->Evolution_Storage_epv = epv; +} + +static void +class_init (EvolutionStorageClass *klass) +{ + GtkObjectClass *object_class; + + object_class = GTK_OBJECT_CLASS (klass); + object_class->destroy = destroy; + + parent_class = gtk_type_class (bonobo_object_get_type ()); + + corba_class_init (); +} + +static void +init (EvolutionStorage *storage) +{ + EvolutionStoragePrivate *priv; + + priv = g_new (EvolutionStoragePrivate, 1); + priv->name = NULL; + priv->corba_storage_listener = NULL; + + storage->priv = priv; +} + + +void +evolution_storage_construct (EvolutionStorage *storage, + Evolution_Storage corba_object, + const char *name) +{ + EvolutionStoragePrivate *priv; + + g_return_if_fail (storage != NULL); + g_return_if_fail (EVOLUTION_IS_STORAGE (storage)); + g_return_if_fail (corba_object != CORBA_OBJECT_NIL); + g_return_if_fail (name != NULL); + g_return_if_fail (name[0] != '\0'); + + bonobo_object_construct (BONOBO_OBJECT (storage), corba_object); + + priv = storage->priv; + priv->name = g_strdup (name); +} + +EvolutionStorage * +evolution_storage_new (const char *name) +{ + EvolutionStorage *new; + POA_Evolution_Storage *servant; + Evolution_Storage corba_object; + + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (name[0] != '\0', NULL); + + servant = create_servant (); + if (servant == NULL) + return NULL; + + new = gtk_type_new (evolution_storage_get_type ()); + + corba_object = bonobo_object_activate_servant (BONOBO_OBJECT (new), servant); + evolution_storage_construct (new, corba_object, name); + + return new; +} + +EvolutionStorageResult +evolution_storage_register (EvolutionStorage *evolution_storage, + Evolution_StorageRegistry corba_storage_registry) +{ + EvolutionStorageResult result; + Evolution_StorageListener corba_storage_listener; + Evolution_Storage corba_storage; + EvolutionStoragePrivate *priv; + CORBA_Environment ev; + + 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 (corba_storage_registry != CORBA_OBJECT_NIL, + EVOLUTION_STORAGE_ERROR_INVALIDPARAMETER); + + priv = evolution_storage->priv; + + if (priv->corba_storage_listener != CORBA_OBJECT_NIL) + return EVOLUTION_STORAGE_ERROR_ALREADYREGISTERED; + + CORBA_exception_init (&ev); + + corba_storage = bonobo_object_corba_objref (BONOBO_OBJECT (evolution_storage)); + corba_storage_listener = Evolution_StorageRegistry_register_storage (corba_storage_registry, + corba_storage, + "pippo", &ev); + + if (ev._major == CORBA_NO_EXCEPTION) { + Bonobo_Unknown_ref (corba_storage_registry, &ev); + priv->corba_storage_registry = CORBA_Object_duplicate (corba_storage_registry, &ev); + + priv->corba_storage_listener = corba_storage_listener; + + result = EVOLUTION_STORAGE_OK; + } else { + if (ev._major != CORBA_USER_EXCEPTION) + result = EVOLUTION_STORAGE_ERROR_CORBA; + else if (strcmp (CORBA_exception_id (&ev), ex_Evolution_StorageRegistry_Exists) == 0) + result = EVOLUTION_STORAGE_ERROR_EXISTS; + else + result = EVOLUTION_STORAGE_ERROR_GENERIC; + } + + CORBA_exception_free (&ev); + + return result; +} + +EvolutionStorageResult +evolution_storage_register_on_shell (EvolutionStorage *evolution_storage, + Evolution_Shell corba_shell) +{ + Evolution_StorageRegistry corba_storage_registry; + EvolutionStorageResult result; + CORBA_Environment ev; + + 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 (corba_shell != CORBA_OBJECT_NIL, + EVOLUTION_STORAGE_ERROR_INVALIDPARAMETER); + + CORBA_exception_init (&ev); + + corba_storage_registry = Bonobo_Unknown_query_interface (corba_shell, + "IDL:Evolution/StorageRegistry:1.0", + &ev); + if (corba_storage_registry == CORBA_OBJECT_NIL || ev._major != CORBA_NO_EXCEPTION) { + CORBA_exception_free (&ev); + return EVOLUTION_STORAGE_ERROR_NOREGISTRY; + } + + result = evolution_storage_register (evolution_storage, corba_storage_registry); + + Bonobo_Unknown_unref (corba_storage_registry, &ev); + CORBA_Object_release (corba_storage_registry, &ev); + + CORBA_exception_free (&ev); + + return result; +} + +EvolutionStorageResult +evolution_storage_new_folder (EvolutionStorage *evolution_storage, + const char *path, + const char *type, + const char *physical_uri, + const char *description) +{ + EvolutionStorageResult result; + EvolutionStoragePrivate *priv; + Evolution_Folder corba_folder; + CORBA_Environment ev; + const char *path_basename; + char *parent_path; + + 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 (description != NULL, EVOLUTION_STORAGE_ERROR_INVALIDPARAMETER); + g_return_val_if_fail (type != NULL, EVOLUTION_STORAGE_ERROR_INVALIDPARAMETER); + g_return_val_if_fail (physical_uri != NULL, EVOLUTION_STORAGE_ERROR_INVALIDPARAMETER); + + priv = evolution_storage->priv; + + path_basename = g_basename (path); + + /* Yuck. */ + corba_folder.name = (CORBA_char *) path_basename; + corba_folder.description = (CORBA_char *) description; + corba_folder.type = (CORBA_char *) type; + corba_folder.physical_uri = (CORBA_char *) physical_uri; + + if (path_basename - path > 1) { + parent_path = g_strndup (path, path_basename - path - 1); + } else { + parent_path = g_strdup (G_DIR_SEPARATOR_S); + } + + CORBA_exception_init (&ev); + + Evolution_StorageListener_new_folder (priv->corba_storage_listener, parent_path, + &corba_folder, &ev); + + if (ev._major == CORBA_NO_EXCEPTION) + result = EVOLUTION_STORAGE_OK; + else if (ev._major != CORBA_USER_EXCEPTION) + result = EVOLUTION_STORAGE_ERROR_CORBA; + else if (strcmp (CORBA_exception_id (&ev), ex_Evolution_StorageListener_Exists) == 0) + result = EVOLUTION_STORAGE_ERROR_EXISTS; + else + result = EVOLUTION_STORAGE_ERROR_GENERIC; + + CORBA_exception_free (&ev); + + g_free (parent_path); + + return result; +} + +EvolutionStorageResult +evolution_storage_removed_folder (EvolutionStorage *evolution_storage, + const char *path) +{ + EvolutionStorageResult result; + EvolutionStoragePrivate *priv; + CORBA_Environment ev; + + 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); + + priv = evolution_storage->priv; + + if (priv->corba_storage_listener == CORBA_OBJECT_NIL) + return EVOLUTION_STORAGE_ERROR_NOTREGISTERED; + + CORBA_exception_init (&ev); + + Evolution_StorageListener_removed_folder (priv->corba_storage_listener, path, &ev); + + if (ev._major == CORBA_NO_EXCEPTION) + result = EVOLUTION_STORAGE_OK; + else if (ev._major != CORBA_USER_EXCEPTION) + result = EVOLUTION_STORAGE_ERROR_CORBA; + else if (strcmp (CORBA_exception_id (&ev), ex_Evolution_StorageListener_NotFound) == 0) + result = EVOLUTION_STORAGE_ERROR_NOTFOUND; + else + result = EVOLUTION_STORAGE_ERROR_GENERIC; + + 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 new file mode 100644 index 0000000000..40e678dd57 --- /dev/null +++ b/shell/evolution-storage.h @@ -0,0 +1,96 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* evolution-storage.h + * + * Copyright (C) 2000 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +#ifndef __EVOLUTION_STORAGE_H__ +#define __EVOLUTION_STORAGE_H__ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <bonobo/bonobo-object.h> + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define EVOLUTION_TYPE_STORAGE (evolution_storage_get_type ()) +#define EVOLUTION_STORAGE(obj) (GTK_CHECK_CAST ((obj), EVOLUTION_TYPE_STORAGE, EvolutionStorage)) +#define EVOLUTION_STORAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), EVOLUTION_TYPE_STORAGE, EvolutionStorageClass)) +#define EVOLUTION_IS_STORAGE(obj) (GTK_CHECK_TYPE ((obj), EVOLUTION_TYPE_STORAGE)) +#define EVOLUTION_IS_STORAGE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), EVOLUTION_TYPE_STORAGE)) + + +typedef struct _EvolutionStorage EvolutionStorage; +typedef struct _EvolutionStoragePrivate EvolutionStoragePrivate; +typedef struct _EvolutionStorageClass EvolutionStorageClass; + +enum _EvolutionStorageResult { + EVOLUTION_STORAGE_OK, + EVOLUTION_STORAGE_ERROR_ALREADYREGISTERED, + EVOLUTION_STORAGE_ERROR_NOTREGISTERED, + EVOLUTION_STORAGE_ERROR_NOREGISTRY, + EVOLUTION_STORAGE_ERROR_CORBA, + EVOLUTION_STORAGE_ERROR_EXISTS, + EVOLUTION_STORAGE_ERROR_INVALIDPARAMETER, + EVOLUTION_STORAGE_ERROR_NOTFOUND, + EVOLUTION_STORAGE_ERROR_GENERIC +}; +typedef enum _EvolutionStorageResult EvolutionStorageResult; + +struct _EvolutionStorage { + BonoboObject parent; + + EvolutionStoragePrivate *priv; +}; + +struct _EvolutionStorageClass { + BonoboObjectClass parent_class; +}; + + +GtkType evolution_storage_get_type (void); +void evolution_storage_construct (EvolutionStorage *storage, + Evolution_Storage corba_object, + const char *name); +EvolutionStorage *evolution_storage_new (const char *name); + +EvolutionStorageResult evolution_storage_register (EvolutionStorage *storage, + Evolution_StorageRegistry corba_registry); +EvolutionStorageResult evolution_storage_register_on_shell (EvolutionStorage *evolution_storage, + Evolution_Shell corba_shell); + +EvolutionStorageResult evolution_storage_new_folder (EvolutionStorage *evolution_storage, + const char *path, + const char *type, + const char *physical_uri, + const char *description); +EvolutionStorageResult evolution_storage_removed_folder (EvolutionStorage *evolution_storage, + const char *path); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __EVOLUTION_STORAGE_H__ */ |