#include "print.h"
#include "rcfile.h"
#include "search.h"
+#include "search_and_run.h"
#include "slideshow.h"
#include "ui_fileops.h"
#include "ui_menu.h"
static gboolean layout_bar_sort_enabled(LayoutWindow *lw);
static void layout_bars_hide_toggle(LayoutWindow *lw);
static void layout_util_sync_views(LayoutWindow *lw);
+static void layout_search_and_run_window_new(LayoutWindow *lw);
/*
*-----------------------------------------------------------------------------
layout_exif_window_new(lw);
}
+static void layout_menu_search_and_run_cb(GtkAction *action, gpointer data)
+{
+ LayoutWindow *lw = data;
+
+ layout_exit_fullscreen(lw);
+ layout_search_and_run_window_new(lw);
+}
+
+
static void layout_menu_float_cb(GtkToggleAction *action, gpointer data)
{
LayoutWindow *lw = data;
{ "StereoMenu", NULL, N_("Stere_o"), NULL, NULL, NULL },
{ "OverlayMenu", NULL, N_("Image _Overlay"), NULL, NULL, NULL },
{ "PluginsMenu", NULL, N_("_Plugins"), NULL, NULL, NULL },
+ { "SarMenu", NULL, N_("S_aR"), NULL, NULL, NULL },
{ "HelpMenu", NULL, N_("_Help"), NULL, NULL, NULL },
{ "FirstImage", GTK_STOCK_GOTO_TOP, N_("_First Image"), "Home", N_("First Image"), CB(layout_menu_image_first_cb) },
{ "NextImage", GTK_STOCK_GO_DOWN, N_("_Next Image"), "space", N_("Next Image"), CB(layout_menu_image_next_cb) },
{ "NextImageAlt1", GTK_STOCK_GO_DOWN, N_("_Next Image"), "Page_Down", N_("Next Image"), CB(layout_menu_image_next_cb) },
- { "ImageForward", GTK_STOCK_GOTO_LAST, N_("Image Forward"), NULL, N_("Image Forward"), CB(layout_menu_image_forward_cb) },
- { "ImageBack", GTK_STOCK_GOTO_FIRST, N_("Image Back"), NULL, N_("Image Back"), CB(layout_menu_image_back_cb) },
+ { "ImageForward", GTK_STOCK_GOTO_LAST, N_("Image Forward"), NULL, N_("Forward in image history"), CB(layout_menu_image_forward_cb) },
+ { "ImageBack", GTK_STOCK_GOTO_FIRST, N_("Image Back"), NULL, N_("Back in image history"), CB(layout_menu_image_back_cb) },
- { "FirstPage", GTK_STOCK_MEDIA_PREVIOUS, N_("_First Page"), NULL, N_( "First Page"), CB(layout_menu_page_first_cb) },
- { "LastPage", GTK_STOCK_MEDIA_NEXT, N_("_Last Page"), NULL, N_("Last Page"), CB(layout_menu_page_last_cb) },
- { "NextPage", GTK_STOCK_MEDIA_FORWARD, N_("_Next Page"), NULL, N_("Next Page"), CB(layout_menu_page_next_cb) },
- { "PrevPage", GTK_STOCK_MEDIA_REWIND, N_("_Previous Page"), NULL, N_("Previous Page"), CB(layout_menu_page_previous_cb) },
+ { "FirstPage",GTK_STOCK_MEDIA_PREVIOUS, N_("_First Page"), NULL, N_( "First Page of multi-page image"), CB(layout_menu_page_first_cb) },
+ { "LastPage", GTK_STOCK_MEDIA_NEXT, N_("_Last Page"), NULL, N_("Last Page of multi-page image"), CB(layout_menu_page_last_cb) },
+ { "NextPage", GTK_STOCK_MEDIA_FORWARD, N_("_Next Page"), NULL, N_("Next Page of multi-page image"), CB(layout_menu_page_next_cb) },
+ { "PrevPage", GTK_STOCK_MEDIA_REWIND, N_("_Previous Page"), NULL, N_("Previous Page of multi-page image"), CB(layout_menu_page_previous_cb) },
- { "NextImageAlt2", GTK_STOCK_GO_DOWN, N_("_Next Image"), "KP_Page_Down", N_("Next Image"), CB(layout_menu_image_next_cb) },
+ { "NextImageAlt2", GTK_STOCK_GO_DOWN, N_("_Next Image"), "KP_Page_Down", N_("Next Image"), CB(layout_menu_image_next_cb) },
{ "LastImage", GTK_STOCK_GOTO_BOTTOM, N_("_Last Image"), "End", N_("Last Image"), CB(layout_menu_image_last_cb) },
- { "Back", GTK_STOCK_GO_BACK, N_("_Back"), NULL, N_("Back"), CB(layout_menu_back_cb) },
- { "Forward", GTK_STOCK_GO_FORWARD, N_("_Forward"), NULL, N_("Forward"), CB(layout_menu_forward_cb) },
- { "Home", GTK_STOCK_HOME, N_("_Home"), NULL, N_("Home"), CB(layout_menu_home_cb) },
- { "Up", GTK_STOCK_GO_UP, N_("_Up"), NULL, N_("Up"), CB(layout_menu_up_cb) },
+ { "Back", GTK_STOCK_GO_BACK, N_("_Back"), NULL, N_("Back in folder history"), CB(layout_menu_back_cb) },
+ { "Forward", GTK_STOCK_GO_FORWARD, N_("_Forward"), NULL, N_("Forward in folder history"), CB(layout_menu_forward_cb) },
+ { "Home", GTK_STOCK_HOME, N_("_Home"), NULL, N_("Home"), CB(layout_menu_home_cb) },
+ { "Up", GTK_STOCK_GO_UP, N_("_Up"), NULL, N_("Up one folder"), CB(layout_menu_up_cb) },
{ "NewWindow", GTK_STOCK_NEW, N_("New _window"), "<control>N", N_("New window"), CB(layout_menu_new_window_cb) },
{ "NewCollection", GTK_STOCK_INDEX, N_("_New collection"), "C", N_("New collection"), CB(layout_menu_new_cb) },
{ "CopyPathUnquoted", NULL, N_("_Copy path unquoted to clipboard"), NULL, N_("Copy path unquoted to clipboard"), CB(layout_menu_copy_path_unquoted_cb) },
{ "CloseWindow", GTK_STOCK_CLOSE, N_("C_lose window"), "<control>W", N_("Close window"), CB(layout_menu_close_cb) },
{ "Quit", GTK_STOCK_QUIT, N_("_Quit"), "<control>Q", N_("Quit"), CB(layout_menu_exit_cb) },
- { "RotateCW", PIXBUF_INLINE_ICON_CW, N_("_Rotate clockwise 90°"), "bracketright", N_("Rotate clockwise 90°"), CB(layout_menu_alter_90_cb) },
+ { "RotateCW", PIXBUF_INLINE_ICON_CW, N_("_Rotate clockwise 90°"), "bracketright", N_("Image Rotate clockwise 90°"), CB(layout_menu_alter_90_cb) },
{ "Rating0", NULL, N_("_Rating 0"), "<alt>KP_0", N_("Rating 0"), CB(layout_menu_rating_0_cb) },
{ "Rating1", NULL, N_("_Rating 1"), "<alt>KP_1", N_("Rating 1"), CB(layout_menu_rating_1_cb) },
{ "Rating2", NULL, N_("_Rating 2"), "<alt>KP_2", N_("Rating 2"), CB(layout_menu_rating_2_cb) },
{ "Rating5", NULL, N_("_Rating 5"), "<alt>KP_5", N_("Rating 5"), CB(layout_menu_rating_5_cb) },
{ "RatingM1", NULL, N_("_Rating -1"), "<alt>KP_Subtract", N_("Rating -1"), CB(layout_menu_rating_m1_cb) },
{ "RotateCCW", PIXBUF_INLINE_ICON_CCW, N_("Rotate _counterclockwise 90°"), "bracketleft", N_("Rotate counterclockwise 90°"), CB(layout_menu_alter_90cc_cb) },
- { "Rotate180", PIXBUF_INLINE_ICON_180, N_("Rotate 1_80°"), "<shift>R", N_("Rotate 180°"), CB(layout_menu_alter_180_cb) },
- { "Mirror", PIXBUF_INLINE_ICON_MIRROR, N_("_Mirror"), "<shift>M", N_("Mirror"), CB(layout_menu_alter_mirror_cb) },
- { "Flip", PIXBUF_INLINE_ICON_FLIP, N_("_Flip"), "<shift>F", N_("Flip"), CB(layout_menu_alter_flip_cb) },
+ { "Rotate180", PIXBUF_INLINE_ICON_180, N_("Rotate 1_80°"), "<shift>R", N_("Image Rotate 180°"), CB(layout_menu_alter_180_cb) },
+ { "Mirror", PIXBUF_INLINE_ICON_MIRROR, N_("_Mirror"), "<shift>M", N_("Image Mirror"), CB(layout_menu_alter_mirror_cb) },
+ { "Flip", PIXBUF_INLINE_ICON_FLIP, N_("_Flip"), "<shift>F", N_("Image Flip"), CB(layout_menu_alter_flip_cb) },
{ "AlterNone", PIXBUF_INLINE_ICON_ORIGINAL, N_("_Original state"), "<shift>O", N_("Original state"), CB(layout_menu_alter_none_cb) },
{ "SelectAll", PIXBUF_INLINE_ICON_SELECT_ALL, N_("Select _all"), "<control>A", N_("Select all"), CB(layout_menu_select_all_cb) },
{ "SelectNone", PIXBUF_INLINE_ICON_SELECT_NONE, N_("Select _none"), "<control><shift>A", N_("Select none"), CB(layout_menu_unselect_all_cb) },
{ "HistogramModeCycle",NULL, N_("Cycle through histogram mo_des"), "J", N_("Cycle through histogram modes"), CB(layout_menu_histogram_toggle_mode_cb) },
{ "HideTools", PIXBUF_INLINE_ICON_HIDETOOLS, N_("_Hide file list"), "<control>H", N_("Hide file list"), CB(layout_menu_hide_cb) },
{ "SlideShowPause", GTK_STOCK_MEDIA_PAUSE, N_("_Pause slideshow"), "P", N_("Pause slideshow"), CB(layout_menu_slideshow_pause_cb) },
- { "SlideShowFaster", GTK_STOCK_FILE, N_("Faster"), "<control>KP_Add", N_("Faster"), CB(layout_menu_slideshow_faster_cb) },
- { "SlideShowSlower", GTK_STOCK_FILE, N_("Slower"), "<control>KP_Subtract", N_("Slower"), CB(layout_menu_slideshow_slower_cb) },
+ { "SlideShowFaster", GTK_STOCK_FILE, N_("Faster"), "<control>KP_Add", N_("Slideshow Faster"), CB(layout_menu_slideshow_faster_cb) },
+ { "SlideShowSlower", GTK_STOCK_FILE, N_("Slower"), "<control>KP_Subtract", N_("Slideshow Slower"), CB(layout_menu_slideshow_slower_cb) },
{ "Refresh", GTK_STOCK_REFRESH, N_("_Refresh"), "R", N_("Refresh"), CB(layout_menu_refresh_cb) },
{ "HelpContents", GTK_STOCK_HELP, N_("_Contents"), "F1", N_("Contents"), CB(layout_menu_help_cb) },
{ "HelpSearch", NULL, N_("On-line help search"), NULL, N_("On-line help search"), CB(layout_menu_help_search_cb) },
{ "HelpKbd", NULL, N_("_Keyboard map"), NULL, N_("Keyboard map"), CB(layout_menu_kbd_map_cb) },
{ "HelpNotes", NULL, N_("_Release notes"), NULL, N_("Release notes"), CB(layout_menu_notes_cb) },
{ "HelpChangeLog", NULL, N_("_ChangeLog"), NULL, N_("ChangeLog notes"), CB(layout_menu_changelog_cb) },
+ { "SearchAndRunCommand", GTK_STOCK_FIND, N_("Search and Run command"), "slash", N_("Search commands by keyword and run them"), CB(layout_menu_search_and_run_cb) },
{ "About", GTK_STOCK_ABOUT, N_("_About"), NULL, N_("About"), CB(layout_menu_about_cb) },
{ "LogWindow", NULL, N_("_Log Window"), NULL, N_("Log Window"), CB(layout_menu_log_window_cb) },
{ "ExifWin", PIXBUF_INLINE_ICON_EXIF, N_("_Exif window"), "<control>E", N_("Exif window"), CB(layout_menu_bar_exif_cb) },
{ "StereoCycle", NULL, N_("_Cycle through stereo modes"), NULL, N_("Cycle through stereo modes"), CB(layout_menu_stereo_mode_next_cb) },
- { "SplitNextPane", NULL, N_("_Next Pane"), "<alt>Right", N_("Next Pane"), CB(layout_menu_split_pane_next_cb) },
- { "SplitPreviousPane", NULL, N_("_Previous Pane"), "<alt>Left", N_("Previous Pane"), CB(layout_menu_split_pane_prev_cb) },
- { "SplitUpPane", NULL, N_("_Up Pane"), "<alt>Up", N_("Up Pane"), CB(layout_menu_split_pane_updown_cb) },
- { "SplitDownPane", NULL, N_("_Down Pane"), "<alt>Down", N_("Down Pane"), CB(layout_menu_split_pane_updown_cb) },
+ { "SplitNextPane", NULL, N_("_Next Pane"), "<alt>Right", N_("Next Split Pane"), CB(layout_menu_split_pane_next_cb) },
+ { "SplitPreviousPane", NULL, N_("_Previous Pane"), "<alt>Left", N_("Previous Split Pane"), CB(layout_menu_split_pane_prev_cb) },
+ { "SplitUpPane", NULL, N_("_Up Pane"), "<alt>Up", N_("Up Split Pane"), CB(layout_menu_split_pane_updown_cb) },
+ { "SplitDownPane", NULL, N_("_Down Pane"), "<alt>Down", N_("Down Split Pane"), CB(layout_menu_split_pane_updown_cb) },
{ "WriteRotation", NULL, N_("_Write orientation to file"), NULL, N_("Write orientation to file"), CB(layout_menu_write_rotate_cb) },
{ "WriteRotationKeepDate", NULL, N_("_Write orientation to file (preserve timestamp)"), NULL, N_("Write orientation to file (preserve timestamp)"), CB(layout_menu_write_rotate_keep_date_cb) },
{ "ClearMarks", NULL, N_("Clear Marks..."), NULL, N_("Clear Marks"), CB(layout_menu_clear_marks_cb) },
" <placeholder name='SlideShowSection'/>"
" <separator/>"
" </menu>"
+" <menu action='SarMenu'>"
+" <menuitem action='SearchAndRunCommand'/>"
+" </menu>"
" <menu action='HelpMenu'>"
" <separator/>"
" <menuitem action='HelpContents'/>"
advanced_exif_set_fd(lw->exif_window, layout_image_get_fd(lw));
}
+static void layout_search_and_run_window_new(LayoutWindow *lw)
+{
+ if (lw->sar_window)
+ {
+ gtk_window_present(GTK_WINDOW(lw->sar_window));
+ return;
+ }
+
+ lw->sar_window = search_and_run_new(lw);
+}
+
/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
--- /dev/null
+/*
+ * Copyright (C) 2019 The Geeqie Team
+ *
+ * Author: Colin Clark
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "main.h"
+#include "search_and_run.h"
+
+#include "layout_util.h"
+#include "ui_misc.h"
+#include "window.h"
+
+enum {
+ SAR_LABEL,
+ SAR_ACTION,
+ SAR_COUNT
+};
+
+typedef struct _SarData SarData;
+struct _SarData
+{
+ GtkWidget *window;
+ GtkWidget *vbox;
+ GtkWidget *entry_box;
+ GtkEntryCompletion *completion;
+ GtkListStore *command_store;
+ GtkAction *action;
+ LayoutWindow *lw;
+ gboolean match_found;
+};
+
+static gint sort_iter_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer data)
+{
+ gint ret = 0;
+ gchar *label1, *label2;
+
+ gtk_tree_model_get(model, a, SAR_LABEL, &label1, -1);
+ gtk_tree_model_get(model, b, SAR_LABEL, &label2, -1);
+
+ if (label1 == NULL || label2 == NULL)
+ {
+ if (label1 == NULL && label2 == NULL)
+ {
+ ret = 0;
+ }
+ else
+ {
+ ret = (label1 == NULL) ? -1 : 1;
+ }
+ }
+ else
+ {
+ ret = g_utf8_collate(label1, label2);
+ }
+
+ g_free(label1);
+ g_free(label2);
+
+ return ret;
+}
+
+static void command_store_populate(SarData* sar)
+{
+ GList *groups, *actions;
+ GtkAction *action;
+ const gchar *accel_path;
+ GtkAccelKey key;
+ GtkTreeIter iter;
+ GtkTreeSortable *sortable;
+ gchar *label, *tooltip;
+ gchar *label2, *tooltip2;
+ GString *new_command;
+ gchar *existing_command;
+ gboolean iter_found;
+ gboolean duplicate_command;
+ gchar *accel;
+
+ sar->command_store = gtk_list_store_new(SAR_COUNT, G_TYPE_STRING, G_TYPE_OBJECT);
+
+ sortable = GTK_TREE_SORTABLE(sar->command_store);
+ gtk_tree_sortable_set_sort_func(sortable, SAR_LABEL, sort_iter_compare_func, NULL, NULL);
+
+ gtk_tree_sortable_set_sort_column_id(sortable, SAR_LABEL, GTK_SORT_ASCENDING);
+
+ groups = gtk_ui_manager_get_action_groups(sar->lw->ui_manager);
+ while (groups)
+ {
+ actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
+ while (actions)
+ {
+ action = GTK_ACTION(actions->data);
+ accel_path = gtk_action_get_accel_path(action);
+ if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
+ {
+ g_object_get(action, "tooltip", &tooltip, "label", &label, NULL);
+ accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
+
+ /* menu items with no tooltip are placeholders */
+ if (g_strrstr(accel_path, ".desktop") != NULL || tooltip != NULL)
+ {
+ if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
+ {
+ g_free(label);
+ label = label2;
+ }
+ if (tooltip)
+ {
+ if (pango_parse_markup(tooltip, -1, '_', NULL, &tooltip2, NULL, NULL) && label2)
+ {
+ g_free(tooltip);
+ tooltip = tooltip2;
+ }
+ }
+
+ new_command = g_string_new(NULL);
+ if (g_strcmp0(label, tooltip) == 0)
+ {
+ g_string_append_printf(new_command, "%s : %s",label, accel);
+ }
+ else
+ {
+ g_string_append_printf(new_command, "%s - %s : %s",label, tooltip, accel);
+ }
+
+ iter_found = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(sar->command_store), &iter);
+ duplicate_command = FALSE;
+
+ while (iter_found)
+ {
+ gtk_tree_model_get(GTK_TREE_MODEL(sar->command_store), &iter, SAR_LABEL, &existing_command, -1);
+ if (g_strcmp0(new_command->str, existing_command) == 0)
+ {
+ g_free(existing_command);
+ duplicate_command = TRUE;
+ break;
+ }
+ g_free(existing_command);
+ iter_found = gtk_tree_model_iter_next(GTK_TREE_MODEL(sar->command_store), &iter);
+ }
+
+ if (!duplicate_command )
+ {
+ gtk_list_store_append(sar->command_store, &iter);
+ gtk_list_store_set(sar->command_store, &iter,
+ SAR_LABEL, new_command->str,
+ SAR_ACTION, action,
+ -1);
+ }
+ g_free(label);
+ g_free(tooltip);
+ g_free(accel);
+ g_string_free(new_command, TRUE);
+ }
+ }
+ actions = actions->next;
+ }
+ groups = groups->next;
+ }
+}
+
+static void search_and_run_destroy(gpointer data)
+{
+ SarData *sar = data;
+
+ sar->lw->sar_window = NULL;
+ gtk_widget_destroy(sar->window);
+}
+
+static gboolean entry_box_activate_cb(GtkWidget *widget, gpointer data)
+{
+ SarData *sar = data;
+
+ if (sar->action)
+ {
+ gtk_action_activate(sar->action);
+ }
+
+ search_and_run_destroy(sar);
+
+ return TRUE;
+}
+
+static gboolean keypress_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+ SarData *sar = data;
+ gboolean ret = FALSE;
+
+ switch (event->keyval)
+ {
+ case GDK_KEY_Escape:
+ search_and_run_destroy(sar);
+ ret = TRUE;
+ break;
+ case GDK_KEY_Return:
+ break;
+ default:
+ sar->match_found = FALSE;
+ sar->action = NULL;
+ }
+
+ return ret;
+}
+
+static gboolean match_selected_cb(GtkEntryCompletion *widget, GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
+{
+ SarData *sar = data;
+
+ gtk_tree_model_get(GTK_TREE_MODEL(model), iter, SAR_ACTION, &sar->action, -1);
+
+ if (sar->action)
+ {
+ gtk_action_activate(sar->action);
+ }
+
+ g_idle_add((GSourceFunc)search_and_run_destroy, sar);
+
+ return TRUE;
+}
+
+static gboolean match_func(GtkEntryCompletion *completion, const gchar *key, GtkTreeIter *iter, gpointer data)
+{
+ SarData *sar = data;
+ gboolean ret = FALSE;
+ gchar *normalized;
+ GtkTreeModel *model;
+ GtkAction *action;
+ gchar *label;
+ GString *reg_exp_str;
+ GRegex *reg_exp;
+ GError *error = NULL;
+
+ model = gtk_entry_completion_get_model(completion);
+ gtk_tree_model_get(GTK_TREE_MODEL(model), iter, SAR_LABEL, &label, -1);
+ gtk_tree_model_get(GTK_TREE_MODEL(model), iter, SAR_ACTION, &action, -1);
+
+ normalized = g_utf8_normalize(label, -1, G_NORMALIZE_DEFAULT);
+
+ reg_exp_str = g_string_new("\\b\(\?=.*:)");
+ reg_exp_str = g_string_append(reg_exp_str, key);
+
+ reg_exp = g_regex_new(reg_exp_str->str, G_REGEX_CASELESS, 0, &error);
+ if (error)
+ {
+ log_printf("Error: could not compile regular expression %s\n%s\n", reg_exp_str->str, error->message);
+ g_error_free(error);
+ error = NULL;
+ reg_exp = g_regex_new("", 0, 0, NULL);
+ }
+
+ ret = g_regex_match(reg_exp, normalized, 0, NULL);
+
+ if (sar->match_found == FALSE && ret == TRUE)
+ {
+ sar->action = action;
+ sar->match_found = TRUE;
+ }
+
+ g_regex_unref(reg_exp);
+ g_string_free(reg_exp_str, TRUE);
+ g_free(normalized);
+
+ return ret;
+}
+
+GtkWidget *search_and_run_new(LayoutWindow *lw)
+{
+ SarData *sar;
+ GdkGeometry geometry;
+
+ sar = g_new0(SarData, 1);
+ sar->lw = lw;
+ sar->window = window_new(GTK_WINDOW_TOPLEVEL, "sar_window", NULL, NULL, _("Search and Run command"));
+ DEBUG_NAME(sar->window);
+
+ geometry.min_width = 500;
+ geometry.min_height = 0;
+ gtk_window_set_geometry_hints(GTK_WINDOW(sar->window), NULL, &geometry, GDK_HINT_MIN_SIZE);
+
+ gtk_window_set_resizable(GTK_WINDOW(sar->window), TRUE);
+
+ sar->vbox = gtk_vbox_new(FALSE, PREF_PAD_GAP);
+ gtk_container_add(GTK_CONTAINER(sar->window), sar->vbox);
+ gtk_widget_show(sar->vbox);
+
+ sar->entry_box = gtk_entry_new();
+ gtk_box_pack_start(GTK_BOX(sar->vbox), sar->entry_box, FALSE, FALSE, 0);
+ gtk_widget_show(sar->entry_box);
+ gtk_widget_show(sar->vbox);
+ gtk_widget_set_tooltip_text(sar->entry_box, "Search for commands and run them");
+ g_signal_connect(G_OBJECT(sar->entry_box), "key_press_event", G_CALLBACK(keypress_cb), sar);
+ g_signal_connect(G_OBJECT(sar->entry_box), "activate", G_CALLBACK(entry_box_activate_cb), sar);
+
+ command_store_populate(sar);
+
+ sar->completion = gtk_entry_completion_new();
+ gtk_entry_set_completion(GTK_ENTRY(sar->entry_box), sar->completion);
+ gtk_entry_completion_set_inline_completion(sar->completion, FALSE);
+ gtk_entry_completion_set_inline_selection(sar->completion, FALSE);
+ gtk_entry_completion_set_minimum_key_length(sar->completion, 1);
+ gtk_entry_completion_set_match_func(sar->completion, match_func, sar, NULL);
+ g_signal_connect(G_OBJECT(sar->completion), "match-selected", G_CALLBACK(match_selected_cb), sar);
+ gtk_entry_completion_set_model(sar->completion, GTK_TREE_MODEL(sar->command_store));
+ gtk_entry_completion_set_text_column(sar->completion, SAR_LABEL);
+
+ gtk_widget_show(sar->window);
+ return sar->window;
+}
+/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */