Finish the DnD stuff by implementing move/copy on the shell side as

well.  Now we should just need to implement the corresponding bits in
the components...

svn path=/trunk/; revision=8949
This commit is contained in:
Ettore Perazzoli
2001-03-26 18:55:41 +00:00
parent 4cc23476d3
commit f342817e88
10 changed files with 423 additions and 26 deletions

View File

@ -1,3 +1,44 @@
2001-03-26 Ettore Perazzoli <ettore@ximian.com>
* evolution-shell-component-client.c
(evolution_shell_component_client_async_xfer_folder): Handle CORBA
exception.
(evolution_shell_component_client_async_create_folder): Likewise.
* e-local-storage.c (create_folder_directory): Create the
`subfolders' directory if it doesn't exist.
* e-storage-set-view.c (tree_drag_data_received): Build the
correct target path by appending the basename from the source
path.
* evolution-shell-component.c
(impl_ShellComponent_async_xfer_folder): Enabled again.
(class_init): Install it.
* e-local-folder.c (METADATA_FILE_NAME_LEN): Removed #define.
(METADATA_FILE_NAME): Removed #define.
(save_metadata): Use the public
`E_LOCAL_FOLDER_METADATA_FILE_NAME' value instead.
(construct_loading_metadata): Likewise.
* e-local-folder.h (E_LOCAL_FOLDER_METADATA_FILE_NAME_LEN): New
#define.
(E_LOCAL_FOLDER_METADATA_FILE_NAME): New #define.
* e-local-storage.c (remove_folder_directory): New helper
function.
(async_xfer_folder_step): New.
(async_xfer_complete): New.
(async_xfer_folder_callback): New.
(impl_async_xfer_folder): Implement.
* e-storage.h: Added value `E_STORAGE_NOTEMPTY' to
`EStorageResult'.
* evolution-shell-component-client.c
(evolution_shell_component_clinet_async_xfer_folder): New.
2001-03-23 Ettore Perazzoli <ettore@ximian.com>
* e-local-storage.c (impl_async_xfer_folder): New, implementation

View File

