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