mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-30 15:31:34 +00:00
441a9dfa80
Port this from ::populate-popup to the new context menu api. At the same time, fix some parts of the demo that were broken since it was changed to use GtkStearchEntry.
321 lines
8.8 KiB
C
321 lines
8.8 KiB
C
/* Entry/Search Entry
|
|
*
|
|
* GtkEntry allows to display icons and progress information.
|
|
* This demo shows how to use these features in a search entry.
|
|
*/
|
|
|
|
#include <glib/gi18n.h>
|
|
#include <gtk/gtk.h>
|
|
|
|
static GtkWidget *window = NULL;
|
|
static GtkWidget *notebook = NULL;
|
|
static GSimpleActionGroup *actions = NULL;
|
|
|
|
static guint search_progress_id = 0;
|
|
static guint finish_search_id = 0;
|
|
|
|
static void
|
|
show_find_button (void)
|
|
{
|
|
gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 0);
|
|
}
|
|
|
|
static void
|
|
show_cancel_button (void)
|
|
{
|
|
gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 1);
|
|
}
|
|
|
|
static gboolean
|
|
search_progress (gpointer data)
|
|
{
|
|
gtk_entry_progress_pulse (GTK_ENTRY (data));
|
|
return G_SOURCE_CONTINUE;
|
|
}
|
|
|
|
static void
|
|
search_progress_done (GtkEntry *entry)
|
|
{
|
|
gtk_entry_set_progress_fraction (entry, 0.0);
|
|
}
|
|
|
|
static gboolean
|
|
finish_search (GtkButton *button)
|
|
{
|
|
show_find_button ();
|
|
if (search_progress_id)
|
|
{
|
|
g_source_remove (search_progress_id);
|
|
search_progress_id = 0;
|
|
}
|
|
return G_SOURCE_REMOVE;
|
|
}
|
|
|
|
static gboolean
|
|
start_search_feedback (gpointer data)
|
|
{
|
|
search_progress_id = g_timeout_add_full (G_PRIORITY_DEFAULT, 100,
|
|
(GSourceFunc)search_progress, data,
|
|
(GDestroyNotify)search_progress_done);
|
|
return G_SOURCE_REMOVE;
|
|
}
|
|
|
|
static void
|
|
start_search (GtkButton *button,
|
|
GtkEntry *entry)
|
|
{
|
|
show_cancel_button ();
|
|
search_progress_id = g_timeout_add_seconds (1, (GSourceFunc)start_search_feedback, entry);
|
|
finish_search_id = g_timeout_add_seconds (15, (GSourceFunc)finish_search, button);
|
|
}
|
|
|
|
|
|
static void
|
|
stop_search (GtkButton *button,
|
|
gpointer data)
|
|
{
|
|
if (finish_search_id)
|
|
{
|
|
g_source_remove (finish_search_id);
|
|
finish_search_id = 0;
|
|
}
|
|
finish_search (button);
|
|
}
|
|
|
|
static void
|
|
clear_entry (GSimpleAction *action,
|
|
GVariant *parameter,
|
|
gpointer user_data)
|
|
{
|
|
GtkEditable *editable = user_data;
|
|
|
|
gtk_editable_set_text (editable, "");
|
|
}
|
|
|
|
static void
|
|
set_search_by (GSimpleAction *action,
|
|
GVariant *value,
|
|
gpointer user_data)
|
|
{
|
|
GtkEntry *entry = user_data;
|
|
const char *term;
|
|
|
|
term = g_variant_get_string (value, NULL);
|
|
|
|
g_simple_action_set_state (action, value);
|
|
|
|
if (g_str_equal (term, "name"))
|
|
{
|
|
gtk_entry_set_icon_tooltip_text (entry, GTK_ENTRY_ICON_PRIMARY, "Search by name");
|
|
gtk_entry_set_placeholder_text (entry, "name");
|
|
}
|
|
else if (g_str_equal (term, "description"))
|
|
{
|
|
gtk_entry_set_icon_tooltip_text (entry, GTK_ENTRY_ICON_PRIMARY, "Search by description");
|
|
gtk_entry_set_placeholder_text (entry, "description");
|
|
}
|
|
else if (g_str_equal (term, "filename"))
|
|
{
|
|
gtk_entry_set_icon_tooltip_text (entry, GTK_ENTRY_ICON_PRIMARY, "Search by file name");
|
|
gtk_entry_set_placeholder_text (entry, "file name");
|
|
}
|
|
}
|
|
|
|
static void
|
|
icon_press_cb (GtkEntry *entry,
|
|
gint position,
|
|
gpointer data)
|
|
{
|
|
if (position == GTK_ENTRY_ICON_PRIMARY)
|
|
{
|
|
GAction *action;
|
|
GVariant *state;
|
|
GVariant *new_state;
|
|
const char *s;
|
|
|
|
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "search-by");
|
|
state = g_action_get_state (action);
|
|
s = g_variant_get_string (state, NULL);
|
|
|
|
if (g_str_equal (s, "name"))
|
|
new_state = g_variant_new_string ("description");
|
|
else if (g_str_equal (s, "description"))
|
|
new_state = g_variant_new_string ("filename");
|
|
else if (g_str_equal (s, "filename"))
|
|
new_state = g_variant_new_string ("name");
|
|
else
|
|
g_assert_not_reached ();
|
|
|
|
g_action_change_state (action, new_state);
|
|
g_variant_unref (state);
|
|
}
|
|
}
|
|
|
|
static void
|
|
activate_cb (GtkEntry *entry,
|
|
GtkButton *button)
|
|
{
|
|
if (search_progress_id != 0)
|
|
return;
|
|
|
|
start_search (button, entry);
|
|
}
|
|
|
|
static void
|
|
search_entry_destroyed (GtkWidget *widget)
|
|
{
|
|
if (finish_search_id != 0)
|
|
{
|
|
g_source_remove (finish_search_id);
|
|
finish_search_id = 0;
|
|
}
|
|
|
|
if (search_progress_id != 0)
|
|
{
|
|
g_source_remove (search_progress_id);
|
|
search_progress_id = 0;
|
|
}
|
|
|
|
window = NULL;
|
|
}
|
|
|
|
static void
|
|
text_changed (GObject *object,
|
|
GParamSpec *pspec,
|
|
gpointer data)
|
|
{
|
|
GtkEntry *entry = GTK_ENTRY (object);
|
|
GActionMap *actions = data;
|
|
GAction *action;
|
|
gboolean has_text;
|
|
|
|
has_text = gtk_entry_get_text_length (entry) > 0;
|
|
|
|
action = g_action_map_lookup_action (actions, "clear");
|
|
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), has_text);
|
|
}
|
|
|
|
static GMenuModel *
|
|
create_search_menu_model (void)
|
|
{
|
|
GMenu *menu = g_menu_new ();
|
|
g_menu_append (menu, _("Name"), "search.search-by::name");
|
|
g_menu_append (menu, _("Description"), "search.search-by::description");
|
|
g_menu_append (menu, _("File Name"), "search.search-by::filename");
|
|
|
|
return G_MENU_MODEL (menu);
|
|
}
|
|
|
|
static void
|
|
entry_add_to_context_menu (GtkEntry *entry)
|
|
{
|
|
GMenu *menu;
|
|
GActionEntry entries[] = {
|
|
{ "clear", clear_entry, NULL, NULL, NULL },
|
|
{ "search-by", NULL, "s", "'name'", set_search_by }
|
|
};
|
|
GMenuModel *submenu;
|
|
GMenuItem *item;
|
|
|
|
actions = g_simple_action_group_new ();
|
|
g_action_map_add_action_entries (G_ACTION_MAP (actions), entries, G_N_ELEMENTS(entries), entry);
|
|
gtk_widget_insert_action_group (GTK_WIDGET (entry), "search", G_ACTION_GROUP (actions));
|
|
|
|
menu = g_menu_new ();
|
|
item = g_menu_item_new (_("C_lear"), "search.clear");
|
|
g_menu_item_set_attribute (item, "touch-icon", "s", "edit-clear-symbolic");
|
|
g_menu_append_item (G_MENU (menu), item);
|
|
g_object_unref (item);
|
|
|
|
submenu = create_search_menu_model ();
|
|
g_menu_append_submenu (menu, _("Search By"), submenu);
|
|
g_object_unref (submenu);
|
|
|
|
gtk_entry_set_extra_menu (entry, G_MENU_MODEL (menu));
|
|
|
|
g_object_unref (menu);
|
|
|
|
g_signal_connect (entry, "notify::text", G_CALLBACK (text_changed), actions);
|
|
}
|
|
|
|
GtkWidget *
|
|
do_search_entry (GtkWidget *do_widget)
|
|
{
|
|
GtkWidget *vbox;
|
|
GtkWidget *hbox;
|
|
GtkWidget *label;
|
|
GtkWidget *entry;
|
|
GtkWidget *find_button;
|
|
GtkWidget *cancel_button;
|
|
|
|
if (!window)
|
|
{
|
|
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
|
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
|
gtk_window_set_title (GTK_WINDOW (window), "Search Entry");
|
|
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
|
g_signal_connect (window, "destroy",
|
|
G_CALLBACK (search_entry_destroyed), &window);
|
|
|
|
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
|
|
g_object_set (vbox, "margin", 5, NULL);
|
|
gtk_container_add (GTK_CONTAINER (window), vbox);
|
|
|
|
label = gtk_label_new (NULL);
|
|
gtk_label_set_markup (GTK_LABEL (label), "Search entry demo");
|
|
gtk_container_add (GTK_CONTAINER (vbox), label);
|
|
|
|
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
|
|
gtk_container_add (GTK_CONTAINER (vbox), hbox);
|
|
|
|
/* Create our entry */
|
|
entry = gtk_entry_new ();
|
|
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry),
|
|
GTK_ENTRY_ICON_PRIMARY,
|
|
"edit-find-symbolic");
|
|
gtk_container_add (GTK_CONTAINER (hbox), entry);
|
|
|
|
/* Create the find and cancel buttons */
|
|
notebook = gtk_notebook_new ();
|
|
gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
|
|
gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
|
|
gtk_container_add (GTK_CONTAINER (hbox), notebook);
|
|
|
|
find_button = gtk_button_new_with_label ("Find");
|
|
g_signal_connect (find_button, "clicked",
|
|
G_CALLBACK (start_search), entry);
|
|
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), find_button, NULL);
|
|
gtk_widget_show (find_button);
|
|
|
|
cancel_button = gtk_button_new_with_label ("Cancel");
|
|
g_signal_connect (cancel_button, "clicked",
|
|
G_CALLBACK (stop_search), NULL);
|
|
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), cancel_button, NULL);
|
|
gtk_widget_show (cancel_button);
|
|
|
|
/* Set up the search icon */
|
|
GVariant *value = g_variant_ref_sink (g_variant_new_string ("name"));
|
|
set_search_by (NULL, value, entry);
|
|
g_variant_unref (value);
|
|
|
|
gtk_entry_set_icon_activatable (GTK_ENTRY (entry), GTK_ENTRY_ICON_PRIMARY, TRUE);
|
|
gtk_entry_set_icon_sensitive (GTK_ENTRY (entry), GTK_ENTRY_ICON_PRIMARY, TRUE);
|
|
|
|
g_signal_connect (entry, "icon-press", G_CALLBACK (icon_press_cb), NULL);
|
|
g_signal_connect (entry, "activate", G_CALLBACK (activate_cb), NULL);
|
|
|
|
/* add accessible alternatives for icon functionality */
|
|
entry_add_to_context_menu (GTK_ENTRY (entry));
|
|
}
|
|
|
|
if (!gtk_widget_get_visible (window))
|
|
gtk_widget_show (window);
|
|
else
|
|
{
|
|
g_clear_object (&actions);
|
|
gtk_widget_destroy (window);
|
|
}
|
|
|
|
return window;
|
|
}
|