1 /* gtkentrycompletion.c
2 * Copyright (C) 2003 Kristian Rietveld <kris@gtk.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
22 #include "gtkentrycompletion.h"
24 #include "gtkentryprivate.h"
25 #include "gtkcelllayout.h"
28 #include "gtkcellrenderertext.h"
30 #include "gtktreeselection.h"
31 #include "gtktreeview.h"
32 #include "gtkscrolledwindow.h"
33 #include "gtksizerequest.h"
35 #include "gtkwindow.h"
38 #include "gtkmarshalers.h"
40 #include "gtkprivate.h"
60 PROP_MINIMUM_KEY_LENGTH,
62 PROP_INLINE_COMPLETION,
63 PROP_POPUP_COMPLETION,
65 PROP_POPUP_SINGLE_MATCH,
70 static void gtk_entry_completion_cell_layout_init (GtkCellLayoutIface *iface);
71 static void gtk_entry_completion_set_property (GObject *object,
75 static void gtk_entry_completion_get_property (GObject *object,
79 static void gtk_entry_completion_finalize (GObject *object);
81 static void gtk_entry_completion_pack_start (GtkCellLayout *cell_layout,
82 GtkCellRenderer *cell,
84 static void gtk_entry_completion_pack_end (GtkCellLayout *cell_layout,
85 GtkCellRenderer *cell,
87 static void gtk_entry_completion_clear (GtkCellLayout *cell_layout);
88 static void gtk_entry_completion_add_attribute (GtkCellLayout *cell_layout,
89 GtkCellRenderer *cell,
90 const char *attribute,
92 static void gtk_entry_completion_set_cell_data_func (GtkCellLayout *cell_layout,
93 GtkCellRenderer *cell,
94 GtkCellLayoutDataFunc func,
96 GDestroyNotify destroy);
97 static void gtk_entry_completion_clear_attributes (GtkCellLayout *cell_layout,
98 GtkCellRenderer *cell);
99 static void gtk_entry_completion_reorder (GtkCellLayout *cell_layout,
100 GtkCellRenderer *cell,
102 static GList * gtk_entry_completion_get_cells (GtkCellLayout *cell_layout);
104 static gboolean gtk_entry_completion_visible_func (GtkTreeModel *model,
107 static gboolean gtk_entry_completion_popup_key_event (GtkWidget *widget,
110 static gboolean gtk_entry_completion_popup_button_press (GtkWidget *widget,
111 GdkEventButton *event,
113 static gboolean gtk_entry_completion_list_button_press (GtkWidget *widget,
114 GdkEventButton *event,
116 static gboolean gtk_entry_completion_action_button_press (GtkWidget *widget,
117 GdkEventButton *event,
119 static void gtk_entry_completion_selection_changed (GtkTreeSelection *selection,
121 static gboolean gtk_entry_completion_list_enter_notify (GtkWidget *widget,
122 GdkEventCrossing *event,
124 static gboolean gtk_entry_completion_list_motion_notify (GtkWidget *widget,
125 GdkEventMotion *event,
127 static void gtk_entry_completion_insert_action (GtkEntryCompletion *completion,
131 static void gtk_entry_completion_action_data_func (GtkTreeViewColumn *tree_column,
132 GtkCellRenderer *cell,
137 static gboolean gtk_entry_completion_match_selected (GtkEntryCompletion *completion,
140 static gboolean gtk_entry_completion_real_insert_prefix (GtkEntryCompletion *completion,
141 const gchar *prefix);
142 static gboolean gtk_entry_completion_cursor_on_match (GtkEntryCompletion *completion,
145 static gboolean gtk_entry_completion_insert_completion (GtkEntryCompletion *completion,
148 static void gtk_entry_completion_insert_completion_text (GtkEntryCompletion *completion,
151 static guint entry_completion_signals[LAST_SIGNAL] = { 0 };
154 static void gtk_entry_completion_buildable_init (GtkBuildableIface *iface);
156 G_DEFINE_TYPE_WITH_CODE (GtkEntryCompletion, gtk_entry_completion, G_TYPE_OBJECT,
157 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
158 gtk_entry_completion_cell_layout_init)
159 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
160 gtk_entry_completion_buildable_init))
164 gtk_entry_completion_class_init (GtkEntryCompletionClass *klass)
166 GObjectClass *object_class;
168 object_class = (GObjectClass *)klass;
170 object_class->set_property = gtk_entry_completion_set_property;
171 object_class->get_property = gtk_entry_completion_get_property;
172 object_class->finalize = gtk_entry_completion_finalize;
174 klass->match_selected = gtk_entry_completion_match_selected;
175 klass->insert_prefix = gtk_entry_completion_real_insert_prefix;
176 klass->cursor_on_match = gtk_entry_completion_cursor_on_match;
179 * GtkEntryCompletion::insert-prefix:
180 * @widget: the object which received the signal
181 * @prefix: the common prefix of all possible completions
183 * Gets emitted when the inline autocompletion is triggered.
184 * The default behaviour is to make the entry display the
185 * whole prefix and select the newly inserted part.
187 * Applications may connect to this signal in order to insert only a
188 * smaller part of the @prefix into the entry - e.g. the entry used in
189 * the #GtkFileChooser inserts only the part of the prefix up to the
192 * Return value: %TRUE if the signal has been handled
196 entry_completion_signals[INSERT_PREFIX] =
197 g_signal_new (I_("insert-prefix"),
198 G_TYPE_FROM_CLASS (klass),
200 G_STRUCT_OFFSET (GtkEntryCompletionClass, insert_prefix),
201 _gtk_boolean_handled_accumulator, NULL,
202 _gtk_marshal_BOOLEAN__STRING,
207 * GtkEntryCompletion::match-selected:
208 * @widget: the object which received the signal
209 * @model: the #GtkTreeModel containing the matches
210 * @iter: a #GtkTreeIter positioned at the selected match
212 * Gets emitted when a match from the list is selected.
213 * The default behaviour is to replace the contents of the
214 * entry with the contents of the text column in the row
215 * pointed to by @iter.
217 * Return value: %TRUE if the signal has been handled
221 entry_completion_signals[MATCH_SELECTED] =
222 g_signal_new (I_("match-selected"),
223 G_TYPE_FROM_CLASS (klass),
225 G_STRUCT_OFFSET (GtkEntryCompletionClass, match_selected),
226 _gtk_boolean_handled_accumulator, NULL,
227 _gtk_marshal_BOOLEAN__OBJECT_BOXED,
233 * GtkEntryCompletion::cursor-on-match:
234 * @widget: the object which received the signal
235 * @model: the #GtkTreeModel containing the matches
236 * @iter: a #GtkTreeIter positioned at the selected match
238 * Gets emitted when a match from the cursor is on a match
239 * of the list. The default behaviour is to replace the contents
240 * of the entry with the contents of the text column in the row
241 * pointed to by @iter.
243 * Return value: %TRUE if the signal has been handled
247 entry_completion_signals[CURSOR_ON_MATCH] =
248 g_signal_new (I_("cursor-on-match"),
249 G_TYPE_FROM_CLASS (klass),
251 G_STRUCT_OFFSET (GtkEntryCompletionClass, cursor_on_match),
252 _gtk_boolean_handled_accumulator, NULL,
253 _gtk_marshal_BOOLEAN__OBJECT_BOXED,
259 * GtkEntryCompletion::action-activated:
260 * @widget: the object which received the signal
261 * @index: the index of the activated action
263 * Gets emitted when an action is activated.
267 entry_completion_signals[ACTION_ACTIVATED] =
268 g_signal_new (I_("action-activated"),
269 G_TYPE_FROM_CLASS (klass),
271 G_STRUCT_OFFSET (GtkEntryCompletionClass, action_activated),
273 _gtk_marshal_VOID__INT,
277 g_object_class_install_property (object_class,
279 g_param_spec_object ("model",
280 P_("Completion Model"),
281 P_("The model to find matches in"),
283 GTK_PARAM_READWRITE));
284 g_object_class_install_property (object_class,
285 PROP_MINIMUM_KEY_LENGTH,
286 g_param_spec_int ("minimum-key-length",
287 P_("Minimum Key Length"),
288 P_("Minimum length of the search key in order to look up matches"),
292 GTK_PARAM_READWRITE));
294 * GtkEntryCompletion:text-column:
296 * The column of the model containing the strings.
297 * Note that the strings must be UTF-8.
301 g_object_class_install_property (object_class,
303 g_param_spec_int ("text-column",
305 P_("The column of the model containing the strings."),
309 GTK_PARAM_READWRITE));
312 * GtkEntryCompletion:inline-completion:
314 * Determines whether the common prefix of the possible completions
315 * should be inserted automatically in the entry. Note that this
316 * requires text-column to be set, even if you are using a custom
321 g_object_class_install_property (object_class,
322 PROP_INLINE_COMPLETION,
323 g_param_spec_boolean ("inline-completion",
324 P_("Inline completion"),
325 P_("Whether the common prefix should be inserted automatically"),
327 GTK_PARAM_READWRITE));
329 * GtkEntryCompletion:popup-completion:
331 * Determines whether the possible completions should be
332 * shown in a popup window.
336 g_object_class_install_property (object_class,
337 PROP_POPUP_COMPLETION,
338 g_param_spec_boolean ("popup-completion",
339 P_("Popup completion"),
340 P_("Whether the completions should be shown in a popup window"),
342 GTK_PARAM_READWRITE));
345 * GtkEntryCompletion:popup-set-width:
347 * Determines whether the completions popup window will be
348 * resized to the width of the entry.
352 g_object_class_install_property (object_class,
353 PROP_POPUP_SET_WIDTH,
354 g_param_spec_boolean ("popup-set-width",
355 P_("Popup set width"),
356 P_("If TRUE, the popup window will have the same size as the entry"),
358 GTK_PARAM_READWRITE));
361 * GtkEntryCompletion:popup-single-match:
363 * Determines whether the completions popup window will shown
364 * for a single possible completion. You probably want to set
365 * this to %FALSE if you are using
366 * <link linkend="GtkEntryCompletion--inline-completion">inline
371 g_object_class_install_property (object_class,
372 PROP_POPUP_SINGLE_MATCH,
373 g_param_spec_boolean ("popup-single-match",
374 P_("Popup single match"),
375 P_("If TRUE, the popup window will appear for a single match."),
377 GTK_PARAM_READWRITE));
379 * GtkEntryCompletion:inline-selection:
381 * Determines whether the possible completions on the popup
382 * will appear in the entry as you navigate through them.
386 g_object_class_install_property (object_class,
387 PROP_INLINE_SELECTION,
388 g_param_spec_boolean ("inline-selection",
389 P_("Inline selection"),
390 P_("Your description here"),
392 GTK_PARAM_READWRITE));
394 g_type_class_add_private (object_class, sizeof (GtkEntryCompletionPrivate));
398 gtk_entry_completion_buildable_init (GtkBuildableIface *iface)
400 iface->add_child = _gtk_cell_layout_buildable_add_child;
401 iface->custom_tag_start = _gtk_cell_layout_buildable_custom_tag_start;
402 iface->custom_tag_end = _gtk_cell_layout_buildable_custom_tag_end;
406 gtk_entry_completion_cell_layout_init (GtkCellLayoutIface *iface)
408 iface->pack_start = gtk_entry_completion_pack_start;
409 iface->pack_end = gtk_entry_completion_pack_end;
410 iface->clear = gtk_entry_completion_clear;
411 iface->add_attribute = gtk_entry_completion_add_attribute;
412 iface->set_cell_data_func = gtk_entry_completion_set_cell_data_func;
413 iface->clear_attributes = gtk_entry_completion_clear_attributes;
414 iface->reorder = gtk_entry_completion_reorder;
415 iface->get_cells = gtk_entry_completion_get_cells;
419 gtk_entry_completion_init (GtkEntryCompletion *completion)
421 GtkCellRenderer *cell;
422 GtkTreeSelection *sel;
423 GtkEntryCompletionPrivate *priv;
424 GtkWidget *popup_frame;
426 /* yes, also priv, need to keep the code readable */
427 completion->priv = G_TYPE_INSTANCE_GET_PRIVATE (completion,
428 GTK_TYPE_ENTRY_COMPLETION,
429 GtkEntryCompletionPrivate);
430 priv = completion->priv;
432 priv->minimum_key_length = 1;
433 priv->text_column = -1;
434 priv->has_completion = FALSE;
435 priv->inline_completion = FALSE;
436 priv->popup_completion = TRUE;
437 priv->popup_set_width = TRUE;
438 priv->popup_single_match = TRUE;
439 priv->inline_selection = FALSE;
442 priv->filter_model = NULL;
444 priv->tree_view = gtk_tree_view_new ();
445 g_signal_connect (priv->tree_view, "button-press-event",
446 G_CALLBACK (gtk_entry_completion_list_button_press),
448 g_signal_connect (priv->tree_view, "enter-notify-event",
449 G_CALLBACK (gtk_entry_completion_list_enter_notify),
451 g_signal_connect (priv->tree_view, "motion-notify-event",
452 G_CALLBACK (gtk_entry_completion_list_motion_notify),
455 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), FALSE);
456 gtk_tree_view_set_hover_selection (GTK_TREE_VIEW (priv->tree_view), TRUE);
458 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
459 gtk_tree_selection_set_mode (sel, GTK_SELECTION_SINGLE);
460 gtk_tree_selection_unselect_all (sel);
461 g_signal_connect (sel, "changed",
462 G_CALLBACK (gtk_entry_completion_selection_changed),
464 priv->first_sel_changed = TRUE;
466 priv->column = gtk_tree_view_column_new ();
467 gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree_view), priv->column);
469 priv->scrolled_window = gtk_scrolled_window_new (NULL, NULL);
470 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scrolled_window),
472 GTK_POLICY_AUTOMATIC);
473 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scrolled_window),
476 /* a nasty hack to get the completions treeview to size nicely */
477 gtk_widget_set_size_request (gtk_scrolled_window_get_vscrollbar (GTK_SCROLLED_WINDOW (priv->scrolled_window)),
481 priv->actions = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
484 gtk_tree_view_new_with_model (GTK_TREE_MODEL (priv->actions));
485 g_object_ref_sink (priv->action_view);
486 g_signal_connect (priv->action_view, "button-press-event",
487 G_CALLBACK (gtk_entry_completion_action_button_press),
489 g_signal_connect (priv->action_view, "enter-notify-event",
490 G_CALLBACK (gtk_entry_completion_list_enter_notify),
492 g_signal_connect (priv->action_view, "motion-notify-event",
493 G_CALLBACK (gtk_entry_completion_list_motion_notify),
495 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->action_view), FALSE);
496 gtk_tree_view_set_hover_selection (GTK_TREE_VIEW (priv->action_view), TRUE);
498 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->action_view));
499 gtk_tree_selection_set_mode (sel, GTK_SELECTION_SINGLE);
500 gtk_tree_selection_unselect_all (sel);
502 cell = gtk_cell_renderer_text_new ();
503 gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (priv->action_view),
506 gtk_entry_completion_action_data_func,
511 priv->popup_window = gtk_window_new (GTK_WINDOW_POPUP);
512 gtk_window_set_resizable (GTK_WINDOW (priv->popup_window), FALSE);
513 gtk_window_set_type_hint (GTK_WINDOW(priv->popup_window),
514 GDK_WINDOW_TYPE_HINT_COMBO);
515 g_signal_connect (priv->popup_window, "key-press-event",
516 G_CALLBACK (gtk_entry_completion_popup_key_event),
518 g_signal_connect (priv->popup_window, "key-release-event",
519 G_CALLBACK (gtk_entry_completion_popup_key_event),
521 g_signal_connect (priv->popup_window, "button-press-event",
522 G_CALLBACK (gtk_entry_completion_popup_button_press),
525 popup_frame = gtk_frame_new (NULL);
526 gtk_frame_set_shadow_type (GTK_FRAME (popup_frame),
527 GTK_SHADOW_ETCHED_IN);
528 gtk_widget_show (popup_frame);
529 gtk_container_add (GTK_CONTAINER (priv->popup_window), popup_frame);
531 priv->vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
532 gtk_container_add (GTK_CONTAINER (popup_frame), priv->vbox);
534 gtk_container_add (GTK_CONTAINER (priv->scrolled_window), priv->tree_view);
535 gtk_box_pack_start (GTK_BOX (priv->vbox), priv->scrolled_window,
538 /* we don't want to see the action treeview when no actions have
539 * been inserted, so we pack the action treeview after the first
540 * action has been added
545 gtk_entry_completion_set_property (GObject *object,
550 GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (object);
551 GtkEntryCompletionPrivate *priv = completion->priv;
556 gtk_entry_completion_set_model (completion,
557 g_value_get_object (value));
560 case PROP_MINIMUM_KEY_LENGTH:
561 gtk_entry_completion_set_minimum_key_length (completion,
562 g_value_get_int (value));
565 case PROP_TEXT_COLUMN:
566 priv->text_column = g_value_get_int (value);
569 case PROP_INLINE_COMPLETION:
570 priv->inline_completion = g_value_get_boolean (value);
573 case PROP_POPUP_COMPLETION:
574 priv->popup_completion = g_value_get_boolean (value);
577 case PROP_POPUP_SET_WIDTH:
578 priv->popup_set_width = g_value_get_boolean (value);
581 case PROP_POPUP_SINGLE_MATCH:
582 priv->popup_single_match = g_value_get_boolean (value);
585 case PROP_INLINE_SELECTION:
586 priv->inline_selection = g_value_get_boolean (value);
590 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
596 gtk_entry_completion_get_property (GObject *object,
601 GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (object);
606 g_value_set_object (value,
607 gtk_entry_completion_get_model (completion));
610 case PROP_MINIMUM_KEY_LENGTH:
611 g_value_set_int (value, gtk_entry_completion_get_minimum_key_length (completion));
614 case PROP_TEXT_COLUMN:
615 g_value_set_int (value, gtk_entry_completion_get_text_column (completion));
618 case PROP_INLINE_COMPLETION:
619 g_value_set_boolean (value, gtk_entry_completion_get_inline_completion (completion));
622 case PROP_POPUP_COMPLETION:
623 g_value_set_boolean (value, gtk_entry_completion_get_popup_completion (completion));
626 case PROP_POPUP_SET_WIDTH:
627 g_value_set_boolean (value, gtk_entry_completion_get_popup_set_width (completion));
630 case PROP_POPUP_SINGLE_MATCH:
631 g_value_set_boolean (value, gtk_entry_completion_get_popup_single_match (completion));
634 case PROP_INLINE_SELECTION:
635 g_value_set_boolean (value, gtk_entry_completion_get_inline_selection (completion));
639 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
645 gtk_entry_completion_finalize (GObject *object)
647 GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (object);
648 GtkEntryCompletionPrivate *priv = completion->priv;
651 gtk_widget_destroy (priv->tree_view);
654 gtk_entry_set_completion (GTK_ENTRY (priv->entry), NULL);
657 g_object_unref (priv->actions);
658 if (priv->action_view)
659 g_object_unref (priv->action_view);
661 g_free (priv->case_normalized_key);
662 g_free (priv->completion_prefix);
664 if (priv->popup_window)
665 gtk_widget_destroy (priv->popup_window);
667 if (priv->match_notify)
668 (* priv->match_notify) (priv->match_data);
670 G_OBJECT_CLASS (gtk_entry_completion_parent_class)->finalize (object);
673 /* implement cell layout interface */
675 gtk_entry_completion_pack_start (GtkCellLayout *cell_layout,
676 GtkCellRenderer *cell,
679 GtkEntryCompletionPrivate *priv;
681 priv = GTK_ENTRY_COMPLETION (cell_layout)->priv;
683 gtk_tree_view_column_pack_start (priv->column, cell, expand);
687 gtk_entry_completion_pack_end (GtkCellLayout *cell_layout,
688 GtkCellRenderer *cell,
691 GtkEntryCompletionPrivate *priv;
693 priv = GTK_ENTRY_COMPLETION (cell_layout)->priv;
695 gtk_tree_view_column_pack_end (priv->column, cell, expand);
699 gtk_entry_completion_clear (GtkCellLayout *cell_layout)
701 GtkEntryCompletionPrivate *priv;
703 priv = GTK_ENTRY_COMPLETION (cell_layout)->priv;
705 gtk_tree_view_column_clear (priv->column);
709 gtk_entry_completion_add_attribute (GtkCellLayout *cell_layout,
710 GtkCellRenderer *cell,
711 const gchar *attribute,
714 GtkEntryCompletionPrivate *priv;
716 priv = GTK_ENTRY_COMPLETION (cell_layout)->priv;
718 gtk_tree_view_column_add_attribute (priv->column, cell, attribute, column);
722 gtk_entry_completion_set_cell_data_func (GtkCellLayout *cell_layout,
723 GtkCellRenderer *cell,
724 GtkCellLayoutDataFunc func,
726 GDestroyNotify destroy)
728 GtkEntryCompletionPrivate *priv;
730 priv = GTK_ENTRY_COMPLETION (cell_layout)->priv;
732 gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (priv->column),
733 cell, func, func_data, destroy);
737 gtk_entry_completion_clear_attributes (GtkCellLayout *cell_layout,
738 GtkCellRenderer *cell)
740 GtkEntryCompletionPrivate *priv;
742 priv = GTK_ENTRY_COMPLETION (cell_layout)->priv;
744 gtk_tree_view_column_clear_attributes (priv->column, cell);
748 gtk_entry_completion_reorder (GtkCellLayout *cell_layout,
749 GtkCellRenderer *cell,
752 GtkEntryCompletionPrivate *priv;
754 priv = GTK_ENTRY_COMPLETION (cell_layout)->priv;
756 gtk_cell_layout_reorder (GTK_CELL_LAYOUT (priv->column), cell, position);
760 gtk_entry_completion_get_cells (GtkCellLayout *cell_layout)
762 GtkEntryCompletionPrivate *priv;
764 priv = GTK_ENTRY_COMPLETION (cell_layout)->priv;
766 return gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (priv->column));
769 /* all those callbacks */
771 gtk_entry_completion_default_completion_func (GtkEntryCompletion *completion,
777 gchar *normalized_string;
778 gchar *case_normalized_string;
780 gboolean ret = FALSE;
784 model = gtk_tree_model_filter_get_model (completion->priv->filter_model);
786 g_return_val_if_fail (gtk_tree_model_get_column_type (model, completion->priv->text_column) == G_TYPE_STRING,
789 gtk_tree_model_get (model, iter,
790 completion->priv->text_column, &item,
795 normalized_string = g_utf8_normalize (item, -1, G_NORMALIZE_ALL);
797 if (normalized_string != NULL)
799 case_normalized_string = g_utf8_casefold (normalized_string, -1);
801 if (!strncmp (key, case_normalized_string, strlen (key)))
804 g_free (case_normalized_string);
806 g_free (normalized_string);
814 gtk_entry_completion_visible_func (GtkTreeModel *model,
818 gboolean ret = FALSE;
820 GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (data);
822 if (!completion->priv->case_normalized_key)
825 if (completion->priv->match_func)
826 ret = (* completion->priv->match_func) (completion,
827 completion->priv->case_normalized_key,
829 completion->priv->match_data);
830 else if (completion->priv->text_column >= 0)
831 ret = gtk_entry_completion_default_completion_func (completion,
832 completion->priv->case_normalized_key,
840 gtk_entry_completion_popup_key_event (GtkWidget *widget,
844 GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (user_data);
846 if (!gtk_widget_get_mapped (completion->priv->popup_window))
849 /* propagate event to the entry */
850 gtk_widget_event (completion->priv->entry, (GdkEvent *)event);
856 gtk_entry_completion_popup_button_press (GtkWidget *widget,
857 GdkEventButton *event,
860 GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (user_data);
862 if (!gtk_widget_get_mapped (completion->priv->popup_window))
865 /* if we come here, it's usually time to popdown */
866 _gtk_entry_completion_popdown (completion);
872 gtk_entry_completion_list_button_press (GtkWidget *widget,
873 GdkEventButton *event,
876 GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (user_data);
877 GtkTreePath *path = NULL;
879 if (!gtk_widget_get_mapped (completion->priv->popup_window))
882 if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget),
884 &path, NULL, NULL, NULL))
889 GtkTreeIter child_iter;
891 gtk_tree_model_get_iter (GTK_TREE_MODEL (completion->priv->filter_model),
893 gtk_tree_path_free (path);
894 gtk_tree_model_filter_convert_iter_to_child_iter (completion->priv->filter_model,
897 model = gtk_tree_model_filter_get_model (completion->priv->filter_model);
899 g_signal_handler_block (completion->priv->entry,
900 completion->priv->changed_id);
901 g_signal_emit (completion, entry_completion_signals[MATCH_SELECTED],
902 0, model, &child_iter, &entry_set);
903 g_signal_handler_unblock (completion->priv->entry,
904 completion->priv->changed_id);
906 _gtk_entry_completion_popdown (completion);
915 gtk_entry_completion_action_button_press (GtkWidget *widget,
916 GdkEventButton *event,
919 GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (user_data);
920 GtkTreePath *path = NULL;
922 if (!gtk_widget_get_mapped (completion->priv->popup_window))
925 _gtk_entry_reset_im_context (GTK_ENTRY (completion->priv->entry));
927 if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget),
929 &path, NULL, NULL, NULL))
931 g_signal_emit (completion, entry_completion_signals[ACTION_ACTIVATED],
932 0, gtk_tree_path_get_indices (path)[0]);
933 gtk_tree_path_free (path);
935 _gtk_entry_completion_popdown (completion);
943 gtk_entry_completion_action_data_func (GtkTreeViewColumn *tree_column,
944 GtkCellRenderer *cell,
949 gchar *string = NULL;
952 gtk_tree_model_get (model, iter,
975 gtk_entry_completion_selection_changed (GtkTreeSelection *selection,
978 GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (data);
980 if (completion->priv->first_sel_changed)
982 completion->priv->first_sel_changed = FALSE;
983 if (gtk_widget_is_focus (completion->priv->tree_view))
984 gtk_tree_selection_unselect_all (selection);
991 * gtk_entry_completion_new:
993 * Creates a new #GtkEntryCompletion object.
995 * Return value: A newly created #GtkEntryCompletion object.
1000 gtk_entry_completion_new (void)
1002 GtkEntryCompletion *completion;
1004 completion = g_object_new (GTK_TYPE_ENTRY_COMPLETION, NULL);
1010 * gtk_entry_completion_get_entry:
1011 * @completion: A #GtkEntryCompletion.
1013 * Gets the entry @completion has been attached to.
1015 * Return value: (transfer none): The entry @completion has been attached to.
1020 gtk_entry_completion_get_entry (GtkEntryCompletion *completion)
1022 g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), NULL);
1024 return completion->priv->entry;
1028 * gtk_entry_completion_set_model:
1029 * @completion: A #GtkEntryCompletion.
1030 * @model: (allow-none): The #GtkTreeModel.
1032 * Sets the model for a #GtkEntryCompletion. If @completion already has
1033 * a model set, it will remove it before setting the new model.
1034 * If model is %NULL, then it will unset the model.
1039 gtk_entry_completion_set_model (GtkEntryCompletion *completion,
1040 GtkTreeModel *model)
1042 g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1043 g_return_if_fail (model == NULL || GTK_IS_TREE_MODEL (model));
1047 gtk_tree_view_set_model (GTK_TREE_VIEW (completion->priv->tree_view),
1049 _gtk_entry_completion_popdown (completion);
1050 completion->priv->filter_model = NULL;
1054 /* code will unref the old filter model (if any) */
1055 completion->priv->filter_model =
1056 GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (model, NULL));
1057 gtk_tree_model_filter_set_visible_func (completion->priv->filter_model,
1058 gtk_entry_completion_visible_func,
1062 gtk_tree_view_set_model (GTK_TREE_VIEW (completion->priv->tree_view),
1063 GTK_TREE_MODEL (completion->priv->filter_model));
1064 g_object_unref (completion->priv->filter_model);
1066 g_object_notify (G_OBJECT (completion), "model");
1068 if (gtk_widget_get_visible (completion->priv->popup_window))
1069 _gtk_entry_completion_resize_popup (completion);
1073 * gtk_entry_completion_get_model:
1074 * @completion: A #GtkEntryCompletion.
1076 * Returns the model the #GtkEntryCompletion is using as data source.
1077 * Returns %NULL if the model is unset.
1079 * Return value: (transfer none): A #GtkTreeModel, or %NULL if none
1080 * is currently being used.
1085 gtk_entry_completion_get_model (GtkEntryCompletion *completion)
1087 g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), NULL);
1089 if (!completion->priv->filter_model)
1092 return gtk_tree_model_filter_get_model (completion->priv->filter_model);
1096 * gtk_entry_completion_set_match_func:
1097 * @completion: A #GtkEntryCompletion.
1098 * @func: The #GtkEntryCompletionMatchFunc to use.
1099 * @func_data: The user data for @func.
1100 * @func_notify: Destroy notifier for @func_data.
1102 * Sets the match function for @completion to be @func. The match function
1103 * is used to determine if a row should or should not be in the completion
1109 gtk_entry_completion_set_match_func (GtkEntryCompletion *completion,
1110 GtkEntryCompletionMatchFunc func,
1112 GDestroyNotify func_notify)
1114 g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1116 if (completion->priv->match_notify)
1117 (* completion->priv->match_notify) (completion->priv->match_data);
1119 completion->priv->match_func = func;
1120 completion->priv->match_data = func_data;
1121 completion->priv->match_notify = func_notify;
1125 * gtk_entry_completion_set_minimum_key_length:
1126 * @completion: A #GtkEntryCompletion.
1127 * @length: The minimum length of the key in order to start completing.
1129 * Requires the length of the search key for @completion to be at least
1130 * @length. This is useful for long lists, where completing using a small
1131 * key takes a lot of time and will come up with meaningless results anyway
1132 * (ie, a too large dataset).
1137 gtk_entry_completion_set_minimum_key_length (GtkEntryCompletion *completion,
1140 g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1141 g_return_if_fail (length >= 0);
1143 if (completion->priv->minimum_key_length != length)
1145 completion->priv->minimum_key_length = length;
1147 g_object_notify (G_OBJECT (completion), "minimum-key-length");
1152 * gtk_entry_completion_get_minimum_key_length:
1153 * @completion: A #GtkEntryCompletion.
1155 * Returns the minimum key length as set for @completion.
1157 * Return value: The currently used minimum key length.
1162 gtk_entry_completion_get_minimum_key_length (GtkEntryCompletion *completion)
1164 g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), 0);
1166 return completion->priv->minimum_key_length;
1170 * gtk_entry_completion_complete:
1171 * @completion: A #GtkEntryCompletion.
1173 * Requests a completion operation, or in other words a refiltering of the
1174 * current list with completions, using the current key. The completion list
1175 * view will be updated accordingly.
1180 gtk_entry_completion_complete (GtkEntryCompletion *completion)
1184 g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1186 if (!completion->priv->filter_model)
1189 g_free (completion->priv->case_normalized_key);
1191 tmp = g_utf8_normalize (gtk_entry_get_text (GTK_ENTRY (completion->priv->entry)),
1192 -1, G_NORMALIZE_ALL);
1193 completion->priv->case_normalized_key = g_utf8_casefold (tmp, -1);
1196 gtk_tree_model_filter_refilter (completion->priv->filter_model);
1198 if (gtk_widget_get_visible (completion->priv->popup_window))
1199 _gtk_entry_completion_resize_popup (completion);
1203 gtk_entry_completion_insert_action (GtkEntryCompletion *completion,
1205 const gchar *string,
1210 gtk_list_store_insert (completion->priv->actions, &iter, index);
1211 gtk_list_store_set (completion->priv->actions, &iter,
1216 if (!gtk_widget_get_parent (completion->priv->action_view))
1218 GtkTreePath *path = gtk_tree_path_new_from_indices (0, -1);
1220 gtk_tree_view_set_cursor (GTK_TREE_VIEW (completion->priv->action_view),
1222 gtk_tree_path_free (path);
1224 gtk_box_pack_start (GTK_BOX (completion->priv->vbox),
1225 completion->priv->action_view, FALSE, FALSE, 0);
1226 gtk_widget_show (completion->priv->action_view);
1231 * gtk_entry_completion_insert_action_text:
1232 * @completion: A #GtkEntryCompletion.
1233 * @index_: The index of the item to insert.
1234 * @text: Text of the item to insert.
1236 * Inserts an action in @completion's action item list at position @index_
1237 * with text @text. If you want the action item to have markup, use
1238 * gtk_entry_completion_insert_action_markup().
1243 gtk_entry_completion_insert_action_text (GtkEntryCompletion *completion,
1247 g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1248 g_return_if_fail (text != NULL);
1250 gtk_entry_completion_insert_action (completion, index_, text, FALSE);
1254 * gtk_entry_completion_insert_action_markup:
1255 * @completion: A #GtkEntryCompletion.
1256 * @index_: The index of the item to insert.
1257 * @markup: Markup of the item to insert.
1259 * Inserts an action in @completion's action item list at position @index_
1260 * with markup @markup.
1265 gtk_entry_completion_insert_action_markup (GtkEntryCompletion *completion,
1267 const gchar *markup)
1269 g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1270 g_return_if_fail (markup != NULL);
1272 gtk_entry_completion_insert_action (completion, index_, markup, TRUE);
1276 * gtk_entry_completion_delete_action:
1277 * @completion: A #GtkEntryCompletion.
1278 * @index_: The index of the item to Delete.
1280 * Deletes the action at @index_ from @completion's action list.
1285 gtk_entry_completion_delete_action (GtkEntryCompletion *completion,
1290 g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1291 g_return_if_fail (index_ >= 0);
1293 gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (completion->priv->actions),
1294 &iter, NULL, index_);
1295 gtk_list_store_remove (completion->priv->actions, &iter);
1299 * gtk_entry_completion_set_text_column:
1300 * @completion: A #GtkEntryCompletion.
1301 * @column: The column in the model of @completion to get strings from.
1303 * Convenience function for setting up the most used case of this code: a
1304 * completion list with just strings. This function will set up @completion
1305 * to have a list displaying all (and just) strings in the completion list,
1306 * and to get those strings from @column in the model of @completion.
1308 * This functions creates and adds a #GtkCellRendererText for the selected
1309 * column. If you need to set the text column, but don't want the cell
1310 * renderer, use g_object_set() to set the ::text_column property directly.
1315 gtk_entry_completion_set_text_column (GtkEntryCompletion *completion,
1318 GtkCellRenderer *cell;
1320 g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1321 g_return_if_fail (column >= 0);
1323 completion->priv->text_column = column;
1325 cell = gtk_cell_renderer_text_new ();
1326 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion),
1328 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (completion),
1332 g_object_notify (G_OBJECT (completion), "text-column");
1336 * gtk_entry_completion_get_text_column:
1337 * @completion: a #GtkEntryCompletion
1339 * Returns the column in the model of @completion to get strings from.
1341 * Return value: the column containing the strings
1346 gtk_entry_completion_get_text_column (GtkEntryCompletion *completion)
1348 g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), -1);
1350 return completion->priv->text_column;
1356 gtk_entry_completion_list_enter_notify (GtkWidget *widget,
1357 GdkEventCrossing *event,
1360 GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (data);
1362 return completion->priv->ignore_enter;
1366 gtk_entry_completion_list_motion_notify (GtkWidget *widget,
1367 GdkEventMotion *event,
1370 GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (data);
1372 completion->priv->ignore_enter = FALSE;
1378 /* some nasty size requisition */
1380 _gtk_entry_completion_resize_popup (GtkEntryCompletion *completion)
1382 GtkAllocation allocation;
1384 gint matches, actions, items, height, x_border, y_border;
1387 gint vertical_separator;
1388 GdkRectangle monitor;
1390 GtkRequisition popup_req;
1391 GtkRequisition entry_req;
1395 GtkTreeViewColumn *action_column;
1398 window = gtk_widget_get_window (completion->priv->entry);
1403 gtk_widget_get_allocation (completion->priv->entry, &allocation);
1404 gtk_widget_get_preferred_size (completion->priv->entry,
1407 gdk_window_get_origin (window, &x, &y);
1409 y += allocation.y + (allocation.height - entry_req.height) / 2;
1411 _gtk_entry_get_borders (GTK_ENTRY (completion->priv->entry), &x_border, &y_border);
1413 matches = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (completion->priv->filter_model), NULL);
1414 actions = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (completion->priv->actions), NULL);
1415 action_column = gtk_tree_view_get_column (GTK_TREE_VIEW (completion->priv->action_view), 0);
1417 gtk_tree_view_column_cell_get_size (completion->priv->column, NULL,
1418 NULL, NULL, NULL, &height);
1419 gtk_tree_view_column_cell_get_size (action_column, NULL,
1420 NULL, NULL, NULL, &action_height);
1422 gtk_widget_style_get (GTK_WIDGET (completion->priv->tree_view),
1423 "vertical-separator", &vertical_separator,
1426 height += vertical_separator;
1428 gtk_widget_realize (completion->priv->tree_view);
1430 screen = gtk_widget_get_screen (GTK_WIDGET (completion->priv->entry));
1431 monitor_num = gdk_screen_get_monitor_at_window (screen, window);
1432 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
1436 if (y > monitor.height / 2)
1437 items = MIN (matches, (((monitor.y + y) - (actions * action_height)) / height) - 1);
1439 items = MIN (matches, (((monitor.height - y) - (actions * action_height)) / height) - 1);
1442 gtk_widget_hide (completion->priv->scrolled_window);
1444 gtk_widget_show (completion->priv->scrolled_window);
1446 if (completion->priv->popup_set_width)
1447 width = MIN (allocation.width, monitor.width) - 2 * x_border;
1451 gtk_tree_view_columns_autosize (GTK_TREE_VIEW (completion->priv->tree_view));
1452 gtk_widget_set_size_request (completion->priv->tree_view, width, items * height);
1456 gtk_widget_show (completion->priv->action_view);
1457 gtk_widget_set_size_request (completion->priv->action_view, width, -1);
1460 gtk_widget_hide (completion->priv->action_view);
1462 gtk_widget_get_preferred_size (completion->priv->popup_window,
1467 else if (x + popup_req.width > monitor.x + monitor.width)
1468 x = monitor.x + monitor.width - popup_req.width;
1470 if (y + entry_req.height + popup_req.height <= monitor.y + monitor.height ||
1471 y - monitor.y < (monitor.y + monitor.height) - (y + entry_req.height))
1473 y += entry_req.height;
1478 y -= popup_req.height;
1484 path = gtk_tree_path_new_from_indices (above ? matches - 1 : 0, -1);
1485 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (completion->priv->tree_view), path,
1486 NULL, FALSE, 0.0, 0.0);
1487 gtk_tree_path_free (path);
1490 gtk_window_move (GTK_WINDOW (completion->priv->popup_window), x, y);
1496 _gtk_entry_completion_popup (GtkEntryCompletion *completion,
1499 GtkTreeViewColumn *column;
1501 GtkWidget *toplevel;
1503 if (gtk_widget_get_mapped (completion->priv->popup_window))
1506 if (!gtk_widget_get_mapped (completion->priv->entry))
1509 if (!gtk_widget_has_focus (completion->priv->entry))
1512 if (completion->priv->grab_device)
1515 completion->priv->ignore_enter = TRUE;
1517 column = gtk_tree_view_get_column (GTK_TREE_VIEW (completion->priv->action_view), 0);
1518 renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
1519 gtk_widget_ensure_style (completion->priv->tree_view);
1520 g_object_set (GTK_CELL_RENDERER (renderers->data), "cell-background-gdk",
1521 >k_widget_get_style (completion->priv->tree_view)->bg[GTK_STATE_NORMAL],
1523 g_list_free (renderers);
1525 gtk_widget_show_all (completion->priv->vbox);
1527 /* default on no match */
1528 completion->priv->current_selected = -1;
1530 _gtk_entry_completion_resize_popup (completion);
1532 toplevel = gtk_widget_get_toplevel (completion->priv->entry);
1533 if (GTK_IS_WINDOW (toplevel))
1534 gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (toplevel)),
1535 GTK_WINDOW (completion->priv->popup_window));
1537 /* prevent the first row being focused */
1538 gtk_widget_grab_focus (completion->priv->tree_view);
1540 gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->tree_view)));
1541 gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->action_view)));
1543 gtk_window_set_screen (GTK_WINDOW (completion->priv->popup_window),
1544 gtk_widget_get_screen (completion->priv->entry));
1546 gtk_widget_show (completion->priv->popup_window);
1548 gtk_device_grab_add (completion->priv->popup_window, device, TRUE);
1549 gdk_device_grab (device, gtk_widget_get_window (completion->priv->popup_window),
1550 GDK_OWNERSHIP_WINDOW, TRUE,
1551 GDK_BUTTON_PRESS_MASK |
1552 GDK_BUTTON_RELEASE_MASK |
1553 GDK_POINTER_MOTION_MASK,
1554 NULL, GDK_CURRENT_TIME);
1556 completion->priv->grab_device = device;
1560 _gtk_entry_completion_popdown (GtkEntryCompletion *completion)
1562 if (!gtk_widget_get_mapped (completion->priv->popup_window))
1565 completion->priv->ignore_enter = FALSE;
1567 if (completion->priv->grab_device)
1569 gdk_device_ungrab (completion->priv->grab_device, GDK_CURRENT_TIME);
1570 gtk_device_grab_remove (completion->priv->popup_window,
1571 completion->priv->grab_device);
1572 completion->priv->grab_device = NULL;
1575 gtk_widget_hide (completion->priv->popup_window);
1579 gtk_entry_completion_match_selected (GtkEntryCompletion *completion,
1580 GtkTreeModel *model,
1585 gtk_tree_model_get (model, iter, completion->priv->text_column, &str, -1);
1586 gtk_entry_set_text (GTK_ENTRY (completion->priv->entry), str ? str : "");
1588 /* move cursor to the end */
1589 gtk_editable_set_position (GTK_EDITABLE (completion->priv->entry), -1);
1597 gtk_entry_completion_cursor_on_match (GtkEntryCompletion *completion,
1598 GtkTreeModel *model,
1601 gtk_entry_completion_insert_completion (completion, model, iter);
1607 gtk_entry_completion_compute_prefix (GtkEntryCompletion *completion)
1610 gchar *prefix = NULL;
1614 if (completion->priv->text_column < 0)
1617 key = gtk_entry_get_text (GTK_ENTRY (completion->priv->entry));
1619 valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (completion->priv->filter_model),
1626 gtk_tree_model_get (GTK_TREE_MODEL (completion->priv->filter_model),
1627 &iter, completion->priv->text_column, &text,
1630 if (text && g_str_has_prefix (text, key))
1633 prefix = g_strdup (text);
1639 while (*p && *p == *q)
1649 /* strip a partial multibyte character */
1650 q = g_utf8_find_prev_char (prefix, p);
1651 switch (g_utf8_get_char_validated (q, p - q))
1663 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (completion->priv->filter_model),
1672 gtk_entry_completion_real_insert_prefix (GtkEntryCompletion *completion,
1673 const gchar *prefix)
1681 prefix_len = g_utf8_strlen (prefix, -1);
1683 key = gtk_entry_get_text (GTK_ENTRY (completion->priv->entry));
1684 key_len = g_utf8_strlen (key, -1);
1686 if (prefix_len > key_len)
1688 gint pos = prefix_len;
1690 gtk_editable_insert_text (GTK_EDITABLE (completion->priv->entry),
1691 prefix + strlen (key), -1, &pos);
1692 gtk_editable_select_region (GTK_EDITABLE (completion->priv->entry),
1693 key_len, prefix_len);
1695 completion->priv->has_completion = TRUE;
1703 * gtk_entry_completion_get_completion_prefix:
1704 * @completion: a #GtkEntryCompletion
1706 * Get the original text entered by the user that triggered
1707 * the completion or %NULL if there's no completion ongoing.
1709 * Returns: the prefix for the current completion
1714 gtk_entry_completion_get_completion_prefix (GtkEntryCompletion *completion)
1716 g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), NULL);
1718 return completion->priv->completion_prefix;
1722 gtk_entry_completion_insert_completion_text (GtkEntryCompletion *completion,
1725 GtkEntryCompletionPrivate *priv = completion->priv;
1728 priv = completion->priv;
1730 if (priv->changed_id > 0)
1731 g_signal_handler_block (priv->entry, priv->changed_id);
1733 if (priv->insert_text_id > 0)
1734 g_signal_handler_block (priv->entry, priv->insert_text_id);
1736 gtk_entry_set_text (GTK_ENTRY (priv->entry), text);
1738 len = strlen (priv->completion_prefix);
1739 gtk_editable_select_region (GTK_EDITABLE (priv->entry), len, -1);
1741 if (priv->changed_id > 0)
1742 g_signal_handler_unblock (priv->entry, priv->changed_id);
1744 if (priv->insert_text_id > 0)
1745 g_signal_handler_unblock (priv->entry, priv->insert_text_id);
1749 gtk_entry_completion_insert_completion (GtkEntryCompletion *completion,
1750 GtkTreeModel *model,
1755 if (completion->priv->text_column < 0)
1758 gtk_tree_model_get (model, iter,
1759 completion->priv->text_column, &str,
1762 gtk_entry_completion_insert_completion_text (completion, str);
1770 * gtk_entry_completion_insert_prefix:
1771 * @completion: a #GtkEntryCompletion
1773 * Requests a prefix insertion.
1779 gtk_entry_completion_insert_prefix (GtkEntryCompletion *completion)
1784 if (completion->priv->insert_text_id > 0)
1785 g_signal_handler_block (completion->priv->entry,
1786 completion->priv->insert_text_id);
1788 prefix = gtk_entry_completion_compute_prefix (completion);
1791 g_signal_emit (completion, entry_completion_signals[INSERT_PREFIX],
1796 if (completion->priv->insert_text_id > 0)
1797 g_signal_handler_unblock (completion->priv->entry,
1798 completion->priv->insert_text_id);
1802 * gtk_entry_completion_set_inline_completion:
1803 * @completion: a #GtkEntryCompletion
1804 * @inline_completion: %TRUE to do inline completion
1806 * Sets whether the common prefix of the possible completions should
1807 * be automatically inserted in the entry.
1812 gtk_entry_completion_set_inline_completion (GtkEntryCompletion *completion,
1813 gboolean inline_completion)
1815 g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1817 inline_completion = inline_completion != FALSE;
1819 if (completion->priv->inline_completion != inline_completion)
1821 completion->priv->inline_completion = inline_completion;
1823 g_object_notify (G_OBJECT (completion), "inline-completion");
1828 * gtk_entry_completion_get_inline_completion:
1829 * @completion: a #GtkEntryCompletion
1831 * Returns whether the common prefix of the possible completions should
1832 * be automatically inserted in the entry.
1834 * Return value: %TRUE if inline completion is turned on
1839 gtk_entry_completion_get_inline_completion (GtkEntryCompletion *completion)
1841 g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), FALSE);
1843 return completion->priv->inline_completion;
1847 * gtk_entry_completion_set_popup_completion:
1848 * @completion: a #GtkEntryCompletion
1849 * @popup_completion: %TRUE to do popup completion
1851 * Sets whether the completions should be presented in a popup window.
1856 gtk_entry_completion_set_popup_completion (GtkEntryCompletion *completion,
1857 gboolean popup_completion)
1859 g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1861 popup_completion = popup_completion != FALSE;
1863 if (completion->priv->popup_completion != popup_completion)
1865 completion->priv->popup_completion = popup_completion;
1867 g_object_notify (G_OBJECT (completion), "popup-completion");
1873 * gtk_entry_completion_get_popup_completion:
1874 * @completion: a #GtkEntryCompletion
1876 * Returns whether the completions should be presented in a popup window.
1878 * Return value: %TRUE if popup completion is turned on
1883 gtk_entry_completion_get_popup_completion (GtkEntryCompletion *completion)
1885 g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), TRUE);
1887 return completion->priv->popup_completion;
1891 * gtk_entry_completion_set_popup_set_width:
1892 * @completion: a #GtkEntryCompletion
1893 * @popup_set_width: %TRUE to make the width of the popup the same as the entry
1895 * Sets whether the completion popup window will be resized to be the same
1896 * width as the entry.
1901 gtk_entry_completion_set_popup_set_width (GtkEntryCompletion *completion,
1902 gboolean popup_set_width)
1904 g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1906 popup_set_width = popup_set_width != FALSE;
1908 if (completion->priv->popup_set_width != popup_set_width)
1910 completion->priv->popup_set_width = popup_set_width;
1912 g_object_notify (G_OBJECT (completion), "popup-set-width");
1917 * gtk_entry_completion_get_popup_set_width:
1918 * @completion: a #GtkEntryCompletion
1920 * Returns whether the completion popup window will be resized to the
1921 * width of the entry.
1923 * Return value: %TRUE if the popup window will be resized to the width of
1929 gtk_entry_completion_get_popup_set_width (GtkEntryCompletion *completion)
1931 g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), TRUE);
1933 return completion->priv->popup_set_width;
1938 * gtk_entry_completion_set_popup_single_match:
1939 * @completion: a #GtkEntryCompletion
1940 * @popup_single_match: %TRUE if the popup should appear even for a single
1943 * Sets whether the completion popup window will appear even if there is
1944 * only a single match. You may want to set this to %FALSE if you
1945 * are using <link linkend="GtkEntryCompletion--inline-completion">inline
1946 * completion</link>.
1951 gtk_entry_completion_set_popup_single_match (GtkEntryCompletion *completion,
1952 gboolean popup_single_match)
1954 g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1956 popup_single_match = popup_single_match != FALSE;
1958 if (completion->priv->popup_single_match != popup_single_match)
1960 completion->priv->popup_single_match = popup_single_match;
1962 g_object_notify (G_OBJECT (completion), "popup-single-match");
1967 * gtk_entry_completion_get_popup_single_match:
1968 * @completion: a #GtkEntryCompletion
1970 * Returns whether the completion popup window will appear even if there is
1971 * only a single match.
1973 * Return value: %TRUE if the popup window will appear regardless of the
1974 * number of matches.
1979 gtk_entry_completion_get_popup_single_match (GtkEntryCompletion *completion)
1981 g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), TRUE);
1983 return completion->priv->popup_single_match;
1987 * gtk_entry_completion_set_inline_selection:
1988 * @completion: a #GtkEntryCompletion
1989 * @inline_selection: %TRUE to do inline selection
1991 * Sets whether it is possible to cycle through the possible completions
1997 gtk_entry_completion_set_inline_selection (GtkEntryCompletion *completion,
1998 gboolean inline_selection)
2000 g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
2002 inline_selection = inline_selection != FALSE;
2004 if (completion->priv->inline_selection != inline_selection)
2006 completion->priv->inline_selection = inline_selection;
2008 g_object_notify (G_OBJECT (completion), "inline-selection");
2013 * gtk_entry_completion_get_inline_selection:
2014 * @completion: a #GtkEntryCompletion
2016 * Returns %TRUE if inline-selection mode is turned on.
2018 * Returns: %TRUE if inline-selection mode is on
2023 gtk_entry_completion_get_inline_selection (GtkEntryCompletion *completion)
2025 g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), FALSE);
2027 return completion->priv->inline_selection;