[gnome-control-center/wip/gbsneto/list-layout: 27/28] window: reimplement search
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center/wip/gbsneto/list-layout: 27/28] window: reimplement search
- Date: Thu, 26 May 2016 17:10:05 +0000 (UTC)
commit fdf7ee4b15057b4c14b1df7b722db6b6fc16e246
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Thu May 26 13:08:40 2016 -0300
window: reimplement search
We previously had a dedicate view for handling search,
based on model filtering and a custom panel to display
that differently.
After moving to GtkListBox, search can be trivially
done by using a filtering function, and widgets can
be fine-tuned to display extra information.
This patch, then, reimplements the search using a filtering
function over the panels' list.
shell/cc-window.c | 303 ++++++-----------------------------------------------
shell/window.ui | 2 +-
2 files changed, 33 insertions(+), 272 deletions(-)
---
diff --git a/shell/cc-window.c b/shell/cc-window.c
index c2ff293..d4b8f9d 100644
--- a/shell/cc-window.c
+++ b/shell/cc-window.c
@@ -84,11 +84,6 @@ struct _CcWindow
GtkListStore *store;
- GtkTreeModel *search_filter;
- GtkWidget *search_view;
- gchar *filter_string;
- gchar **filter_terms;
-
GHashTable *id_to_row;
CcPanel *active_panel;
@@ -298,8 +293,6 @@ shell_show_overview_page (CcWindow *self)
self->previous_panels = g_queue_new ();
/* clear the search text */
- g_free (self->filter_string);
- self->filter_string = g_strdup ("");
gtk_entry_set_text (GTK_ENTRY (self->search_entry), "");
if (gtk_search_bar_get_search_mode (GTK_SEARCH_BAR (self->search_bar)))
gtk_widget_grab_focus (self->search_entry);
@@ -359,253 +352,54 @@ row_selected_cb (GtkListBox *listbox,
}
}
+/*
+ * GtkListBox functions
+ */
static gboolean
-model_filter_func (GtkTreeModel *model,
- GtkTreeIter *iter,
- CcWindow *self)
+filter_func (GtkListBoxRow *row,
+ gpointer user_data)
{
- char **t;
- gboolean matches = FALSE;
+ CcWindow *self;
+ RowData *data;
+ const gchar *search_text;
- if (!self->filter_string || !self->filter_terms)
- return FALSE;
+ self = CC_WINDOW (user_data);
+ data = g_object_get_data (G_OBJECT (row), "data");
+ search_text = gtk_entry_get_text (GTK_ENTRY (self->search_entry));
- for (t = self->filter_terms; *t; t++)
- {
- matches = cc_shell_model_iter_matches_search (CC_SHELL_MODEL (model),
- iter,
- *t);
- if (!matches)
- break;
- }
+ /*
+ * The description label is only visible when the search is
+ * happening.
+ */
+ gtk_widget_set_visible (data->description_label, g_utf8_strlen (search_text, -1) > 0);
- return matches;
+ return g_strstr_len (data->name, -1, search_text) != NULL ||
+ g_strstr_len (data->description, -1, search_text) != NULL;
}
static void
search_entry_changed_cb (GtkEntry *entry,
CcWindow *self)
{
- char *str;
-
- /* if the entry text was set manually (not by the user) */
- if (!g_strcmp0 (self->filter_string, gtk_entry_get_text (entry)))
- {
- cc_shell_model_set_sort_terms (CC_SHELL_MODEL (self->store), NULL);
- return;
- }
-
- /* Don't re-filter for added trailing or leading spaces */
- str = cc_util_normalize_casefold_and_unaccent (gtk_entry_get_text (entry));
- g_strstrip (str);
- if (!g_strcmp0 (str, self->filter_string))
- {
- g_free (str);
- return;
- }
-
- g_free (self->filter_string);
- self->filter_string = str;
-
- g_strfreev (self->filter_terms);
- self->filter_terms = g_strsplit (self->filter_string, " ", -1);
-
- cc_shell_model_set_sort_terms (CC_SHELL_MODEL (self->store), self->filter_terms);
-
- if (!g_strcmp0 (self->filter_string, ""))
- {
- shell_show_overview_page (self);
- }
- else
- {
- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (self->search_filter));
- gtk_stack_set_visible_child_name (GTK_STACK (self->stack), SEARCH_PAGE);
- }
-}
-
-static gboolean
-search_entry_key_press_event_cb (GtkEntry *entry,
- GdkEventKey *event,
- CcWindow *self)
-{
- if (event->keyval == GDK_KEY_Return &&
- g_strcmp0 (self->filter_string, "") != 0)
- {
- GtkTreePath *path;
- GtkTreeSelection *selection;
-
- path = gtk_tree_path_new_first ();
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->search_view));
- gtk_tree_selection_select_path (selection, path);
-
- if (!gtk_tree_selection_path_is_selected (selection, path))
- {
- gtk_tree_path_free (path);
- return FALSE;
- }
-
- gtk_tree_view_row_activated (GTK_TREE_VIEW (self->search_view), path,
- gtk_tree_view_get_column (GTK_TREE_VIEW (self->search_view), 0));
- gtk_tree_path_free (path);
- return TRUE;
- }
-
- if (event->keyval == GDK_KEY_Escape)
- {
- gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (self->search_bar), FALSE);
- gtk_entry_set_text (entry, "");
- return TRUE;
- }
-
- return FALSE;
+ gtk_list_box_invalidate_filter (GTK_LIST_BOX (self->listbox));
}
static void
-on_search_row_activated (GtkTreeView *treeview,
- GtkTreePath *path,
- GtkTreeViewColumn *column,
- CcWindow *shell)
+search_entry_activate_cb (GtkEntry *entry,
+ CcWindow *self)
{
- GtkTreeSelection *selection;
- GtkTreeModel *model;
- GtkTreeIter iter;
- char *id = NULL;
-
- selection = gtk_tree_view_get_selection (treeview);
-
- if (!gtk_tree_selection_get_selected (selection, &model, &iter))
- return;
-
- gtk_tree_model_get (model, &iter,
- COL_ID, &id,
- -1);
+ GtkListBoxRow *row;
- if (id)
- cc_window_set_active_panel_from_id (CC_SHELL (shell), id, NULL, NULL);
+ row = gtk_list_box_get_row_at_y (GTK_LIST_BOX (self->listbox), 0);
- gtk_tree_selection_unselect_all (selection);
-
- g_free (id);
-}
-
-static gboolean
-on_search_button_press_event (GtkTreeView *treeview,
- GdkEventButton *event,
- CcWindow *shell)
-{
- if (event->type == GDK_BUTTON_PRESS && event->button == 1)
+ if (row)
{
- GtkTreePath *path = NULL;
- GtkTreeSelection *selection;
- GtkTreeModel *model;
- GtkTreeIter iter;
-
- /* We don't check for the position being blank,
- * it could be the dead space between columns */
- gtk_tree_view_is_blank_at_pos (treeview,
- event->x, event->y,
- &path,
- NULL,
- NULL,
- NULL);
- if (path == NULL)
- return FALSE;
-
- model = gtk_tree_view_get_model (treeview);
- if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
- {
- gtk_tree_path_free (path);
- return FALSE;
- }
-
- selection = gtk_tree_view_get_selection (treeview);
- gtk_tree_selection_select_iter (selection, &iter);
-
- on_search_row_activated (treeview, NULL, NULL, shell);
-
- gtk_tree_path_free (path);
-
- return TRUE;
+ gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (self->search_bar), FALSE);
+ gtk_list_box_select_row (GTK_LIST_BOX (self->listbox), row);
+ gtk_widget_grab_focus (GTK_WIDGET (row));
}
-
- return FALSE;
}
-static void
-setup_search (CcWindow *self)
-{
- GtkWidget *search_view;
- GtkCellRenderer *renderer;
- GtkTreeViewColumn *column;
-
- g_return_if_fail (self->store != NULL);
-
- /* create the search filter */
- self->search_filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (self->store),
- NULL);
-
- gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (self->search_filter),
- (GtkTreeModelFilterVisibleFunc)
- model_filter_func,
- self, NULL);
-
- /* set up the search view */
- self->search_view = search_view = gtk_tree_view_new ();
- gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (search_view), FALSE);
- gtk_tree_view_set_enable_search (GTK_TREE_VIEW (search_view), FALSE);
- gtk_tree_view_set_model (GTK_TREE_VIEW (search_view),
- GTK_TREE_MODEL (self->search_filter));
- /* This needs to happen after setting the model, otherwise
- * the search column will be the first string column */
- gtk_tree_view_set_search_column (GTK_TREE_VIEW (search_view), -1);
-
- renderer = gtk_cell_renderer_pixbuf_new ();
- g_object_set (renderer,
- "xpad", 15,
- "ypad", 10,
- "stock-size", GTK_ICON_SIZE_DIALOG,
- "follow-state", TRUE,
- NULL);
- column = gtk_tree_view_column_new_with_attributes ("Icon", renderer,
- "gicon", COL_GICON,
- NULL);
- gtk_tree_view_column_set_expand (column, FALSE);
- gtk_tree_view_append_column (GTK_TREE_VIEW (self->search_view), column);
-
- renderer = gtk_cell_renderer_text_new ();
- g_object_set (renderer,
- "xpad", 0,
- NULL);
- column = gtk_tree_view_column_new_with_attributes ("Name", renderer,
- "text", COL_NAME,
- NULL);
- gtk_tree_view_column_set_expand (column, FALSE);
- gtk_tree_view_append_column (GTK_TREE_VIEW (self->search_view), column);
-
- renderer = gd_styled_text_renderer_new ();
- gd_styled_text_renderer_add_class (GD_STYLED_TEXT_RENDERER (renderer), "dim-label");
- g_object_set (renderer,
- "xpad", 15,
- "ellipsize", PANGO_ELLIPSIZE_END,
- NULL);
- column = gtk_tree_view_column_new_with_attributes ("Description", renderer,
- "text", COL_DESCRIPTION,
- NULL);
- gtk_tree_view_column_set_expand (column, TRUE);
- gtk_tree_view_append_column (GTK_TREE_VIEW (self->search_view), column);
-
- gtk_container_add (GTK_CONTAINER (self->search_scrolled), search_view);
-
- g_signal_connect (self->search_view, "row-activated",
- G_CALLBACK (on_search_row_activated), self);
- g_signal_connect (self->search_view, "button-press-event",
- G_CALLBACK (on_search_button_press_event), self);
-
- self->filter_string = g_strdup ("");
-
- gtk_widget_show (self->search_view);
-}
static void
setup_model (CcWindow *shell)
@@ -924,7 +718,6 @@ cc_window_dispose (GObject *object)
}
g_clear_object (&self->store);
- g_clear_object (&self->search_filter);
g_clear_object (&self->active_panel);
G_OBJECT_CLASS (cc_window_parent_class)->dispose (object);
@@ -941,9 +734,6 @@ cc_window_finalize (GObject *object)
self->previous_panels = NULL;
}
- g_free (self->filter_string);
- g_strfreev (self->filter_terms);
-
g_hash_table_remove_all (self->id_to_row);
g_hash_table_destroy (self->id_to_row);
@@ -987,8 +777,8 @@ cc_window_class_init (CcWindowClass *klass)
gtk_widget_class_bind_template_callback (widget_class, gdk_window_set_cb);
gtk_widget_class_bind_template_callback (widget_class, row_selected_cb);
+ gtk_widget_class_bind_template_callback (widget_class, search_entry_activate_cb);
gtk_widget_class_bind_template_callback (widget_class, search_entry_changed_cb);
- gtk_widget_class_bind_template_callback (widget_class, search_entry_key_press_event_cb);
gtk_widget_class_bind_template_callback (widget_class, sidelist_size_allocate_cb);
gtk_widget_class_bind_template_callback (widget_class, stack_page_notify_cb);
gtk_widget_class_bind_template_callback (widget_class, window_map_event_cb);
@@ -1014,9 +804,6 @@ window_key_press_event (GtkWidget *win,
gboolean retval;
GdkModifierType state;
gboolean is_rtl;
- gboolean overview;
- gboolean search;
- const gchar *id;
retval = GDK_EVENT_PROPAGATE;
state = event->state;
@@ -1025,12 +812,7 @@ window_key_press_event (GtkWidget *win,
state = state & gtk_accelerator_get_default_mod_mask ();
is_rtl = gtk_widget_get_direction (win) == GTK_TEXT_DIR_RTL;
- id = gtk_stack_get_visible_child_name (GTK_STACK (self->stack));
- overview = g_str_equal (id, OVERVIEW_PAGE);
- search = g_str_equal (id, SEARCH_PAGE);
-
- if ((overview || search) &&
- gtk_search_bar_handle_event (GTK_SEARCH_BAR (self->search_bar), (GdkEvent*) event) == GDK_EVENT_STOP)
+ if (gtk_search_bar_handle_event (GTK_SEARCH_BAR (self->search_bar), (GdkEvent*) event) == GDK_EVENT_STOP)
return GDK_EVENT_STOP;
if (state == GDK_CONTROL_MASK)
@@ -1041,8 +823,6 @@ window_key_press_event (GtkWidget *win,
case GDK_KEY_S:
case GDK_KEY_f:
case GDK_KEY_F:
- if (!overview && !search)
- break;
retval = !gtk_search_bar_get_search_mode (GTK_SEARCH_BAR (self->search_bar));
gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (self->search_bar), retval);
if (retval)
@@ -1056,18 +836,10 @@ window_key_press_event (GtkWidget *win,
break;
case GDK_KEY_W:
case GDK_KEY_w:
- if (!overview)
- shell_show_overview_page (self);
retval = GDK_EVENT_STOP;
break;
}
}
- else if (state == GDK_MOD1_MASK && event->keyval == GDK_KEY_Up)
- {
- if (!overview)
- shell_show_overview_page (self);
- retval = GDK_EVENT_STOP;
- }
else if ((!is_rtl && state == GDK_MOD1_MASK && event->keyval == GDK_KEY_Left) ||
(is_rtl && state == GDK_MOD1_MASK && event->keyval == GDK_KEY_Right) ||
event->keyval == GDK_KEY_Back)
@@ -1075,19 +847,8 @@ window_key_press_event (GtkWidget *win,
go_to_previous_panel (self);
retval = GDK_EVENT_STOP;
}
- return retval;
-}
-static void
-create_search_page (CcWindow *self)
-{
- self->search_scrolled = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (self->search_scrolled),
- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
- gtk_stack_add_named (GTK_STACK (self->stack), self->search_scrolled, SEARCH_PAGE);
-
- /* setup search functionality */
- setup_search (self);
+ return retval;
}
static void
@@ -1102,7 +863,8 @@ create_window (CcWindow *self)
* not tracked.
*/
self->listbox = gtk_list_box_new ();
- gtk_list_box_set_selection_mode (GTK_LIST_BOX (self->listbox), GTK_SELECTION_SINGLE);
+ gtk_list_box_set_selection_mode (GTK_LIST_BOX (self->listbox), GTK_SELECTION_BROWSE);
+ gtk_list_box_set_filter_func (GTK_LIST_BOX (self->listbox), filter_func, self, NULL);
g_signal_connect (self->listbox, "row-selected", G_CALLBACK (row_selected_cb), self);
@@ -1110,7 +872,6 @@ create_window (CcWindow *self)
gtk_widget_show (self->listbox);
setup_model (self);
- create_search_page (self);
/* connect various signals */
g_signal_connect_after (self, "key_press_event",
diff --git a/shell/window.ui b/shell/window.ui
index b0cd3cd..67c3421 100644
--- a/shell/window.ui
+++ b/shell/window.ui
@@ -33,8 +33,8 @@
<property name="primary_icon_name">edit-find-symbolic</property>
<property name="primary_icon_activatable">False</property>
<property name="primary_icon_sensitive">False</property>
+ <signal name="activate" handler="search_entry_activate_cb" object="CcWindow"
swapped="no" />
<signal name="search-changed" handler="search_entry_changed_cb" object="CcWindow"
swapped="no" />
- <signal name="key-press-event" handler="search_entry_key_press_event_cb"
object="CcWindow" swapped="no" />
</object>
</child>
</object>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]