Example #1
0
static void cache_manager_standard_clean_start_cb(GenericDialog *gd, gpointer data)
{
	CleanData *cd = data;
	GList *list;
	gchar *path;
	FileData *dir_fd;

#if GTK_CHECK_VERSION(2,20,0)
	if (cd->list || !gtk_widget_get_sensitive(cd->button_start)) return;
#else
	if (cd->list || !GTK_WIDGET_SENSITIVE(cd->button_start)) return;
#endif

	gtk_widget_set_sensitive(cd->button_start, FALSE);
	gtk_widget_set_sensitive(cd->button_stop, TRUE);
	gtk_widget_set_sensitive(cd->button_close, FALSE);

	gtk_progress_bar_set_text(GTK_PROGRESS_BAR(cd->progress), _("running..."));

	path = g_build_filename(homedir(), THUMB_FOLDER_GLOBAL, THUMB_FOLDER_NORMAL, NULL);
	dir_fd = file_data_new_simple(path);
	filelist_read(dir_fd, &list, NULL);
	cd->list = list;
	file_data_unref(dir_fd);
	g_free(path);

	path = g_build_filename(homedir(), THUMB_FOLDER_GLOBAL, THUMB_FOLDER_LARGE, NULL);
	dir_fd = file_data_new_simple(path);
	filelist_read(dir_fd, &list, NULL);
	cd->list = g_list_concat(cd->list, list);
	file_data_unref(dir_fd);
	g_free(path);

	path = g_build_filename(homedir(), THUMB_FOLDER_GLOBAL, THUMB_FOLDER_FAIL, NULL);
	dir_fd = file_data_new_simple(path);
	filelist_read(dir_fd, &list, NULL);
	cd->list = g_list_concat(cd->list, list);
	file_data_unref(dir_fd);
	g_free(path);

	cd->count_total = g_list_length(cd->list);
	cd->count_done = 0;

	/* start iterating */
	if (cd->clear)
		{
		cd->idle_id = g_idle_add(cache_manager_standard_clean_clear_cb, cd);
		}
	else
		{
		cache_manager_standard_clean_valid_cb(NULL, TRUE, cd);
		}
}
Example #2
0
static void vdtree_add_by_data(ViewDir *vd, FileData *fd, GtkTreeIter *parent)
{
	GtkTreeStore *store;
	GtkTreeIter child;
	NodeData *nd;
	GdkPixbuf *pixbuf;
	NodeData *end;
	GtkTreeIter empty;

	if (!fd) return;

	if (access_file(fd->path, R_OK | X_OK))
		{
		pixbuf = vd->pf->close;
		}
	else
		{
		pixbuf = vd->pf->deny;
		}

	nd = g_new0(NodeData, 1);
	nd->fd = fd;
	nd->version = fd->version;
	nd->expanded = FALSE;
	nd->last_update = time(NULL);

	store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)));
	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 = file_data_new_simple("");
	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 (options->tree_descend_subdirs &&
		    gtk_tree_view_row_expanded(GTK_TREE_VIEW(vd->view), tpath) &&
		    !nd->expanded)
			{
			vdtree_populate_path_by_iter(vd, &child, FALSE, vd->dir_fd);
			}
		gtk_tree_path_free(tpath);
		}
}
Example #3
0
static void collect_manager_refresh(void)
{
	GList *list;
	GList *work;
	FileData *dir_fd;

	dir_fd = file_data_new_simple(get_collections_dir());
	filelist_read(dir_fd, &list, NULL);
	file_data_unref(dir_fd);

	work = collection_manager_entry_list;
	while (work && list)
		{
		CollectManagerEntry *entry;
		GList *list_step;

		entry = work->data;
		work = work->next;

		list_step = list;
		while (list_step && entry)
			{
			FileData *fd;

			fd = list_step->data;
			list_step = list_step->next;

			if (strcmp(fd->path, entry->path) == 0)
				{
				list = g_list_remove(list, fd);
				file_data_unref(fd);

				entry = NULL;
				}
			else
				{
				collect_manager_entry_free(entry);
				}
			}
		}

	work = list;
	while (work)
		{
		FileData *fd;

		fd = work->data;
		work = work->next;

		collect_manager_entry_new(fd->path);
		}

	filelist_free(list);
}
Example #4
0
static void vdtree_setup_root(ViewDir *vd)
{
	const gchar *path = G_DIR_SEPARATOR_S;
	FileData *fd;


	fd = file_data_new_simple(path);
	vdtree_add_by_data(vd, fd, NULL);

	vdtree_expand_by_data(vd, fd, TRUE);
	vdtree_populate_path(vd, fd, FALSE, FALSE);
}
Example #5
0
static void vd_rename_finished_cb(gboolean success, const gchar *new_path, gpointer data)
{
	ViewDir *vd = data;
	if (success)
		{
		FileData *fd = file_data_new_simple(new_path);
		GtkTreeIter iter;

		if (vd_find_row(vd, fd, &iter))
			{
			tree_view_row_make_visible(GTK_TREE_VIEW(vd->view), &iter, TRUE);
			}

		file_data_unref(fd);
		}
}
Example #6
0
static void cache_manager_render_start_cb(GenericDialog *fd, gpointer data)
{
	CleanData *cd = data;
	gchar *path;

#if GTK_CHECK_VERSION(2,20,0)
	if (cd->list || !gtk_widget_get_sensitive(cd->button_start)) return;
#else
	if (cd->list || !GTK_WIDGET_SENSITIVE(cd->button_start)) return;
#endif

	path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(cd->entry))));
	parse_out_relatives(path);

	if (!isdir(path))
		{
		warning_dialog(_("Invalid folder"),
				_("The specified folder can not be found."),
			       GTK_STOCK_DIALOG_WARNING, cd->gd->dialog);
		}
	else
		{
		FileData *dir_fd;
		gtk_widget_set_sensitive(cd->group, FALSE);
		gtk_widget_set_sensitive(cd->button_start, FALSE);
		gtk_widget_set_sensitive(cd->button_stop, TRUE);
		gtk_widget_set_sensitive(cd->button_close, FALSE);

		spinner_set_interval(cd->spinner, SPINNER_SPEED);

		dir_fd = file_data_new_simple(path);
		cache_manager_render_folder(cd, dir_fd);
		file_data_unref(dir_fd);
		while (cache_manager_render_file(cd));
		}

	g_free(path);
}
Example #7
0
gboolean metadata_write_perform(FileData *fd)
{
	gboolean success;
	ExifData *exif;
	
	g_assert(fd->change);
	
	if (fd->change->dest && 
	    strcmp(extension_from_path(fd->change->dest), GQ_CACHE_EXT_METADATA) == 0)
		{
		success = metadata_legacy_write(fd);
		if (success) metadata_legacy_delete(fd, fd->change->dest);
		return success;
		}

	/* write via exiv2 */
	/*  we can either use cached metadata which have fd->modified_xmp already applied 
	                             or read metadata from file and apply fd->modified_xmp
	    metadata are read also if the file was modified meanwhile */
	exif = exif_read_fd(fd); 
	if (!exif) return FALSE;

	success = (fd->change->dest) ? exif_write_sidecar(exif, fd->change->dest) : exif_write(exif); /* write modified metadata */
	exif_free_fd(fd, exif);

	if (fd->change->dest)
		/* this will create a FileData for the sidecar and link it to the main file 
		   (we can't wait until the sidecar is discovered by directory scanning because
		    exif_read_fd is called before that and it would read the main file only and 
		    store the metadata in the cache)
		    FIXME: this does not catch new sidecars created by independent external programs
		*/
		file_data_unref(file_data_new_simple(fd->change->dest)); 
		
	if (success) metadata_legacy_delete(fd, fd->change->dest);
	return success;
}
Example #8
0
static gboolean collection_load_private(CollectionData *cd, const gchar *path, CollectionLoadFlags flags)
{
	gchar s_buf[GQ_COLLECTION_READ_BUFSIZE];
	FILE *f;
	gchar *pathl;
	gboolean limit_failures = TRUE;
	gboolean success = TRUE;
	gboolean has_official_header = FALSE;
	gboolean has_geometry_header = FALSE;
	gboolean has_gqview_header   = FALSE;
	gboolean need_header	 = TRUE;
	guint total = 0;
	guint fail = 0;
	gboolean changed = FALSE;
	CollectManagerEntry *entry = NULL;
	guint flush = !!(flags & COLLECTION_LOAD_FLUSH);
	guint append = !!(flags & COLLECTION_LOAD_APPEND);
	guint only_geometry = !!(flags & COLLECTION_LOAD_GEOMETRY);

	if (!only_geometry)
		{
		collection_load_stop(cd);

		if (flush)
			collect_manager_flush();
		else
			entry = collect_manager_get_entry(path);

		if (!append)
			{
			collection_list_free(cd->list);
			cd->list = NULL;
			}
		}

	if (!path && !cd->path) return FALSE;

	if (!path) path = cd->path;

	DEBUG_1("collection load: append=%d flush=%d only_geometry=%d path=%s",
			  append, flush, only_geometry, path);

	/* load it */
	pathl = path_from_utf8(path);
	f = fopen(pathl, "r");
	g_free(pathl);
	if (!f)
		{
		log_printf("Failed to open collection file: \"%s\"\n", path);
		return FALSE;
		}

	while (fgets(s_buf, sizeof(s_buf), f))
		{
		gchar *buf;
		gchar *p = s_buf;

		/* Skip whitespaces and empty lines */
		while (*p && g_ascii_isspace(*p)) p++;
		if (*p == '\n' || *p == '\r') continue;

		/* Parse comments */
		if (*p == '#')
			{
			if (!need_header) continue;
			if (g_ascii_strncasecmp(p, GQ_COLLECTION_MARKER, strlen(GQ_COLLECTION_MARKER)) == 0)
				{
				/* Looks like an official collection, allow unchecked input.
				 * All this does is allow adding files that may not exist,
				 * which is needed for the collection manager to work.
				 * Also unofficial files abort after too many invalid entries.
				 */
				has_official_header = TRUE;
				limit_failures = FALSE;
				}
			else if (strncmp(p, "#geometry:", 10 ) == 0 &&
				 scan_geometry(p + 10, &cd->window_x, &cd->window_y, &cd->window_w, &cd->window_h))
				{
				has_geometry_header = TRUE;
				cd->window_read = TRUE;
				if (only_geometry) break;
				}
			else if (g_ascii_strncasecmp(p, "#GQview collection", strlen("#GQview collection")) == 0)
				{
				/* As 2008/04/15 there is no difference between our collection file format
				 * and GQview 2.1.5 collection file format so ignore failures as well. */
				has_gqview_header = TRUE;
				limit_failures = FALSE;
				}
			need_header = (!has_official_header && !has_gqview_header) || !has_geometry_header;
			continue;
			}

		if (only_geometry) continue;

		/* Read filenames */
		while (*p && *p != '"') p++;
		if (*p) p++;
		buf = p;
		while (*p && *p != '"') p++;
		*p = 0;
		if (*buf)
			{
			gboolean valid;

			if (!flush)
				changed |= collect_manager_process_action(entry, &buf);

			valid = (buf[0] == G_DIR_SEPARATOR && collection_add_check(cd, file_data_new_simple(buf), FALSE, TRUE));
			if (!valid) DEBUG_1("collection invalid file: %s", buf);

			total++;
			if (!valid)
				{
				fail++;
				if (limit_failures &&
				    fail > GQ_COLLECTION_FAIL_MIN &&
				    fail * 100 / total > GQ_COLLECTION_FAIL_PERCENT)
					{
					log_printf("%d invalid filenames in unofficial collection file, closing: %s\n", fail, path);
					success = FALSE;
					break;
					}
				}
			}
		}

	DEBUG_1("collection files: total = %d fail = %d official=%d gqview=%d geometry=%d",
			  total, fail, has_official_header, has_gqview_header, has_geometry_header);

	fclose(f);
	if (only_geometry) return has_geometry_header;

	if (!flush)
		{
		gchar *buf = NULL;
		while (collect_manager_process_action(entry, &buf))
			{
			collection_add_check(cd, file_data_new_simple(buf), FALSE, TRUE);
			changed = TRUE;
			g_free(buf);
			buf = NULL;
			}
		}

	cd->list = collection_list_sort(cd->list, cd->sort_method);

	if (!flush && changed && success)
		collection_save_private(cd, path);

	if (!flush)
		collect_manager_entry_reset(entry);

	if (!append) cd->changed = FALSE;

	return success;
}
Example #9
0
/* This checks relative caches in dir/.thumbnails and
 * removes them if they have no source counterpart.
 */