@ -53,9 +53,6 @@ static EFolderClass *parent_class = NULL;
#define URI_PREFIX "file://"
#define URI_PREFIX_LEN 7
#define METADATA_FILE_NAME "folder-metadata.xml"
#define METADATA_FILE_NAME_LEN 19
struct _ELocalFolderPrivate {
int dummy;
};
@ -98,7 +95,7 @@ construct_loading_metadata (ELocalFolder *local_folder,
folder = E_FOLDER (local_folder);
metadata_path = g_concat_dir_and_file (path, METADATA_FILE_NAME);
metadata_path = g_concat_dir_and_file (path, E_LOCAL_FOLDER_METADATA_FILE_NAME);
doc = xmlParseFile (metadata_path);
if (doc == NULL) {
@ -155,7 +152,7 @@ save_metadata (ELocalFolder *local_folder)
(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);
physical_path = g_concat_dir_and_file (physical_directory, E_LOCAL_FOLDER_METADATA_FILE_NAME);
if (xmlSaveFile (physical_path, doc) < 0) {
unlink (physical_path);

View File

@ -1,7 +1,7 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/* e-local-folder.h
*
* Copyright (C) 2000 Helix Code, Inc.
* Copyright (C) 2000, 2001 Ximian, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@ -39,6 +39,9 @@ extern "C" {
#define E_IS_LOCAL_FOLDER(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_LOCAL_FOLDER))
#define E_IS_LOCAL_FOLDER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_LOCAL_FOLDER))
#define E_LOCAL_FOLDER_METADATA_FILE_NAME "folder-metadata.xml"
#define E_LOCAL_FOLDER_METADATA_FILE_NAME_LEN 19
typedef struct _ELocalFolder ELocalFolder;
typedef struct _ELocalFolderClass ELocalFolderClass;

View File

@ -384,7 +384,7 @@ component_async_create_folder_callback (EvolutionShellComponentClient *shell_com
e_folder_set_physical_uri (folder, callback_data->physical_uri);
if (e_local_folder_save (E_LOCAL_FOLDER (folder))) {
new_folder (E_LOCAL_STORAGE(callback_data->storage),
new_folder (E_LOCAL_STORAGE (callback_data->storage),
callback_data->path, folder);
} else {
rmdir (callback_data->physical_path);
@ -453,6 +453,14 @@ create_folder_directory (ELocalStorage *local_storage,
subfolders_directory_physical_path = g_concat_dir_and_file (parent_physical_path,
SUBFOLDER_DIR_NAME);
if (! g_file_exists (subfolders_directory_physical_path)) {
if (mkdir (subfolders_directory_physical_path, 0700) == -1) {
g_free (subfolders_directory_physical_path);
g_free (parent_physical_path);
return errno_to_storage_result ();
}
}
physical_path = g_concat_dir_and_file (subfolders_directory_physical_path,
folder_name);
g_free (subfolders_directory_physical_path);
@ -541,6 +549,37 @@ create_folder (ELocalStorage *local_storage,
callback_data);
}
static EStorageResult
remove_folder_directory (ELocalStorage *local_storage,
const char *path)
{
char *physical_path;
char *file_name;
physical_path = get_physical_path (local_storage, path);
/* 1. Delete the subfolder directory. If this fails, it means that we
have subfolders. */
file_name = g_concat_dir_and_file (physical_path, SUBFOLDER_DIR_NAME);
if (g_file_exists (file_name) && rmdir (file_name) == -1)
return E_STORAGE_NOTEMPTY; /* FIXME? */
g_free (file_name);
/* 2. Delete the metadata file associated with this folder. */
file_name = g_concat_dir_and_file (physical_path, E_LOCAL_FOLDER_METADATA_FILE_NAME);
unlink (file_name);
g_free (file_name);
/* 3. Delete the physical directory. */
if (rmdir (physical_path) == -1) {
g_free (physical_path);
return E_STORAGE_GENERICERROR;
}
g_free (physical_path);
return E_STORAGE_OK;
}
/* GtkObject methods. */
@ -580,6 +619,9 @@ impl_get_name (EStorage *storage)
return E_LOCAL_STORAGE_NAME;
}
/* Creating folders. */
static void
impl_async_create_folder (EStorage *storage,
const char *path,
@ -595,6 +637,9 @@ impl_async_create_folder (EStorage *storage,
create_folder (local_storage, NULL, path, type, description, callback, data);
}
/* Removing folders. */
static void
impl_async_remove_folder (EStorage *storage,
const char *path,
@ -606,14 +651,252 @@ impl_async_remove_folder (EStorage *storage,
local_storage = E_LOCAL_STORAGE (storage);
}
/* Transferring folders. */
struct _XferItem {
char *source_path;
char *destination_path;
};
typedef struct _XferItem XferItem;
static XferItem *
xfer_item_new (char *source_path,
char *destination_path)
{
XferItem *new;
new = g_new (XferItem, 1);
new->source_path = source_path;
new->destination_path = destination_path;
return new;
}
static void
xfer_item_free (XferItem *item)
{
g_free (item->source_path);
g_free (item->destination_path);
g_free (item);
}
static void
append_xfer_item_list (EStorage *storage,
char *source_path,
char *destination_path,
GList **list)
{
GList *subfolders;
GList *p;
*list = g_list_prepend (*list, xfer_item_new (source_path, destination_path));
subfolders = e_storage_get_subfolder_paths (storage, source_path);
for (p = subfolders; p != NULL; p = p->next) {
char *source_subpath;
char *destination_subpath;
source_subpath = g_strdup ((const char *) p->data);
destination_subpath = g_concat_dir_and_file (destination_path,
g_basename (source_subpath));
append_xfer_item_list (storage, source_subpath, destination_subpath, list);
}
e_free_string_list (subfolders);
}
struct _XferData {
/* The storage on which we are performing the xfer operation. */
ELocalStorage *local_storage;
/* List of source/destination path couples to copy, in the right
order. */
GList *folder_items;
/* Pointer into `folder_items'. The folder item pointed by this is the
one handled by the previous CORBA invocation. */
GList *current_folder_item;
/* Whether we want to remove the source too. */
gboolean remove_source;
/* The callback, with its data. */
EStorageResultCallback callback;
void *callback_data;
};
typedef struct _XferData XferData;
static void
async_xfer_folder_step (ELocalStorage *local_storage,
const char *source_path,
const char *destination_path,
gboolean remove_source,
EvolutionShellComponentClientCallback component_client_callback,
void *component_client_callback_data)
{
ELocalStoragePrivate *priv;
EFolder *source_folder;
EvolutionShellComponentClient *component_client;
char *physical_path;
char *physical_uri;
priv = local_storage->priv;
g_print ("async_xfer_folder_step %s -> %s\n", source_path, destination_path);
source_folder = e_storage_get_folder (E_STORAGE (local_storage), source_path);
g_assert (source_folder != NULL);
create_folder_directory (local_storage, destination_path,
e_folder_get_type_string (source_folder),
e_folder_get_description (source_folder),
&physical_path);
physical_uri = g_strconcat ("file://", physical_path, NULL);
g_free (physical_path);
component_client = e_folder_type_registry_get_handler_for_type (priv->folder_type_registry,
e_folder_get_type_string (source_folder));
g_assert (component_client != NULL);
evolution_shell_component_client_async_xfer_folder (component_client,
e_folder_get_physical_uri (source_folder),
physical_uri,
remove_source,
component_client_callback,
component_client_callback_data);
g_free (physical_uri);
}
static void
async_xfer_folder_complete (XferData *xfer_data)
{
ELocalStorage *local_storage;
GList *p;
local_storage = xfer_data->local_storage;
#if 0
if (xfer_data->remove_source) {
EStorageResult result;
/* Remove all the source physical directories, and also the
corresponding folders from the folder tree. */
for (p = g_list_last (xfer_data->folder_items); p != NULL; p = p->prev) {
XferItem *item;
item = (XferItem *) p->data;
result = remove_folder_directory (local_storage, item->source_path);
/* FIXME handle failure differently? This should be n
unlikely situation. */
if (result == E_STORAGE_OK)
e_storage_removed_folder (E_STORAGE (local_storage), item->source_path);
}
}
#endif
/* Free the data. */
for (p = xfer_data->folder_items; p != NULL; p = p->next) {
XferItem *item;
item = (XferItem *) p->data;
xfer_item_free (item);
}
g_list_free (xfer_data->folder_items);
g_free (xfer_data);
}
static void
async_xfer_folder_callback (EvolutionShellComponentClient *shell_component_client,
EvolutionShellComponentResult result,
void *callback_data)
{
XferData *xfer_data;
XferItem *item;
EFolder *source_folder;
EFolder *destination_folder;
char *new_physical_uri;
/* FIXME handle errors. */
xfer_data = (XferData *) callback_data;
item = (XferItem *) xfer_data->current_folder_item->data;
source_folder = e_storage_get_folder (E_STORAGE (xfer_data->local_storage), item->source_path);
destination_folder = e_local_folder_new (e_folder_get_name (source_folder),
e_folder_get_type_string (source_folder),
e_folder_get_description (source_folder));
new_physical_uri = g_strconcat ("file:///", item->destination_path, NULL);
e_folder_set_physical_uri (destination_folder, new_physical_uri);
g_free (new_physical_uri);
e_local_folder_save (E_LOCAL_FOLDER (new_folder)); /* FIXME check for errors */
new_folder (xfer_data->local_storage, item->destination_path, destination_folder);
xfer_data->current_folder_item = xfer_data->current_folder_item->next;
if (xfer_data->current_folder_item == NULL) {
async_xfer_folder_complete (xfer_data);
return;
}
item = (XferItem *) xfer_data->current_folder_item->data;
async_xfer_folder_step (xfer_data->local_storage,
item->source_path,
item->destination_path,
xfer_data->remove_source,
async_xfer_folder_callback,
xfer_data);
}
static void
impl_async_xfer_folder (EStorage *storage,
const char *source_path,
const char *destination_path,
const gboolean remove_source,
gboolean remove_source,
EStorageResultCallback callback,
void *data)
void *callback_data)
{
ELocalStorage *local_storage;
ELocalStoragePrivate *priv;
XferData *xfer_data;
GList *folder_items; /* <XferItem> */
XferItem *first_item;
local_storage = E_LOCAL_STORAGE (storage);
priv = local_storage->priv;
folder_items = NULL;
append_xfer_item_list (storage, g_strdup (source_path), g_strdup (destination_path), &folder_items);
folder_items = g_list_reverse (folder_items); /* lame */
xfer_data = g_new (XferData, 1);
xfer_data->local_storage = local_storage;
xfer_data->folder_items = folder_items;
xfer_data->current_folder_item = folder_items;
xfer_data->remove_source = remove_source;
xfer_data->callback = callback;
xfer_data->callback_data = callback_data;
first_item = (XferItem *) xfer_data->folder_items->data;
async_xfer_folder_step (E_LOCAL_STORAGE (storage),
first_item->source_path,
first_item->destination_path,
remove_source,
async_xfer_folder_callback,
xfer_data);
}

View File

@ -1170,17 +1170,22 @@ tree_drag_data_received (ETree *etree,
if (strcmp (target_type, EVOLUTION_PATH_TARGET_TYPE) == 0) {
const char *source_path;
const char *destination_path;
const char *destination_folder_path;
char *destination_path;
source_path = (const char *) selection_data->data;
/* (Basic sanity checks.) */
if (source_path == NULL || source_path[0] != G_DIR_SEPARATOR || source_path[1] == '\0')
return;
destination_path = e_tree_memory_node_get_data (E_TREE_MEMORY (priv->etree_model), path);
if (destination_path == NULL)
destination_folder_path = e_tree_memory_node_get_data (E_TREE_MEMORY (priv->etree_model), path);
if (destination_folder_path == NULL)
return;
destination_path = g_concat_dir_and_file (destination_folder_path,
g_basename (source_path));
switch (context->action) {
case GDK_ACTION_MOVE:
g_print ("EStorageSetView: Moving from `%s' to `%s'\n", source_path, destination_path);
@ -1195,6 +1200,8 @@ tree_drag_data_received (ETree *etree,
default:
g_warning ("EStorageSetView: Don't know action %d\n", context->action);
}
g_free (destination_path);
}
target_path = e_tree_memory_node_get_data (E_TREE_MEMORY(priv->etree_model), path);

View File

@ -51,6 +51,7 @@ enum _EStorageResult {
E_STORAGE_INVALIDTYPE,
E_STORAGE_IOERROR,
E_STORAGE_NOSPACE,
E_STORAGE_NOTEMPTY,
E_STORAGE_NOTFOUND,
E_STORAGE_NOTIMPLEMENTED,
E_STORAGE_PERMISSIONDENIED,

View File

@ -574,6 +574,14 @@ evolution_shell_component_client_async_create_folder (EvolutionShellComponentCli
physical_uri, type,
&ev);
if (ev._major != CORBA_NO_EXCEPTION && priv->callback != NULL) {
(* callback) (shell_component_client,
shell_component_result_from_corba_exception (ev),
data);
priv->callback = NULL;
priv->callback_data = NULL;
}
CORBA_exception_free (&ev);
}
@ -586,6 +594,58 @@ evolution_shell_component_client_async_remove_folder (EvolutionShellComponentCli
/* FIXME to do. */
}
void
evolution_shell_component_client_async_xfer_folder (EvolutionShellComponentClient *shell_component_client,
const char *source_physical_uri,
const char *destination_physical_uri,
gboolean remove_source,
EvolutionShellComponentClientCallback callback,
void *data)
{
EvolutionShellComponentClientPrivate *priv;
GNOME_Evolution_ShellComponent corba_shell_component;
CORBA_Environment ev;
g_return_if_fail (shell_component_client != NULL);
g_return_if_fail (EVOLUTION_IS_SHELL_COMPONENT_CLIENT (shell_component_client));
g_return_if_fail (source_physical_uri != NULL);
g_return_if_fail (destination_physical_uri != NULL);
g_return_if_fail (data != NULL);
priv = shell_component_client->priv;
if (priv->callback != NULL) {
(* callback) (shell_component_client, EVOLUTION_SHELL_COMPONENT_BUSY, data);
return;
}
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;
GNOME_Evolution_ShellComponent_xferFolderAsync (corba_shell_component,
priv->listener_interface,
source_physical_uri,
destination_physical_uri,
remove_source,
&ev);
if (ev._major != CORBA_NO_EXCEPTION && priv->callback != NULL) {
(* callback) (shell_component_client,
shell_component_result_from_corba_exception (ev),
data);
priv->callback = NULL;
priv->callback_data = NULL;
}
CORBA_exception_free (&ev);
}
void
evolution_shell_component_client_populate_folder_context_menu (EvolutionShellComponentClient *shell_component_client,
BonoboUIComponent *uih,

View File

@ -95,6 +95,12 @@ void evolution_shell_component_client_async_remove_folder (EvolutionShellCompo
const char *physical_uri,
EvolutionShellComponentClientCallback callback,
void *data);
void evolution_shell_component_client_async_xfer_folder (EvolutionShellComponentClient *shell_component_client,
const char *source_physical_uri,
const char *destination_physical_uri,
gboolean remove_source,
EvolutionShellComponentClientCallback callback,
void *data);
void evolution_shell_component_client_populate_folder_context_menu (EvolutionShellComponentClient *shell_component_client,
BonoboUIComponent *uih,

View File

@ -44,7 +44,7 @@ struct _EvolutionShellComponentPrivate {
EvolutionShellComponentCreateViewFn create_view_fn;
EvolutionShellComponentCreateFolderFn create_folder_fn;
EvolutionShellComponentRemoveFolderFn remove_folder_fn;
EvolutionShellComponentCopyFolderFn copy_folder_fn;
EvolutionShellComponentXferFolderFn xfer_folder_fn;
EvolutionShellComponentPopulateFolderContextMenuFn populate_folder_context_menu_fn;
EvolutionShellComponentGetDndSelectionFn get_dnd_selection_fn;
@ -306,9 +306,8 @@ impl_ShellComponent_async_remove_folder (PortableServer_Servant servant,
(* priv->remove_folder_fn) (shell_component, physical_uri, listener, priv->closure);
}
#if 0
static void
impl_ShellComponent_async_copy_folder (PortableServer_Servant servant,
impl_ShellComponent_async_xfer_folder (PortableServer_Servant servant,
const GNOME_Evolution_ShellComponentListener listener,
const CORBA_char *source_physical_uri,
const CORBA_char *destination_physical_uri,
@ -323,21 +322,20 @@ impl_ShellComponent_async_copy_folder (PortableServer_Servant servant,
shell_component = EVOLUTION_SHELL_COMPONENT (bonobo_object);
priv = shell_component->priv;
if (priv->copy_folder_fn == NULL) {
if (priv->xfer_folder_fn == NULL) {
GNOME_Evolution_ShellComponentListener_notifyResult (listener,
GNOME_Evolution_ShellComponentListener_UNSUPPORTED_OPERATION,
ev);
return;
}
(* priv->copy_folder_fn) (shell_component,
(* priv->xfer_folder_fn) (shell_component,
source_physical_uri,
destination_physical_uri,
remove_source,
listener,
priv->closure);
}
#endif
static void
impl_ShellComponent_populate_folder_context_menu (PortableServer_Servant servant,
@ -447,6 +445,7 @@ class_init (EvolutionShellComponentClass *klass)
epv->createView = impl_ShellComponent_create_view;
epv->createFolderAsync = impl_ShellComponent_async_create_folder;
epv->removeFolderAsync = impl_ShellComponent_async_remove_folder;
epv->xferFolderAsync = impl_ShellComponent_async_xfer_folder;
epv->populateFolderContextMenu = impl_ShellComponent_populate_folder_context_menu;
}
@ -461,7 +460,7 @@ init (EvolutionShellComponent *shell_component)
priv->create_view_fn = NULL;
priv->create_folder_fn = NULL;
priv->remove_folder_fn = NULL;
priv->copy_folder_fn = NULL;
priv->xfer_folder_fn = NULL;
priv->populate_folder_context_menu_fn = NULL;
priv->owner_client = NULL;
@ -477,7 +476,7 @@ evolution_shell_component_construct (EvolutionShellComponent *shell_component,
EvolutionShellComponentCreateViewFn create_view_fn,
EvolutionShellComponentCreateFolderFn create_folder_fn,
EvolutionShellComponentRemoveFolderFn remove_folder_fn,
EvolutionShellComponentCopyFolderFn copy_folder_fn,
EvolutionShellComponentXferFolderFn xfer_folder_fn,
EvolutionShellComponentPopulateFolderContextMenuFn populate_folder_context_menu_fn,
EvolutionShellComponentGetDndSelectionFn get_dnd_selection_fn,
void *closure)
@ -492,7 +491,7 @@ evolution_shell_component_construct (EvolutionShellComponent *shell_component,
priv->create_view_fn = create_view_fn;
priv->create_folder_fn = create_folder_fn;
priv->remove_folder_fn = remove_folder_fn;
priv->copy_folder_fn = copy_folder_fn;
priv->xfer_folder_fn = xfer_folder_fn;
priv->populate_folder_context_menu_fn = populate_folder_context_menu_fn;
priv->get_dnd_selection_fn = get_dnd_selection_fn;
@ -524,7 +523,7 @@ evolution_shell_component_new (const EvolutionShellComponentFolderType folder_ty
EvolutionShellComponentCreateViewFn create_view_fn,
EvolutionShellComponentCreateFolderFn create_folder_fn,
EvolutionShellComponentRemoveFolderFn remove_folder_fn,
EvolutionShellComponentCopyFolderFn copy_folder_fn,
EvolutionShellComponentXferFolderFn xfer_folder_fn,
EvolutionShellComponentPopulateFolderContextMenuFn populate_folder_context_menu_fn,
EvolutionShellComponentGetDndSelectionFn get_dnd_selection_fn,
void *closure)
@ -538,7 +537,7 @@ evolution_shell_component_new (const EvolutionShellComponentFolderType folder_ty
create_view_fn,
create_folder_fn,
remove_folder_fn,
copy_folder_fn,
xfer_folder_fn,
populate_folder_context_menu_fn,
get_dnd_selection_fn,
closure);

View File

@ -83,7 +83,7 @@ typedef void (* EvolutionShellComponentRemoveFolderFn) (EvolutionShellComponent
const char *physical_uri,
const GNOME_Evolution_ShellComponentListener listener,
void *closure);
typedef void (* EvolutionShellComponentCopyFolderFn) (EvolutionShellComponent *shell_component,
typedef void (* EvolutionShellComponentXferFolderFn) (EvolutionShellComponent *shell_component,
const char *source_physical_uri,
const char *destination_physical_uri,
gboolean remove_source,
@ -138,7 +138,7 @@ void evolution_shell_component_construct (EvolutionShellCom
EvolutionShellComponentCreateViewFn create_view_fn,
EvolutionShellComponentCreateFolderFn create_folder_fn,
EvolutionShellComponentRemoveFolderFn remove_folder_fn,
EvolutionShellComponentCopyFolderFn copy_folder_fn,
EvolutionShellComponentXferFolderFn xfer_folder_fn,
EvolutionShellComponentPopulateFolderContextMenuFn populate_folder_context_menu_fn,
EvolutionShellComponentGetDndSelectionFn get_dnd_selection_fn,
void *closure);
@ -146,7 +146,7 @@ EvolutionShellComponent *evolution_shell_component_new (const EvolutionSh
EvolutionShellComponentCreateViewFn create_view_fn,
EvolutionShellComponentCreateFolderFn create_folder_fn,
EvolutionShellComponentRemoveFolderFn remove_folder_fn,
EvolutionShellComponentCopyFolderFn copy_folder_fn,
EvolutionShellComponentXferFolderFn xfer_folder_fn,
EvolutionShellComponentPopulateFolderContextMenuFn populate_folder_context_menu_fn,
EvolutionShellComponentGetDndSelectionFn get_dnd_selection_fn,
void *closure);