Mercurial > geeqie
annotate src/collect-io.c @ 362:c5d5ebcc1e50
collection_load(): increase verbosity in debug mode.
author | zas_ |
---|---|
date | Mon, 14 Apr 2008 22:57:26 +0000 |
parents | e0295af4f716 |
children | 5b8617c3821c |
rev | line source |
---|---|
9 | 1 /* |
196 | 2 * Geeqie |
9 | 3 * (C) 2004 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 | |
281 | 13 #include "main.h" |
9 | 14 #include "collect-io.h" |
15 | |
16 #include "collect.h" | |
312 | 17 #include "filelist.h" |
9 | 18 #include "layout_util.h" |
19 #include "rcfile.h" | |
312 | 20 #include "secure_save.h" |
9 | 21 #include "thumb.h" |
22 #include "ui_fileops.h" | |
23 | |
24 | |
288
d1f74154463e
Replace occurences of Geeqie / geeqie by constants defined in main.h.
zas_
parents:
283
diff
changeset
|
25 #define GQ_COLLECTION_MARKER "#" GQ_APPNAME |
9 | 26 |
283 | 27 #define GQ_COLLECTION_FAIL_MIN 300 |
28 #define GQ_COLLECTION_FAIL_PERCENT 98 | |
360
822040a51249
Increase collection_load() buffer size and do not activate
zas_
parents:
359
diff
changeset
|
29 #define GQ_COLLECTION_READ_BUFSIZE 4096 |
9 | 30 |
138 | 31 typedef struct _CollectManagerEntry CollectManagerEntry; |
9 | 32 |
33 static void collection_load_thumb_step(CollectionData *cd); | |
138 | 34 static gint collection_save_private(CollectionData *cd, const gchar *path); |
35 | |
36 static CollectManagerEntry *collect_manager_get_entry(const gchar *path); | |
37 static void collect_manager_entry_reset(CollectManagerEntry *entry); | |
235 | 38 static gint collect_manager_process_action(CollectManagerEntry *entry, gchar **path_ptr); |
9 | 39 |
40 | |
41 static gint scan_geometry(gchar *buffer, gint *x, gint *y, gint *w, gint *h) | |
42 { | |
43 gint nx, ny, nw, nh; | |
44 | |
45 if(sscanf(buffer, "%d %d %d %d", &nx, &ny, &nw, &nh) != 4) return FALSE; | |
46 | |
47 *x = nx; | |
48 *y = ny; | |
49 *w = nw; | |
50 *h = nh; | |
51 | |
52 return TRUE; | |
53 } | |
54 | |
358 | 55 static gint collection_load_private(CollectionData *cd, const gchar *path, CollectionLoadFlags flags) |
9 | 56 { |
360
822040a51249
Increase collection_load() buffer size and do not activate
zas_
parents:
359
diff
changeset
|
57 gchar s_buf[GQ_COLLECTION_READ_BUFSIZE]; |
9 | 58 FILE *f; |
59 gchar *pathl; | |
361
e0295af4f716
collection_load(): replace official by limit_failures (and
zas_
parents:
360
diff
changeset
|
60 gint limit_failures = TRUE; |
9 | 61 gint success = TRUE; |
62 guint total = 0; | |
63 guint fail = 0; | |
138 | 64 gboolean changed = FALSE; |
65 CollectManagerEntry *entry = NULL; | |
358 | 66 guint flush = flags & COLLECTION_LOAD_FLUSH; |
67 guint append = flags & COLLECTION_LOAD_APPEND; | |
359
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
68 guint only_geometry = flags & COLLECTION_LOAD_GEOMETRY; |
9 | 69 |
359
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
70 if (!only_geometry) |
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
71 { |
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
72 collection_load_stop(cd); |
9 | 73 |
359
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
74 if (flush) |
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
75 collect_manager_flush(); |
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
76 else |
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
77 entry = collect_manager_get_entry(path); |
9 | 78 |
359
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
79 if (!append) |
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
80 { |
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
81 collection_list_free(cd->list); |
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
82 cd->list = NULL; |
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
83 } |
9 | 84 } |
85 | |
86 if (!path && !cd->path) return FALSE; | |
87 | |
88 if (!path) path = cd->path; | |
360
822040a51249
Increase collection_load() buffer size and do not activate
zas_
parents:
359
diff
changeset
|
89 |
822040a51249
Increase collection_load() buffer size and do not activate
zas_
parents:
359
diff
changeset
|
90 if (debug) printf("collection load: append=%d flush=%d only_geometry=%d path=%s\n", |
822040a51249
Increase collection_load() buffer size and do not activate
zas_
parents:
359
diff
changeset
|
91 append, flush, only_geometry, path); |
9 | 92 |
93 /* load it */ | |
94 pathl = path_from_utf8(path); | |
95 f = fopen(pathl, "r"); | |
96 g_free(pathl); | |
97 if (!f) | |
98 { | |
99 printf("Failed to open collection file: \"%s\"\n", path); | |
100 return FALSE; | |
101 } | |
102 | |
103 while (fgets(s_buf, sizeof(s_buf), f)) | |
104 { | |
105 gchar *buf; | |
106 if (s_buf[0]=='#') | |
107 { | |
283 | 108 if (strncasecmp(s_buf, GQ_COLLECTION_MARKER, strlen(GQ_COLLECTION_MARKER)) == 0) |
9 | 109 { |
110 /* Looks like an official collection, allow unchecked input. | |
111 * All this does is allow adding files that may not exist, | |
112 * which is needed for the collection manager to work. | |
113 * Also unofficial files abort after too many invalid entries. | |
114 */ | |
361
e0295af4f716
collection_load(): replace official by limit_failures (and
zas_
parents:
360
diff
changeset
|
115 limit_failures = FALSE; |
9 | 116 } |
117 else if (strncmp(s_buf, "#geometry:", 10 ) == 0 && | |
118 scan_geometry(s_buf + 10, &cd->window_x, &cd->window_y, &cd->window_w, &cd->window_h) ) | |
119 { | |
120 cd->window_read = TRUE; | |
359
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
121 if (only_geometry) |
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
122 { |
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
123 fclose(f); |
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
124 return TRUE; |
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
125 } |
9 | 126 } |
360
822040a51249
Increase collection_load() buffer size and do not activate
zas_
parents:
359
diff
changeset
|
127 else if (strncasecmp(s_buf, "GQview collection", strlen("GQview collection")) == 0) |
822040a51249
Increase collection_load() buffer size and do not activate
zas_
parents:
359
diff
changeset
|
128 { |
822040a51249
Increase collection_load() buffer size and do not activate
zas_
parents:
359
diff
changeset
|
129 /* As 2008/04/15 there is no difference between our collection file format |
822040a51249
Increase collection_load() buffer size and do not activate
zas_
parents:
359
diff
changeset
|
130 * and GQview 2.1.5 collection file format so ignore failures as well. */ |
361
e0295af4f716
collection_load(): replace official by limit_failures (and
zas_
parents:
360
diff
changeset
|
131 limit_failures = FALSE; |
360
822040a51249
Increase collection_load() buffer size and do not activate
zas_
parents:
359
diff
changeset
|
132 } |
9 | 133 continue; |
134 } | |
135 if (s_buf[0]=='\n') continue; | |
136 | |
217 | 137 buf = quoted_value(s_buf, NULL); |
9 | 138 if (buf) |
139 { | |
140 gint valid; | |
138 | 141 |
142 if (!flush) | |
143 changed |= collect_manager_process_action(entry, &buf); | |
144 | |
145 valid = (buf[0] == '/' && collection_add_check(cd, file_data_new_simple(buf), FALSE, TRUE)); | |
362 | 146 if (debug && !valid) printf("collection invalid file: %s\n", buf); |
9 | 147 g_free(buf); |
148 | |
149 total++; | |
361
e0295af4f716
collection_load(): replace official by limit_failures (and
zas_
parents:
360
diff
changeset
|
150 if (!valid && limit_failures) |
9 | 151 { |
152 fail++; | |
283 | 153 if (fail > GQ_COLLECTION_FAIL_MIN && |
154 fail * 100 / total > GQ_COLLECTION_FAIL_PERCENT) | |
9 | 155 { |
362 | 156 printf("%d invalid filenames in unoffical collection file, closing: %s\n", fail, path); |
9 | 157 success = FALSE; |
158 break; | |
159 } | |
160 } | |
161 } | |
162 } | |
163 | |
362 | 164 if (debug) printf("collection files: total = %d fail = %d\n", total, fail); |
165 | |
9 | 166 fclose(f); |
359
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
167 if (only_geometry) return FALSE; |
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
168 |
138 | 169 if (!flush) |
170 { | |
171 gchar *buf = NULL; | |
172 while (collect_manager_process_action(entry, &buf)) | |
173 { | |
174 collection_add_check(cd, file_data_new_simple(buf), FALSE, TRUE); | |
175 changed = TRUE; | |
176 g_free(buf); | |
177 } | |
178 } | |
9 | 179 |
180 cd->list = collection_list_sort(cd->list, cd->sort_method); | |
138 | 181 |
182 if (!flush && changed && success) | |
183 collection_save_private(cd, path); | |
184 | |
185 if (!flush) | |
186 collect_manager_entry_reset(entry); | |
187 | |
9 | 188 if (!append) cd->changed = FALSE; |
189 | |
190 return success; | |
191 } | |
192 | |
358 | 193 gint collection_load(CollectionData *cd, const gchar *path, CollectionLoadFlags flags) |
9 | 194 { |
358 | 195 if (collection_load_private(cd, path, flags | COLLECTION_LOAD_FLUSH)) |
9 | 196 { |
197 layout_recent_add_path(cd->path); | |
198 return TRUE; | |
199 } | |
200 | |
201 return FALSE; | |
202 } | |
203 | |
204 static void collection_load_thumb_do(CollectionData *cd) | |
205 { | |
206 GdkPixbuf *pixbuf; | |
207 | |
208 if (!cd->thumb_loader || !g_list_find(cd->list, cd->thumb_info)) return; | |
209 | |
210 pixbuf = thumb_loader_get_pixbuf(cd->thumb_loader, TRUE); | |
211 collection_info_set_thumb(cd->thumb_info, pixbuf); | |
212 g_object_unref(pixbuf); | |
213 | |
214 if (cd->info_updated_func) cd->info_updated_func(cd, cd->thumb_info, cd->info_updated_data); | |
215 } | |
216 | |
217 static void collection_load_thumb_error_cb(ThumbLoader *tl, gpointer data) | |
218 { | |
219 CollectionData *cd = data; | |
220 | |
221 collection_load_thumb_do(cd); | |
222 collection_load_thumb_step(cd); | |
223 } | |
224 | |
225 static void collection_load_thumb_done_cb(ThumbLoader *tl, gpointer data) | |
226 { | |
227 CollectionData *cd = data; | |
228 | |
229 collection_load_thumb_do(cd); | |
230 collection_load_thumb_step(cd); | |
231 } | |
232 | |
233 static void collection_load_thumb_step(CollectionData *cd) | |
234 { | |
235 GList *work; | |
236 CollectInfo *ci; | |
237 | |
238 if (!cd->list) | |
239 { | |
240 collection_load_stop(cd); | |
241 return; | |
242 } | |
243 | |
244 work = cd->list; | |
245 ci = work->data; | |
246 work = work->next; | |
247 /* find first unloaded thumb */ | |
248 while (work && ci->pixbuf) | |
249 { | |
250 ci = work->data; | |
251 work = work->next; | |
252 } | |
253 | |
254 if (!ci || ci->pixbuf) | |
255 { | |
256 /* done */ | |
257 collection_load_stop(cd); | |
258 | |
259 /* send a NULL CollectInfo to notify end */ | |
260 if (cd->info_updated_func) cd->info_updated_func(cd, NULL, cd->info_updated_data); | |
261 | |
262 return; | |
263 } | |
264 | |
265 /* setup loader and call it */ | |
266 cd->thumb_info = ci; | |
267 thumb_loader_free(cd->thumb_loader); | |
333 | 268 cd->thumb_loader = thumb_loader_new(options->thumbnails.max_width, options->thumbnails.max_height); |
9 | 269 thumb_loader_set_callbacks(cd->thumb_loader, |
270 collection_load_thumb_done_cb, | |
271 collection_load_thumb_error_cb, | |
272 NULL, | |
273 cd); | |
274 | |
275 /* start it */ | |
138 | 276 if (!thumb_loader_start(cd->thumb_loader, ci->fd->path)) |
9 | 277 { |
278 /* error, handle it, do next */ | |
138 | 279 if (debug) printf("error loading thumb for %s\n", ci->fd->path); |
9 | 280 collection_load_thumb_do(cd); |
281 collection_load_thumb_step(cd); | |
282 } | |
283 } | |
284 | |
285 void collection_load_thumb_idle(CollectionData *cd) | |
286 { | |
287 if (!cd->thumb_loader) collection_load_thumb_step(cd); | |
288 } | |
289 | |
358 | 290 gint collection_load_begin(CollectionData *cd, const gchar *path, CollectionLoadFlags flags) |
9 | 291 { |
358 | 292 if (!collection_load(cd, path, flags)) return FALSE; |
9 | 293 |
294 collection_load_thumb_idle(cd); | |
295 | |
296 return TRUE; | |
297 } | |
298 | |
299 void collection_load_stop(CollectionData *cd) | |
300 { | |
301 if (!cd->thumb_loader) return; | |
302 | |
303 thumb_loader_free(cd->thumb_loader); | |
304 cd->thumb_loader = NULL; | |
305 } | |
306 | |
307 static gint collection_save_private(CollectionData *cd, const gchar *path) | |
308 { | |
312 | 309 SecureSaveInfo *ssi; |
9 | 310 GList *work; |
311 gchar *pathl; | |
312 | |
313 if (!path && !cd->path) return FALSE; | |
314 | |
315 if (!path) | |
316 { | |
317 path = cd->path; | |
318 } | |
319 | |
320 | |
312 | 321 pathl = path_from_utf8(path); |
322 ssi = secure_open(pathl); | |
9 | 323 g_free(pathl); |
312 | 324 if (!ssi) |
325 { | |
326 gchar *buf; | |
9 | 327 |
312 | 328 buf = g_strdup_printf(_("failed to open collection (write) \"%s\"\n"), path); |
329 print_term(buf); | |
330 g_free(buf); | |
9 | 331 return FALSE; |
332 } | |
333 | |
312 | 334 secure_fprintf(ssi, "%s collection\n", GQ_COLLECTION_MARKER); |
335 secure_fprintf(ssi, "#created with %s version %s\n", GQ_APPNAME, VERSION); | |
9 | 336 |
337 collection_update_geometry(cd); | |
338 if (cd->window_read) | |
339 { | |
312 | 340 secure_fprintf(ssi, "#geometry: %d %d %d %d\n", cd->window_x, cd->window_y, cd->window_w, cd->window_h); |
9 | 341 } |
342 | |
343 work = cd->list; | |
312 | 344 while (work && secsave_errno == SS_ERR_NONE) |
9 | 345 { |
346 CollectInfo *ci = work->data; | |
312 | 347 secure_fprintf(ssi, "\"%s\"\n", ci->fd->path); |
9 | 348 work = work->next; |
349 } | |
350 | |
312 | 351 secure_fprintf(ssi, "#end\n"); |
9 | 352 |
312 | 353 if (secure_close(ssi)) |
9 | 354 { |
312 | 355 gchar *buf; |
356 | |
357 buf = g_strdup_printf(_("error saving collection file: %s\nerror: %s\n"), path, | |
358 secsave_strerror(secsave_errno)); | |
359 print_term(buf); | |
360 g_free(buf); | |
9 | 361 return FALSE; |
362 } | |
363 | |
364 if (!cd->path || strcmp(path, cd->path) != 0) | |
365 { | |
366 gchar *buf = cd->path; | |
367 cd->path = g_strdup(path); | |
368 path = cd->path; | |
369 g_free(buf); | |
370 | |
371 g_free(cd->name); | |
372 cd->name = g_strdup(filename_from_path(cd->path)); | |
373 | |
374 collection_path_changed(cd); | |
375 } | |
376 | |
377 cd->changed = FALSE; | |
378 | |
379 return TRUE; | |
380 } | |
381 | |
382 gint collection_save(CollectionData *cd, const gchar *path) | |
383 { | |
384 if (collection_save_private(cd, path)) | |
385 { | |
386 layout_recent_add_path(cd->path); | |
387 return TRUE; | |
388 } | |
389 | |
390 return FALSE; | |
391 } | |
392 | |
393 gint collection_load_only_geometry(CollectionData *cd, const gchar *path) | |
394 { | |
359
96fb24f948b7
Merge collection_load_only_geometry() into collection_load().
zas_
parents:
358
diff
changeset
|
395 return collection_load(cd, path, COLLECTION_LOAD_GEOMETRY); |
9 | 396 } |
397 | |
398 | |
399 /* | |
400 *------------------------------------------------------------------- | |
401 * collection manager | |
402 *------------------------------------------------------------------- | |
403 */ | |
404 | |
405 #define COLLECT_MANAGER_ACTIONS_PER_IDLE 1000 | |
406 #define COLLECT_MANAGER_FLUSH_DELAY 10000 | |
407 | |
408 struct _CollectManagerEntry | |
409 { | |
410 gchar *path; | |
138 | 411 GList *add_list; |
412 GHashTable *oldpath_hash; | |
413 GHashTable *newpath_hash; | |
414 gboolean empty; | |
9 | 415 }; |
416 | |
417 typedef enum { | |
418 COLLECTION_MANAGER_UPDATE, | |
419 COLLECTION_MANAGER_ADD, | |
420 COLLECTION_MANAGER_REMOVE | |
421 } CollectManagerType; | |
422 | |
423 typedef struct _CollectManagerAction CollectManagerAction; | |
424 struct _CollectManagerAction | |
425 { | |
426 gchar *oldpath; | |
427 gchar *newpath; | |
428 | |
429 CollectManagerType type; | |
430 | |
431 gint ref; | |
432 }; | |
433 | |
434 | |
435 static GList *collection_manager_entry_list = NULL; | |
436 static GList *collection_manager_action_list = NULL; | |
437 static GList *collection_manager_action_tail = NULL; | |
438 static gint collection_manager_timer_id = -1; | |
439 | |
440 | |
441 static CollectManagerAction *collect_manager_action_new(const gchar *oldpath, const gchar *newpath, | |
442 CollectManagerType type) | |
443 { | |
444 CollectManagerAction *action; | |
445 | |
446 action = g_new0(CollectManagerAction, 1); | |
447 action->ref = 1; | |
448 | |
449 action->oldpath = g_strdup(oldpath); | |
450 action->newpath = g_strdup(newpath); | |
451 | |
452 action->type = type; | |
453 | |
454 return action; | |
455 } | |
456 | |
457 static void collect_manager_action_ref(CollectManagerAction *action) | |
458 { | |
459 action->ref++; | |
460 } | |
461 | |
462 static void collect_manager_action_unref(CollectManagerAction *action) | |
463 { | |
464 action->ref--; | |
465 | |
466 if (action->ref > 0) return; | |
467 | |
468 g_free(action->oldpath); | |
469 g_free(action->newpath); | |
470 g_free(action); | |
471 } | |
472 | |
138 | 473 static void collect_manager_entry_free_data(CollectManagerEntry *entry) |
9 | 474 { |
475 GList *work; | |
476 | |
138 | 477 work = entry->add_list; |
9 | 478 while (work) |
479 { | |
480 CollectManagerAction *action; | |
481 | |
482 action = work->data; | |
483 work = work->next; | |
484 | |
485 collect_manager_action_unref(action); | |
486 } | |
138 | 487 g_list_free(entry->add_list); |
488 g_hash_table_destroy(entry->oldpath_hash); | |
489 g_hash_table_destroy(entry->newpath_hash); | |
490 } | |
491 | |
492 static void collect_manager_entry_init_data(CollectManagerEntry *entry) | |
493 { | |
494 entry->add_list = NULL; | |
495 entry->oldpath_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify) collect_manager_action_unref); | |
496 entry->newpath_hash = g_hash_table_new(g_str_hash, g_str_equal); | |
497 entry->empty = TRUE; | |
498 | |
499 } | |
500 | |
501 static CollectManagerEntry *collect_manager_entry_new(const gchar *path) | |
502 { | |
503 CollectManagerEntry *entry; | |
504 | |
505 entry = g_new0(CollectManagerEntry, 1); | |
506 entry->path = g_strdup(path); | |
507 collect_manager_entry_init_data(entry); | |
508 | |
509 collection_manager_entry_list = g_list_append(collection_manager_entry_list, entry); | |
510 | |
511 return entry; | |
512 } | |
513 | |
514 | |
515 static void collect_manager_entry_free(CollectManagerEntry *entry) | |
516 { | |
517 collection_manager_entry_list = g_list_remove(collection_manager_entry_list, entry); | |
518 | |
519 collect_manager_entry_free_data(entry); | |
9 | 520 |
521 g_free(entry->path); | |
522 g_free(entry); | |
523 } | |
524 | |
138 | 525 static void collect_manager_entry_reset(CollectManagerEntry *entry) |
526 { | |
527 collect_manager_entry_free_data(entry); | |
528 collect_manager_entry_init_data(entry); | |
529 } | |
530 | |
531 static CollectManagerEntry *collect_manager_get_entry(const gchar *path) | |
532 { | |
533 GList *work; | |
534 | |
535 work = collection_manager_entry_list; | |
536 while (work) | |
537 { | |
538 CollectManagerEntry *entry; | |
539 | |
540 entry = work->data; | |
541 work = work->next; | |
542 if (strcmp(entry->path, path) == 0) | |
543 { | |
544 return entry; | |
545 } | |
546 } | |
547 return NULL; | |
548 | |
549 } | |
550 | |
551 static void collect_manager_entry_add_action(CollectManagerEntry *entry, CollectManagerAction *action) | |
552 { | |
553 | |
554 CollectManagerAction *orig_action; | |
555 | |
556 entry->empty = FALSE; | |
557 | |
558 if (action->oldpath == NULL) | |
559 { | |
560 /* add file */ | |
561 if (action->newpath == NULL) | |
562 { | |
563 return; | |
564 } | |
565 | |
566 orig_action = g_hash_table_lookup(entry->newpath_hash, action->newpath); | |
567 if (orig_action) | |
568 { | |
569 /* target already exists */ | |
570 printf("collection manager failed to add another action for target %s in collection %s\n", | |
571 action->newpath, entry->path); | |
572 return; | |
573 } | |
574 entry->add_list = g_list_append(entry->add_list, action); | |
575 g_hash_table_insert(entry->newpath_hash, action->newpath, action); | |
576 collect_manager_action_ref(action); | |
577 return; | |
578 } | |
579 | |
580 orig_action = g_hash_table_lookup(entry->newpath_hash, action->oldpath); | |
581 if (orig_action) | |
582 { | |
583 /* new action with the same file */ | |
584 CollectManagerAction *new_action = collect_manager_action_new(orig_action->oldpath, action->newpath, action->type); | |
585 | |
586 if (new_action->oldpath) | |
587 { | |
588 g_hash_table_steal(entry->oldpath_hash, orig_action->oldpath); | |
589 g_hash_table_insert(entry->oldpath_hash, new_action->oldpath, new_action); | |
590 } | |
591 else | |
592 { | |
593 GList *work = g_list_find(entry->add_list, orig_action); | |
594 work->data = new_action; | |
595 } | |
596 | |
597 g_hash_table_steal(entry->newpath_hash, orig_action->newpath); | |
598 if (new_action->newpath) | |
599 { | |
600 g_hash_table_insert(entry->newpath_hash, new_action->newpath, new_action); | |
601 } | |
602 collect_manager_action_unref(orig_action); | |
603 return; | |
604 } | |
605 | |
606 | |
607 orig_action = g_hash_table_lookup(entry->oldpath_hash, action->oldpath); | |
608 if (orig_action) | |
609 { | |
610 /* another action for the same source, ignore */ | |
611 printf("collection manager failed to add another action for source %s in collection %s\n", | |
612 action->oldpath, entry->path); | |
613 return; | |
614 } | |
615 | |
616 g_hash_table_insert(entry->oldpath_hash, action->oldpath, action); | |
617 if (action->newpath) | |
618 { | |
619 g_hash_table_insert(entry->newpath_hash, action->newpath, action); | |
620 } | |
621 collect_manager_action_ref(action); | |
622 } | |
623 | |
235 | 624 static gint collect_manager_process_action(CollectManagerEntry *entry, gchar **path_ptr) |
138 | 625 { |
626 gchar *path = *path_ptr; | |
627 CollectManagerAction *action; | |
628 | |
629 if (path == NULL) | |
630 { | |
631 /* get new files */ | |
632 if (entry->add_list) | |
633 { | |
634 action = entry->add_list->data; | |
635 g_assert(action->oldpath == NULL); | |
636 entry->add_list = g_list_remove(entry->add_list, action); | |
637 path = g_strdup(action->newpath); | |
638 g_hash_table_remove(entry->newpath_hash, path); | |
639 collect_manager_action_unref(action); | |
640 } | |
641 *path_ptr = path; | |
642 return (path != NULL); | |
643 } | |
644 | |
645 action = g_hash_table_lookup(entry->oldpath_hash, path); | |
646 | |
647 if (action) | |
648 { | |
649 g_free(path); | |
650 path = g_strdup(action->newpath); | |
651 *path_ptr = path; | |
652 return TRUE; | |
653 } | |
654 | |
655 return FALSE; /* no change */ | |
656 } | |
657 | |
9 | 658 static void collect_manager_refresh(void) |
659 { | |
660 GList *list = NULL; | |
661 GList *work; | |
662 gchar *base; | |
663 | |
283 | 664 base = g_strconcat(homedir(), "/", GQ_RC_DIR_COLLECTIONS, NULL); |
9 | 665 path_list(base, &list, NULL); |
666 g_free(base); | |
667 | |
668 work = collection_manager_entry_list; | |
669 while (work && list) | |
670 { | |
671 CollectManagerEntry *entry; | |
672 GList *list_step; | |
673 | |
674 entry = work->data; | |
675 work = work->next; | |
676 | |
677 list_step = list; | |
678 while (list_step && entry) | |
679 { | |
680 gchar *path; | |
681 | |
682 path = list_step->data; | |
683 list_step = list_step->next; | |
684 | |
685 if (strcmp(path, entry->path) == 0) | |
686 { | |
687 list = g_list_remove(list, path); | |
688 g_free(path); | |
689 | |
690 entry = NULL; | |
691 } | |
692 else | |
693 { | |
694 collect_manager_entry_free(entry); | |
695 } | |
696 } | |
697 } | |
698 | |
699 work = list; | |
700 while (work) | |
701 { | |
702 gchar *path; | |
703 | |
704 path = work->data; | |
705 work = work->next; | |
706 | |
707 collect_manager_entry_new(path); | |
708 g_free(path); | |
709 } | |
710 | |
711 g_list_free(list); | |
712 } | |
713 | |
714 static void collect_manager_process_actions(gint max) | |
715 { | |
716 if (debug && collection_manager_action_list) | |
717 { | |
718 printf("collection manager processing actions\n"); | |
719 } | |
720 | |
721 while (collection_manager_action_list != NULL && max > 0) | |
722 { | |
723 CollectManagerAction *action; | |
724 GList *work; | |
725 | |
726 action = collection_manager_action_list->data; | |
727 work = collection_manager_entry_list; | |
728 while (work) | |
729 { | |
730 CollectManagerEntry *entry; | |
731 | |
732 entry = work->data; | |
733 work = work->next; | |
734 | |
735 if (action->type == COLLECTION_MANAGER_UPDATE) | |
736 { | |
138 | 737 collect_manager_entry_add_action(entry, action); |
9 | 738 } |
739 else if (action->oldpath && action->newpath && | |
740 strcmp(action->newpath, entry->path) == 0) | |
741 { | |
742 /* convert action to standard add format */ | |
743 g_free(action->newpath); | |
744 if (action->type == COLLECTION_MANAGER_ADD) | |
745 { | |
746 action->newpath = action->oldpath; | |
747 action->oldpath = NULL; | |
748 } | |
749 else if (action->type == COLLECTION_MANAGER_REMOVE) | |
750 { | |
751 action->newpath = NULL; | |
752 } | |
138 | 753 collect_manager_entry_add_action(entry, action); |
9 | 754 } |
755 | |
756 max--; | |
757 } | |
758 | |
759 if (action->type != COLLECTION_MANAGER_UPDATE && | |
760 action->oldpath && action->newpath) | |
761 { | |
762 printf("collection manager failed to %s %s for collection %s\n", | |
763 (action->type == COLLECTION_MANAGER_ADD) ? "add" : "remove", | |
764 action->oldpath, action->newpath); | |
765 } | |
766 | |
767 if (collection_manager_action_tail == collection_manager_action_list) | |
768 { | |
769 collection_manager_action_tail = NULL; | |
770 } | |
771 collection_manager_action_list = g_list_remove(collection_manager_action_list, action); | |
772 collect_manager_action_unref(action); | |
773 } | |
774 } | |
775 | |
776 static gint collect_manager_process_entry(CollectManagerEntry *entry) | |
777 { | |
778 CollectionData *cd; | |
779 gint success; | |
780 | |
138 | 781 if (entry->empty) return FALSE; |
9 | 782 |
783 cd = collection_new(entry->path); | |
358 | 784 success = collection_load_private(cd, entry->path, COLLECTION_LOAD_NONE); |
9 | 785 |
786 collection_unref(cd); | |
787 | |
788 return TRUE; | |
789 } | |
790 | |
791 static gint collect_manager_process_entry_list(void) | |
792 { | |
793 GList *work; | |
794 | |
795 work = collection_manager_entry_list; | |
796 while (work) | |
797 { | |
798 CollectManagerEntry *entry; | |
799 | |
800 entry = work->data; | |
801 work = work->next; | |
802 if (collect_manager_process_entry(entry)) return TRUE; | |
803 } | |
804 | |
805 return FALSE; | |
806 } | |
807 | |
138 | 808 |
809 | |
9 | 810 static gint collect_manager_process_cb(gpointer data) |
811 { | |
812 if (collection_manager_action_list) collect_manager_refresh(); | |
813 collect_manager_process_actions(COLLECT_MANAGER_ACTIONS_PER_IDLE); | |
814 if (collection_manager_action_list) return TRUE; | |
815 | |
816 if (collect_manager_process_entry_list()) return TRUE; | |
817 | |
818 if (debug) printf("collection manager is up to date\n"); | |
819 return FALSE; | |
820 } | |
821 | |
822 static gint collect_manager_timer_cb(gpointer data) | |
823 { | |
824 if (debug) printf("collection manager timer expired\n"); | |
825 | |
826 g_idle_add_full(G_PRIORITY_LOW, collect_manager_process_cb, NULL, NULL); | |
827 | |
828 collection_manager_timer_id = -1; | |
829 return FALSE; | |
830 } | |
831 | |
832 static void collect_manager_timer_push(gint stop) | |
833 { | |
834 if (collection_manager_timer_id != -1) | |
835 { | |
836 if (!stop) return; | |
837 | |
838 g_source_remove(collection_manager_timer_id); | |
839 collection_manager_timer_id = -1; | |
840 } | |
841 | |
842 if (!stop) | |
843 { | |
844 collection_manager_timer_id = g_timeout_add(COLLECT_MANAGER_FLUSH_DELAY, | |
845 collect_manager_timer_cb, NULL); | |
846 if (debug) printf("collection manager timer started\n"); | |
847 } | |
848 } | |
849 | |
850 static void collect_manager_add_action(CollectManagerAction *action) | |
851 { | |
852 if (!action) return; | |
853 | |
854 /* we keep track of the list's tail to keep this a n(1) operation */ | |
855 | |
856 if (collection_manager_action_tail) | |
857 { | |
66
ebbff299ad0d
Fri Sep 1 02:12:45 2006 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
858 collection_manager_action_tail = g_list_append(collection_manager_action_tail, action); |
9 | 859 collection_manager_action_tail = collection_manager_action_tail->next; |
860 } | |
861 else | |
862 { | |
863 collection_manager_action_list = g_list_append(collection_manager_action_list, action); | |
864 collection_manager_action_tail = collection_manager_action_list; | |
865 } | |
866 | |
867 collect_manager_timer_push(FALSE); | |
868 } | |
869 | |
138 | 870 void collect_manager_moved(FileData *fd) |
9 | 871 { |
872 CollectManagerAction *action; | |
138 | 873 const gchar *oldpath = fd->change->source; |
874 const gchar *newpath = fd->change->dest; | |
9 | 875 |
876 action = collect_manager_action_new(oldpath, newpath, COLLECTION_MANAGER_UPDATE); | |
877 collect_manager_add_action(action); | |
878 } | |
879 | |
138 | 880 void collect_manager_add(FileData *fd, const gchar *collection) |
9 | 881 { |
882 CollectManagerAction *action; | |
883 CollectWindow *cw; | |
884 | |
138 | 885 if (!fd || !collection) return; |
9 | 886 |
887 cw = collection_window_find_by_path(collection); | |
888 if (cw) | |
889 { | |
138 | 890 if (collection_list_find(cw->cd->list, fd->path) == NULL) |
9 | 891 { |
138 | 892 collection_add(cw->cd, fd, FALSE); |
9 | 893 } |
894 return; | |
895 } | |
896 | |
138 | 897 action = collect_manager_action_new(fd->path, collection, COLLECTION_MANAGER_ADD); |
9 | 898 collect_manager_add_action(action); |
899 } | |
900 | |
138 | 901 void collect_manager_remove(FileData *fd, const gchar *collection) |
9 | 902 { |
903 CollectManagerAction *action; | |
904 CollectWindow *cw; | |
905 | |
138 | 906 if (!fd || !collection) return; |
9 | 907 |
908 cw = collection_window_find_by_path(collection); | |
909 if (cw) | |
910 { | |
138 | 911 while (collection_remove(cw->cd, fd)); |
9 | 912 return; |
913 } | |
914 | |
138 | 915 action = collect_manager_action_new(fd->path, collection, COLLECTION_MANAGER_REMOVE); |
9 | 916 collect_manager_add_action(action); |
917 } | |
918 | |
919 void collect_manager_flush(void) | |
920 { | |
921 collect_manager_timer_push(TRUE); | |
922 | |
923 if (debug) printf("collection manager flushing\n"); | |
924 while (collect_manager_process_cb(NULL)); | |
925 } | |
926 |