gint cache_maintain_dir(FileData *dir_fd, gint recursive, gint clear)
{
	GList *list = NULL;
	gchar *cachedir;
	FileData *cachedir_fd;
	gboolean still_have_a_file = FALSE;
	GList *work;

	cachedir = g_build_filename(dir, GQ_CACHE_LOCAL_THUMB, NULL);
	cachedir_fd = file_data_new_simple(cachedir);
	g_free(cachedir);

	filelist_read(cachedir_fd, &list, NULL);
	work = list;

	while (work)
		{
		FileData *fd;
		gchar *source;

		fd = work->data;
		work = work->next;

		source = g_build_filename(dir->path, fd->name, NULL);

		if (clear ||
		    extension_truncate(source, GQ_CACHE_EXT_THUMB) ||
		    extension_truncate(source, GQ_CACHE_EXT_SIM))
			{
			if (!clear && isfile(source))
				{
				still_have_a_file = TRUE;
				}
			else
				{
				if (!unlink_file(fd->path))
					{
					DEBUG_1("Failed to remove cache file %s", fd->path);
					still_have_a_file = TRUE;
					}
				}
			}
		else
			{
			still_have_a_file = TRUE;
			}
		g_free(source);
		}

	filelist_free(list);
	file_data_unref(cachedir_fd);

	if (recursive)
		{
		list = NULL;

		filelist_read(dir_fd, NULL, &list);
		work = list;
		while (work)
			{
			FileData *fd = work->data;
			work = work->next;

			still_have_a_file |= cache_maintain_dir(fd->path, recursive, clear);
			}

		filelist_free(list);
		}

	return still_have_a_file;
}
Example #10
0
/* This checks all files in ~/GQ_RC_DIR/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;
	FileData *dir_fd;
	GList *flist = NULL;
	gboolean still_have_a_file = FALSE;

	DEBUG_1("maintainance check: %s", dir);

	base_length = strlen(homedir()) + strlen("/") + strlen(GQ_CACHE_RC_THUMB);
	base = g_strconcat(homedir(), "/", GQ_CACHE_RC_THUMB, dir, NULL);
	dir_fd = file_data_new_simple(base);
	g_free(base);

	if (filelist_read(dir_fd, &flist, &dlist))
		{
		GList *work;

		work = dlist;
		while (work)
			{
			FileData *fd = work->data;
			if (recursive && strlen(fd->path) > base_length &&
			    !cache_maintain_home_dir(fd->path + base_length, recursive, clear))
				{
				DEBUG_1("Deleting thumb dir: %s", fd->path);
				if (!rmdir_utf8(fd->path))
					{
					log_printf("Unable to delete dir: %s\n", fd->path);
					}
				}
			else
				{
				still_have_a_file = TRUE;
				}
			work = work->next;
			}

		work = flist;
		while (work)
			{
			FileData *fd = work->data;
			gchar *path = g_strdup(fd->path);
			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)) log_printf("failed to delete:%s\n", path);
				}
			else
				{
				still_have_a_file = TRUE;
				}
			g_free(path);

			work = work->next;
			}
		}

	filelist_free(dlist);
	filelist_free(flist);
	file_data_unref(dir_fd);

	return still_have_a_file;
}
Example #11
0
/* sorry for complexity (cm->done_list), but need it to remove empty dirs */
void cache_maintain_home(gboolean metadata, gboolean clear, GtkWidget *parent)
{
	CMData *cm;
	GList *dlist;
	FileData *dir_fd;
	const gchar *msg;
	const gchar *cache_folder;
	GtkWidget *hbox;

	if (metadata)
		{
		cache_folder = get_metadata_cache_dir();
		}
	else
		{
		cache_folder = get_thumbnails_cache_dir();
		}

	dir_fd = file_data_new_simple(cache_folder);
	if (!filelist_read(dir_fd, NULL, &dlist))
		{
		file_data_unref(dir_fd);
		return;
		}

	dlist = g_list_append(dlist, dir_fd);

	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"),
				    "main_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);
}
Example #12
0
void pan_calendar_update(PanWindow *pw, PanItem *pi_day)
{
	PanItem *pbox;
	PanItem *pi;
	GList *list;
	GList *work;
	gint x1, y1, x2, y2, x3, y3;
	gint x, y, w, h;
	gint grid;
	gint column;
	
	while ((pi = pan_item_find_by_key(pw, PAN_ITEM_NONE, "day_bubble"))) pan_item_remove(pw, pi);

	if (!pi_day || pi_day->type != PAN_ITEM_BOX ||
	    !pi_day->key || strcmp(pi_day->key, "day") != 0) return;

	list = pan_layout_intersect(pw, pi_day->x, pi_day->y, pi_day->width, pi_day->height);

	work = list;
	while (work)
		{
		PanItem *dot;
		GList *node;

		dot = work->data;
		node = work;
		work = work->next;

		if (dot->type != PAN_ITEM_BOX || !dot->fd ||
		    !dot->key || strcmp(dot->key, "dot") != 0)
			{
			list = g_list_delete_link(list, node);
			}
		}

#if 0
	if (!list) return;
#endif

	grid = (gint)(sqrt(g_list_length(list)) + 0.5);

	x = pi_day->x + pi_day->width + 4;
	y = pi_day->y;

#if 0
	if (y + grid * (PAN_THUMB_SIZE + PAN_THUMB_GAP) + PAN_BOX_BORDER * 4 > pw->pr->image_height)
		{
		y = pw->pr->image_height - (grid * (PAN_THUMB_SIZE + PAN_THUMB_GAP) + PAN_BOX_BORDER * 4);
		}
#endif

	pbox = pan_item_box_new(pw, NULL, x, y, PAN_BOX_BORDER, PAN_BOX_BORDER,
				PAN_CAL_POPUP_BORDER,
				PAN_CAL_POPUP_COLOR, PAN_CAL_POPUP_ALPHA,
				PAN_CAL_POPUP_BORDER_COLOR, PAN_CAL_POPUP_ALPHA);
	pan_item_set_key(pbox, "day_bubble");

	if (pi_day->fd)
		{
		PanItem *plabel;
		gchar *buf;

		buf = pan_date_value_string(pi_day->fd->date, PAN_DATE_LENGTH_WEEK);
		plabel = pan_item_text_new(pw, x, y, buf, PAN_TEXT_ATTR_BOLD | PAN_TEXT_ATTR_HEADING,
					   PAN_TEXT_BORDER_SIZE,
					   PAN_CAL_POPUP_TEXT_COLOR, 255);
		pan_item_set_key(plabel, "day_bubble");
		g_free(buf);

		pan_item_size_by_item(pbox, plabel, 0);

		y += plabel->height;
		}

	if (list)
		{
		column = 0;

		x += PAN_BOX_BORDER;
		y += PAN_BOX_BORDER;

		work = list;
		while (work)
			{
			PanItem *dot;

			dot = work->data;
			work = work->next;

			if (dot->fd)
				{
				PanItem *pimg;

				pimg = pan_item_thumb_new(pw, file_data_new_simple(dot->fd->path), x, y);
				pan_item_set_key(pimg, "day_bubble");

				pan_item_size_by_item(pbox, pimg, PAN_BOX_BORDER);

				column++;
				if (column < grid)
					{
					x += PAN_THUMB_SIZE + PAN_THUMB_GAP;
					}
				else
					{
					column = 0;
					x = pbox->x + PAN_BOX_BORDER;
					y += PAN_THUMB_SIZE + PAN_THUMB_GAP;
					}
				}
			}
		}

	x1 = pi_day->x + pi_day->width - 8;
	y1 = pi_day->y + 8;
	x2 = pbox->x + 1;
	y2 = pbox->y + MIN(42, pbox->height);
	x3 = pbox->x + 1;
	y3 = MAX(pbox->y, y2 - 30);
	util_clip_triangle(x1, y1, x2, y2, x3, y3,
			   &x, &y, &w, &h);

	pi = pan_item_tri_new(pw, NULL, x, y, w, h,
			      x1, y1, x2, y2, x3, y3,
			      PAN_CAL_POPUP_COLOR, PAN_CAL_POPUP_ALPHA);
	pan_item_tri_border(pi, PAN_BORDER_1 | PAN_BORDER_3, PAN_CAL_POPUP_BORDER_COLOR, PAN_CAL_POPUP_ALPHA);
	pan_item_set_key(pi, "day_bubble");
	pan_item_added(pw, pi);

	pan_item_box_shadow(pbox, PAN_SHADOW_OFFSET * 2, PAN_SHADOW_FADE * 2);
	pan_item_added(pw, pbox);

	pan_layout_resize(pw);
}
Example #13
0
static gboolean vdlist_populate(ViewDir *vd, gboolean clear)
{
    GtkListStore *store;
    GList *work;
    GtkTreeIter iter;
    gboolean valid;
    gchar *filepath;
    GList *old_list;
    gboolean ret;
    FileData *fd;
    SortType sort_type = SORT_NAME;
    gboolean sort_ascend = TRUE;

    old_list = VDLIST(vd)->list;

    ret = filelist_read(vd->dir_fd, NULL, &VDLIST(vd)->list);
    VDLIST(vd)->list = filelist_sort(VDLIST(vd)->list, sort_type, sort_ascend);

    /* add . and .. */

    if (strcmp(vd->dir_fd->path, G_DIR_SEPARATOR_S) != 0)
    {
        filepath = g_build_filename(vd->dir_fd->path, "..", NULL);
        fd = file_data_new_simple(filepath);
        VDLIST(vd)->list = g_list_prepend(VDLIST(vd)->list, fd);
        g_free(filepath);
    }

    if (options->file_filter.show_dot_directory)
    {
        filepath = g_build_filename(vd->dir_fd->path, ".", NULL);
        fd = file_data_new_simple(filepath);
        VDLIST(vd)->list = g_list_prepend(VDLIST(vd)->list, fd);
        g_free(filepath);
    }

    store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)));
    if (clear) gtk_list_store_clear(store);

    valid = gtk_tree_model_iter_children(GTK_TREE_MODEL(store), &iter, NULL);

    work = VDLIST(vd)->list;
    while (work)
    {
        gint match;
        GdkPixbuf *pixbuf;
        const gchar *date = "";
        gboolean done = FALSE;

        fd = work->data;

        if (access_file(fd->path, R_OK | X_OK) && fd->name)
        {
            if (fd->name[0] == '.' && fd->name[1] == '\0')
            {
                pixbuf = vd->pf->open;
            }
            else if (fd->name[0] == '.' && fd->name[1] == '.' && fd->name[2] == '\0')
            {
                pixbuf = vd->pf->parent;
            }
            else
            {
                pixbuf = vd->pf->close;
                if (vd->layout && vd->layout->options.show_directory_date)
                    date = text_from_time(fd->date);
            }
        }
        else
        {
            pixbuf = vd->pf->deny;
        }

        while (!done)
        {
            FileData *old_fd = NULL;

            if (valid)
            {
                gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
                                   DIR_COLUMN_POINTER, &old_fd,
                                   -1);

                if (fd == old_fd)
                {
                    match = 0;
                }
                else
                {
                    match = filelist_sort_compare_filedata_full(fd, old_fd, sort_type, sort_ascend);

                    if (match == 0) g_warning("multiple fd for the same path");
                }

            }
            else
            {
                match = -1;
            }

            if (match < 0)
            {
                GtkTreeIter new;

                if (valid)
                {
                    gtk_list_store_insert_before(store, &new, &iter);
                }
                else
                {
                    gtk_list_store_append(store, &new);
                }

                gtk_list_store_set(store, &new,
                                   DIR_COLUMN_POINTER, fd,
                                   DIR_COLUMN_ICON, pixbuf,
                                   DIR_COLUMN_NAME, fd->name,
                                   DIR_COLUMN_DATE, date,
                                   -1);

                done = TRUE;
            }
            else if (match > 0)
Example #14
0
gboolean vdtree_populate_path_by_iter(ViewDir *vd, GtkTreeIter *iter, gboolean force, FileData *target_fd)
{
	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(vd->view));
	gtk_tree_model_get(store, iter, DIR_COLUMN_POINTER, &nd, -1);

	if (!nd) return FALSE;

	current_time = time(NULL);

	if (nd->expanded)
		{
		if (!isdir(nd->fd->path))
			{
			if (vd->click_fd == nd->fd) vd->click_fd = NULL;
			if (vd->drop_fd == nd->fd) vd->drop_fd = NULL;
			gtk_tree_store_remove(GTK_TREE_STORE(store), iter);
			vdtree_node_free(nd);
			return FALSE;
			}
		if (!force && current_time - nd->last_update < 2)
			{
			DEBUG_1("Too frequent update of %s", nd->fd->path);
			return TRUE;
			}
		if (nd->fd->version == nd->version) return TRUE;
		}

	vdtree_busy_push(vd);

	filelist_read(nd->fd, 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 (!options->file_filter.show_hidden_files &&
	    target_fd &&
	    strncmp(nd->fd->path, target_fd->path, strlen(nd->fd->path)) == 0)
		{
		gint n;

		n = strlen(nd->fd->path);
		if (target_fd->path[n] == G_DIR_SEPARATOR && target_fd->path[n+1] == '.')
			{
			gchar *name8;
			struct stat sbuf;

			n++;

			while (target_fd->path[n] != '\0' && target_fd->path[n] != G_DIR_SEPARATOR) n++;
			name8 = g_strndup(target_fd->path, n);

			if (stat_utf8(name8, &sbuf))
				{
				list = g_list_prepend(list, file_data_new_simple(name8));
				}

			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_unref(fd);
			}
		else
			{
			NodeData *cnd;

			cnd = vdtree_find_iter_by_fd(vd, iter, fd, &child);
			if (cnd)
				{
				if (cnd->expanded && cnd->version != fd->version)
					{
					vdtree_populate_path_by_iter(vd, &child, FALSE, target_fd);
					}

				gtk_tree_store_set(GTK_TREE_STORE(store), &child, DIR_COLUMN_NAME, fd->name, -1);
				cnd->version = fd->version;
				old = g_list_remove(old, cnd);
				file_data_unref(fd);
				}
			else
				{
				vdtree_add_by_data(vd, fd, iter);
				}
			}
		}

	work = old;
	while (work)
		{
		NodeData *cnd = work->data;
		work = work->next;

		if (vd->click_fd == cnd->fd) vd->click_fd = NULL;
		if (vd->drop_fd == cnd->fd) vd->drop_fd = NULL;

		if (vdtree_find_iter_by_data(vd, 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(vd);

	nd->expanded = TRUE;
	nd->last_update = current_time;

	return TRUE;
}
Example #15
0
void pan_timeline_compute(PanWindow *pw, const gchar *path, gint *width, gint *height)
{
	GList *list;
	GList *work;
	gint x, y;
	time_t tc;
	gint total;
	gint count;
	PanItem *pi_month = NULL;
	PanItem *pi_day = NULL;
	gint month_start;
	gint day_start;
	gint x_width;
	gint y_height;

	list = pan_list_tree(path, SORT_NONE, TRUE, pw->ignore_symlinks);

	if (pw->cache_list && pw->exif_date_enable)
		{
		pw->cache_list = filelist_sort(pw->cache_list, SORT_NAME, TRUE);
		list = filelist_sort(list, SORT_NAME, TRUE);
		pan_cache_sync_date(pw, list);
		}

	pw->cache_list = filelist_sort(pw->cache_list, SORT_TIME, TRUE);
	list = filelist_sort(list, SORT_TIME, TRUE);

	*width = PAN_BOX_BORDER * 2;
	*height = PAN_BOX_BORDER * 2;

	x = 0;
	y = 0;
	month_start = y;
	day_start = month_start;
	x_width = 0;
	y_height = 0;
	tc = 0;
	total = 0;
	count = 0;
	work = list;
	while (work)
		{
		FileData *fd;
		PanItem *pi;

		fd = work->data;
		work = work->next;

		if (!pan_date_compare(fd->date, tc, PAN_DATE_LENGTH_DAY))
			{
			GList *needle;
			gchar *buf;

			if (!pan_date_compare(fd->date, tc, PAN_DATE_LENGTH_MONTH))
				{
				pi_day = NULL;

				if (pi_month)
					{
					x = pi_month->x + pi_month->width + PAN_BOX_BORDER;
					}
				else
					{
					x = PAN_BOX_BORDER;
					}

				y = PAN_BOX_BORDER;

				buf = pan_date_value_string(fd->date, PAN_DATE_LENGTH_MONTH);
				pi = pan_item_text_new(pw, x, y, buf,
						       PAN_TEXT_ATTR_BOLD | PAN_TEXT_ATTR_HEADING,
						       PAN_TEXT_BORDER_SIZE,
						       PAN_TEXT_COLOR, 255);
				g_free(buf);
				y += pi->height;

				pi_month = pan_item_box_new(pw, file_data_new_simple(fd->path),
							    x, y, 0, 0,
							    PAN_BOX_OUTLINE_THICKNESS,
							    PAN_BOX_COLOR, PAN_BOX_ALPHA,
							    PAN_BOX_OUTLINE_COLOR, PAN_BOX_OUTLINE_ALPHA);

				x += PAN_BOX_BORDER;
				y += PAN_BOX_BORDER;
				month_start = y;
				}

			if (pi_day) x = pi_day->x + pi_day->width + PAN_BOX_BORDER;

			tc = fd->date;
			total = 1;
			count = 0;

			needle = work;
			while (needle)
				{
				FileData *nfd;

				nfd = needle->data;
				if (pan_date_compare(nfd->date, tc, PAN_DATE_LENGTH_DAY))
					{
					needle = needle->next;
					total++;
					}
				else
					{
					needle = NULL;
					}
				}

			buf = pan_date_value_string(fd->date, PAN_DATE_LENGTH_WEEK);
			pi = pan_item_text_new(pw, x, y, buf, PAN_TEXT_ATTR_NONE,
					       PAN_TEXT_BORDER_SIZE,
					       PAN_TEXT_COLOR, 255);
			g_free(buf);

			y += pi->height;

			pi_day = pan_item_box_new(pw, file_data_new_simple(fd->path), x, y, 0, 0,
						  PAN_BOX_OUTLINE_THICKNESS,
						  PAN_BOX_COLOR, PAN_BOX_ALPHA,
						  PAN_BOX_OUTLINE_COLOR, PAN_BOX_OUTLINE_ALPHA);

			x += PAN_BOX_BORDER;
			y += PAN_BOX_BORDER;
			day_start = y;
			}

		if (pw->size > PAN_IMAGE_SIZE_THUMB_LARGE)
			{
			pi = pan_item_image_new(pw, fd, x, y, 10, 10);
			if (pi->width > x_width) x_width = pi->width;
			y_height = pi->height;
			}
		else
			{
			pi = pan_item_thumb_new(pw, fd, x, y);
			x_width = PAN_THUMB_SIZE;
			y_height = PAN_THUMB_SIZE;
			}

		pan_item_size_by_item(pi_day, pi, PAN_BOX_BORDER);
		pan_item_size_by_item(pi_month, pi_day, PAN_BOX_BORDER);

		total--;
		count++;

		if (total > 0 && count < PAN_GROUP_MAX)
			{
			y += y_height + PAN_THUMB_GAP;
			}
		else
			{
			x += x_width + PAN_THUMB_GAP;
			x_width = 0;
			count = 0;

			if (total > 0)
				y = day_start;
			else
				y = month_start;
			}

		pan_item_size_coordinates(pi_month, PAN_BOX_BORDER, width, height);
		}

	g_list_free(list);
}
Example #16
0
void pan_calendar_compute(PanWindow *pw, FileData *dir_fd, gint *width, gint *height)
{
	GList *list;
	GList *work;
	gint x, y;
	time_t tc;
	gint count;
	gint day_max;
	gint day_width;
	gint day_height;
	gint grid;
	gint year = 0;
	gint month = 0;
	gint end_year = 0;
	gint end_month = 0;

	list = pan_list_tree(dir_fd, SORT_NONE, TRUE, pw->ignore_symlinks);

	if (pw->cache_list && pw->exif_date_enable)
		{
		pw->cache_list = pan_cache_sort(pw->cache_list, SORT_NAME, TRUE);
		list = filelist_sort(list, SORT_NAME, TRUE);
		pan_cache_sync_date(pw, list);
		}

	pw->cache_list = pan_cache_sort(pw->cache_list, SORT_TIME, TRUE);
	list = filelist_sort(list, SORT_TIME, TRUE);

	day_max = 0;
	count = 0;
	tc = 0;
	work = list;
	while (work)
		{
		FileData *fd;

		fd = work->data;
		work = work->next;

		if (!pan_date_compare(fd->date, tc, PAN_DATE_LENGTH_DAY))
			{
			count = 0;
			tc = fd->date;
			}
		else
			{
			count++;
			if (day_max < count) day_max = count;
			}
		}

	DEBUG_1("biggest day contains %d images", day_max);

	grid = (gint)(sqrt((gdouble)day_max) + 0.5) * (PAN_THUMB_SIZE + PAN_SHADOW_OFFSET * 2 + PAN_THUMB_GAP);
	day_width = MAX(PAN_CAL_DAY_WIDTH, grid);
	day_height = MAX(PAN_CAL_DAY_HEIGHT, grid);

	if (list)
		{
		FileData *fd = list->data;

		year = pan_date_value(fd->date, PAN_DATE_LENGTH_YEAR);
		month = pan_date_value(fd->date, PAN_DATE_LENGTH_MONTH);
		}

	work = g_list_last(list);
	if (work)
		{
		FileData *fd = work->data;
		end_year = pan_date_value(fd->date, PAN_DATE_LENGTH_YEAR);
		end_month = pan_date_value(fd->date, PAN_DATE_LENGTH_MONTH);
		}

	*width = PAN_BOX_BORDER * 2;
	*height = PAN_BOX_BORDER * 2;

	x = PAN_BOX_BORDER;
	y = PAN_BOX_BORDER;

	work = list;
	while (work && (year < end_year || (year == end_year && month <= end_month)))
		{
		PanItem *pi_month;
		PanItem *pi_text;
		gint day;
		gint days;
		gint col;
		gint row;
		time_t dt;
		gchar *buf;

		/* figure last second of this month */
		dt = pan_date_to_time((month == 12) ? year + 1 : year, (month == 12) ? 1 : month + 1, 1);
		dt -= 60 * 60 * 24;

		/* anything to show this month? */
		if (!pan_date_compare(((FileData *)(work->data))->date, dt, PAN_DATE_LENGTH_MONTH))
			{
			month ++;
			if (month > 12)
				{
				year++;
				month = 1;
				}
			continue;
			}

		days = pan_date_value(dt, PAN_DATE_LENGTH_DAY);
		dt = pan_date_to_time(year, month, 1);
		col = pan_date_value(dt, PAN_DATE_LENGTH_WEEK);
		row = 1;

		x = PAN_BOX_BORDER;

		pi_month = pan_item_box_new(pw, NULL, x, y, PAN_CAL_DAY_WIDTH * 7, PAN_CAL_DAY_HEIGHT / 4,
					    PAN_CAL_MONTH_BORDER,
					    PAN_CAL_MONTH_COLOR, PAN_CAL_MONTH_ALPHA,
					    PAN_CAL_MONTH_BORDER_COLOR, PAN_CAL_MONTH_ALPHA);
		buf = pan_date_value_string(dt, PAN_DATE_LENGTH_MONTH);
		pi_text = pan_item_text_new(pw, x, y, buf,
					    PAN_TEXT_ATTR_BOLD | PAN_TEXT_ATTR_HEADING,
					    PAN_TEXT_BORDER_SIZE,
					    PAN_CAL_MONTH_TEXT_COLOR, 255);
		g_free(buf);
		pi_text->x = pi_month->x + (pi_month->width - pi_text->width) / 2;

		pi_month->height = pi_text->y + pi_text->height - pi_month->y;

		x = PAN_BOX_BORDER + col * PAN_CAL_DAY_WIDTH;
		y = pi_month->y + pi_month->height + PAN_BOX_BORDER;

		for (day = 1; day <= days; day++)
			{
			FileData *fd;
			PanItem *pi_day;
			gint dx, dy;
			gint n = 0;
			gchar fake_path[20];

			dt = pan_date_to_time(year, month, day);

			/*
			 * Create a FileData entry that represents the given day.
			 * It does not correspond to any real file
			 */

			g_snprintf(fake_path, sizeof(fake_path), "//%04d-%02d-%02d", year, month, day);
			fd = file_data_new_simple(fake_path);
			fd->date = dt;
			pi_day = pan_item_box_new(pw, fd, x, y, PAN_CAL_DAY_WIDTH, PAN_CAL_DAY_HEIGHT,
						  PAN_CAL_DAY_BORDER,
						  PAN_CAL_DAY_COLOR, PAN_CAL_DAY_ALPHA,
						  PAN_CAL_DAY_BORDER_COLOR, PAN_CAL_DAY_ALPHA);
			pan_item_set_key(pi_day, "day");

			dx = x + PAN_CAL_DOT_GAP * 2;
			dy = y + PAN_CAL_DOT_GAP * 2;

			fd = (work) ? work->data : NULL;
			while (fd && pan_date_compare(fd->date, dt, PAN_DATE_LENGTH_DAY))
				{
				PanItem *pi;

				pi = pan_item_box_new(pw, fd, dx, dy, PAN_CAL_DOT_SIZE, PAN_CAL_DOT_SIZE,
						      0,
						      PAN_CAL_DOT_COLOR, PAN_CAL_DOT_ALPHA,
						      0, 0, 0, 0);
				pan_item_set_key(pi, "dot");

				dx += PAN_CAL_DOT_SIZE + PAN_CAL_DOT_GAP;
				if (dx + PAN_CAL_DOT_SIZE > pi_day->x + pi_day->width - PAN_CAL_DOT_GAP * 2)
					{
					dx = x + PAN_CAL_DOT_GAP * 2;
					dy += PAN_CAL_DOT_SIZE + PAN_CAL_DOT_GAP;
					}
				if (dy + PAN_CAL_DOT_SIZE > pi_day->y + pi_day->height - PAN_CAL_DOT_GAP * 2)
					{
					/* must keep all dots within respective day even if it gets ugly */
					dy = y + PAN_CAL_DOT_GAP * 2;
					}

				n++;

				work = work->next;
				fd = (work) ? work->data : NULL;
				}

			if (n > 0)
				{
				PanItem *pi;

				pi_day->color_r = MAX(pi_day->color_r - 61 - n * 3, 80);
				pi_day->color_g = pi_day->color_r;

				buf = g_strdup_printf("( %d )", n);
				pi = pan_item_text_new(pw, x, y, buf, PAN_TEXT_ATTR_NONE,
						       PAN_TEXT_BORDER_SIZE,
						       PAN_CAL_DAY_TEXT_COLOR, 255);
				g_free(buf);

				pi->x = pi_day->x + (pi_day->width - pi->width) / 2;
				pi->y = pi_day->y + (pi_day->height - pi->height) / 2;
				}

			buf = g_strdup_printf("%d", day);
			pan_item_text_new(pw, x + 4, y + 4, buf, PAN_TEXT_ATTR_BOLD | PAN_TEXT_ATTR_HEADING,
					  PAN_TEXT_BORDER_SIZE,
					  PAN_CAL_DAY_TEXT_COLOR, 255);
			g_free(buf);


			pan_item_size_coordinates(pi_day, PAN_BOX_BORDER, width, height);

			col++;
			if (col > 6)
				{
				col = 0;
				row++;
				x = PAN_BOX_BORDER;
				y += PAN_CAL_DAY_HEIGHT;
				}
			else
				{
				x += PAN_CAL_DAY_WIDTH;
				}
			}

		if (col > 0) y += PAN_CAL_DAY_HEIGHT;
		y += PAN_BOX_BORDER * 2;

		month ++;
		if (month > 12)
			{
			year++;
			month = 1;
			}
		}

	*width += grid;
	*height = MAX(*height, grid + PAN_BOX_BORDER * 2 * 2);

	g_list_free(list);
}