Support inline autocompletion in entries (#135953)
2004-07-19 Matthias Clasen <mclasen@redhat.com> Support inline autocompletion in entries (#135953) * gtk/gtkentryprivate.h: * gtk/gtkentrycompletion.h: * gtk/gtkentrycompletion.c (gtk_entry_completion_class_init): Add a new signal ::insert-prefix which can be used to override the default inline-completion behaviour. Add two new boolean properties, :popup_completion and :inline_completion which determine how the possible completions should be presented. (gtk_entry_completion_insert_prefix): New function to request a prefix insertion. * gtk/gtkentry.c: Add the necessary glue for inline completion.
This commit is contained in:
committed by
Matthias Clasen
parent
23b6bd5378
commit
5351a4e444
16
ChangeLog
16
ChangeLog
@ -1,3 +1,19 @@
|
|||||||
|
2004-07-19 Matthias Clasen <mclasen@redhat.com>
|
||||||
|
|
||||||
|
Support inline autocompletion in entries (#135953)
|
||||||
|
|
||||||
|
* gtk/gtkentryprivate.h:
|
||||||
|
* gtk/gtkentrycompletion.h:
|
||||||
|
* gtk/gtkentrycompletion.c (gtk_entry_completion_class_init):
|
||||||
|
Add a new signal ::insert-prefix which can be used to override
|
||||||
|
the default inline-completion behaviour. Add two new boolean
|
||||||
|
properties, :popup_completion and :inline_completion which
|
||||||
|
determine how the possible completions should be presented.
|
||||||
|
(gtk_entry_completion_insert_prefix): New function to request
|
||||||
|
a prefix insertion.
|
||||||
|
|
||||||
|
* gtk/gtkentry.c: Add the necessary glue for inline completion.
|
||||||
|
|
||||||
Sun Jul 18 15:28:24 2004 Soeren Sandmann <sandmann@daimi.au.dk>
|
Sun Jul 18 15:28:24 2004 Soeren Sandmann <sandmann@daimi.au.dk>
|
||||||
|
|
||||||
* gtk/gtkdnd.c (gtk_drag_source_set, gtk_drag_dest_set): Create an
|
* gtk/gtkdnd.c (gtk_drag_source_set, gtk_drag_dest_set): Create an
|
||||||
|
|||||||
@ -1,3 +1,19 @@
|
|||||||
|
2004-07-19 Matthias Clasen <mclasen@redhat.com>
|
||||||
|
|
||||||
|
Support inline autocompletion in entries (#135953)
|
||||||
|
|
||||||
|
* gtk/gtkentryprivate.h:
|
||||||
|
* gtk/gtkentrycompletion.h:
|
||||||
|
* gtk/gtkentrycompletion.c (gtk_entry_completion_class_init):
|
||||||
|
Add a new signal ::insert-prefix which can be used to override
|
||||||
|
the default inline-completion behaviour. Add two new boolean
|
||||||
|
properties, :popup_completion and :inline_completion which
|
||||||
|
determine how the possible completions should be presented.
|
||||||
|
(gtk_entry_completion_insert_prefix): New function to request
|
||||||
|
a prefix insertion.
|
||||||
|
|
||||||
|
* gtk/gtkentry.c: Add the necessary glue for inline completion.
|
||||||
|
|
||||||
Sun Jul 18 15:28:24 2004 Soeren Sandmann <sandmann@daimi.au.dk>
|
Sun Jul 18 15:28:24 2004 Soeren Sandmann <sandmann@daimi.au.dk>
|
||||||
|
|
||||||
* gtk/gtkdnd.c (gtk_drag_source_set, gtk_drag_dest_set): Create an
|
* gtk/gtkdnd.c (gtk_drag_source_set, gtk_drag_dest_set): Create an
|
||||||
|
|||||||
@ -1,3 +1,19 @@
|
|||||||
|
2004-07-19 Matthias Clasen <mclasen@redhat.com>
|
||||||
|
|
||||||
|
Support inline autocompletion in entries (#135953)
|
||||||
|
|
||||||
|
* gtk/gtkentryprivate.h:
|
||||||
|
* gtk/gtkentrycompletion.h:
|
||||||
|
* gtk/gtkentrycompletion.c (gtk_entry_completion_class_init):
|
||||||
|
Add a new signal ::insert-prefix which can be used to override
|
||||||
|
the default inline-completion behaviour. Add two new boolean
|
||||||
|
properties, :popup_completion and :inline_completion which
|
||||||
|
determine how the possible completions should be presented.
|
||||||
|
(gtk_entry_completion_insert_prefix): New function to request
|
||||||
|
a prefix insertion.
|
||||||
|
|
||||||
|
* gtk/gtkentry.c: Add the necessary glue for inline completion.
|
||||||
|
|
||||||
Sun Jul 18 15:28:24 2004 Soeren Sandmann <sandmann@daimi.au.dk>
|
Sun Jul 18 15:28:24 2004 Soeren Sandmann <sandmann@daimi.au.dk>
|
||||||
|
|
||||||
* gtk/gtkdnd.c (gtk_drag_source_set, gtk_drag_dest_set): Create an
|
* gtk/gtkdnd.c (gtk_drag_source_set, gtk_drag_dest_set): Create an
|
||||||
|
|||||||
@ -1,3 +1,19 @@
|
|||||||
|
2004-07-19 Matthias Clasen <mclasen@redhat.com>
|
||||||
|
|
||||||
|
Support inline autocompletion in entries (#135953)
|
||||||
|
|
||||||
|
* gtk/gtkentryprivate.h:
|
||||||
|
* gtk/gtkentrycompletion.h:
|
||||||
|
* gtk/gtkentrycompletion.c (gtk_entry_completion_class_init):
|
||||||
|
Add a new signal ::insert-prefix which can be used to override
|
||||||
|
the default inline-completion behaviour. Add two new boolean
|
||||||
|
properties, :popup_completion and :inline_completion which
|
||||||
|
determine how the possible completions should be presented.
|
||||||
|
(gtk_entry_completion_insert_prefix): New function to request
|
||||||
|
a prefix insertion.
|
||||||
|
|
||||||
|
* gtk/gtkentry.c: Add the necessary glue for inline completion.
|
||||||
|
|
||||||
Sun Jul 18 15:28:24 2004 Soeren Sandmann <sandmann@daimi.au.dk>
|
Sun Jul 18 15:28:24 2004 Soeren Sandmann <sandmann@daimi.au.dk>
|
||||||
|
|
||||||
* gtk/gtkdnd.c (gtk_drag_source_set, gtk_drag_dest_set): Create an
|
* gtk/gtkdnd.c (gtk_drag_source_set, gtk_drag_dest_set): Create an
|
||||||
|
|||||||
159
gtk/gtkentry.c
159
gtk/gtkentry.c
@ -322,6 +322,31 @@ static void get_widget_window_size (GtkEntry *entry,
|
|||||||
gint *width,
|
gint *width,
|
||||||
gint *height);
|
gint *height);
|
||||||
|
|
||||||
|
/* Completion */
|
||||||
|
static gint gtk_entry_completion_timeout (gpointer data);
|
||||||
|
static gboolean gtk_entry_completion_key_press (GtkWidget *widget,
|
||||||
|
GdkEventKey *event,
|
||||||
|
gpointer user_data);
|
||||||
|
static void gtk_entry_completion_changed (GtkWidget *entry,
|
||||||
|
gpointer user_data);
|
||||||
|
static gboolean check_completion_callback (GtkEntryCompletion *completion);
|
||||||
|
static void clear_completion_callback (GtkEntry *entry,
|
||||||
|
GParamSpec *pspec);
|
||||||
|
static gboolean accept_completion_callback (GtkEntry *entry);
|
||||||
|
static void completion_insert_text_callback (GtkEntry *entry,
|
||||||
|
const gchar *text,
|
||||||
|
gint length,
|
||||||
|
gint position,
|
||||||
|
GtkEntryCompletion *completion);
|
||||||
|
static void completion_changed (GtkEntryCompletion *completion,
|
||||||
|
GParamSpec *pspec,
|
||||||
|
gpointer data);
|
||||||
|
static void disconnect_completion_signals (GtkEntry *entry,
|
||||||
|
GtkEntryCompletion *completion);
|
||||||
|
static void connect_completion_signals (GtkEntry *entry,
|
||||||
|
GtkEntryCompletion *completion);
|
||||||
|
|
||||||
|
|
||||||
static GtkWidgetClass *parent_class = NULL;
|
static GtkWidgetClass *parent_class = NULL;
|
||||||
|
|
||||||
GType
|
GType
|
||||||
@ -4999,6 +5024,122 @@ gtk_entry_completion_changed (GtkWidget *entry,
|
|||||||
completion);
|
completion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
check_completion_callback (GtkEntryCompletion *completion)
|
||||||
|
{
|
||||||
|
completion->priv->check_completion_idle = NULL;
|
||||||
|
|
||||||
|
gtk_entry_completion_insert_prefix (completion);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clear_completion_callback (GtkEntry *entry,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GtkEntryCompletion *completion = gtk_entry_get_completion (entry);
|
||||||
|
|
||||||
|
completion->priv->has_completion = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
accept_completion_callback (GtkEntry *entry)
|
||||||
|
{
|
||||||
|
GtkEntryCompletion *completion = gtk_entry_get_completion (entry);
|
||||||
|
|
||||||
|
if (completion->priv->has_completion)
|
||||||
|
gtk_editable_set_position (GTK_EDITABLE (entry),
|
||||||
|
entry->text_length);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
completion_insert_text_callback (GtkEntry *entry,
|
||||||
|
const gchar *text,
|
||||||
|
gint length,
|
||||||
|
gint position,
|
||||||
|
GtkEntryCompletion *completion)
|
||||||
|
{
|
||||||
|
/* idle to update the selection based on the file list */
|
||||||
|
if (completion->priv->check_completion_idle == NULL)
|
||||||
|
{
|
||||||
|
completion->priv->check_completion_idle = g_idle_source_new ();
|
||||||
|
g_source_set_priority (completion->priv->check_completion_idle, G_PRIORITY_HIGH);
|
||||||
|
g_source_set_closure (completion->priv->check_completion_idle,
|
||||||
|
g_cclosure_new_object (G_CALLBACK (check_completion_callback),
|
||||||
|
G_OBJECT (completion)));
|
||||||
|
g_source_attach (completion->priv->check_completion_idle, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
completion_changed (GtkEntryCompletion *completion,
|
||||||
|
GParamSpec *pspec,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
GtkEntry *entry = GTK_ENTRY (data);
|
||||||
|
|
||||||
|
disconnect_completion_signals (entry, completion);
|
||||||
|
connect_completion_signals (entry, completion);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
disconnect_completion_signals (GtkEntry *entry,
|
||||||
|
GtkEntryCompletion *completion)
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (completion,
|
||||||
|
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_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_handlers_disconnect_by_func (entry,
|
||||||
|
G_CALLBACK (completion_insert_text_callback), completion);
|
||||||
|
g_signal_handlers_disconnect_by_func (entry,
|
||||||
|
G_CALLBACK (clear_completion_callback), completion);
|
||||||
|
g_signal_handlers_disconnect_by_func (entry,
|
||||||
|
G_CALLBACK (accept_completion_callback), completion);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
connect_completion_signals (GtkEntry *entry,
|
||||||
|
GtkEntryCompletion *completion)
|
||||||
|
{
|
||||||
|
if (completion->priv->popup_completion)
|
||||||
|
{
|
||||||
|
completion->priv->changed_id =
|
||||||
|
g_signal_connect (entry, "changed",
|
||||||
|
G_CALLBACK (gtk_entry_completion_changed), completion);
|
||||||
|
g_signal_connect (entry, "key_press_event",
|
||||||
|
G_CALLBACK (gtk_entry_completion_key_press), completion);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (completion->priv->inline_completion)
|
||||||
|
{
|
||||||
|
completion->priv->insert_text_id =
|
||||||
|
g_signal_connect (entry, "insert_text",
|
||||||
|
G_CALLBACK (completion_insert_text_callback), completion);
|
||||||
|
g_signal_connect (entry, "notify::cursor-position",
|
||||||
|
G_CALLBACK (clear_completion_callback), completion);
|
||||||
|
g_signal_connect (entry, "notify::selection-bound",
|
||||||
|
G_CALLBACK (clear_completion_callback), completion);
|
||||||
|
g_signal_connect (entry, "activate",
|
||||||
|
G_CALLBACK (accept_completion_callback), completion);
|
||||||
|
g_signal_connect (entry, "focus_out_event",
|
||||||
|
G_CALLBACK (accept_completion_callback), completion);
|
||||||
|
}
|
||||||
|
g_signal_connect (completion, "notify::popup_completion",
|
||||||
|
G_CALLBACK (completion_changed), entry);
|
||||||
|
g_signal_connect (completion, "notify::inline_completion",
|
||||||
|
G_CALLBACK (completion_changed), entry);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gtk_entry_set_completion:
|
* gtk_entry_set_completion:
|
||||||
* @entry: A #GtkEntry.
|
* @entry: A #GtkEntry.
|
||||||
@ -5035,14 +5176,7 @@ gtk_entry_set_completion (GtkEntry *entry,
|
|||||||
if (GTK_WIDGET_MAPPED (old->priv->popup_window))
|
if (GTK_WIDGET_MAPPED (old->priv->popup_window))
|
||||||
_gtk_entry_completion_popdown (old);
|
_gtk_entry_completion_popdown (old);
|
||||||
|
|
||||||
gtk_cell_layout_clear (GTK_CELL_LAYOUT (old));
|
disconnect_completion_signals (entry, old);
|
||||||
old->priv->text_column = -1;
|
|
||||||
|
|
||||||
if (g_signal_handler_is_connected (entry, old->priv->changed_id))
|
|
||||||
g_signal_handler_disconnect (entry, old->priv->changed_id);
|
|
||||||
if (g_signal_handler_is_connected (entry, old->priv->key_press_id))
|
|
||||||
g_signal_handler_disconnect (entry, old->priv->key_press_id);
|
|
||||||
|
|
||||||
old->priv->entry = NULL;
|
old->priv->entry = NULL;
|
||||||
|
|
||||||
g_object_unref (old);
|
g_object_unref (old);
|
||||||
@ -5057,14 +5191,7 @@ gtk_entry_set_completion (GtkEntry *entry,
|
|||||||
/* hook into the entry */
|
/* hook into the entry */
|
||||||
g_object_ref (completion);
|
g_object_ref (completion);
|
||||||
|
|
||||||
completion->priv->changed_id =
|
connect_completion_signals (entry, completion);
|
||||||
g_signal_connect (entry, "changed",
|
|
||||||
G_CALLBACK (gtk_entry_completion_changed), completion);
|
|
||||||
|
|
||||||
completion->priv->key_press_id =
|
|
||||||
g_signal_connect (entry, "key_press_event",
|
|
||||||
G_CALLBACK (gtk_entry_completion_key_press), completion);
|
|
||||||
|
|
||||||
completion->priv->entry = GTK_WIDGET (entry);
|
completion->priv->entry = GTK_WIDGET (entry);
|
||||||
g_object_set_data (G_OBJECT (entry), GTK_ENTRY_COMPLETION_KEY, completion);
|
g_object_set_data (G_OBJECT (entry), GTK_ENTRY_COMPLETION_KEY, completion);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,6 +41,7 @@
|
|||||||
/* signals */
|
/* signals */
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
INSERT_PREFIX,
|
||||||
MATCH_SELECTED,
|
MATCH_SELECTED,
|
||||||
ACTION_ACTIVATED,
|
ACTION_ACTIVATED,
|
||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
@ -52,7 +53,9 @@ enum
|
|||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_MODEL,
|
PROP_MODEL,
|
||||||
PROP_MINIMUM_KEY_LENGTH,
|
PROP_MINIMUM_KEY_LENGTH,
|
||||||
PROP_TEXT_COLUMN
|
PROP_TEXT_COLUMN,
|
||||||
|
PROP_INLINE_COMPLETION,
|
||||||
|
PROP_POPUP_COMPLETION
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GTK_ENTRY_COMPLETION_GET_PRIVATE(obj)(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ENTRY_COMPLETION, GtkEntryCompletionPrivate))
|
#define GTK_ENTRY_COMPLETION_GET_PRIVATE(obj)(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ENTRY_COMPLETION, GtkEntryCompletionPrivate))
|
||||||
@ -128,6 +131,8 @@ static void gtk_entry_completion_action_data_func (GtkTreeViewColumn
|
|||||||
static gboolean gtk_entry_completion_match_selected (GtkEntryCompletion *completion,
|
static gboolean gtk_entry_completion_match_selected (GtkEntryCompletion *completion,
|
||||||
GtkTreeModel *model,
|
GtkTreeModel *model,
|
||||||
GtkTreeIter *iter);
|
GtkTreeIter *iter);
|
||||||
|
static gboolean gtk_entry_completion_real_insert_prefix (GtkEntryCompletion *completion,
|
||||||
|
gchar *key);
|
||||||
|
|
||||||
static GObjectClass *parent_class = NULL;
|
static GObjectClass *parent_class = NULL;
|
||||||
static guint entry_completion_signals[LAST_SIGNAL] = { 0 };
|
static guint entry_completion_signals[LAST_SIGNAL] = { 0 };
|
||||||
@ -185,6 +190,35 @@ gtk_entry_completion_class_init (GtkEntryCompletionClass *klass)
|
|||||||
object_class->finalize = gtk_entry_completion_finalize;
|
object_class->finalize = gtk_entry_completion_finalize;
|
||||||
|
|
||||||
klass->match_selected = gtk_entry_completion_match_selected;
|
klass->match_selected = gtk_entry_completion_match_selected;
|
||||||
|
klass->insert_prefix = gtk_entry_completion_real_insert_prefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GtkEntryCompletion::insert-prefix:
|
||||||
|
* @widget: the object which received the signal
|
||||||
|
* @prefix: the common prefix of all possible completions
|
||||||
|
*
|
||||||
|
* The ::insert-prefix signal is emitted when the inline autocompletion
|
||||||
|
* is triggered. The default behaviour is to make the entry display the
|
||||||
|
* whole prefix and select the newly inserted part.
|
||||||
|
*
|
||||||
|
* Applications may connect to this signal in order to insert only a
|
||||||
|
* smaller part of the @prefix into the entry - e.g. the entry used in
|
||||||
|
* the #GtkFileChooser inserts only the part of the prefix up to the
|
||||||
|
* next '/'.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE if the signal has been handled
|
||||||
|
*
|
||||||
|
* Since: 2.6
|
||||||
|
*/
|
||||||
|
entry_completion_signals[INSERT_PREFIX] =
|
||||||
|
g_signal_new ("insert_prefix",
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GtkEntryCompletionClass, insert_prefix),
|
||||||
|
_gtk_boolean_handled_accumulator, NULL,
|
||||||
|
_gtk_marshal_BOOLEAN__STRING,
|
||||||
|
G_TYPE_BOOLEAN, 1,
|
||||||
|
G_TYPE_STRING);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GtkEntryCompletion::match-selected:
|
* GtkEntryCompletion::match-selected:
|
||||||
@ -198,6 +232,8 @@ gtk_entry_completion_class_init (GtkEntryCompletionClass *klass)
|
|||||||
* @iter.
|
* @iter.
|
||||||
*
|
*
|
||||||
* Return value: %TRUE if the signal has been handled
|
* Return value: %TRUE if the signal has been handled
|
||||||
|
*
|
||||||
|
* Since: 2.4
|
||||||
*/
|
*/
|
||||||
entry_completion_signals[MATCH_SELECTED] =
|
entry_completion_signals[MATCH_SELECTED] =
|
||||||
g_signal_new ("match_selected",
|
g_signal_new ("match_selected",
|
||||||
@ -217,6 +253,8 @@ gtk_entry_completion_class_init (GtkEntryCompletionClass *klass)
|
|||||||
*
|
*
|
||||||
* The ::action-activated signal is emitted when an action
|
* The ::action-activated signal is emitted when an action
|
||||||
* is activated.
|
* is activated.
|
||||||
|
*
|
||||||
|
* Since: 2.4
|
||||||
*/
|
*/
|
||||||
entry_completion_signals[ACTION_ACTIVATED] =
|
entry_completion_signals[ACTION_ACTIVATED] =
|
||||||
g_signal_new ("action_activated",
|
g_signal_new ("action_activated",
|
||||||
@ -245,7 +283,7 @@ gtk_entry_completion_class_init (GtkEntryCompletionClass *klass)
|
|||||||
1,
|
1,
|
||||||
G_PARAM_READWRITE));
|
G_PARAM_READWRITE));
|
||||||
/**
|
/**
|
||||||
* GtkEntryCompletion::text-column:
|
* GtkEntryCompletion:text-column:
|
||||||
*
|
*
|
||||||
* The column of the model containing the strings.
|
* The column of the model containing the strings.
|
||||||
*
|
*
|
||||||
@ -261,6 +299,38 @@ gtk_entry_completion_class_init (GtkEntryCompletionClass *klass)
|
|||||||
-1,
|
-1,
|
||||||
G_PARAM_READWRITE));
|
G_PARAM_READWRITE));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GtkEntryCompletion:inline_completion:
|
||||||
|
*
|
||||||
|
* The boolean :inline_completion property determines whether the
|
||||||
|
* common prefix of the possible completions should be inserted
|
||||||
|
* automatically in the entry.
|
||||||
|
*
|
||||||
|
* Since: 2.6
|
||||||
|
**/
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_INLINE_COMPLETION,
|
||||||
|
g_param_spec_boolean ("inline_completion",
|
||||||
|
P_("Inline completion"),
|
||||||
|
P_("Whether the common prefix should be inserted automatically"),
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READWRITE));
|
||||||
|
/**
|
||||||
|
* GtkEntryCompletion:popup_completion:
|
||||||
|
*
|
||||||
|
* The boolean :popup_completion property determines whether the
|
||||||
|
* possible completions should be shown in a popup window.
|
||||||
|
*
|
||||||
|
* Since: 2.6
|
||||||
|
**/
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_POPUP_COMPLETION,
|
||||||
|
g_param_spec_boolean ("popup_completion",
|
||||||
|
P_("Popup completion"),
|
||||||
|
P_("Whether the completions should be shown in a popup window"),
|
||||||
|
TRUE,
|
||||||
|
G_PARAM_READWRITE));
|
||||||
|
|
||||||
g_type_class_add_private (object_class, sizeof (GtkEntryCompletionPrivate));
|
g_type_class_add_private (object_class, sizeof (GtkEntryCompletionPrivate));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,6 +359,9 @@ gtk_entry_completion_init (GtkEntryCompletion *completion)
|
|||||||
|
|
||||||
priv->minimum_key_length = 1;
|
priv->minimum_key_length = 1;
|
||||||
priv->text_column = -1;
|
priv->text_column = -1;
|
||||||
|
priv->has_completion = FALSE;
|
||||||
|
priv->inline_completion = FALSE;
|
||||||
|
priv->popup_completion = TRUE;
|
||||||
|
|
||||||
/* completions */
|
/* completions */
|
||||||
priv->filter_model = NULL;
|
priv->filter_model = NULL;
|
||||||
@ -410,6 +483,14 @@ gtk_entry_completion_set_property (GObject *object,
|
|||||||
priv->text_column = g_value_get_int (value);
|
priv->text_column = g_value_get_int (value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_INLINE_COMPLETION:
|
||||||
|
priv->inline_completion = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_POPUP_COMPLETION:
|
||||||
|
priv->popup_completion = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -439,6 +520,14 @@ gtk_entry_completion_get_property (GObject *object,
|
|||||||
g_value_set_int (value, gtk_entry_completion_get_text_column (completion));
|
g_value_set_int (value, gtk_entry_completion_get_text_column (completion));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_INLINE_COMPLETION:
|
||||||
|
g_value_set_boolean (value, gtk_entry_completion_get_inline_completion (completion));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_POPUP_COMPLETION:
|
||||||
|
g_value_set_boolean (value, gtk_entry_completion_get_popup_completion (completion));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -1320,3 +1409,199 @@ gtk_entry_completion_match_selected (GtkEntryCompletion *completion,
|
|||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gchar *
|
||||||
|
gtk_entry_completion_compute_prefix (GtkEntryCompletion *completion)
|
||||||
|
{
|
||||||
|
GtkTreeIter iter;
|
||||||
|
gchar *prefix = NULL;
|
||||||
|
gboolean valid;
|
||||||
|
|
||||||
|
const gchar *key = gtk_entry_get_text (GTK_ENTRY (completion->priv->entry));
|
||||||
|
|
||||||
|
valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (completion->priv->filter_model),
|
||||||
|
&iter);
|
||||||
|
|
||||||
|
while (valid)
|
||||||
|
{
|
||||||
|
gchar *text;
|
||||||
|
|
||||||
|
gtk_tree_model_get (GTK_TREE_MODEL (completion->priv->filter_model),
|
||||||
|
&iter, completion->priv->text_column, &text,
|
||||||
|
-1);
|
||||||
|
|
||||||
|
if (g_str_has_prefix (text, key))
|
||||||
|
{
|
||||||
|
if (!prefix)
|
||||||
|
prefix = g_strdup (text);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gchar *p = prefix;
|
||||||
|
const gchar *q = text;
|
||||||
|
|
||||||
|
while (*p && *p == *q)
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
q++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*p = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (text);
|
||||||
|
valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (completion->priv->filter_model),
|
||||||
|
&iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gtk_entry_completion_real_insert_prefix (GtkEntryCompletion *completion,
|
||||||
|
gchar *prefix)
|
||||||
|
{
|
||||||
|
if (prefix)
|
||||||
|
{
|
||||||
|
gint key_len;
|
||||||
|
gint prefix_len;
|
||||||
|
gint pos;
|
||||||
|
const gchar *key;
|
||||||
|
|
||||||
|
prefix_len = g_utf8_strlen (prefix, -1);
|
||||||
|
|
||||||
|
key = gtk_entry_get_text (GTK_ENTRY (completion->priv->entry));
|
||||||
|
key_len = g_utf8_strlen (key, -1);
|
||||||
|
|
||||||
|
if (prefix_len > key_len)
|
||||||
|
{
|
||||||
|
gtk_editable_insert_text (GTK_EDITABLE (completion->priv->entry),
|
||||||
|
prefix + key_len, -1, &pos);
|
||||||
|
gtk_editable_select_region (GTK_EDITABLE (completion->priv->entry),
|
||||||
|
key_len, prefix_len);
|
||||||
|
|
||||||
|
completion->priv->has_completion = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_entry_completion_insert_prefix:
|
||||||
|
* @completion: a #GtkEntryCompletion
|
||||||
|
*
|
||||||
|
* Requests a prefix insertion.
|
||||||
|
*
|
||||||
|
* Since: 2.6
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
gtk_entry_completion_insert_prefix (GtkEntryCompletion *completion)
|
||||||
|
{
|
||||||
|
gboolean done;
|
||||||
|
gchar *prefix;
|
||||||
|
|
||||||
|
g_signal_handler_block (completion->priv->entry,
|
||||||
|
completion->priv->insert_text_id);
|
||||||
|
prefix = gtk_entry_completion_compute_prefix (completion);
|
||||||
|
if (prefix)
|
||||||
|
{
|
||||||
|
g_signal_emit (completion, entry_completion_signals[INSERT_PREFIX],
|
||||||
|
0, prefix, &done);
|
||||||
|
g_free (prefix);
|
||||||
|
}
|
||||||
|
g_signal_handler_unblock (completion->priv->entry,
|
||||||
|
completion->priv->insert_text_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_entry_completion_set_inline_completion:
|
||||||
|
* @completion: a #GtkEntryCompletion
|
||||||
|
* @inline_completion: %TRUE to do inline completion
|
||||||
|
*
|
||||||
|
* Sets whether the common prefix of the possible completions should
|
||||||
|
* be automatically inserted in the entry.
|
||||||
|
*
|
||||||
|
* Since: 2.6
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
gtk_entry_completion_set_inline_completion (GtkEntryCompletion *completion,
|
||||||
|
gboolean inline_completion)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
|
||||||
|
|
||||||
|
inline_completion = inline_completion != FALSE;
|
||||||
|
|
||||||
|
if (completion->priv->inline_completion != inline_completion)
|
||||||
|
{
|
||||||
|
completion->priv->inline_completion = inline_completion;
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (completion), "inline_completion");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_entry_completion_get_inline_completion:
|
||||||
|
* @completion: a #GtkEntryCompletion
|
||||||
|
*
|
||||||
|
* Returns whether the common prefix of the possible completions should
|
||||||
|
* be automatically inserted in the entry.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE if inline completion is turned on
|
||||||
|
*
|
||||||
|
* Since: 2.6
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
gtk_entry_completion_get_inline_completion (GtkEntryCompletion *completion)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), FALSE);
|
||||||
|
|
||||||
|
return completion->priv->inline_completion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_entry_completion_set_popup_completion:
|
||||||
|
* @completion: a #GtkEntryCompletion
|
||||||
|
* @inline_completion: %TRUE to do popup completion
|
||||||
|
*
|
||||||
|
* Sets whether the completions should be presented in a popup window.
|
||||||
|
*
|
||||||
|
* Since: 2.6
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
gtk_entry_completion_set_popup_completion (GtkEntryCompletion *completion,
|
||||||
|
gboolean popup_completion)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
|
||||||
|
|
||||||
|
popup_completion = popup_completion != FALSE;
|
||||||
|
|
||||||
|
if (completion->priv->popup_completion != popup_completion)
|
||||||
|
{
|
||||||
|
completion->priv->popup_completion = popup_completion;
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (completion), "popup_completion");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_entry_completion_get_popup_completion:
|
||||||
|
* @completion: a #GtkEntryCompletion
|
||||||
|
*
|
||||||
|
* Returns whether the completions should be presented in a popup window.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE if popup completion is turned on
|
||||||
|
*
|
||||||
|
* Since: 2.6
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
gtk_entry_completion_get_popup_completion (GtkEntryCompletion *completion)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), TRUE);
|
||||||
|
|
||||||
|
return completion->priv->popup_completion;
|
||||||
|
}
|
||||||
|
|||||||
@ -63,12 +63,13 @@ struct _GtkEntryCompletionClass
|
|||||||
GtkTreeIter *iter);
|
GtkTreeIter *iter);
|
||||||
void (* action_activated) (GtkEntryCompletion *completion,
|
void (* action_activated) (GtkEntryCompletion *completion,
|
||||||
gint index_);
|
gint index_);
|
||||||
|
gboolean (* insert_prefix) (GtkEntryCompletion *completion,
|
||||||
|
gchar *prefix);
|
||||||
|
|
||||||
/* Padding for future expansion */
|
/* Padding for future expansion */
|
||||||
void (*_gtk_reserved0) (void);
|
void (*_gtk_reserved0) (void);
|
||||||
void (*_gtk_reserved1) (void);
|
void (*_gtk_reserved1) (void);
|
||||||
void (*_gtk_reserved2) (void);
|
void (*_gtk_reserved2) (void);
|
||||||
void (*_gtk_reserved3) (void);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* core */
|
/* core */
|
||||||
@ -89,6 +90,7 @@ void gtk_entry_completion_set_minimum_key_length (GtkEntryComplet
|
|||||||
gint length);
|
gint length);
|
||||||
gint gtk_entry_completion_get_minimum_key_length (GtkEntryCompletion *completion);
|
gint gtk_entry_completion_get_minimum_key_length (GtkEntryCompletion *completion);
|
||||||
void gtk_entry_completion_complete (GtkEntryCompletion *completion);
|
void gtk_entry_completion_complete (GtkEntryCompletion *completion);
|
||||||
|
void gtk_entry_completion_insert_prefix (GtkEntryCompletion *completion);
|
||||||
|
|
||||||
void gtk_entry_completion_insert_action_text (GtkEntryCompletion *completion,
|
void gtk_entry_completion_insert_action_text (GtkEntryCompletion *completion,
|
||||||
gint index_,
|
gint index_,
|
||||||
@ -99,6 +101,13 @@ void gtk_entry_completion_insert_action_markup (GtkEntryComplet
|
|||||||
void gtk_entry_completion_delete_action (GtkEntryCompletion *completion,
|
void gtk_entry_completion_delete_action (GtkEntryCompletion *completion,
|
||||||
gint index_);
|
gint index_);
|
||||||
|
|
||||||
|
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_popup_completion (GtkEntryCompletion *completion,
|
||||||
|
gboolean popup_completion);
|
||||||
|
gboolean gtk_entry_completion_get_popup_completion (GtkEntryCompletion *completion);
|
||||||
|
|
||||||
/* convenience */
|
/* convenience */
|
||||||
void gtk_entry_completion_set_text_column (GtkEntryCompletion *completion,
|
void gtk_entry_completion_set_text_column (GtkEntryCompletion *completion,
|
||||||
gint column);
|
gint column);
|
||||||
|
|||||||
@ -55,10 +55,14 @@ struct _GtkEntryCompletionPrivate
|
|||||||
|
|
||||||
gulong completion_timeout;
|
gulong completion_timeout;
|
||||||
gulong changed_id;
|
gulong changed_id;
|
||||||
gulong key_press_id;
|
gulong insert_text_id;
|
||||||
gulong key_release_id;
|
|
||||||
|
|
||||||
gboolean ignore_enter;
|
guint ignore_enter : 1;
|
||||||
|
guint has_completion : 1;
|
||||||
|
guint inline_completion : 1;
|
||||||
|
guint popup_completion : 1;
|
||||||
|
|
||||||
|
GSource *check_completion_idle;
|
||||||
};
|
};
|
||||||
|
|
||||||
gboolean _gtk_entry_completion_resize_popup (GtkEntryCompletion *completion);
|
gboolean _gtk_entry_completion_resize_popup (GtkEntryCompletion *completion);
|
||||||
|
|||||||
Reference in New Issue
Block a user