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_vbox_new (FALSE, 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 gdk_window_get_origin (window, &x, &y);
1404 _gtk_entry_get_borders (GTK_ENTRY (completion->priv->entry), &x_border, &y_border);
1406 matches = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (completion->priv->filter_model), NULL);
1407 actions = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (completion->priv->actions), NULL);
1408 action_column = gtk_tree_view_get_column (GTK_TREE_VIEW (completion->priv->action_view), 0);
1410 gtk_tree_view_column_cell_get_size (completion->priv->column, NULL,
1411 NULL, NULL, NULL, &height);
1412 gtk_tree_view_column_cell_get_size (action_column, NULL,
1413 NULL, NULL, NULL, &action_height);
1415 gtk_widget_style_get (GTK_WIDGET (completion->priv->tree_view),
1416 "vertical-separator", &vertical_separator,
1419 height += vertical_separator;
1421 gtk_widget_realize (completion->priv->tree_view);
1423 screen = gtk_widget_get_screen (GTK_WIDGET (completion->priv->entry));
1424 monitor_num = gdk_screen_get_monitor_at_window (screen, window);
1425 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
1429 if (y > monitor.height / 2)
1430 items = MIN (matches, (((monitor.y + y) - (actions * action_height)) / height) - 1);
1432 items = MIN (matches, (((monitor.height - y) - (actions * action_height)) / height) - 1);
1435 gtk_widget_hide (completion->priv->scrolled_window);
1437 gtk_widget_show (completion->priv->scrolled_window);
1439 gtk_widget_get_allocation (completion->priv->entry, &allocation);
1440 if (completion->priv->popup_set_width)
1441 width = MIN (allocation.width, monitor.width) - 2 * x_border;
1445 gtk_tree_view_columns_autosize (GTK_TREE_VIEW (completion->priv->tree_view));
1446 gtk_widget_set_size_request (completion->priv->tree_view, width, items * height);
1450 gtk_widget_show (completion->priv->action_view);
1451 gtk_widget_set_size_request (completion->priv->action_view, width, -1);
1454 gtk_widget_hide (completion->priv->action_view);
1456 gtk_size_request_get_size (GTK_SIZE_REQUEST (completion->priv->popup_window),
1458 gtk_size_request_get_size (GTK_SIZE_REQUEST (completion->priv->entry),
1463 else if (x + popup_req.width > monitor.x + monitor.width)
1464 x = monitor.x + monitor.width - popup_req.width;
1466 if (y + entry_req.height + popup_req.height <= monitor.y + monitor.height ||
1467 y - monitor.y < (monitor.y + monitor.height) - (y + entry_req.height))
1469 y += entry_req.height;
1474 y -= popup_req.height;
1480 path = gtk_tree_path_new_from_indices (above ? matches - 1 : 0, -1);
1481 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (completion->priv->tree_view), path,
1482 NULL, FALSE, 0.0, 0.0);
1483 gtk_tree_path_free (path);
1486 gtk_window_move (GTK_WINDOW (completion->priv->popup_window), x, y);
1492 _gtk_entry_completion_popup (GtkEntryCompletion *completion,
1495 GtkTreeViewColumn *column;
1497 GtkWidget *toplevel;
1499 if (gtk_widget_get_mapped (completion->priv->popup_window))
1502 if (!gtk_widget_get_mapped (completion->priv->entry))
1505 if (!gtk_widget_has_focus (completion->priv->entry))
1508 if (completion->priv->grab_device)
1511 completion->priv->ignore_enter = TRUE;
1513 column = gtk_tree_view_get_column (GTK_TREE_VIEW (completion->priv->action_view), 0);
1514 renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
1515 gtk_widget_ensure_style (completion->priv->tree_view);
1516 g_object_set (GTK_CELL_RENDERER (renderers->data), "cell-background-gdk",
1517 >k_widget_get_style (completion->priv->tree_view)->bg[GTK_STATE_NORMAL],
1519 g_list_free (renderers);
1521 gtk_widget_show_all (completion->priv->vbox);
1523 /* default on no match */
1524 completion->priv->current_selected = -1;
1526 _gtk_entry_completion_resize_popup (completion);
1528 toplevel = gtk_widget_get_toplevel (completion->priv->entry);
1529 if (GTK_IS_WINDOW (toplevel))
1530 gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (toplevel)),
1531 GTK_WINDOW (completion->priv->popup_window));
1533 /* prevent the first row being focused */
1534 gtk_widget_grab_focus (completion->priv->tree_view);
1536 gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->tree_view)));
1537 gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->action_view)));
1539 gtk_window_set_screen (GTK_WINDOW (completion->priv->popup_window),
1540 gtk_widget_get_screen (completion->priv->entry));
1542 gtk_widget_show (completion->priv->popup_window);
1544 gtk_device_grab_add (completion->priv->popup_window, device, TRUE);
1545 gdk_device_grab (device, gtk_widget_get_window (completion->priv->popup_window),
1546 GDK_OWNERSHIP_WINDOW, TRUE,
1547 GDK_BUTTON_PRESS_MASK |
1548 GDK_BUTTON_RELEASE_MASK |
1549 GDK_POINTER_MOTION_MASK,
1550 NULL, GDK_CURRENT_TIME);
1552 completion->priv->grab_device = device;
1556 _gtk_entry_completion_popdown (GtkEntryCompletion *completion)
1558 if (!gtk_widget_get_mapped (completion->priv->popup_window))
1561 completion->priv->ignore_enter = FALSE;
1563 if (completion->priv->grab_device)
1565 gdk_device_ungrab (completion->priv->grab_device, GDK_CURRENT_TIME);
1566 gtk_device_grab_remove (completion->priv->popup_window,
1567 completion->priv->grab_device);
1568 completion->priv->grab_device = NULL;
1571 gtk_widget_hide (completion->priv->popup_window);
1575 gtk_entry_completion_match_selected (GtkEntryCompletion *completion,
1576 GtkTreeModel *model,
1581 gtk_tree_model_get (model, iter, completion->priv->text_column, &str, -1);
1582 gtk_entry_set_text (GTK_ENTRY (completion->priv->entry), str ? str : "");
1584 /* move cursor to the end */
1585 gtk_editable_set_position (GTK_EDITABLE (completion->priv->entry), -1);
1593 gtk_entry_completion_cursor_on_match (GtkEntryCompletion *completion,
1594 GtkTreeModel *model,
1597 gtk_entry_completion_insert_completion (completion, model, iter);
1603 gtk_entry_completion_compute_prefix (GtkEntryCompletion *completion)
1606 gchar *prefix = NULL;
1610 if (completion->priv->text_column < 0)
1613 key = gtk_entry_get_text (GTK_ENTRY (completion->priv->entry));
1615 valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (completion->priv->filter_model),
1622 gtk_tree_model_get (GTK_TREE_MODEL (completion->priv->filter_model),
1623 &iter, completion->priv->text_column, &text,
1626 if (text && g_str_has_prefix (text, key))
1629 prefix = g_strdup (text);
1635 while (*p && *p == *q)
1645 /* strip a partial multibyte character */
1646 q = g_utf8_find_prev_char (prefix, p);
1647 switch (g_utf8_get_char_validated (q, p - q))
1659 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (completion->priv->filter_model),
1668 gtk_entry_completion_real_insert_prefix (GtkEntryCompletion *completion,
1669 const gchar *prefix)
1677 prefix_len = g_utf8_strlen (prefix, -1);
1679 key = gtk_entry_get_text (GTK_ENTRY (completion->priv->entry));
1680 key_len = g_utf8_strlen (key, -1);
1682 if (prefix_len > key_len)
1684 gint pos = prefix_len;
1686 gtk_editable_insert_text (GTK_EDITABLE (completion->priv->entry),
1687 prefix + strlen (key), -1, &pos);
1688 gtk_editable_select_region (GTK_EDITABLE (completion->priv->entry),
1689 key_len, prefix_len);
1691 completion->priv->has_completion = TRUE;
1699 * gtk_entry_completion_get_completion_prefix:
1700 * @completion: a #GtkEntryCompletion
1702 * Get the original text entered by the user that triggered
1703 * the completion or %NULL if there's no completion ongoing.
1705 * Returns: the prefix for the current completion
1710 gtk_entry_completion_get_completion_prefix (GtkEntryCompletion *completion)
1712 g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), NULL);
1714 return completion->priv->completion_prefix;
1718 gtk_entry_completion_insert_completion_text (GtkEntryCompletion *completion,
1721 GtkEntryCompletionPrivate *priv = completion->priv;
1724 priv = completion->priv;
1726 if (priv->changed_id > 0)
1727 g_signal_handler_block (priv->entry, priv->changed_id);
1729 if (priv->insert_text_id > 0)
1730 g_signal_handler_block (priv->entry, priv->insert_text_id);
1732 gtk_entry_set_text (GTK_ENTRY (priv->entry), text);
1734 len = strlen (priv->completion_prefix);
1735 gtk_editable_select_region (GTK_EDITABLE (priv->entry), len, -1);
1737 if (priv->changed_id > 0)
1738 g_signal_handler_unblock (priv->entry, priv->changed_id);
1740 if (priv->insert_text_id > 0)
1741 g_signal_handler_unblock (priv->entry, priv->insert_text_id);
1745 gtk_entry_completion_insert_completion (GtkEntryCompletion *completion,
1746 GtkTreeModel *model,
1751 if (completion->priv->text_column < 0)
1754 gtk_tree_model_get (model, iter,
1755 completion->priv->text_column, &str,
1758 gtk_entry_completion_insert_completion_text (completion, str);
1766 * gtk_entry_completion_insert_prefix:
1767 * @completion: a #GtkEntryCompletion
1769 * Requests a prefix insertion.
1775 gtk_entry_completion_insert_prefix (GtkEntryCompletion *completion)
1780 if (completion->priv->insert_text_id > 0)
1781 g_signal_handler_block (completion->priv->entry,
1782 completion->priv->insert_text_id);
1784 prefix = gtk_entry_completion_compute_prefix (completion);
1787 g_signal_emit (completion, entry_completion_signals[INSERT_PREFIX],
1792 if (completion->priv->insert_text_id > 0)
1793 g_signal_handler_unblock (completion->priv->entry,
1794 completion->priv->insert_text_id);
1798 * gtk_entry_completion_set_inline_completion:
1799 * @completion: a #GtkEntryCompletion
1800 * @inline_completion: %TRUE to do inline completion
1802 * Sets whether the common prefix of the possible completions should
1803 * be automatically inserted in the entry.
1808 gtk_entry_completion_set_inline_completion (GtkEntryCompletion *completion,
1809 gboolean inline_completion)
1811 g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1813 inline_completion = inline_completion != FALSE;
1815 if (completion->priv->inline_completion != inline_completion)
1817 completion->priv->inline_completion = inline_completion;
1819 g_object_notify (G_OBJECT (completion), "inline-completion");
1824 * gtk_entry_completion_get_inline_completion:
1825 * @completion: a #GtkEntryCompletion
1827 * Returns whether the common prefix of the possible completions should
1828 * be automatically inserted in the entry.
1830 * Return value: %TRUE if inline completion is turned on
1835 gtk_entry_completion_get_inline_completion (GtkEntryCompletion *completion)
1837 g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), FALSE);
1839 return completion->priv->inline_completion;
1843 * gtk_entry_completion_set_popup_completion:
1844 * @completion: a #GtkEntryCompletion
1845 * @popup_completion: %TRUE to do popup completion
1847 * Sets whether the completions should be presented in a popup window.
1852 gtk_entry_completion_set_popup_completion (GtkEntryCompletion *completion,
1853 gboolean popup_completion)
1855 g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1857 popup_completion = popup_completion != FALSE;
1859 if (completion->priv->popup_completion != popup_completion)
1861 completion->priv->popup_completion = popup_completion;
1863 g_object_notify (G_OBJECT (completion), "popup-completion");
1869 * gtk_entry_completion_get_popup_completion:
1870 * @completion: a #GtkEntryCompletion
1872 * Returns whether the completions should be presented in a popup window.
1874 * Return value: %TRUE if popup completion is turned on
1879 gtk_entry_completion_get_popup_completion (GtkEntryCompletion *completion)
1881 g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), TRUE);
1883 return completion->priv->popup_completion;
1887 * gtk_entry_completion_set_popup_set_width:
1888 * @completion: a #GtkEntryCompletion
1889 * @popup_set_width: %TRUE to make the width of the popup the same as the entry
1891 * Sets whether the completion popup window will be resized to be the same
1892 * width as the entry.
1897 gtk_entry_completion_set_popup_set_width (GtkEntryCompletion *completion,
1898 gboolean popup_set_width)
1900 g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1902 popup_set_width = popup_set_width != FALSE;
1904 if (completion->priv->popup_set_width != popup_set_width)
1906 completion->priv->popup_set_width = popup_set_width;
1908 g_object_notify (G_OBJECT (completion), "popup-set-width");
1913 * gtk_entry_completion_get_popup_set_width:
1914 * @completion: a #GtkEntryCompletion
1916 * Returns whether the completion popup window will be resized to the
1917 * width of the entry.
1919 * Return value: %TRUE if the popup window will be resized to the width of
1925 gtk_entry_completion_get_popup_set_width (GtkEntryCompletion *completion)
1927 g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), TRUE);
1929 return completion->priv->popup_set_width;
1934 * gtk_entry_completion_set_popup_single_match:
1935 * @completion: a #GtkEntryCompletion
1936 * @popup_single_match: %TRUE if the popup should appear even for a single
1939 * Sets whether the completion popup window will appear even if there is
1940 * only a single match. You may want to set this to %FALSE if you
1941 * are using <link linkend="GtkEntryCompletion--inline-completion">inline
1942 * completion</link>.
1947 gtk_entry_completion_set_popup_single_match (GtkEntryCompletion *completion,
1948 gboolean popup_single_match)
1950 g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1952 popup_single_match = popup_single_match != FALSE;
1954 if (completion->priv->popup_single_match != popup_single_match)
1956 completion->priv->popup_single_match = popup_single_match;
1958 g_object_notify (G_OBJECT (completion), "popup-single-match");
1963 * gtk_entry_completion_get_popup_single_match:
1964 * @completion: a #GtkEntryCompletion
1966 * Returns whether the completion popup window will appear even if there is
1967 * only a single match.
1969 * Return value: %TRUE if the popup window will appear regardless of the
1970 * number of matches.
1975 gtk_entry_completion_get_popup_single_match (GtkEntryCompletion *completion)
1977 g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), TRUE);
1979 return completion->priv->popup_single_match;
1983 * gtk_entry_completion_set_inline_selection:
1984 * @completion: a #GtkEntryCompletion
1985 * @inline_selection: %TRUE to do inline selection
1987 * Sets whether it is possible to cycle through the possible completions
1993 gtk_entry_completion_set_inline_selection (GtkEntryCompletion *completion,
1994 gboolean inline_selection)
1996 g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1998 inline_selection = inline_selection != FALSE;
2000 if (completion->priv->inline_selection != inline_selection)
2002 completion->priv->inline_selection = inline_selection;
2004 g_object_notify (G_OBJECT (completion), "inline-selection");
2009 * gtk_entry_completion_get_inline_selection:
2010 * @completion: a #GtkEntryCompletion
2012 * Returns %TRUE if inline-selection mode is turned on.
2014 * Returns: %TRUE if inline-selection mode is on
2019 gtk_entry_completion_get_inline_selection (GtkEntryCompletion *completion)
2021 g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), FALSE);
2023 return completion->priv->inline_selection;