summaryrefslogtreecommitdiff
path: root/gladeui/glade-inspector.c
diff options
context:
space:
mode:
authorTristan Van Berkom <tristan.van.berkom@gmail.com>2013-04-07 22:45:47 +0900
committerTristan Van Berkom <tristan.van.berkom@gmail.com>2013-04-08 01:39:07 +0900
commit8780ba94d3aed95ab29213bb9127ff836836bdb7 (patch)
treebcc522420c33a660cc1b88ac9bbc185bc9289cfb /gladeui/glade-inspector.c
parent7434df5696da1eb0fd60826d3354c1e0c5c1eaf4 (diff)
downloadglade-8780ba94d3aed95ab29213bb9127ff836836bdb7.tar.gz
GladeInspector: Re-enable completions in the search entry.
Guys, it's twice now that someone breaks completions, with the naive idea that some stock function from GTK+ can do it right, please, please never break completions in the inspector again, thankyou.
Diffstat (limited to 'gladeui/glade-inspector.c')
-rw-r--r--gladeui/glade-inspector.c241
1 files changed, 169 insertions, 72 deletions
diff --git a/gladeui/glade-inspector.c b/gladeui/glade-inspector.c
index 7c4d9c3e..90d160f4 100644
--- a/gladeui/glade-inspector.c
+++ b/gladeui/glade-inspector.c
@@ -56,6 +56,17 @@
GLADE_TYPE_INSPECTOR, \
GladeInspectorPrivate))
+
+static void search_entry_text_inserted_cb (GtkEntry *entry,
+ const gchar *text,
+ gint length,
+ gint *position,
+ GladeInspector *inspector);
+static void search_entry_text_deleted_cb (GtkEditable *editable,
+ gint start_pos,
+ gint end_pos,
+ GladeInspector *inspector);
+
enum
{
PROP_0,
@@ -80,6 +91,7 @@ struct _GladeInspectorPrivate
GtkWidget *entry;
guint idle_complete;
gboolean search_disabled;
+ gchar *completion_text;
};
static GParamSpec *properties[N_PROPERTIES];
@@ -215,7 +227,7 @@ glade_inspector_visible_func (GtkTreeModel *model,
gboolean retval = FALSE;
- if (priv->search_disabled)
+ if (priv->search_disabled || priv->completion_text == NULL)
return TRUE;
if (gtk_tree_model_iter_children (model, &iter, parent))
@@ -226,15 +238,15 @@ glade_inspector_visible_func (GtkTreeModel *model,
}
while (gtk_tree_model_iter_next (model, &iter) && !retval);
}
+
if (!retval)
{
- const gchar *text = gtk_entry_get_text (GTK_ENTRY (priv->entry));
gchar *widget_name;
gtk_tree_model_get (model, parent, GLADE_PROJECT_MODEL_COLUMN_NAME,
&widget_name, -1);
- retval = find_in_string_insensitive (widget_name, text);
+ retval = find_in_string_insensitive (widget_name, priv->completion_text);
g_free (widget_name);
}
@@ -243,7 +255,7 @@ glade_inspector_visible_func (GtkTreeModel *model,
}
static void
-glade_inspector_filter (GladeInspector *inspector)
+glade_inspector_refilter (GladeInspector *inspector)
{
GladeInspectorPrivate *priv = inspector->priv;
@@ -252,61 +264,115 @@ glade_inspector_filter (GladeInspector *inspector)
gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter));
gtk_tree_view_expand_all (GTK_TREE_VIEW (priv->view));
}
-
}
static void
search_entry_changed_cb (GtkEntry *entry, GladeInspector *inspector)
{
- glade_inspector_filter (inspector);
+ glade_inspector_refilter (inspector);
}
+typedef struct {
+ const gchar *text;
+ gchar *common_text;
+} CommonMatchData;
+
static void
-selection_name_foreach_func (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gchar **selection)
+reduce_string (gchar *str1,
+ gchar *str2)
{
- if (*selection == NULL)
+ gint str1len = strlen (str1);
+ gint i;
+
+ for (i = 0; str2[i] != '\0'; i++)
{
- gchar *name;
-
- gtk_tree_model_get (model, iter, GLADE_PROJECT_MODEL_COLUMN_NAME, &name, -1);
- *selection = name;
+
+ if (str1[i] != str2[i] || i >= str1len)
+ {
+ str1[i] = '\0';
+ break;
+ }
}
+
+ if (str2[i] == '\0')
+ str1[i] = '\0';
+}
+
+static gboolean
+search_common_matches (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ CommonMatchData *data)
+{
+ gchar *row_text = NULL;
+ gboolean match;
+
+ gtk_tree_model_get (model, iter, GLADE_PROJECT_MODEL_COLUMN_NAME, &row_text, -1);
+
+ match = (strncmp (data->text, row_text, strlen (data->text)) == 0);
+
+ if (match)
+ {
+ if (data->common_text)
+ {
+ reduce_string (data->common_text, row_text);
+
+ g_free (row_text);
+ }
+ else
+ data->common_text = row_text;
+ }
+ else
+ g_free (row_text);
+
+ return FALSE;
}
static gchar *
-get_selected_name (GladeInspector *inspector)
+get_partial_match (GladeInspector *inspector,
+ const gchar *search)
{
- GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (inspector->priv->view));
- gchar *name = NULL;
+ GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (inspector->priv->view));
+ CommonMatchData data;
+
+ data.text = search;
+ data.common_text = NULL;
- gtk_tree_selection_selected_foreach (selection,
- (GtkTreeSelectionForeachFunc)
- selection_name_foreach_func, &name);
+ gtk_tree_model_foreach (model, (GtkTreeModelForeachFunc)search_common_matches, &data);
- return name;
+ return data.common_text;
}
static gboolean
search_complete_idle (GladeInspector *inspector)
{
GladeInspectorPrivate *priv = inspector->priv;
- gchar *completed = get_selected_name (inspector);
+ gchar *completed;
const gchar *str;
gsize length;
str = gtk_entry_get_text (GTK_ENTRY (priv->entry));
+ completed = get_partial_match (inspector, str);
+
+ g_free (priv->completion_text);
+ priv->completion_text = g_strdup (str);
+
if (completed)
{
length = strlen (str);
+ g_signal_handlers_block_by_func (priv->entry, search_entry_text_inserted_cb, inspector);
+ g_signal_handlers_block_by_func (priv->entry, search_entry_text_deleted_cb, inspector);
+
gtk_entry_set_text (GTK_ENTRY (priv->entry), completed);
gtk_editable_set_position (GTK_EDITABLE (priv->entry), length);
gtk_editable_select_region (GTK_EDITABLE (priv->entry), length, -1);
g_free (completed);
+
+ g_signal_handlers_unblock_by_func (priv->entry, search_entry_text_inserted_cb, inspector);
+ g_signal_handlers_unblock_by_func (priv->entry, search_entry_text_deleted_cb, inspector);
+
}
priv->idle_complete = 0;
@@ -330,6 +396,27 @@ search_entry_text_inserted_cb (GtkEntry *entry,
}
}
+static void
+search_entry_text_deleted_cb (GtkEditable *editable,
+ gint start_pos,
+ gint end_pos,
+ GladeInspector *inspector)
+{
+ GladeInspectorPrivate *priv = inspector->priv;
+
+ if (!priv->search_disabled)
+ {
+ const gchar *str;
+
+ str = gtk_entry_get_text (GTK_ENTRY (priv->entry));
+
+ g_free (priv->completion_text);
+ priv->completion_text = g_strdup (str);
+
+ glade_inspector_refilter (inspector);
+ }
+}
+
static gboolean
search_entry_key_press_event_cb (GtkEntry *entry,
GdkEventKey *event,
@@ -338,6 +425,8 @@ search_entry_key_press_event_cb (GtkEntry *entry,
GladeInspectorPrivate *priv = inspector->priv;
const gchar *str;
+ str = gtk_entry_get_text (GTK_ENTRY (priv->entry));
+
if (event->keyval == GDK_KEY_Tab)
{
if (event->state & GDK_CONTROL_MASK)
@@ -346,8 +435,13 @@ search_entry_key_press_event_cb (GtkEntry *entry,
}
else
{
+ g_free (priv->completion_text);
+ priv->completion_text = g_strdup (str);
+
gtk_editable_set_position (GTK_EDITABLE (entry), -1);
gtk_editable_select_region (GTK_EDITABLE (entry), -1, -1);
+
+ glade_inspector_refilter (inspector);
}
return TRUE;
}
@@ -356,52 +450,56 @@ search_entry_key_press_event_cb (GtkEntry *entry,
{
gchar *name;
- str = gtk_entry_get_text (GTK_ENTRY (priv->entry));
-
- if (str && (name = get_selected_name (inspector)))
+ if (str && (name = get_partial_match (inspector, str)))
{
+ g_free (priv->completion_text);
+ priv->completion_text = name;
+
+ g_signal_handlers_block_by_func (priv->entry, search_entry_text_inserted_cb, inspector);
+ g_signal_handlers_block_by_func (priv->entry, search_entry_text_deleted_cb, inspector);
+
gtk_entry_set_text (GTK_ENTRY (entry), name);
- g_free (name);
+
+ g_signal_handlers_unblock_by_func (priv->entry, search_entry_text_inserted_cb, inspector);
+ g_signal_handlers_unblock_by_func (priv->entry, search_entry_text_deleted_cb, inspector);
+
gtk_editable_set_position (GTK_EDITABLE (entry), -1);
gtk_editable_select_region (GTK_EDITABLE (entry), -1, -1);
}
return TRUE;
}
- return FALSE;
-}
+ if (event->keyval == GDK_KEY_BackSpace)
+ {
+ if (!priv->search_disabled && !priv->idle_complete && str && str[0])
+ {
+ /* Now, set the text to the current completion text -1 char, and recomplete */
+ if (priv->completion_text && priv->completion_text[0])
+ {
+ /* If we're not at the position of the length of the completion text, just carry on */
+ if (!gtk_editable_get_selection_bounds (GTK_EDITABLE (priv->entry), NULL, NULL))
+ return FALSE;
-static void
-widget_font_desc_set_style (GtkWidget *widget, PangoStyle style)
-{
- GtkStyleContext *context = gtk_widget_get_style_context (widget);
- PangoFontDescription *font_desc =
- pango_font_description_copy (gtk_style_context_get_font (context, GTK_STATE_FLAG_NORMAL));
+ priv->completion_text[strlen (priv->completion_text) -1] = '\0';
- pango_font_description_set_style (font_desc, style);
- gtk_widget_override_font (widget, font_desc);
- pango_font_description_free (font_desc);
-}
+ g_signal_handlers_block_by_func (priv->entry, search_entry_text_inserted_cb, inspector);
+ g_signal_handlers_block_by_func (priv->entry, search_entry_text_deleted_cb, inspector);
-static void
-search_entry_update (GladeInspector *inspector)
-{
- GladeInspectorPrivate *priv = inspector->priv;
- const gchar *str = gtk_entry_get_text (GTK_ENTRY (priv->entry));
+ gtk_entry_set_text (GTK_ENTRY (priv->entry), priv->completion_text);
+ gtk_editable_set_position (GTK_EDITABLE (priv->entry), -1);
- if (str[0] == '\0')
- {
- GtkStyleContext *context;
- GdkRGBA color;
+ g_signal_handlers_unblock_by_func (priv->entry, search_entry_text_inserted_cb, inspector);
+ g_signal_handlers_unblock_by_func (priv->entry, search_entry_text_deleted_cb, inspector);
- priv->search_disabled = TRUE;
- widget_font_desc_set_style (priv->entry, PANGO_STYLE_ITALIC);
- gtk_entry_set_text (GTK_ENTRY (priv->entry), _("< search widgets >"));
+ priv->idle_complete =
+ g_idle_add ((GSourceFunc) search_complete_idle, inspector);
- context = gtk_widget_get_style_context (priv->entry);
- gtk_style_context_get_color (context, GTK_STATE_FLAG_INSENSITIVE, &color);
- gtk_widget_override_color (priv->entry, GTK_STATE_FLAG_NORMAL, &color);
+ return TRUE;
+ }
+ }
}
+
+ return FALSE;
}
static gboolean
@@ -412,13 +510,7 @@ search_entry_focus_in_cb (GtkWidget *entry,
GladeInspectorPrivate *priv = inspector->priv;
if (priv->search_disabled)
- {
- gtk_entry_set_text (GTK_ENTRY (priv->entry), "");
- gtk_widget_override_color (priv->entry, GTK_STATE_NORMAL, NULL);
- gtk_widget_override_font (priv->entry, NULL);
-
- priv->search_disabled = FALSE;
- }
+ priv->search_disabled = FALSE;
return FALSE;
}
@@ -428,7 +520,14 @@ search_entry_focus_out_cb (GtkWidget *entry,
GdkEventFocus *event,
GladeInspector *inspector)
{
- search_entry_update (inspector);
+ GladeInspectorPrivate *priv = inspector->priv;
+
+ priv->search_disabled = TRUE;
+
+ g_free (priv->completion_text);
+ priv->completion_text = NULL;
+
+ gtk_entry_set_text (GTK_ENTRY (priv->entry), "");
return FALSE;
}
@@ -446,7 +545,7 @@ glade_inspector_init (GladeInspector *inspector)
priv->entry = gtk_entry_new ();
- search_entry_update (inspector);
+ gtk_entry_set_placeholder_text (GTK_ENTRY (priv->entry), _("< Search Widgets >"));
gtk_widget_show (priv->entry);
gtk_box_pack_start (GTK_BOX (inspector), priv->entry, FALSE, FALSE, 2);
@@ -457,6 +556,9 @@ glade_inspector_init (GladeInspector *inspector)
g_signal_connect_after (priv->entry, "insert-text",
G_CALLBACK (search_entry_text_inserted_cb),
inspector);
+ g_signal_connect_after (priv->entry, "delete-text",
+ G_CALLBACK (search_entry_text_deleted_cb),
+ inspector);
g_signal_connect (priv->entry, "focus-in-event",
G_CALLBACK (search_entry_focus_in_cb), inspector);
g_signal_connect (priv->entry, "focus-out-event",
@@ -494,7 +596,6 @@ glade_inspector_dispose (GObject *object)
{
GladeInspector *inspector = GLADE_INSPECTOR (object);
- glade_inspector_set_search_entry (inspector, NULL);
glade_inspector_set_project (inspector, NULL);
if (inspector->priv->idle_complete)
@@ -509,6 +610,10 @@ glade_inspector_dispose (GObject *object)
static void
glade_inspector_finalize (GObject *object)
{
+ GladeInspector *inspector = GLADE_INSPECTOR (object);
+
+ g_free (inspector->priv->completion_text);
+
G_OBJECT_CLASS (glade_inspector_parent_class)->finalize (object);
}
@@ -823,14 +928,6 @@ glade_inspector_set_project (GladeInspector *inspector, GladeProject *project)
g_object_unref (priv->filter); /* pass ownership of the filter to the model */
connect_project_signals (inspector, project);
-
- gtk_tree_view_set_search_entry (GTK_TREE_VIEW (priv->view), GTK_ENTRY (priv->entry));
- gtk_tree_view_set_enable_search (GTK_TREE_VIEW (priv->view), TRUE);
- }
- else
- {
- gtk_tree_view_set_search_entry (GTK_TREE_VIEW (priv->view), NULL);
- gtk_tree_view_set_enable_search (GTK_TREE_VIEW (priv->view), FALSE);
}
g_object_notify_by_pspec (G_OBJECT (inspector), properties[PROP_PROJECT]);