From ae63b21c61633186c4a5c2330c84877e6524765b Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 22 Feb 2015 12:30:49 -0500 Subject: [PATCH] icon browser: Add some dnd support Use a custom tree model and enable dragging from the icon view. Currently, we just support dropping the icon name as text. --- demos/icon-browser/Makefile.am | 1 + demos/icon-browser/iconbrowserwin.c | 52 +++++++++++------ demos/icon-browser/iconstore.c | 91 +++++++++++++++++++++++++++++ demos/icon-browser/iconstore.h | 26 +++++++++ demos/icon-browser/window.ui | 8 +-- 5 files changed, 152 insertions(+), 26 deletions(-) create mode 100644 demos/icon-browser/iconstore.c create mode 100644 demos/icon-browser/iconstore.h diff --git a/demos/icon-browser/Makefile.am b/demos/icon-browser/Makefile.am index 9ab38613ea..ddaf2c7547 100644 --- a/demos/icon-browser/Makefile.am +++ b/demos/icon-browser/Makefile.am @@ -20,6 +20,7 @@ gtk3_icon_browser_SOURCES = \ main.c \ iconbrowserapp.c iconbrowserapp.h \ iconbrowserwin.c iconbrowserwin.h \ + iconstore.c iconstore.h \ resources.c BUILT_SOURCES = \ diff --git a/demos/icon-browser/iconbrowserwin.c b/demos/icon-browser/iconbrowserwin.c index 50709a08ff..fdf51e945a 100644 --- a/demos/icon-browser/iconbrowserwin.c +++ b/demos/icon-browser/iconbrowserwin.c @@ -1,6 +1,7 @@ #include #include "iconbrowserapp.h" #include "iconbrowserwin.h" +#include "iconstore.h" #include typedef struct @@ -42,13 +43,6 @@ struct _IconBrowserWindowClass GtkApplicationWindowClass parent_class; }; -enum { - NAME_COLUMN, - SYMBOLIC_NAME_COLUMN, - DESCRIPTION_COLUMN, - CONTEXT_COLUMN -}; - G_DEFINE_TYPE(IconBrowserWindow, icon_browser_window, GTK_TYPE_APPLICATION_WINDOW); static void @@ -82,12 +76,12 @@ item_activated (GtkIconView *icon_view, GtkTreePath *path, IconBrowserWindow *wi gtk_tree_model_get_iter (GTK_TREE_MODEL (win->filter_model), &iter, path); if (win->symbolic) - column = SYMBOLIC_NAME_COLUMN; + column = ICON_STORE_SYMBOLIC_NAME_COLUMN; else - column = NAME_COLUMN; + column = ICON_STORE_NAME_COLUMN; gtk_tree_model_get (GTK_TREE_MODEL (win->filter_model), &iter, column, &name, - DESCRIPTION_COLUMN, &description, + ICON_STORE_DESCRIPTION_COLUMN, &description, -1); if (name == NULL || !gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), name)) @@ -141,10 +135,10 @@ add_icon (IconBrowserWindow *win, symbolic_name = NULL; } gtk_list_store_insert_with_values (win->store, NULL, -1, - NAME_COLUMN, regular_name, - SYMBOLIC_NAME_COLUMN, symbolic_name, - DESCRIPTION_COLUMN, description, - CONTEXT_COLUMN, context, + ICON_STORE_NAME_COLUMN, regular_name, + ICON_STORE_SYMBOLIC_NAME_COLUMN, symbolic_name, + ICON_STORE_DESCRIPTION_COLUMN, description, + ICON_STORE_CONTEXT_COLUMN, context, -1); } @@ -697,13 +691,13 @@ icon_visible_func (GtkTreeModel *model, search_text = gtk_entry_get_text (GTK_ENTRY (win->searchentry)); if (win->symbolic) - column = SYMBOLIC_NAME_COLUMN; + column = ICON_STORE_SYMBOLIC_NAME_COLUMN; else - column = NAME_COLUMN; + column = ICON_STORE_NAME_COLUMN; gtk_tree_model_get (model, iter, column, &name, - CONTEXT_COLUMN, &context, + ICON_STORE_CONTEXT_COLUMN, &context, -1); if (!name) visible = FALSE; @@ -726,9 +720,11 @@ symbolic_toggled (GtkToggleButton *toggle, IconBrowserWindow *win) win->symbolic = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle)); if (win->symbolic) - column = SYMBOLIC_NAME_COLUMN; + column = ICON_STORE_SYMBOLIC_NAME_COLUMN; else - column = NAME_COLUMN; + column = ICON_STORE_NAME_COLUMN; + + icon_store_set_text_column (ICON_STORE (win->store), column); gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (win->list), win->cell, "icon-name", column, NULL); gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (win->list), win->text_cell, "text", column, NULL); @@ -747,8 +743,24 @@ search_mode_toggled (GObject *searchbar, GParamSpec *pspec, IconBrowserWindow *w static void icon_browser_window_init (IconBrowserWindow *win) { + GtkTargetList *list; + GtkTargetEntry *targets; + gint n_targets; + gtk_widget_init_template (GTK_WIDGET (win)); + list = gtk_target_list_new (NULL, 0); + gtk_target_list_add_text_targets (list, 0); + targets = gtk_target_table_new_from_list (list, &n_targets); + gtk_target_list_unref (list); + + gtk_icon_view_enable_model_drag_source (GTK_ICON_VIEW (win->list), + GDK_BUTTON1_MASK, + targets, n_targets, + GDK_ACTION_COPY); + + gtk_target_table_free (targets, n_targets); + win->contexts = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free); gtk_tree_model_filter_set_visible_func (win->filter_model, icon_visible_func, win, NULL); @@ -765,6 +777,8 @@ icon_browser_window_init (IconBrowserWindow *win) static void icon_browser_window_class_init (IconBrowserWindowClass *class) { + g_type_ensure (ICON_STORE_TYPE); + gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class), "/org/gtk/iconbrowser/window.ui"); diff --git a/demos/icon-browser/iconstore.c b/demos/icon-browser/iconstore.c new file mode 100644 index 0000000000..b43691ffa2 --- /dev/null +++ b/demos/icon-browser/iconstore.c @@ -0,0 +1,91 @@ +#include "iconstore.h" +#include + +struct _IconStore +{ + GtkListStore parent; + + gint text_column; +}; + +struct _IconStoreClass +{ + GtkListStoreClass parent_class; +}; + +static void icon_store_drag_source_init (GtkTreeDragSourceIface *iface); + +G_DEFINE_TYPE_WITH_CODE (IconStore, icon_store, GTK_TYPE_LIST_STORE, + G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE, + icon_store_drag_source_init)) + + +static void +icon_store_init (IconStore *store) +{ + GType types[4] = { G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING }; + + gtk_list_store_set_column_types (GTK_LIST_STORE (store), 4, types); + + store->text_column = ICON_STORE_NAME_COLUMN; +} + +static void +icon_store_class_init (IconStoreClass *class) +{ +} + +static gboolean +row_draggable (GtkTreeDragSource *drag_source, + GtkTreePath *path) +{ + return TRUE; +} + +static gboolean +drag_data_delete (GtkTreeDragSource *drag_source, + GtkTreePath *path) +{ + GtkTreeIter iter; + + if (gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source), &iter, path)) + return gtk_list_store_remove (GTK_LIST_STORE (drag_source), &iter); + return FALSE; +} + +static gboolean +drag_data_get (GtkTreeDragSource *drag_source, + GtkTreePath *path, + GtkSelectionData *selection) +{ + GtkTreeIter iter; + gchar *text; + + if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source), &iter, path)) + return FALSE; + + gtk_tree_model_get (GTK_TREE_MODEL (drag_source), &iter, + ICON_STORE (drag_source)->text_column, &text, + -1); + + gtk_selection_data_set_text (selection, text, -1); + + g_free (text); + + return TRUE; +} + + +static void +icon_store_drag_source_init (GtkTreeDragSourceIface *iface) +{ + iface->row_draggable = row_draggable; + iface->drag_data_delete = drag_data_delete; + iface->drag_data_get = drag_data_get; +} + +void +icon_store_set_text_column (IconStore *store, gint text_column) +{ + store->text_column = text_column; +} diff --git a/demos/icon-browser/iconstore.h b/demos/icon-browser/iconstore.h new file mode 100644 index 0000000000..a21f7bd7aa --- /dev/null +++ b/demos/icon-browser/iconstore.h @@ -0,0 +1,26 @@ +#ifndef __ICON_STORE_H +#define __ICON_STORE_H + +#include + + +#define ICON_STORE_TYPE (icon_store_get_type ()) +#define ICON_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ICON_STORE_TYPE, IconStore)) + + +typedef struct _IconStore IconStore; +typedef struct _IconStoreClass IconStoreClass; + +enum { + ICON_STORE_NAME_COLUMN, + ICON_STORE_SYMBOLIC_NAME_COLUMN, + ICON_STORE_DESCRIPTION_COLUMN, + ICON_STORE_CONTEXT_COLUMN +}; + +GType icon_store_get_type (void); + +void icon_store_set_text_column (IconStore *store, + gint column); + +#endif /* __ICON_STORE_H */ diff --git a/demos/icon-browser/window.ui b/demos/icon-browser/window.ui index 4c61860446..e91d16b698 100644 --- a/demos/icon-browser/window.ui +++ b/demos/icon-browser/window.ui @@ -1,13 +1,7 @@ - - - - - - - + store