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

📄 view_dir_tree.c

📁 Gqview,Linux下基于GTK+库写成的轻量级而能丰富的图像浏览程序。
💻 C
📖 第 1 页 / 共 3 页
字号:
{	ViewDirTree *vdt = data;	GtkTreePath *tpath;	GtkTreeIter iter;	FileData *fd = NULL;	vdt->click_fd = NULL;	if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), x, y,					  &tpath, NULL, NULL, NULL))		{		GtkTreeModel *store;		NodeData *nd;		store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));		gtk_tree_model_get_iter(store, &iter, tpath);		gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &nd, -1);		gtk_tree_path_free(tpath);		fd = (nd) ? nd->fd : NULL;		}	if (!fd) return;        if (info == TARGET_URI_LIST)                {		GList *list;		gint active;		list = uri_list_from_text(selection_data->data, TRUE);		if (!list) return;		active = access_file(fd->path, W_OK | X_OK);		vdtree_color_set(vdt, fd, TRUE);		vdt->popup = vdtree_drop_menu(vdt, active);		gtk_menu_popup(GTK_MENU(vdt->popup), NULL, NULL, NULL, NULL, 0, time);		vdt->drop_fd = fd;		vdt->drop_list = list;		}}static gint vdtree_dnd_drop_expand_cb(gpointer data){	ViewDirTree *vdt = data;	GtkTreeIter iter;	if (vdt->drop_fd &&	    vdtree_find_row(vdt, vdt->drop_fd, &iter, NULL))		{		vdtree_populate_path_by_iter(vdt, &iter, FALSE, vdt->path);		vdtree_expand_by_data(vdt, vdt->drop_fd, TRUE);		}	vdt->drop_expand_id = -1;	return FALSE;}static void vdtree_dnd_drop_expand_cancel(ViewDirTree *vdt){	if (vdt->drop_expand_id != -1) g_source_remove(vdt->drop_expand_id);	vdt->drop_expand_id = -1;}static void vdtree_dnd_drop_expand(ViewDirTree *vdt){	vdtree_dnd_drop_expand_cancel(vdt);	vdt->drop_expand_id = g_timeout_add(1000, vdtree_dnd_drop_expand_cb, vdt);}static void vdtree_drop_update(ViewDirTree *vdt, gint x, gint y){	GtkTreePath *tpath;	GtkTreeIter iter;	FileData *fd = NULL;	if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vdt->treeview), x, y,					  &tpath, NULL, NULL, NULL))		{		GtkTreeModel *store;		NodeData *nd;		store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdt->treeview));		gtk_tree_model_get_iter(store, &iter, tpath);		gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &nd, -1);		gtk_tree_path_free(tpath);		fd = (nd) ? nd->fd : NULL;		}	if (fd != vdt->drop_fd)		{		vdtree_color_set(vdt, vdt->drop_fd, FALSE);		vdtree_color_set(vdt, fd, TRUE);		if (fd) vdtree_dnd_drop_expand(vdt);		}	vdt->drop_fd = fd;}static void vdtree_dnd_drop_scroll_cancel(ViewDirTree *vdt){	if (vdt->drop_scroll_id != -1) g_source_remove(vdt->drop_scroll_id);	vdt->drop_scroll_id = -1;}static gint vdtree_auto_scroll_idle_cb(gpointer data){	ViewDirTree *vdt = data;	if (vdt->drop_fd)		{		GdkWindow *window;		gint x, y;		gint w, h;		window = vdt->treeview->window;		gdk_window_get_pointer(window, &x, &y, NULL);		gdk_drawable_get_size(window, &w, &h);		if (x >= 0 && x < w && y >= 0 && y < h)			{			vdtree_drop_update(vdt, x, y);			}		}	vdt->drop_scroll_id = -1;	return FALSE;}static gint vdtree_auto_scroll_notify_cb(GtkWidget *widget, gint x, gint y, gpointer data){	ViewDirTree *vdt = data;	if (!vdt->drop_fd || vdt->drop_list) return FALSE;	if (vdt->drop_scroll_id == -1) vdt->drop_scroll_id = g_idle_add(vdtree_auto_scroll_idle_cb, vdt);	return TRUE;}static gint vdtree_dnd_drop_motion(GtkWidget *widget, GdkDragContext *context,				   gint x, gint y, guint time, gpointer data){        ViewDirTree *vdt = data;	vdt->click_fd = NULL;	if (gtk_drag_get_source_widget(context) == vdt->treeview)		{		gdk_drag_status(context, 0, time);		return TRUE;		}	else		{		gdk_drag_status(context, context->suggested_action, time);		}	vdtree_drop_update(vdt, x, y);	if (vdt->drop_fd)		{		GtkAdjustment *adj = gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(vdt->treeview));		widget_auto_scroll_start(vdt->treeview, adj, -1, -1, vdtree_auto_scroll_notify_cb, vdt);		}	return FALSE;}static void vdtree_dnd_drop_leave(GtkWidget *widget, GdkDragContext *context, guint time, gpointer data){	ViewDirTree *vdt = data;	if (vdt->drop_fd != vdt->click_fd) vdtree_color_set(vdt, vdt->drop_fd, FALSE);	vdt->drop_fd = NULL;	vdtree_dnd_drop_expand_cancel(vdt);}static void vdtree_dnd_init(ViewDirTree *vdt){	gtk_drag_source_set(vdt->treeview, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,			    dnd_file_drag_types, dnd_file_drag_types_count,			    GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK);	g_signal_connect(G_OBJECT(vdt->treeview), "drag_data_get",			 G_CALLBACK(vdtree_dnd_get), vdt);	g_signal_connect(G_OBJECT(vdt->treeview), "drag_begin",			 G_CALLBACK(vdtree_dnd_begin), vdt);	g_signal_connect(G_OBJECT(vdt->treeview), "drag_end",			 G_CALLBACK(vdtree_dnd_end), vdt);	vdtree_dest_set(vdt, TRUE);	g_signal_connect(G_OBJECT(vdt->treeview), "drag_data_received",			 G_CALLBACK(vdtree_dnd_drop_receive), vdt);	g_signal_connect(G_OBJECT(vdt->treeview), "drag_motion",			 G_CALLBACK(vdtree_dnd_drop_motion), vdt);	g_signal_connect(G_OBJECT(vdt->treeview), "drag_leave",			 G_CALLBACK(vdtree_dnd_drop_leave), vdt);}/* *---------------------------------------------------------------------------- * parts lists *---------------------------------------------------------------------------- */static GList *parts_list(const gchar *path){	GList *list = NULL;	const gchar *strb, *strp;	gint l;	strp = path;	if (*strp != '/') return NULL;	strp++;	strb = strp;	l = 0;	while (*strp != '\0')		{		if (*strp == '/')			{			if (l > 0) list = g_list_prepend(list, g_strndup(strb, l));			strp++;			strb = strp;			l = 0;			}		else			{			strp++;			l++;			}		}	if (l > 0) list = g_list_prepend(list, g_strndup(strb, l));	list = g_list_reverse(list);	list = g_list_prepend(list, g_strdup("/"));	return list;}static void parts_list_free(GList *list){	GList *work = list;	while (work)		{		PathData *pd = work->data;		g_free(pd->name);		g_free(pd);		work = work->next;		}	g_list_free(list);}static GList *parts_list_add_node_points(ViewDirTree *vdt, GList *list){	GList *work;	GtkTreeModel *store;	GtkTreeIter iter;	gint valid;	store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdt->treeview));	valid = gtk_tree_model_get_iter_first(store, &iter);	work = list;	while (work)		{		PathData *pd;		FileData *fd = NULL;		pd = g_new0(PathData, 1);		pd->name = work->data;		while (valid && !fd)			{			NodeData *nd;			gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &nd, -1);			if (strcmp(nd->fd->name, pd->name) == 0)				{				fd = nd->fd;				}			else				{				valid = gtk_tree_model_iter_next(store, &iter);				}			}		pd->node = fd;		work->data = pd;		if (fd)			{			GtkTreeIter parent;			memcpy(&parent, &iter, sizeof(parent));			valid = gtk_tree_model_iter_children(store, &iter, &parent);			}		work = work->next;		}	return list;}/* *---------------------------------------------------------------------------- * misc *---------------------------------------------------------------------------- */#if 0static void vdtree_row_deleted_cb(GtkTreeModel *tree_model, GtkTreePath *tpath, gpointer data){	GtkTreeIter iter;	NodeData *nd;	gtk_tree_model_get_iter(tree_model, &iter, tpath);	gtk_tree_model_get(tree_model, &iter, DIR_COLUMN_POINTER, &nd, -1);	if (!nd) return;	file_data_free(nd->fd);	g_free(nd);}#endif/* *---------------------------------------------------------------------------- * node traversal, management *---------------------------------------------------------------------------- */static gint vdtree_find_iter_by_data(ViewDirTree *vdt, GtkTreeIter *parent, NodeData *nd, GtkTreeIter *iter){	GtkTreeModel *store;	store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdt->treeview));	if (!nd || !gtk_tree_model_iter_children(store, iter, parent)) return -1;	do	{		NodeData *cnd;		gtk_tree_model_get(store, iter, DIR_COLUMN_POINTER, &cnd, -1);		if (cnd == nd) return TRUE;		} while (gtk_tree_model_iter_next(store, iter));	return FALSE;}static NodeData *vdtree_find_iter_by_name(ViewDirTree *vdt, GtkTreeIter *parent, const gchar *name, GtkTreeIter *iter){	GtkTreeModel *store;	store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdt->treeview));	if (!name || !gtk_tree_model_iter_children(store, iter, parent)) return NULL;	do	{		NodeData *nd;		gtk_tree_model_get(store, iter, DIR_COLUMN_POINTER, &nd, -1);		if (nd && strcmp(nd->fd->name, name) == 0) return nd;		} while (gtk_tree_model_iter_next(store, iter));	return NULL;}static void vdtree_add_by_data(ViewDirTree *vdt, FileData *fd, GtkTreeIter *parent){	GtkTreeStore *store;	GtkTreeIter child;	GList *list;	NodeData *nd;	GdkPixbuf *pixbuf;	NodeData *end;	GtkTreeIter empty;	if (!fd) return;	list = parts_list(fd->path);	if (!list) return;	if (access_file(fd->path, R_OK | X_OK))		{		pixbuf = vdt->pf->close;		}	else		{		pixbuf = vdt->pf->deny;		}	nd = g_new0(NodeData, 1);	nd->fd = fd;	nd->expanded = FALSE;	nd->last_update = time(NULL);	store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vdt->treeview)));	gtk_tree_store_append(store, &child, parent);	gtk_tree_store_set(store, &child, DIR_COLUMN_POINTER, nd,					 DIR_COLUMN_ICON, pixbuf,					 DIR_COLUMN_NAME, nd->fd->name,					 DIR_COLUMN_COLOR, FALSE, -1);	/* all nodes are created with an "empty" node, so that the expander is shown	 * this is removed when the child is populated */	end = g_new0(NodeData, 1);	end->fd = g_new0(FileData, 1);	end->fd->path = g_strdup("");	end->fd->name = end->fd->path;	end->expanded = TRUE;	gtk_tree_store_append(store, &empty, &child);	gtk_tree_store_set(store, &empty, DIR_COLUMN_POINTER, end,					  DIR_COLUMN_NAME, "empty", -1);	if (parent)		{		NodeData *pnd;		GtkTreePath *tpath;		gtk_tree_model_get(GTK_TREE_MODEL(store), parent, DIR_COLUMN_POINTER, &pnd, -1);		tpath = gtk_tree_model_get_path(GTK_TREE_MODEL(store), parent);		if (tree_descend_subdirs &&		    gtk_tree_view_row_expanded(GTK_TREE_VIEW(vdt->treeview), tpath) &&		    !nd->expanded)			{			vdtree_populate_path_by_iter(vdt, &child, FALSE, vdt->path);			}		gtk_tree_path_free(tpath);		}}static gint vdtree_populate_path_by_iter(ViewDirTree *vdt, GtkTreeIter *iter, gint force, const gchar *target_path){	GtkTreeModel *store;	GList *list;	GList *work;	GList *old;	time_t current_time;	GtkTreeIter child;	NodeData *nd;	store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdt->treeview));	gtk_tree_model_get(store, iter, DIR_COLUMN_POINTER, &nd, -1);	if (!nd) return FALSE;	current_time = time(NULL);		if (nd->expanded)		{		if (!force && current_time - nd->last_update < 10) return TRUE;		if (!isdir(nd->fd->path))			{			if (vdt->click_fd == nd->fd) vdt->click_fd = NULL;			if (vdt->drop_fd == nd->fd) vdt->drop_fd = NULL;			gtk_tree_store_remove(GTK_TREE_STORE(store), iter);			vdtree_node_free(nd);			return FALSE;			}		if (!force && filetime(nd->fd->path) == nd->fd->date) return TRUE;		}	vdtree_busy_push(vdt);	list = NULL;	filelist_read(nd->fd->path, NULL, &list);	/* when hidden files are not enabled, and the user enters a hidden path,	 * allow the tree to display that path by specifically inserting the hidden entries	 */	if (!show_dot_files &&	    target_path &&	    strncmp(nd->fd->path, target_path, strlen(nd->fd->path)) == 0)		{		gint n;		n = strlen(nd->fd->path);		if (target_path[n] == '/' && target_path[n+1] == '.')			{			gchar *name8;			gchar *namel;			struct stat sbuf;			n++;			while (target_path[n] != '\0' && target_path[n] != '/') n++;			name8 = g_strndup(target_path, n);			namel = path_from_utf8(name8);			if (stat_utf8(name8, &sbuf))				{				list = g_list_prepend(list, file_data_new(namel, &sbuf));				}			g_free(namel);			g_free(name8);			}		}	old = NULL;	if (gtk_tree_model_iter_children(store, &child, iter))		{		do	{			NodeData *cnd;			gtk_tree_model_get(store, &child, DIR_COLUMN_POINTER, &cnd, -1);			old = g_list_prepend(old, cnd);			} while (gtk_tree_model_iter_next(store, &child));		}	work = list;	while (work)		{		FileData *fd;		fd = work->data;		work = work->next;		if (strcmp(fd->name, ".") == 0 || strcmp(fd->name, "..") == 0)			{			file_data_free(fd);			}		else			{			NodeData *cnd;			cnd = vdtree_find_iter_by_name(vdt, iter, fd->name, &child);			if (cnd)				{				old = g_list_remove(old, cnd);				if (cnd->expanded && cnd->fd->date != fd->date &&				    vdtree_populate_path_by_iter(vdt, &child, FALSE, target_path))					{					cnd->fd->size = fd->size;					cnd->fd->date = fd->date;					}				file_data_free(fd);				}			else				{				vdtree_add_by_data(vdt, fd, iter);				}			}		}	work = old;	while (work)		{		NodeData *cnd = work->data;		work = work->next;		if (vdt->click_fd == cnd->fd) vdt->click_fd = NULL;		if (vdt->drop_fd == cnd->fd) vdt->drop_fd = NULL;		if (vdtree_find_iter_by_data(vdt, iter, cnd, &child))			{			gtk_tree_store_remove(GTK_TREE_STORE(store), &child);			vdtree_node_free(cnd);			}		}	g_list_free(old);	g_list_free(list);	vdtree_busy_pop(vdt);	nd->expanded = TRUE;	nd->last_update = current_time;	return TRUE;}static FileData *vdtree_populate_path(ViewDirTree *vdt, const gchar *path, gint expand, gint force){	GList *list;	GList *work;	FileData *fd = NULL;	if (!path) return NULL;	vdtree_busy_push(vdt);

⌨️ 快捷键说明

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