[Commits] [SCM] claws branch, gtk3tree, updated. 3.99.0-73-gc6a10f64c
thorsten at claws-mail.org
thorsten at claws-mail.org
Tue Mar 30 15:12:34 CEST 2021
The branch, gtk3tree has been updated
via c6a10f64caac59e271a5a8be09442e138175b6ad (commit)
from 8cfe1ccd2d5f126332519b0bcf283781444f8332 (commit)
Summary of changes:
src/folderview.c | 210 +++++++++++++++++++++++++++++++++++++++++--------------
src/folderview.h | 5 +-
2 files changed, 162 insertions(+), 53 deletions(-)
- Log -----------------------------------------------------------------
commit c6a10f64caac59e271a5a8be09442e138175b6ad
Author: Thorsten Maerz <info at netztorte.de>
Date: Tue Mar 30 15:09:32 2021 +0200
Reimplement drag&drop for folders and messages
diff --git a/src/folderview.c b/src/folderview.c
index 27afa4476..4e4949f59 100644
--- a/src/folderview.c
+++ b/src/folderview.c
@@ -1776,7 +1776,73 @@ void folderview_check_new_all(void)
void folderview_move_folder(FolderView *folderview, FolderItem *from_folder,
FolderItem *to_folder, gboolean copy)
{
- debug_print("========STUB======== folderview_move_folder\n");
+ FolderItem *new_folder = NULL;
+ gchar *buf;
+ gint status;
+
+ cm_return_if_fail(folderview != NULL);
+ cm_return_if_fail(from_folder != NULL);
+ cm_return_if_fail(to_folder != NULL);
+
+ if (prefs_common.warn_dnd) {
+ buf = g_strdup_printf(copy ? _("Do you really want to copy folder '%s' in '%s'?"):
+ _("Do you really want to make folder '%s' a subfolder of '%s'?"),
+ from_folder->name, to_folder->name);
+ status = alertpanel_full(copy ? _("Copy folder"):_("Move folder"), buf,
+ _("_No"), _("_Yes"), NULL, ALERTFOCUS_FIRST,
+ TRUE, NULL, ALERT_QUESTION);
+ g_free(buf);
+
+ if ((status & ~G_ALERTDISABLE) != G_ALERTALTERNATE)
+ return;
+ else if (status & G_ALERTDISABLE)
+ prefs_common.warn_dnd = FALSE;
+ }
+
+ buf = g_strdup_printf(copy ? _("Copying %s to %s..."):_("Moving %s to %s..."),
+ from_folder->name, to_folder->name);
+ STATUSBAR_PUSH(folderview->mainwin, buf);
+ g_free(buf);
+ summary_clear_all(folderview->summaryview);
+ gtk_widget_set_sensitive(GTK_WIDGET(folderview->treeview), FALSE);
+ inc_lock();
+ main_window_cursor_wait(folderview->mainwin);
+
+ statusbar_verbosity_set(FALSE);
+ folder_item_update_freeze();
+ folderview_freeze(folderview);
+ if ((status = folder_item_move_to(from_folder, to_folder, &new_folder, copy)) == F_MOVE_OK) {
+ statusbar_verbosity_set(FALSE);
+ main_window_cursor_normal(folderview->mainwin);
+ STATUSBAR_POP(folderview->mainwin);
+ folder_item_update_thaw();
+ folder_item_update_recursive(new_folder, F_ITEM_UPDATE_MSGCNT);
+ folderview_select(folderview, new_folder);
+ folderview_thaw(folderview);
+ } else {
+ statusbar_verbosity_set(FALSE);
+ main_window_cursor_normal(folderview->mainwin);
+ STATUSBAR_POP(folderview->mainwin);
+ folderview_thaw(folderview);
+ folder_item_update_thaw();
+ switch (status) {
+ case F_MOVE_FAILED_DEST_IS_PARENT:
+ alertpanel_error(_("Source and destination are the same."));
+ break;
+ case F_MOVE_FAILED_DEST_IS_CHILD:
+ alertpanel_error(copy ? _("Can't copy a folder to one of its children."):
+ _("Can't move a folder to one of its children."));
+ break;
+ case F_MOVE_FAILED_DEST_OUTSIDE_MAILBOX:
+ alertpanel_error(_("A folder cannot be moved between different mailboxes."));
+ break;
+ default:
+ alertpanel_error(copy ? _("Copy failed!"):_("Move failed!"));
+ break;
+ }
+ }
+ inc_unlock();
+ gtk_widget_set_sensitive(GTK_WIDGET(folderview->treeview), TRUE);
}
void folderview_set_target_folder_color(GdkRGBA color_op)
@@ -1956,6 +2022,12 @@ void folderview_unregister_popup(FolderViewPopup *fpopup)
g_hash_table_remove(folderview_popups, fpopup->klass);
}
+void free_paths_to_recollapse(GSList *paths_to_recollapse)
+{
+ GSList *list;
+ for (list=paths_to_recollapse; list; list = g_slist_next(list))
+ gtk_tree_path_free(list->data);
+}
static void folderview_recollapse_paths(FolderView *folderview,
GtkTreePath *path)
{
@@ -1969,8 +2041,8 @@ static void folderview_recollapse_paths(FolderView *folderview,
gtk_tree_view_collapse_row(GTK_TREE_VIEW(folderview->treeview),
listpath);
done = g_slist_append(done, listpath);
+ gtk_tree_path_free(listpath);
}
- gtk_tree_path_free(listpath);
}
for (list = done; list != NULL; list = g_slist_next(list)) {
folderview->paths_to_recollapse = g_slist_remove(folderview->paths_to_recollapse,
@@ -1984,23 +2056,26 @@ static void drag_state_stop(FolderView *folderview)
if (folderview->drag_timer_id)
g_source_remove(folderview->drag_timer_id);
folderview->drag_timer_id = 0;
- folderview->drag_path = NULL;
+ if (folderview->drag_dst_path) {
+ gtk_tree_path_free(folderview->drag_dst_path);
+ folderview->drag_dst_path = NULL;
+ }
}
static gboolean folderview_defer_expand(FolderView *folderview)
{
- if (folderview->drag_path) {
- folderview_recollapse_paths(folderview, folderview->drag_path);
- if (folderview->drag_item->collapsed) {
+ if (folderview->drag_dst_path) {
+ folderview_recollapse_paths(folderview, folderview->drag_dst_path);
+ if (folderview->drag_dst_item->collapsed) {
gtk_tree_view_expand_row(GTK_TREE_VIEW(folderview->treeview),
- folderview->drag_path, FALSE);
+ folderview->drag_dst_path, FALSE);
/* reverse order: child doesn't get closed, if parent is already closed. */
folderview->paths_to_recollapse = g_slist_insert
(folderview->paths_to_recollapse,
- folderview->drag_path, 0);
+ gtk_tree_path_copy(folderview->drag_dst_path), 0);
}
}
- folderview->drag_item = NULL;
+ folderview->drag_dst_item = NULL;
folderview->drag_timer_id = 0;
return FALSE;
}
@@ -2016,22 +2091,29 @@ static void drag_state_start(FolderView *folderview, GtkTreePath *path, FolderIt
(prefs_common.hover_timeout,
(GSourceFunc)folderview_defer_expand,
folderview))) {
- folderview->drag_path = path;
- folderview->drag_item = item;
+ /* free path from earlier folderview_recollapse_paths() invocations */
+ if (folderview->drag_dst_path)
+ gtk_tree_path_free(folderview->drag_dst_path);
+ folderview->drag_dst_path = path;
+ folderview->drag_dst_item = item;
}
}
#ifndef GENERIC_UMPC
+/* only called for dragged treeview nodes, not for summaryview items */
static void folderview_drag_begin(GtkWidget *widget, GdkDragContext *context,
FolderView *folderview)
{
-//TM: debug_print("========STUB======== folderview_drag_begin\n");
+ gtk_tree_view_get_cursor(GTK_TREE_VIEW(folderview->treeview),
+ &folderview->drag_src_path, NULL);
+ free_paths_to_recollapse(folderview->paths_to_recollapse);
if (folderview->paths_to_recollapse)
g_slist_free(folderview->paths_to_recollapse);
folderview->paths_to_recollapse = NULL;
gtk_drag_set_icon_default(context);
}
#endif
+/* only called for dragged treeview nodes, not for summaryview items */
static void folderview_drag_data_get(GtkWidget *widget,
GdkDragContext *drag_context,
GtkSelectionData *selection_data,
@@ -2039,19 +2121,20 @@ static void folderview_drag_data_get(GtkWidget *widget,
guint time,
FolderView *folderview)
{
- debug_print("========STUB======== folderview_drag_data_get\n");
-#if 0
+ GtkTreeModel *model;
+ GtkTreeIter iter;
FolderItem *item;
- GList *sel;
gchar *source = NULL;
if (info == TARGET_DUMMY) {
- sel = GTK_CMCLIST(folderview->ctree)->selection;
- if (!sel)
+ if (!folderview->drag_src_path)
return;
- item = gtk_cmctree_node_get_row_data
- (GTK_CMCTREE(folderview->ctree),
- GTK_CMCTREE_NODE(sel->data));
+ model = gtk_tree_view_get_model(GTK_TREE_VIEW(folderview->treeview));
+ if (!model)
+ return;
+
+ gtk_tree_model_get_iter(model, &iter, folderview->drag_src_path);
+ gtk_tree_model_get(model, &iter, F_COL_FOLDERITEM, &item, -1);
if (item) {
source = g_strdup_printf ("FROM_OTHER_FOLDER%s", folder_item_get_identifier(item));
gtk_selection_data_set(selection_data,
@@ -2061,7 +2144,6 @@ static void folderview_drag_data_get(GtkWidget *widget,
} else {
g_warning("unknown info %d", info);
}
-#endif
}
static gboolean folderview_dnd_scroll_cb(gpointer data)
@@ -2088,6 +2170,7 @@ static gboolean folderview_dnd_scroll_cb(gpointer data)
return TRUE;
}
+/* called for dragged treeview nodes and summaryview items */
static gboolean folderview_drag_motion_cb(GtkWidget *widget,
GdkDragContext *context,
gint x,
@@ -2095,7 +2178,6 @@ static gboolean folderview_drag_motion_cb(GtkWidget *widget,
guint time,
FolderView *folderview)
{
-//TM: debug_print("========STUB======== folderview_drag_motion_cb\n");
GtkTreePath *path;
GtkTreeViewDropPosition drop_pos;
GtkTreeIter iter;
@@ -2143,6 +2225,11 @@ static gboolean folderview_drag_motion_cb(GtkWidget *widget,
src_item != item && FOLDER_CLASS(item->folder)->copy_msg != NULL &&
FOLDER_TYPE(item->folder) != F_UNKNOWN)
acceptable = TRUE;
+ /* TM: remember current selection, to restore it afterwards */
+ if (!folderview->drag_src_path) {
+ gtk_tree_view_get_cursor(GTK_TREE_VIEW(folderview->treeview),
+ &folderview->drag_src_path, NULL);
+ }
} else if (srcwidget == folderview->treeview) {
/* comes from folderview */
/* we are moving folder items, only accept folders that are not
@@ -2189,17 +2276,15 @@ static gboolean folderview_drag_motion_cb(GtkWidget *widget,
return acceptable;
}
+/* called for dragged treeview nodes and summaryview items
+ * TM: for dragged folders, folderview_drag_data_get() and folderview_drag_end_cb() are called hereafter
+ * for dragged messages, folderview_drag_received_cb() is called hereafter */
static void folderview_drag_leave_cb(GtkWidget *widget,
GdkDragContext *context,
guint time,
FolderView *folderview)
{
debug_print("========STUB======== folderview_drag_leave_cb\n");
-#if 0
- drag_state_stop(folderview);
- folderview->scroll_value = 0;
- gtk_cmctree_select(GTK_CMCTREE(widget), folderview->opened);
-#endif
}
static void free_info (gpointer stuff, gpointer data)
@@ -2210,6 +2295,7 @@ static void free_info (gpointer stuff, gpointer data)
#endif
}
+/* only for TARGET_MAIL_URI_LIST */
void folderview_finish_dnd(const gchar *data, GdkDragContext *drag_context,
guint time, FolderItem *item)
{
@@ -2256,6 +2342,7 @@ void folderview_finish_dnd(const gchar *data, GdkDragContext *drag_context,
#endif
}
+/* called for dragged treeview nodes and summaryview items */
static void folderview_drag_received_cb(GtkWidget *widget,
GdkDragContext *drag_context,
gint x,
@@ -2265,26 +2352,30 @@ static void folderview_drag_received_cb(GtkWidget *widget,
guint time,
FolderView *folderview)
{
- debug_print("========STUB======== folderview_drag_received_cb\n");
-#if 0
gint row, column;
FolderItem *item = NULL, *src_item;
- GtkCMCTreeNode *node;
+ GtkTreePath *path;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
int offset = prefs_common.show_col_headers ? 24:0;
folderview->scroll_value = 0;
+ gtk_tree_view_get_cursor(GTK_TREE_VIEW(widget), &path, NULL);
+ model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
+ if (!model)
+ return;
+
+ gtk_tree_model_get_iter(model, &iter, path);
+ gtk_tree_model_get(model, &iter, F_COL_FOLDERITEM, &item, -1);
+ if (!item)
+ return;
+
if (info == TARGET_DUMMY) {
drag_state_stop(folderview);
const gchar *ddata = (const gchar *)gtk_selection_data_get_data(data);
if ((gchar *)strstr(ddata, "FROM_OTHER_FOLDER") != ddata) {
/* comes from summaryview */
- if (gtk_cmclist_get_selection_info
- (GTK_CMCLIST(widget), x - offset, y - offset, &row, &column) == 0)
- return;
-
- node = gtk_cmctree_node_nth(GTK_CMCTREE(widget), row);
- item = gtk_cmctree_node_get_row_data(GTK_CMCTREE(widget), node);
src_item = folderview->summaryview->folder_item;
if (item->no_select) {
@@ -2312,6 +2403,17 @@ static void folderview_drag_received_cb(GtkWidget *widget,
summary_move_selected_to(folderview->summaryview, item);
gtk_drag_finish(drag_context, TRUE, TRUE, time);
}
+ /* TM: drop done - cleanup */
+ drag_state_stop(folderview);
+ folderview->scroll_value = 0;
+ if (folderview->drag_src_path) {
+ gtk_tree_view_set_cursor
+ (GTK_TREE_VIEW(folderview->treeview),
+ folderview->drag_src_path, NULL, FALSE);
+ gtk_tree_path_free(folderview->drag_src_path);
+ folderview->drag_src_path = NULL;
+ summary_grab_focus(folderview->summaryview);
+ }
} else {
/* comes from folderview */
char *source;
@@ -2320,14 +2422,6 @@ static void folderview_drag_received_cb(GtkWidget *widget,
gdk_drag_context_get_selected_action(drag_context));
source = (char *)gtk_selection_data_get_data(data) + 17;
- if (gtk_cmclist_get_selection_info
- (GTK_CMCLIST(widget), x - offset, y - offset, &row, &column) == 0
- || *source == 0) {
- gtk_drag_finish(drag_context, FALSE, FALSE, time);
- return;
- }
- node = gtk_cmctree_node_nth(GTK_CMCTREE(widget), row);
- item = gtk_cmctree_node_get_row_data(GTK_CMCTREE(widget), node);
src_item = folder_find_item_from_identifier(source);
folder_is_normal =
@@ -2345,8 +2439,14 @@ static void folderview_drag_received_cb(GtkWidget *widget,
folderview_move_folder(folderview, src_item, item, copy);
gtk_drag_finish(drag_context, TRUE, TRUE, time);
}
- folderview->nodes_to_recollapse = NULL;
+ if (folderview->paths_to_recollapse) {
+ free_paths_to_recollapse(folderview->paths_to_recollapse);
+ g_slist_free(folderview->paths_to_recollapse);
+ folderview->paths_to_recollapse = NULL;
+ }
} else if (info == TARGET_MAIL_URI_LIST) {
+ debug_print("========STUB======== folderview_drag_received_cb:TARGET_MAIL_URI_LIST\n");
+#if 0
if (gtk_cmclist_get_selection_info
(GTK_CMCLIST(widget), x - offset, y - offset, &row, &column) == 0)
return;
@@ -2365,21 +2465,26 @@ static void folderview_drag_received_cb(GtkWidget *widget,
}
folderview_finish_dnd(gtk_selection_data_get_data(data),
drag_context, time, item);
+#endif /* 0 - TARGET_MAIL_URI_LIST */
}
-#endif
}
+/* Only called for dragged treeview nodes, not for summaryview items */
static void folderview_drag_end_cb(GtkWidget *widget,
GdkDragContext *drag_context,
FolderView *folderview)
{
- debug_print("========STUB======== folderview_drag_end_cb\n");
-#if 0
drag_state_stop(folderview);
folderview->scroll_value = 0;
- g_slist_free(folderview->nodes_to_recollapse);
- folderview->nodes_to_recollapse = NULL;
-#endif
+ if (folderview->paths_to_recollapse) {
+ free_paths_to_recollapse(folderview->paths_to_recollapse);
+ g_slist_free(folderview->paths_to_recollapse);
+ folderview->paths_to_recollapse = NULL;
+ }
+ if (folderview->drag_src_path) {
+ gtk_tree_path_free(folderview->drag_src_path);
+ folderview->drag_src_path = NULL;
+ }
}
@@ -2427,6 +2532,9 @@ void folderview_remove_item(FolderView *folderview, FolderItem *item)
debug_print("========STUB======== folderview_remove_item\n");
}
+/* TM: There is no freeze/thaw. Detaching the model can be a workaround,
+ * but that doesn't allow changes to the treeview (only direct changes to
+ * the datastore are possible then). */
void folderview_freeze(FolderView *folderview)
{
debug_print("========STUB======== folderview_freeze\n");
diff --git a/src/folderview.h b/src/folderview.h
index 5b4252b09..49ab644ae 100644
--- a/src/folderview.h
+++ b/src/folderview.h
@@ -66,8 +66,9 @@ struct _FolderView
/* DND states */
GSList *paths_to_recollapse;
guint drag_timer_id; /* timer id */
- FolderItem *drag_item; /* dragged item */
- GtkTreePath *drag_path; /* drag node */
+ FolderItem *drag_dst_item; /* dragged item (destination) */
+ GtkTreePath *drag_dst_path; /* drag path (destination) */
+ GtkTreePath *drag_src_path; /* drag path (source: either dragged folder, or folder, that contained the dragged message) */
gint scroll_value;
guint scroll_timeout_id;
-----------------------------------------------------------------------
hooks/post-receive
--
Claws Mail
More information about the Commits
mailing list