comparison src/filelist.c @ 1:b3e0e515fabf

Initial revision
author gqview
date Mon, 03 Apr 2000 18:24:05 +0000
parents
children c0e337a01cb7
comparison
equal deleted inserted replaced
0:513c7c01b50c 1:b3e0e515fabf
1 /*
2 * GQview image viewer
3 * (C)1999 John Ellis
4 *
5 * Author: John Ellis
6 *
7 */
8
9 #include "gqview.h"
10
11 static gint filelist_click_row = -1;
12
13 static void update_progressbar(gfloat val);
14
15 static gint file_is_hidden(gchar *name);
16 static gint file_is_in_filter(gchar *name);
17 static void add_to_filter(gchar *text, gint add);
18
19 static gint sort_list_cb(void *a, void *b);
20 static void filelist_read(gchar *path);
21
22 static gint file_find_closest_unaccounted(gint row, gint count, GList *ignore_list);
23
24 static void history_menu_select_cb(GtkWidget *widget, gpointer data);
25 static gchar *truncate_hist_text(gchar *t, gint l);
26 static void filelist_set_history(gchar *path);
27
28 /*
29 *-----------------------------------------------------------------------------
30 * file status information (private)
31 *-----------------------------------------------------------------------------
32 */
33
34 static void update_progressbar(gfloat val)
35 {
36 gtk_progress_bar_update (GTK_PROGRESS_BAR(info_progress_bar), val);
37 }
38
39 void update_status_label(gchar *text)
40 {
41 gchar *buf;
42 gint count;
43 gchar *ss = "";
44
45 if (text)
46 {
47 gtk_label_set(GTK_LABEL(info_status), text);
48 return;
49 }
50
51 if (slideshow_is_running()) ss = _(" Slideshow");
52
53 count = file_selection_count();
54 if (count > 0)
55 buf = g_strdup_printf(_("%d files (%d)%s"), file_count(), count, ss);
56 else
57 buf = g_strdup_printf(_("%d files%s"), file_count(), ss);
58
59 gtk_label_set(GTK_LABEL(info_status), buf);
60 g_free(buf);
61 }
62
63 /*
64 *-----------------------------------------------------------------------------
65 * file filtering
66 *-----------------------------------------------------------------------------
67 */
68
69 static gint file_is_hidden(gchar *name)
70 {
71 if (name[0] != '.') return FALSE;
72 if (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')) return FALSE;
73 return TRUE;
74 }
75
76 static gint file_is_in_filter(gchar *name)
77 {
78 GList *work;
79 if (!filename_filter || file_filter_disable) return TRUE;
80
81 work = filename_filter;
82 while (work)
83 {
84 gchar *filter = work->data;
85 gint lf = strlen(filter);
86 gint ln = strlen(name);
87 if (ln >= lf)
88 {
89 if (strncasecmp(name + ln - lf, filter, lf) == 0) return TRUE;
90 }
91 work = work->next;
92 }
93
94 return FALSE;
95 }
96
97 static void add_to_filter(gchar *text, gint add)
98 {
99 if (add) filename_filter = g_list_append(filename_filter, g_strdup(text));
100 }
101
102 void rebuild_file_filter()
103 {
104 if (filename_filter)
105 {
106 g_list_foreach(filename_filter,(GFunc)g_free,NULL);
107 g_list_free(filename_filter);
108 filename_filter = NULL;
109 }
110
111 add_to_filter(".jpg", filter_include_jpg);
112 add_to_filter(".jpeg", filter_include_jpg);
113 add_to_filter(".xpm", filter_include_xpm);
114 add_to_filter(".tif", filter_include_tif);
115 add_to_filter(".tiff", filter_include_tif);
116 add_to_filter(".gif", filter_include_gif);
117 add_to_filter(".png", filter_include_png);
118 add_to_filter(".ppm", filter_include_ppm);
119 add_to_filter(".pgm", filter_include_pgm);
120 add_to_filter(".pcx", filter_include_pcx);
121 add_to_filter(".bmp", filter_include_bmp);
122
123 if (custom_filter)
124 {
125 gchar *buf = g_strdup(custom_filter);
126 gchar *pos_ptr_b;
127 gchar *pos_ptr_e = custom_filter;
128 while(pos_ptr_e[0] != '\0')
129 {
130 pos_ptr_b = pos_ptr_e;
131 while (pos_ptr_e[0] != ';' && pos_ptr_e[0] != '\0') pos_ptr_e++;
132 if (pos_ptr_e[0] == ';')
133 {
134 pos_ptr_e[0] = '\0';
135 pos_ptr_e++;
136 }
137 add_to_filter(pos_ptr_b, TRUE);
138 }
139 g_free(buf);
140 }
141 }
142
143 /*
144 *-----------------------------------------------------------------------------
145 * load file list (private)
146 *-----------------------------------------------------------------------------
147 */
148
149 static gint sort_list_cb(void *a, void *b)
150 {
151 return strcmp((gchar *)a, (gchar *)b);
152 }
153
154 static void filelist_read(gchar *path)
155 {
156 DIR *dp;
157 struct dirent *dir;
158 struct stat ent_sbuf;
159
160 if((dp = opendir(path))==NULL)
161 {
162 /* dir not found */
163 return;
164 }
165
166 g_list_foreach(dir_list,(GFunc)g_free,NULL);
167 g_list_free(dir_list);
168 dir_list = NULL;
169
170 g_list_foreach(file_list,(GFunc)g_free,NULL);
171 g_list_free(file_list);
172 file_list = NULL;
173
174 while ((dir = readdir(dp)) != NULL)
175 {
176 /* skips removed files */
177 if (dir->d_ino > 0)
178 {
179 gchar *name = dir->d_name;
180 if (show_dot_files || !file_is_hidden(name))
181 {
182 gchar *filepath = g_strconcat(path, "/", name, NULL);
183 if (stat(filepath,&ent_sbuf) >= 0 && S_ISDIR(ent_sbuf.st_mode))
184 {
185 dir_list = g_list_prepend(dir_list, g_strdup(name));
186 }
187 else
188 {
189 if (file_is_in_filter(name))
190 file_list = g_list_prepend(file_list, g_strdup(name));
191 }
192 g_free(filepath);
193 }
194 }
195 }
196
197 closedir(dp);
198
199 dir_list = g_list_sort(dir_list, (GCompareFunc) sort_list_cb);
200 file_list = g_list_sort(file_list, (GCompareFunc) sort_list_cb);
201 }
202
203 /*
204 *-----------------------------------------------------------------------------
205 * file list utilities to retrieve information (public)
206 *-----------------------------------------------------------------------------
207 */
208
209 gint file_count()
210 {
211 return g_list_length(file_list);
212 }
213
214 gint file_selection_count()
215 {
216 gint count = 0;
217 GList *work = GTK_CLIST(file_clist)->selection;
218 while(work)
219 {
220 count++;
221 if (debug) printf("s = %d\n", GPOINTER_TO_INT(work->data));
222 work = work->next;
223 }
224
225 if (debug) printf("files selected = %d\n", count);
226
227 return count;
228 }
229
230 gint find_file_in_list(gchar *path)
231 {
232 GList *work = file_list;
233 gchar *buf;
234 gchar *name;
235 gint count = -1;
236
237 if (!path) return -1;
238
239 buf = remove_level_from_path(path);
240 if (strcmp(buf, current_path) != 0)
241 {
242 g_free(buf);
243 return -1;
244 }
245 g_free(buf);
246
247 name = filename_from_path(path);
248 while(work)
249 {
250 count++;
251 if (strcmp(name, work->data) == 0) return count;
252 work = work->next;
253 }
254
255 return -1;
256 }
257
258 gchar *file_get_path(gint row)
259 {
260 gchar *path = NULL;
261 gchar *name = gtk_clist_get_row_data(GTK_CLIST(file_clist), row);
262
263 if (name) path = g_strconcat(current_path, "/", name, NULL);
264
265 return path;
266 }
267
268 gint file_is_selected(gint row)
269 {
270 GList *work = GTK_CLIST(file_clist)->selection;
271
272 while(work)
273 {
274 if (GPOINTER_TO_INT(work->data) == row) return TRUE;
275 work = work->next;
276 }
277
278 return FALSE;
279 }
280
281 /*
282 *-----------------------------------------------------------------------------
283 * utilities to retrieve list of selected files (public)
284 *-----------------------------------------------------------------------------
285 */
286
287 GList *file_get_selected_list()
288 {
289 GList *list = NULL;
290 GList *work = GTK_CLIST(file_clist)->selection;
291
292 while(work)
293 {
294 gchar *name = gtk_clist_get_row_data(GTK_CLIST(file_clist),
295 GPOINTER_TO_INT(work->data));
296 list = g_list_prepend(list, g_strconcat(current_path, "/", name, NULL));
297 work = work->next;
298 }
299
300 list = g_list_reverse(list);
301
302 return list;
303 }
304
305 void free_selected_list(GList *list)
306 {
307 g_list_foreach(list, (GFunc)g_free, NULL);
308 g_list_free(list);
309 }
310
311 gint file_clicked_is_selected()
312 {
313 return file_is_selected(filelist_click_row);
314 }
315
316 gchar *file_clicked_get_path()
317 {
318 return file_get_path(filelist_click_row);
319 }
320
321 /*
322 *-----------------------------------------------------------------------------
323 * image change routines
324 *-----------------------------------------------------------------------------
325 */
326
327 void file_image_change_to(gint row)
328 {
329 gtk_clist_unselect_all(GTK_CLIST(file_clist));
330 gtk_clist_select_row(GTK_CLIST(file_clist), row, -1);
331 if (gtk_clist_row_is_visible(GTK_CLIST(file_clist), row) != GTK_VISIBILITY_FULL)
332 {
333 gtk_clist_moveto(GTK_CLIST(file_clist), row, -1, 0.5, 0.0);
334 }
335 }
336
337 void file_next_image()
338 {
339 gint current = find_file_in_list(image_get_path());
340 gint total = file_count();
341
342 if (current >= 0)
343 {
344 if (current < total - 1)
345 {
346 file_image_change_to(current + 1);
347 }
348 }
349 else
350 {
351 file_image_change_to(0);
352 }
353 }
354
355 void file_prev_image()
356 {
357 gint current = find_file_in_list(image_get_path());
358
359 if (current >= 0)
360 {
361 if (current > 0)
362 {
363 file_image_change_to(current - 1);
364 }
365 }
366 else
367 {
368 file_image_change_to(file_count() - 1);
369 }
370 }
371
372 void file_first_image()
373 {
374 gint current = find_file_in_list(image_get_path());
375 if (current != 0 && file_count() > 0)
376 {
377 file_image_change_to(0);
378 }
379 }
380
381 void file_last_image()
382 {
383 gint current = find_file_in_list(image_get_path());
384 gint count = file_count();
385 if (current != count - 1 && count > 0)
386 {
387 file_image_change_to(count - 1);
388 }
389 }
390
391 /*
392 *-----------------------------------------------------------------------------
393 * file delete/rename update routines
394 *-----------------------------------------------------------------------------
395 */
396
397 static gint file_find_closest_unaccounted(gint row, gint count, GList *ignore_list)
398 {
399 GList *list = NULL;
400 GList *work;
401 gint rev = row - 1;
402 row ++;
403
404 work = ignore_list;
405 while(work)
406 {
407 gint f = find_file_in_list(work->data);
408 if (f >= 0) list = g_list_append(list, GINT_TO_POINTER(f));
409 work = work->next;
410 }
411
412 while(list)
413 {
414 gint c = TRUE;
415 work = list;
416 while(work && c)
417 {
418 gpointer p = work->data;
419 work = work->next;
420 if (row == GPOINTER_TO_INT(p))
421 {
422 row++;
423 c = FALSE;
424 }
425 if (rev == GPOINTER_TO_INT(p))
426 {
427 rev--;
428 c = FALSE;
429 }
430 if (!c) list = g_list_remove(list, p);
431 }
432 if (c && list)
433 {
434 g_list_free(list);
435 list = NULL;
436 }
437 }
438 if (row > count - 1)
439 {
440 if (rev < 0)
441 return -1;
442 else
443 return rev;
444 }
445 else
446 {
447 return row;
448 }
449 }
450
451 void file_is_gone(gchar *path, GList *ignore_list)
452 {
453 GList *list;
454 gchar *name;
455 gint row;
456 gint new_row = -1;
457 row = find_file_in_list(path);
458 if (row < 0) return;
459
460 if (file_is_selected(row) /* && file_selection_count() == 1 */)
461 {
462 gint n = file_count();
463 if (ignore_list)
464 {
465 new_row = file_find_closest_unaccounted(row, n, ignore_list);
466 if (debug) printf("row = %d, closest is %d\n", row, new_row);
467 }
468 else
469 {
470 if (row + 1 < n)
471 {
472 new_row = row + 1;
473 }
474 else if (row > 0)
475 {
476 new_row = row - 1;
477 }
478 }
479 gtk_clist_unselect_all(GTK_CLIST(file_clist));
480 if (new_row >= 0)
481 {
482 gtk_clist_select_row(GTK_CLIST(file_clist), new_row, -1);
483 file_image_change_to(new_row);
484 }
485 else
486 {
487 image_change_to(NULL);
488 }
489 }
490
491 gtk_clist_remove(GTK_CLIST(file_clist), row);
492 list = g_list_nth(file_list, row);
493 name = list->data;
494 file_list = g_list_remove(file_list, name);
495 g_free(name);
496 update_status_label(NULL);
497 }
498
499 void file_is_renamed(gchar *source, gchar *dest)
500 {
501 gint row;
502 gchar *source_base;
503 gchar *dest_base;
504
505 if (image_get_path() && !strcmp(source, image_get_path()))
506 {
507 image_set_path(dest);
508 }
509
510 row = find_file_in_list(source);
511 if (row < 0) return;
512
513 source_base = remove_level_from_path(source);
514 dest_base = remove_level_from_path(dest);
515
516 if (strcmp(source_base, dest_base) == 0)
517 {
518 gchar *name;
519 gint n;
520 GList *work = g_list_nth(file_list, row);
521 name = work->data;
522 file_list = g_list_remove(file_list, name);
523 g_free(name);
524 name = g_strdup(filename_from_path(dest));
525 file_list = g_list_insert_sorted(file_list, name, (GCompareFunc) sort_list_cb);
526 n = g_list_index(file_list, name);
527
528 if (gtk_clist_get_cell_type(GTK_CLIST(file_clist), row, 0) != GTK_CELL_PIXTEXT)
529 {
530 gtk_clist_set_text (GTK_CLIST(file_clist), row, 0, name);
531 }
532 else
533 {
534 guint8 spacing = 0;
535 GdkPixmap *pixmap = NULL;
536 GdkBitmap *mask = NULL;
537 gtk_clist_get_pixtext(GTK_CLIST(file_clist), row, 0,
538 NULL, &spacing, &pixmap, &mask);
539 gtk_clist_set_pixtext(GTK_CLIST(file_clist), row, 0,
540 name, spacing, pixmap, mask);
541 }
542
543 gtk_clist_set_row_data(GTK_CLIST(file_clist), row, name);
544 gtk_clist_row_move(GTK_CLIST(file_clist), row, n);
545 }
546 else
547 {
548 GList *work = g_list_nth(file_list, row);
549 gchar *name = work->data;
550 file_list = g_list_remove(file_list, name);
551 gtk_clist_remove(GTK_CLIST(file_clist), row);
552 g_free(name);
553 update_status_label(NULL);
554 }
555
556 g_free(source_base);
557 g_free(dest_base);
558
559 }
560
561 /*
562 *-----------------------------------------------------------------------------
563 * directory list callbacks
564 *-----------------------------------------------------------------------------
565 */
566
567 void dir_select_cb(GtkWidget *widget, gint row, gint col,
568 GdkEvent *event, gpointer data)
569 {
570 gchar *name;
571 gchar *new_path;
572 name = gtk_clist_get_row_data (GTK_CLIST(dir_clist), row);
573 if (strcmp(name, ".") == 0)
574 {
575 new_path = g_strdup(current_path);
576 }
577 else if (strcmp(name, "..") == 0)
578 {
579 new_path = remove_level_from_path(current_path);
580 }
581 else
582 {
583 if (strcmp(current_path, "/") == 0)
584 new_path = g_strconcat(current_path, name, NULL);
585 else
586 new_path = g_strconcat(current_path, "/", name, NULL);
587 }
588 filelist_change_to(new_path);
589 g_free(new_path);
590 }
591
592 void dir_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
593 {
594 gint row = -1;
595 gint col = -1;
596
597 gtk_clist_get_selection_info (GTK_CLIST (widget), bevent->x, bevent->y, &row, &col);
598
599 if (bevent->button == 2)
600 {
601 gtk_object_set_user_data(GTK_OBJECT(dir_clist), GINT_TO_POINTER(row));
602 }
603 }
604
605 /*
606 *-----------------------------------------------------------------------------
607 * file list callbacks
608 *-----------------------------------------------------------------------------
609 */
610
611 void file_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
612 {
613 gint row = -1;
614 gint col = -1;
615
616 gtk_clist_get_selection_info (GTK_CLIST (widget), bevent->x, bevent->y, &row, &col);
617 if (row == -1 || col == -1)
618 {
619 filelist_click_row = -1;
620 return;
621 }
622
623 filelist_click_row = row;
624
625 if (bevent->button == 3)
626 {
627 file_clist_highlight_set();
628 gtk_menu_popup (GTK_MENU(menu_file_popup), NULL, NULL, NULL, NULL,
629 bevent->button, bevent->time);
630 }
631 }
632
633 void file_select_cb(GtkWidget *widget, gint row, gint col,
634 GdkEvent *event, gpointer data)
635 {
636 gchar *name;
637 gchar *path;
638
639 if (file_selection_count() != 1)
640 {
641 update_status_label(NULL);
642 return;
643 }
644
645 name = gtk_clist_get_row_data(GTK_CLIST(file_clist), row);
646 path = g_strconcat(current_path, "/", name, NULL);
647 image_change_to(path);
648 update_status_label(NULL);
649 g_free(path);
650 }
651
652 void file_unselect_cb(GtkWidget *widget, gint row, gint col,
653 GdkEvent *event, gpointer data)
654 {
655 #if 0
656 gchar *name;
657 gchar *path;
658
659 name = gtk_clist_get_row_data(GTK_CLIST(file_clist), row);
660 path = g_strconcat(current_path, "/", name, NULL);
661
662 if (strcmp(path, image_get_path()) == 0)
663 {
664 if (file_selection_count() > 0 && !file_is_selected(find_file_in_list(image_get_path())) )
665 {
666 gint new_row = GPOINTER_TO_INT(GTK_CLIST(file_clist)->selection->data);
667 gchar *new_name = gtk_clist_get_row_data(GTK_CLIST(file_clist), new_row);
668 gchar *new_path = g_strconcat(current_path, "/", new_name, NULL);
669 image_change_to(new_path);
670 g_free(new_path);
671 }
672 }
673 g_free(path);
674 #endif
675 update_status_label(NULL);
676 }
677
678 /*
679 *-----------------------------------------------------------------------------
680 * file list highlight utils
681 *-----------------------------------------------------------------------------
682 */
683
684 void file_clist_highlight_set()
685 {
686 if (file_clicked_is_selected()) return;
687
688 gtk_clist_set_background(GTK_CLIST(file_clist), filelist_click_row,
689 &GTK_WIDGET (file_clist)->style->bg[GTK_STATE_PRELIGHT]);
690 gtk_clist_set_foreground(GTK_CLIST(file_clist), filelist_click_row,
691 &GTK_WIDGET (file_clist)->style->fg[GTK_STATE_PRELIGHT]);
692 }
693
694 void file_clist_highlight_unset()
695 {
696 if (file_clicked_is_selected()) return;
697
698 gtk_clist_set_background(GTK_CLIST(file_clist), filelist_click_row, NULL);
699 gtk_clist_set_foreground(GTK_CLIST(file_clist), filelist_click_row, NULL);
700 }
701
702 /*
703 *-----------------------------------------------------------------------------
704 * path entry and history menu
705 *-----------------------------------------------------------------------------
706 */
707
708 void path_entry_cb(gchar *newdir, gpointer data)
709 {
710 gchar *new_path = g_strdup(newdir);
711 parse_out_relatives(new_path);
712 if (isdir(new_path))
713 filelist_change_to(new_path);
714 else if (isfile(new_path))
715 {
716 gchar *path = remove_level_from_path(new_path);
717 filelist_change_to(path);
718 g_free(path);
719 image_change_to(new_path);
720 }
721 g_free(new_path);
722 }
723
724 static void history_menu_select_cb(GtkWidget *widget, gpointer data)
725 {
726 gchar *new_path = data;
727 filelist_change_to(new_path);
728 }
729
730 static gchar *truncate_hist_text(gchar *t, gint l)
731 {
732 gchar *tp;
733 gchar *tbuf;
734 if (l >= strlen(t)) return g_strdup(t);
735 tp = t + strlen(t) - l;
736 while (tp[0] != '/' && tp < t + strlen(t)) tp++;
737 /* this checks to see if directory name is longer than l, if so
738 * reset the length of name to l, it's better to have a partial
739 * name than no name at all.
740 */
741 if (tp >= t + strlen(t)) tp = t + strlen(t) - l;
742 tbuf = g_strconcat("/...", tp, NULL);
743 return tbuf;
744 }
745
746 static void filelist_set_history(gchar *path)
747 {
748 static GList *history_list = NULL;
749 gchar *buf;
750 gchar *buf_ptr;
751 GtkWidget *menu;
752 GtkWidget *item;
753
754 if (!path) return;
755
756 gtk_entry_set_text(GTK_ENTRY(path_entry), current_path);
757
758 if (history_list)
759 {
760 g_list_foreach(history_list, (GFunc)g_free, NULL);
761 g_list_free(history_list);
762 history_list = NULL;
763 }
764
765 menu = gtk_menu_new();
766
767 buf = g_strdup(path);
768 buf_ptr = buf + strlen(buf) - 1 ;
769 while (buf_ptr > buf)
770 {
771 gchar *full_path;
772 gchar *truncated;
773 truncated = truncate_hist_text(buf, 32);
774
775 full_path = g_strdup(buf);
776 history_list = g_list_append(history_list, full_path);
777
778 item = gtk_menu_item_new_with_label (truncated);
779 gtk_signal_connect (GTK_OBJECT (item), "activate",
780 (GtkSignalFunc) history_menu_select_cb, full_path);
781
782 gtk_menu_append (GTK_MENU (menu), item);
783 gtk_widget_show (item);
784
785 g_free(truncated);
786
787 while (buf_ptr[0] != '/' && buf_ptr > buf) buf_ptr--;
788 buf_ptr[0] = '\0';
789 }
790 g_free(buf);
791
792 item = gtk_menu_item_new_with_label ("/");
793
794 gtk_signal_connect (GTK_OBJECT (item), "activate",
795 (GtkSignalFunc) history_menu_select_cb, "/");
796
797 gtk_menu_append (GTK_MENU (menu), item);
798 gtk_widget_show (item);
799
800 gtk_option_menu_set_menu(GTK_OPTION_MENU(history_menu), menu);
801 }
802
803 /*
804 *-----------------------------------------------------------------------------
805 * list update routines (public)
806 *-----------------------------------------------------------------------------
807 */
808
809 static gint thumbs_running = 0;
810
811 void interrupt_thumbs()
812 {
813 if (thumbs_running > 0) thumbs_running ++;
814 }
815
816 void filelist_populate_clist()
817 {
818 GList *work;
819 gint width;
820 gint tmp_width;
821 gint row;
822 gchar *image_name = NULL;
823 gchar *buf;
824
825 gint row_p = 0;
826 gchar *text;
827 guint8 spacing;
828 GdkPixmap *nopixmap;
829 GdkBitmap *nomask;
830
831 interrupt_thumbs();
832
833 filelist_set_history(current_path);
834
835 gtk_clist_freeze (GTK_CLIST (dir_clist));
836 gtk_clist_clear (GTK_CLIST (dir_clist));
837
838 width = 0;
839 work = dir_list;
840 while(work)
841 {
842 gchar *buf[2];
843 buf[0] = work->data;
844 buf[1] = NULL;
845 row = gtk_clist_append(GTK_CLIST(dir_clist), buf);
846 gtk_clist_set_row_data (GTK_CLIST(dir_clist), row, work->data);
847 tmp_width = gdk_string_width(dir_clist->style->font, buf[0]);
848 if (tmp_width > width) width = tmp_width;
849 work = work->next;
850 }
851
852 gtk_clist_set_column_width(GTK_CLIST(dir_clist), 0, width);
853 gtk_clist_thaw(GTK_CLIST (dir_clist));
854
855 buf = remove_level_from_path(image_get_path());
856 if (buf && strcmp(buf, current_path) == 0)
857 {
858 image_name = image_get_name();
859 }
860 g_free(buf);
861
862 gtk_clist_freeze (GTK_CLIST (file_clist));
863
864 if (!thumbnails_enabled)
865 {
866 gtk_clist_set_row_height (GTK_CLIST(file_clist),
867 GTK_WIDGET(file_clist)->style->font->ascent +
868 GTK_WIDGET(file_clist)->style->font->descent + 1);
869 }
870 else
871 {
872 gtk_clist_set_row_height (GTK_CLIST(file_clist), thumb_max_height + 2);
873 maintain_thumbnail_dir(current_path, FALSE);
874 }
875
876 width = 0;
877 work = file_list;
878
879 while(work)
880 {
881 gint has_pixmap;
882 gint match;
883 gchar *name = work->data;
884 gint done = FALSE;
885
886 while (!done)
887 {
888 if (GTK_CLIST(file_clist)->rows > row_p)
889 {
890 if (gtk_clist_get_cell_type(GTK_CLIST(file_clist),row_p, 0) == GTK_CELL_PIXTEXT)
891 {
892 gtk_clist_get_pixtext(GTK_CLIST(file_clist), row_p, 0, &text, &spacing, &nopixmap, &nomask);
893 has_pixmap = TRUE;
894 }
895 else
896 {
897 gtk_clist_get_text(GTK_CLIST(file_clist), row_p, 0, &text);
898 has_pixmap = FALSE;
899 }
900 match = strcmp(name, text);
901 }
902 else
903 {
904 match = -1;
905 }
906
907 if (match < 0)
908 {
909 gchar *buf[2];
910 buf[0] = name;
911 buf[1] = NULL;
912 row = gtk_clist_insert(GTK_CLIST(file_clist), row_p, buf);
913 gtk_clist_set_row_data (GTK_CLIST(file_clist), row, name);
914 if (thumbnails_enabled)
915 gtk_clist_set_shift(GTK_CLIST(file_clist), row, 0, 0, 5 + thumb_max_width);
916 done = TRUE;
917 if (image_name && strcmp(name, image_name) == 0)
918 gtk_clist_select_row(GTK_CLIST(file_clist), row, 0);
919 }
920 else if (match > 0)
921 {
922 gtk_clist_remove(GTK_CLIST(file_clist), row_p);
923 }
924 else
925 {
926 if (thumbnails_enabled && !has_pixmap)
927 gtk_clist_set_shift(GTK_CLIST(file_clist), row_p, 0, 0, 5 + thumb_max_width);
928 if (!thumbnails_enabled/* && has_pixmap*/)
929 {
930 gtk_clist_set_text(GTK_CLIST(file_clist), row_p, 0, name);
931 gtk_clist_set_shift(GTK_CLIST(file_clist), row_p, 0, 0, 0);
932 }
933 gtk_clist_set_row_data (GTK_CLIST(file_clist), row_p, name);
934 done = TRUE;
935 }
936 }
937 row_p++;
938
939 if (thumbnails_enabled)
940 tmp_width = gdk_string_width(file_clist->style->font, name) + thumb_max_width + 5;
941 else
942 tmp_width = gdk_string_width(file_clist->style->font, name);
943 if (tmp_width > width) width = tmp_width;
944 work = work->next;
945 }
946
947 while (GTK_CLIST(file_clist)->rows > row_p)
948 gtk_clist_remove(GTK_CLIST(file_clist), row_p);
949
950 gtk_clist_set_column_width(GTK_CLIST(file_clist), 0, width);
951 gtk_clist_thaw(GTK_CLIST (file_clist));
952
953 if (thumbnails_enabled)
954 {
955 GList *done_list = NULL;
956 gint past_run;
957 gint finished = FALSE;
958 gint j;
959 gint count = 0;
960 update_status_label(_("Loading thumbs..."));
961
962 for (j = 0; j < GTK_CLIST(file_clist)->rows; j++)
963 {
964 done_list = g_list_prepend(done_list, GINT_TO_POINTER(FALSE));
965 }
966
967 /* load thumbs */
968
969 while (!finished && done_list)
970 {
971 gint p = -1;
972 gint r = -1;
973 gint c = -1;
974 gtk_clist_get_selection_info (GTK_CLIST(file_clist), 1, 1, &r, &c);
975 if (r != -1)
976 {
977 work = g_list_nth(done_list, r);
978 while (work)
979 {
980 if (gtk_clist_row_is_visible(GTK_CLIST(file_clist), r))
981 {
982 if (!GPOINTER_TO_INT(work->data))
983 {
984 work->data = GINT_TO_POINTER(TRUE);
985 p = r;
986 work = NULL;
987 }
988 else
989 {
990 r++;
991 work = work->next;
992 }
993 }
994 else
995 {
996 work = NULL;
997 }
998 }
999 }
1000 if (p == -1)
1001 {
1002 work = done_list;
1003 r = 0;
1004 while(work && p == -1)
1005 {
1006 if (!GPOINTER_TO_INT(work->data))
1007 {
1008 p = r;
1009 work->data = GINT_TO_POINTER(TRUE);
1010 }
1011 else
1012 {
1013 r++;
1014 work = work->next;
1015 if (!work) finished = TRUE;
1016 }
1017 }
1018 }
1019
1020 count++;
1021
1022 if (!finished && gtk_clist_get_cell_type(GTK_CLIST(file_clist), p, 0) != GTK_CELL_PIXTEXT)
1023 {
1024 GdkPixmap *pixmap = NULL;
1025 GdkBitmap *mask = NULL;
1026 gchar *name;
1027 gchar *path;
1028
1029 thumbs_running ++;
1030 past_run = thumbs_running;
1031 while(gtk_events_pending()) gtk_main_iteration();
1032 if (thumbs_running > past_run)
1033 {
1034 thumbs_running -= 2;
1035 update_progressbar(0.0);
1036 update_status_label(NULL);
1037 g_list_free(done_list);
1038 return;
1039 }
1040 thumbs_running --;
1041
1042 name = gtk_clist_get_row_data(GTK_CLIST(file_clist), p);
1043 path = g_strconcat (current_path, "/", name, NULL);
1044 spacing = create_thumbnail(path, &pixmap, &mask);
1045 g_free(path);
1046 gtk_clist_set_pixtext (GTK_CLIST(file_clist), p, 0, name, spacing + 5, pixmap, mask);
1047 gtk_clist_set_shift(GTK_CLIST(file_clist), p, 0, 0, 0);
1048
1049 update_progressbar((gfloat)(count) / GTK_CLIST(file_clist)->rows);
1050 }
1051 }
1052 update_progressbar(0.0);
1053 g_list_free(done_list);
1054 }
1055
1056 update_status_label(NULL);
1057 }
1058
1059 void filelist_refresh()
1060 {
1061 filelist_read(current_path);
1062 filelist_populate_clist();
1063 filelist_click_row = -1;
1064 }
1065
1066 void filelist_change_to(gchar *path)
1067 {
1068 if (!isdir(path)) return;
1069
1070 g_free(current_path);
1071 current_path = g_strdup(path);
1072
1073 filelist_refresh();
1074 }