📄 view_file_icon.c
字号:
/* * GQview * (C) 2004 John Ellis * * Author: John Ellis * * This software is released under the GNU General Public License (GNU GPL). * Please read the included file COPYING for more information. * This software comes with no warranty of any kind, use at your own risk! */#include "gqview.h"#include "view_file_icon.h"#include "cellrenderericon.h"#include "collect.h"#include "collect-io.h"#include "collect-table.h"#include "dnd.h"#include "editors.h"#include "img-view.h"#include "info.h"#include "filelist.h"#include "layout.h"#include "layout_image.h"#include "menu.h"#include "thumb.h"#include "utilops.h"#include "ui_bookmark.h"#include "ui_fileops.h"#include "ui_menu.h"#include "ui_tree_edit.h"#include <gdk/gdkkeysyms.h> /* for keyboard values *//* between these, the icon width is increased by thumb_max_width / 2 */#define THUMB_MIN_ICON_WIDTH 128#define THUMB_MAX_ICON_WIDTH 150#define VFICON_MAX_COLUMNS 32#define THUMB_BORDER_PADDING 2#define VFICON_TIP_DELAY 500#define ICON_DATA(x) ((IconData *)x)#define FILE_DATA(x) ((FileData *)x)enum { FILE_COLUMN_POINTER = 0, FILE_COLUMN_COUNT};typedef enum { SELECTION_NONE = 0, SELECTION_SELECTED = 1 << 0, SELECTION_PRELIGHT = 1 << 1, SELECTION_FOCUS = 1 << 2} SelectionType;typedef struct _IconData IconData;struct _IconData{ FileData fd; SelectionType selected;};static gint iconlist_read(const gchar *path, GList **list){ GList *temp; GList *work; if (!filelist_read(path, &temp, NULL)) return FALSE; work = temp; while (work) { FileData *fd; IconData *id; fd = work->data; id = g_new0(IconData, 1); memcpy(id, fd, sizeof(FileData)); id->selected = SELECTION_NONE; work->data = id; g_free(fd); work = work->next; } *list = temp; return TRUE;}static void iconlist_free(GList *list){ filelist_free(list);}static void vficon_toggle_filenames(ViewFileIcon *vfi);static void vficon_selection_remove(ViewFileIcon *vfi, FileData *fd, SelectionType mask, GtkTreeIter *iter);static void vficon_move_focus(ViewFileIcon *vfi, gint row, gint col, gint relative);static void vficon_set_focus(ViewFileIcon *vfi, FileData *fd);static void vficon_thumb_update(ViewFileIcon *vfi);static void vficon_populate_at_new_size(ViewFileIcon *vfi, gint w, gint h, gint force);/* *----------------------------------------------------------------------------- * pop-up menu *----------------------------------------------------------------------------- */static GList *vficon_pop_menu_file_list(ViewFileIcon *vfi){ if (!vfi->click_fd) return NULL; if (ICON_DATA(vfi->click_fd)->selected & SELECTION_SELECTED) { return vficon_selection_get_list(vfi); } return g_list_append(NULL, g_strdup(vfi->click_fd->path));}static void vficon_pop_menu_edit_cb(GtkWidget *widget, gpointer data){ ViewFileIcon *vfi; gint n; GList *list; vfi = submenu_item_get_data(widget); n = GPOINTER_TO_INT(data); if (!vfi) return; list = vficon_pop_menu_file_list(vfi); start_editor_from_path_list(n, list); path_list_free(list);}static void vficon_pop_menu_info_cb(GtkWidget *widget, gpointer data){ ViewFileIcon *vfi = data; info_window_new(NULL, vficon_pop_menu_file_list(vfi));}static void vficon_pop_menu_view_cb(GtkWidget *widget, gpointer data){ ViewFileIcon *vfi = data; if (!vfi->click_fd) return; if (ICON_DATA(vfi->click_fd)->selected & SELECTION_SELECTED) { GList *list; list = vficon_selection_get_list(vfi); view_window_new_from_list(list); path_list_free(list); } else { view_window_new(vfi->click_fd->path); }}static void vficon_pop_menu_copy_cb(GtkWidget *widget, gpointer data){ ViewFileIcon *vfi = data; file_util_copy(NULL, vficon_pop_menu_file_list(vfi), NULL, vfi->listview);}static void vficon_pop_menu_move_cb(GtkWidget *widget, gpointer data){ ViewFileIcon *vfi = data; file_util_move(NULL, vficon_pop_menu_file_list(vfi), NULL, vfi->listview);}static void vficon_pop_menu_rename_cb(GtkWidget *widget, gpointer data){ ViewFileIcon *vfi = data; file_util_rename(NULL, vficon_pop_menu_file_list(vfi), vfi->listview);}static void vficon_pop_menu_delete_cb(GtkWidget *widget, gpointer data){ ViewFileIcon *vfi = data; file_util_delete(NULL, vficon_pop_menu_file_list(vfi), vfi->listview);}static void vficon_pop_menu_sort_cb(GtkWidget *widget, gpointer data){ ViewFileIcon *vfi; SortType type; vfi = submenu_item_get_data(widget); if (!vfi) return; type = (SortType)GPOINTER_TO_INT(data); if (vfi->layout) { layout_sort_set(vfi->layout, type, vfi->sort_ascend); } else { vficon_sort_set(vfi, type, vfi->sort_ascend); }}static void vficon_pop_menu_sort_ascend_cb(GtkWidget *widget, gpointer data){ ViewFileIcon *vfi = data; if (vfi->layout) { layout_sort_set(vfi->layout, vfi->sort_method, !vfi->sort_ascend); } else { vficon_sort_set(vfi, vfi->sort_method, !vfi->sort_ascend); }}static void vficon_pop_menu_list_cb(GtkWidget *widget, gpointer data){ ViewFileIcon *vfi = data; if (vfi->layout) layout_views_set(vfi->layout, vfi->layout->tree_view, FALSE);}static void vficon_pop_menu_show_names_cb(GtkWidget *widget, gpointer data){ ViewFileIcon *vfi = data; vficon_toggle_filenames(vfi);}static void vficon_pop_menu_refresh_cb(GtkWidget *widget, gpointer data){ ViewFileIcon *vfi = data; vficon_refresh(vfi);}static void vficon_popup_destroy_cb(GtkWidget *widget, gpointer data){ ViewFileIcon *vfi = data; vficon_selection_remove(vfi, vfi->click_fd, SELECTION_PRELIGHT, NULL); vfi->click_fd = NULL; vfi->popup = NULL;}static GtkWidget *vficon_pop_menu(ViewFileIcon *vfi, gint active){ GtkWidget *menu; GtkWidget *item; GtkWidget *submenu; menu = popup_menu_short_lived(); g_signal_connect(G_OBJECT(menu), "destroy", G_CALLBACK(vficon_popup_destroy_cb), vfi); submenu_add_edit(menu, &item, G_CALLBACK(vficon_pop_menu_edit_cb), vfi); gtk_widget_set_sensitive(item, active); item = menu_item_add_stock(menu, _("_Properties"), GTK_STOCK_PROPERTIES, G_CALLBACK(vficon_pop_menu_info_cb), vfi); gtk_widget_set_sensitive(item, active); item = menu_item_add_stock(menu, _("View in _new window"), GTK_STOCK_NEW, G_CALLBACK(vficon_pop_menu_view_cb), vfi); gtk_widget_set_sensitive(item, active); menu_item_add_divider(menu); item = menu_item_add_stock(menu, _("_Copy..."), GTK_STOCK_COPY, G_CALLBACK(vficon_pop_menu_copy_cb), vfi); gtk_widget_set_sensitive(item, active); item = menu_item_add(menu, _("_Move..."), G_CALLBACK(vficon_pop_menu_move_cb), vfi); gtk_widget_set_sensitive(item, active); item = menu_item_add(menu, _("_Rename..."), G_CALLBACK(vficon_pop_menu_rename_cb), vfi); gtk_widget_set_sensitive(item, active); item = menu_item_add_stock(menu, _("_Delete..."), GTK_STOCK_DELETE, G_CALLBACK(vficon_pop_menu_delete_cb), vfi); gtk_widget_set_sensitive(item, active); menu_item_add_divider(menu); submenu = submenu_add_sort(NULL, G_CALLBACK(vficon_pop_menu_sort_cb), vfi, FALSE, FALSE, TRUE, vfi->sort_method); menu_item_add_divider(submenu); menu_item_add_check(submenu, _("Ascending"), vfi->sort_ascend, G_CALLBACK(vficon_pop_menu_sort_ascend_cb), vfi); item = menu_item_add(menu, _("_Sort"), NULL, NULL); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu); menu_item_add_check(menu, _("View as _icons"), TRUE, G_CALLBACK(vficon_pop_menu_list_cb), vfi); menu_item_add_check(menu, _("Show filename _text"), vfi->show_text, G_CALLBACK(vficon_pop_menu_show_names_cb), vfi); menu_item_add_stock(menu, _("Re_fresh"), GTK_STOCK_REFRESH, G_CALLBACK(vficon_pop_menu_refresh_cb), vfi); return menu;}/* *------------------------------------------------------------------- * signals *------------------------------------------------------------------- */static void vficon_send_update(ViewFileIcon *vfi){ if (vfi->func_status) vfi->func_status(vfi, vfi->data_status);}static void vficon_send_layout_select(ViewFileIcon *vfi, FileData *fd){ const gchar *read_ahead_path = NULL; if (!vfi->layout || !fd) return; if (enable_read_ahead) { FileData *fd_n; gint row; row = g_list_index(vfi->list, fd); if (row > vficon_index_by_path(vfi, layout_image_get_path(vfi->layout)) && row + 1 < vficon_count(vfi, NULL)) { fd_n = vficon_index_get_data(vfi, row + 1); } else if (row > 0) { fd_n = vficon_index_get_data(vfi, row - 1); } else { fd_n = NULL; } if (fd_n) read_ahead_path = fd_n->path; } layout_image_set_with_ahead(vfi->layout, fd->path, read_ahead_path);}static void vficon_toggle_filenames(ViewFileIcon *vfi){ vfi->show_text = !vfi->show_text; show_icon_names = vfi->show_text; vficon_populate_at_new_size(vfi, vfi->listview->allocation.width, vfi->listview->allocation.height, TRUE);}static gint vficon_get_icon_width(ViewFileIcon *vfi){ gint width; if (!vfi->show_text) return thumb_max_width; width = thumb_max_width + thumb_max_width / 2; if (width < THUMB_MIN_ICON_WIDTH) width = THUMB_MIN_ICON_WIDTH; if (width > THUMB_MAX_ICON_WIDTH) width = thumb_max_width; return width;}/* *------------------------------------------------------------------- * misc utils *------------------------------------------------------------------- */static gint vficon_find_position(ViewFileIcon *vfi, FileData *fd, gint *row, gint *col){ gint n; n = g_list_index(vfi->list, fd); if (n < 0) return FALSE; *row = n / vfi->columns; *col = n - (*row * vfi->columns); return TRUE;}static gint vficon_find_iter(ViewFileIcon *vfi, FileData *fd, GtkTreeIter *iter, gint *column){ GtkTreeModel *store; gint row, col; store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview)); if (!vficon_find_position(vfi, fd, &row, &col)) return FALSE; if (!gtk_tree_model_iter_nth_child(store, iter, NULL, row)) return FALSE; if (column) *column = col; return TRUE;}static FileData *vficon_find_data(ViewFileIcon *vfi, gint row, gint col, GtkTreeIter *iter){ GtkTreeModel *store; GtkTreeIter p; if (row < 0 || col < 0) return NULL; store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview)); if (gtk_tree_model_iter_nth_child(store, &p, NULL, row)) { GList *list; gtk_tree_model_get(store, &p, FILE_COLUMN_POINTER, &list, -1); if (!list) return NULL; if (iter) *iter = p; return g_list_nth_data(list, col); } return NULL;}static FileData *vficon_find_data_by_coord(ViewFileIcon *vfi, gint x, gint y, GtkTreeIter *iter){ GtkTreePath *tpath; GtkTreeViewColumn *column; if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vfi->listview), x, y, &tpath, &column, NULL, NULL)) { GtkTreeModel *store; GtkTreeIter row; GList *list; gint n; store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview)); gtk_tree_model_get_iter(store, &row, tpath); gtk_tree_path_free(tpath); gtk_tree_model_get(store, &row, FILE_COLUMN_POINTER, &list, -1); n = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), "column_number")); if (list) { if (iter) *iter = row; return g_list_nth_data(list, n); } } return NULL;}/* *------------------------------------------------------------------- * tooltip type window *------------------------------------------------------------------- */static void tip_show(ViewFileIcon *vfi){ GtkWidget *label; gint x, y; if (vfi->tip_window) return; gdk_window_get_pointer(gtk_tree_view_get_bin_window(GTK_TREE_VIEW(vfi->listview)), &x, &y, NULL); vfi->tip_fd = vficon_find_data_by_coord(vfi, x, y, NULL); if (!vfi->tip_fd) return; vfi->tip_window = gtk_window_new(GTK_WINDOW_POPUP); gtk_window_set_resizable(GTK_WINDOW(vfi->tip_window), FALSE); gtk_container_set_border_width(GTK_CONTAINER(vfi->tip_window), 2); label = gtk_label_new(vfi->tip_fd->name); g_object_set_data(G_OBJECT(vfi->tip_window), "tip_label", label); gtk_container_add(GTK_CONTAINER(vfi->tip_window), label); gtk_widget_show(label); gdk_window_get_pointer(NULL, &x, &y, NULL); if (!GTK_WIDGET_REALIZED(vfi->tip_window)) gtk_widget_realize(vfi->tip_window); gtk_window_move(GTK_WINDOW(vfi->tip_window), x + 16, y + 16); gtk_widget_show(vfi->tip_window);}static void tip_hide(ViewFileIcon *vfi){ if (vfi->tip_window) gtk_widget_destroy(vfi->tip_window); vfi->tip_window = NULL;}static gint tip_schedule_cb(gpointer data){ ViewFileIcon *vfi = data; GtkWidget *window; if (vfi->tip_delay_id == -1) return FALSE; window = gtk_widget_get_toplevel(vfi->listview); if (GTK_WIDGET_SENSITIVE(window) && GTK_WINDOW(window)->has_focus) { tip_show(vfi); } vfi->tip_delay_id = -1; return FALSE;}static void tip_schedule(ViewFileIcon *vfi){ tip_hide(vfi); if (vfi->tip_delay_id != -1) { g_source_remove(vfi->tip_delay_id); vfi->tip_delay_id = -1; } if (!vfi->show_text) { vfi->tip_delay_id = g_timeout_add(VFICON_TIP_DELAY, tip_schedule_cb, vfi); }}static void tip_unschedule(ViewFileIcon *vfi){ tip_hide(vfi); if (vfi->tip_delay_id != -1) g_source_remove(vfi->tip_delay_id); vfi->tip_delay_id = -1;}static void tip_update(ViewFileIcon *vfi, FileData *fd){ if (vfi->tip_window) { gint x, y; gdk_window_get_pointer(NULL, &x, &y, NULL); gtk_window_move(GTK_WINDOW(vfi->tip_window), x + 16, y + 16); if (fd != vfi->tip_fd) { GtkWidget *label; vfi->tip_fd = fd; if (!vfi->tip_fd) { tip_hide(vfi); tip_schedule(vfi); return; } label = g_object_get_data(G_OBJECT(vfi->tip_window), "tip_label"); gtk_label_set_text(GTK_LABEL(label), vfi->tip_fd->name); } } else { tip_schedule(vfi); }}/* *------------------------------------------------------------------- * dnd *------------------------------------------------------------------- */static void vficon_dnd_get(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data, guint info, guint time, gpointer data){ ViewFileIcon *vfi = data; GList *list = NULL; gchar *uri_text = NULL; gint total; if (!vfi->click_fd) return; if (ICON_DATA(vfi->click_fd)->selected & SELECTION_SELECTED) { list = vficon_selection_get_list(vfi); } else { const gchar *path = vfi->click_fd->path; list = g_list_append(NULL, g_strdup(path)); } if (!list) return; uri_text = uri_text_from_list(list, &total, (info == TARGET_TEXT_PLAIN)); path_list_free(list); if (debug) printf(uri_text); gtk_selection_data_set(selection_data, selection_data->target, 8, uri_text, total); g_free(uri_text);}static void vficon_dnd_begin(GtkWidget *widget, GdkDragContext *context, gpointer data){ ViewFileIcon *vfi = data; tip_unschedule(vfi); if (vfi->click_fd && vfi->click_fd->pixbuf) { gint items; if (ICON_DATA(vfi->click_fd)->selected & SELECTION_SELECTED) items = g_list_length(vfi->selection); else items = 1; dnd_set_drag_icon(widget, context, vfi->click_fd->pixbuf, items); }}static void vficon_dnd_end(GtkWidget *widget, GdkDragContext *context, gpointer data){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -