history_list_free_key(SORT_KEY_COLLECTIONS);
bookmark_list_set_key(bookmarks, SORT_KEY_COLLECTIONS);
- dir_fd = file_data_new_simple(get_collections_dir());
+ dir_fd = file_data_new_dir(get_collections_dir());
filelist_read(dir_fd, &list, NULL);
file_data_unref(dir_fd);
cache_folder = get_thumbnails_cache_dir();
}
- dir_fd = file_data_new_simple(cache_folder);
+ dir_fd = file_data_new_dir(cache_folder);
if (!filelist_read(dir_fd, NULL, &dlist))
{
file_data_unref(dir_fd);
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);
+ dir_fd = file_data_new_dir(base);
g_free(base);
if (filelist_read(dir_fd, &flist, &dlist))
GList *work;
cachedir = g_build_filename(dir, GQ_CACHE_LOCAL_THUMB, NULL);
- cachedir_fd = file_data_new_simple(cachedir);
+ cachedir_fd = file_data_new_dir(cachedir);
g_free(cachedir);
filelist_read(cachedir_fd, &list, NULL);
spinner_set_interval(cd->spinner, SPINNER_SPEED);
- dir_fd = file_data_new_simple(path);
+ dir_fd = file_data_new_dir(path);
cache_manager_render_folder(cd, dir_fd);
file_data_unref(dir_fd);
while (cache_manager_render_file(cd));
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);
+ dir_fd = file_data_new_dir(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);
+ dir_fd = file_data_new_dir(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);
+ dir_fd = file_data_new_dir(path);
filelist_read(dir_fd, &list, NULL);
cd->list = g_list_concat(cd->list, list);
file_data_unref(dir_fd);
GList *work;
FileData *dir_fd;
- dir_fd = file_data_new_simple(get_collections_dir());
+ dir_fd = file_data_new_dir(get_collections_dir());
filelist_read(dir_fd, &list, NULL);
file_data_unref(dir_fd);
return ret;
}
-static FileData *file_data_new(const gchar *path_utf8, struct stat *st, gboolean check_sidecars, GHashTable *basename_hash)
+static FileData *file_data_new(const gchar *path_utf8, struct stat *st, gboolean disable_sidecars, GHashTable *basename_hash)
{
FileData *fd;
- DEBUG_2("file_data_new: '%s' %d %d", path_utf8, check_sidecars, !!basename_hash);
+ DEBUG_2("file_data_new: '%s' %d %d", path_utf8, disable_sidecars, !!basename_hash);
+
+ if (S_ISDIR(st->st_mode)) disable_sidecars = TRUE;
if (!file_data_pool)
file_data_pool = g_hash_table_new(g_str_hash, g_str_equal);
if (fd)
{
gboolean changed;
+
+ if (disable_sidecars) file_data_disable_grouping(fd, TRUE);
+
if (basename_hash)
{
file_data_basename_hash_insert(basename_hash, fd);
- if (check_sidecars)
+ if (!disable_sidecars)
file_data_check_sidecars(fd, basename_hash);
}
changed = file_data_check_changed_files(fd);
else
changed = file_data_check_changed_files_recursive(fd, st);
- if (changed && check_sidecars && sidecar_file_priority(fd->extension))
+ if (changed && !disable_sidecars && sidecar_file_priority(fd->extension))
file_data_check_sidecars(fd, basename_hash);
DEBUG_2("file_data_pool hit: '%s' %s", fd->path, changed ? "(changed)" : "");
fd->mode = st->st_mode;
fd->ref = 1;
fd->magick = 0x12345678;
+
+ if (disable_sidecars) fd->disable_grouping = TRUE;
file_data_set_path(fd, path_utf8); /* set path, name, collate_key_*, original_path */
if (basename_hash) file_data_basename_hash_insert(basename_hash, fd);
- if (check_sidecars)
+ if (!disable_sidecars)
+ {
+ g_assert(basename_hash);
file_data_check_sidecars(fd, basename_hash);
+ }
return fd;
}
-/* extension must contain only ASCII characters */
-static GList *check_case_insensitive_ext(gchar *path)
-{
- gchar *sl;
- gchar *extl;
- gint ext_len;
- GList *list = NULL;
-
- sl = path_from_utf8(path);
-
- extl = strrchr(sl, '.');
- if (extl)
- {
- gint i, j;
- extl++; /* the first char after . */
- ext_len = strlen(extl);
-
- for (i = 0; i < (1 << ext_len); i++)
- {
- struct stat st;
- gboolean skip = FALSE;
- for (j = 0; j < ext_len; j++)
- {
- if (i & (1 << (ext_len - 1 - j)))
- {
- extl[j] = g_ascii_tolower(extl[j]);
- /* make sure the result does not contain duplicates */
- if (extl[j] == g_ascii_toupper(extl[j]))
- {
- /* no change, probably a number, we have already tested this combination */
- skip = TRUE;
- break;
- }
- }
- else
- extl[j] = g_ascii_toupper(extl[j]);
- }
- if (skip) continue;
-
- if (stat(sl, &st) == 0)
- {
- list = g_list_prepend(list, file_data_new_local(sl, &st, FALSE, FALSE));
- }
- }
- }
- g_free(sl);
-
- return list;
-}
static void file_data_check_sidecars(FileData *fd, GHashTable *basename_hash)
{
base_len = fd->extension - fd->path;
fname = g_string_new_len(fd->path, base_len);
- if (basename_hash)
- {
- basename_list = g_hash_table_lookup(basename_hash, fname->str);
- }
+ basename_list = g_hash_table_lookup(basename_hash, fname->str);
/* check for possible sidecar files;
gchar *ext = work->data;
work = work->next;
- if (!basename_hash)
- {
- GList *new_list;
- g_string_truncate(fname, base_len);
- g_string_append(fname, ext);
- new_list = check_case_insensitive_ext(fname->str);
- group_list = g_list_concat(group_list, new_list);
- }
- else
+ const GList *work2 = basename_list;
+
+ while (work2)
{
- const GList *work2 = basename_list;
+ FileData *sfd = work2->data;
- while (work2)
+ if (g_ascii_strcasecmp(ext, sfd->extension) == 0)
{
- FileData *sfd = work2->data;
-
- if (g_ascii_strcasecmp(ext, sfd->extension) == 0)
- {
- group_list = g_list_append(group_list, file_data_ref(sfd));
- }
- work2 = work2->next;
+ group_list = g_list_append(group_list, file_data_ref(sfd));
}
+ work2 = work2->next;
}
}
g_string_free(fname, TRUE);
}
-static FileData *file_data_new_local(const gchar *path, struct stat *st, gboolean check_sidecars, GHashTable *basename_hash)
+static FileData *file_data_new_local(const gchar *path, struct stat *st, gboolean disable_sidecars, GHashTable *basename_hash)
{
gchar *path_utf8 = path_to_utf8(path);
- FileData *ret = file_data_new(path_utf8, st, check_sidecars, basename_hash);
+ FileData *ret = file_data_new(path_utf8, st, disable_sidecars, basename_hash);
g_free(path_utf8);
return ret;
}
-FileData *file_data_new_simple(const gchar *path_utf8)
-{
- struct stat st;
-
- if (!stat_utf8(path_utf8, &st))
- {
- st.st_size = 0;
- st.st_mtime = 0;
- }
-
- return file_data_new(path_utf8, &st, TRUE, NULL);
-}
-
FileData *file_data_add_sidecar_file(FileData *target, FileData *sfd)
{
sfd->parent = target;
return TRUE;
}
-static gboolean filelist_read_real(FileData *dir_fd, GList **files, GList **dirs, gboolean follow_symlinks)
+static gboolean filelist_read_real(const gchar *dir_path, GList **files, GList **dirs, gboolean follow_symlinks)
{
DIR *dp;
struct dirent *dir;
if (files) *files = NULL;
if (dirs) *dirs = NULL;
- pathl = path_from_utf8(dir_fd->path);
+ pathl = path_from_utf8(dir_path);
if (!pathl) return FALSE;
dp = opendir(pathl);
strcmp(name, GQ_CACHE_LOCAL_METADATA) != 0 &&
strcmp(name, THUMB_FOLDER_LOCAL) != 0)
{
- dlist = g_list_prepend(dlist, file_data_new_local(filepath, &ent_sbuf, FALSE, NULL));
+ dlist = g_list_prepend(dlist, file_data_new_local(filepath, &ent_sbuf, TRUE, NULL));
}
}
else
{
if (files && filter_name_exists(name))
{
- flist = g_list_prepend(flist, file_data_new_local(filepath, &ent_sbuf, TRUE, basename_hash));
+ flist = g_list_prepend(flist, file_data_new_local(filepath, &ent_sbuf, FALSE, basename_hash));
}
}
}
gboolean filelist_read(FileData *dir_fd, GList **files, GList **dirs)
{
- return filelist_read_real(dir_fd, files, dirs, TRUE);
+ return filelist_read_real(dir_fd->path, files, dirs, TRUE);
}
gboolean filelist_read_lstat(FileData *dir_fd, GList **files, GList **dirs)
{
- return filelist_read_real(dir_fd, files, dirs, FALSE);
+ return filelist_read_real(dir_fd->path, files, dirs, FALSE);
+}
+
+FileData *file_data_new_simple(const gchar *path_utf8)
+{
+ gchar *dir;
+ struct stat st;
+ FileData *fd;
+ GList *files;
+
+ if (!stat_utf8(path_utf8, &st))
+ {
+ st.st_size = 0;
+ st.st_mtime = 0;
+ }
+
+ if (S_ISDIR(st.st_mode))
+ return file_data_new(path_utf8, &st, TRUE, NULL);
+
+ dir = remove_level_from_path(path_utf8);
+
+ filelist_read_real(dir, &files, NULL, TRUE);
+
+ fd = g_hash_table_lookup(file_data_pool, path_utf8);
+ g_assert(fd);
+ file_data_ref(fd);
+
+ filelist_free(files);
+ g_free(dir);
+ return fd;
+}
+
+FileData *file_data_new_no_grouping(const gchar *path_utf8)
+{
+ struct stat st;
+
+ if (!stat_utf8(path_utf8, &st))
+ {
+ st.st_size = 0;
+ st.st_mtime = 0;
+ }
+
+ return file_data_new(path_utf8, &st, TRUE, NULL);
+}
+
+FileData *file_data_new_dir(const gchar *path_utf8)
+{
+ struct stat st;
+
+ if (!stat_utf8(path_utf8, &st))
+ {
+ st.st_size = 0;
+ st.st_mtime = 0;
+ }
+
+ g_assert(S_ISDIR(st.st_mode));
+ return file_data_new(path_utf8, &st, TRUE, NULL);
}
void filelist_free(GList *list)
gchar *text_from_size_abrev(gint64 size);
const gchar *text_from_time(time_t t);
-/* this expects a utf-8 path */
+/* scan for sidecar files - expensive */
FileData *file_data_new_simple(const gchar *path_utf8);
+/* should be used on helper files which can't have sidecars */
+FileData *file_data_new_no_grouping(const gchar *path_utf8);
+
+/* should be used on dirs */
+FileData *file_data_new_dir(const gchar *path_utf8);
+
#ifdef DEBUG_FILEDATA
FileData *file_data_ref_debug(const gchar *file, gint line, FileData *fd);
void file_data_unref_debug(const gchar *file, gint line, FileData *fd);
file_data_unregister_real_time_monitor(lw->dir_fd);
file_data_unref(lw->dir_fd);
}
- lw->dir_fd = file_data_new_simple(base);
+ lw->dir_fd = file_data_new_dir(base);
file_data_register_real_time_monitor(lw->dir_fd);
g_free(base);
}
FileData *dir_fd;
base = remove_level_from_path(fd->path);
- dir_fd = file_data_new_simple(base);
+ dir_fd = file_data_new_dir(base);
if (dir_fd != lw->dir_fd)
{
layout_set_fd(lw, dir_fd);
if (!path) return;
/* Open previous path */
- dir_fd = file_data_new_simple(path);
+ dir_fd = file_data_new_dir(path);
layout_set_fd(lw, dir_fd);
file_data_unref(dir_fd);
}
if (path)
{
- FileData *dir_fd = file_data_new_simple(path);
+ FileData *dir_fd = file_data_new_dir(path);
layout_set_fd(lw, dir_fd);
file_data_unref(dir_fd);
}
path_parsed = g_strdup(dir);
parse_out_relatives(path_parsed);
- dir_fd = file_data_new_simple(path_parsed);
+ dir_fd = file_data_new_dir(path_parsed);
if (filelist_read(dir_fd, &files, NULL))
*/
g_snprintf(fake_path, sizeof(fake_path), "//%04d-%02d-%02d", year, month, day);
- fd = file_data_new_simple(fake_path);
+ fd = file_data_new_no_grouping(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,
y += pi->height;
- pi_day = pan_item_box_new(pw, file_data_new_simple(fd->path), x, y, 0, 0,
+ pi_day = pan_item_box_new(pw, file_data_ref(fd), x, y, 0, 0,
PAN_BOX_OUTLINE_THICKNESS,
PAN_BOX_COLOR, PAN_BOX_ALPHA,
PAN_BOX_OUTLINE_COLOR, PAN_BOX_OUTLINE_ALPHA);
}
else
{
- FileData *dir_fd = file_data_new_simple(path);
+ FileData *dir_fd = file_data_new_dir(path);
tab_completion_append_to_history(pw->path_entry, path);
pan_layout_set_fd(pw, dir_fd);
static void gr_slideshow_start_rec(const gchar *text, GIOChannel *channel, gpointer data)
{
GList *list;
- FileData *dir_fd = file_data_new_simple(text);
+ FileData *dir_fd = file_data_new_dir(text);
list = filelist_recursive(dir_fd);
file_data_unref(dir_fd);
if (!list) return;
path = fd->path + strlen(sd->search_dir_fd->path);
if (path != fd->path)
{
- FileData *dir_fd = file_data_new_simple(path);
+ FileData *dir_fd = file_data_new_dir(path);
success = filelist_read(dir_fd, &list, NULL);
file_data_unref(dir_fd);
}
if (isdir(path))
{
file_data_unref(sd->search_dir_fd);
- sd->search_dir_fd = file_data_new_simple(path);
+ sd->search_dir_fd = file_data_new_dir(path);
tab_completion_append_to_history(sd->path_entry, sd->search_dir_fd->path);
{
/* search metadata */
file_data_unref(sd->search_dir_fd);
- sd->search_dir_fd = file_data_new_simple(get_metadata_cache_dir());
+ sd->search_dir_fd = file_data_new_dir(get_metadata_cache_dir());
search_start(sd);
}
else if (sd->search_type == SEARCH_MATCH_CONTAINS)
static void thumb_loader_error_cb(ImageLoader *il, gpointer data);
-static void thumb_loader_setup(ThumbLoader *tl, const gchar *path);
+static void thumb_loader_setup(ThumbLoader *tl, FileData *fd);
static GdkPixbuf *get_xv_thumbnail(gchar *thumb_filename, gint max_w, gint max_h);
DEBUG_1("thumbnail size mismatch, regenerating: %s", tl->fd->path);
tl->cache_hit = FALSE;
- thumb_loader_setup(tl, tl->fd->path);
+ thumb_loader_setup(tl, tl->fd);
g_signal_connect(G_OBJECT(tl->il), "done", (GCallback)thumb_loader_done_cb, tl);
if (!tl->idle_done_id) tl->idle_done_id = g_idle_add(thumb_loader_done_delay_cb, tl);
}
-static void thumb_loader_setup(ThumbLoader *tl, const gchar *path)
+static void thumb_loader_setup(ThumbLoader *tl, FileData *fd)
{
- FileData *fd = file_data_new_simple(path);
image_loader_free(tl->il);
tl->il = image_loader_new(fd);
- file_data_unref(fd);
image_loader_set_priority(tl->il, G_PRIORITY_LOW);
/* this will speed up jpegs by up to 3x in some cases */
if (cache_path)
{
- thumb_loader_setup(tl, cache_path);
+ FileData *fd = file_data_new_no_grouping(cache_path);
+ thumb_loader_setup(tl, fd);
+ file_data_unref(fd);
g_free(cache_path);
tl->cache_hit = TRUE;
}
else
{
- thumb_loader_setup(tl, tl->fd->path);
+ thumb_loader_setup(tl, tl->fd);
}
g_signal_connect(G_OBJECT(tl->il), "done", (GCallback)thumb_loader_done_cb, tl);
tl->cache_hit = FALSE;
log_printf("%s", _("Thumbnail image in cache failed to load, trying to recreate.\n"));
- thumb_loader_setup(tl, tl->fd->path);
+ thumb_loader_setup(tl, tl->fd);
g_signal_connect(G_OBJECT(tl->il), "done", (GCallback)thumb_loader_done_cb, tl);
if (image_loader_start(tl->il)) return TRUE;
}
static void thumb_loader_std_error_cb(ImageLoader *il, gpointer data);
static gint thumb_loader_std_setup(ThumbLoaderStd *tl, FileData *fd);
-static gint thumb_loader_std_setup_path(ThumbLoaderStd *tl, const gchar *path);
ThumbLoaderStd *thumb_loader_std_new(gint width, gint height)
if (!tl->thumb_path_local)
{
tl->thumb_path = thumb_loader_std_cache_path(tl, TRUE, NULL, FALSE);
- if (isfile(tl->thumb_path) && thumb_loader_std_setup_path(tl, tl->thumb_path))
+ if (isfile(tl->thumb_path))
{
- tl->thumb_path_local = TRUE;
- return TRUE;
+ FileData *fd = file_data_new_no_grouping(tl->thumb_path);
+ if (thumb_loader_std_setup(tl, fd))
+ {
+ file_data_unref(fd);
+ tl->thumb_path_local = TRUE;
+ return TRUE;
+ }
+ file_data_unref(fd);
}
g_free(tl->thumb_path);
return FALSE;
}
-static gboolean thumb_loader_std_setup_path(ThumbLoaderStd *tl, const gchar *path)
-{
- FileData *fd = file_data_new_simple(path);
- gboolean ret = thumb_loader_std_setup(tl, fd);
- file_data_unref(fd);
- return ret;
-}
-
/*
* Note: Currently local_cache only specifies where to save a _new_ thumb, if
* a valid existing thumb is found anywhere the local thumb will not be created.
tl->thumb_path_local = FALSE;
found = isfile(tl->thumb_path);
- if (found && thumb_loader_std_setup_path(tl, tl->thumb_path)) return TRUE;
+ if (found)
+ {
+ FileData *fd = file_data_new_no_grouping(tl->thumb_path);
+ if (thumb_loader_std_setup(tl, fd))
+ {
+ file_data_unref(fd);
+ return TRUE;
+ }
+ file_data_unref(fd);
+ }
if (thumb_loader_std_fail_check(tl) ||
!thumb_loader_std_next_source(tl, found))
tv->func_valid = func_valid;
tv->data = data;
- if (!thumb_loader_std_setup_path(tv->tl, thumb_path))
+ FileData *fd = file_data_new_no_grouping(thumb_path);
+ if (!thumb_loader_std_setup(tv->tl, fd))
{
tv->idle_id = g_idle_add(thumb_loader_std_thumb_file_validate_idle_cb, tv);
}
tv->idle_id = 0;
}
+ file_data_unref(fd);
return tv->tl;
}
tm->tl->cache_enable = TRUE;
tm->tl->cache_hit = FALSE;
tm->tl->cache_local = FALSE;
-
file_data_unref(tm->tl->fd);
tm->tl->fd = file_data_new_simple(tm->dest);
tm->tl->source_mtime = strtol(mtime_str, NULL, 10);
gboolean warned = FALSE;
FileData *dir_fd;
- dir_fd = file_data_new_simple(options->file_ops.safe_delete_path);
+ dir_fd = file_data_new_dir(options->file_ops.safe_delete_path);
if (!filelist_read(dir_fd, &list, NULL))
{
file_data_unref(dir_fd);
ViewDir *vd = data;
if (success)
{
- FileData *fd = file_data_new_simple(new_path);
+ FileData *fd = file_data_new_dir(new_path);
GtkTreeIter iter;
if (vd_find_row(vd, fd, &iter))
if (vd->select_func)
{
- FileData *fd = file_data_new_simple(path);
+ FileData *fd = file_data_new_dir(path);
vd->select_func(vd, fd, vd->select_data);
file_data_unref(fd);
}
break;
case DIRVIEW_TREE:
{
- FileData *new_fd = file_data_new_simple(new_path);
+ FileData *new_fd = file_data_new_dir(new_path);
fd = vdtree_populate_path(vd, new_fd, TRUE, TRUE);
file_data_unref(new_fd);
}
if (vd->type == DIRVIEW_TREE)
{
GtkTreeIter iter;
- FileData *base_fd = file_data_new_simple(base);
+ FileData *base_fd = file_data_new_dir(base);
if (vd_find_row(vd, base_fd, &iter))
{
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);
+ fd = file_data_new_dir(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);
+ fd = file_data_new_dir(filepath);
VDLIST(vd)->list = g_list_prepend(VDLIST(vd)->list, fd);
g_free(filepath);
}
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))
+ if (isdir(name8))
{
- list = g_list_prepend(list, file_data_new_simple(name8));
+ list = g_list_prepend(list, file_data_new_dir(name8));
}
g_free(name8);
FileData *fd;
- fd = file_data_new_simple(path);
+ fd = file_data_new_dir(path);
vdtree_add_by_data(vd, fd, NULL);
vdtree_expand_by_data(vd, fd, TRUE);