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