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

📄 cache_maint.c

📁 Gqview,Linux下基于GTK+库写成的轻量级而能丰富的图像浏览程序。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 "cache_maint.h"#include "cache.h"#include "filelist.h"#include "thumb.h"#include "thumb_standard.h"#include "ui_fileops.h"#include "ui_misc.h"#include "ui_spinner.h"#include "ui_tabcomp.h"#include "ui_utildlg.h"typedef struct _CMData CMData;struct _CMData{	GList *list;	GList *done_list;	gint idle_id;	GenericDialog *gd;	GtkWidget *entry;	GtkWidget *spinner;	GtkWidget *button_stop;	GtkWidget *button_close;	gint clear;	gint metadata;};#define PURGE_DIALOG_WIDTH 400/* *------------------------------------------------------------------- * cache maintenance *------------------------------------------------------------------- */static gint extension_truncate(gchar *path, const gchar *ext){	gint l;	gint el;	if (!path || !ext) return FALSE;	l = strlen(path);	el = strlen(ext);	if (l < el || strcmp(path + (l - el), ext) != 0) return FALSE;	path[l - el] = '\0';	return TRUE;}static gchar *extension_find_dot(gchar *path){	gchar *ptr;	if (!path || *path == '\0') return NULL;	ptr = path;	while (*ptr != '\0') ptr++;	while (ptr > path && *ptr != '.') ptr--;	if (ptr == path) return NULL;	return ptr;}static gint isempty(const gchar *path){	DIR *dp;	struct dirent *dir;	gchar *pathl;	pathl = path_from_utf8(path);	dp = opendir(pathl);	g_free(pathl);	if (!dp) return FALSE;	while ((dir = readdir(dp)) != NULL)		{		gchar *name = dir->d_name;		if (dir->d_ino > 0 &&		    !(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) )			{			closedir(dp);			return FALSE;			}		}	closedir(dp);	return TRUE;}static void cache_maintain_home_close(CMData *cm){	if (cm->idle_id != -1) g_source_remove(cm->idle_id);	if (cm->gd) generic_dialog_close(cm->gd);	path_list_free(cm->list);	g_list_free(cm->done_list);	g_free(cm);}static void cache_maintain_home_stop(CMData *cm){	if (cm->idle_id != -1)		{		g_source_remove(cm->idle_id);		cm->idle_id = -1;		}	gtk_entry_set_text(GTK_ENTRY(cm->entry), _("done"));	spinner_set_interval(cm->spinner, -1);	gtk_widget_set_sensitive(cm->button_stop, FALSE);	gtk_widget_set_sensitive(cm->button_close, TRUE);}static gint cache_maintain_home_cb(gpointer data){	CMData *cm = data;	GList *dlist = NULL;	GList *list = NULL;	gchar *path;	gint just_done = FALSE;	gint still_have_a_file = TRUE;	gint base_length;	const gchar *cache_folder;	if (cm->metadata)		{		cache_folder = GQVIEW_CACHE_RC_METADATA;		}	else		{		cache_folder = GQVIEW_CACHE_RC_THUMB;		}	base_length = strlen(homedir()) + strlen("/") + strlen(cache_folder);	if (!cm->list)		{		if (debug) printf("purge chk done.\n");		cm->idle_id = -1;		cache_maintain_home_stop(cm);		return FALSE;		}	path = cm->list->data;	if (debug) printf("purge chk (%d) \"%s\"\n", (cm->clear && !cm->metadata), path);	if (g_list_find(cm->done_list, path) == NULL)		{		cm->done_list = g_list_prepend(cm->done_list, path);		if (path_list(path, &list, &dlist))			{			GList *work;			just_done = TRUE;			still_have_a_file = FALSE;				work = list;			while (work)				{				gchar *path_buf = work->data;				gchar *dot;					dot = extension_find_dot(path_buf);					if (dot) *dot = '\0';				if ((!cm->metadata && cm->clear) ||				    (strlen(path_buf) > base_length && !isfile(path_buf + base_length)) )					{					if (dot) *dot = '.';					if (!unlink_file(path_buf)) printf("failed to delete:%s\n", path_buf);					}				else					{					still_have_a_file = TRUE;					}				work = work->next;				}			}		}	path_list_free(list);	cm->list = g_list_concat(dlist, cm->list);	if (cm->list && g_list_find(cm->done_list, cm->list->data) != NULL)		{		/* check if the dir is empty */				if (cm->list->data == path && just_done)			{			if (!still_have_a_file && !dlist && cm->list->next && !rmdir_utf8(path))				{				printf("Unable to delete dir: %s\n", path);				}			}		else			{			/* must re-check for an empty dir */			if (isempty(path) && cm->list->next && !rmdir_utf8(path))				{				printf("Unable to delete dir: %s\n", path);				}			}		path = cm->list->data;		cm->done_list = g_list_remove(cm->done_list, path);		cm->list = g_list_remove(cm->list, path);		g_free(path);		}	if (cm->list)		{		const gchar *buf;		path = cm->list->data;		if (strlen(path) > base_length)			{			buf = path + base_length;			}		else			{			buf = "...";			}		gtk_entry_set_text(GTK_ENTRY(cm->entry), buf);		}	return TRUE;}static void cache_maintain_home_close_cb(GenericDialog *gd, gpointer data){	CMData *cm = data;	if (!GTK_WIDGET_SENSITIVE(cm->button_close)) return;	cache_maintain_home_close(cm);}static void cache_maintain_home_stop_cb(GenericDialog *gd, gpointer data){	CMData *cm = data;	cache_maintain_home_stop(cm);}/* sorry for complexity (cm->done_list), but need it to remove empty dirs */void cache_maintain_home(gint metadata, gint clear, GtkWidget *parent){	CMData *cm;	GList *dlist = NULL;	gchar *base;	const gchar *msg;	const gchar *cache_folder;	GtkWidget *hbox;	if (metadata)		{		cache_folder = GQVIEW_CACHE_RC_METADATA;		}	else		{		cache_folder = GQVIEW_CACHE_RC_THUMB;		}	base = g_strconcat(homedir(), "/", cache_folder, NULL);	if (!path_list(base, NULL, &dlist))		{		g_free(base);		return;		}	dlist = g_list_append(dlist, base);	cm = g_new0(CMData, 1);	cm->list = dlist;	cm->done_list = NULL;	cm->clear = clear;	cm->metadata = metadata;	if (metadata)		{		msg = _("Removing old metadata...");		}	else if (clear)		{		msg = _("Clearing cached thumbnails...");		}	else		{		msg = _("Removing old thumbnails...");		}	cm->gd = generic_dialog_new(_("Maintenance"),				    "GQview", "gqview_maintenance",				    parent, FALSE,				    NULL, cm);	cm->gd->cancel_cb = cache_maintain_home_close_cb;	cm->button_close = generic_dialog_add_button(cm->gd, GTK_STOCK_CLOSE, NULL,						     cache_maintain_home_close_cb, FALSE);	gtk_widget_set_sensitive(cm->button_close, FALSE);	cm->button_stop = generic_dialog_add_button(cm->gd, GTK_STOCK_STOP, NULL,						    cache_maintain_home_stop_cb, FALSE);	generic_dialog_add_message(cm->gd, NULL, msg, NULL);	gtk_window_set_default_size(GTK_WINDOW(cm->gd->dialog), PURGE_DIALOG_WIDTH, -1);	hbox = gtk_hbox_new(FALSE, 0);	gtk_box_pack_start(GTK_BOX(cm->gd->vbox), hbox, FALSE, FALSE, 5);	gtk_widget_show(hbox);	cm->entry = gtk_entry_new();	GTK_WIDGET_UNSET_FLAGS(cm->entry, GTK_CAN_FOCUS);	gtk_editable_set_editable(GTK_EDITABLE(cm->entry), FALSE);	gtk_box_pack_start(GTK_BOX(hbox), cm->entry, TRUE, TRUE, 0);	gtk_widget_show(cm->entry);	cm->spinner = spinner_new(NULL, SPINNER_SPEED);	gtk_box_pack_start(GTK_BOX(hbox), cm->spinner, FALSE, FALSE, 0);	gtk_widget_show(cm->spinner);		gtk_widget_show(cm->gd->dialog);	cm->idle_id = g_idle_add(cache_maintain_home_cb, cm);}/* This checks all files in ~/.gqview/thumbnails and * removes them if thay have no source counterpart. * (this assumes all cache files have an extension of 4 chars including '.') */gint cache_maintain_home_dir(const gchar *dir, gint recursive, gint clear){	gchar *base;	gint base_length;	GList *dlist = NULL;	GList *flist = NULL;	gint still_have_a_file = FALSE;	if (debug) printf("maintainance check: %s\n", dir);	base_length = strlen(homedir()) + strlen("/") + strlen(GQVIEW_CACHE_RC_THUMB);	base = g_strconcat(homedir(), "/", GQVIEW_CACHE_RC_THUMB, dir, NULL);	if (path_list(base, &flist, &dlist))		{		GList *work;		work = dlist;		while(work)			{			gchar *path = work->data;			if (recursive && strlen(path) > base_length &&			    !cache_maintain_home_dir(path + base_length, recursive, clear))				{				if (debug) printf("Deleting thumb dir: %s\n", path);				if (!rmdir_utf8(path))					{					printf("Unable to delete dir: %s\n", path);					}				}			else				{				still_have_a_file = TRUE;				}			work = work->next;			}		work = flist;		while (work)			{			gchar *path = work->data;			gchar *dot;			dot = extension_find_dot(path);			if (dot) *dot = '\0';			if (clear ||			    (strlen(path) > base_length && !isfile(path + base_length)) )				{				if (dot) *dot = '.';				if (!unlink_file(path)) printf("failed to delete:%s\n", path);				}			else				{				still_have_a_file = TRUE;				}			work = work->next;			}		}	path_list_free(dlist);	path_list_free(flist);	g_free(base);	return still_have_a_file;}/* This checks relative caches in dir/.thumbnails and * removes them if they have no source counterpart. */gint cache_maintain_dir(const gchar *dir, gint recursive, gint clear){	GList *list = NULL;	gchar *cachedir;	gint still_have_a_file = FALSE;	GList *work;	cachedir = g_strconcat(dir, "/", GQVIEW_CACHE_LOCAL_THUMB, NULL);	path_list(cachedir, &list, NULL);	work = list;	while (work)		{		const gchar *path;		gchar *source;		path = work->data;		work = work->next;		source = g_strconcat(dir, "/", filename_from_path(path), NULL);		if (clear ||		    extension_truncate(source, GQVIEW_CACHE_EXT_THUMB) ||		    extension_truncate(source, GQVIEW_CACHE_EXT_SIM))			{			if (!clear && isfile(source))				{				still_have_a_file = TRUE;				}			else				{				if (!unlink_file(path))					{					if (debug) printf("Failed to remove cache file %s\n", path);					still_have_a_file = TRUE;					}				}			}		else			{			still_have_a_file = TRUE;			}		g_free(source);		}	path_list_free(list);	g_free(cachedir);	if (recursive)		{		list = NULL;		path_list(dir, NULL, &list);		work = list;		while (work)			{			const gchar *path = work->data;			work = work->next;			still_have_a_file |= cache_maintain_dir(path, recursive, clear);			}		path_list_free(list);		}	return still_have_a_file;}static void cache_file_move(const gchar *src, const gchar *dest){	if (!dest || !src || !isfile(src)) return;	if (!move_file(src, dest))		{		if (debug) printf("Failed to move cache file %s\nto %s\n", src, dest);		/* we remove it anyway - it's stale */		unlink_file(src);		}}void cache_maint_moved(const gchar *src, const gchar *dest){	gchar *base;	mode_t mode = 0755;	if (!src || !dest) return;	base = cache_get_location(CACHE_TYPE_THUMB, dest, FALSE, &mode);	if (cache_ensure_dir_exists(base, mode))		{		gchar *buf;		gchar *d;		buf = cache_find_location(CACHE_TYPE_THUMB, src);		d = cache_get_location(CACHE_TYPE_THUMB, dest, TRUE, NULL);		cache_file_move(buf, d);		g_free(d);		g_free(buf);		buf = cache_find_location(CACHE_TYPE_SIM, src);		d = cache_get_location(CACHE_TYPE_SIM, dest, TRUE, NULL);		cache_file_move(buf, d);		g_free(d);		g_free(buf);		}	else		{		printf("Failed to create cache dir for move %s\n", base);		}	g_free(base);	base = cache_get_location(CACHE_TYPE_METADATA, dest, FALSE, &mode);	if (cache_ensure_dir_exists(base, mode))		{		gchar *buf;		gchar *d;                                                                                                                    		buf = cache_find_location(CACHE_TYPE_METADATA, src);		d = cache_get_location(CACHE_TYPE_METADATA, dest, TRUE, NULL);		cache_file_move(buf, d);		g_free(d);		g_free(buf);		}	g_free(base);	if (enable_thumb_caching && thumbnail_spec_standard) thumb_std_maint_moved(src, dest);}static void cache_file_remove(const gchar *path){	if (path && isfile(path) && !unlink_file(path))		{		if (debug) printf("Failed to remove cache file %s\n", path);		}}void cache_maint_removed(const gchar *source){	gchar *buf;	buf = cache_find_location(CACHE_TYPE_THUMB, source);	cache_file_remove(buf);	g_free(buf);	buf = cache_find_location(CACHE_TYPE_SIM, source);	cache_file_remove(buf);	g_free(buf);	buf = cache_find_location(CACHE_TYPE_METADATA, source);	cache_file_remove(buf);	g_free(buf);	if (enable_thumb_caching && thumbnail_spec_standard) thumb_std_maint_removed(source);}void cache_maint_copied(const gchar *src, const gchar *dest){	gchar *dest_base;	gchar *src_cache;	mode_t mode = 0755;	src_cache = cache_find_location(CACHE_TYPE_METADATA, src);	if (!src_cache) return;	dest_base = cache_get_location(CACHE_TYPE_METADATA, dest, FALSE, &mode);	if (cache_ensure_dir_exists(dest_base, mode))		{		gchar *path;                                                                                                                    		path = cache_get_location(CACHE_TYPE_METADATA, dest, TRUE, NULL);		if (!copy_file(src_cache, path))			{			if (debug) printf("failed to copy metadata %s to %s\n", src_cache, path);			}		g_free(path);		}	g_free(dest_base);	g_free(src_cache);}/* *------------------------------------------------------------------- * new cache maintenance utilities *------------------------------------------------------------------- */typedef struct _CacheManager CacheManager;struct _CacheManager{	GenericDialog *dialog;	GtkWidget *folder_entry;	GtkWidget *progress;	GList *list_todo;	gint count_total;	gint count_done;

⌨️ 快捷键说明

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