diff options
-rw-r--r-- | shell/ChangeLog | 29 | ||||
-rw-r--r-- | shell/e-storage-set-view.c | 197 | ||||
-rw-r--r-- | shell/e-storage-set.c | 47 | ||||
-rw-r--r-- | shell/e-storage-set.h | 14 |
4 files changed, 228 insertions, 59 deletions
diff --git a/shell/ChangeLog b/shell/ChangeLog index 84952a0674..aa64a3df09 100644 --- a/shell/ChangeLog +++ b/shell/ChangeLog @@ -1,3 +1,32 @@ +2001-03-22 Ettore Perazzoli <ettore@ximian.com> + + * e-storage-set-view.c: Removed `source_drag_types', + `num_source_drag_types', `destination_drag_types', + `num_destination_drag_types', `target_list'. + (E_SHORTCUT_TARGET_TYPE): Renamed from "E_SHORTCUT_TYPE". + (EVOLUTION_PATH_TARGET_TYPE): Define to "_EVOLUTION_PRIVATE_PATH". + (find_matching_target_for_drag_context): If any of the targets + matches it, return it. + (handle_evolution_path_drag_motion): New. + (tree_drag_motion): Use it if we are matching an + `EVOLUTION_PATH_TARGET_TYPE' target. + (e_storage_set_view_construct): Call `e_tree_drag_dest_set()' on + the view so that we become a possible DnD target. + (get_folder_at_node): Don't die if you don't find a folder there. + (create_target_entries_from_dnd_type_list): Make the first entry + an `EVOLUTION_PATH_TARGET_TYPE', the second one an + `E_SHORTCUT_TYPE', and the following ones the ones defined by the + folder. + (set_evolution_path_selection): New function to set the private + Evolution path selection. + (set_e_shortcut_selection): Assert @selection_data to be not NULL. + (class_init): Don't set up the `target_list' anymore. + (storage_sort_callback): Actually compare the two nodes, not the + first node with itself. + + * e-storage-set.c (e_storage_set_async_copy_folder): New. + (e_storage_set_async_move_folder): New. + 2001-03-22 Christopher James Lahey <clahey@ximian.com> * e-storage-set-view.c (etree_get_save_id): Changed get_save_id to diff --git a/shell/e-storage-set-view.c b/shell/e-storage-set-view.c index ea66eb7e99..ba5172a73a 100644 --- a/shell/e-storage-set-view.c +++ b/shell/e-storage-set-view.c @@ -60,6 +60,18 @@ static char *list [] = { </ETableSpecification>" +/* This is used on the source side to define the two basic types that we always + export. */ +enum _DndTargetTypeIdx { + EVOLUTION_PATH_TARGET_TYPE_IDX = 0, + E_SHORTCUT_TARGET_TYPE_IDX = 1 +}; +typedef enum _DndTargetTypeIdx DndTargetTypeIdx; + +#define EVOLUTION_PATH_TARGET_TYPE "_EVOLUTION_PRIVATE_PATH" +#define E_SHORTCUT_TARGET_TYPE "E-SHORTCUT" + + #define PARENT_TYPE E_TREE_TYPE static ETreeClass *parent_class = NULL; @@ -133,15 +145,25 @@ static const int num_destination_drag_types = sizeof (destination_drag_types) / static GtkTargetList *target_list; +/* Sorting callbacks. */ + static int -storage_sort_callback (ETreeMemory *etmm, ETreePath node1, ETreePath node2, gpointer closure) +storage_sort_callback (ETreeMemory *etmm, + ETreePath node1, + ETreePath node2, + void *closure) { - char *folder_path1 = e_tree_memory_node_get_data(etmm, node1); - char *folder_path2 = e_tree_memory_node_get_data(etmm, node1); + char *folder_path1; + char *folder_path2; gboolean path1_local; gboolean path2_local; - path1_local = !strcmp(folder_path1, G_DIR_SEPARATOR_S E_LOCAL_STORAGE_NAME); - path2_local = !strcmp(folder_path2, G_DIR_SEPARATOR_S E_LOCAL_STORAGE_NAME); + + folder_path1 = e_tree_memory_node_get_data(etmm, node1); + folder_path2 = e_tree_memory_node_get_data(etmm, node2); + + path1_local = ! strcmp (folder_path1, G_DIR_SEPARATOR_S E_LOCAL_STORAGE_NAME); + path2_local = ! strcmp (folder_path2, G_DIR_SEPARATOR_S E_LOCAL_STORAGE_NAME); + if (path1_local && path2_local) return 0; if (path1_local) @@ -149,17 +171,20 @@ storage_sort_callback (ETreeMemory *etmm, ETreePath node1, ETreePath node2, gpoi if (path2_local) return 1; - return strcmp(e_tree_model_value_at(E_TREE_MODEL(etmm), node1, 0), e_tree_model_value_at(E_TREE_MODEL(etmm), node2, 0)); + return strcmp (e_tree_model_value_at (E_TREE_MODEL (etmm), node1, 0), + e_tree_model_value_at (E_TREE_MODEL (etmm), node2, 0)); } static int folder_sort_callback (ETreeMemory *etmm, ETreePath path1, ETreePath path2, gpointer closure) { - return strcmp(e_tree_model_value_at(E_TREE_MODEL(etmm), path1, 0), e_tree_model_value_at(E_TREE_MODEL(etmm), path2, 0)); + return strcmp (e_tree_model_value_at (E_TREE_MODEL (etmm), path1, 0), + e_tree_model_value_at (E_TREE_MODEL (etmm), path2, 0)); } -/* Helper functions. */ + +/* Helper functions. */ static gboolean add_node_to_hash (EStorageSetView *storage_set_view, @@ -281,7 +306,6 @@ get_folder_at_node (EStorageSetView *storage_set_view, { EStorageSetViewPrivate *priv; const char *folder_path; - EFolder *folder; priv = storage_set_view->priv; @@ -291,10 +315,7 @@ get_folder_at_node (EStorageSetView *storage_set_view, folder_path = e_tree_memory_node_get_data (E_TREE_MEMORY(priv->etree_model), path); g_assert (folder_path != NULL); - folder = e_storage_set_get_folder (priv->storage_set, folder_path); - g_assert (folder != NULL); - - return folder; + return e_storage_set_get_folder (priv->storage_set, folder_path); } static EvolutionShellComponentClient * @@ -359,6 +380,9 @@ convert_corba_drag_action_to_gdk (GNOME_Evolution_ShellComponentDnd_ActionSet ac return retval; } +/* This will look for the targets in @drag_context, choose one that matches + with the allowed types at @path, and return its name. The EVOLUTION_PATH + type always matches. */ static const char * find_matching_target_for_drag_context (EStorageSetView *storage_set_view, ETreePath path, @@ -389,6 +413,10 @@ find_matching_target_for_drag_context (EStorageSetView *storage_set_view, char *possible_type; possible_type = gdk_atom_name ((GdkAtom) p->data); + if (strcmp (possible_type, EVOLUTION_PATH_TARGET_TYPE) == 0) { + g_free (possible_type); + return EVOLUTION_PATH_TARGET_TYPE; + } for (q = accepted_types; q != NULL; q = q->next) { const char *accepted_type; @@ -451,18 +479,27 @@ create_target_entries_from_dnd_type_list (GList *dnd_types, else num_entries = g_list_length (dnd_types); - /* We always add an entry for an Evolution URI type. This will let us - do drag & drop within Evolution at least. */ - num_entries ++; + /* We always add two entries, one for an Evolution URI type, and one + for e-shortcuts. This will let us do drag & drop within Evolution + at least. */ + num_entries += 2; entries = g_new (GtkTargetEntry, num_entries); i = 0; /* The Evolution URI will always come first. */ - entries[i].target = E_SHORTCUT_TYPE; + entries[i].target = EVOLUTION_PATH_TARGET_TYPE; entries[i].flags = 0; - entries[i].info = 0; + entries[i].info = i; + g_assert (i == EVOLUTION_PATH_TARGET_TYPE_IDX); + i ++; + + /* ...Then the shortcut type. */ + entries[i].target = E_SHORTCUT_TARGET_TYPE; + entries[i].flags = 0; + entries[i].info = i; + g_assert (i == E_SHORTCUT_TARGET_TYPE_IDX); i ++; for (p = dnd_types; p != NULL; p = p->next, i++) { @@ -524,24 +561,6 @@ create_target_list_for_node (EStorageSetView *storage_set_view, return target_list; } -#if 0 -static void -set_uri_list_selection (EStorageSetView *storage_set_view, - GtkSelectionData *selection_data) -{ - EStorageSetViewPrivate *priv; - char *uri_list; - - priv = storage_set_view->priv; - - /* FIXME: Get `evolution:' from somewhere instead of hardcoding it here. */ - uri_list = g_strconcat ("evolution:", priv->selected_row_path, "\n", NULL); - gtk_selection_data_set (selection_data, selection_data->target, - 8, (guchar *) uri_list, strlen (uri_list)); - g_free (uri_list); -} -#endif - static void set_e_shortcut_selection (EStorageSetView *storage_set_view, GtkSelectionData *selection_data) @@ -553,6 +572,7 @@ set_e_shortcut_selection (EStorageSetView *storage_set_view, const char *name; g_assert (storage_set_view != NULL); + g_assert (selection_data != NULL); priv = storage_set_view->priv; @@ -588,6 +608,22 @@ set_e_shortcut_selection (EStorageSetView *storage_set_view, g_free (shortcut); } +static void +set_evolution_path_selection (EStorageSetView *storage_set_view, + GtkSelectionData *selection_data) +{ + EStorageSetViewPrivate *priv; + const char *evolution_path; + + g_assert (storage_set_view != NULL); + g_assert (selection_data != NULL); + + priv = storage_set_view->priv; + + gtk_selection_data_set (selection_data, selection_data->target, + 8, (guchar *) priv->selected_row_path, strlen (priv->selected_row_path) + 1); +} + /* Folder context menu. */ /* FIXME: This should be moved somewhere else, so that also the shortcut code @@ -944,9 +980,13 @@ tree_drag_data_get (ETree *etree, storage_set_view = E_STORAGE_SET_VIEW (etree); priv = storage_set_view->priv; - if (info == 0) { + switch (info) { + case E_SHORTCUT_TARGET_TYPE_IDX: set_e_shortcut_selection (storage_set_view, selection_data); return; + case EVOLUTION_PATH_TARGET_TYPE_IDX: + set_evolution_path_selection (storage_set_view, selection_data); + return; } g_assert (info > 0); @@ -1008,6 +1048,27 @@ tree_drag_data_delete (ETree *tree, /* -- Destination-side DnD. */ static gboolean +handle_evolution_path_drag_motion (EStorageSetView *storage_set_view, + ETreePath path, + GdkDragContext *context, + unsigned int time) +{ + GdkModifierType modifiers; + GdkDragAction action; + + gdk_window_get_pointer (NULL, NULL, NULL, &modifiers); + + if ((modifiers & GDK_CONTROL_MASK) != 0) + action = GDK_ACTION_COPY; + else + action = GDK_ACTION_MOVE; + + gdk_drag_status (context, action, time); + + return TRUE; +} + +static gboolean tree_drag_motion (ETree *tree, int row, ETreePath path, @@ -1034,14 +1095,19 @@ tree_drag_motion (ETree *tree, if (component_client == NULL) return FALSE; - destination_folder_interface = evolution_shell_component_client_get_dnd_source_interface (component_client); - if (destination_folder_interface == NULL) - return FALSE; - dnd_type = find_matching_target_for_drag_context (storage_set_view, path, context); if (dnd_type == NULL) return FALSE; + g_print ("drag_motion %s\n", dnd_type); + + if (strcmp (dnd_type, EVOLUTION_PATH_TARGET_TYPE) == 0) + return handle_evolution_path_drag_motion (storage_set_view, path, context, time); + + destination_folder_interface = evolution_shell_component_client_get_dnd_source_interface (component_client); + if (destination_folder_interface == NULL) + return FALSE; + CORBA_exception_init (&ev); corba_context.dndType = (char *) dnd_type; /* (Safe cast, as we don't actually free the corba_context.) */ @@ -1099,11 +1165,43 @@ tree_drag_data_received (ETree *etree, EStorageSetView *storage_set_view; EStorageSetViewPrivate *priv; const char *target_path; + char *target_type; storage_set_view = E_STORAGE_SET_VIEW (etree); priv = storage_set_view->priv; + target_type = gdk_atom_name (selection_data->target); + + if (strcmp (target_type, EVOLUTION_PATH_TARGET_TYPE) == 0) { + const char *source_path; + const 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) + return; + + switch (context->action) { + case GDK_ACTION_MOVE: + g_print ("EStorageSetView: Moving from `%s' to `%s'\n", source_path, destination_path); + e_storage_set_async_move_folder (priv->storage_set, source_path, destination_path, NULL, NULL); + break; + case GDK_ACTION_COPY: + g_print ("EStorageSetView: Copying from `%s' to `%s'\n", source_path, destination_path); + e_storage_set_async_copy_folder (priv->storage_set, source_path, destination_path, NULL, NULL); + break; + default: + g_warning ("EStorageSetView: Don't know action %d\n", context->action); + } + } + target_path = e_tree_memory_node_get_data (E_TREE_MEMORY(priv->etree_model), path); + + g_free (target_type); } static gboolean @@ -1484,11 +1582,6 @@ class_init (EStorageSetViewClass *klass) GTK_TYPE_STRING); gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); - - /* Set up DND. */ - - target_list = gtk_target_list_new (source_drag_types, num_source_drag_types); - g_assert (target_list != NULL); } static void @@ -1702,19 +1795,11 @@ e_storage_set_view_construct (EStorageSetView *storage_set_view, gtk_object_unref (GTK_OBJECT (extras)); -#if 0 - e_tree_drag_source_set (E_TREE (storage_set_view), GDK_BUTTON1_MASK, - source_drag_types, num_source_drag_types, - GDK_ACTION_MOVE | GDK_ACTION_COPY); - - e_tree_drag_dest_set (E_TREE (storage_set_view), GTK_DEST_DEFAULT_ALL, - source_drag_types, num_source_drag_types, - GDK_ACTION_MOVE | GDK_ACTION_COPY); -#endif - gtk_object_ref (GTK_OBJECT (storage_set)); priv->storage_set = storage_set; + e_tree_drag_dest_set (E_TREE (storage_set_view), 0, NULL, 0, GDK_ACTION_MOVE | GDK_ACTION_COPY); + gtk_signal_connect_while_alive (GTK_OBJECT (storage_set), "new_storage", GTK_SIGNAL_FUNC (new_storage_cb), storage_set_view, GTK_OBJECT (storage_set_view)); diff --git a/shell/e-storage-set.c b/shell/e-storage-set.c index 9921fe192c..333ec39c99 100644 --- a/shell/e-storage-set.c +++ b/shell/e-storage-set.c @@ -602,4 +602,51 @@ e_storage_set_get_path_for_physical_uri (EStorageSet *storage_set, } +/** + * e_storage_set_async_copy_folder: + * @storage_set: + * @source_path: + * @destination_path: + * @callback: + * @data: + * + * Copy a folder from @source_path to @destination_path. + **/ +void +e_storage_set_async_copy_folder (EStorageSet *storage_set, + const char *source_path, + const char *destination_path, + EStorageResultCallback callback, + void *data) +{ + g_return_if_fail (storage_set != NULL); + g_return_if_fail (E_IS_STORAGE_SET (storage_set)); + g_return_if_fail (source_path != NULL); + g_return_if_fail (destination_path != NULL); +} + +/** + * e_storage_set_async_move_folder: + * @storage_set: + * @source_path: + * @destination_path: + * @callback: + * @data: + * + * Move a folder from @source_path to @destination_path. + **/ +void +e_storage_set_async_move_folder (EStorageSet *storage_set, + const char *source_path, + const char *destination_path, + EStorageResultCallback callback, + void *data) +{ + g_return_if_fail (storage_set != NULL); + g_return_if_fail (E_IS_STORAGE_SET (storage_set)); + g_return_if_fail (source_path != NULL); + g_return_if_fail (destination_path != NULL); +} + + E_MAKE_TYPE (e_storage_set, "EStorageSet", EStorageSet, class_init, init, PARENT_TYPE) diff --git a/shell/e-storage-set.h b/shell/e-storage-set.h index b39725ea1c..66e2ce8ab0 100644 --- a/shell/e-storage-set.h +++ b/shell/e-storage-set.h @@ -69,19 +69,16 @@ 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_async_create_folder (EStorageSet *storage_set, @@ -95,6 +92,17 @@ void e_storage_set_async_remove_folder (EStorageSet *storage EStorageResultCallback callback, void *data); +void e_storage_set_async_copy_folder (EStorageSet *storage_set, + const char *source_path, + const char *destination_path, + EStorageResultCallback callback, + void *data); +void e_storage_set_async_move_folder (EStorageSet *storage_set, + const char *source_path, + const char *destination_path, + EStorageResultCallback callback, + void *data); + EFolderTypeRegistry *e_storage_set_get_folder_type_registry (EStorageSet *storage_set); /* Utility functions. */ |