]> Pileus Git - ~andy/gtk/blob - tests/testentrycompletion.c
Really handle a NULL model, fixes #137211 for real.
[~andy/gtk] / tests / testentrycompletion.c
1
2 #include <config.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <gtk/gtk.h>
6
7 /* Don't copy this bad example; inline RGB data is always a better
8  * idea than inline XPMs.
9  */
10 static char  *book_closed_xpm[] = {
11 "16 16 6 1",
12 "       c None s None",
13 ".      c black",
14 "X      c red",
15 "o      c yellow",
16 "O      c #808080",
17 "#      c white",
18 "                ",
19 "       ..       ",
20 "     ..XX.      ",
21 "   ..XXXXX.     ",
22 " ..XXXXXXXX.    ",
23 ".ooXXXXXXXXX.   ",
24 "..ooXXXXXXXXX.  ",
25 ".X.ooXXXXXXXXX. ",
26 ".XX.ooXXXXXX..  ",
27 " .XX.ooXXX..#O  ",
28 "  .XX.oo..##OO. ",
29 "   .XX..##OO..  ",
30 "    .X.#OO..    ",
31 "     ..O..      ",
32 "      ..        ",
33 "                "
34 };
35
36 static GtkWidget *window = NULL;
37
38
39 /* Creates a tree model containing the completions */
40 GtkTreeModel *
41 create_simple_completion_model (void)
42 {
43   GtkListStore *store;
44   GtkTreeIter iter;
45   
46   store = gtk_list_store_new (1, G_TYPE_STRING);
47
48   gtk_list_store_append (store, &iter);
49   gtk_list_store_set (store, &iter, 0, "GNOME", -1);
50   gtk_list_store_append (store, &iter);
51   gtk_list_store_set (store, &iter, 0, "gnominious", -1);
52   gtk_list_store_append (store, &iter);
53   gtk_list_store_set (store, &iter, 0, "Gnomonic projection", -1);
54
55   gtk_list_store_append (store, &iter);
56   gtk_list_store_set (store, &iter, 0, "total", -1);
57   gtk_list_store_append (store, &iter);
58   gtk_list_store_set (store, &iter, 0, "totally", -1);
59   gtk_list_store_append (store, &iter);
60   gtk_list_store_set (store, &iter, 0, "toto", -1);
61   gtk_list_store_append (store, &iter);
62   gtk_list_store_set (store, &iter, 0, "tottery", -1);
63   gtk_list_store_append (store, &iter);
64   gtk_list_store_set (store, &iter, 0, "totterer", -1);
65   gtk_list_store_append (store, &iter);
66   gtk_list_store_set (store, &iter, 0, "Totten trust", -1);
67   gtk_list_store_append (store, &iter);
68   gtk_list_store_set (store, &iter, 0, "totipotent", -1);
69   gtk_list_store_append (store, &iter);
70   gtk_list_store_set (store, &iter, 0, "totipotency", -1);
71   gtk_list_store_append (store, &iter);
72   gtk_list_store_set (store, &iter, 0, "totemism", -1);
73   gtk_list_store_append (store, &iter);
74   gtk_list_store_set (store, &iter, 0, "totem pole", -1);
75   gtk_list_store_append (store, &iter);
76   gtk_list_store_set (store, &iter, 0, "Totara", -1);
77   gtk_list_store_append (store, &iter);
78   gtk_list_store_set (store, &iter, 0, "totalizer", -1);
79   gtk_list_store_append (store, &iter);
80   gtk_list_store_set (store, &iter, 0, "totalizator", -1);
81   gtk_list_store_append (store, &iter);
82   gtk_list_store_set (store, &iter, 0, "totalitarianism", -1);
83   gtk_list_store_append (store, &iter);
84   gtk_list_store_set (store, &iter, 0, "total parenteral nutrition", -1);
85   gtk_list_store_append (store, &iter);
86   gtk_list_store_set (store, &iter, 0, "total hysterectomy", -1);
87   gtk_list_store_append (store, &iter);
88   gtk_list_store_set (store, &iter, 0, "total eclipse", -1);
89   gtk_list_store_append (store, &iter);
90   gtk_list_store_set (store, &iter, 0, "Totipresence", -1);
91   gtk_list_store_append (store, &iter);
92   gtk_list_store_set (store, &iter, 0, "Totipalmi", -1);
93   gtk_list_store_append (store, &iter);
94   gtk_list_store_set (store, &iter, 0, "zombie", -1);
95  
96   return GTK_TREE_MODEL (store);
97 }
98
99 /* Creates a tree model containing the completions */
100 GtkTreeModel *
101 create_completion_model (void)
102 {
103   GtkListStore *store;
104   GtkTreeIter iter;
105   GdkPixbuf *pixbuf;
106
107   pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **)book_closed_xpm);
108
109   store = gtk_list_store_new (2, GDK_TYPE_PIXBUF, G_TYPE_STRING);
110
111   gtk_list_store_append (store, &iter);
112   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "ambient", -1);
113   gtk_list_store_append (store, &iter);
114   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "ambidextrously", -1);
115   gtk_list_store_append (store, &iter);
116   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "ambidexter", -1);
117   gtk_list_store_append (store, &iter);
118   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "ambiguity", -1);
119   gtk_list_store_append (store, &iter);
120   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "American Party", -1);
121   gtk_list_store_append (store, &iter);
122   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "American mountain ash", -1);
123   gtk_list_store_append (store, &iter);
124   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "amelioration", -1);
125   gtk_list_store_append (store, &iter);
126   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "Amelia Earhart", -1);
127   gtk_list_store_append (store, &iter);
128   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "Totten trust", -1);
129   gtk_list_store_append (store, &iter);
130   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "Laminated arch", -1);
131  
132   return GTK_TREE_MODEL (store);
133 }
134
135 static gboolean
136 match_func (GtkEntryCompletion *completion,
137             const gchar        *key,
138             GtkTreeIter        *iter,
139             gpointer            user_data)
140 {
141   gchar *item = NULL;
142   GtkTreeModel *model;
143
144   gboolean ret = FALSE;
145
146   model = gtk_entry_completion_get_model (completion);
147
148   gtk_tree_model_get (model, iter, 1, &item, -1);
149
150   if (item != NULL)
151     {
152       g_print ("compare %s %s\n", key, item);
153       if (strncmp (key, item, strlen (key)) == 0)
154         ret = TRUE;
155
156       g_free (item);
157     }
158
159   return ret;
160 }
161
162 static void
163 activated_cb (GtkEntryCompletion *completion, 
164               gint                index,
165               gpointer            user_data)
166 {
167   g_print ("action activated: %d\n", index);
168 }
169
170 static gint timer_count = 0;
171
172 static gchar *dynamic_completions[] = {
173   "GNOME",
174   "gnominious",
175   "Gnomonic projection",
176   "total",
177   "totally",
178   "toto",
179   "tottery",
180   "totterer",
181   "Totten trust",
182   "totipotent",
183   "totipotency",
184   "totemism",
185   "totem pole",
186   "Totara",
187   "totalizer",
188   "totalizator",
189   "totalitarianism",
190   "total parenteral nutrition",
191   "total hysterectomy",
192   "total eclipse",
193   "Totipresence",
194   "Totipalmi",
195   "zombie"
196 };
197
198 static gint
199 animation_timer (GtkEntryCompletion *completion)
200 {
201   GtkTreeIter iter;
202   gint n_completions = G_N_ELEMENTS (dynamic_completions);
203   gint n;
204   static GtkListStore *old_store = NULL;
205   GtkListStore *store = GTK_LIST_STORE (gtk_entry_completion_get_model (completion));
206
207   if (timer_count % 10 == 0)
208     {
209       if (!old_store)
210         {
211           g_print ("removing model!\n");
212
213           old_store = g_object_ref (gtk_entry_completion_get_model (completion));
214           gtk_entry_completion_set_model (completion, NULL);
215         }
216       else
217         {
218           g_print ("readding model!\n");
219           
220           gtk_entry_completion_set_model (completion, old_store);
221           g_object_unref (old_store);
222           old_store = NULL;
223         }
224
225       timer_count ++;
226       return TRUE;
227     }
228
229   if (!old_store)
230     {
231       if ((timer_count / n_completions) % 2 == 0)
232         {
233           n = timer_count % n_completions;
234           gtk_list_store_append (store, &iter);
235           gtk_list_store_set (store, &iter, 0, dynamic_completions[n], -1);
236           
237         }
238       else
239         {
240           gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
241           gtk_list_store_remove (store, &iter);
242         }
243     }
244   
245   timer_count++;
246   return TRUE;
247 }
248
249 gboolean 
250 match_selected_cb (GtkEntryCompletion *completion,
251                    GtkTreeModel       *model,
252                    GtkTreeIter        *iter)
253 {
254   gchar *str;
255   GtkWidget *entry;
256
257   entry = gtk_entry_completion_get_entry (completion);
258   gtk_tree_model_get (GTK_TREE_MODEL (model), iter, 1, &str, -1);
259   gtk_entry_set_text (GTK_ENTRY (entry), str);
260   gtk_editable_set_position (GTK_EDITABLE (entry), -1);
261   g_free (str);
262
263   return TRUE;
264 }
265
266 int 
267 main (int argc, char *argv[])
268 {
269   GtkWidget *vbox;
270   GtkWidget *label;
271   GtkWidget *entry;
272   GtkEntryCompletion *completion;
273   GtkTreeModel *completion_model;
274   GtkCellRenderer *cell;
275
276   gtk_init (&argc, &argv);
277
278   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
279   gtk_container_set_border_width (GTK_CONTAINER (window), 5);
280   g_signal_connect (window, "delete_event", gtk_main_quit, NULL);
281   
282   vbox = gtk_vbox_new (FALSE, 2);
283   gtk_container_add (GTK_CONTAINER (window), vbox);
284     
285   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
286   
287   label = gtk_label_new (NULL);
288
289   gtk_label_set_markup (GTK_LABEL (label), "Completion demo, try writing <b>total</b> or <b>gnome</b> for example.");
290   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
291
292   /* Create our first entry */
293   entry = gtk_entry_new ();
294   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
295   
296   /* Create the completion object */
297   completion = gtk_entry_completion_new ();
298   
299   /* Assign the completion to the entry */
300   gtk_entry_set_completion (GTK_ENTRY (entry), completion);
301   g_object_unref (completion);
302   
303   /* Create a tree model and use it as the completion model */
304   completion_model = create_simple_completion_model ();
305   gtk_entry_completion_set_model (completion, completion_model);
306   g_object_unref (completion_model);
307   
308   /* Use model column 0 as the text column */
309   gtk_entry_completion_set_text_column (completion, 0);
310
311   /* Create our second entry */
312   entry = gtk_entry_new ();
313   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
314
315   /* Create the completion object */
316   completion = gtk_entry_completion_new ();
317   
318   /* Assign the completion to the entry */
319   gtk_entry_set_completion (GTK_ENTRY (entry), completion);
320   g_object_unref (completion);
321   
322   /* Create a tree model and use it as the completion model */
323   completion_model = create_completion_model ();
324   gtk_entry_completion_set_model (completion, completion_model);
325   gtk_entry_completion_set_minimum_key_length (completion, 2);
326   g_object_unref (completion_model);
327   
328   /* Use model column 1 as the text column */
329   cell = gtk_cell_renderer_pixbuf_new ();
330   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion), cell, FALSE);
331   gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (completion), cell, 
332                                   "pixbuf", 0, NULL); 
333
334   cell = gtk_cell_renderer_text_new ();
335   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion), cell, FALSE);
336   gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (completion), cell, 
337                                   "text", 1, NULL); 
338   
339   gtk_entry_completion_set_match_func (completion, match_func, NULL, NULL);
340   g_signal_connect (G_OBJECT (completion), "match-selected", 
341                     G_CALLBACK (match_selected_cb), NULL);
342
343   gtk_entry_completion_insert_action_text (completion, 100, "action!");
344   gtk_entry_completion_insert_action_text (completion, 101, "'nother action!");
345   g_signal_connect (completion, "action_activated", G_CALLBACK (activated_cb), 0);
346
347   /* Create our third entry */
348   entry = gtk_entry_new ();
349   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
350
351   /* Create the completion object */
352   completion = gtk_entry_completion_new ();
353   
354   /* Assign the completion to the entry */
355   gtk_entry_set_completion (GTK_ENTRY (entry), completion);
356   g_object_unref (completion);
357   
358   /* Create a tree model and use it as the completion model */
359   completion_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
360
361   gtk_entry_completion_set_model (completion, completion_model);
362   g_object_unref (completion_model);
363
364   /* Use model column 0 as the text column */
365   gtk_entry_completion_set_text_column (completion, 0);
366
367   /* Fill the completion dynamically */
368   g_timeout_add (1000, (GSourceFunc) animation_timer, completion);
369
370   /* Fourth entry */
371   gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new ("Model-less entry completion"), FALSE, FALSE, 0);
372
373   entry = gtk_entry_new ();
374   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
375
376   /* Create the completion object */
377   completion = gtk_entry_completion_new ();
378   
379   /* Assign the completion to the entry */
380   gtk_entry_set_completion (GTK_ENTRY (entry), completion);
381   g_object_unref (completion);
382   
383   gtk_widget_show_all (window);
384
385   gtk_main ();
386   
387   return 0;
388 }
389
390