⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 view_dir_tree.c

📁 Gqview,Linux下基于GTK+库写成的轻量级而能丰富的图像浏览程序。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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_dir_tree.h"#include "dnd.h"#include "dupe.h"#include "filelist.h"#include "layout.h"#include "layout_image.h"#include "layout_util.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 */#define VDTREE_INDENT 14#define VDTREE_PAD 4enum {	DIR_COLUMN_POINTER = 0,	DIR_COLUMN_ICON,	DIR_COLUMN_NAME,	DIR_COLUMN_COLOR,	DIR_COLUMN_COUNT};typedef struct _PathData PathData;struct _PathData{	gchar *name;	FileData *node;};typedef struct _NodeData NodeData;struct _NodeData{	FileData *fd;	gint expanded;	time_t last_update;};static gint vdtree_populate_path_by_iter(ViewDirTree *vdt, GtkTreeIter *iter, gint force, const gchar *target_path);static FileData *vdtree_populate_path(ViewDirTree *vdt, const gchar *path, gint expand, gint force);/* *---------------------------------------------------------------------------- * utils *---------------------------------------------------------------------------- */static void set_cursor(GtkWidget *widget, GdkCursorType cursor_type){	GdkCursor *cursor = NULL;	if (!widget || !widget->window) return;	if (cursor_type > -1) cursor = gdk_cursor_new (cursor_type);	gdk_window_set_cursor (widget->window, cursor);	if (cursor) gdk_cursor_unref(cursor);	gdk_flush();}static void vdtree_busy_push(ViewDirTree *vdt){	if (vdt->busy_ref == 0) set_cursor(vdt->treeview, GDK_WATCH);	vdt->busy_ref++;}static void vdtree_busy_pop(ViewDirTree *vdt){	if (vdt->busy_ref == 1) set_cursor(vdt->treeview, -1);	if (vdt->busy_ref > 0) vdt->busy_ref--;}static gint vdtree_find_row(ViewDirTree *vdt, FileData *fd, GtkTreeIter *iter, GtkTreeIter *parent){	GtkTreeModel *store;	gint valid;	store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdt->treeview));	if (parent)		{		valid = gtk_tree_model_iter_children(store, iter, parent);		}	else		{		valid = gtk_tree_model_get_iter_first(store, iter);		}	while (valid)		{		NodeData *nd;		GtkTreeIter found;		gtk_tree_model_get(GTK_TREE_MODEL(store), iter, DIR_COLUMN_POINTER, &nd, -1);		if (nd->fd == fd) return TRUE;		if (vdtree_find_row(vdt, fd, &found, iter))			{			memcpy(iter, &found, sizeof(found));			return TRUE;			}		valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), iter);		}	return FALSE;}static void vdtree_icon_set_by_iter(ViewDirTree *vdt, GtkTreeIter *iter, GdkPixbuf *pixbuf){	GtkTreeModel *store;	GdkPixbuf *old;	store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdt->treeview));	gtk_tree_model_get(store, iter, DIR_COLUMN_ICON, &old, -1);	if (old != vdt->pf->deny)		{		gtk_tree_store_set(GTK_TREE_STORE(store), iter, DIR_COLUMN_ICON, pixbuf, -1);		}}static void vdtree_expand_by_iter(ViewDirTree *vdt, GtkTreeIter *iter, gint expand){	GtkTreeModel *store;	GtkTreePath *tpath;	store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdt->treeview));	tpath = gtk_tree_model_get_path(store, iter);	if (expand)		{		gtk_tree_view_expand_row(GTK_TREE_VIEW(vdt->treeview), tpath, FALSE);		vdtree_icon_set_by_iter(vdt, iter, vdt->pf->open);		}	else		{		gtk_tree_view_collapse_row(GTK_TREE_VIEW(vdt->treeview), tpath);		}	gtk_tree_path_free(tpath);}static void vdtree_expand_by_data(ViewDirTree *vdt, FileData *fd, gint expand){	GtkTreeIter iter;	if (vdtree_find_row(vdt, fd, &iter, NULL))		{		vdtree_expand_by_iter(vdt, &iter, expand);		}}static void vdtree_color_set(ViewDirTree *vdt, FileData *fd, gint color_set){	GtkTreeModel *store;	GtkTreeIter iter;	if (!vdtree_find_row(vdt, fd, &iter, NULL)) return;	store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdt->treeview));	gtk_tree_store_set(GTK_TREE_STORE(store), &iter, DIR_COLUMN_COLOR, color_set, -1);}static gint vdtree_rename_row_cb(TreeEditData *td, const gchar *old, const gchar *new, gpointer data){	ViewDirTree *vdt = data;	GtkTreeModel *store;	GtkTreeIter iter;	NodeData *nd;	gchar *old_path;	gchar *new_path;	gchar *base;	store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdt->treeview));	if (!gtk_tree_model_get_iter(store, &iter, td->path)) return FALSE;	gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &nd, -1);	if (!nd) return FALSE;	old_path = g_strdup(nd->fd->path);	base = remove_level_from_path(old_path);	new_path = concat_dir_and_file(base, new);	g_free(base);	if (file_util_rename_dir(old_path, new_path, vdt->treeview))		{		vdtree_populate_path(vdt, new_path, TRUE, TRUE);		if (vdt->layout && strcmp(vdt->path, old_path) == 0)			{			layout_set_path(vdt->layout, new_path);			}		}	g_free(old_path);	g_free(new_path);	return FALSE;}static void vdtree_rename_by_data(ViewDirTree *vdt, FileData *fd){	GtkTreeModel *store;	GtkTreePath *tpath;	GtkTreeIter iter;	if (!fd ||	    !vdtree_find_row(vdt, fd, &iter, NULL)) return;	store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdt->treeview));	tpath = gtk_tree_model_get_path(store, &iter);	tree_edit_by_path(GTK_TREE_VIEW(vdt->treeview), tpath, 0, fd->name,			  vdtree_rename_row_cb, vdt);	gtk_tree_path_free(tpath);}static void vdtree_node_free(NodeData *nd){	if (!nd) return;	file_data_free(nd->fd);	g_free(nd);}static void vdtree_popup_destroy_cb(GtkWidget *widget, gpointer data){	ViewDirTree *vdt = data;	vdtree_color_set(vdt, vdt->click_fd, FALSE);	vdt->click_fd = NULL;	vdt->popup = NULL;	vdtree_color_set(vdt, vdt->drop_fd, FALSE);	path_list_free(vdt->drop_list);	vdt->drop_list = NULL;	vdt->drop_fd = NULL;}/* *----------------------------------------------------------------------------- * drop menu (from dnd) *----------------------------------------------------------------------------- */static void vdtree_drop_menu_copy_cb(GtkWidget *widget, gpointer data){	ViewDirTree *vdt = data;	const gchar *path;	GList *list;	if (!vdt->drop_fd) return;	path = vdt->drop_fd->path;	list = vdt->drop_list;	vdt->drop_list = NULL;	file_util_copy_simple(list, path);}static void vdtree_drop_menu_move_cb(GtkWidget *widget, gpointer data){	ViewDirTree *vdt = data;	const gchar *path;	GList *list;	if (!vdt->drop_fd) return;	path = vdt->drop_fd->path;	list = vdt->drop_list;	vdt->drop_list = NULL;	file_util_move_simple(list, path);}static GtkWidget *vdtree_drop_menu(ViewDirTree *vdt, gint active){	GtkWidget *menu;	menu = popup_menu_short_lived();	g_signal_connect(G_OBJECT(menu), "destroy",			 G_CALLBACK(vdtree_popup_destroy_cb), vdt);	menu_item_add_stock_sensitive(menu, _("_Copy"), GTK_STOCK_COPY, active,				      G_CALLBACK(vdtree_drop_menu_copy_cb), vdt);	menu_item_add_sensitive(menu, _("_Move"), active, G_CALLBACK(vdtree_drop_menu_move_cb), vdt);	menu_item_add_divider(menu);	menu_item_add_stock(menu, _("Cancel"), GTK_STOCK_CANCEL, NULL, vdt);	return menu;}/* *----------------------------------------------------------------------------- * pop-up menu *----------------------------------------------------------------------------- */static void vdtree_pop_menu_up_cb(GtkWidget *widget, gpointer data){	ViewDirTree *vdt = data;	gchar *path;	if (!vdt->path || strcmp(vdt->path, "/") == 0) return;	path = remove_level_from_path(vdt->path);	if (vdt->select_func)		{		vdt->select_func(vdt, path, vdt->select_data);		}	g_free(path);}static void vdtree_pop_menu_slide_cb(GtkWidget *widget, gpointer data){	ViewDirTree *vdt = data;	gchar *path;	if (!vdt->layout) return;	if (!vdt->click_fd) return;	path = g_strdup(vdt->click_fd->path);	layout_set_path(vdt->layout, path);	layout_select_none(vdt->layout);	layout_image_slideshow_stop(vdt->layout);	layout_image_slideshow_start(vdt->layout);	g_free(path);}static void vdtree_pop_menu_slide_rec_cb(GtkWidget *widget, gpointer data){	ViewDirTree *vdt = data;	gchar *path;	GList *list;	if (!vdt->layout) return;	if (!vdt->click_fd) return;	path = g_strdup(vdt->click_fd->path);	list = path_list_recursive(path);	layout_image_slideshow_stop(vdt->layout);	layout_image_slideshow_start_from_list(vdt->layout, list);	g_free(path);}static void vdtree_pop_menu_dupe(ViewDirTree *vdt, gint recursive){	DupeWindow *dw;	const gchar *path;	GList *list = NULL;	if (!vdt->click_fd) return;	path = vdt->click_fd->path;	if (recursive)		{		list = g_list_append(list, g_strdup(path));		}	else		{		path_list(path, &list, NULL);		list = path_list_filter(list, FALSE);		}	dw = dupe_window_new(DUPE_MATCH_NAME);	dupe_window_add_files(dw, list, recursive);	path_list_free(list);}static void vdtree_pop_menu_dupe_cb(GtkWidget *widget, gpointer data){	ViewDirTree *vdt = data;	vdtree_pop_menu_dupe(vdt, FALSE);}static void vdtree_pop_menu_dupe_rec_cb(GtkWidget *widget, gpointer data){	ViewDirTree *vdt = data;	vdtree_pop_menu_dupe(vdt, TRUE);}static void vdtree_pop_menu_new_cb(GtkWidget *widget, gpointer data){	ViewDirTree *vdt = data;	const gchar *path;	gchar *new_path;	gchar *buf;	if (!vdt->click_fd) return;	path = vdt->click_fd->path;	buf = concat_dir_and_file(path, _("new_folder"));	new_path = unique_filename(buf, NULL, NULL, FALSE);	g_free(buf);	if (!new_path) return;	if (!mkdir_utf8(new_path, 0755))		{		gchar *text;		text = g_strdup_printf(_("Unable to create folder:\n%s"), new_path);		file_util_warning_dialog(_("Error creating folder"), text, GTK_STOCK_DIALOG_ERROR, vdt->treeview);		g_free(text);		}	else		{		FileData *fd;		fd = vdtree_populate_path(vdt, new_path, TRUE, TRUE);		vdtree_rename_by_data(vdt, fd);		}	g_free(new_path);}static void vdtree_pop_menu_rename_cb(GtkWidget *widget, gpointer data){	ViewDirTree *vdt = data;	vdtree_rename_by_data(vdt, vdt->click_fd);}static void vdtree_pop_menu_tree_cb(GtkWidget *widget, gpointer data){	ViewDirTree *vdt = data;	if (vdt->layout) layout_views_set(vdt->layout, FALSE, vdt->layout->icon_view);}static void vdtree_pop_menu_refresh_cb(GtkWidget *widget, gpointer data){	ViewDirTree *vdt = data;	if (vdt->layout) layout_refresh(vdt->layout);}static GtkWidget *vdtree_pop_menu(ViewDirTree *vdt, FileData *fd){	GtkWidget *menu;	gint active;	active = (fd != NULL);	menu = popup_menu_short_lived();	g_signal_connect(G_OBJECT(menu), "destroy",			 G_CALLBACK(vdtree_popup_destroy_cb), vdt);	menu_item_add_stock_sensitive(menu, _("_Up to parent"), GTK_STOCK_GO_UP,		       		      (vdt->path && strcmp(vdt->path, "/") != 0),				      G_CALLBACK(vdtree_pop_menu_up_cb), vdt);	menu_item_add_divider(menu);	menu_item_add_sensitive(menu, _("_Slideshow"), active,				G_CALLBACK(vdtree_pop_menu_slide_cb), vdt);	menu_item_add_sensitive(menu, _("Slideshow recursive"), active,				G_CALLBACK(vdtree_pop_menu_slide_rec_cb), vdt);	menu_item_add_divider(menu);	menu_item_add_stock_sensitive(menu, _("Find _duplicates..."), GTK_STOCK_FIND, active,				      G_CALLBACK(vdtree_pop_menu_dupe_cb), vdt);	menu_item_add_stock_sensitive(menu, _("Find duplicates recursive..."), GTK_STOCK_FIND, active,				      G_CALLBACK(vdtree_pop_menu_dupe_rec_cb), vdt);	menu_item_add_divider(menu);	active = (fd &&		  access_file(fd->path, W_OK | X_OK));	menu_item_add_sensitive(menu, _("_New folder..."), active,				G_CALLBACK(vdtree_pop_menu_new_cb), vdt);	menu_item_add_sensitive(menu, _("_Rename..."), active,				G_CALLBACK(vdtree_pop_menu_rename_cb), vdt);	menu_item_add_divider(menu);	menu_item_add_check(menu, _("View as _tree"), TRUE,			    G_CALLBACK(vdtree_pop_menu_tree_cb), vdt);	menu_item_add_stock(menu, _("Re_fresh"), GTK_STOCK_REFRESH,			    G_CALLBACK(vdtree_pop_menu_refresh_cb), vdt);	return menu;}/* *---------------------------------------------------------------------------- * dnd *---------------------------------------------------------------------------- */static GtkTargetEntry vdtree_dnd_drop_types[] = {	{ "text/uri-list", 0, TARGET_URI_LIST }};static gint vdtree_dnd_drop_types_count = 1;static void vdtree_dest_set(ViewDirTree *vdt, gint enable){	if (enable)		{		gtk_drag_dest_set(vdt->treeview,				  GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,				  vdtree_dnd_drop_types, vdtree_dnd_drop_types_count,				  GDK_ACTION_MOVE | GDK_ACTION_COPY);		}	else		{		gtk_drag_dest_unset(vdt->treeview);		}}static void vdtree_dnd_get(GtkWidget *widget, GdkDragContext *context,			   GtkSelectionData *selection_data, guint info,			   guint time, gpointer data){	ViewDirTree *vdt = data;	gchar *path;	GList *list;	gchar *uri_text = NULL;	gint length = 0;	if (!vdt->click_fd) return;	path = vdt->click_fd->path;	switch (info)		{		case TARGET_URI_LIST:		case TARGET_TEXT_PLAIN:			list = g_list_prepend(NULL, path);			uri_text = uri_text_from_list(list, &length, (info == TARGET_TEXT_PLAIN));			g_list_free(list);			break;		}	if (uri_text)		{		gtk_selection_data_set(selection_data, selection_data->target,				       8, uri_text, length);		g_free(uri_text);		}}static void vdtree_dnd_begin(GtkWidget *widget, GdkDragContext *context, gpointer data){	ViewDirTree *vdt = data;	vdtree_color_set(vdt, vdt->click_fd, TRUE);	vdtree_dest_set(vdt, FALSE);}static void vdtree_dnd_end(GtkWidget *widget, GdkDragContext *context, gpointer data){	ViewDirTree *vdt = data;	vdtree_color_set(vdt, vdt->click_fd, FALSE);	vdtree_dest_set(vdt, TRUE);}static void vdtree_dnd_drop_receive(GtkWidget *widget,				    GdkDragContext *context, gint x, gint y,				    GtkSelectionData *selection_data, guint info,				    guint time, gpointer data)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -