Skip to content

Instantly share code, notes, and snippets.

@elboulangero
Last active September 26, 2016 10:29
Show Gist options
  • Save elboulangero/0d832e203fbb1aec4513c5b1a20794b6 to your computer and use it in GitHub Desktop.
Save elboulangero/0d832e203fbb1aec4513c5b1a20794b6 to your computer and use it in GitHub Desktop.
GtkTreeView inconsistent 'row-activated' signal emission before drag'n'drop, 'activate-on-single-click'=TRUE, 'reorderable'=TRUE
/*
* Compile with:
* gcc $(pkg-config --cflags gtk+-3.0 --libs gtk+-3.0) -lm gtk-tree-view-row-activated.c -o gtk-tree-view-row-activated
*/
#include <stdlib.h>
#include <math.h>
#include <glib.h>
#include <gtk/gtk.h>
/*
* Debug
*/
static const gchar *
time_now(void)
{
static gchar *now_str;
GDateTime *now;
g_free(now_str);
now = g_date_time_new_now_local();
now_str = g_strdup_printf("%02d:%02d:%02d.%03d",
g_date_time_get_hour(now),
g_date_time_get_minute(now),
g_date_time_get_second(now),
lround(g_date_time_get_microsecond(now) / 1000.0));
g_date_time_unref(now);
return now_str;
}
#define debug(fmt, ...) \
printf("%s: " fmt "\n", time_now(), ##__VA_ARGS__);
/*
* Signal handlers
*/
static gboolean
idle(gpointer user_data)
{
debug("Idle");
return FALSE;
}
static void
on_tree_view_row_activated(GtkTreeView *tree_view,
GtkTreePath *path,
GtkTreeViewColumn *column,
gpointer user_data)
{
debug("Row activated");
g_idle_add(idle, NULL);
}
static void
on_tree_view_drag_begin(GtkWidget *widget,
GdkDragContext *context,
gpointer user_data)
{
debug("Drag begin");
}
static void
on_tree_view_drag_end(GtkWidget *widget,
GdkDragContext *context,
gpointer user_data)
{
debug("Drag end");
printf("----\n");
}
/*
* Main
*/
static void
station_cell_data_func(GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell,
GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer data)
{
gchar *text;
gtk_tree_model_get(tree_model, iter,
0, &text,
-1);
g_object_set(cell,
"text", text,
NULL);
g_free(text);
}
int
main(int argc, char *argv[])
{
/* Init */
gtk_init(&argc, &argv);
/* Create the tree view */
GtkWidget *tree_view;
tree_view = gtk_tree_view_new();
GtkListStore *list_store;
list_store = gtk_list_store_new(1, G_TYPE_STRING);
gtk_tree_view_set_model(GTK_TREE_VIEW(tree_view), GTK_TREE_MODEL(list_store));
g_object_unref(list_store);
GtkCellRenderer *renderer;
renderer = gtk_cell_renderer_text_new();
GtkTreeViewColumn *column;
column = gtk_tree_view_column_new_with_attributes("Text", renderer, NULL);
gtk_tree_view_column_set_cell_data_func(column, renderer,
station_cell_data_func,
NULL, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
/* Populate the tree view */
GtkTreeIter tree_iter;
gtk_list_store_append(list_store, &tree_iter);
gtk_list_store_set(list_store, &tree_iter,
0, "Yesterday",
-1);
gtk_list_store_append(list_store, &tree_iter);
gtk_list_store_set(list_store, &tree_iter,
0, "Today",
-1);
gtk_list_store_append(list_store, &tree_iter);
gtk_list_store_set(list_store, &tree_iter,
0, "Tomorrow",
-1);
/* Configure the tree view */
/* Activate on single-click */
gtk_tree_view_set_activate_on_single_click(GTK_TREE_VIEW(tree_view), TRUE);
/* Set re-orderable, and therefore enable drag'n'drop */
gtk_tree_view_set_reorderable(GTK_TREE_VIEW(tree_view), TRUE);
/* Connect signal handlers */
g_signal_connect(tree_view, "row-activated",
G_CALLBACK(on_tree_view_row_activated), NULL);
g_signal_connect(tree_view, "drag-begin",
G_CALLBACK(on_tree_view_drag_begin), NULL);
g_signal_connect(tree_view, "drag-end",
G_CALLBACK(on_tree_view_drag_end), NULL);
/* Create the window */
GtkWidget *box;
box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
g_object_set(box, "margin", 8, NULL);
GtkWidget *label;
label = gtk_label_new("Try re-ordering the items and look\n"
"for the 'row-activated' signal.\n"
"It may or may not be emitted.");
gtk_box_pack_start(GTK_BOX(box), label, TRUE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(box), tree_view, TRUE, FALSE, 0);
GtkWidget *window;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_container_add(GTK_CONTAINER(window), box);
gtk_widget_show_all(window);
/* Main loop */
gtk_main();
return EXIT_SUCCESS;
}
@elboulangero
Copy link
Author

Typical output. The signal 'row-activated' is sometimes emitted before the 'drag-begin' signal, sometimes not.

$ ./gtk-tree-view-row-activated 
17:18:19.825: Drag begin
17:18:20.365: Drag end
----
17:18:23.175: Row activated
17:18:23.178: Drag begin
17:18:23.182: Idle
17:18:23.796: Drag end
----
17:18:25.581: Row activated
17:18:25.584: Drag begin
17:18:25.588: Idle
17:18:26.265: Drag end
----
17:18:27.613: Row activated
17:18:27.615: Drag begin
17:18:27.619: Idle
17:18:28.154: Drag end
----
17:18:29.894: Drag begin
17:18:30.719: Drag end
----

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment