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