2 * Copyright (C) 2006 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "pan-view-filter.h"
28 #include "ui_tabcomp.h"
31 PanViewFilterUi *pan_filter_ui_new(PanWindow *pw)
33 PanViewFilterUi *ui = g_new0(PanViewFilterUi, 1);
37 // Build the actual filter UI.
38 ui->filter_box = gtk_hbox_new(FALSE, PREF_PAD_SPACE);
39 pref_spacer(ui->filter_box, 0);
40 pref_label_new(ui->filter_box, _("Keyword Filter:"));
42 hbox = gtk_hbox_new(TRUE, PREF_PAD_SPACE);
43 gtk_box_pack_start(GTK_BOX(ui->filter_box), hbox, TRUE, TRUE, 0);
44 gtk_widget_show(hbox);
46 combo = tab_completion_new_with_history(&ui->filter_entry, "", "pan_view_filter", -1,
47 pan_filter_activate_cb, pw);
48 gtk_box_pack_start(GTK_BOX(hbox), combo, TRUE, TRUE, 0);
49 gtk_widget_show(combo);
51 // TODO(xsdg): Figure out whether it's useful to keep this label around.
52 ui->filter_label = gtk_label_new("");
53 //gtk_box_pack_start(GTK_BOX(hbox), ui->filter_label, FALSE, FALSE, 0);
54 //gtk_widget_show(ui->filter_label);
56 ui->filter_kw_hbox = gtk_hbox_new(FALSE, PREF_PAD_SPACE);
57 gtk_box_pack_start(GTK_BOX(hbox), ui->filter_kw_hbox, TRUE, TRUE, 0);
58 gtk_widget_show(ui->filter_kw_hbox);
60 // Build the spin-button to show/hide the filter UI.
61 ui->filter_button = gtk_toggle_button_new();
62 gtk_button_set_relief(GTK_BUTTON(ui->filter_button), GTK_RELIEF_NONE);
63 gtk_button_set_focus_on_click(GTK_BUTTON(ui->filter_button), FALSE);
64 hbox = gtk_hbox_new(FALSE, PREF_PAD_GAP);
65 gtk_container_add(GTK_CONTAINER(ui->filter_button), hbox);
66 gtk_widget_show(hbox);
67 ui->filter_button_arrow = gtk_arrow_new(GTK_ARROW_UP, GTK_SHADOW_NONE);
68 gtk_box_pack_start(GTK_BOX(hbox), ui->filter_button_arrow, FALSE, FALSE, 0);
69 gtk_widget_show(ui->filter_button_arrow);
70 pref_label_new(hbox, _("Filter"));
72 g_signal_connect(G_OBJECT(ui->filter_button), "clicked",
73 G_CALLBACK(pan_filter_toggle_cb), pw);
75 /* Since we're using the GHashTable as a HashSet (in which key and value pointers
76 * are always identical), specifying key _and_ value destructor callbacks will
77 * cause a double-free.
79 ui->filter_kw_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
84 void pan_filter_ui_destroy(PanViewFilterUi **ui_ptr)
86 if (ui_ptr == NULL || *ui_ptr == NULL) return;
88 // Note that g_clear_pointer handles already-NULL pointers.
89 g_clear_pointer(&(*ui_ptr)->filter_kw_table, g_hash_table_destroy);
95 static void pan_filter_status(PanWindow *pw, const gchar *text)
97 gtk_label_set_text(GTK_LABEL(pw->filter_ui->filter_label), (text) ? text : "");
100 static void pan_filter_kw_button_cb(GtkButton *widget, gpointer data)
102 PanWindow *pw = data;
103 PanViewFilterUi *ui = pw->filter_ui;
105 g_hash_table_remove(ui->filter_kw_table, gtk_button_get_label(GTK_BUTTON(widget)));
106 gtk_widget_destroy(GTK_WIDGET(widget));
108 pan_filter_status(pw, _("Removed keyword…"));
109 pan_layout_update(pw);
112 void pan_filter_activate_cb(const gchar *text, gpointer data)
114 GtkWidget *kw_button;
115 PanWindow *pw = data;
116 PanViewFilterUi *ui = pw->filter_ui;
120 gtk_entry_set_text(GTK_ENTRY(ui->filter_entry), "");
122 if (g_hash_table_contains(ui->filter_kw_table, text))
124 pan_filter_status(pw, _("Already added…"));
128 tab_completion_append_to_history(ui->filter_entry, text);
130 g_hash_table_add(ui->filter_kw_table, g_strdup(text));
132 kw_button = gtk_button_new_with_label(text);
133 gtk_box_pack_start(GTK_BOX(ui->filter_kw_hbox), kw_button, FALSE, FALSE, 0);
134 gtk_widget_show(kw_button);
136 g_signal_connect(G_OBJECT(kw_button), "clicked",
137 G_CALLBACK(pan_filter_kw_button_cb), pw);
139 pan_filter_status(pw, _("Added keyword…"));
140 pan_layout_update(pw);
143 void pan_filter_activate(PanWindow *pw)
147 text = g_strdup(gtk_entry_get_text(GTK_ENTRY(pw->filter_ui->filter_entry)));
148 pan_filter_activate_cb(text, pw);
152 void pan_filter_toggle_cb(GtkWidget *button, gpointer data)
154 PanWindow *pw = data;
155 PanViewFilterUi *ui = pw->filter_ui;
158 visible = gtk_widget_get_visible(ui->filter_box);
159 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)) == visible) return;
163 gtk_widget_hide(ui->filter_box);
164 gtk_arrow_set(GTK_ARROW(ui->filter_button_arrow), GTK_ARROW_UP, GTK_SHADOW_NONE);
168 gtk_widget_show(ui->filter_box);
169 gtk_arrow_set(GTK_ARROW(ui->filter_button_arrow), GTK_ARROW_DOWN, GTK_SHADOW_NONE);
170 gtk_widget_grab_focus(ui->filter_entry);
174 void pan_filter_toggle_visible(PanWindow *pw, gboolean enable)
176 PanViewFilterUi *ui = pw->filter_ui;
181 if (gtk_widget_get_visible(ui->filter_box))
183 gtk_widget_grab_focus(ui->filter_entry);
187 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ui->filter_button), TRUE);
192 if (gtk_widget_get_visible(ui->filter_entry))
194 if (gtk_widget_has_focus(ui->filter_entry))
196 gtk_widget_grab_focus(GTK_WIDGET(pw->imd->widget));
198 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ui->filter_button), FALSE);