Mercurial > geeqie
annotate src/collect.c @ 108:9c355d5c8619
Fri Nov 10 16:11:28 2006 John Ellis <johne@verizon.net>
* format_fuji.c (format_fuji_raw): Use exif_byte_get_int32() to get
the value, as when that is eventually fixed to be alignment safe,
the so shall this.
author | gqview |
---|---|
date | Fri, 10 Nov 2006 21:15:52 +0000 |
parents | 50dc5a14d37b |
children | 71e1ebee420e |
rev | line source |
---|---|
9 | 1 /* |
2 * GQview | |
94
50dc5a14d37b
Thu Nov 2 17:51:31 2006 John Ellis <johne@verizon.net>
gqview
parents:
91
diff
changeset
|
3 * (C) 2006 John Ellis |
9 | 4 * |
5 * Author: John Ellis | |
6 * | |
7 * This software is released under the GNU General Public License (GNU GPL). | |
8 * Please read the included file COPYING for more information. | |
9 * This software comes with no warranty of any kind, use at your own risk! | |
10 */ | |
11 | |
12 | |
13 #include "gqview.h" | |
14 #include "collect.h" | |
15 | |
16 #include "collect-dlg.h" | |
17 #include "collect-io.h" | |
18 #include "collect-table.h" | |
19 #include "editors.h" | |
20 #include "filelist.h" | |
21 #include "img-view.h" | |
22 #include "info.h" | |
23 #include "layout.h" | |
24 #include "layout_image.h" | |
91
d063f97503b7
Wed Nov 1 11:39:48 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
25 #include "pixbuf_util.h" |
94
50dc5a14d37b
Thu Nov 2 17:51:31 2006 John Ellis <johne@verizon.net>
gqview
parents:
91
diff
changeset
|
26 #include "print.h" |
9 | 27 #include "utilops.h" |
28 #include "ui_fileops.h" | |
29 #include "ui_tree_edit.h" | |
30 | |
31 #include <gdk/gdkkeysyms.h> /* for keyboard values */ | |
32 | |
33 | |
34 #define COLLECT_DEF_WIDTH 440 | |
35 #define COLLECT_DEF_HEIGHT 450 | |
36 | |
37 static GList *collection_list = NULL; | |
38 static GList *collection_window_list = NULL; | |
39 | |
40 static void collection_window_get_geometry(CollectWindow *cw); | |
41 static void collection_window_refresh(CollectWindow *cw); | |
42 static void collection_window_update_title(CollectWindow *cw); | |
43 static void collection_window_add(CollectWindow *cw, CollectInfo *ci); | |
44 static void collection_window_insert(CollectWindow *cw, CollectInfo *ci); | |
45 static void collection_window_remove(CollectWindow *cw, CollectInfo *ci); | |
46 static void collection_window_update(CollectWindow *cw, CollectInfo *ci); | |
47 | |
48 static void collection_window_close(CollectWindow *cw); | |
49 | |
50 /* | |
51 *------------------------------------------------------------------- | |
52 * data, list handling | |
53 *------------------------------------------------------------------- | |
54 */ | |
55 | |
56 CollectInfo *collection_info_new(const gchar *path, struct stat *st, GdkPixbuf *pixbuf) | |
57 { | |
58 CollectInfo *ci; | |
59 | |
60 if (!path) return NULL; | |
61 | |
62 ci = g_new0(CollectInfo, 1); | |
63 ci->path = g_strdup(path); | |
64 ci->size = st->st_size; | |
65 ci->date = st->st_mtime; | |
66 | |
67 ci->pixbuf = pixbuf; | |
68 if (ci->pixbuf) g_object_ref(ci->pixbuf); | |
69 | |
70 return ci; | |
71 } | |
72 | |
73 void collection_info_free_thumb(CollectInfo *ci) | |
74 { | |
75 if (ci->pixbuf) g_object_unref(ci->pixbuf); | |
76 ci->pixbuf = NULL; | |
77 } | |
78 | |
79 void collection_info_free(CollectInfo *ci) | |
80 { | |
81 if (!ci) return; | |
82 | |
83 g_free(ci->path); | |
84 collection_info_free_thumb(ci); | |
85 g_free(ci); | |
86 } | |
87 | |
88 void collection_info_set_thumb(CollectInfo *ci, GdkPixbuf *pixbuf) | |
89 { | |
90 if (pixbuf) g_object_ref(pixbuf); | |
91 collection_info_free_thumb(ci); | |
92 ci->pixbuf = pixbuf; | |
93 } | |
94 | |
95 gint collection_info_load_thumb(CollectInfo *ci) | |
96 { | |
97 if (!ci) return FALSE; | |
98 | |
99 collection_info_free_thumb(ci); | |
100 | |
101 printf("collection_info_load_thumb not implemented!\n(because an instant thumb loader not implemented)"); | |
102 return FALSE; | |
103 #if 0 | |
104 if (create_thumbnail(ci->path, &ci->pixmap, &ci->mask) < 0) return FALSE; | |
105 | |
106 if (ci->pixmap) gdk_pixmap_ref(ci->pixmap); | |
107 if (ci->mask) gdk_bitmap_ref(ci->mask); | |
108 | |
109 return TRUE; | |
110 #endif | |
111 } | |
112 | |
113 void collection_list_free(GList *list) | |
114 { | |
115 GList *work; | |
116 work = list; | |
117 while(work) | |
118 { | |
119 collection_info_free((CollectInfo *)work->data); | |
120 work = work->next; | |
121 } | |
122 g_list_free(list); | |
123 } | |
124 | |
125 /* an ugly static var, well what ya gonna do ? */ | |
126 static SortType collection_list_sort_method = SORT_NAME; | |
127 | |
128 static gint collection_list_sort_cb(gconstpointer a, gconstpointer b) | |
129 { | |
130 const CollectInfo *cia = a; | |
131 const CollectInfo *cib = b; | |
132 | |
133 switch(collection_list_sort_method) | |
134 { | |
135 case SORT_NONE: | |
136 return 0; | |
137 break; | |
138 case SORT_SIZE: | |
139 if (cia->size < cib->size) return -1; | |
140 if (cia->size > cib->size) return 1; | |
141 return 0; | |
142 break; | |
143 case SORT_TIME: | |
144 if (cia->date < cib->date) return -1; | |
145 if (cia->date > cib->date) return 1; | |
146 return 0; | |
147 break; | |
148 case SORT_PATH: | |
149 return CASE_SORT(cia->path, cib->path); | |
150 break; | |
151 #ifdef HAVE_STRVERSCMP | |
152 case SORT_NUMBER: | |
153 return strverscmp(filename_from_path(cia->path), filename_from_path(cib->path)); | |
154 break; | |
155 #endif | |
156 case SORT_NAME: | |
157 default: | |
158 return CASE_SORT(filename_from_path(cia->path), filename_from_path(cib->path)); | |
159 break; | |
160 } | |
161 | |
162 return 0; | |
163 } | |
164 | |
165 GList *collection_list_sort(GList *list, SortType method) | |
166 { | |
167 if (method == SORT_NONE) return list; | |
168 | |
169 collection_list_sort_method = method; | |
170 | |
171 return g_list_sort(list, collection_list_sort_cb); | |
172 } | |
173 | |
174 GList *collection_list_add(GList *list, CollectInfo *ci, SortType method) | |
175 { | |
176 if (method != SORT_NONE) | |
177 { | |
178 collection_list_sort_method = method; | |
179 list = g_list_insert_sorted(list, ci, collection_list_sort_cb); | |
180 } | |
181 else | |
182 { | |
183 list = g_list_append(list, ci); | |
184 } | |
185 | |
186 return list; | |
187 } | |
188 | |
189 GList *collection_list_insert(GList *list, CollectInfo *ci, CollectInfo *insert_ci, SortType method) | |
190 { | |
191 if (method != SORT_NONE) | |
192 { | |
193 collection_list_sort_method = method; | |
194 list = g_list_insert_sorted(list, ci, collection_list_sort_cb); | |
195 } | |
196 else | |
197 { | |
198 GList *point; | |
199 | |
200 point = g_list_find(list, insert_ci); | |
201 list = uig_list_insert_link(list, point, ci); | |
202 } | |
203 | |
204 return list; | |
205 } | |
206 | |
207 GList *collection_list_remove(GList *list, CollectInfo *ci) | |
208 { | |
209 list = g_list_remove(list, ci); | |
210 collection_info_free(ci); | |
211 return list; | |
212 } | |
213 | |
214 CollectInfo *collection_list_find(GList *list, const gchar *path) | |
215 { | |
216 GList *work = list; | |
217 | |
218 while(work) | |
219 { | |
220 CollectInfo *ci = work->data; | |
221 if (strcmp(ci->path, path) == 0) return ci; | |
222 work = work->next; | |
223 } | |
224 | |
225 return NULL; | |
226 } | |
227 | |
228 #if 0 | |
229 static GList *collection_list_find_link(GList *list, gchar *path) | |
230 { | |
231 GList *work = list; | |
232 | |
233 while(work) | |
234 { | |
235 CollectInfo *ci = work->data; | |
236 if (strcmp(ci->path, path) == 0) return work; | |
237 work = work->next; | |
238 } | |
239 | |
240 return NULL; | |
241 } | |
242 | |
243 static gint collection_list_find_index(GList *list, gchar *path) | |
244 { | |
245 gint c = 0; | |
246 GList *work = list; | |
247 | |
248 while(work) | |
249 { | |
250 CollectInfo *ci = work->data; | |
251 if (strcmp(ci->path, path) == 0) return c; | |
252 work = work->next; | |
253 c++; | |
254 } | |
255 | |
256 return -1; | |
257 } | |
258 #endif | |
259 | |
260 GList *collection_list_to_path_list(GList *list) | |
261 { | |
262 GList *pathlist = NULL; | |
263 GList *work = list; | |
264 | |
265 while (work) | |
266 { | |
267 CollectInfo *info = work->data; | |
268 pathlist = g_list_prepend(pathlist, g_strdup(info->path)); | |
269 work = work->next; | |
270 } | |
271 | |
272 pathlist = g_list_reverse(pathlist); | |
273 return pathlist; | |
274 } | |
275 | |
276 CollectWindow *collection_window_find(CollectionData *cd) | |
277 { | |
278 GList *work; | |
279 | |
280 work = collection_window_list; | |
281 while (work) | |
282 { | |
283 CollectWindow *cw = work->data; | |
284 if (cw->cd == cd) return cw; | |
285 work = work->next; | |
286 } | |
287 | |
288 return NULL; | |
289 } | |
290 | |
291 CollectWindow *collection_window_find_by_path(const gchar *path) | |
292 { | |
293 GList *work; | |
294 | |
295 if (!path) return NULL; | |
296 | |
297 work = collection_window_list; | |
298 while (work) | |
299 { | |
300 CollectWindow *cw = work->data; | |
301 if (cw->cd->path && strcmp(cw->cd->path, path) == 0) return cw; | |
302 work = work->next; | |
303 } | |
304 | |
305 return NULL; | |
306 } | |
307 | |
308 /* | |
309 *------------------------------------------------------------------- | |
310 * please use these to actually add/remove stuff | |
311 *------------------------------------------------------------------- | |
312 */ | |
313 | |
314 CollectionData *collection_new(const gchar *path) | |
315 { | |
316 CollectionData *cd; | |
317 static gint untitled_counter = 0; | |
318 | |
319 cd = g_new0(CollectionData, 1); | |
320 | |
321 collection_list = g_list_append(collection_list, cd); | |
322 | |
323 cd->ref = 1; /* starts with a ref of 1 */ | |
324 | |
325 cd->list = NULL; | |
326 cd->sort_method = SORT_NONE; | |
327 cd->thumb_loader = NULL; | |
328 cd->info_updated_func = NULL; | |
329 | |
330 cd->window_read = FALSE; | |
331 cd->window_x = 0; | |
332 cd->window_y = 0; | |
333 cd->window_w = COLLECT_DEF_WIDTH; | |
334 cd->window_h = COLLECT_DEF_HEIGHT; | |
335 | |
336 cd->changed = FALSE; | |
337 | |
338 if (path) | |
339 { | |
340 cd->path = g_strdup(path); | |
341 cd->name = g_strdup(filename_from_path(cd->path)); | |
342 /* load it */ | |
343 } | |
344 else | |
345 { | |
346 cd->path = NULL; | |
347 | |
348 if (untitled_counter == 0) | |
349 { | |
350 cd->name = g_strdup(_("Untitled")); | |
351 } | |
352 else | |
353 { | |
354 cd->name = g_strdup_printf(_("Untitled (%d)"), untitled_counter + 1); | |
355 } | |
356 | |
357 untitled_counter++; | |
358 } | |
359 | |
360 return cd; | |
361 } | |
362 | |
363 void collection_free(CollectionData *cd) | |
364 { | |
365 if (!cd) return; | |
366 | |
367 if (debug) printf("collection \"%s\" freed\n", cd->name); | |
368 | |
369 collection_load_stop(cd); | |
370 collection_list_free(cd->list); | |
371 | |
372 collection_list = g_list_remove(collection_list, cd); | |
373 | |
374 g_free(cd->path); | |
375 g_free(cd->name); | |
376 | |
377 g_free(cd); | |
378 } | |
379 | |
380 void collection_ref(CollectionData *cd) | |
381 { | |
382 cd->ref++; | |
383 | |
384 if (debug) printf("collection \"%s\" ref count = %d\n", cd->name, cd->ref); | |
385 } | |
386 | |
387 void collection_unref(CollectionData *cd) | |
388 { | |
389 cd->ref--; | |
390 | |
391 if (debug) printf("collection \"%s\" ref count = %d\n", cd->name, cd->ref); | |
392 | |
393 if (cd->ref < 1) | |
394 { | |
395 collection_free(cd); | |
396 } | |
397 } | |
398 | |
399 void collection_path_changed(CollectionData *cd) | |
400 { | |
401 collection_window_update_title(collection_window_find(cd)); | |
402 } | |
403 | |
404 gint collection_to_number(CollectionData *cd) | |
405 { | |
406 return g_list_index(collection_list, cd); | |
407 } | |
408 | |
409 CollectionData *collection_from_number(gint n) | |
410 { | |
411 return g_list_nth_data(collection_list, n); | |
412 } | |
413 | |
414 CollectionData *collection_from_dnd_data(const gchar *data, GList **list, GList **info_list) | |
415 { | |
416 CollectionData *cd; | |
417 gint n; | |
418 | |
419 if (strncmp(data, "COLLECTION:", 11) != 0) return NULL; | |
420 | |
421 n = (gint)strtol(data + 11, NULL, 10); | |
422 cd = collection_from_number(n); | |
423 | |
424 if (!cd || (!list && !info_list)) | |
425 { | |
426 return cd; | |
427 } | |
428 else | |
429 { | |
430 GList *work = NULL; | |
431 GList *infol = NULL; | |
432 gint b, e; | |
433 | |
434 b = 0; | |
435 while(data[b] != '\0' && data[b] != '\n' ) b++; | |
436 b++; | |
437 e = b; | |
438 | |
439 while (data[b] != '\0') | |
440 { | |
441 CollectInfo *info; | |
442 | |
443 while (data[e] != '\n' && data[e] != '\0') e++; | |
444 n = (gint)strtol(data + b, NULL, 10); | |
445 | |
446 info = g_list_nth_data(cd->list, n); | |
447 if (info && list) work = g_list_append(work, g_strdup(info->path)); | |
448 if (info && info_list) infol = g_list_append(infol, info); | |
449 | |
450 while (data[e] == '\n') e++; | |
451 b = e; | |
452 } | |
453 if (list) *list = work; | |
454 if (info_list) *info_list = infol; | |
455 } | |
456 | |
457 return cd; | |
458 } | |
459 | |
460 gchar *collection_info_list_to_dnd_data(CollectionData *cd, GList *list, gint *length) | |
461 { | |
462 gchar *uri_text = NULL; | |
463 gint total; | |
464 GList *work; | |
465 gint n; | |
466 GList *temp; | |
467 gchar *ptr; | |
468 | |
469 n = collection_to_number(cd); | |
470 | |
471 if (!list || n < 0) | |
472 { | |
473 *length = 0; | |
474 return NULL; | |
475 } | |
476 | |
477 temp = NULL; | |
478 temp = g_list_prepend(temp, g_strdup_printf("COLLECTION:%d\n", n)); | |
479 work = list; | |
480 while(work) | |
481 { | |
482 n = g_list_index(cd->list, work->data); | |
483 if (n >= 0) | |
484 { | |
485 temp = g_list_prepend(temp, g_strdup_printf("%d\n", n)); | |
486 } | |
487 work = work->next; | |
488 } | |
489 | |
490 total = 0; | |
491 work = temp; | |
492 while(work) | |
493 { | |
494 total += strlen((gchar *)work->data); | |
495 work = work->next; | |
496 } | |
497 total += 1; | |
498 | |
499 uri_text = g_malloc(total); | |
500 ptr = uri_text; | |
501 | |
502 work = g_list_last(temp); | |
503 while(work) | |
504 { | |
505 gchar *text = work->data; | |
506 | |
507 work = work->prev; | |
508 | |
509 strcpy(ptr, text); | |
510 ptr += strlen(text); | |
511 } | |
512 | |
513 ptr[0] = '\0'; | |
514 | |
515 path_list_free(temp); | |
516 | |
517 *length = total; | |
518 | |
519 return uri_text; | |
520 } | |
521 | |
522 gint collection_info_valid(CollectionData *cd, CollectInfo *info) | |
523 { | |
524 if (collection_to_number(cd) < 0) return FALSE; | |
525 | |
526 return (g_list_index(cd->list, info) != 0); | |
527 } | |
528 | |
529 CollectInfo *collection_next_by_info(CollectionData *cd, CollectInfo *info) | |
530 { | |
531 GList *work; | |
532 | |
533 work = g_list_find(cd->list, info); | |
534 | |
535 if (!work) return NULL; | |
536 work = work->next; | |
537 if (work) return work->data; | |
538 return NULL; | |
539 } | |
540 | |
541 CollectInfo *collection_prev_by_info(CollectionData *cd, CollectInfo *info) | |
542 { | |
543 GList *work; | |
544 | |
545 work = g_list_find(cd->list, info); | |
546 | |
547 if (!work) return NULL; | |
548 work = work->prev; | |
549 if (work) return work->data; | |
550 return NULL; | |
551 } | |
552 | |
553 CollectInfo *collection_get_first(CollectionData *cd) | |
554 { | |
555 if (cd->list) return cd->list->data; | |
556 | |
557 return NULL; | |
558 } | |
559 | |
560 CollectInfo *collection_get_last(CollectionData *cd) | |
561 { | |
562 GList *list; | |
563 | |
564 list = g_list_last(cd->list); | |
565 | |
566 if (list) return list->data; | |
567 | |
568 return NULL; | |
569 } | |
570 | |
571 void collection_set_sort_method(CollectionData *cd, SortType method) | |
572 { | |
573 if (!cd) return; | |
574 | |
575 if (cd->sort_method == method) return; | |
576 | |
577 cd->sort_method = method; | |
578 cd->list = collection_list_sort(cd->list, cd->sort_method); | |
579 if (cd->list) cd->changed = TRUE; | |
580 | |
581 collection_window_refresh(collection_window_find(cd)); | |
582 } | |
583 | |
584 void collection_set_update_info_func(CollectionData *cd, | |
585 void (*func)(CollectionData *, CollectInfo *, gpointer), gpointer data) | |
586 { | |
587 cd->info_updated_func = func; | |
588 cd->info_updated_data = data; | |
589 } | |
590 | |
591 gint collection_add_check(CollectionData *cd, const gchar *path, gint sorted, gint must_exist) | |
592 { | |
593 struct stat st; | |
594 gint valid; | |
595 | |
596 if (must_exist) | |
597 { | |
598 valid = (stat_utf8(path, &st) && !S_ISDIR(st.st_mode)); | |
599 } | |
600 else | |
601 { | |
602 valid = TRUE; | |
603 st.st_size = 0; | |
604 st.st_mtime = 0; | |
605 } | |
606 | |
607 if (valid) | |
608 { | |
609 CollectInfo *ci; | |
610 ci = collection_info_new(path, &st, NULL); | |
611 cd->list = collection_list_add(cd->list, ci, sorted ? cd->sort_method : SORT_NONE); | |
612 cd->changed = TRUE; | |
613 | |
614 if (!sorted || cd->sort_method == SORT_NONE) | |
615 { | |
616 collection_window_add(collection_window_find(cd), ci); | |
617 } | |
618 else | |
619 { | |
620 collection_window_insert(collection_window_find(cd), ci); | |
621 } | |
622 } | |
623 | |
624 return valid; | |
625 } | |
626 | |
627 gint collection_add(CollectionData *cd, const gchar *path, gint sorted) | |
628 { | |
629 return collection_add_check(cd, path, sorted, TRUE); | |
630 } | |
631 | |
632 gint collection_insert(CollectionData *cd, const gchar *path, CollectInfo *insert_ci, gint sorted) | |
633 { | |
634 struct stat st; | |
635 | |
636 if (!insert_ci) return collection_add(cd, path, sorted); | |
637 | |
638 if (stat_utf8(path, &st) >= 0 && !S_ISDIR(st.st_mode)) | |
639 { | |
640 CollectInfo *ci; | |
641 ci = collection_info_new(path, &st, NULL); | |
642 cd->list = collection_list_insert(cd->list, ci, insert_ci, sorted ? cd->sort_method : SORT_NONE); | |
643 cd->changed = TRUE; | |
644 | |
645 collection_window_insert(collection_window_find(cd), ci); | |
646 | |
647 return TRUE; | |
648 } | |
649 | |
650 return FALSE; | |
651 } | |
652 | |
653 gint collection_remove(CollectionData *cd, const gchar *path) | |
654 { | |
655 CollectInfo *ci; | |
656 | |
657 ci = collection_list_find(cd->list, path); | |
658 | |
659 if (!ci) return FALSE; | |
660 | |
661 cd->list = g_list_remove(cd->list, ci); | |
662 cd->changed = TRUE; | |
663 | |
664 collection_window_remove(collection_window_find(cd), ci); | |
665 collection_info_free(ci); | |
666 | |
667 return TRUE; | |
668 } | |
669 | |
670 static void collection_remove_by_info(CollectionData *cd, CollectInfo *info) | |
671 { | |
672 if (!info || !g_list_find(cd->list, info)) return; | |
673 | |
674 cd->list = g_list_remove(cd->list, info); | |
675 cd->changed = (cd->list != NULL); | |
676 | |
677 collection_window_remove(collection_window_find(cd), info); | |
678 collection_info_free(info); | |
679 } | |
680 | |
681 void collection_remove_by_info_list(CollectionData *cd, GList *list) | |
682 { | |
683 GList *work; | |
684 | |
685 if (!list) return; | |
686 | |
687 if (!list->next) | |
688 { | |
689 /* more efficient (in collect-table) to remove a single item this way */ | |
690 collection_remove_by_info(cd, (CollectInfo *)list->data); | |
691 return; | |
692 } | |
693 | |
694 work = list; | |
695 while(work) | |
696 { | |
697 cd->list = collection_list_remove(cd->list, work->data); | |
698 work = work->next; | |
699 } | |
700 cd->changed = (cd->list != NULL); | |
701 | |
702 collection_window_refresh(collection_window_find(cd)); | |
703 } | |
704 | |
705 gint collection_rename(CollectionData *cd, const gchar *source, const gchar *dest) | |
706 { | |
707 CollectInfo *ci; | |
708 | |
709 ci = collection_list_find(cd->list, source); | |
710 | |
711 if (!ci) return FALSE; | |
712 | |
713 g_free(ci->path); | |
714 ci->path = g_strdup(dest); | |
715 cd->changed = TRUE; | |
716 | |
717 collection_window_update(collection_window_find(cd), ci); | |
718 | |
719 return TRUE; | |
720 } | |
721 | |
722 void collection_update_geometry(CollectionData *cd) | |
723 { | |
724 collection_window_get_geometry(collection_window_find(cd)); | |
725 } | |
726 | |
727 /* | |
728 *------------------------------------------------------------------- | |
729 * simple maintenance for renaming, deleting | |
730 *------------------------------------------------------------------- | |
731 */ | |
732 | |
733 void collection_maint_removed(const gchar *path) | |
734 { | |
735 GList *work; | |
736 | |
737 work = collection_list; | |
738 while(work) | |
739 { | |
740 CollectionData *cd = work->data; | |
741 work = work->next; | |
742 | |
743 while(collection_remove(cd, path)); | |
744 } | |
745 #if 0 | |
746 /* Do we really need to do this? removed files are | |
747 * automatically ignored when loading a collection. | |
748 */ | |
749 collect_manager_moved(path, NULL); | |
750 #endif | |
751 } | |
752 | |
753 void collection_maint_renamed(const gchar *source, const gchar *dest) | |
754 { | |
755 GList *work; | |
756 | |
757 work = collection_list; | |
758 while(work) | |
759 { | |
760 CollectionData *cd = work->data; | |
761 work = work->next; | |
762 | |
763 while(collection_rename(cd, source, dest)); | |
764 } | |
765 | |
766 collect_manager_moved(source, dest); | |
767 } | |
768 | |
769 /* | |
770 *------------------------------------------------------------------- | |
771 * window key presses | |
772 *------------------------------------------------------------------- | |
773 */ | |
774 | |
775 static gint collection_window_keypress(GtkWidget *widget, GdkEventKey *event, gpointer data) | |
776 { | |
777 CollectWindow *cw = data; | |
778 gint stop_signal = FALSE; | |
779 gint edit_val = -1; | |
780 GList *list; | |
781 | |
782 if (event->state & GDK_CONTROL_MASK) | |
783 { | |
85
9d5c75b5ec28
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
784 stop_signal = TRUE; |
9 | 785 switch (event->keyval) |
786 { | |
787 case '1': | |
788 edit_val = 0; | |
789 break; | |
790 case '2': | |
791 edit_val = 1; | |
792 break; | |
793 case '3': | |
794 edit_val = 2; | |
795 break; | |
796 case '4': | |
797 edit_val = 3; | |
798 break; | |
799 case '5': | |
800 edit_val = 4; | |
801 break; | |
802 case '6': | |
803 edit_val = 5; | |
804 break; | |
805 case '7': | |
806 edit_val = 6; | |
807 break; | |
808 case '8': | |
809 edit_val = 7; | |
810 break; | |
811 case '9': | |
812 edit_val = 8; | |
813 break; | |
814 case '0': | |
815 edit_val = 9; | |
816 break; | |
817 case 'A': case 'a': | |
818 if (event->state & GDK_SHIFT_MASK) | |
819 { | |
820 collection_table_unselect_all(cw->table); | |
821 } | |
822 else | |
823 { | |
824 collection_table_select_all(cw->table); | |
825 } | |
826 break; | |
827 case 'L': case 'l': | |
828 list = layout_list(NULL); | |
829 if (list) | |
830 { | |
831 collection_table_add_path_list(cw->table, list); | |
832 path_list_free(list); | |
833 } | |
834 break; | |
835 case 'C': case 'c': | |
836 file_util_copy(NULL, collection_table_selection_get_list(cw->table), NULL, cw->window); | |
837 break; | |
838 case 'M': case 'm': | |
839 file_util_move(NULL, collection_table_selection_get_list(cw->table), NULL, cw->window); | |
840 break; | |
841 case 'R': case 'r': | |
842 file_util_rename(NULL, collection_table_selection_get_list(cw->table), cw->window); | |
843 break; | |
844 case 'D': case 'd': | |
845 file_util_delete(NULL, collection_table_selection_get_list(cw->table), cw->window); | |
846 break; | |
847 case 'P': case 'p': | |
848 info_window_new(NULL, collection_table_selection_get_list(cw->table)); | |
849 break; | |
850 case 'S': case 's': | |
851 collection_dialog_save_as(NULL, cw->cd); | |
852 break; | |
853 case 'W': case 'w': | |
854 collection_window_close(cw); | |
855 break; | |
856 default: | |
85
9d5c75b5ec28
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
857 stop_signal = FALSE; |
9 | 858 break; |
859 } | |
860 } | |
861 else | |
862 { | |
85
9d5c75b5ec28
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
863 stop_signal = TRUE; |
9 | 864 switch (event->keyval) |
865 { | |
866 case GDK_Return: case GDK_KP_Enter: | |
867 layout_image_set_collection(NULL, cw->cd, | |
868 collection_table_get_focus_info(cw->table)); | |
869 break; | |
870 case 'V': case 'v': | |
871 view_window_new_from_collection(cw->cd, | |
872 collection_table_get_focus_info(cw->table)); | |
873 break; | |
874 case 'S': case 's': | |
875 if (!cw->cd->path) | |
876 { | |
877 collection_dialog_save_as(NULL, cw->cd); | |
878 } | |
879 else if (!collection_save(cw->cd, cw->cd->path)) | |
880 { | |
881 printf("failed saving to collection path: %s\n", cw->cd->path); | |
882 } | |
883 break; | |
884 case 'A': case 'a': | |
85
9d5c75b5ec28
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
885 collection_dialog_append(NULL, cw->cd); |
9 | 886 break; |
887 case 'N': case 'n': | |
888 collection_set_sort_method(cw->cd, SORT_NAME); | |
889 break; | |
890 #ifdef HAVE_STRVERSCMP | |
891 case 'I': case 'i': | |
892 collection_set_sort_method(cw->cd, SORT_NUMBER); | |
893 break; | |
894 #endif | |
895 case 'D': case 'd': | |
896 collection_set_sort_method(cw->cd, SORT_TIME); | |
897 break; | |
898 case 'B': case 'b': | |
899 collection_set_sort_method(cw->cd, SORT_SIZE); | |
900 break; | |
901 case 'P': case 'p': | |
94
50dc5a14d37b
Thu Nov 2 17:51:31 2006 John Ellis <johne@verizon.net>
gqview
parents:
91
diff
changeset
|
902 if (event->state & GDK_SHIFT_MASK) |
50dc5a14d37b
Thu Nov 2 17:51:31 2006 John Ellis <johne@verizon.net>
gqview
parents:
91
diff
changeset
|
903 { |
50dc5a14d37b
Thu Nov 2 17:51:31 2006 John Ellis <johne@verizon.net>
gqview
parents:
91
diff
changeset
|
904 CollectInfo *info; |
50dc5a14d37b
Thu Nov 2 17:51:31 2006 John Ellis <johne@verizon.net>
gqview
parents:
91
diff
changeset
|
905 const gchar *path; |
50dc5a14d37b
Thu Nov 2 17:51:31 2006 John Ellis <johne@verizon.net>
gqview
parents:
91
diff
changeset
|
906 |
50dc5a14d37b
Thu Nov 2 17:51:31 2006 John Ellis <johne@verizon.net>
gqview
parents:
91
diff
changeset
|
907 info = collection_table_get_focus_info(cw->table); |
50dc5a14d37b
Thu Nov 2 17:51:31 2006 John Ellis <johne@verizon.net>
gqview
parents:
91
diff
changeset
|
908 path = (info) ? info->path : NULL; |
50dc5a14d37b
Thu Nov 2 17:51:31 2006 John Ellis <johne@verizon.net>
gqview
parents:
91
diff
changeset
|
909 |
50dc5a14d37b
Thu Nov 2 17:51:31 2006 John Ellis <johne@verizon.net>
gqview
parents:
91
diff
changeset
|
910 print_window_new(path, collection_table_selection_get_list(cw->table), |
50dc5a14d37b
Thu Nov 2 17:51:31 2006 John Ellis <johne@verizon.net>
gqview
parents:
91
diff
changeset
|
911 collection_list_to_path_list(cw->cd->list), cw->window); |
50dc5a14d37b
Thu Nov 2 17:51:31 2006 John Ellis <johne@verizon.net>
gqview
parents:
91
diff
changeset
|
912 } |
50dc5a14d37b
Thu Nov 2 17:51:31 2006 John Ellis <johne@verizon.net>
gqview
parents:
91
diff
changeset
|
913 else |
50dc5a14d37b
Thu Nov 2 17:51:31 2006 John Ellis <johne@verizon.net>
gqview
parents:
91
diff
changeset
|
914 { |
50dc5a14d37b
Thu Nov 2 17:51:31 2006 John Ellis <johne@verizon.net>
gqview
parents:
91
diff
changeset
|
915 collection_set_sort_method(cw->cd, SORT_PATH); |
50dc5a14d37b
Thu Nov 2 17:51:31 2006 John Ellis <johne@verizon.net>
gqview
parents:
91
diff
changeset
|
916 } |
9 | 917 break; |
918 case GDK_Delete: case GDK_KP_Delete: | |
919 list = g_list_copy(cw->table->selection); | |
920 if (list) | |
921 { | |
922 collection_remove_by_info_list(cw->cd, list); | |
923 g_list_free(list); | |
924 } | |
925 else | |
926 { | |
927 collection_remove_by_info(cw->cd, collection_table_get_focus_info(cw->table)); | |
928 } | |
929 break; | |
930 default: | |
85
9d5c75b5ec28
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
931 stop_signal = FALSE; |
9 | 932 break; |
933 } | |
934 } | |
935 | |
936 if (edit_val != -1) | |
937 { | |
938 list = collection_table_selection_get_list(cw->table); | |
939 start_editor_from_path_list(edit_val, list); | |
940 path_list_free(list); | |
941 } | |
942 | |
943 return stop_signal; | |
944 } | |
945 | |
946 /* | |
947 *------------------------------------------------------------------- | |
948 * window | |
949 *------------------------------------------------------------------- | |
950 */ | |
951 static void collection_window_get_geometry(CollectWindow *cw) | |
952 { | |
953 CollectionData *cd; | |
954 | |
955 if (!cw) return; | |
956 | |
957 cd = cw->cd; | |
958 gdk_window_get_position (cw->window->window, &cd->window_x, &cd->window_y); | |
959 gdk_drawable_get_size(cw->window->window, &cd->window_w, &cd->window_h); | |
960 cd->window_read = TRUE; | |
961 } | |
962 | |
963 static void collection_window_refresh(CollectWindow *cw) | |
964 { | |
965 if (!cw) return; | |
966 | |
967 collection_table_refresh(cw->table); | |
968 } | |
969 | |
970 static void collection_window_update_title(CollectWindow *cw) | |
971 { | |
972 gchar *buf; | |
973 | |
974 if (!cw) return; | |
975 | |
976 buf = g_strdup_printf(_("%s - GQview Collection"), cw->cd->name); | |
977 gtk_window_set_title(GTK_WINDOW(cw->window), buf); | |
978 g_free(buf); | |
979 } | |
980 | |
981 static void collection_window_update_info(CollectionData *cd, CollectInfo *ci, gpointer data) | |
982 { | |
983 CollectWindow *cw = data; | |
984 | |
985 collection_table_file_update(cw->table, ci); | |
986 } | |
987 | |
988 static void collection_window_add(CollectWindow *cw, CollectInfo *ci) | |
989 { | |
990 if (!cw) return; | |
991 | |
992 if (!ci->pixbuf) collection_load_thumb_idle(cw->cd); | |
993 collection_table_file_add(cw->table, ci); | |
994 } | |
995 | |
996 static void collection_window_insert(CollectWindow *cw, CollectInfo *ci) | |
997 { | |
998 if (!cw) return; | |
999 | |
1000 if (!ci->pixbuf) collection_load_thumb_idle(cw->cd); | |
1001 collection_table_file_insert(cw->table, ci); | |
1002 if (!cw) return; | |
1003 } | |
1004 | |
1005 #if 0 | |
1006 static void collection_window_move(CollectWindow *cw, CollectInfo *ci) | |
1007 { | |
1008 if (!cw) return; | |
1009 } | |
1010 #endif | |
1011 | |
1012 static void collection_window_remove(CollectWindow *cw, CollectInfo *ci) | |
1013 { | |
1014 if (!cw) return; | |
1015 | |
1016 collection_table_file_remove(cw->table, ci); | |
1017 } | |
1018 | |
1019 static void collection_window_update(CollectWindow *cw, CollectInfo *ci) | |
1020 { | |
1021 if (!cw) return; | |
1022 | |
1023 collection_table_file_update(cw->table, ci); | |
1024 collection_table_file_update(cw->table, NULL); | |
1025 } | |
1026 | |
1027 static void collection_window_close_final(CollectWindow *cw) | |
1028 { | |
1029 if (cw->close_dialog) return; | |
1030 | |
1031 collection_window_list = g_list_remove(collection_window_list, cw); | |
1032 collection_window_get_geometry(cw); | |
1033 | |
1034 gtk_widget_destroy(cw->window); | |
1035 | |
1036 collection_set_update_info_func(cw->cd, NULL, NULL); | |
1037 collection_unref(cw->cd); | |
1038 | |
1039 g_free(cw); | |
1040 } | |
1041 | |
1042 static void collection_close_save_cb(GenericDialog *gd, gpointer data) | |
1043 { | |
1044 CollectWindow *cw = data; | |
1045 | |
1046 cw->close_dialog = NULL; | |
1047 generic_dialog_close(gd); | |
1048 | |
1049 if (!cw->cd->path) | |
1050 { | |
1051 collection_dialog_save_close(NULL, cw->cd); | |
1052 return; | |
1053 } | |
1054 else if (!collection_save(cw->cd, cw->cd->path)) | |
1055 { | |
1056 gchar *buf; | |
1057 buf = g_strdup_printf(_("Failed to save the collection:\n%s"), cw->cd->path); | |
1058 warning_dialog(_("Save Failed"), buf, GTK_STOCK_DIALOG_ERROR, cw->window); | |
1059 g_free(buf); | |
1060 return; | |
1061 } | |
1062 | |
1063 collection_window_close_final(cw); | |
1064 } | |
1065 | |
1066 static void collection_close_close_cb(GenericDialog *gd, gpointer data) | |
1067 { | |
1068 CollectWindow *cw = data; | |
1069 | |
1070 cw->close_dialog = NULL; | |
1071 generic_dialog_close(gd); | |
1072 | |
1073 collection_window_close_final(cw); | |
1074 } | |
1075 | |
1076 static void collection_close_cancel_cb(GenericDialog *gd, gpointer data) | |
1077 { | |
1078 CollectWindow *cw = data; | |
1079 | |
1080 cw->close_dialog = NULL; | |
1081 generic_dialog_close(gd); | |
1082 } | |
1083 | |
1084 static void collection_close_dlg_show(CollectWindow *cw) | |
1085 { | |
1086 GenericDialog *gd; | |
1087 | |
1088 if (cw->close_dialog) | |
1089 { | |
1090 gtk_window_present(GTK_WINDOW(cw->close_dialog)); | |
1091 return; | |
1092 } | |
1093 | |
1094 gd = generic_dialog_new(_("Close collection"), | |
1095 "GQview", "close_collection", cw->window, FALSE, | |
1096 collection_close_cancel_cb, cw); | |
1097 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, | |
1098 _("Close collection"), | |
1099 _("Collection has been modified.\nSave first?")); | |
1100 | |
1101 generic_dialog_add_button(gd, GTK_STOCK_SAVE, NULL, collection_close_save_cb, TRUE); | |
1102 generic_dialog_add_button(gd, GTK_STOCK_DELETE, _("_Discard"), collection_close_close_cb, FALSE); | |
1103 | |
1104 cw->close_dialog = gd->dialog; | |
1105 | |
1106 gtk_widget_show(gd->dialog); | |
1107 } | |
1108 | |
1109 static void collection_window_close(CollectWindow *cw) | |
1110 { | |
1111 if (!cw->cd->changed && !cw->close_dialog) | |
1112 { | |
1113 collection_window_close_final(cw); | |
1114 return; | |
1115 } | |
1116 | |
1117 collection_close_dlg_show(cw); | |
1118 } | |
1119 | |
1120 void collection_window_close_by_collection(CollectionData *cd) | |
1121 { | |
1122 CollectWindow *cw; | |
1123 | |
1124 cw = collection_window_find(cd); | |
1125 if (cw) collection_window_close_final(cw); | |
1126 } | |
1127 | |
1128 gint collection_window_modified_exists(void) | |
1129 { | |
1130 GList *work; | |
1131 | |
1132 work = collection_window_list; | |
1133 while (work) | |
1134 { | |
1135 CollectWindow *cw = work->data; | |
1136 if (cw->cd->changed) return TRUE; | |
1137 work = work->next; | |
1138 } | |
1139 | |
1140 return FALSE; | |
1141 } | |
1142 | |
1143 static gint collection_window_delete(GtkWidget *widget, GdkEvent *event, gpointer data) | |
1144 { | |
1145 CollectWindow *cw = data; | |
1146 collection_window_close(cw); | |
1147 | |
1148 return TRUE; | |
1149 } | |
1150 | |
1151 CollectWindow *collection_window_new(const gchar *path) | |
1152 { | |
1153 CollectWindow *cw; | |
1154 GtkWidget *vbox; | |
1155 GtkWidget *frame; | |
1156 GtkWidget *status_label; | |
1157 GtkWidget *extra_label; | |
1158 GdkGeometry geometry; | |
1159 | |
1160 cw = g_new0(CollectWindow, 1); | |
1161 | |
1162 cw->close_dialog = NULL; | |
1163 | |
1164 collection_window_list = g_list_append(collection_window_list, cw); | |
1165 | |
1166 cw->cd = collection_new(path); | |
1167 | |
1168 cw->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
91
d063f97503b7
Wed Nov 1 11:39:48 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
1169 window_set_icon(cw->window, PIXBUF_INLINE_ICON_BOOK, NULL); |
9 | 1170 |
1171 geometry.min_width = 32; | |
1172 geometry.min_height = 32; | |
1173 geometry.base_width = COLLECT_DEF_WIDTH; | |
1174 geometry.base_height = COLLECT_DEF_HEIGHT; | |
1175 gtk_window_set_geometry_hints(GTK_WINDOW(cw->window), NULL, &geometry, | |
1176 GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE); | |
1177 | |
1178 | |
1179 if (save_window_positions && path && collection_load_only_geometry(cw->cd, path)) | |
1180 { | |
1181 /* FIXME: x, y is not implemented */ | |
1182 gtk_window_set_default_size(GTK_WINDOW(cw->window), cw->cd->window_w, cw->cd->window_h); | |
1183 } | |
1184 else | |
1185 { | |
1186 gtk_window_set_default_size(GTK_WINDOW(cw->window), COLLECT_DEF_WIDTH, COLLECT_DEF_HEIGHT); | |
1187 } | |
1188 | |
1189 gtk_window_set_resizable(GTK_WINDOW(cw->window), TRUE); | |
1190 collection_window_update_title(cw); | |
1191 gtk_window_set_wmclass(GTK_WINDOW(cw->window), "collection", "GQview"); | |
1192 gtk_container_set_border_width (GTK_CONTAINER (cw->window), 0); | |
1193 | |
1194 g_signal_connect(G_OBJECT(cw->window), "delete_event", | |
1195 G_CALLBACK(collection_window_delete), cw); | |
1196 | |
1197 g_signal_connect(G_OBJECT(cw->window),"key_press_event", | |
1198 G_CALLBACK(collection_window_keypress), cw); | |
1199 | |
1200 vbox = gtk_vbox_new(FALSE, 0); | |
1201 gtk_container_add(GTK_CONTAINER(cw->window), vbox); | |
1202 gtk_widget_show(vbox); | |
1203 | |
1204 cw->table = collection_table_new(cw->cd); | |
1205 gtk_box_pack_start(GTK_BOX(vbox), cw->table->scrolled, TRUE, TRUE, 0); | |
1206 gtk_widget_show(cw->table->scrolled); | |
1207 | |
1208 cw->status_box = gtk_hbox_new(TRUE, 0); | |
1209 gtk_box_pack_start(GTK_BOX(vbox), cw->status_box, FALSE, FALSE, 0); | |
1210 gtk_widget_show(cw->status_box); | |
1211 | |
1212 frame = gtk_frame_new(NULL); | |
1213 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); | |
1214 gtk_box_pack_start(GTK_BOX(cw->status_box), frame, TRUE, TRUE, 0); | |
1215 gtk_widget_show(frame); | |
1216 | |
1217 status_label = gtk_label_new(""); | |
1218 gtk_container_add(GTK_CONTAINER(frame), status_label); | |
1219 gtk_widget_show(status_label); | |
1220 | |
1221 extra_label = gtk_progress_bar_new(); | |
1222 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(extra_label), 0.0); | |
1223 gtk_box_pack_start(GTK_BOX(cw->status_box), extra_label, TRUE, TRUE, 0); | |
1224 gtk_widget_show(extra_label); | |
1225 | |
1226 collection_table_set_labels(cw->table, status_label, extra_label); | |
1227 | |
1228 gtk_widget_show(cw->window); | |
1229 gtk_widget_grab_focus(cw->table->listview); | |
1230 | |
1231 collection_set_update_info_func(cw->cd, collection_window_update_info, cw); | |
1232 | |
1233 if (path && *path == '/') collection_load_begin(cw->cd, NULL, FALSE); | |
1234 | |
1235 return cw; | |
1236 } | |
1237 |