folder dnd
authorColin Leroy <colin@colino.net>
Wed, 6 Nov 2002 23:56:26 +0000 (23:56 +0000)
committerColin Leroy <colin@colino.net>
Wed, 6 Nov 2002 23:56:26 +0000 (23:56 +0000)
ChangeLog.claws
configure.in
src/folder.c
src/folder.h
src/folderview.c

index 89f0754da2fddfe78ea16aed39a6b7e4d52e64fe..e5731e43af75d71a2e9dd54f69539c84c7e884f2 100644 (file)
@@ -1,3 +1,13 @@
+2002-11-07 [colin]     0.8.5claws81
+
+       * src/folder.[ch]
+               Add folder_item_move_to() function to move a 
+               folderitem into another one (updates matcher etc)
+       * src/folderview.c
+               Add folder drag'n drop (context menu to come)
+               [Should be dataloss free, but Please backup before 
+                trying !]
+
 2002-11-06 [colin]     0.8.5claws80
 
        * src/mh.c
index 70477baf019019c7d0727df59de92a6b55eb5bbe..b9f7d5f97eb200b0aa797400ce3aa84992a9b0a8 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=8
 MICRO_VERSION=5
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=claws80
+EXTRA_VERSION=claws81
 VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION$EXTRA_VERSION
 
 dnl set $target
index eb0f396bba4f370533fc3b28a2c07fecf0e7a244..081cb80a11773b41de5c05124ef2afca9f1de415 100644 (file)
@@ -449,7 +449,8 @@ FolderItem *folder_create_folder(FolderItem *parent, const gchar *name)
        FolderItem *new_item;
 
        new_item = parent->folder->create_folder(parent->folder, parent, name);
-       new_item->cache = msgcache_new();
+       if (new_item)
+               new_item->cache = msgcache_new();
 
        return new_item;
 }
@@ -1435,6 +1436,104 @@ gint folder_item_move_msg(FolderItem *dest, MsgInfo *msginfo)
        return num;
 }
 */
+               
+gint folder_item_move_recursive (FolderItem *src, FolderItem *dest) 
+{
+       GSList *mlist;
+       GSList *cur;
+       FolderItem *new_item;
+       FolderItem *next_item;
+       GNode *srcnode;
+
+       mlist = folder_item_get_msg_list(src);
+
+       /* move messages */
+       debug_print("Moving %s to %s\n", src->path, dest->path);
+       new_item = folder_create_folder(dest, g_basename(src->path));
+       
+       if (new_item == NULL) {
+               printf("Can't create folder\n");
+               return -1;
+       }
+       
+       for (cur = mlist ; cur != NULL ; cur = cur->next) {
+               MsgInfo * msginfo;
+               msginfo = (MsgInfo *) cur->data;
+               folder_item_move_msg(new_item, msginfo);
+       }
+       srcnode = src->folder->node;    
+       srcnode = g_node_find(srcnode, G_PRE_ORDER, G_TRAVERSE_ALL, src);
+       srcnode = srcnode->children;
+       while (srcnode != NULL) {
+               if (srcnode && srcnode->data) {
+                       next_item = (FolderItem*) srcnode->data;
+                       if (folder_item_move_recursive(next_item, new_item) != 0)
+                               return -1;
+               }
+               srcnode = srcnode->next;
+       }
+       return 0;
+}
+
+gint folder_item_move_to(FolderItem *src, FolderItem *dest)
+{
+       FolderItem *tmp = dest->parent;
+       char * srcpath, * dstpath;
+       char * phys_srcpath, * phys_dstpath;
+       while (tmp) {
+               if (tmp == src) {
+                       alertpanel_error(_("Can't move a folder to one of its children."));
+                       return -1;
+               }
+               tmp = tmp->parent;
+       }
+       
+       tmp = src->parent;
+       
+       srcpath = folder_item_get_identifier(src);
+       dstpath = folder_item_get_identifier(dest);
+       
+       if (srcpath == NULL || dstpath == NULL) {
+               printf("Can't get identifiers\n");
+               return -1;
+       }
+
+       phys_srcpath = folder_item_get_path(src);
+       phys_dstpath = g_strconcat(folder_item_get_path(dest),G_DIR_SEPARATOR_S,g_basename(srcpath),NULL);
+       
+       if (src->parent == dest) {
+               alertpanel_error(_("Source and destination are the same."));
+               g_free(srcpath);
+               g_free(dstpath);
+               g_free(phys_srcpath);
+               g_free(phys_dstpath);
+               return -1;
+       }
+       debug_print("moving \"%s\" to \"%s\"\n", phys_srcpath, phys_dstpath);
+       if (folder_item_move_recursive(src, dest) != 0) {
+               alertpanel_error(_("Move failed !"));
+               return -1;
+       }
+       
+       /* update rules */
+       debug_print("updating rules ....\n");
+       prefs_filtering_rename_path(srcpath, g_strconcat(dstpath, G_DIR_SEPARATOR_S, g_basename(srcpath), NULL));
+
+       src->folder->remove_folder(src->folder, src);
+       /* not to much worry if remove fails, move has been done */
+       
+       folder_write_list();
+
+       /* rescan parents */
+       debug_print("rescanning foldertree ....\n");
+       folderview_rescan_tree(dest->folder);
+               
+       g_free(srcpath);
+       g_free(dstpath);
+       g_free(phys_srcpath);
+       g_free(phys_dstpath);
+       return 0;
+}
 
 gint folder_item_move_msg(FolderItem *dest, MsgInfo *msginfo)
 {
index e95cd0a5fd932bf1896dab0984ac21b69d87baa0..fdd87679ecf908345f1adaf3a2458cf4cf0b5f21 100644 (file)
@@ -352,6 +352,8 @@ gchar *folder_item_fetch_msg                (FolderItem     *item,
 gint   folder_item_add_msg             (FolderItem     *dest,
                                         const gchar    *file,
                                         gboolean        remove_source);
+gint   folder_item_move_to             (FolderItem     *src,
+                                        FolderItem     *dest);
 gint   folder_item_move_msg            (FolderItem     *dest,
                                         MsgInfo        *msginfo);
 gint   folder_item_move_msgs_with_dest (FolderItem     *dest,
@@ -370,7 +372,6 @@ gboolean folder_item_is_msg_changed (FolderItem     *item,
 gchar *folder_item_get_cache_file      (FolderItem     *item);
 gchar *folder_item_get_mark_file       (FolderItem     *item);
 gchar * folder_item_get_identifier(FolderItem * item);
-FolderItem * folder_find_item_from_identifier(const gchar *identifier);
 
 GHashTable *folder_persist_prefs_new   (Folder *folder);
 void folder_persist_prefs_free         (GHashTable *pptable);
index e92ddda54f6fd60f8bcebd150e8534489c2d01d1..7b388d8305a60aa7e89ee511997082a9a2d9e2f0 100644 (file)
@@ -247,6 +247,15 @@ static void folderview_drag_received_cb  (GtkWidget        *widget,
                                          guint             info,
                                          guint             time,
                                          FolderView       *folderview);
+static void folderview_start_drag       (GtkWidget *widget, gint button, GdkEvent *event,
+                                         FolderView       *folderview);
+static void folderview_drag_data_get     (GtkWidget        *widget,
+                                         GdkDragContext   *drag_context,
+                                         GtkSelectionData *selection_data,
+                                         guint             info,
+                                         guint             time,
+                                         FolderView       *folderview);
+
 static void folderview_scoring_cb(FolderView *folderview, guint action,
                                  GtkWidget *widget);
 static void folderview_processing_cb(FolderView *folderview, guint action,
@@ -356,7 +365,7 @@ FolderView *folderview_create(void)
                             prefs_common.folderview_width,
                             prefs_common.folderview_height);
 
-       ctree = gtk_ctree_new_with_titles(N_FOLDER_COLS, COL_FOLDER, titles);
+       ctree = gtk_sctree_new_with_titles(N_FOLDER_COLS, COL_FOLDER, titles);
        
        gtk_container_add(GTK_CONTAINER(scrolledwin), ctree);
        gtk_clist_set_selection_mode(GTK_CLIST(ctree), GTK_SELECTION_BROWSE);
@@ -424,6 +433,11 @@ FolderView *folderview_create(void)
                           folderview);
        gtk_signal_connect(GTK_OBJECT(ctree), "tree_select_row",
                           GTK_SIGNAL_FUNC(folderview_selected), folderview);
+       gtk_signal_connect(GTK_OBJECT(ctree), "start_drag",
+                          GTK_SIGNAL_FUNC(folderview_start_drag), folderview);
+       gtk_signal_connect(GTK_OBJECT(ctree), "drag_data_get",
+                          GTK_SIGNAL_FUNC(folderview_drag_data_get),
+                          folderview);
 
        gtk_signal_connect_after(GTK_OBJECT(ctree), "tree_expand",
                                 GTK_SIGNAL_FUNC(folderview_tree_expanded),
@@ -2593,32 +2607,61 @@ static void folderview_drag_received_cb(GtkWidget        *widget,
        FolderItem *item, *src_item;
        GtkCTreeNode *node;
 
-       if (gtk_clist_get_selection_info
-               (GTK_CLIST(widget), x - 24, y - 24, &row, &column) == 0)
-               return;
+       if ((void *)strstr(data->data, "FROM_OTHER_FOLDER") != (void *)data->data) {
+               /* comes from summaryview */
+               if (gtk_clist_get_selection_info
+                       (GTK_CLIST(widget), x - 24, y - 24, &row, &column) == 0)
+                       return;
 
-       node = gtk_ctree_node_nth(GTK_CTREE(widget), row);
-       item = gtk_ctree_node_get_row_data(GTK_CTREE(widget), node);
-       src_item = folderview->summaryview->folder_item;
-       if (item && src_item) {
-               switch (drag_context->action) {
-                       case GDK_ACTION_COPY:
+               node = gtk_ctree_node_nth(GTK_CTREE(widget), row);
+               item = gtk_ctree_node_get_row_data(GTK_CTREE(widget), node);
+               src_item = folderview->summaryview->folder_item;
+               if (item && src_item) {
+                       switch (drag_context->action) {
+                               case GDK_ACTION_COPY:
+                                       summary_copy_selected_to(folderview->summaryview, item);
+                                       gtk_drag_finish(drag_context, TRUE, FALSE, time);
+                                       break;
+                               case GDK_ACTION_MOVE:
+                               case GDK_ACTION_DEFAULT:
+                               default:
+                       if (src_item->folder->type != item->folder->type ||
+                           (item->folder->type == F_IMAP &&
+                            src_item->folder != item->folder))
                                summary_copy_selected_to(folderview->summaryview, item);
-                               gtk_drag_finish(drag_context, TRUE, FALSE, time);
-                               break;
-                       case GDK_ACTION_MOVE:
-                       case GDK_ACTION_DEFAULT:
-                       default:
-               if (src_item->folder->type != item->folder->type ||
-                   (item->folder->type == F_IMAP &&
-                    src_item->folder != item->folder))
-                       summary_copy_selected_to(folderview->summaryview, item);
+                       else
+                               summary_move_selected_to(folderview->summaryview, item);
+                       gtk_drag_finish(drag_context, TRUE, TRUE, time);
+                       }
+               } else
+                       gtk_drag_finish(drag_context, FALSE, FALSE, time);
+       } else {
+               /* comes from folderview */
+               char *source;
+               char *buf;
+               source = data->data + 17;
+               if (*source == 0)
+                       return;
+               if (gtk_clist_get_selection_info
+                       (GTK_CLIST(widget), x - 24, y - 24, &row, &column) == 0)
+                       return;
+               node = gtk_ctree_node_nth(GTK_CTREE(widget), row);
+               item = gtk_ctree_node_get_row_data(GTK_CTREE(widget), node);
+               src_item = folder_find_item_from_path(source);
+               if (!src_item)
+                       return;
+               if (src_item->stype != F_NORMAL)
+                       return;
+               buf = g_strdup_printf(_("Moving %s to %s..."), src_item->name, item->name);
+               STATUSBAR_PUSH(folderview->mainwin, buf);
+               main_window_cursor_wait(folderview->mainwin);
+               if (!folder_item_move_to(src_item, item))
+                       gtk_drag_finish(drag_context, TRUE, TRUE, time);
                else
-                       summary_move_selected_to(folderview->summaryview, item);
-               gtk_drag_finish(drag_context, TRUE, TRUE, time);
-               }
-       } else
-               gtk_drag_finish(drag_context, FALSE, FALSE, time);
+                       gtk_drag_finish(drag_context, FALSE, FALSE, time);
+               STATUSBAR_PUSH(folderview->mainwin, _("Done."));
+               main_window_cursor_normal(folderview->mainwin);
+       }
 }
 
 static gint folderview_clist_compare(GtkCList *clist,
@@ -2696,3 +2739,53 @@ void folderview_reflect_prefs_pixmap_theme(FolderView *folderview)
        folderview_init(folderview);
        folderview_set_all();
 }
+
+GtkTargetEntry folderview_drag_types[1] =
+{
+       {"text/plain", GTK_TARGET_SAME_APP, TARGET_DUMMY}
+};
+
+
+static void folderview_start_drag(GtkWidget *widget, gint button, GdkEvent *event,
+                                 FolderView       *folderview)
+{
+       GtkTargetList *list;
+       GdkDragContext *context;
+
+       g_return_if_fail(folderview != NULL);
+       if (folderview->selected == NULL) return;
+
+       list = gtk_target_list_new(folderview_drag_types, 1);
+
+       context = gtk_drag_begin(widget, list,
+                                GDK_ACTION_MOVE|GDK_ACTION_COPY|GDK_ACTION_DEFAULT, button, event);
+       gtk_drag_set_icon_default(context);
+}
+
+static void folderview_drag_data_get(GtkWidget        *widget,
+                                    GdkDragContext   *drag_context,
+                                    GtkSelectionData *selection_data,
+                                    guint             info,
+                                    guint             time,
+                                    FolderView       *folderview)
+{
+       FolderItem *item;
+       GList *cur;
+       gchar *source=NULL;
+       
+       for (cur = GTK_CLIST(folderview->ctree)->selection;
+            cur != NULL; cur = cur->next) {
+               item = gtk_ctree_node_get_row_data
+                       (GTK_CTREE(folderview->ctree), 
+                        GTK_CTREE_NODE(cur->data));
+               if (item) {
+                       source = g_strdup_printf ("FROM_OTHER_FOLDER%s", item->path);
+                       gtk_selection_data_set(selection_data,
+                                              selection_data->target, 8,
+                                              source, strlen(source));
+                       break;
+               } else
+                       return;
+       }
+}
+