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

📄 view_dir_list.c

📁 Gqview,Linux下基于GTK+库写成的轻量级而能丰富的图像浏览程序。
💻 C
📖 第 1 页 / 共 2 页
字号:
static void vdlist_scroll_to_row(ViewDirList *vdl, FileData *fd, gfloat y_align){	GtkTreeIter iter;	if (GTK_WIDGET_REALIZED(vdl->listview) &&	    vdlist_find_row(vdl, fd, &iter) >= 0)		{		GtkTreeModel *store;		GtkTreePath *tpath;		store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdl->listview));		tpath = gtk_tree_model_get_path(store, &iter);		gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(vdl->listview), tpath, NULL, TRUE, y_align, 0.0);		gtk_tree_view_set_cursor(GTK_TREE_VIEW(vdl->listview), tpath, NULL, FALSE);		gtk_tree_path_free(tpath);		if (!GTK_WIDGET_HAS_FOCUS(vdl->listview)) gtk_widget_grab_focus(vdl->listview);		}}static void vdlist_drop_update(ViewDirList *vdl, gint x, gint y){	GtkTreePath *tpath;	GtkTreeIter iter;	FileData *fd = NULL;	if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vdl->listview), x, y,					  &tpath, NULL, NULL, NULL))		{		GtkTreeModel *store;		store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdl->listview));		gtk_tree_model_get_iter(store, &iter, tpath);		gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &fd, -1);		gtk_tree_path_free(tpath);		}	if (fd != vdl->drop_fd)		{		vdlist_color_set(vdl, vdl->drop_fd, FALSE);		vdlist_color_set(vdl, fd, TRUE);		}	vdl->drop_fd = fd;}static void vdlist_dnd_drop_scroll_cancel(ViewDirList *vdl){	if (vdl->drop_scroll_id != -1) g_source_remove(vdl->drop_scroll_id);	vdl->drop_scroll_id = -1;}static gint vdlist_auto_scroll_idle_cb(gpointer data){	ViewDirList *vdl = data;	if (vdl->drop_fd)		{		GdkWindow *window;		gint x, y;		gint w, h;		window = vdl->listview->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)			{			vdlist_drop_update(vdl, x, y);			}		}	vdl->drop_scroll_id = -1;	return FALSE;}static gint vdlist_auto_scroll_notify_cb(GtkWidget *widget, gint x, gint y, gpointer data){	ViewDirList *vdl = data;	if (!vdl->drop_fd || vdl->drop_list) return FALSE;	if (vdl->drop_scroll_id == -1) vdl->drop_scroll_id = g_idle_add(vdlist_auto_scroll_idle_cb, vdl);	return TRUE;}static gint vdlist_dnd_drop_motion(GtkWidget *widget, GdkDragContext *context,				   gint x, gint y, guint time, gpointer data){	ViewDirList *vdl = data;	vdl->click_fd = NULL;	if (gtk_drag_get_source_widget(context) == vdl->listview)		{		/* from same window */		gdk_drag_status(context, 0, time);		return TRUE;		}	else		{		gdk_drag_status(context, context->suggested_action, time);		}	vdlist_drop_update(vdl, x, y);        if (vdl->drop_fd)		{		GtkAdjustment *adj = gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(vdl->listview));		widget_auto_scroll_start(vdl->listview, adj, -1, -1, vdlist_auto_scroll_notify_cb, vdl);		}	return FALSE;}static void vdlist_dnd_drop_leave(GtkWidget *widget, GdkDragContext *context, guint time, gpointer data){	ViewDirList *vdl = data;	if (vdl->drop_fd != vdl->click_fd) vdlist_color_set(vdl, vdl->drop_fd, FALSE);	vdl->drop_fd = NULL;}static void vdlist_dnd_init(ViewDirList *vdl){	gtk_drag_source_set(vdl->listview, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,			    dnd_file_drag_types, dnd_file_drag_types_count,			    GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);	g_signal_connect(G_OBJECT(vdl->listview), "drag_data_get",			 G_CALLBACK(vdlist_dnd_get), vdl);	g_signal_connect(G_OBJECT(vdl->listview), "drag_begin",			 G_CALLBACK(vdlist_dnd_begin), vdl);	g_signal_connect(G_OBJECT(vdl->listview), "drag_end",			 G_CALLBACK(vdlist_dnd_end), vdl);	vdlist_dest_set(vdl, TRUE);	g_signal_connect(G_OBJECT(vdl->listview), "drag_data_received",			 G_CALLBACK(vdlist_dnd_drop_receive), vdl);	g_signal_connect(G_OBJECT(vdl->listview), "drag_motion",			 G_CALLBACK(vdlist_dnd_drop_motion), vdl);	g_signal_connect(G_OBJECT(vdl->listview), "drag_leave",			 G_CALLBACK(vdlist_dnd_drop_leave), vdl);}/* *----------------------------------------------------------------------------- * main *----------------------------------------------------------------------------- */ static void vdlist_select_row(ViewDirList *vdl, FileData *fd){	if (fd && vdl->select_func)		{		gchar *path;		path = g_strdup(fd->path);		vdl->select_func(vdl, path, vdl->select_data);		g_free(path);		}}const gchar *vdlist_row_get_path(ViewDirList *vdl, gint row){	FileData *fd;	fd = g_list_nth_data(vdl->list, row);	if (fd) return fd->path;	return NULL;}static void vdlist_populate(ViewDirList *vdl){	GtkListStore *store;	GList *work;	store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vdl->listview)));	gtk_list_store_clear(store);	work = vdl->list;	while (work)		{		FileData *fd;		GtkTreeIter iter;		GdkPixbuf *pixbuf;		fd = work->data;		if (access_file(fd->path, R_OK | X_OK) && fd->name)			{			if (fd->name[0] == '.' && fd->name[1] == '\0')				{				pixbuf = vdl->pf->open;				}			else if (fd->name[0] == '.' && fd->name[1] == '.' && fd->name[2] == '\0')				{				pixbuf = vdl->pf->parent;				}			else				{				pixbuf = vdl->pf->close;				}			}		else			{			pixbuf = vdl->pf->deny;			}		gtk_list_store_append(store, &iter);		gtk_list_store_set(store, &iter,				   DIR_COLUMN_POINTER, fd,				   DIR_COLUMN_ICON, pixbuf,				   DIR_COLUMN_NAME, fd->name, -1);		work = work->next;		}	vdl->click_fd = NULL;	vdl->drop_fd = NULL;}gint vdlist_set_path(ViewDirList *vdl, const gchar *path){	gint ret;	FileData *fd;	gchar *old_path = NULL;	if (!path) return FALSE;	if (vdl->path && strcmp(path, vdl->path) == 0) return TRUE;	if (vdl->path)		{		gchar *base;		base = remove_level_from_path(vdl->path);		if (strcmp(base, path) == 0)			{			old_path = g_strdup(filename_from_path(vdl->path));			}		g_free(base);		}	g_free(vdl->path);	vdl->path = g_strdup(path);	filelist_free(vdl->list);	vdl->list = NULL;	ret = filelist_read(vdl->path, NULL, &vdl->list);	vdl->list = filelist_sort(vdl->list, SORT_NAME, TRUE);	/* add . and .. */	if (strcmp(vdl->path, "/") != 0)		{		fd = g_new0(FileData, 1);		fd->path = remove_level_from_path(vdl->path);		fd->name = "..";		vdl->list = g_list_prepend(vdl->list, fd);		}	fd = g_new0(FileData, 1);	fd->path = g_strdup(vdl->path);	fd->name = ".";	vdl->list = g_list_prepend(vdl->list, fd);	vdlist_populate(vdl);	if (old_path)		{		/* scroll to make last path visible */		FileData *found = NULL;		GList *work;		work = vdl->list;		while (work && !found)			{			FileData *fd = work->data;			if (strcmp(old_path, fd->name) == 0) found = fd;			work = work->next;			}		if (found) vdlist_scroll_to_row(vdl, found, 0.5);		g_free(old_path);		return ret;		}	if (GTK_WIDGET_REALIZED(vdl->listview))		{		gtk_tree_view_scroll_to_point(GTK_TREE_VIEW(vdl->listview), 0, 0);		}	return ret;}void vdlist_refresh(ViewDirList *vdl){	gchar *path;	path = g_strdup(vdl->path);	vdl->path = NULL;	vdlist_set_path(vdl, path);	g_free(path);}static void vdlist_menu_position_cb(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data){	ViewDirList *vdl = data;	GtkTreeModel *store;	GtkTreeIter iter;	GtkTreePath *tpath;	gint cw, ch;	if (vdlist_find_row(vdl, vdl->click_fd, &iter) < 0) return;	store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdl->listview));	tpath = gtk_tree_model_get_path(store, &iter);	tree_view_get_cell_clamped(GTK_TREE_VIEW(vdl->listview), tpath, 0, TRUE, x, y, &cw, &ch);	gtk_tree_path_free(tpath);	*y += ch;	popup_menu_position_clamp(menu, x, y, 0);}static gint vdlist_press_key_cb(GtkWidget *widget, GdkEventKey *event, gpointer data){	ViewDirList *vdl = data;	GtkTreePath *tpath;		if (event->keyval != GDK_Menu) return FALSE;	gtk_tree_view_get_cursor(GTK_TREE_VIEW(vdl->listview), &tpath, NULL);	if (tpath)		{		GtkTreeModel *store;		GtkTreeIter iter;		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, &vdl->click_fd, -1);				gtk_tree_path_free(tpath);		}	else		{		vdl->click_fd = NULL;		}	vdlist_color_set(vdl, vdl->click_fd, TRUE);	vdl->popup = vdlist_pop_menu(vdl, vdl->click_fd);	gtk_menu_popup(GTK_MENU(vdl->popup), NULL, NULL, vdlist_menu_position_cb, vdl, 0, GDK_CURRENT_TIME);	return TRUE;}static gint vdlist_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data){	ViewDirList *vdl = data;	GtkTreePath *tpath;	GtkTreeIter iter;	FileData *fd = NULL;	if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y,					  &tpath, NULL, NULL, NULL))		{		GtkTreeModel *store;		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, &fd, -1);		gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), tpath, NULL, FALSE);		gtk_tree_path_free(tpath);		}	vdl->click_fd = fd;	vdlist_color_set(vdl, vdl->click_fd, TRUE);	if (bevent->button == 3)		{		vdl->popup = vdlist_pop_menu(vdl, vdl->click_fd);		gtk_menu_popup(GTK_MENU(vdl->popup), NULL, NULL, NULL, NULL,			       bevent->button, bevent->time);		}	return TRUE;}static gint vdlist_release_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data){	ViewDirList *vdl = data;	GtkTreePath *tpath;	GtkTreeIter iter;	FileData *fd = NULL;	vdlist_color_set(vdl, vdl->click_fd, FALSE);	if (bevent->button != 1) return TRUE;	if ((bevent->x != 0 || bevent->y != 0) &&	    gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y,					  &tpath, NULL, NULL, NULL))		{		GtkTreeModel *store;		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, &fd, -1);		gtk_tree_path_free(tpath);		}	if (fd && vdl->click_fd == fd)		{		vdlist_select_row(vdl, vdl->click_fd);		}	return TRUE;}static void vdlist_select_cb(GtkTreeView *tview, GtkTreePath *tpath, GtkTreeViewColumn *column, gpointer data){	ViewDirList *vdl = data;	GtkTreeModel *store;	GtkTreeIter iter;	FileData *fd;	store = gtk_tree_view_get_model(tview);	gtk_tree_model_get_iter(store, &iter, tpath);	gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &fd, -1);	vdlist_select_row(vdl, fd);}static GdkColor *vdlist_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 vdlist_color_cb(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,			    GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data){	ViewDirList *vdl = data;	gboolean set;	gtk_tree_model_get(tree_model, iter, DIR_COLUMN_COLOR, &set, -1);	g_object_set(G_OBJECT(cell),		     "cell-background-gdk", vdlist_color_shifted(vdl->listview),		     "cell-background-set", set, NULL);}static void vdlist_destroy_cb(GtkWidget *widget, gpointer data){	ViewDirList *vdl = data;	if (vdl->popup)		{		g_signal_handlers_disconnect_matched(G_OBJECT(vdl->popup), G_SIGNAL_MATCH_DATA,						     0, 0, 0, NULL, vdl);		gtk_widget_destroy(vdl->popup);		}	vdlist_dnd_drop_scroll_cancel(vdl);	widget_auto_scroll_stop(vdl->listview);	path_list_free(vdl->drop_list);	folder_icons_free(vdl->pf);	g_free(vdl->path);	filelist_free(vdl->list);	g_free(vdl);}ViewDirList *vdlist_new(const gchar *path){	ViewDirList *vdl;	GtkListStore *store;	GtkTreeSelection *selection;	GtkTreeViewColumn *column;	GtkCellRenderer *renderer;	vdl = g_new0(ViewDirList, 1);	vdl->path = NULL;	vdl->list = NULL;	vdl->click_fd = NULL;	vdl->drop_fd = NULL;	vdl->drop_list = NULL;	vdl->drop_scroll_id = -1;	vdl->popup = NULL;	vdl->widget = gtk_scrolled_window_new(NULL, NULL);	gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(vdl->widget), GTK_SHADOW_IN);	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(vdl->widget),				       GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);	g_signal_connect(G_OBJECT(vdl->widget), "destroy",			 G_CALLBACK(vdlist_destroy_cb), vdl);	store = gtk_list_store_new(4, G_TYPE_POINTER, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_BOOLEAN);	vdl->listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));	g_object_unref(store);	gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(vdl->listview), FALSE);	gtk_tree_view_set_enable_search(GTK_TREE_VIEW(vdl->listview), FALSE);	g_signal_connect(G_OBJECT(vdl->listview), "row_activated",			 G_CALLBACK(vdlist_select_cb), vdl);	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vdl->listview));	gtk_tree_selection_set_mode(selection, GTK_SELECTION_NONE);	column = gtk_tree_view_column_new();	gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);	renderer = gtk_cell_renderer_pixbuf_new();	gtk_tree_view_column_pack_start(column, renderer, FALSE);	gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", DIR_COLUMN_ICON);	gtk_tree_view_column_set_cell_data_func(column, renderer, vdlist_color_cb, vdl, NULL);	renderer = gtk_cell_renderer_text_new();	gtk_tree_view_column_pack_start(column, renderer, TRUE);	gtk_tree_view_column_add_attribute(column, renderer, "text", DIR_COLUMN_NAME);	gtk_tree_view_column_set_cell_data_func(column, renderer, vdlist_color_cb, vdl, NULL);	gtk_tree_view_append_column(GTK_TREE_VIEW(vdl->listview), column);	g_signal_connect(G_OBJECT(vdl->listview), "key_press_event",			   G_CALLBACK(vdlist_press_key_cb), vdl);	gtk_container_add(GTK_CONTAINER(vdl->widget), vdl->listview);	gtk_widget_show(vdl->listview);	vdl->pf = folder_icons_new();	vdlist_dnd_init(vdl);	g_signal_connect(G_OBJECT(vdl->listview), "button_press_event",			 G_CALLBACK(vdlist_press_cb), vdl);	g_signal_connect(G_OBJECT(vdl->listview), "button_release_event",			 G_CALLBACK(vdlist_release_cb), vdl);	if (path) vdlist_set_path(vdl, path);	return vdl;}void vdlist_set_select_func(ViewDirList *vdl,			    void (*func)(ViewDirList *vdl, const gchar *path, gpointer data), gpointer data){	vdl->select_func = func;	vdl->select_data = data;}void vdlist_set_layout(ViewDirList *vdl, LayoutWindow *layout){	vdl->layout = layout;}

⌨️ 快捷键说明

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