📄 search.c
字号:
if (!sd->match_similarity_enable) { GtkTreeSortable *sortable; gint id; GtkSortType order; sortable = GTK_TREE_SORTABLE(gtk_tree_view_get_model(GTK_TREE_VIEW(sd->result_view))); if (gtk_tree_sortable_get_sort_column_id(sortable, &id, &order) && id == SEARCH_COLUMN_RANK) { gtk_tree_sortable_set_sort_column_id(sortable, SEARCH_COLUMN_PATH, GTK_SORT_ASCENDING); } } if (sd->search_type == SEARCH_MATCH_NONE) { /* search path */ path = remove_trailing_slash(gtk_entry_get_text(GTK_ENTRY(sd->path_entry))); if (isdir(path)) { g_free(sd->search_path); sd->search_path = path; path = NULL; tab_completion_append_to_history(sd->path_entry, sd->search_path); search_start(sd); } else { file_util_warning_dialog(_("Folder not found"), _("Please enter an existing folder to search."), GTK_STOCK_DIALOG_WARNING, sd->window); } g_free(path); } else if (sd->search_type == SEARCH_MATCH_ALL) { /* search metadata */ g_free(sd->search_path); sd->search_path = g_strconcat(homedir(), "/", GQVIEW_CACHE_RC_METADATA, NULL); search_start(sd); } else if (sd->search_type == SEARCH_MATCH_CONTAINS) { /* search current result list */ GList *list; list = search_result_refine_list(sd); g_free(sd->search_path); sd->search_path = NULL; search_start(sd); sd->search_file_list = g_list_concat(sd->search_file_list, list); }}/* *------------------------------------------------------------------- * window construct *------------------------------------------------------------------- */enum { MENU_CHOICE_COLUMN_NAME = 0, MENU_CHOICE_COLUMN_VALUE};static void search_thumb_toggle_cb(GtkWidget *button, gpointer data){ SearchData *sd = data; search_result_thumb_enable(sd, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));}static gint sort_matchdata_dimensions(MatchFileData *a, MatchFileData *b){ gint sa; gint sb; sa = a->width * a->height; sb = b->width * b->height; if (sa > sb) return 1; if (sa < sb) return -1; return 0;}static gint search_result_sort_cb(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer data){ gint n = GPOINTER_TO_INT(data); FileData *fda; FileData *fdb; gtk_tree_model_get(model, a, SEARCH_COLUMN_POINTER, &fda, -1); gtk_tree_model_get(model, b, SEARCH_COLUMN_POINTER, &fdb, -1); if (!fda || !fdb) return 0; switch (n) { case SEARCH_COLUMN_RANK: if (((MatchFileData *)fda)->rank > ((MatchFileData *)fdb)->rank) return 1; if (((MatchFileData *)fda)->rank < ((MatchFileData *)fdb)->rank) return -1; return 0; break; case SEARCH_COLUMN_NAME: return CASE_SORT(fda->name, fdb->name); break; case SEARCH_COLUMN_SIZE: if (fda->size > fdb->size) return 1; if (fda->size < fdb->size) return -1; return 0; break; case SEARCH_COLUMN_DATE: if (fda->date > fdb->date) return 1; if (fda->date < fdb->date) return -1; return 0; break; case SEARCH_COLUMN_DIMENSIONS: return sort_matchdata_dimensions((MatchFileData *)fda, (MatchFileData *)fdb); break; case SEARCH_COLUMN_PATH: return CASE_SORT(fda->path, fdb->path); break; default: break; } return 0;}static void search_result_add_column(SearchData * sd, gint n, const gchar *title, gint image, gint right_justify){ GtkTreeViewColumn *column; GtkCellRenderer *renderer; column = gtk_tree_view_column_new(); gtk_tree_view_column_set_title(column, title); gtk_tree_view_column_set_min_width(column, 4); if (n != SEARCH_COLUMN_THUMB) gtk_tree_view_column_set_resizable(column, TRUE); if (!image) { gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY); renderer = gtk_cell_renderer_text_new(); if (right_justify) g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL); gtk_tree_view_column_pack_start(column, renderer, TRUE); gtk_tree_view_column_add_attribute(column, renderer, "text", n); gtk_tree_view_column_set_sort_column_id(column, n); } else { gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); renderer = gtk_cell_renderer_pixbuf_new(); cell_renderer_height_override(renderer); gtk_tree_view_column_pack_start(column, renderer, TRUE); gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", n); } gtk_tree_view_append_column(GTK_TREE_VIEW(sd->result_view), column);}static void menu_choice_set_visible(GtkWidget *widget, gint visible){ if (visible) { if (!GTK_WIDGET_VISIBLE(widget)) gtk_widget_show(widget); } else { if (GTK_WIDGET_VISIBLE(widget)) gtk_widget_hide(widget); }}static void menu_choice_path_cb(GtkWidget *combo, gpointer data){ SearchData *sd = data; GtkTreeModel *store; GtkTreeIter iter; store = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter)) return; gtk_tree_model_get(store, &iter, MENU_CHOICE_COLUMN_VALUE, &sd->search_type, -1); menu_choice_set_visible(gtk_widget_get_parent(sd->check_recurse), (sd->search_type == SEARCH_MATCH_NONE));}static void menu_choice_name_cb(GtkWidget *combo, gpointer data){ SearchData *sd = data; GtkTreeModel *store; GtkTreeIter iter; store = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter)) return; gtk_tree_model_get(store, &iter, MENU_CHOICE_COLUMN_VALUE, &sd->match_name, -1);}static void menu_choice_size_cb(GtkWidget *combo, gpointer data){ SearchData *sd = data; GtkTreeModel *store; GtkTreeIter iter; store = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter)) return; gtk_tree_model_get(store, &iter, MENU_CHOICE_COLUMN_VALUE, &sd->match_size, -1); menu_choice_set_visible(gtk_widget_get_parent(sd->spin_size_end), (sd->match_size == SEARCH_MATCH_BETWEEN));}static void menu_choice_date_cb(GtkWidget *combo, gpointer data){ SearchData *sd = data; GtkTreeModel *store; GtkTreeIter iter; store = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter)) return; gtk_tree_model_get(store, &iter, MENU_CHOICE_COLUMN_VALUE, &sd->match_date, -1); menu_choice_set_visible(gtk_widget_get_parent(sd->date_sel_end), (sd->match_date == SEARCH_MATCH_BETWEEN));}static void menu_choice_dimensions_cb(GtkWidget *combo, gpointer data){ SearchData *sd = data; GtkTreeModel *store; GtkTreeIter iter; store = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter)) return; gtk_tree_model_get(store, &iter, MENU_CHOICE_COLUMN_VALUE, &sd->match_dimensions, -1); menu_choice_set_visible(gtk_widget_get_parent(sd->spin_width_end), (sd->match_dimensions == SEARCH_MATCH_BETWEEN));}static void menu_choice_keyword_cb(GtkWidget *combo, gpointer data){ SearchData *sd = data; GtkTreeModel *store; GtkTreeIter iter; store = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter)) return; gtk_tree_model_get(store, &iter, MENU_CHOICE_COLUMN_VALUE, &sd->match_keywords, -1);}static void menu_choice_spin_cb(GtkAdjustment *adjustment, gpointer data){ gint *value = data; *value = (gint)gtk_adjustment_get_value(adjustment);}static GtkWidget *menu_spin(GtkWidget *box, gdouble min, gdouble max, gint value, GCallback func, gpointer data){ GtkWidget *spin; GtkAdjustment *adj; spin = gtk_spin_button_new_with_range(min, max, 1); gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin), (gdouble)value); adj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(spin)); if (func) g_signal_connect(G_OBJECT(adj), "value_changed", G_CALLBACK(func), data); gtk_box_pack_start(GTK_BOX(box), spin, FALSE, FALSE, 0); gtk_widget_show(spin); return spin;}static void menu_choice_check_cb(GtkWidget *button, gpointer data){ GtkWidget *widget = data; gboolean active; gboolean *value; active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)); gtk_widget_set_sensitive(widget, active); value = g_object_get_data(G_OBJECT(button), "check_var"); if (value) *value = active;}static GtkWidget *menu_choice_menu(const MatchList *items, gint item_count, GCallback func, gpointer data){ GtkWidget *combo; GtkCellRenderer *renderer; GtkListStore *store; gint i; store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT); combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); g_object_unref(store); renderer = gtk_cell_renderer_text_new(); gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer, TRUE); gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), renderer, "text", MENU_CHOICE_COLUMN_NAME, NULL); for (i = 0; i < item_count; i++) { GtkTreeIter iter; gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, MENU_CHOICE_COLUMN_NAME, _(items[i].text), MENU_CHOICE_COLUMN_VALUE, items[i].type, -1); } gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); if (func) g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(func), data); return combo;}static GtkWidget *menu_choice(GtkWidget *box, GtkWidget **check, GtkWidget **menu, const gchar *text, gboolean *value, const MatchList *items, gint item_count, GCallback func, gpointer data){ GtkWidget *base_box; GtkWidget *hbox; GtkWidget *button; GtkWidget *option; base_box = gtk_hbox_new(FALSE, PREF_PAD_GAP); gtk_box_pack_start(GTK_BOX(box), base_box, FALSE, FALSE, 0); gtk_widget_show(base_box); button = gtk_check_button_new(); if (value) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), *value); gtk_box_pack_start(GTK_BOX(base_box), button, FALSE, FALSE, 0); gtk_widget_show(button); if (check) *check = button; if (value) g_object_set_data(G_OBJECT(button), "check_var", value); hbox = gtk_hbox_new(FALSE, PREF_PAD_SPACE); gtk_box_pack_start(GTK_BOX(base_box), hbox, TRUE, TRUE, 0); gtk_widget_show(hbox); g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(menu_choice_check_cb), hbox); gtk_widget_set_sensitive(hbox, (value) ? *value : FALSE); pref_label_new(hbox, text); if (!items && !menu) return hbox; option = menu_choice_menu(items, item_count, func, data); gtk_box_pack_start(GTK_BOX(hbox), option, FALSE, FALSE, 0); gtk_widget_show(option); if (menu) *menu = option; return hbox;}static void search_window_close(SearchData *sd){ gtk_widget_destroy(sd->window);}static gint search_window_delete_cb(GtkWidget *widget, GdkEventAny *event, gpointer data){ SearchData *sd = data; search_window_close(sd); return TRUE;}static void search_window_destroy_cb(GtkWidget *widget, gpointer data){ SearchData *sd = data; search_window_list = g_list_remove(search_window_list, sd); search_result_update_idle_cancel(sd); filelist_free(sd->search_buffer_list); sd->search_buffer_list = NULL; search_stop(sd); search_result_clear(sd); g_free(sd->search_path); g_free(sd->search_name); g_free(sd->search_similarity_path); path_list_free(sd->search_keyword_list); g_free(sd);}void search_new(const gchar *path, const gchar *example_file){ SearchData *sd; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *hbox2; GtkWidget *pad_box; GtkWidget *frame; GtkWidget *scrolled; GtkListStore *store; GtkTreeSortable *sortable; GtkTreeSelection *selection; GtkWidget *combo; GdkGeometry geometry; sd = g_new0(SearchData, 1); sd->search_path = g_strdup(path); sd->search_path_recurse = TRUE; sd->search_size = 0; sd->search_width = 640; sd->search_height = 480; sd->search_width_end = 1024; sd->search_height_end = 768; sd->search_name = NULL; sd->search_name_match_case = FALSE; sd->search_type = SEARCH_MATCH_NONE; sd->match_name = SEARCH_MATCH_CONTAINS; sd->match_size = SEARCH_MATCH_EQUAL; sd->match_date = SEARCH_MATCH_EQUAL; sd->match_dimensions = SEARCH_MATCH_EQUAL; sd->match_keywords = SEARCH_MATCH_ALL; sd->match_name_enable = TRUE; sd->match_size_enable = FALSE; sd->match_date_enable = FALSE; sd->match_dimensions_enable = FALSE; sd->match_similarity_enable = FALSE; sd->match_keywords_enable = FALSE; sd->search_similarity = 95; sd->search_similarity_path = g_strdup(example_file); sd->search_similarity_cd = NULL; sd->search_idle_id = -1; sd->update_idle_id = -1; sd->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); window_set_icon(sd->window, NULL, NULL); gtk_window_set_resizable(GTK_WINDOW(sd->window), TRUE); gtk_window_set_title(GTK_WINDOW(sd->window), _("Image search - GQview")); gtk_window_set_wmclass(GTK_WINDOW(sd->window), "search", "GQview"); geometry.min_width = 32; geometry.min_height = 32; geometry.base_width = DEF_SEARCH_WIDTH; geometry.base_height = DEF_SEARCH_HEIGHT; gtk_window_set_geometry_hints(GTK_WINDOW(sd->window), NULL, &geometry, GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE); gtk_window_set_default_size(GTK_WINDOW(sd->window), DEF_SEARCH_WIDTH, DEF_SEARCH_HEIGHT); g_signal_connect(G_OBJECT(sd->window), "delete_event", G_CALLBACK(search_window_delete_cb), sd); g_signal_connect(G_OBJECT(sd->window), "destroy", G_CALLBACK(search_window_destroy_cb), sd); g_signal_connect(G_OBJECT(sd->window), "key_press_event", G_CALLBACK(search_window_keypress_cb), sd); vbox = gtk_vbox_new(FALSE, PREF_PAD_GAP); gtk_container_set_border_width(GTK_CONTAINER(vbox), PREF_PAD_GAP); gtk_container_add(GTK_CONTAINER(sd->window), vbox); gtk_widget_show(vbox); sd->box_search = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP); hbox = pref_box_new(sd->box_search, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE); pref_label_new(hbox, _("Search:")); sd->menu_path = menu_choice_menu(text_search_menu_path, sizeof(text_search_menu_path) / sizeof(MatchList), G_CALLBACK(menu_choice_path_cb), sd); gtk_box_pack_start(GTK_BOX(hbox), sd->menu_path, FALSE, FALSE, 0); gtk_widget_show(sd->menu_path); hbox2 = pref_box_new(hbox, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE); combo = tab_completion_new_with_history(&sd->path_entry, sd->search_path, "search_path", -1, NULL, NULL); tab_completion_add_select_button(sd->path_entry, NULL, TRUE); gtk_box_pack_start(GTK_BOX(hbox2), combo, TRUE, TRUE, 0); gtk_widget_show(combo); sd->check_recurse = pref_checkbox_new_int(hbox2, _("Recurse"), sd->search_path_recurse, &sd->search_path_recurse); hbox = menu_choice(sd->box_search, &sd->check_name, &sd->menu_name, _("File name"), &sd->match_name_enable, text_search_menu_name, sizeof(text_search_menu_name) / sizeof(MatchList), G_CALLBACK(menu_choice_name_cb), sd); combo = history_combo_new(&sd->entry_name, "", "search_name", -1); gtk_box_pack_start(GTK_BOX(hbox), combo, TRUE, TRUE, 0); gtk_widget_show(combo); pref_checkbox_new_int(hbox, _("Match case"), sd->search_name_match_case, &sd->search_name_match_case); hbox = menu_choice(sd->box_search, &sd->check_size, &sd->menu_size, _("File size is"), &sd->match_size_enable, text_search_menu_size, sizeof(text_search_menu_size) / sizeof(MatchList), G_CALLBACK(menu_choice_size_cb), sd); sd->spin_size = menu_spin(hbox, 0, 1024*1024*1024, sd->search_size, G_CALLBACK(menu_choice_spin_cb), &sd->search_size); hbox2 = gtk_hbox_new(FALSE, PREF_PAD_SPACE); gtk_box_pack_start(GTK_BOX(hbox), hbox2, FALSE, FALSE, 0); pref_label_new(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -