44 gtk_list_store_append(test->
store, &iter);
45 gtk_list_store_set(test->
store, &iter, 0, text, -1);
50 while(gtk_events_pending()) gtk_main_iteration();
55 g_main_loop_quit(loop);
56 return G_SOURCE_REMOVE;
61 GMainLoop *loop = g_main_loop_new(NULL,
FALSE);
63 g_main_loop_run(loop);
64 g_main_loop_unref(loop);
69 gboolean mapped =
FALSE;
70 GList *toplevels = gtk_window_list_toplevels();
71 for(GList *toplevel = toplevels; toplevel; toplevel = g_list_next(toplevel))
73 GtkWidget *widget = GTK_WIDGET(toplevel->data);
74 if(widget != entry_window && gtk_widget_get_mapped(widget)) mapped =
TRUE;
76 g_list_free(toplevels);
82 GdkEventKey
event = { 0 };
83 event.type = GDK_KEY_PRESS;
84 event.window = g_object_ref(gtk_widget_get_window(widget));
85 event.send_event =
TRUE;
86 event.time = GDK_CURRENT_TIME;
87 event.keyval = keyval;
88 gboolean handled =
FALSE;
89 g_signal_emit_by_name(widget,
"key-press-event", &event, &handled);
90 g_object_unref(event.window);
95 GtkTreeIter *iter, gpointer user_data)
97 gchar *candidate = NULL;
98 gtk_tree_model_get(gtk_entry_completion_get_model(completion), iter, 0, &candidate, -1);
99 const gchar *token = g_strrstr(
key,
",");
100 token = token ? token + 1 :
key;
101 while(*token ==
' ') token++;
102 const gboolean matches = g_str_has_prefix(candidate, token);
110 test->
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
111 test->
entry = GTK_ENTRY(gtk_entry_new());
112 test->
store = gtk_list_store_new(1, G_TYPE_STRING);
115 test->
completion = gtk_entry_completion_new();
116 gtk_entry_completion_set_model(test->
completion, GTK_TREE_MODEL(test->
store));
117 gtk_entry_completion_set_text_column(test->
completion, 0);
118 gtk_entry_completion_set_inline_completion(test->
completion,
TRUE);
119 gtk_entry_completion_set_popup_completion(test->
completion,
TRUE);
120 gtk_entry_completion_set_minimum_key_length(test->
completion, 1);
122 g_signal_connect(test->
completion,
"match-selected",
125 gtk_container_add(GTK_CONTAINER(test->
window), GTK_WIDGET(test->
entry));
126 gtk_widget_show_all(test->
window);
127 gtk_window_set_focus(GTK_WINDOW(test->
window), GTK_WIDGET(test->
entry));
128 gtk_window_present(GTK_WINDOW(test->
window));
129 gdk_window_focus(gtk_widget_get_window(test->
window), GDK_CURRENT_TIME);
131 GdkEvent *focus_event = gdk_event_new(GDK_FOCUS_CHANGE);
132 focus_event->focus_change.window = g_object_ref(gtk_widget_get_window(GTK_WIDGET(test->
entry)));
133 focus_event->focus_change.in =
TRUE;
134 gtk_widget_send_focus_change(GTK_WIDGET(test->
entry), focus_event);
135 gdk_event_free(focus_event);
136 assert_true(gtk_widget_has_focus(GTK_WIDGET(test->
entry)));
144 gtk_entry_set_completion(test->
entry, NULL);
145 gtk_widget_destroy(test->
window);
148 g_object_unref(test->
store);
155 if(event->keyval != GDK_KEY_Return)
return FALSE;
156 state->entry_calls++;
158 state->text = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
166 gtk_entry_set_text(test->
entry,
"subjects");
168 gtk_list_store_clear(test->
store);
173 assert_string_equal(gtk_entry_get_text(test->
entry),
"");
174 assert_ptr_equal(gtk_entry_get_completion(test->
entry), test->
completion);
182 gtk_entry_set_text(test->
entry,
"subjects");
185 assert_string_equal(gtk_entry_get_text(test->
entry),
"");
188 gtk_entry_set_text(test->
entry,
"subjects|animals, places");
191 assert_string_equal(gtk_entry_get_text(test->
entry),
"");
195 gtk_editable_insert_text(GTK_EDITABLE(test->
entry),
"places", -1, &
position);
197 gtk_entry_completion_insert_prefix(test->
completion);
200 assert_ptr_equal(gtk_entry_get_completion(test->
entry), test->
completion);
201 assert_string_equal(gtk_entry_get_text(test->
entry),
"places|france|paris");
206 GtkEntry *entry = GTK_ENTRY(gtk_entry_new());
207 gtk_entry_set_text(entry,
"places|france");
211 assert_string_equal(gtk_entry_get_text(entry),
"");
212 assert_null(gtk_entry_get_completion(entry));
213 gtk_widget_destroy(GTK_WIDGET(entry));
220 gtk_entry_set_text(test->
entry,
"subjects|animals, pla");
221 gtk_editable_set_position(GTK_EDITABLE(test->
entry), -1);
222 gtk_entry_completion_set_inline_completion(test->
completion,
TRUE);
224 assert_true(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(test->
store), &iter));
225 assert_true(gtk_tree_model_iter_next(GTK_TREE_MODEL(test->
store), &iter));
227 gboolean handled =
FALSE;
228 g_signal_emit_by_name(test->
completion,
"match-selected",
229 GTK_TREE_MODEL(test->
store), &iter, &handled);
232 assert_true(handled);
233 assert_string_equal(gtk_entry_get_text(test->
entry),
234 "subjects|animals,places|france|paris");
235 assert_true(gtk_entry_completion_get_inline_completion(test->
completion));
236 assert_ptr_equal(gtk_entry_get_completion(test->
entry), test->
completion);
244 if(!gtk_window_is_active(GTK_WINDOW(test->
window))) skip();
246 gulong handler_id = g_signal_connect(test->
entry,
"key-press-event",
249 g_signal_handler_disconnect(test->
entry, handler_id);
251 handler_id = g_signal_connect(test->
entry,
"key-press-event",
254 gtk_editable_insert_text(GTK_EDITABLE(test->
entry),
"subjects|animals, pla", -1, &
position);
258 g_signal_handler_disconnect(test->
entry, handler_id);
265 assert_string_equal(gtk_entry_get_text(test->
entry),
266 "subjects|animals,places|france|paris");
269 assert_true(gtk_entry_completion_get_inline_completion(test->
completion));
273 assert_string_equal(handler_state.
text,
"subjects|animals,places|france|paris");
275 g_signal_handler_disconnect(test->
entry, handler_id);
276 g_free(handler_state.
text);
281 if(!gtk_init_check(&argc, &argv))
return 77;
282 const struct CMUnitTest tests[] = {
293 return cmocka_run_group_tests(tests, NULL, NULL);
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
const float uint32_t state[4]
GtkEntryCompletion * completion
void dt_tagging_entry_clear(GtkEntry *entry)
gboolean dt_tagging_completion_match_selected(GtkEntryCompletion *completion, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
static void test_selected_completion_replaces_only_the_active_token(void **state)
static int _teardown_completion(void **state)
static void test_completion_survives_repeated_single_and_hierarchical_clears(void **state)
static void test_clear_cancels_completion_before_model_refresh(void **state)
static gboolean _send_key(GtkWidget *widget, const guint keyval)
static gboolean _quit_main_loop(GMainLoop *loop)
static void _append_completion(dt_tagging_completion_test_t *test, const char *text)
static void _drain_gtk_events()
static gboolean _match_last_hierarchical_token(GtkEntryCompletion *completion, const gchar *key, GtkTreeIter *iter, gpointer user_data)
static gboolean _record_plain_return(GtkWidget *entry, GdkEventKey *event, dt_return_handler_state_t *state)
static void test_clear_supports_entry_without_completion(void **state)
static void test_completion_keeps_return_priority_after_reattach(void **state)
static void _wait_for_completion_sources()
static int _setup_completion(void **state)
static gboolean _completion_popup_is_mapped(GtkWidget *entry_window)