From 77efa0c6319a87e2d6ec8af307917a9426f3164e Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Thu, 19 Apr 2018 09:42:51 -0400 Subject: [PATCH] gui/model: Configure the gui model as a drag source We'll need to do this to enable drag and drop to reorder playlists. Signed-off-by: Anna Schumaker --- gui/model.c | 42 ++++++++++++++++++++++++++++++++++++++++++ gui/treeview.c | 3 +++ include/gui/model.h | 9 +++++++++ 3 files changed, 54 insertions(+) diff --git a/gui/model.c b/gui/model.c index 734c60eb..6966529d 100644 --- a/gui/model.c +++ b/gui/model.c @@ -28,6 +28,12 @@ static GType gui_model_columns[GUI_MODEL_N_COLUMNS] = { [GUI_MODEL_FONT] = G_TYPE_STRING, }; +const GtkTargetEntry gui_model_drag_targets[] = { + { GUI_DRAG_DATA, GTK_TARGET_SAME_APP, 0 }, +}; + +const unsigned int gui_model_n_targets = G_N_ELEMENTS(gui_model_drag_targets); + static GtkTreeModelFlags __gui_model_get_flags(GtkTreeModel *model) { return GTK_TREE_MODEL_LIST_ONLY; @@ -169,6 +175,27 @@ static gboolean __gui_model_iter_parent(GtkTreeModel *model, GtkTreeIter *iter, return FALSE; } +static gboolean __gui_model_drag_data_get(GtkTreeDragSource *drag_source, + GtkTreePath *path, + GtkSelectionData *selection_data) +{ + struct gui_model_drag_data *data = g_malloc(sizeof(*data)); + + data->drag_row = gtk_tree_path_get_indices(path)[0]; + data->drag_track = gui_model_path_get_track(path); + + gtk_selection_data_set(selection_data, gdk_atom_intern(GUI_DRAG_DATA, false), + 8 /* bytes */, (void *)data, sizeof(*data)); + g_free(data); + return true; +} + +static gboolean __gui_model_drag_data_delete(GtkTreeDragSource *drag_source, + GtkTreePath *path) +{ + return true; +} + static void __gui_model_init(GuiModel *model) { model->gm_stamp = g_random_int(); @@ -203,6 +230,12 @@ static void __gui_tree_model_init(GtkTreeModelIface *iface) iface->iter_parent = __gui_model_iter_parent; } +static void __gui_drag_source_init(GtkTreeDragSourceIface *iface) +{ + iface->drag_data_get = __gui_model_drag_data_get; + iface->drag_data_delete = __gui_model_drag_data_delete; +} + static const GTypeInfo gui_model_type_info = { .class_size = sizeof(GuiModelClass), .base_init = NULL, @@ -221,6 +254,12 @@ static const GInterfaceInfo gui_tree_model = { .interface_data = NULL, }; +static const GInterfaceInfo gui_drag_source = { + .interface_init = (GInterfaceInitFunc)__gui_drag_source_init, + .interface_finalize = NULL, + .interface_data = NULL, +}; + void gui_model_init(void) { @@ -229,6 +268,9 @@ void gui_model_init(void) (GTypeFlags)0); g_type_add_interface_static(gui_model_type, GTK_TYPE_TREE_MODEL, &gui_tree_model); + g_type_add_interface_static(gui_model_type, GTK_TYPE_TREE_DRAG_SOURCE, + &gui_drag_source); + gui_model = g_object_new(gui_model_type, NULL); g_assert(gui_model != NULL); diff --git a/gui/treeview.c b/gui/treeview.c index f24a2852..d6ddd2da 100644 --- a/gui/treeview.c +++ b/gui/treeview.c @@ -167,6 +167,9 @@ void gui_treeview_init() gtk_tree_view_set_model(gui_treeview(), GTK_TREE_MODEL(gui_filter_get())); + gtk_tree_view_enable_model_drag_source(gui_treeview(), GDK_BUTTON1_MASK, + gui_model_drag_targets, gui_model_n_targets, + GDK_ACTION_MOVE); for (i = 0; i < GUI_MODEL_N_COLUMNS; i++) { col = gtk_tree_view_get_column(gui_treeview(), i); diff --git a/include/gui/model.h b/include/gui/model.h index 326ae8ac..f4d8543a 100644 --- a/include/gui/model.h +++ b/include/gui/model.h @@ -38,6 +38,15 @@ struct gui_model_class { }; typedef struct gui_model_class GuiModelClass; +struct gui_model_drag_data { + unsigned int drag_row; + struct track *drag_track; +}; + +#define GUI_DRAG_DATA "GUI_DRAG_DATA" + +extern const GtkTargetEntry gui_model_drag_targets[]; +extern const unsigned int gui_model_n_targets; /* Called to initialize the GuiModel */ void gui_model_init(void);