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

📄 pan-view.c

📁 Gqview,Linux下基于GTK+库写成的轻量级而能丰富的图像浏览程序。
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * GQview * (C) 2005 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 "pan-view.h"#include "cache.h"#include "cache-loader.h"#include "dnd.h"#include "editors.h"#include "filelist.h"#include "fullscreen.h"#include "image.h"#include "image-load.h"#include "img-view.h"#include "info.h"#include "menu.h"#include "pixbuf-renderer.h"#include "pixbuf_util.h"#include "thumb.h"#include "utilops.h"#include "ui_bookmark.h"#include "ui_fileops.h"#include "ui_menu.h"#include "ui_misc.h"#include "ui_tabcomp.h"#include <gdk/gdkkeysyms.h> /* for keyboard values */#include <math.h>#define PAN_WINDOW_DEFAULT_WIDTH 720#define PAN_WINDOW_DEFAULT_HEIGHT 500#define PAN_TILE_SIZE 512#define PAN_THUMB_SIZE_DOTS 4#define PAN_THUMB_SIZE_NONE 24#define PAN_THUMB_SIZE_SMALL 64#define PAN_THUMB_SIZE_NORMAL 128#define PAN_THUMB_SIZE_LARGE 256#define PAN_THUMB_SIZE pw->thumb_size#define PAN_THUMB_GAP_DOTS 2#define PAN_THUMB_GAP_SMALL 14#define PAN_THUMB_GAP_NORMAL 30#define PAN_THUMB_GAP_LARGE 40#define PAN_THUMB_GAP_HUGE 50#define PAN_THUMB_GAP pw->thumb_gap#define PAN_SHADOW_OFFSET 6#define PAN_SHADOW_FADE 5#define PAN_SHADOW_COLOR 0, 0, 0#define PAN_SHADOW_ALPHA 64#define PAN_OUTLINE_THICKNESS 1#define PAN_OUTLINE_COLOR_1 255, 255, 255#define PAN_OUTLINE_COLOR_2 64, 64, 64#define PAN_OUTLINE_ALPHA 180#define PAN_BACKGROUND_COLOR 150, 150, 150#define PAN_GRID_SIZE 60#define PAN_GRID_COLOR 0, 0, 0#define PAN_GRID_ALPHA 20#define PAN_FOLDER_BOX_COLOR 255, 255, 255#define PAN_FOLDER_BOX_ALPHA 100#define PAN_FOLDER_BOX_BORDER 20#define PAN_FOLDER_BOX_OUTLINE_THICKNESS 4#define PAN_FOLDER_BOX_OUTLINE_COLOR 0, 0, 0#define PAN_FOLDER_BOX_OUTLINE_ALPHA 128#define PAN_TEXT_BORDER_SIZE 4#define PAN_TEXT_COLOR 0, 0, 0#define PAN_POPUP_COLOR 255, 255, 225#define PAN_POPUP_ALPHA 255#define PAN_POPUP_BORDER 1#define PAN_POPUP_BORDER_COLOR 0, 0, 0#define PAN_POPUP_TEXT_COLOR 0, 0, 0#define PAN_CAL_POPUP_COLOR 220, 220, 220#define PAN_CAL_POPUP_ALPHA 255#define PAN_CAL_POPUP_BORDER 1#define PAN_CAL_POPUP_BORDER_COLOR 0, 0, 0#define PAN_CAL_POPUP_TEXT_COLOR 0, 0, 0#define PAN_CAL_DAY_WIDTH 100#define PAN_CAL_DAY_HEIGHT 80#define PAN_CAL_DAY_COLOR 255, 255, 255#define PAN_CAL_DAY_ALPHA 220#define PAN_CAL_DAY_BORDER 2#define PAN_CAL_DAY_BORDER_COLOR 0, 0, 0#define PAN_CAL_DAY_TEXT_COLOR 0, 0, 0#define PAN_CAL_MONTH_COLOR 255, 255, 255#define PAN_CAL_MONTH_ALPHA 200#define PAN_CAL_MONTH_BORDER 4#define PAN_CAL_MONTH_BORDER_COLOR 0, 0, 0#define PAN_CAL_MONTH_TEXT_COLOR 0, 0, 0#define PAN_CAL_DOT_SIZE 3#define PAN_CAL_DOT_GAP 2#define PAN_CAL_DOT_COLOR 128, 128, 128#define PAN_CAL_DOT_ALPHA 128#define PAN_GROUP_MAX 16#define ZOOM_INCREMENT 1.0#define ZOOM_LABEL_WIDTH 64#define PAN_PREF_GROUP "pan_view_options"#define PAN_PREF_HIDE_WARNING "hide_performance_warning"#define PAN_PREF_EXIF_DATE "use_exif_date"typedef enum {	LAYOUT_TIMELINE = 0,	LAYOUT_CALENDAR,	LAYOUT_FOLDERS_LINEAR,	LAYOUT_FOLDERS_FLOWER,	LAYOUT_GRID,} LayoutType;typedef enum {	LAYOUT_SIZE_THUMB_DOTS = 0,	LAYOUT_SIZE_THUMB_NONE,	LAYOUT_SIZE_THUMB_SMALL,	LAYOUT_SIZE_THUMB_NORMAL,	LAYOUT_SIZE_THUMB_LARGE,	LAYOUT_SIZE_10,	LAYOUT_SIZE_25,	LAYOUT_SIZE_33,	LAYOUT_SIZE_50,	LAYOUT_SIZE_100} LayoutSize;typedef enum {	ITEM_NONE,	ITEM_THUMB,	ITEM_BOX,	ITEM_TRIANGLE,	ITEM_TEXT,	ITEM_IMAGE} ItemType;typedef enum {	TEXT_ATTR_NONE = 0,	TEXT_ATTR_BOLD = 1 << 0,	TEXT_ATTR_HEADING = 1 << 1,	TEXT_ATTR_MARKUP = 1 << 2} TextAttrType;enum {	BORDER_NONE = 0,	BORDER_1 = 1 << 0,	BORDER_2 = 1 << 1,	BORDER_3 = 1 << 2,	BORDER_4 = 1 << 3};typedef struct _PanItem PanItem;struct _PanItem {	ItemType type;	gint x;	gint y;	gint width;	gint height;	gchar *key;	FileData *fd;	GdkPixbuf *pixbuf;	gint refcount;	gchar *text;	TextAttrType text_attr;	guint8 color_r;	guint8 color_g;	guint8 color_b;	guint8 color_a;	guint8 color2_r;	guint8 color2_g;	guint8 color2_b;	guint8 color2_a;	gint border;	gpointer data;	gint queued;};typedef struct _PanWindow PanWindow;struct _PanWindow{	GtkWidget *window;	ImageWindow *imd;	ImageWindow *imd_normal;	FullScreenData *fs;	GtkWidget *path_entry;	GtkWidget *label_message;	GtkWidget *label_zoom;	GtkWidget *search_box;	GtkWidget *search_entry;	GtkWidget *search_label;	GtkWidget *search_button;	GtkWidget *search_button_arrow;	GtkWidget *date_button;	GtkWidget *scrollbar_h;	GtkWidget *scrollbar_v;	gint overlay_id;	gchar *path;	LayoutType layout;	LayoutSize size;	gint thumb_size;	gint thumb_gap;	gint image_size;	gint exif_date_enable;	gint ignore_symlinks;	GList *list;	GList *list_static;	GList *list_grid;	GList *cache_list;	GList *cache_todo;	gint cache_count;	gint cache_total;	gint cache_tick;	CacheLoader *cache_cl;	ImageLoader *il;	ThumbLoader *tl;	PanItem *queue_pi;	GList *queue;	PanItem *click_pi;	PanItem *search_pi;	gint idle_id;};typedef struct _PanGrid PanGrid;struct _PanGrid {	gint x;	gint y;	gint w;	gint h;	GList *list;};typedef struct _PanCacheData PanCacheData;struct _PanCacheData {	FileData fd;	CacheData *cd;};static GList *pan_window_list = NULL;static GList *pan_window_layout_list(const gchar *path, SortType sort, gint ascend,				     gint ignore_symlinks);static GList *pan_layout_intersect(PanWindow *pw, gint x, gint y, gint width, gint height);static void pan_window_layout_update_idle(PanWindow *pw);static GtkWidget *pan_popup_menu(PanWindow *pw);static void pan_fullscreen_toggle(PanWindow *pw, gint force_off);static void pan_window_close(PanWindow *pw);static void pan_window_dnd_init(PanWindow *pw);typedef enum {	DATE_LENGTH_EXACT,	DATE_LENGTH_HOUR,	DATE_LENGTH_DAY,	DATE_LENGTH_WEEK,	DATE_LENGTH_MONTH,	DATE_LENGTH_YEAR} DateLengthType;static gint date_compare(time_t a, time_t b, DateLengthType length){	struct tm ta;	struct tm tb;	if (length == DATE_LENGTH_EXACT) return (a == b);	if (!localtime_r(&a, &ta) ||	    !localtime_r(&b, &tb)) return FALSE;	if (ta.tm_year != tb.tm_year) return FALSE;	if (length == DATE_LENGTH_YEAR) return TRUE;	if (ta.tm_mon != tb.tm_mon) return FALSE;	if (length == DATE_LENGTH_MONTH) return TRUE;	if (length == DATE_LENGTH_WEEK) return (ta.tm_yday / 7 == tb.tm_yday / 7);	if (ta.tm_mday != tb.tm_mday) return FALSE;	if (length == DATE_LENGTH_DAY) return TRUE;	return (ta.tm_hour == tb.tm_hour);}static gint date_value(time_t d, DateLengthType length){	struct tm td;	if (!localtime_r(&d, &td)) return -1;	switch (length)		{		case DATE_LENGTH_DAY:			return td.tm_mday;			break;		case DATE_LENGTH_WEEK:			return td.tm_wday;			break;		case DATE_LENGTH_MONTH:			return td.tm_mon + 1;			break;		case DATE_LENGTH_YEAR:			return td.tm_year + 1900;			break;		case DATE_LENGTH_EXACT:		default:			break;		}	return -1;}static gchar *date_value_string(time_t d, DateLengthType length){	struct tm td;	gchar buf[128];	gchar *format = NULL;	if (!localtime_r(&d, &td)) return g_strdup("");	switch (length)		{		case DATE_LENGTH_DAY:			return g_strdup_printf("%d", td.tm_mday);			break;		case DATE_LENGTH_WEEK:			format = "%A %e";			break;		case DATE_LENGTH_MONTH:			format = "%B %Y";			break;		case DATE_LENGTH_YEAR:			return g_strdup_printf("%d", td.tm_year + 1900);			break;		case DATE_LENGTH_EXACT:		default:			return g_strdup(text_from_time(d));			break;		}	if (format && strftime(buf, sizeof(buf), format, &td) > 0)		{		gchar *ret = g_locale_to_utf8(buf, -1, NULL, NULL, NULL);		if (ret) return ret;		}	return g_strdup("");}static time_t date_to_time(gint year, gint month, gint day){	struct tm lt;	lt.tm_sec = 0;	lt.tm_min = 0;	lt.tm_hour = 0;	lt.tm_mday = (day >= 1 && day <= 31) ? day : 1;	lt.tm_mon = (month >= 1 && month <= 12) ? month - 1 : 0;	lt.tm_year = year - 1900;	lt.tm_isdst = 0;	return mktime(&lt);}/* *----------------------------------------------------------------------------- * cache *----------------------------------------------------------------------------- */static void pan_cache_free(PanWindow *pw){	GList *work;	work = pw->cache_list;	while (work)		{		PanCacheData *pc;		pc = work->data;		work = work->next;		cache_sim_data_free(pc->cd);		file_data_free((FileData *)pc);		}	g_list_free(pw->cache_list);	pw->cache_list = NULL;	filelist_free(pw->cache_todo);	pw->cache_todo = NULL;	pw->cache_count = 0;	pw->cache_total = 0;	pw->cache_tick = 0;	cache_loader_free(pw->cache_cl);	pw->cache_cl = NULL;}static void pan_cache_fill(PanWindow *pw, const gchar *path){	GList *list;	pan_cache_free(pw);	list = pan_window_layout_list(path, SORT_NAME, TRUE, pw->ignore_symlinks);	pw->cache_todo = g_list_reverse(list);	pw->cache_total = g_list_length(pw->cache_todo);}static void pan_cache_step_done_cb(CacheLoader *cl, gint error, gpointer data){	PanWindow *pw = data;	if (pw->cache_list)		{		PanCacheData *pc;		pc = pw->cache_list->data;		if (!pc->cd)			{			pc->cd = cl->cd;			cl->cd = NULL;			}		}	cache_loader_free(cl);	pw->cache_cl = NULL;	pan_window_layout_update_idle(pw);}static gint pan_cache_step(PanWindow *pw){	FileData *fd;	PanCacheData *pc;	CacheDataType load_mask;	if (!pw->cache_todo) return TRUE;	fd = pw->cache_todo->data;	pw->cache_todo = g_list_remove(pw->cache_todo, fd);#if 0	if (enable_thumb_caching)		{		gchar *found;		found = cache_find_location(CACHE_TYPE_SIM, fd->path);		if (found && filetime(found) == fd->date)			{			cd = cache_sim_data_load(found);			}		g_free(found);		}	if (!cd) cd = cache_sim_data_new();	if (!cd->dimensions)		{		cd->dimensions = image_load_dimensions(fd->path, &cd->width, &cd->height);		if (enable_thumb_caching &&		    cd->dimensions)			{			gchar *base;			mode_t mode = 0755;			base = cache_get_location(CACHE_TYPE_SIM, fd->path, FALSE, &mode);			if (cache_ensure_dir_exists(base, mode))				{				g_free(cd->path);				cd->path = cache_get_location(CACHE_TYPE_SIM, fd->path, TRUE, NULL);				if (cache_sim_data_save(cd))					{					filetime_set(cd->path, filetime(fd->path));					}				}			g_free(base);			}		pw->cache_tick = 9;		}#endif	pc = g_new0(PanCacheData, 1);	memcpy(pc, fd, sizeof(FileData));	g_free(fd);	pc->cd = NULL;	pw->cache_list = g_list_prepend(pw->cache_list, pc);	cache_loader_free(pw->cache_cl);	load_mask = CACHE_LOADER_NONE;	if (pw->size > LAYOUT_SIZE_THUMB_LARGE) load_mask |= CACHE_LOADER_DIMENSIONS;	if (pw->exif_date_enable) load_mask |= CACHE_LOADER_DATE;	pw->cache_cl = cache_loader_new(((FileData *)pc)->path, load_mask,					pan_cache_step_done_cb, pw);	return (pw->cache_cl == NULL);}/* This sync date function is optimized for lists with a common sort */static void pan_cache_sync_date(PanWindow *pw, GList *list){	GList *haystack;	GList *work;	haystack = g_list_copy(pw->cache_list);	work = list;	while (work)		{		FileData *fd;		GList *needle;		fd = work->data;		work = work->next;		needle = haystack;		while (needle)			{			PanCacheData *pc;			gchar *path;			pc = needle->data;			path = ((FileData *)pc)->path;			if (path && strcmp(path, fd->path) == 0)				{				if (pc->cd && pc->cd->have_date && pc->cd->date >= 0)					{					fd->date = pc->cd->date;					}				haystack = g_list_delete_link(haystack, needle);				needle = NULL;				}			else				{				needle = needle->next;				}			}		}	g_list_free(haystack);}/* *----------------------------------------------------------------------------- * item grid *----------------------------------------------------------------------------- */

⌨️ 快捷键说明

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