Mercurial > geeqie
annotate src/thumb_standard.c @ 40:dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
* pan-view.c: Add option to ignore symbolic links to folders when
creating file list (no gui control yet), and do not allow listing
the root folder as this introduces too many issues (for instance
how do we ignore special filesystems such as /proc using only stat
attributes?). Add fix to not show empty folders in the flower view.
* thumb_standard.c (thumb_loader_std_finish): Fix logic that caused
thumbnails to be saved for images with a size between normal and large
when using large thumbnails.
* ui_fileops.[ch]: Add utilities lstat_utf8 and islink.
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
##### an offical release when making enhancements and translation updates. #####
author | gqview |
---|---|
date | Sat, 16 Apr 2005 16:26:49 +0000 |
parents | 25335c62cd9b |
children | ee03f36e9e4b |
rev | line source |
---|---|
9 | 1 /* |
2 * GQview | |
3 * (C) 2005 John Ellis | |
4 * | |
5 * Author: John Ellis | |
6 * | |
7 * This software is released under the GNU General Public License (GNU GPL). | |
8 * Please read the included file COPYING for more information. | |
9 * This software comes with no warranty of any kind, use at your own risk! | |
10 */ | |
11 | |
12 | |
13 #include "gqview.h" | |
14 #include "thumb_standard.h" | |
15 | |
16 #include "cache.h" /* for cache_ensure_dir_exists */ | |
17 #include "image-load.h" | |
18 #include "md5-util.h" | |
19 #include "pixbuf_util.h" | |
20 #include "ui_fileops.h" | |
21 | |
22 | |
23 /* | |
24 * This thumbnail caching implementation attempts to conform | |
25 * to the Thumbnail Managing Standard proposed on freedesktop.org | |
26 * The standard is documented here: | |
27 * http://triq.net/~jens/thumbnail-spec/index.html | |
28 * (why isn't it actually hosted on freedesktop.org?) | |
29 * | |
30 * This code attempts to conform to version 0.7.0 of the standard. | |
31 * | |
32 * Notes: | |
33 * > Validation of the thumb's embedded uri is a simple strcmp between our | |
34 * version of the escaped uri and the thumb's escaped uri. But not all uri | |
35 * escape functions escape the same set of chars, comparing the unescaped | |
36 * versions may be more accurate. | |
37 * > Only Thumb::URI and Thumb::MTime are stored in a thumb at this time. | |
38 * Storing the Size, Width, Height should probably be implemented. | |
39 */ | |
40 | |
41 | |
42 #define THUMB_SIZE_NORMAL 128 | |
43 #define THUMB_SIZE_LARGE 256 | |
44 | |
45 #define THUMB_MARKER_URI "tEXt::Thumb::URI" | |
46 #define THUMB_MARKER_MTIME "tEXt::Thumb::MTime" | |
47 #define THUMB_MARKER_SIZE "tEXt::Thumb::Size" | |
48 #define THUMB_MARKER_WIDTH "tEXt::Thumb::Image::Width" | |
49 #define THUMB_MARKER_HEIGHT "tEXt::Thumb::Image::Height" | |
50 #define THUMB_MARKER_APP "tEXt::Software" | |
51 | |
52 #define THUMB_PERMS_FOLDER 0700 | |
53 #define THUMB_PERMS_THUMB 0600 | |
54 | |
55 | |
56 | |
57 /* | |
58 *----------------------------------------------------------------------------- | |
59 * thumbnail loader | |
60 *----------------------------------------------------------------------------- | |
61 */ | |
62 | |
63 | |
64 static void thumb_loader_std_error_cb(ImageLoader *il, gpointer data); | |
65 static gint thumb_loader_std_setup(ThumbLoaderStd *tl, const gchar *path); | |
66 | |
67 | |
68 ThumbLoaderStd *thumb_loader_std_new(gint width, gint height) | |
69 { | |
70 ThumbLoaderStd *tl; | |
71 | |
72 tl = g_new0(ThumbLoaderStd, 1); | |
73 | |
74 tl->standard_loader = TRUE; | |
75 | |
76 tl->requested_width = width; | |
77 tl->requested_height = height; | |
78 | |
79 tl->pixbuf = NULL; | |
80 tl->il = NULL; | |
81 tl->source_path = NULL; | |
82 | |
83 tl->cache_enable = enable_thumb_caching; | |
84 tl->cache_local = FALSE; | |
85 tl->cache_retry = FALSE; | |
86 | |
87 return tl; | |
88 } | |
89 | |
90 void thumb_loader_std_set_callbacks(ThumbLoaderStd *tl, | |
91 ThumbLoaderStdFunc func_done, | |
92 ThumbLoaderStdFunc func_error, | |
93 ThumbLoaderStdFunc func_progress, | |
94 gpointer data) | |
95 { | |
96 if (!tl) return; | |
97 | |
98 tl->func_done = func_done; | |
99 tl->func_error = func_error; | |
100 tl->func_progress = func_progress; | |
101 tl->data = data; | |
102 } | |
103 | |
104 static void thumb_loader_std_reset(ThumbLoaderStd *tl) | |
105 { | |
106 if (tl->pixbuf) g_object_unref(tl->pixbuf); | |
107 tl->pixbuf = NULL; | |
108 | |
109 image_loader_free(tl->il); | |
110 tl->il = NULL; | |
111 | |
112 g_free(tl->source_path); | |
113 tl->source_path = NULL; | |
114 | |
115 g_free(tl->thumb_path); | |
116 tl->thumb_path = NULL; | |
117 | |
118 g_free(tl->thumb_uri); | |
119 tl->thumb_uri = NULL; | |
120 tl->local_uri = NULL; | |
121 | |
122 tl->thumb_path_local = FALSE; | |
123 | |
124 tl->cache_hit = FALSE; | |
125 | |
126 tl->source_mtime = 0; | |
127 tl->source_size = 0; | |
128 tl->source_mode = 0; | |
129 | |
130 tl->progress = 0.0; | |
131 } | |
132 | |
133 static gchar *thumb_std_cache_path(const gchar *path, const gchar *uri, gint local, | |
134 const gchar *cache_subfolder) | |
135 { | |
136 gchar *result = NULL; | |
137 gchar *cache_base; | |
138 gchar *md5_text; | |
139 guchar digest[16]; | |
140 | |
141 if (!path || !uri || !cache_subfolder) return NULL; | |
142 | |
143 if (local) | |
144 { | |
145 gchar *base; | |
146 | |
147 base = remove_level_from_path(path); | |
148 cache_base = g_strconcat(base, "/", THUMB_FOLDER, "/", cache_subfolder, NULL); | |
149 g_free(base); | |
150 } | |
151 else | |
152 { | |
153 cache_base = g_strconcat(homedir(), "/", THUMB_FOLDER, "/", cache_subfolder, NULL); | |
154 } | |
155 | |
156 md5_get_digest(uri, strlen(uri), digest); | |
157 md5_text = md5_digest_to_text(digest); | |
158 | |
159 if (cache_base && md5_text) | |
160 { | |
161 result = g_strconcat(cache_base, "/", md5_text, THUMB_NAME_EXTENSION, NULL); | |
162 } | |
163 | |
164 g_free(cache_base); | |
165 g_free(md5_text); | |
166 | |
167 return result; | |
168 } | |
169 | |
170 static gchar *thumb_loader_std_cache_path(ThumbLoaderStd *tl, gint local, GdkPixbuf *pixbuf, gint fail) | |
171 { | |
172 #if 0 | |
173 gchar *result = NULL; | |
174 gchar *cache_base; | |
175 #endif | |
176 const gchar *folder_size; | |
177 #if 0 | |
178 const gchar *uri; | |
179 gchar *md5_text; | |
180 guchar digest[16]; | |
181 #endif | |
182 gint w, h; | |
183 | |
184 if (!tl->source_path || !tl->thumb_uri) return NULL; | |
185 | |
186 if (pixbuf) | |
187 { | |
188 w = gdk_pixbuf_get_width(pixbuf); | |
189 h = gdk_pixbuf_get_height(pixbuf); | |
190 } | |
191 else | |
192 { | |
193 w = tl->requested_width; | |
194 h = tl->requested_height; | |
195 } | |
196 | |
197 if (fail) | |
198 { | |
199 folder_size = THUMB_FOLDER_FAIL; | |
200 } | |
201 else if (w > THUMB_SIZE_NORMAL || h > THUMB_SIZE_NORMAL) | |
202 { | |
203 folder_size = THUMB_FOLDER_LARGE; | |
204 } | |
205 else | |
206 { | |
207 folder_size = THUMB_FOLDER_NORMAL; | |
208 } | |
209 | |
210 return thumb_std_cache_path(tl->source_path, | |
211 (local) ? tl->local_uri : tl->thumb_uri, | |
212 local, folder_size); | |
213 | |
214 #if 0 | |
215 if (local) | |
216 { | |
217 gchar *base; | |
218 | |
219 base = remove_level_from_path(tl->source_path); | |
220 cache_base = g_strconcat(base, "/", THUMB_FOLDER, "/", folder_size, NULL); | |
221 g_free(base); | |
222 } | |
223 else | |
224 { | |
225 cache_base = g_strconcat(homedir(), "/", THUMB_FOLDER, "/", folder_size, NULL); | |
226 } | |
227 | |
228 uri = (local) ? tl->local_uri : tl->thumb_uri; | |
229 md5_get_digest(uri, strlen(uri), digest); | |
230 md5_text = md5_digest_to_text(digest); | |
231 | |
232 if (cache_base && md5_text) | |
233 { | |
234 result = g_strconcat(cache_base, "/", md5_text, THUMB_NAME_EXTENSION, NULL); | |
235 } | |
236 | |
237 g_free(cache_base); | |
238 g_free(md5_text); | |
239 | |
240 return result; | |
241 #endif | |
242 } | |
243 | |
244 static gint thumb_loader_std_fail_check(ThumbLoaderStd *tl) | |
245 { | |
246 gchar *fail_path; | |
247 gint result = FALSE; | |
248 | |
249 fail_path = thumb_loader_std_cache_path(tl, FALSE, NULL, TRUE); | |
250 if (isfile(fail_path)) | |
251 { | |
252 GdkPixbuf *pixbuf; | |
253 | |
254 if (tl->cache_retry) | |
255 { | |
256 pixbuf = NULL; | |
257 } | |
258 else | |
259 { | |
260 gchar *pathl; | |
261 | |
262 pathl = path_from_utf8(fail_path); | |
263 pixbuf = gdk_pixbuf_new_from_file(pathl, NULL); | |
264 g_free(pathl); | |
265 } | |
266 | |
267 if (pixbuf) | |
268 { | |
269 const gchar *mtime_str; | |
270 | |
271 mtime_str = gdk_pixbuf_get_option(pixbuf, THUMB_MARKER_MTIME); | |
272 if (mtime_str && strtol(mtime_str, NULL, 10) == tl->source_mtime) | |
273 { | |
274 result = TRUE; | |
275 if (debug) | |
276 { | |
277 printf("thumb fail valid: %s\n", tl->source_path); | |
278 printf(" thumb: %s\n", fail_path); | |
279 } | |
280 } | |
281 | |
282 g_object_unref(G_OBJECT(pixbuf)); | |
283 } | |
284 | |
285 if (!result) unlink_file(fail_path); | |
286 } | |
287 g_free(fail_path); | |
288 | |
289 return result; | |
290 } | |
291 | |
292 static gint thumb_loader_std_validate(ThumbLoaderStd *tl, GdkPixbuf *pixbuf) | |
293 { | |
294 const gchar *valid_uri; | |
295 const gchar *uri; | |
296 const gchar *mtime_str; | |
297 time_t mtime; | |
298 gint w, h; | |
299 | |
300 if (!pixbuf) return FALSE; | |
301 | |
302 w = gdk_pixbuf_get_width(pixbuf); | |
303 h = gdk_pixbuf_get_height(pixbuf); | |
304 | |
305 if (w != THUMB_SIZE_NORMAL && w != THUMB_SIZE_LARGE && | |
306 h != THUMB_SIZE_NORMAL && h != THUMB_SIZE_LARGE) return FALSE; | |
307 | |
308 valid_uri = (tl->thumb_path_local) ? tl->local_uri : tl->thumb_uri; | |
309 | |
310 uri = gdk_pixbuf_get_option(pixbuf, THUMB_MARKER_URI); | |
311 mtime_str = gdk_pixbuf_get_option(pixbuf, THUMB_MARKER_MTIME); | |
312 | |
313 if (!mtime_str || !uri || !valid_uri) return FALSE; | |
314 if (strcmp(uri, valid_uri) != 0) return FALSE; | |
315 | |
316 mtime = strtol(mtime_str, NULL, 10); | |
317 if (tl->source_mtime != mtime) return FALSE; | |
318 | |
319 return TRUE; | |
320 } | |
321 | |
322 static void thumb_loader_std_save(ThumbLoaderStd *tl, GdkPixbuf *pixbuf) | |
323 { | |
324 gchar *base_path; | |
325 gchar *tmp_path; | |
326 gint fail; | |
327 | |
328 if (!tl->cache_enable || tl->cache_hit) return; | |
329 if (tl->thumb_path) return; | |
330 | |
331 if (!pixbuf) | |
332 { | |
333 /* local failures are not stored */ | |
334 if (tl->cache_local) return; | |
335 | |
336 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 1, 1); | |
337 fail = TRUE; | |
338 } | |
339 else | |
340 { | |
341 g_object_ref(G_OBJECT(pixbuf)); | |
342 fail = FALSE; | |
343 } | |
344 | |
345 tl->thumb_path = thumb_loader_std_cache_path(tl, tl->cache_local, pixbuf, fail); | |
346 if (!tl->thumb_path) | |
347 { | |
348 g_object_unref(G_OBJECT(pixbuf)); | |
349 return; | |
350 } | |
351 tl->thumb_path_local = tl->cache_local; | |
352 | |
353 /* create thumbnail dir if needed */ | |
354 base_path = remove_level_from_path(tl->thumb_path); | |
355 if (tl->cache_local) | |
356 { | |
357 if (!isdir(base_path)) | |
358 { | |
359 struct stat st; | |
360 gchar *source_base; | |
361 | |
362 source_base = remove_level_from_path(tl->source_path); | |
363 if (stat_utf8(source_base, &st)) | |
364 { | |
365 cache_ensure_dir_exists(base_path, st.st_mode); | |
366 } | |
367 g_free(source_base); | |
368 } | |
369 } | |
370 else | |
371 { | |
372 cache_ensure_dir_exists(base_path, THUMB_PERMS_FOLDER); | |
373 } | |
374 g_free(base_path); | |
375 | |
376 if (debug) | |
377 { | |
378 printf("thumb saving: %s\n", tl->source_path); | |
379 printf(" saved: %s\n", tl->thumb_path); | |
380 } | |
381 | |
382 /* save thumb, using a temp file then renaming into place */ | |
383 tmp_path = unique_filename(tl->thumb_path, ".tmp", "_", 2); | |
384 if (tmp_path) | |
385 { | |
386 const gchar *mark_uri; | |
387 gchar *mark_app; | |
388 gchar *mark_mtime; | |
389 gchar *pathl; | |
390 gint success; | |
391 | |
392 mark_uri = (tl->cache_local) ? tl->local_uri :tl->thumb_uri; | |
393 | |
394 mark_app = g_strdup_printf("GQview %s", VERSION); | |
395 mark_mtime = g_strdup_printf("%lu", tl->source_mtime); | |
396 | |
397 pathl = path_from_utf8(tmp_path); | |
398 success = gdk_pixbuf_save(pixbuf, pathl, "png", NULL, | |
399 THUMB_MARKER_URI, mark_uri, | |
400 THUMB_MARKER_MTIME, mark_mtime, | |
401 THUMB_MARKER_APP, mark_app, | |
402 NULL); | |
403 if (success) | |
404 { | |
405 chmod(pathl, (tl->cache_local) ? tl->source_mode : THUMB_PERMS_THUMB); | |
406 success = rename_file(tmp_path, tl->thumb_path); | |
407 } | |
408 | |
409 g_free(pathl); | |
410 | |
411 g_free(mark_mtime); | |
412 g_free(mark_app); | |
413 | |
414 g_free(tmp_path); | |
415 if (!success && debug) | |
416 { | |
417 printf("thumb save failed: %s\n", tl->source_path); | |
418 printf(" thumb: %s\n", tl->thumb_path); | |
419 } | |
420 | |
421 } | |
422 | |
423 g_object_unref(G_OBJECT(pixbuf)); | |
424 } | |
425 | |
426 static gint thumb_loader_std_scale_aspect(gint req_w, gint req_h, gint old_w, gint old_h, | |
427 gint *new_w, gint *new_h) | |
428 { | |
429 if (((gdouble)req_w / old_w) < ((gdouble)req_h / old_h)) | |
430 { | |
431 *new_w = req_w; | |
432 *new_h = (gdouble)*new_w / old_w * old_h; | |
433 if (*new_h < 1) *new_h = 1; | |
434 } | |
435 else | |
436 { | |
437 *new_h = req_h; | |
438 *new_w = (gdouble)*new_h / old_h * old_w; | |
439 if (*new_w < 1) *new_w = 1; | |
440 } | |
441 | |
442 return (*new_w != old_w || *new_h != old_h); | |
443 } | |
444 | |
14
25335c62cd9b
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
445 static GdkPixbuf *thumb_loader_std_finish(ThumbLoaderStd *tl, GdkPixbuf *pixbuf, gint shrunk) |
9 | 446 { |
447 GdkPixbuf *pixbuf_thumb = NULL; | |
448 GdkPixbuf *result; | |
449 gint sw, sh; | |
450 | |
451 sw = gdk_pixbuf_get_width(pixbuf); | |
452 sh = gdk_pixbuf_get_height(pixbuf); | |
453 | |
40
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
454 if (tl->cache_enable) |
9 | 455 { |
40
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
456 if (!tl->cache_hit) |
9 | 457 { |
40
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
458 gint cache_w, cache_h; |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
459 |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
460 if (tl->requested_width > THUMB_SIZE_NORMAL || tl->requested_height > THUMB_SIZE_NORMAL) |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
461 { |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
462 cache_w = cache_h = THUMB_SIZE_LARGE; |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
463 } |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
464 else |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
465 { |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
466 cache_w = cache_h = THUMB_SIZE_NORMAL; |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
467 } |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
468 |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
469 if (sw > cache_w || sh > cache_h || shrunk) |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
470 { |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
471 gint thumb_w, thumb_h; |
9 | 472 |
40
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
473 if (thumb_loader_std_scale_aspect(cache_w, cache_h, sw, sh, |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
474 &thumb_w, &thumb_h)) |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
475 { |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
476 pixbuf_thumb = gdk_pixbuf_scale_simple(pixbuf, thumb_w, thumb_h, |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
477 (GdkInterpType)thumbnail_quality); |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
478 } |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
479 else |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
480 { |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
481 pixbuf_thumb = pixbuf; |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
482 g_object_ref(G_OBJECT(pixbuf_thumb)); |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
483 } |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
484 |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
485 thumb_loader_std_save(tl, pixbuf_thumb); |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
486 } |
9 | 487 } |
40
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
488 else if (tl->cache_hit && |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
489 tl->cache_local && !tl->thumb_path_local) |
9 | 490 { |
40
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
491 /* A local cache save was requested, but a valid thumb is in $HOME, |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
492 * so specifically save as a local thumbnail. |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
493 */ |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
494 g_free(tl->thumb_path); |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
495 tl->thumb_path = NULL; |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
496 |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
497 tl->cache_hit = FALSE; |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
498 |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
499 if (debug) printf("thumb copied: %s\n", tl->source_path); |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
500 |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
501 thumb_loader_std_save(tl, pixbuf); |
9 | 502 } |
503 } | |
504 | |
505 if (sw <= tl->requested_width && sh <= tl->requested_height) | |
506 { | |
507 result = pixbuf; | |
508 g_object_ref(result); | |
509 } | |
510 else | |
511 { | |
512 gint thumb_w, thumb_h; | |
513 | |
514 if (pixbuf_thumb) | |
515 { | |
516 pixbuf = pixbuf_thumb; | |
517 sw = gdk_pixbuf_get_width(pixbuf); | |
518 sh = gdk_pixbuf_get_height(pixbuf); | |
519 } | |
520 | |
521 if (thumb_loader_std_scale_aspect(tl->requested_width, tl->requested_height, sw, sh, | |
522 &thumb_w, &thumb_h)) | |
523 { | |
524 result = gdk_pixbuf_scale_simple(pixbuf, thumb_w, thumb_h, | |
525 (GdkInterpType)thumbnail_quality); | |
526 } | |
527 else | |
528 { | |
529 result = pixbuf; | |
530 g_object_ref(result); | |
531 } | |
532 } | |
533 | |
534 if (pixbuf_thumb) g_object_unref(pixbuf_thumb); | |
535 | |
536 return result; | |
537 } | |
538 | |
539 static gint thumb_loader_std_next_source(ThumbLoaderStd *tl, gint remove_broken) | |
540 { | |
541 image_loader_free(tl->il); | |
542 tl->il = NULL; | |
543 | |
544 if (tl->thumb_path) | |
545 { | |
546 if (!tl->thumb_path_local && remove_broken) | |
547 { | |
548 if (debug) printf("thumb broken, unlinking: %s\n", tl->thumb_path); | |
549 unlink_file(tl->thumb_path); | |
550 } | |
551 | |
552 g_free(tl->thumb_path); | |
553 tl->thumb_path = NULL; | |
554 | |
555 if (!tl->thumb_path_local) | |
556 { | |
557 tl->thumb_path = thumb_loader_std_cache_path(tl, TRUE, NULL, FALSE); | |
558 if (isfile(tl->thumb_path) && thumb_loader_std_setup(tl, tl->thumb_path)) | |
559 { | |
560 tl->thumb_path_local = TRUE; | |
561 return TRUE; | |
562 } | |
563 | |
564 g_free(tl->thumb_path); | |
565 tl->thumb_path = NULL; | |
566 } | |
567 | |
568 if (thumb_loader_std_setup(tl, tl->source_path)) return TRUE; | |
569 } | |
570 | |
571 thumb_loader_std_save(tl, NULL); | |
572 return FALSE; | |
573 } | |
574 | |
575 static void thumb_loader_std_done_cb(ImageLoader *il, gpointer data) | |
576 { | |
577 ThumbLoaderStd *tl = data; | |
578 GdkPixbuf *pixbuf; | |
579 | |
580 if (debug) | |
581 { | |
582 printf("thumb image done: %s\n", tl->source_path); | |
583 printf(" from: %s\n", tl->il->path); | |
584 } | |
585 | |
586 pixbuf = image_loader_get_pixbuf(tl->il); | |
587 if (!pixbuf) | |
588 { | |
589 if (debug) printf("...but no pixbuf\n"); | |
590 thumb_loader_std_error_cb(il, data); | |
591 return; | |
592 } | |
593 | |
594 if (tl->thumb_path && !thumb_loader_std_validate(tl, pixbuf)) | |
595 { | |
596 if (thumb_loader_std_next_source(tl, TRUE)) return; | |
597 | |
598 if (tl->func_error) tl->func_error(tl, tl->data); | |
599 return; | |
600 } | |
601 | |
602 tl->cache_hit = (tl->thumb_path != NULL); | |
603 | |
14
25335c62cd9b
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
604 tl->pixbuf = thumb_loader_std_finish(tl, pixbuf, il->shrunk); |
9 | 605 |
606 if (tl->func_done) tl->func_done(tl, tl->data); | |
607 } | |
608 | |
609 static void thumb_loader_std_error_cb(ImageLoader *il, gpointer data) | |
610 { | |
611 ThumbLoaderStd *tl = data; | |
612 | |
613 /* if at least some of the image is available, go to done */ | |
614 if (image_loader_get_pixbuf(tl->il) != NULL) | |
615 { | |
616 thumb_loader_std_done_cb(il, data); | |
617 return; | |
618 } | |
619 | |
620 if (debug) | |
621 { | |
622 printf("thumb image error: %s\n", tl->source_path); | |
623 printf(" from: %s\n", tl->il->path); | |
624 } | |
625 | |
626 if (thumb_loader_std_next_source(tl, TRUE)) return; | |
627 | |
628 if (tl->func_error) tl->func_error(tl, tl->data); | |
629 } | |
630 | |
631 static void thumb_loader_std_progress_cb(ImageLoader *il, gdouble percent, gpointer data) | |
632 { | |
633 ThumbLoaderStd *tl = data; | |
634 | |
635 tl->progress = (gdouble)percent; | |
636 | |
637 if (tl->func_progress) tl->func_progress(tl, tl->data); | |
638 } | |
639 | |
640 static gint thumb_loader_std_setup(ThumbLoaderStd *tl, const gchar *path) | |
641 { | |
642 tl->il = image_loader_new(path); | |
643 | |
14
25335c62cd9b
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
644 if (thumbnail_fast) |
9 | 645 { |
14
25335c62cd9b
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
646 /* this will speed up jpegs by up to 3x in some cases */ |
25335c62cd9b
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
647 if (tl->requested_width <= THUMB_SIZE_NORMAL && |
25335c62cd9b
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
648 tl->requested_height <= THUMB_SIZE_NORMAL) |
25335c62cd9b
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
649 { |
25335c62cd9b
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
650 image_loader_set_requested_size(tl->il, THUMB_SIZE_NORMAL, THUMB_SIZE_NORMAL); |
25335c62cd9b
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
651 } |
25335c62cd9b
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
652 else |
25335c62cd9b
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
653 { |
25335c62cd9b
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
654 image_loader_set_requested_size(tl->il, THUMB_SIZE_LARGE, THUMB_SIZE_LARGE); |
25335c62cd9b
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
655 } |
9 | 656 } |
657 | |
658 image_loader_set_error_func(tl->il, thumb_loader_std_error_cb, tl); | |
659 if (tl->func_progress) | |
660 { | |
661 image_loader_set_percent_func(tl->il, thumb_loader_std_progress_cb, tl); | |
662 } | |
663 | |
664 if (image_loader_start(tl->il, thumb_loader_std_done_cb, tl)) | |
665 { | |
666 return TRUE; | |
667 } | |
668 | |
669 image_loader_free(tl->il); | |
670 tl->il = NULL; | |
671 return FALSE; | |
672 } | |
673 | |
674 /* | |
675 * Note: Currently local_cache only specifies where to save a _new_ thumb, if | |
676 * a valid existing thumb is found anywhere the local thumb will not be created. | |
677 */ | |
678 void thumb_loader_std_set_cache(ThumbLoaderStd *tl, gint enable_cache, gint local, gint retry_failed) | |
679 { | |
680 if (!tl) return; | |
681 | |
682 tl->cache_enable = enable_cache; | |
683 tl->cache_local = local; | |
684 tl->cache_retry = retry_failed; | |
685 } | |
686 | |
687 gint thumb_loader_std_start(ThumbLoaderStd *tl, const gchar *path) | |
688 { | |
689 static gchar *thumb_cache = NULL; | |
690 struct stat st; | |
691 | |
692 if (!tl || !path) return FALSE; | |
693 | |
694 thumb_loader_std_reset(tl); | |
695 | |
696 if (!stat_utf8(path, &st)) return FALSE; | |
697 | |
698 tl->source_path = g_strdup(path); | |
699 tl->source_mtime = st.st_mtime; | |
700 tl->source_size = st.st_size; | |
701 tl->source_mode = st.st_mode; | |
702 | |
703 if (!thumb_cache) thumb_cache = g_strconcat(homedir(), "/", THUMB_FOLDER, NULL); | |
704 if (strncmp(tl->source_path, thumb_cache, strlen(thumb_cache)) != 0) | |
705 { | |
706 gchar *pathl; | |
707 | |
708 pathl = path_from_utf8(path); | |
709 tl->thumb_uri = g_filename_to_uri(pathl, NULL, NULL); | |
710 tl->local_uri = filename_from_path(tl->thumb_uri); | |
711 g_free(pathl); | |
712 } | |
713 | |
714 if (tl->cache_enable) | |
715 { | |
716 gint found; | |
717 | |
718 if (thumb_loader_std_fail_check(tl)) return FALSE; | |
719 | |
720 tl->thumb_path = thumb_loader_std_cache_path(tl, FALSE, NULL, FALSE); | |
721 tl->thumb_path_local = FALSE; | |
722 | |
723 found = isfile(tl->thumb_path); | |
724 if (found && thumb_loader_std_setup(tl, tl->thumb_path)) return TRUE; | |
725 | |
726 return thumb_loader_std_next_source(tl, found); | |
727 } | |
728 | |
729 if (!thumb_loader_std_setup(tl, tl->source_path)) | |
730 { | |
731 thumb_loader_std_save(tl, NULL); | |
732 return FALSE; | |
733 } | |
734 | |
735 return TRUE; | |
736 } | |
737 | |
738 void thumb_loader_std_free(ThumbLoaderStd *tl) | |
739 { | |
740 if (!tl) return; | |
741 | |
742 thumb_loader_std_reset(tl); | |
743 g_free(tl); | |
744 } | |
745 | |
746 GdkPixbuf *thumb_loader_std_get_pixbuf(ThumbLoaderStd *tl, gint with_fallback) | |
747 { | |
748 GdkPixbuf *pixbuf; | |
749 | |
750 if (tl && tl->pixbuf) | |
751 { | |
752 pixbuf = tl->pixbuf; | |
753 g_object_ref(pixbuf); | |
754 } | |
755 else if (with_fallback) | |
756 { | |
757 gint w, h; | |
758 | |
759 pixbuf = pixbuf_inline(PIXBUF_INLINE_BROKEN); | |
760 w = gdk_pixbuf_get_width(pixbuf); | |
761 h = gdk_pixbuf_get_height(pixbuf); | |
762 | |
763 if (w > tl->requested_width || h > tl->requested_height) | |
764 { | |
765 gint nw, nh; | |
766 | |
767 if (thumb_loader_std_scale_aspect(tl->requested_width, tl->requested_height, | |
768 w, h, &nw, &nh)) | |
769 { | |
770 GdkPixbuf *tmp; | |
771 | |
772 tmp = pixbuf; | |
773 pixbuf = gdk_pixbuf_scale_simple(tmp, nw, nh, GDK_INTERP_TILES); | |
774 g_object_unref(G_OBJECT(tmp)); | |
775 } | |
776 } | |
777 } | |
778 else | |
779 { | |
780 pixbuf = NULL; | |
781 } | |
782 | |
783 return pixbuf; | |
784 } | |
785 | |
786 | |
787 typedef struct _ThumbValidate ThumbValidate; | |
788 struct _ThumbValidate | |
789 { | |
790 ThumbLoaderStd *tl; | |
791 gchar *path; | |
792 gint days; | |
793 | |
794 void (*func_valid)(const gchar *path, gint valid, gpointer data); | |
795 gpointer data; | |
796 | |
797 gint idle_id; | |
798 }; | |
799 | |
800 static void thumb_loader_std_thumb_file_validate_free(ThumbValidate *tv) | |
801 { | |
802 thumb_loader_std_free(tv->tl); | |
803 g_free(tv->path); | |
804 g_free(tv); | |
805 } | |
806 | |
807 void thumb_loader_std_thumb_file_validate_cancel(ThumbLoaderStd *tl) | |
808 { | |
809 ThumbValidate *tv; | |
810 | |
811 if (!tl) return; | |
812 | |
813 tv = tl->data; | |
814 | |
815 if (tv->idle_id != -1) g_source_remove(tv->idle_id); | |
816 tv->idle_id = -1; | |
817 | |
818 thumb_loader_std_thumb_file_validate_free(tv); | |
819 } | |
820 | |
821 static void thumb_loader_std_thumb_file_validate_finish(ThumbValidate *tv, gint valid) | |
822 { | |
823 if (tv->func_valid) tv->func_valid(tv->path, valid, tv->data); | |
824 | |
825 thumb_loader_std_thumb_file_validate_free(tv); | |
826 } | |
827 | |
828 static void thumb_loader_std_thumb_file_validate_done_cb(ThumbLoaderStd *tl, gpointer data) | |
829 { | |
830 ThumbValidate *tv = data; | |
831 GdkPixbuf *pixbuf; | |
832 gint valid = FALSE; | |
833 | |
834 pixbuf = thumb_loader_std_get_pixbuf(tv->tl, FALSE); | |
835 if (pixbuf) | |
836 { | |
837 const gchar *uri; | |
838 const gchar *mtime_str; | |
839 | |
840 uri = gdk_pixbuf_get_option(pixbuf, THUMB_MARKER_URI); | |
841 mtime_str = gdk_pixbuf_get_option(pixbuf, THUMB_MARKER_MTIME); | |
842 if (uri && mtime_str) | |
843 { | |
844 if (strncmp(uri, "file:", strlen("file:")) == 0) | |
845 { | |
846 struct stat st; | |
847 gchar *target; | |
848 | |
849 target = g_filename_from_uri(uri, NULL, NULL); | |
850 if (stat(target, &st) == 0 && | |
851 st.st_mtime == strtol(mtime_str, NULL, 10)) | |
852 { | |
853 valid = TRUE; | |
854 } | |
855 g_free(target); | |
856 } | |
857 else | |
858 { | |
859 struct stat st; | |
860 | |
861 if (debug) printf("thumb uri foreign, doing day check: %s\n", uri); | |
862 | |
863 if (stat_utf8(tv->path, &st)) | |
864 { | |
865 time_t now; | |
866 | |
867 now = time(NULL); | |
868 if (st.st_atime >= now - (time_t)tv->days * 24 * 60 * 60) | |
869 { | |
870 valid = TRUE; | |
871 } | |
872 } | |
873 } | |
874 } | |
875 | |
876 g_object_unref(pixbuf); | |
877 } | |
878 | |
879 thumb_loader_std_thumb_file_validate_finish(tv, valid); | |
880 } | |
881 | |
882 static void thumb_loader_std_thumb_file_validate_error_cb(ThumbLoaderStd *tl, gpointer data) | |
883 { | |
884 ThumbValidate *tv = data; | |
885 | |
886 thumb_loader_std_thumb_file_validate_finish(tv, FALSE); | |
887 } | |
888 | |
889 static gint thumb_loader_std_thumb_file_validate_idle_cb(gpointer data) | |
890 { | |
891 ThumbValidate *tv = data; | |
892 | |
893 tv->idle_id = -1; | |
894 thumb_loader_std_thumb_file_validate_finish(tv, FALSE); | |
895 | |
896 return FALSE; | |
897 } | |
898 | |
899 ThumbLoaderStd *thumb_loader_std_thumb_file_validate(const gchar *thumb_path, gint allowed_days, | |
900 void (*func_valid)(const gchar *path, gint valid, gpointer data), | |
901 gpointer data) | |
902 { | |
903 ThumbValidate *tv; | |
904 | |
905 tv = g_new0(ThumbValidate, 1); | |
906 | |
907 tv->tl = thumb_loader_std_new(THUMB_SIZE_LARGE, THUMB_SIZE_LARGE); | |
908 thumb_loader_std_set_callbacks(tv->tl, | |
909 thumb_loader_std_thumb_file_validate_done_cb, | |
910 thumb_loader_std_thumb_file_validate_error_cb, | |
911 NULL, | |
912 tv); | |
913 thumb_loader_std_reset(tv->tl); | |
914 | |
915 tv->path = g_strdup(thumb_path); | |
916 tv->days = allowed_days; | |
917 tv->func_valid = func_valid; | |
918 tv->data = data; | |
919 | |
920 if (!thumb_loader_std_setup(tv->tl, thumb_path)) | |
921 { | |
922 tv->idle_id = g_idle_add(thumb_loader_std_thumb_file_validate_idle_cb, tv); | |
923 } | |
924 else | |
925 { | |
926 tv->idle_id = -1; | |
927 } | |
928 | |
929 return tv->tl; | |
930 } | |
931 | |
932 static void thumb_std_maint_remove_one(const gchar *source, const gchar *uri, gint local, | |
933 const gchar *subfolder) | |
934 { | |
935 gchar *thumb_path; | |
936 | |
937 thumb_path = thumb_std_cache_path(source, | |
938 (local) ? filename_from_path(uri) : uri, | |
939 local, subfolder); | |
940 if (isfile(thumb_path)) | |
941 { | |
942 if (debug) printf("thumb removing: %s\n", thumb_path); | |
943 unlink_file(thumb_path); | |
944 } | |
945 g_free(thumb_path); | |
946 } | |
947 | |
948 /* this also removes local thumbnails (the source is gone so it makes sense) */ | |
949 void thumb_std_maint_removed(const gchar *source) | |
950 { | |
951 gchar *uri; | |
952 gchar *sourcel; | |
953 | |
954 sourcel = path_from_utf8(source); | |
955 uri = g_filename_to_uri(sourcel, NULL, NULL); | |
956 g_free(sourcel); | |
957 | |
958 /* all this to remove a thumbnail? */ | |
959 | |
960 thumb_std_maint_remove_one(source, uri, FALSE, THUMB_FOLDER_NORMAL); | |
961 thumb_std_maint_remove_one(source, uri, FALSE, THUMB_FOLDER_LARGE); | |
962 thumb_std_maint_remove_one(source, uri, FALSE, THUMB_FOLDER_FAIL); | |
963 thumb_std_maint_remove_one(source, uri, TRUE, THUMB_FOLDER_NORMAL); | |
964 thumb_std_maint_remove_one(source, uri, TRUE, THUMB_FOLDER_LARGE); | |
965 | |
966 g_free(uri); | |
967 } | |
968 | |
969 typedef struct _TMaintMove TMaintMove; | |
970 struct _TMaintMove | |
971 { | |
972 gchar *source; | |
973 gchar *dest; | |
974 | |
975 ThumbLoaderStd *tl; | |
976 gchar *source_uri; | |
977 gchar *thumb_path; | |
978 | |
979 gint pass; | |
980 }; | |
981 | |
982 static GList *thumb_std_maint_move_list = NULL; | |
983 static GList *thumb_std_maint_move_tail = NULL; | |
984 | |
985 | |
986 static void thumb_std_maint_move_step(TMaintMove *tm); | |
987 static gint thumb_std_maint_move_idle(gpointer data); | |
988 | |
989 | |
990 static void thumb_std_maint_move_validate_cb(const gchar *path, gint valid, gpointer data) | |
991 { | |
992 TMaintMove *tm = data; | |
993 GdkPixbuf *pixbuf; | |
994 | |
995 pixbuf = thumb_loader_std_get_pixbuf(tm->tl, FALSE); | |
996 if (pixbuf) | |
997 { | |
998 const gchar *uri; | |
999 const gchar *mtime_str; | |
1000 | |
1001 uri = gdk_pixbuf_get_option(pixbuf, THUMB_MARKER_URI); | |
1002 mtime_str = gdk_pixbuf_get_option(pixbuf, THUMB_MARKER_MTIME); | |
1003 | |
1004 if (uri && mtime_str && strcmp(uri, tm->source_uri) == 0) | |
1005 { | |
1006 gchar *pathl; | |
1007 | |
1008 /* The validation utility abuses ThumbLoader, and we | |
1009 * abuse the utility just to load the thumbnail, | |
1010 * but the loader needs to look sane for the save to complete. | |
1011 */ | |
1012 | |
1013 tm->tl->cache_enable = TRUE; | |
1014 tm->tl->cache_hit = FALSE; | |
1015 tm->tl->cache_local = FALSE; | |
1016 | |
1017 g_free(tm->tl->source_path); | |
1018 tm->tl->source_path = g_strdup(tm->dest); | |
1019 tm->tl->source_mtime = strtol(mtime_str, NULL, 10); | |
1020 | |
1021 pathl = path_from_utf8(tm->tl->source_path); | |
1022 g_free(tm->tl->thumb_uri); | |
1023 tm->tl->thumb_uri = g_filename_to_uri(pathl, NULL, NULL); | |
1024 tm->tl->local_uri = filename_from_path(tm->tl->thumb_uri); | |
1025 g_free(pathl); | |
1026 | |
1027 g_free(tm->tl->thumb_path); | |
1028 tm->tl->thumb_path = NULL; | |
1029 tm->tl->thumb_path_local = FALSE; | |
1030 | |
1031 if (debug) printf("thumb move attempting save:\n"); | |
1032 | |
1033 thumb_loader_std_save(tm->tl, pixbuf); | |
1034 } | |
1035 | |
1036 if (debug) printf("thumb move unlink: %s\n", tm->thumb_path); | |
1037 unlink_file(tm->thumb_path); | |
1038 } | |
1039 | |
1040 thumb_std_maint_move_step(tm); | |
1041 } | |
1042 | |
1043 static void thumb_std_maint_move_step(TMaintMove *tm) | |
1044 { | |
1045 const gchar *folder; | |
1046 | |
1047 tm->pass++; | |
1048 if (tm->pass > 2) | |
1049 { | |
1050 g_free(tm->source); | |
1051 g_free(tm->dest); | |
1052 g_free(tm->source_uri); | |
1053 g_free(tm->thumb_path); | |
1054 g_free(tm); | |
1055 | |
1056 if (thumb_std_maint_move_list) | |
1057 { | |
1058 g_idle_add_full(G_PRIORITY_LOW, thumb_std_maint_move_idle, NULL, NULL); | |
1059 } | |
1060 | |
1061 return; | |
1062 } | |
1063 | |
1064 folder = (tm->pass == 1) ? THUMB_FOLDER_NORMAL : THUMB_FOLDER_LARGE; | |
1065 | |
1066 g_free(tm->thumb_path); | |
1067 tm->thumb_path = thumb_std_cache_path(tm->source, tm->source_uri, FALSE, folder); | |
1068 tm->tl = thumb_loader_std_thumb_file_validate(tm->thumb_path, 0, | |
1069 thumb_std_maint_move_validate_cb, tm); | |
1070 } | |
1071 | |
1072 static gint thumb_std_maint_move_idle(gpointer data) | |
1073 { | |
1074 TMaintMove *tm; | |
1075 gchar *pathl; | |
1076 | |
1077 if (!thumb_std_maint_move_list) return FALSE; | |
1078 | |
1079 tm = thumb_std_maint_move_list->data; | |
1080 | |
1081 thumb_std_maint_move_list = g_list_remove(thumb_std_maint_move_list, tm); | |
1082 if (!thumb_std_maint_move_list) thumb_std_maint_move_tail = NULL; | |
1083 | |
1084 pathl = path_from_utf8(tm->source); | |
1085 tm->source_uri = g_filename_to_uri(pathl, NULL, NULL); | |
1086 g_free(pathl); | |
1087 | |
1088 tm->pass = 0; | |
1089 | |
1090 thumb_std_maint_move_step(tm); | |
1091 | |
1092 return FALSE; | |
1093 } | |
1094 | |
1095 /* This will schedule a move of the thumbnail for source image to dest when idle. | |
1096 * We do this so that file renaming or moving speed is not sacrificed by | |
1097 * moving the thumbnails at the same time because: | |
1098 * | |
1099 * This cache design requires the tedious task of loading the png thumbnails and saving them. | |
1100 * | |
1101 * The thumbnails are processed when the app is idle. If the app | |
1102 * exits early well too bad - they can simply be regenerated from scratch. | |
1103 * | |
1104 * This does not manage local thumbnails (fixme ?) | |
1105 */ | |
1106 void thumb_std_maint_moved(const gchar *source, const gchar *dest) | |
1107 { | |
1108 TMaintMove *tm; | |
1109 | |
1110 tm = g_new0(TMaintMove, 1); | |
1111 tm->source = g_strdup(source); | |
1112 tm->dest = g_strdup(dest); | |
1113 | |
1114 if (!thumb_std_maint_move_list) | |
1115 { | |
1116 g_idle_add_full(G_PRIORITY_LOW, thumb_std_maint_move_idle, NULL, NULL); | |
1117 } | |
1118 | |
1119 if (thumb_std_maint_move_tail) | |
1120 { | |
1121 g_list_append(thumb_std_maint_move_tail, tm); | |
1122 thumb_std_maint_move_tail = thumb_std_maint_move_tail->next; | |
1123 } | |
1124 else | |
1125 { | |
1126 thumb_std_maint_move_list = g_list_append(thumb_std_maint_move_list, tm); | |
1127 thumb_std_maint_move_tail = thumb_std_maint_move_list; | |
1128 } | |
1129 } | |
1130 | |
1131 |