summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--gtk/gtkentry.c43
-rw-r--r--gtk/gtkentrycompletion.c154
-rw-r--r--gtk/gtkentrycompletion.h10
-rw-r--r--gtk/gtkentryprivate.h2
5 files changed, 216 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index c52305a947..a4cb1f1f48 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2007-04-27 Xan Lopez <xan@gnome.org>
+
+ Support inline-selection in entries (#318459)
+
+ * gtk/gtkentry.c:
+ * gtk/gtkentrycompletion.c:
+ * gtk/gtkentrycompletion.h:
+ * gtk/gtkentryprivate.h:
+
+ When enabled cursor-match is emited when the cursor is on
+ a possible completion on the list. The default implementation
+ will replace the contents on the entry with the contents of
+ the text column in the completion model.
+
+ Review and improvements by Matthias Clasen.
+
2007-04-27 Michael Natterer <mitch@imendio.com>
Merged heavily modified patch from maemo-gtk which enables opening
diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c
index e6653d1a0d..992ac6f00b 100644
--- a/gtk/gtkentry.c
+++ b/gtk/gtkentry.c
@@ -5679,6 +5679,22 @@ gtk_entry_completion_key_press (GtkWidget *widget,
path = gtk_tree_path_new_from_indices (completion->priv->current_selected, -1);
gtk_tree_view_set_cursor (GTK_TREE_VIEW (completion->priv->tree_view),
path, NULL, FALSE);
+
+ if (completion->priv->inline_selection)
+ {
+
+ GtkTreeIter iter;
+ GtkTreeModel *model = NULL;
+ GtkTreeSelection *sel;
+ gboolean entry_set;
+
+ sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->tree_view));
+ if (!gtk_tree_selection_get_selected (sel, &model, &iter))
+ return FALSE;
+
+ g_signal_emit_by_name (completion, "cursor_on_match", model,
+ &iter, &entry_set);
+ }
}
else if (completion->priv->current_selected - matches >= 0)
{
@@ -5693,11 +5709,23 @@ gtk_entry_completion_key_press (GtkWidget *widget,
return TRUE;
}
- else if (event->keyval == GDK_Escape)
+ else if (event->keyval == GDK_Escape ||
+ event->keyval == GDK_Left ||
+ event->keyval == GDK_KP_Left ||
+ event->keyval == GDK_Right ||
+ event->keyval == GDK_KP_Right)
{
_gtk_entry_reset_im_context (GTK_ENTRY (widget));
_gtk_entry_completion_popdown (completion);
+ if (completion->priv->inline_selection)
+ {
+ if (event->keyval == GDK_Escape)
+ gtk_editable_delete_selection (GTK_EDITABLE (widget));
+ /* Move the cursor to the end */
+ gtk_editable_set_position (GTK_EDITABLE (widget), -1);
+ }
+
return TRUE;
}
else if (event->keyval == GDK_Tab ||
@@ -5750,7 +5778,7 @@ gtk_entry_completion_key_press (GtkWidget *widget,
/* move the cursor to the end */
gtk_editable_set_position (GTK_EDITABLE (widget), -1);
- g_free (str);
+ g_free (str);
}
return TRUE;
@@ -5880,12 +5908,18 @@ disconnect_completion_signals (GtkEntry *entry,
G_CALLBACK (completion_changed), entry);
if (completion->priv->changed_id > 0 &&
g_signal_handler_is_connected (entry, completion->priv->changed_id))
- g_signal_handler_disconnect (entry, completion->priv->changed_id);
+ {
+ g_signal_handler_disconnect (entry, completion->priv->changed_id);
+ completion->priv->changed_id = 0;
+ }
g_signal_handlers_disconnect_by_func (entry,
G_CALLBACK (gtk_entry_completion_key_press), completion);
if (completion->priv->insert_text_id > 0 &&
g_signal_handler_is_connected (entry, completion->priv->insert_text_id))
- g_signal_handler_disconnect (entry, completion->priv->insert_text_id);
+ {
+ g_signal_handler_disconnect (entry, completion->priv->insert_text_id);
+ completion->priv->insert_text_id = 0;
+ }
g_signal_handlers_disconnect_by_func (entry,
G_CALLBACK (completion_insert_text_callback), completion);
g_signal_handlers_disconnect_by_func (entry,
@@ -5919,6 +5953,7 @@ connect_completion_signals (GtkEntry *entry,
g_signal_connect (entry, "focus_out_event",
G_CALLBACK (accept_completion_callback), completion);
}
+
g_signal_connect (completion, "notify",
G_CALLBACK (completion_changed), entry);
}
diff --git a/gtk/gtkentrycompletion.c b/gtk/gtkentrycompletion.c
index d8bc08a06a..f4d74d62f4 100644
--- a/gtk/gtkentrycompletion.c
+++ b/gtk/gtkentrycompletion.c
@@ -47,6 +47,7 @@ enum
INSERT_PREFIX,
MATCH_SELECTED,
ACTION_ACTIVATED,
+ CURSOR_ON_MATCH,
LAST_SIGNAL
};
@@ -60,7 +61,8 @@ enum
PROP_INLINE_COMPLETION,
PROP_POPUP_COMPLETION,
PROP_POPUP_SET_WIDTH,
- PROP_POPUP_SINGLE_MATCH
+ PROP_POPUP_SINGLE_MATCH,
+ PROP_INLINE_SELECTION
};
#define GTK_ENTRY_COMPLETION_GET_PRIVATE(obj)(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ENTRY_COMPLETION, GtkEntryCompletionPrivate))
@@ -136,6 +138,9 @@ static gboolean gtk_entry_completion_match_selected (GtkEntryCompletion *co
GtkTreeIter *iter);
static gboolean gtk_entry_completion_real_insert_prefix (GtkEntryCompletion *completion,
const gchar *prefix);
+static gboolean gtk_entry_completion_cursor_on_match (GtkEntryCompletion *completion,
+ GtkTreeModel *model,
+ GtkTreeIter *iter);
static guint entry_completion_signals[LAST_SIGNAL] = { 0 };
@@ -156,6 +161,7 @@ gtk_entry_completion_class_init (GtkEntryCompletionClass *klass)
klass->match_selected = gtk_entry_completion_match_selected;
klass->insert_prefix = gtk_entry_completion_real_insert_prefix;
+ klass->cursor_on_match = gtk_entry_completion_cursor_on_match;
/**
* GtkEntryCompletion::insert-prefix:
@@ -210,6 +216,32 @@ gtk_entry_completion_class_init (GtkEntryCompletionClass *klass)
G_TYPE_BOOLEAN, 2,
GTK_TYPE_TREE_MODEL,
GTK_TYPE_TREE_ITER);
+ /**
+ * GtkEntryCompletion::cursor-on-match:
+ * @widget: the object which received the signal
+ * @model: the #GtkTreeModel containing the matches
+ * @iter: a #GtkTreeIter positioned at the selected match
+ *
+ * Gets emitted when a match from the cursor is on a match
+ * of the list.The default behaviour is to replace the contents
+ * of the entry with the contents of the text column in the row
+ * pointed to by @iter.
+ *
+ * Return value: %TRUE if the signal has been handled
+ *
+ * Since: 2.12
+ */
+
+ entry_completion_signals[CURSOR_ON_MATCH] =
+ g_signal_new (I_("cursor_on_match"),
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkEntryCompletionClass, cursor_on_match),
+ _gtk_boolean_handled_accumulator, NULL,
+ _gtk_marshal_BOOLEAN__OBJECT_BOXED,
+ G_TYPE_BOOLEAN, 2,
+ GTK_TYPE_TREE_MODEL,
+ GTK_TYPE_TREE_ITER);
/**
* GtkEntryCompletion::action-activated:
@@ -330,6 +362,21 @@ gtk_entry_completion_class_init (GtkEntryCompletionClass *klass)
P_("If TRUE, the popup window will appear for a single match."),
TRUE,
GTK_PARAM_READWRITE));
+ /**
+ * GtkEntryCompletion:inline-selection:
+ *
+ * Determines whether the possible completions on the popup
+ * will appear in the entry as you navigate through them.
+
+ * Since: 2.12
+ */
+ g_object_class_install_property (object_class,
+ PROP_INLINE_SELECTION,
+ g_param_spec_boolean ("inline-selection",
+ P_("Inline selection"),
+ P_("Your description here"),
+ FALSE,
+ GTK_PARAM_READWRITE));
g_type_class_add_private (object_class, sizeof (GtkEntryCompletionPrivate));
}
@@ -364,6 +411,7 @@ gtk_entry_completion_init (GtkEntryCompletion *completion)
priv->popup_completion = TRUE;
priv->popup_set_width = TRUE;
priv->popup_single_match = TRUE;
+ priv->inline_selection = FALSE;
/* completions */
priv->filter_model = NULL;
@@ -378,6 +426,7 @@ gtk_entry_completion_init (GtkEntryCompletion *completion)
g_signal_connect (priv->tree_view, "motion_notify_event",
G_CALLBACK (gtk_entry_completion_list_motion_notify),
completion);
+
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), FALSE);
gtk_tree_view_set_hover_selection (GTK_TREE_VIEW (priv->tree_view), TRUE);
@@ -505,6 +554,10 @@ gtk_entry_completion_set_property (GObject *object,
priv->popup_single_match = g_value_get_boolean (value);
break;
+ case PROP_INLINE_SELECTION:
+ priv->inline_selection = g_value_get_boolean (value);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -550,6 +603,10 @@ gtk_entry_completion_get_property (GObject *object,
g_value_set_boolean (value, gtk_entry_completion_get_popup_single_match (completion));
break;
+ case PROP_INLINE_SELECTION:
+ g_value_set_boolean (value, gtk_entry_completion_get_inline_selection (completion));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1277,7 +1334,7 @@ gtk_entry_completion_list_motion_notify (GtkWidget *widget,
{
GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (data);
- completion->priv->ignore_enter = FALSE;
+ completion->priv->ignore_enter = FALSE;
return FALSE;
}
@@ -1468,6 +1525,15 @@ gtk_entry_completion_match_selected (GtkEntryCompletion *completion,
return TRUE;
}
+static gboolean
+gtk_entry_completion_cursor_on_match (GtkEntryCompletion *completion,
+ GtkTreeModel *model,
+ GtkTreeIter *iter)
+{
+ gtk_entry_completion_insert_completion (completion, model, iter);
+
+ return TRUE;
+}
static gchar *
gtk_entry_completion_compute_prefix (GtkEntryCompletion *completion)
@@ -1565,6 +1631,65 @@ gtk_entry_completion_real_insert_prefix (GtkEntryCompletion *completion,
return TRUE;
}
+void
+gtk_entry_completion_insert_completion_text (GtkEntryCompletion *completion,
+ const gchar *text)
+{
+ GtkEntryCompletionPrivate *priv = completion->priv;
+ gint len;
+
+ if (priv->changed_id > 0)
+ {
+ g_signal_handler_block (priv->entry,
+ priv->changed_id);
+ }
+
+ if (priv->insert_text_id > 0)
+ {
+ g_signal_handler_block (completion->priv->entry,
+ completion->priv->insert_text_id);
+ }
+
+ gtk_editable_get_selection_bounds (GTK_EDITABLE (priv->entry), &len, NULL);
+ gtk_entry_set_text (GTK_ENTRY (priv->entry), text);
+ gtk_editable_select_region (GTK_EDITABLE (priv->entry), len, -1);
+
+ if (priv->changed_id > 0)
+ {
+ g_signal_handler_unblock (priv->entry,
+ priv->changed_id);
+ }
+
+ if (priv->insert_text_id > 0)
+ {
+ g_signal_handler_unblock (priv->entry,
+ priv->insert_text_id);
+ }
+}
+
+gboolean
+gtk_entry_completion_insert_completion (GtkEntryCompletion *completion,
+ GtkTreeModel *model,
+ GtkTreeIter *iter)
+{
+ gchar *str = NULL;
+
+ g_return_val_if_fail (GTK_IS_TREE_MODEL (model), FALSE);
+
+ if (completion->priv->text_column < 0)
+ return FALSE;
+
+ gtk_tree_model_get (model, iter,
+ completion->priv->text_column, &str,
+ -1);
+
+ gtk_entry_completion_insert_completion_text (completion, str);
+
+ g_free (str);
+
+ return TRUE;
+}
+
/**
* gtk_entry_completion_insert_prefix:
* @completion: a #GtkEntryCompletion
@@ -1573,6 +1698,7 @@ gtk_entry_completion_real_insert_prefix (GtkEntryCompletion *completion,
*
* Since: 2.6
**/
+
void
gtk_entry_completion_insert_prefix (GtkEntryCompletion *completion)
{
@@ -1622,7 +1748,6 @@ gtk_entry_completion_set_inline_completion (GtkEntryCompletion *completion,
}
}
-
/**
* gtk_entry_completion_get_inline_completion:
* @completion: a #GtkEntryCompletion
@@ -1782,6 +1907,29 @@ gtk_entry_completion_get_popup_single_match (GtkEntryCompletion *completion)
return completion->priv->popup_single_match;
}
+void
+gtk_entry_completion_set_inline_selection (GtkEntryCompletion *completion,
+ gboolean inline_selection)
+{
+ g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
+
+ inline_selection = inline_selection != FALSE;
+
+ if (completion->priv->inline_selection != inline_selection)
+ {
+ completion->priv->inline_selection = inline_selection;
+
+ g_object_notify (G_OBJECT (completion), "inline-selection");
+ }
+}
+
+gboolean
+gtk_entry_completion_get_inline_selection (GtkEntryCompletion *completion)
+{
+ g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), FALSE);
+
+ return completion->priv->inline_selection;
+}
#define __GTK_ENTRY_COMPLETION_C__
#include "gtkaliasdef.c"
diff --git a/gtk/gtkentrycompletion.h b/gtk/gtkentrycompletion.h
index 01a40fd957..26285d2ac6 100644
--- a/gtk/gtkentrycompletion.h
+++ b/gtk/gtkentrycompletion.h
@@ -65,11 +65,13 @@ struct _GtkEntryCompletionClass
gint index_);
gboolean (* insert_prefix) (GtkEntryCompletion *completion,
const gchar *prefix);
+ gboolean (* cursor_on_match) (GtkEntryCompletion *completion,
+ GtkTreeModel *model,
+ GtkTreeIter *iter);
/* Padding for future expansion */
void (*_gtk_reserved0) (void);
void (*_gtk_reserved1) (void);
- void (*_gtk_reserved2) (void);
};
/* core */
@@ -104,6 +106,9 @@ void gtk_entry_completion_delete_action (GtkEntryComplet
void gtk_entry_completion_set_inline_completion (GtkEntryCompletion *completion,
gboolean inline_completion);
gboolean gtk_entry_completion_get_inline_completion (GtkEntryCompletion *completion);
+void gtk_entry_completion_set_inline_selection (GtkEntryCompletion *completion,
+ gboolean inline_selection);
+gboolean gtk_entry_completion_get_inline_selection (GtkEntryCompletion *completion);
void gtk_entry_completion_set_popup_completion (GtkEntryCompletion *completion,
gboolean popup_completion);
gboolean gtk_entry_completion_get_popup_completion (GtkEntryCompletion *completion);
@@ -114,7 +119,8 @@ void gtk_entry_completion_set_popup_single_match (GtkEntryComplet
gboolean popup_single_match);
gboolean gtk_entry_completion_get_popup_single_match (GtkEntryCompletion *completion);
-
+void gtk_entry_completion_insert_completion_text (GtkEntryCompletion *completion,
+ const gchar *text);
/* convenience */
void gtk_entry_completion_set_text_column (GtkEntryCompletion *completion,
gint column);
diff --git a/gtk/gtkentryprivate.h b/gtk/gtkentryprivate.h
index 6589a0c201..696f744401 100644
--- a/gtk/gtkentryprivate.h
+++ b/gtk/gtkentryprivate.h
@@ -64,6 +64,8 @@ struct _GtkEntryCompletionPrivate
guint popup_completion : 1;
guint popup_set_width : 1;
guint popup_single_match : 1;
+ guint inline_selection : 1;
+
GSource *check_completion_idle;
};