[Xfce4-commits] <exo:master> Add search filter to the icon chooser dialog.
Nick Schermer
noreply at xfce.org
Sun Feb 14 17:56:01 CET 2010
Updating branch refs/heads/master
to 3b0f4534bec8a38d54785eaa10fb0d0ad46760a6 (commit)
from 708cad4d7374373c9e18fe659b231abb4962b18c (commit)
commit 3b0f4534bec8a38d54785eaa10fb0d0ad46760a6
Author: Nick Schermer <nick at xfce.org>
Date: Sun Feb 14 17:47:01 2010 +0100
Add search filter to the icon chooser dialog.
Also combine the multiple version of the model set
code into 1 function.
exo/exo-icon-chooser-dialog.c | 239 +++++++++++++++++++++++++++-------------
1 files changed, 161 insertions(+), 78 deletions(-)
diff --git a/exo/exo-icon-chooser-dialog.c b/exo/exo-icon-chooser-dialog.c
index 87e7e1c..0a68c33 100644
--- a/exo/exo-icon-chooser-dialog.c
+++ b/exo/exo-icon-chooser-dialog.c
@@ -40,6 +40,7 @@
#include <exo/exo-icon-chooser-dialog.h>
#include <exo/exo-icon-chooser-model.h>
#include <exo/exo-icon-view.h>
+#include <exo/exo-string.h>
#include <exo/exo-private.h>
#include <exo/exo-alias.h>
@@ -63,29 +64,36 @@
-static void exo_icon_chooser_dialog_style_set (GtkWidget *widget,
- GtkStyle *previous_style);
-static void exo_icon_chooser_dialog_screen_changed (GtkWidget *widget,
- GdkScreen *previous_screen);
-static void exo_icon_chooser_dialog_close (GtkDialog *dialog);
-static gboolean exo_icon_chooser_dialog_separator_func (GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer user_data);
-static gboolean exo_icon_chooser_dialog_visible_func (GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer user_data);
-static void exo_icon_chooser_dialog_combo_changed (GtkWidget *combo,
- ExoIconChooserDialog *icon_chooser_dialog);
-static void exo_icon_chooser_dialog_selection_changed (ExoIconChooserDialog *icon_chooser_dialog);
+static void exo_icon_chooser_dialog_finalize (GObject *object);
+static void exo_icon_chooser_dialog_style_set (GtkWidget *widget,
+ GtkStyle *previous_style);
+static void exo_icon_chooser_dialog_screen_changed (GtkWidget *widget,
+ GdkScreen *previous_screen);
+static void exo_icon_chooser_dialog_close (GtkDialog *dialog);
+static void exo_icon_chooser_dialog_set_model (ExoIconChooserDialog *dialog);
+static gboolean exo_icon_chooser_dialog_separator_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data);
+static gboolean exo_icon_chooser_dialog_visible_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data);
+static gboolean exo_icon_chooser_dialog_start_interactive_search (ExoIconChooserDialog *icon_chooser_dialog);
+static void exo_icon_chooser_dialog_combo_changed (GtkWidget *combo,
+ ExoIconChooserDialog *icon_chooser_dialog);
+static void exo_icon_chooser_dialog_entry_changed (GtkWidget *entry,
+ ExoIconChooserDialog *icon_chooser_dialog);
+static void exo_icon_chooser_dialog_selection_changed (ExoIconChooserDialog *icon_chooser_dialog);
struct _ExoIconChooserDialogPrivate
{
GtkWidget *combo;
+ GtkWidget *entry;
GtkWidget *icon_chooser;
GtkWidget *file_chooser;
GtkWidget *file_preview;
+ gchar *casefolded_text;
};
@@ -135,6 +143,7 @@ G_DEFINE_TYPE (ExoIconChooserDialog, exo_icon_chooser_dialog, GTK_TYPE_DIALOG)
static void
exo_icon_chooser_dialog_class_init (ExoIconChooserDialogClass *klass)
{
+ GObjectClass *gobject_class;
GtkDialogClass *gtkdialog_class;
GtkWidgetClass *gtkwidget_class;
GtkBindingSet *binding_set;
@@ -142,6 +151,9 @@ exo_icon_chooser_dialog_class_init (ExoIconChooserDialogClass *klass)
/* add our private data to the type's instances */
g_type_class_add_private (klass, sizeof (ExoIconChooserDialogPrivate));
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = exo_icon_chooser_dialog_finalize;
+
gtkwidget_class = GTK_WIDGET_CLASS (klass);
gtkwidget_class->style_set = exo_icon_chooser_dialog_style_set;
gtkwidget_class->screen_changed = exo_icon_chooser_dialog_screen_changed;
@@ -162,13 +174,11 @@ exo_icon_chooser_dialog_init (ExoIconChooserDialog *icon_chooser_dialog)
{
ExoIconChooserDialogPrivate *priv = EXO_ICON_CHOOSER_DIALOG_GET_PRIVATE (icon_chooser_dialog);
ExoIconChooserContext context;
- ExoIconChooserModel *chooser_model;
GtkCellRenderer *renderer;
GtkFileFilter *filter;
- GtkTreeModel *filter_model;
GtkWidget *scrolled_window;
GtkWidget *label;
- GtkWidget *hbox;
+ GtkWidget *table;
GtkWidget *vbox;
/* initialize the library's i18n support */
@@ -184,27 +194,40 @@ exo_icon_chooser_dialog_init (ExoIconChooserDialog *icon_chooser_dialog)
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (icon_chooser_dialog)->vbox), vbox, TRUE, TRUE, 0);
gtk_widget_show (vbox);
- /* add the header box */
- hbox = gtk_hbox_new (FALSE, 12);
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
- gtk_widget_show (hbox);
+ /* add the header table */
+ table = gtk_table_new (2, 2, FALSE);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 12);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+ gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
+ gtk_widget_show (table);
- /* setup the header label */
+ /* setup the context combo box */
label = gtk_label_new_with_mnemonic (_("Select _icon from:"));
gtk_misc_set_alignment (GTK_MISC (label), 0.0f, 0.5f);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
gtk_widget_show (label);
- /* setup the context combo box */
priv->combo = gtk_combo_box_new_text ();
for (context = 0; context < G_N_ELEMENTS (CONTEXT_TITLES); ++context)
gtk_combo_box_append_text (GTK_COMBO_BOX (priv->combo), _(CONTEXT_TITLES[context]));
gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (priv->combo), exo_icon_chooser_dialog_separator_func, icon_chooser_dialog, NULL);
g_signal_connect (G_OBJECT (priv->combo), "changed", G_CALLBACK (exo_icon_chooser_dialog_combo_changed), icon_chooser_dialog);
- gtk_box_pack_start (GTK_BOX (hbox), priv->combo, TRUE, TRUE, 0);
+ gtk_table_attach (GTK_TABLE (table), priv->combo, 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->combo);
gtk_widget_show (priv->combo);
+ /* search filter */
+ label = gtk_label_new_with_mnemonic (_("_Search icon:"));
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0f, 0.5f);
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
+ gtk_widget_show (label);
+
+ priv->entry = gtk_entry_new ();
+ gtk_table_attach (GTK_TABLE (table), priv->entry, 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->entry);
+ g_signal_connect (G_OBJECT (priv->entry), "changed", G_CALLBACK (exo_icon_chooser_dialog_entry_changed), icon_chooser_dialog);
+ gtk_widget_show (priv->entry);
+
/* setup the scrolled window for the icon chooser */
scrolled_window = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_ETCHED_IN);
@@ -217,7 +240,9 @@ exo_icon_chooser_dialog_init (ExoIconChooserDialog *icon_chooser_dialog)
exo_binding_new (G_OBJECT (priv->icon_chooser), "visible", G_OBJECT (scrolled_window), "visible");
g_signal_connect_swapped (priv->icon_chooser, "item-activated", G_CALLBACK (gtk_window_activate_default), icon_chooser_dialog);
g_signal_connect_swapped (priv->icon_chooser, "selection-changed", G_CALLBACK (exo_icon_chooser_dialog_selection_changed), icon_chooser_dialog);
+ g_signal_connect_swapped (priv->icon_chooser, "start-interactive-search", G_CALLBACK (exo_icon_chooser_dialog_start_interactive_search), icon_chooser_dialog);
gtk_container_add (GTK_CONTAINER (scrolled_window), priv->icon_chooser);
+ gtk_window_set_focus (GTK_WINDOW (icon_chooser_dialog), priv->icon_chooser);
gtk_widget_show (priv->icon_chooser);
/* setup the icon renderer */
@@ -252,16 +277,8 @@ exo_icon_chooser_dialog_init (ExoIconChooserDialog *icon_chooser_dialog)
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (priv->file_chooser), filter);
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (priv->file_chooser), filter);
- /* setup the filtered icon model for the icon chooser */
- chooser_model = _exo_icon_chooser_model_get_for_widget (GTK_WIDGET (icon_chooser_dialog));
- filter_model = gtk_tree_model_filter_new (GTK_TREE_MODEL (chooser_model), NULL);
- gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter_model), exo_icon_chooser_dialog_visible_func, icon_chooser_dialog, NULL);
- exo_icon_view_set_model (EXO_ICON_VIEW (priv->icon_chooser), filter_model);
- g_object_unref (G_OBJECT (chooser_model));
- g_object_unref (G_OBJECT (filter_model));
-
- /* enable search on the display name */
- exo_icon_view_set_search_column (EXO_ICON_VIEW (priv->icon_chooser), EXO_ICON_CHOOSER_MODEL_COLUMN_DISPLAY_NAME);
+ /* update the model */
+ exo_icon_chooser_dialog_set_model (icon_chooser_dialog);
/* default to "Application Icons", since thats what users probably expect to see */
gtk_combo_box_set_active (GTK_COMBO_BOX (priv->combo), EXO_ICON_CHOOSER_CONTEXT_APPLICATIONS);
@@ -272,34 +289,27 @@ exo_icon_chooser_dialog_init (ExoIconChooserDialog *icon_chooser_dialog)
static void
+exo_icon_chooser_dialog_finalize (GObject *object)
+{
+ ExoIconChooserDialogPrivate *priv = EXO_ICON_CHOOSER_DIALOG_GET_PRIVATE (object);
+
+ g_free (priv->casefolded_text);
+
+ (*G_OBJECT_CLASS (exo_icon_chooser_dialog_parent_class)->finalize) (object);
+}
+
+
+
+static void
exo_icon_chooser_dialog_style_set (GtkWidget *widget,
GtkStyle *previous_style)
{
- ExoIconChooserDialogPrivate *priv = EXO_ICON_CHOOSER_DIALOG_GET_PRIVATE (widget);
- ExoIconChooserModel *model;
- GtkTreeModel *filter;
-
/* call the parent's style_set method */
if (GTK_WIDGET_CLASS (exo_icon_chooser_dialog_parent_class)->style_set != NULL)
(*GTK_WIDGET_CLASS (exo_icon_chooser_dialog_parent_class)->style_set) (widget, previous_style);
- /* determine the icon chooser model for the widget */
- model = _exo_icon_chooser_model_get_for_widget (widget);
-
- /* check if we have a new model here */
- filter = exo_icon_view_get_model (EXO_ICON_VIEW (priv->icon_chooser));
- if (GTK_TREE_MODEL (model) != gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter)))
- {
- /* setup a new filter for the model */
- filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (model), NULL);
- gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter), exo_icon_chooser_dialog_visible_func, widget, NULL);
- exo_icon_view_set_model (EXO_ICON_VIEW (priv->icon_chooser), filter);
- g_object_unref (G_OBJECT (filter));
-
- /* enable search on the display name */
- exo_icon_view_set_search_column (EXO_ICON_VIEW (priv->icon_chooser), EXO_ICON_CHOOSER_MODEL_COLUMN_DISPLAY_NAME);
- }
- g_object_unref (G_OBJECT (model));
+ /* update the model */
+ exo_icon_chooser_dialog_set_model (EXO_ICON_CHOOSER_DIALOG (widget));
}
@@ -308,31 +318,12 @@ static void
exo_icon_chooser_dialog_screen_changed (GtkWidget *widget,
GdkScreen *previous_screen)
{
- ExoIconChooserDialogPrivate *priv = EXO_ICON_CHOOSER_DIALOG_GET_PRIVATE (widget);
- ExoIconChooserModel *model;
- GtkTreeModel *filter;
-
/* call the parent's screen_changed method */
if (GTK_WIDGET_CLASS (exo_icon_chooser_dialog_parent_class)->screen_changed != NULL)
(*GTK_WIDGET_CLASS (exo_icon_chooser_dialog_parent_class)->screen_changed) (widget, previous_screen);
- /* determine the icon chooser model for the widget */
- model = _exo_icon_chooser_model_get_for_widget (widget);
-
- /* check if we have a new model here */
- filter = exo_icon_view_get_model (EXO_ICON_VIEW (priv->icon_chooser));
- if (GTK_TREE_MODEL (model) != gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter)))
- {
- /* setup a new filter for the model */
- filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (model), NULL);
- gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter), exo_icon_chooser_dialog_visible_func, widget, NULL);
- exo_icon_view_set_model (EXO_ICON_VIEW (priv->icon_chooser), filter);
- g_object_unref (G_OBJECT (filter));
-
- /* enable search on the display name */
- exo_icon_view_set_search_column (EXO_ICON_VIEW (priv->icon_chooser), EXO_ICON_CHOOSER_MODEL_COLUMN_DISPLAY_NAME);
- }
- g_object_unref (G_OBJECT (model));
+ /* update the model */
+ exo_icon_chooser_dialog_set_model (EXO_ICON_CHOOSER_DIALOG (widget));
}
@@ -356,6 +347,35 @@ exo_icon_chooser_dialog_close (GtkDialog *dialog)
+static void
+exo_icon_chooser_dialog_set_model (ExoIconChooserDialog *dialog)
+{
+ ExoIconChooserDialogPrivate *priv = EXO_ICON_CHOOSER_DIALOG_GET_PRIVATE (dialog);
+ ExoIconChooserModel *model;
+ GtkTreeModel *filter;
+
+ /* determine the icon chooser model for the widget */
+ model = _exo_icon_chooser_model_get_for_widget (GTK_WIDGET (dialog));
+
+ /* check if we have a new model here */
+ filter = exo_icon_view_get_model (EXO_ICON_VIEW (priv->icon_chooser));
+ if (filter == NULL
+ || GTK_TREE_MODEL (model) != gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter)))
+ {
+ /* setup a new filter for the model */
+ filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (model), NULL);
+ gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter), exo_icon_chooser_dialog_visible_func, dialog, NULL);
+ exo_icon_view_set_model (EXO_ICON_VIEW (priv->icon_chooser), filter);
+ g_object_unref (G_OBJECT (filter));
+
+ /* enable search on the display name */
+ exo_icon_view_set_search_column (EXO_ICON_VIEW (priv->icon_chooser), EXO_ICON_CHOOSER_MODEL_COLUMN_DISPLAY_NAME);
+ }
+ g_object_unref (G_OBJECT (model));
+}
+
+
+
static gboolean
exo_icon_chooser_dialog_separator_func (GtkTreeModel *model,
GtkTreeIter *iter,
@@ -382,6 +402,10 @@ exo_icon_chooser_dialog_visible_func (GtkTreeModel *model,
ExoIconChooserDialogPrivate *priv = EXO_ICON_CHOOSER_DIALOG_GET_PRIVATE (user_data);
guint icon_chooser_context;
guint item_context;
+ gchar *normalized;
+ gchar *name;
+ gchar *name_casefolded;
+ gboolean visible;
/* check if we need to test the context */
icon_chooser_context = gtk_combo_box_get_active (GTK_COMBO_BOX (priv->combo));
@@ -391,7 +415,26 @@ exo_icon_chooser_dialog_visible_func (GtkTreeModel *model,
gtk_tree_model_get (model, iter, EXO_ICON_CHOOSER_MODEL_COLUMN_CONTEXT, &item_context, -1);
/* ...and compare them */
- return (icon_chooser_context == item_context);
+ if (icon_chooser_context != item_context)
+ return FALSE;
+ }
+
+ /* filter by string */
+ if (priv->casefolded_text != NULL)
+ {
+ gtk_tree_model_get (model, iter, EXO_ICON_CHOOSER_MODEL_COLUMN_DISPLAY_NAME, &name, -1);
+
+ /* casefold the name */
+ normalized = g_utf8_normalize (name, -1, G_NORMALIZE_ALL);
+ g_free (name);
+ name_casefolded = g_utf8_casefold (normalized, -1);
+ g_free (normalized);
+
+ visible = (strstr (name_casefolded, priv->casefolded_text) != NULL);
+
+ g_free (name_casefolded);
+
+ return visible;
}
/* all icons should be shown */
@@ -400,6 +443,18 @@ exo_icon_chooser_dialog_visible_func (GtkTreeModel *model,
+static gboolean
+exo_icon_chooser_dialog_start_interactive_search (ExoIconChooserDialog *icon_chooser_dialog)
+{
+ ExoIconChooserDialogPrivate *priv = EXO_ICON_CHOOSER_DIALOG_GET_PRIVATE (icon_chooser_dialog);
+
+ gtk_window_set_focus (GTK_WINDOW (icon_chooser_dialog), priv->entry);
+
+ return TRUE;
+}
+
+
+
static void
exo_icon_chooser_dialog_combo_changed (GtkWidget *combo,
ExoIconChooserDialog *icon_chooser_dialog)
@@ -446,6 +501,34 @@ exo_icon_chooser_dialog_combo_changed (GtkWidget *combo,
static void
+exo_icon_chooser_dialog_entry_changed (GtkWidget *combo,
+ ExoIconChooserDialog *icon_chooser_dialog)
+{
+ ExoIconChooserDialogPrivate *priv = EXO_ICON_CHOOSER_DIALOG_GET_PRIVATE (icon_chooser_dialog);
+ const gchar *text;
+ gchar *normalized;
+ GtkTreeModel *model;
+
+ g_free (priv->casefolded_text);
+ priv->casefolded_text = NULL;
+
+ text = gtk_entry_get_text (GTK_ENTRY (priv->entry));
+ if (!exo_str_is_empty (text))
+ {
+ /* case fold the search string */
+ normalized = g_utf8_normalize (text, -1, G_NORMALIZE_ALL);
+ priv->casefolded_text = g_utf8_casefold (normalized, -1);
+ g_free (normalized);
+ }
+
+ model = exo_icon_view_get_model (EXO_ICON_VIEW (priv->icon_chooser));
+ if (G_LIKELY (model != NULL))
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (model));
+}
+
+
+
+static void
exo_icon_chooser_dialog_selection_changed (ExoIconChooserDialog *icon_chooser_dialog)
{
gchar *icon;
More information about the Xfce4-commits
mailing list