view_file_list.c
来自「Gqview,Linux下基于GTK+库写成的轻量级而能丰富的图像浏览程序。」· C语言 代码 · 共 1,819 行 · 第 1/3 页
C
1,819 行
gtk_tree_view_column_set_fixed_width(column, (thumb) ? thumb_max_width : 4); list = gtk_tree_view_column_get_cell_renderers(column); if (!list) return; cell = list->data; g_list_free(list); g_object_set(G_OBJECT(cell), "height", (thumb) ? thumb_max_height : -1, NULL); gtk_tree_view_columns_autosize(GTK_TREE_VIEW(listview));}static void vflist_populate_view(ViewFileList *vfl){ GtkListStore *store; GtkTreeIter iter; gint thumbs; GList *work; GtkTreeRowReference *visible_row = NULL; GtkTreePath *tpath; gint valid; store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vfl->listview))); thumbs = vfl->thumbs_enabled; vflist_thumb_stop(vfl); if (!vfl->list) { gtk_list_store_clear(store); vflist_send_update(vfl); return; } if (GTK_WIDGET_REALIZED(vfl->listview) && gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vfl->listview), 0, 0, &tpath, NULL, NULL, NULL)) { visible_row = gtk_tree_row_reference_new(GTK_TREE_MODEL(store), tpath); gtk_tree_path_free(tpath); } vflist_listview_set_height(vfl->listview, thumbs); valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); work = vfl->list; while (work) { gint match; FileData *fd = work->data; gint done = FALSE; while (!done) { FileData *old_fd = NULL; if (valid) { gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &old_fd, -1); match = CASE_SORT(fd->name, old_fd->name); } else { match = -1; } if (match < 0) { GtkTreeIter new; gchar *size; size = text_from_size(fd->size); if (valid) { gtk_list_store_insert_before(store, &new, &iter); } else { gtk_list_store_append(store, &new); } gtk_list_store_set(store, &new, FILE_COLUMN_POINTER, fd, FILE_COLUMN_THUMB, (thumbs) ? fd->pixbuf : NULL, FILE_COLUMN_NAME, fd->name, FILE_COLUMN_SIZE, size, FILE_COLUMN_DATE, text_from_time(fd->date), FILE_COLUMN_COLOR, FALSE, -1); g_free(size); done = TRUE; } else if (match > 0) { valid = gtk_list_store_remove(store, &iter); } else { gtk_list_store_set(store, &iter, FILE_COLUMN_POINTER, fd, -1); if (fd->date != old_fd->date) { gchar *size; /* update, file changed */ size = text_from_size(fd->size); gtk_list_store_set(store, &iter, FILE_COLUMN_SIZE, size, FILE_COLUMN_DATE, text_from_time(fd->date), -1); g_free(size); } else if (fd != old_fd) { /* preserve thumbnail */ if (fd->pixbuf) g_object_unref(fd->pixbuf); fd->pixbuf = old_fd->pixbuf; if (fd->pixbuf) g_object_ref(fd->pixbuf); } gtk_list_store_set(store, &iter, FILE_COLUMN_THUMB, (thumbs) ? fd->pixbuf : NULL, -1); if (vfl->select_fd == old_fd) vfl->select_fd = fd; if (valid) valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter); done = TRUE; } } work = work->next; } while (valid) { valid = gtk_list_store_remove(store, &iter); } if (visible_row) { if (gtk_tree_row_reference_valid(visible_row)) { tpath = gtk_tree_row_reference_get_path(visible_row); gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(vfl->listview), tpath, NULL, TRUE, 0.0, 0.0); gtk_tree_path_free(tpath); } gtk_tree_row_reference_free(visible_row); } vflist_send_update(vfl); vflist_thumb_update(vfl);}gint vflist_refresh(ViewFileList *vfl){ GList *old_list; gint ret = TRUE; old_list = vfl->list; vfl->list = NULL; if (vfl->path) { ret = filelist_read(vfl->path, &vfl->list, NULL); } vfl->list = filelist_sort(vfl->list, vfl->sort_method, vfl->sort_ascend); vflist_populate_view(vfl); filelist_free(old_list); return ret;}/* this overrides the low default of a GtkCellRenderer from 100 to CELL_HEIGHT_OVERRIDE, something sane for our purposes */#define CELL_HEIGHT_OVERRIDE 512static void cell_renderer_height_override(GtkCellRenderer *renderer){ GParamSpec *spec; spec = g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(renderer)), "height"); if (spec && G_IS_PARAM_SPEC_INT(spec)) { GParamSpecInt *spec_int; spec_int = G_PARAM_SPEC_INT(spec); if (spec_int->maximum < CELL_HEIGHT_OVERRIDE) spec_int->maximum = CELL_HEIGHT_OVERRIDE; }}static GdkColor *vflist_listview_color_shifted(GtkWidget *widget){ static GdkColor color; static GtkWidget *done = NULL; if (done != widget) { GtkStyle *style; style = gtk_widget_get_style(widget); memcpy(&color, &style->base[GTK_STATE_NORMAL], sizeof(color)); shift_color(&color, -1, 0); done = widget; } return &color;}static void vflist_listview_color_cb(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data){ ViewFileList *vfl = data; gboolean set; gtk_tree_model_get(tree_model, iter, FILE_COLUMN_COLOR, &set, -1); g_object_set(G_OBJECT(cell), "cell-background-gdk", vflist_listview_color_shifted(vfl->listview), "cell-background-set", set, NULL);}static void vflist_listview_add_column(ViewFileList *vfl, 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 (!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); } 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_column_set_cell_data_func(column, renderer, vflist_listview_color_cb, vfl, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(vfl->listview), column);}/* *----------------------------------------------------------------------------- * base *----------------------------------------------------------------------------- */gint vflist_set_path(ViewFileList *vfl, const gchar *path){ GtkListStore *store; if (!path) return FALSE; if (vfl->path && strcmp(path, vfl->path) == 0) return TRUE; g_free(vfl->path); vfl->path = g_strdup(path); /* force complete reload */ store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vfl->listview))); gtk_list_store_clear(store); filelist_free(vfl->list); vfl->list = NULL; return vflist_refresh(vfl);}static void vflist_destroy_cb(GtkWidget *widget, gpointer data){ ViewFileList *vfl = data; if (vfl->popup) { g_signal_handlers_disconnect_matched(G_OBJECT(vfl->popup), G_SIGNAL_MATCH_DATA, 0, 0, 0, NULL, vfl); gtk_widget_destroy(vfl->popup); } vflist_select_idle_cancel(vfl); vflist_thumb_stop(vfl); g_free(vfl->path); filelist_free(vfl->list); g_free(vfl);}ViewFileList *vflist_new(const gchar *path, gint thumbs){ ViewFileList *vfl; GtkListStore *store; GtkTreeSelection *selection; vfl = g_new0(ViewFileList, 1); vfl->path = NULL; vfl->list = NULL; vfl->click_fd = NULL; vfl->select_fd = NULL; vfl->sort_method = SORT_NAME; vfl->sort_ascend = TRUE; vfl->thumbs_enabled = thumbs; vfl->thumbs_running = FALSE; vfl->thumbs_count = 0; vfl->thumbs_loader = NULL; vfl->thumbs_filedata = NULL; vfl->select_idle_id = -1; vfl->popup = NULL; vfl->widget = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(vfl->widget), GTK_SHADOW_IN); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(vfl->widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); g_signal_connect(G_OBJECT(vfl->widget), "destroy", G_CALLBACK(vflist_destroy_cb), vfl); store = gtk_list_store_new(6, G_TYPE_POINTER, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN); vfl->listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); g_object_unref(store); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vfl->listview)); gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE); gtk_tree_selection_set_select_function(selection, vflist_select_cb, vfl, NULL); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(vfl->listview), FALSE); gtk_tree_view_set_enable_search(GTK_TREE_VIEW(vfl->listview), FALSE); vflist_listview_add_column(vfl, FILE_COLUMN_THUMB, "", TRUE, FALSE); vflist_listview_add_column(vfl, FILE_COLUMN_NAME, _("Name"), FALSE, FALSE); vflist_listview_add_column(vfl, FILE_COLUMN_SIZE, _("Size"), FALSE, TRUE); vflist_listview_add_column(vfl, FILE_COLUMN_DATE, _("Date"), FALSE, TRUE); g_signal_connect(G_OBJECT(vfl->listview), "key_press_event", G_CALLBACK(vflist_press_key_cb), vfl); gtk_container_add (GTK_CONTAINER(vfl->widget), vfl->listview); gtk_widget_show(vfl->listview); vflist_dnd_init(vfl); g_signal_connect(G_OBJECT(vfl->listview), "button_press_event", G_CALLBACK(vflist_press_cb), vfl); g_signal_connect(G_OBJECT(vfl->listview), "button_release_event", G_CALLBACK(vflist_release_cb), vfl); if (path) vflist_set_path(vfl, path); return vfl;}void vflist_set_status_func(ViewFileList *vfl, void (*func)(ViewFileList *vfl, gpointer data), gpointer data){ vfl->func_status = func; vfl->data_status = data;}void vflist_set_thumb_status_func(ViewFileList *vfl, void (*func)(ViewFileList *vfl, gdouble val, const gchar *text, gpointer data), gpointer data){ vfl->func_thumb_status = func; vfl->data_thumb_status = data;}void vflist_thumb_set(ViewFileList *vfl, gint enable){ if (vfl->thumbs_enabled == enable) return; vfl->thumbs_enabled = enable; vflist_refresh(vfl);}void vflist_set_layout(ViewFileList *vfl, LayoutWindow *layout){ vfl->layout = layout;}/* *----------------------------------------------------------------------------- * maintenance (for rename, move, remove) *----------------------------------------------------------------------------- */static gint vflist_maint_find_closest(ViewFileList *vfl, gint row, gint count, GList *ignore_list){ GList *list = NULL; GList *work; gint rev = row - 1; row ++; work = ignore_list; while (work) { gint f = vflist_index_by_path(vfl, work->data); if (f >= 0) list = g_list_prepend(list, GINT_TO_POINTER(f)); work = work->next; } while (list) { gint c = TRUE; work = list; while (work && c) { gpointer p = work->data; work = work->next; if (row == GPOINTER_TO_INT(p)) { row++; c = FALSE; } if (rev == GPOINTER_TO_INT(p)) { rev--; c = FALSE; } if (!c) list = g_list_remove(list, p); } if (c && list) { g_list_free(list); list = NULL; } } if (row > count - 1) { if (rev < 0) return -1; else return rev; } else { return row; }}gint vflist_maint_renamed(ViewFileList *vfl, const gchar *source, const gchar *dest){ gint ret = FALSE; gint row; gchar *source_base; gchar *dest_base; GList *work; FileData *fd; row = vflist_index_by_path(vfl, source); if (row < 0) return FALSE; source_base = remove_level_from_path(source); dest_base = remove_level_from_path(dest); work = g_list_nth(vfl->list, row); fd = work->data; if (strcmp(source_base, dest_base) == 0) { GtkListStore *store; GtkTreeIter iter; GtkTreeIter position; gint old_row; gint n; old_row = g_list_index(vfl->list, fd); vfl->list = g_list_remove(vfl->list, fd); g_free(fd->path); fd->path = g_strdup(dest); fd->name = filename_from_path(fd->path); vfl->list = filelist_insert_sort(vfl->list, fd, vfl->sort_method, vfl->sort_ascend); n = g_list_index(vfl->list, fd); store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vfl->listview))); row = vflist_find_row(vfl, fd, &iter); if (vflist_find_row(vfl, fd, &iter) >= 0 && gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &position, NULL, n)) { if (old_row >= n) { gtk_list_store_move_before(store, &iter, &position); } else { gtk_list_store_move_after(store, &iter, &position); } } gtk_list_store_set(store, &iter, FILE_COLUMN_NAME, fd->name, -1); ret = TRUE; } else { ret = vflist_maint_removed(vfl, source, NULL); } g_free(source_base); g_free(dest_base); return ret;}gint vflist_maint_removed(ViewFileList *vfl, const gchar *path, GList *ignore_list){ GtkTreeIter iter; GList *list; FileData *fd; gint row; gint new_row = -1; row = vflist_index_by_path(vfl, path); if (row < 0) return FALSE; if (vflist_index_is_selected(vfl, row) && layout_image_get_collection(vfl->layout, NULL) == NULL) { gint n; n = vflist_count(vfl, NULL); if (ignore_list) { new_row = vflist_maint_find_closest(vfl, row, n, ignore_list); if (debug) printf("row = %d, closest is %d\n", row, new_row); } else { if (row + 1 < n) { new_row = row + 1; } else if (row > 0) { new_row = row - 1; } } vflist_select_none(vfl); if (new_row >= 0) { fd = vflist_index_get_data(vfl, new_row); if (vflist_find_row(vfl, fd, &iter) >= 0) { GtkTreeSelection *selection; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vfl->listview)); gtk_tree_selection_select_iter(selection, &iter); vflist_move_cursor(vfl, &iter); } } } fd = vflist_index_get_data(vfl, row); if (vflist_find_row(vfl, fd, &iter) >= 0) { GtkListStore *store; store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vfl->listview))); gtk_list_store_remove(store, &iter); } list = g_list_nth(vfl->list, row); fd = list->data; /* thumbnail loader check */ if (fd == vfl->thumbs_filedata) vfl->thumbs_filedata = NULL; vfl->list = g_list_remove(vfl->list, fd); file_data_free(fd); vflist_send_update(vfl); return TRUE;}gint vflist_maint_moved(ViewFileList *vfl, const gchar *source, const gchar *dest, GList *ignore_list){ gint ret = FALSE; gchar *buf; if (!source || !vfl->path) return FALSE; buf = remove_level_from_path(source); if (strcmp(buf, vfl->path) == 0) { ret = vflist_maint_removed(vfl, source, ignore_list); } g_free(buf); return ret;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?