diff options
author | Not Zed <NotZed@Ximian.com> | 2004-02-09 21:11:51 +0800 |
---|---|---|
committer | Michael Zucci <zucchi@src.gnome.org> | 2004-02-09 21:11:51 +0800 |
commit | 67aa7010610fced90d25618f94e6caf7df5749cb (patch) | |
tree | f98d92cfa162d4e197cb975d2175493bafc162de /mail/em-folder-tree-model.c | |
parent | 4287c8e129507c5b4120f0038f2f130130a81633 (diff) | |
download | gsoc2013-evolution-67aa7010610fced90d25618f94e6caf7df5749cb.tar.gz gsoc2013-evolution-67aa7010610fced90d25618f94e6caf7df5749cb.tar.zst gsoc2013-evolution-67aa7010610fced90d25618f94e6caf7df5749cb.zip |
merged in code from em_folder_tree_model_drag_data_delete.
2004-02-09 Not Zed <NotZed@Ximian.com>
* em-folder-tree.c (tree_drag_data_delete): merged in code from
em_folder_tree_model_drag_data_delete.
(tree_drag_data_get): similar.
(tree_drag_data_received): similar.
(drag_text_uri_list): removed, use em_utils_selection_set_urilist
in tree_drag_data_get instead.
(em_folder_tree_enable_drag_and_drop): merged in
em_folder_tree_model_set_drag_drop_types.
(tree_drag_motion): merge in drop_possible, handle qualifiers, and
return the right type.
(em_folder_tree_model_row_drop_target): rename to
emft_drop_target, and make private. Beefed up substantially,
handles illogical drops, dropping on to special folders and
properly handling vfolder uri's (at least within the same tree
instance).
* em-folder-tree-model.c: Moved all of the DND stuff to
em-folder-tree, where it belongs, made it all static. Should
allow for some sharing of code too.
svn path=/trunk/; revision=24679
Diffstat (limited to 'mail/em-folder-tree-model.c')
-rw-r--r-- | mail/em-folder-tree-model.c | 596 |
1 files changed, 0 insertions, 596 deletions
diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c index c9490628e1..3c1399ba74 100644 --- a/mail/em-folder-tree-model.c +++ b/mail/em-folder-tree-model.c @@ -59,38 +59,6 @@ static GType col_types[] = { G_TYPE_BOOLEAN, /* has not-yet-loaded subfolders */ }; - -/* Drag & Drop types */ -enum DndDragType { - DND_DRAG_TYPE_FOLDER, /* drag an evo folder */ - DND_DRAG_TYPE_TEXT_URI_LIST, /* drag to an mbox file */ - NUM_DRAG_TYPES -}; - -enum DndDropType { - DND_DROP_TYPE_UID_LIST, /* drop a list of message uids */ - DND_DROP_TYPE_FOLDER, /* drop an evo folder */ - DND_DROP_TYPE_MESSAGE_RFC822, /* drop a message/rfc822 stream */ - DND_DROP_TYPE_TEXT_URI_LIST, /* drop an mbox file */ - NUM_DROP_TYPES -}; - -static GtkTargetEntry drag_types[] = { - { "x-folder", 0, DND_DRAG_TYPE_FOLDER }, - { "text/uri-list", 0, DND_DRAG_TYPE_TEXT_URI_LIST }, -}; - -static GtkTargetEntry drop_types[] = { - { "x-uid-list" , 0, DND_DROP_TYPE_UID_LIST }, - { "x-folder", 0, DND_DROP_TYPE_FOLDER }, - { "message/rfc822", 0, DND_DROP_TYPE_MESSAGE_RFC822 }, - { "text/uri-list", 0, DND_DROP_TYPE_TEXT_URI_LIST }, -}; - -static GdkAtom drag_atoms[NUM_DRAG_TYPES]; -static GdkAtom drop_atoms[NUM_DROP_TYPES]; - - /* GObject virtual method overrides */ static void em_folder_tree_model_class_init (EMFolderTreeModelClass *klass); static void em_folder_tree_model_init (EMFolderTreeModel *model); @@ -109,11 +77,8 @@ enum { }; static guint signals[LAST_SIGNAL] = { 0, }; - - static GtkTreeStoreClass *parent_class = NULL; - GType em_folder_tree_model_get_type (void) { @@ -175,12 +140,6 @@ em_folder_tree_model_class_init (EMFolderTreeModelClass *klass) G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); - - for (i = 0; i < NUM_DRAG_TYPES; i++) - drag_atoms[i] = gdk_atom_intern (drag_types[i].target, FALSE); - - for (i = 0; i < NUM_DROP_TYPES; i++) - drop_atoms[i] = gdk_atom_intern (drop_types[i].target, FALSE); } static int @@ -1000,558 +959,3 @@ em_folder_tree_model_set_unread_count (EMFolderTreeModel *model, CamelStore *sto gtk_tree_store_set ((GtkTreeStore *) model, &iter, COL_UINT_UNREAD, unread, -1); } - -struct _DragDataReceivedAsync { - struct _mail_msg msg; - - /* input data */ - GdkDragContext *context; - - union { - CamelStreamMem *rfc822; - char *folder; - char **urilist; - struct { - char *uri; - GPtrArray *uids; - } uidlist; - } selection; - - CamelStore *store; - char *full_name; - gboolean move; - guint info; - - /* output data */ - gboolean moved; -}; - -/* Drag & Drop methods */ -static void -drop_uid_list(struct _DragDataReceivedAsync *m, CamelFolder *dest) -{ - CamelFolder *src; - - d(printf(" * drop uid list from '%s'\n", m->selection.uidlist.uri)); - - if (!(src = mail_tool_uri_to_folder(m->selection.uidlist.uri, 0, &m->msg.ex))) - return; - - camel_folder_transfer_messages_to(src, m->selection.uidlist.uids, dest, NULL, m->move, &m->msg.ex); - camel_object_unref(src); - - m->moved = m->move && !camel_exception_is_set(&m->msg.ex); -} - -static void -drop_folder(struct _DragDataReceivedAsync *m) -{ - CamelFolder *src; - char *new_name; - - d(printf(" * Drop folder '%s' onto '%s'\n", m->selection.folder, m->full_name)); - - if (!(src = mail_tool_uri_to_folder(m->selection.folder, 0, &m->msg.ex))) - return; - - /* handles dropping to the root properly */ - if (m->full_name[0]) - new_name = g_strdup_printf("%s/%s", m->full_name, src->name); - else - new_name = g_strdup(src->name); - - if (src->parent_store == m->store && m->move) { - /* simple case, rename */ - camel_store_rename_folder(m->store, src->full_name, new_name, &m->msg.ex); - m->moved = !camel_exception_is_set (&m->msg.ex); - } else { - CamelFolder *dest; - - /* copy the folder to the new location */ - if ((dest = camel_store_get_folder(m->store, new_name, CAMEL_STORE_FOLDER_CREATE, &m->msg.ex))) { - GPtrArray *uids; - - uids = camel_folder_get_uids (src); - camel_folder_transfer_messages_to (src, uids, dest, NULL, FALSE, &m->msg.ex); - camel_folder_free_uids (src, uids); - - camel_object_unref (dest); - } - } - - g_free(new_name); - camel_object_unref(src); -} - -static gboolean -import_message_rfc822 (CamelFolder *dest, CamelStream *stream, gboolean scan_from, CamelException *ex) -{ - CamelMimeParser *mp; - - mp = camel_mime_parser_new (); - camel_mime_parser_scan_from (mp, scan_from); - camel_mime_parser_init_with_stream (mp, stream); - - while (camel_mime_parser_step (mp, 0, 0) == CAMEL_MIME_PARSER_STATE_FROM) { - CamelMessageInfo *info; - CamelMimeMessage *msg; - - msg = camel_mime_message_new (); - if (camel_mime_part_construct_from_parser (CAMEL_MIME_PART (msg), mp) == -1) { - camel_object_unref (msg); - camel_object_unref (mp); - return FALSE; - } - - /* append the message to the folder... */ - info = g_new0 (CamelMessageInfo, 1); - camel_folder_append_message (dest, msg, info, NULL, ex); - camel_object_unref (msg); - - if (camel_exception_is_set (ex)) { - camel_object_unref (mp); - return FALSE; - } - - /* skip over the FROM_END state */ - camel_mime_parser_step (mp, 0, 0); - } - - camel_object_unref (mp); - - return TRUE; -} - -static void -drop_message_rfc822(struct _DragDataReceivedAsync *m, CamelFolder *dest) -{ - gboolean scan_from; - - d(printf(" * drop message/rfc822\n")); - - scan_from = m->selection.rfc822->buffer->len > 5 - && !strncmp(m->selection.rfc822->buffer->data, "From ", 5); - import_message_rfc822(dest, (CamelStream *)m->selection.rfc822, scan_from, &m->msg.ex); -} - -static void -drop_text_uri_list(struct _DragDataReceivedAsync *m, CamelFolder *dest) -{ - CamelStream *stream; - CamelURL *url; - int fd, i, go=1; - - d(printf(" * drop uri list\n")); - - for (i = 0; go && m->selection.urilist[i] != NULL; i++) { - d(printf(" - '%s'\n", (char *)m->selection.urilist[i])); - - url = camel_url_new(m->selection.urilist[i], NULL); - if (url == NULL) - continue; - - if (strcmp(url->protocol, "file") == 0 - && (fd = open(url->path, O_RDONLY)) != -1) { - stream = camel_stream_fs_new_with_fd(fd); - go = import_message_rfc822(dest, stream, TRUE, &m->msg.ex); - camel_object_unref(stream); - } - camel_url_free(url); - } -} - -static void -emftm_drag_data_received_async__drop (struct _mail_msg *mm) -{ - struct _DragDataReceivedAsync *m = (struct _DragDataReceivedAsync *) mm; - CamelFolder *folder; - - /* for types other than folder, we can't drop to the root path */ - if (m->info == DND_DROP_TYPE_FOLDER) { - /* copy or move (aka rename) a folder */ - drop_folder(m); - } else if (m->full_name[0] == 0) { - camel_exception_set (&mm->ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot drop message(s) into toplevel store")); - } else if ((folder = camel_store_get_folder (m->store, m->full_name, 0, &mm->ex))) { - switch (m->info) { - case DND_DROP_TYPE_UID_LIST: - /* import a list of uids from another evo folder */ - drop_uid_list(m, folder); - break; - case DND_DROP_TYPE_MESSAGE_RFC822: - /* import a message/rfc822 stream */ - drop_message_rfc822(m, folder); - break; - case DND_DROP_TYPE_TEXT_URI_LIST: - /* import an mbox, maildir, or mh folder? */ - drop_text_uri_list(m, folder); - break; - default: - g_assert_not_reached (); - } - camel_object_unref(folder); - } -} - -static void -emftm_drag_data_received_async__done (struct _mail_msg *mm) -{ - struct _DragDataReceivedAsync *m = (struct _DragDataReceivedAsync *) mm; - gboolean success, delete; - - success = !camel_exception_is_set (&mm->ex); - delete = success && m->move && !m->moved; - - gtk_drag_finish (m->context, success, delete, GDK_CURRENT_TIME); -} - -static void -emftm_drag_data_received_async__free (struct _mail_msg *mm) -{ - struct _DragDataReceivedAsync *m = (struct _DragDataReceivedAsync *) mm; - - g_object_unref(m->context); - camel_object_unref(m->store); - g_free(m->full_name); - - switch (m->info) { - case DND_DROP_TYPE_FOLDER: - g_free(m->selection.folder); - break; - case DND_DROP_TYPE_UID_LIST: - g_free(m->selection.uidlist.uri); - em_utils_uids_free(m->selection.uidlist.uids); - break; - case DND_DROP_TYPE_MESSAGE_RFC822: - camel_object_unref(m->selection.rfc822); - break; - case DND_DROP_TYPE_TEXT_URI_LIST: - g_strfreev(m->selection.urilist); - break; - default: - abort(); - } -} - -static struct _mail_msg_op drag_data_received_async_op = { - NULL, - emftm_drag_data_received_async__drop, - emftm_drag_data_received_async__done, - emftm_drag_data_received_async__free, -}; - -void -em_folder_tree_model_drag_data_received (EMFolderTreeModel *model, GdkDragContext *context, GtkTreePath *dest_path, - GtkSelectionData *selection, guint info) -{ - struct _DragDataReceivedAsync *m; - const char *full_name; - CamelStore *store; - GtkTreeIter iter; - char *path, *tmp; - int i; - - /* this means we are receiving no data */ - if (!selection->data || selection->length == -1) { - gtk_drag_finish (context, FALSE, FALSE, GDK_CURRENT_TIME); - return; - } - - if (!gtk_tree_model_get_iter ((GtkTreeModel *) model, &iter, dest_path)) { - gtk_drag_finish (context, FALSE, FALSE, GDK_CURRENT_TIME); - return; - } - - gtk_tree_model_get ((GtkTreeModel *) model, &iter, - COL_POINTER_CAMEL_STORE, &store, - COL_STRING_FOLDER_PATH, &path, -1); - - /* make sure user isn't try to drop on a placeholder row */ - if (path == NULL) { - gtk_drag_finish (context, FALSE, FALSE, GDK_CURRENT_TIME); - return; - } - - full_name = path[0] == '/' ? path + 1 : path; - - g_object_ref (context); - camel_object_ref (store); - - m = mail_msg_new (&drag_data_received_async_op, NULL, sizeof (struct _DragDataReceivedAsync)); - m->context = context; - m->store = store; - m->full_name = g_strdup (full_name); - m->move = context->action == GDK_ACTION_MOVE; - m->info = info; - - switch (info) { - case DND_DROP_TYPE_FOLDER: - m->selection.folder = g_strdup(selection->data); - break; - case DND_DROP_TYPE_UID_LIST: - em_utils_selection_get_uidlist(selection, &m->selection.uidlist.uri, &m->selection.uidlist.uids); - break; - case DND_DROP_TYPE_MESSAGE_RFC822: - m->selection.rfc822 = (CamelStreamMem *)camel_stream_mem_new_with_buffer(selection->data, selection->length); - break; - case DND_DROP_TYPE_TEXT_URI_LIST: - tmp = g_strndup(selection->data, selection->length); - m->selection.urilist = g_strsplit(tmp, "\n", 0); - g_free(tmp); - for (i=0;m->selection.urilist[i];i++) - g_strstrip(m->selection.urilist[i]); - break; - default: - abort(); - } - - e_thread_put (mail_thread_new, (EMsg *) m); -} - - -GdkDragAction -em_folder_tree_model_row_drop_possible (EMFolderTreeModel *model, GdkDragContext *context, GtkTreePath *path) -{ - GdkAtom target; - int i; - - target = em_folder_tree_model_row_drop_target (model, context, path); - if (target == GDK_NONE) - return 0; - - for (i = 0; i < NUM_DROP_TYPES; i++) { - if (drop_atoms[i] == target) { - switch (i) { - case DND_DROP_TYPE_FOLDER: - return GDK_ACTION_MOVE; - default: - return GDK_ACTION_COPY; - } - } - } - - return 0; -} - - -GdkAtom -em_folder_tree_model_row_drop_target (EMFolderTreeModel *model, GdkDragContext *context, GtkTreePath *path) -{ - gboolean is_store; - GtkTreeIter iter; - GList *targets; - char *uri; - - if (!gtk_tree_model_get_iter ((GtkTreeModel *) model, &iter, path)) - return GDK_NONE; - - gtk_tree_model_get ((GtkTreeModel *) model, &iter, COL_BOOL_IS_STORE, &is_store, COL_STRING_URI, &uri, -1); - - /* can't drag&drop into/onto a vfolder or the vfolder store */ - if (uri && !strncmp (uri, "vfolder:", 8)) { - /* FIXME: ...unless the source is a vfolder */ - return GDK_NONE; - } - - targets = context->targets; - - if (is_store) { - /* can only drop x-folders into a store */ - GdkAtom xfolder; - - xfolder = drop_atoms[DND_DROP_TYPE_FOLDER]; - while (targets != NULL) { - if (targets->data == (gpointer) xfolder) - return xfolder; - - targets = targets->next; - } - } else { - /* can drop anything into folders */ - int i; - - while (targets != NULL) { - for (i = 0; i < NUM_DROP_TYPES; i++) { - if (targets->data == (gpointer) drop_atoms[i]) - return drop_atoms[i]; - } - - targets = targets->next; - } - } - - return GDK_NONE; -} - - -gboolean -em_folder_tree_model_row_draggable (EMFolderTreeModel *model, GtkTreePath *path) -{ - gboolean is_store; - GtkTreeIter iter; - - if (!gtk_tree_model_get_iter ((GtkTreeModel *) model, &iter, path)) - return FALSE; - - gtk_tree_model_get ((GtkTreeModel *) model, &iter, COL_BOOL_IS_STORE, &is_store, -1); - - return !is_store; -} - - -static void -drag_text_uri_list (CamelFolder *src, GtkSelectionData *selection, CamelException *ex) -{ - CamelFolder *dest; - const char *tmpdir; - CamelStore *store; - GPtrArray *uids; - GString *url; - - if (!(tmpdir = e_mkdtemp ("drag-n-drop-XXXXXX"))) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not create temporary directory: %s"), - g_strerror (errno)); - return; - } - - url = g_string_new ("mbox:"); - g_string_append (url, tmpdir); - if (!(store = camel_session_get_store (session, url->str, ex))) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not create temporary mbox store: %s"), - camel_exception_get_description (ex)); - g_string_free (url, TRUE); - - return; - } - - if (!(dest = camel_store_get_folder (store, "mbox", CAMEL_STORE_FOLDER_CREATE, ex))) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not create temporary mbox folder: %s"), - camel_exception_get_description (ex)); - - camel_object_unref (store); - g_string_free (url, TRUE); - - return; - } - - camel_object_unref (store); - uids = camel_folder_get_uids (src); - - camel_folder_transfer_messages_to (src, uids, dest, NULL, FALSE, ex); - if (camel_exception_is_set (ex)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not copy messages to temporary mbox folder: %s"), - camel_exception_get_description (ex)); - } else { - /* replace "mbox:" with "file:" */ - memcpy (url->str, "file", 4); - g_string_append (url, "\r\n"); - gtk_selection_data_set (selection, drag_atoms[DND_DRAG_TYPE_TEXT_URI_LIST], 8, url->str, url->len); - } - - camel_folder_free_uids (src, uids); - camel_object_unref (dest); - g_string_free (url, TRUE); -} - -void -em_folder_tree_model_drag_data_get (EMFolderTreeModel *model, GdkDragContext *context, GtkTreePath *src_path, GtkSelectionData *selection, guint info) -{ - const char *full_name; - CamelFolder *folder; - CamelStore *store; - CamelException ex; - GtkTreeIter iter; - char *path, *uri; - - if (!gtk_tree_model_get_iter ((GtkTreeModel *) model, &iter, src_path)) - return; - - gtk_tree_model_get ((GtkTreeModel *) model, &iter, - COL_POINTER_CAMEL_STORE, &store, - COL_STRING_FOLDER_PATH, &path, - COL_STRING_URI, &uri, -1); - - /* make sure user isn't trying to drag on a placeholder row */ - if (path == NULL) - return; - - full_name = path[0] == '/' ? path + 1 : path; - - camel_exception_init (&ex); - - switch (info) { - case DND_DRAG_TYPE_FOLDER: - /* dragging to a new location in the folder tree */ - printf ("dragging uri: %s\n", uri); - gtk_selection_data_set (selection, drag_atoms[info], 8, uri, strlen (uri) + 1); - break; - case DND_DRAG_TYPE_TEXT_URI_LIST: - /* dragging to nautilus or something, probably */ - /* Note: this doesn't need to be done in another - * thread because the folder should already be - * cached */ - if ((folder = camel_store_get_folder (store, full_name, 0, &ex))) { - drag_text_uri_list (folder, selection, &ex); - camel_object_unref (folder); - } - break; - default: - g_assert_not_reached (); - } - - if (camel_exception_is_set (&ex)) { - camel_exception_clear (&ex); - return; - } - - return; -} - - -gboolean -em_folder_tree_model_drag_data_delete (EMFolderTreeModel *model, GtkTreePath *src_path) -{ - const char *full_name; - gboolean is_store; - CamelStore *store; - CamelException ex; - GtkTreeIter iter; - char *path; - - if (!gtk_tree_model_get_iter ((GtkTreeModel *) model, &iter, src_path)) - return FALSE; - - gtk_tree_model_get ((GtkTreeModel *) model, &iter, - COL_POINTER_CAMEL_STORE, &store, - COL_STRING_FOLDER_PATH, &path, - COL_BOOL_IS_STORE, &is_store, -1); - - if (is_store) - return FALSE; - - full_name = path[0] == '/' ? path + 1 : path; - - camel_exception_init (&ex); - camel_store_delete_folder (store, full_name, &ex); - if (camel_exception_is_set (&ex)) { - camel_exception_clear (&ex); - return FALSE; - } - - return TRUE; -} - - -void -em_folder_tree_model_set_drag_drop_types (EMFolderTreeModel *model, GtkWidget *widget) -{ - gtk_drag_source_set (widget, GDK_BUTTON1_MASK, drag_types, NUM_DRAG_TYPES, - GDK_ACTION_COPY | GDK_ACTION_MOVE); - gtk_drag_dest_set (widget, GTK_DEST_DEFAULT_ALL, drop_types, - NUM_DROP_TYPES, GDK_ACTION_COPY | GDK_ACTION_MOVE); -} |