11 static gint filelist_click_row = -1;
13 static void update_progressbar(gfloat val);
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);
19 static gint sort_list_cb(void *a, void *b);
20 static void filelist_read(gchar *path);
22 static gint file_find_closest_unaccounted(gint row, gint count, GList *ignore_list);
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);
29 *-----------------------------------------------------------------------------
30 * file status information (private)
31 *-----------------------------------------------------------------------------
34 static void update_progressbar(gfloat val)
36 gtk_progress_bar_update (GTK_PROGRESS_BAR(info_progress_bar), val);
39 void update_status_label(gchar *text)
47 gtk_label_set(GTK_LABEL(info_status), text);
51 if (slideshow_is_running()) ss = _(" Slideshow");
53 count = file_selection_count();
55 buf = g_strdup_printf(_("%d files (%d)%s"), file_count(), count, ss);
57 buf = g_strdup_printf(_("%d files%s"), file_count(), ss);
59 gtk_label_set(GTK_LABEL(info_status), buf);
64 *-----------------------------------------------------------------------------
66 *-----------------------------------------------------------------------------
69 static gint file_is_hidden(gchar *name)
71 if (name[0] != '.') return FALSE;
72 if (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')) return FALSE;
76 static gint file_is_in_filter(gchar *name)
79 if (!filename_filter || file_filter_disable) return TRUE;
81 work = filename_filter;
84 gchar *filter = work->data;
85 gint lf = strlen(filter);
86 gint ln = strlen(name);
89 if (strncasecmp(name + ln - lf, filter, lf) == 0) return TRUE;
97 static void add_to_filter(gchar *text, gint add)
99 if (add) filename_filter = g_list_append(filename_filter, g_strdup(text));
102 void rebuild_file_filter()
106 g_list_foreach(filename_filter,(GFunc)g_free,NULL);
107 g_list_free(filename_filter);
108 filename_filter = NULL;
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);
125 gchar *buf = g_strdup(custom_filter);
127 gchar *pos_ptr_e = custom_filter;
128 while(pos_ptr_e[0] != '\0')
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] == ';')
137 add_to_filter(pos_ptr_b, TRUE);
144 *-----------------------------------------------------------------------------
145 * load file list (private)
146 *-----------------------------------------------------------------------------
149 static gint sort_list_cb(void *a, void *b)
151 return strcmp((gchar *)a, (gchar *)b);
154 static void filelist_read(gchar *path)
158 struct stat ent_sbuf;
160 if((dp = opendir(path))==NULL)
166 g_list_foreach(dir_list,(GFunc)g_free,NULL);
167 g_list_free(dir_list);
170 g_list_foreach(file_list,(GFunc)g_free,NULL);
171 g_list_free(file_list);
174 while ((dir = readdir(dp)) != NULL)
176 /* skips removed files */
179 gchar *name = dir->d_name;
180 if (show_dot_files || !file_is_hidden(name))
182 gchar *filepath = g_strconcat(path, "/", name, NULL);
183 if (stat(filepath,&ent_sbuf) >= 0 && S_ISDIR(ent_sbuf.st_mode))
185 dir_list = g_list_prepend(dir_list, g_strdup(name));
189 if (file_is_in_filter(name))
190 file_list = g_list_prepend(file_list, g_strdup(name));
199 dir_list = g_list_sort(dir_list, (GCompareFunc) sort_list_cb);
200 file_list = g_list_sort(file_list, (GCompareFunc) sort_list_cb);
204 *-----------------------------------------------------------------------------
205 * file list utilities to retrieve information (public)
206 *-----------------------------------------------------------------------------
211 return g_list_length(file_list);
214 gint file_selection_count()
217 GList *work = GTK_CLIST(file_clist)->selection;
221 if (debug) printf("s = %d\n", GPOINTER_TO_INT(work->data));
225 if (debug) printf("files selected = %d\n", count);
230 gint find_file_in_list(gchar *path)
232 GList *work = file_list;
237 if (!path) return -1;
239 buf = remove_level_from_path(path);
240 if (strcmp(buf, current_path) != 0)
247 name = filename_from_path(path);
251 if (strcmp(name, work->data) == 0) return count;
258 gchar *file_get_path(gint row)
261 gchar *name = gtk_clist_get_row_data(GTK_CLIST(file_clist), row);
263 if (name) path = g_strconcat(current_path, "/", name, NULL);
268 gint file_is_selected(gint row)
270 GList *work = GTK_CLIST(file_clist)->selection;
274 if (GPOINTER_TO_INT(work->data) == row) return TRUE;
282 *-----------------------------------------------------------------------------
283 * utilities to retrieve list of selected files (public)
284 *-----------------------------------------------------------------------------
287 GList *file_get_selected_list()
290 GList *work = GTK_CLIST(file_clist)->selection;
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));
300 list = g_list_reverse(list);
305 void free_selected_list(GList *list)
307 g_list_foreach(list, (GFunc)g_free, NULL);
311 gint file_clicked_is_selected()
313 return file_is_selected(filelist_click_row);
316 gchar *file_clicked_get_path()
318 return file_get_path(filelist_click_row);
322 *-----------------------------------------------------------------------------
323 * image change routines
324 *-----------------------------------------------------------------------------
327 void file_image_change_to(gint row)
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)
333 gtk_clist_moveto(GTK_CLIST(file_clist), row, -1, 0.5, 0.0);
337 void file_next_image()
339 gint current = find_file_in_list(image_get_path());
340 gint total = file_count();
344 if (current < total - 1)
346 file_image_change_to(current + 1);
351 file_image_change_to(0);
355 void file_prev_image()
357 gint current = find_file_in_list(image_get_path());
363 file_image_change_to(current - 1);
368 file_image_change_to(file_count() - 1);
372 void file_first_image()
374 gint current = find_file_in_list(image_get_path());
375 if (current != 0 && file_count() > 0)
377 file_image_change_to(0);
381 void file_last_image()
383 gint current = find_file_in_list(image_get_path());
384 gint count = file_count();
385 if (current != count - 1 && count > 0)
387 file_image_change_to(count - 1);
392 *-----------------------------------------------------------------------------
393 * file delete/rename update routines
394 *-----------------------------------------------------------------------------
397 static gint file_find_closest_unaccounted(gint row, gint count, GList *ignore_list)
407 gint f = find_file_in_list(work->data);
408 if (f >= 0) list = g_list_append(list, GINT_TO_POINTER(f));
418 gpointer p = work->data;
420 if (row == GPOINTER_TO_INT(p))
425 if (rev == GPOINTER_TO_INT(p))
430 if (!c) list = g_list_remove(list, p);
451 void file_is_gone(gchar *path, GList *ignore_list)
457 row = find_file_in_list(path);
460 if (file_is_selected(row) /* && file_selection_count() == 1 */)
462 gint n = file_count();
465 new_row = file_find_closest_unaccounted(row, n, ignore_list);
466 if (debug) printf("row = %d, closest is %d\n", row, new_row);
479 gtk_clist_unselect_all(GTK_CLIST(file_clist));
482 gtk_clist_select_row(GTK_CLIST(file_clist), new_row, -1);
483 file_image_change_to(new_row);
487 image_change_to(NULL);
491 gtk_clist_remove(GTK_CLIST(file_clist), row);
492 list = g_list_nth(file_list, row);
494 file_list = g_list_remove(file_list, name);
496 update_status_label(NULL);
499 void file_is_renamed(gchar *source, gchar *dest)
505 if (image_get_path() && !strcmp(source, image_get_path()))
507 image_set_path(dest);
510 row = find_file_in_list(source);
513 source_base = remove_level_from_path(source);
514 dest_base = remove_level_from_path(dest);
516 if (strcmp(source_base, dest_base) == 0)
520 GList *work = g_list_nth(file_list, row);
522 file_list = g_list_remove(file_list, 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);
528 if (gtk_clist_get_cell_type(GTK_CLIST(file_clist), row, 0) != GTK_CELL_PIXTEXT)
530 gtk_clist_set_text (GTK_CLIST(file_clist), row, 0, name);
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);
543 gtk_clist_set_row_data(GTK_CLIST(file_clist), row, name);
544 gtk_clist_row_move(GTK_CLIST(file_clist), row, n);
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);
553 update_status_label(NULL);
562 *-----------------------------------------------------------------------------
563 * directory list callbacks
564 *-----------------------------------------------------------------------------
567 void dir_select_cb(GtkWidget *widget, gint row, gint col,
568 GdkEvent *event, gpointer data)
572 name = gtk_clist_get_row_data (GTK_CLIST(dir_clist), row);
573 if (strcmp(name, ".") == 0)
575 new_path = g_strdup(current_path);
577 else if (strcmp(name, "..") == 0)
579 new_path = remove_level_from_path(current_path);
583 if (strcmp(current_path, "/") == 0)
584 new_path = g_strconcat(current_path, name, NULL);
586 new_path = g_strconcat(current_path, "/", name, NULL);
588 filelist_change_to(new_path);
592 void dir_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
597 gtk_clist_get_selection_info (GTK_CLIST (widget), bevent->x, bevent->y, &row, &col);
599 if (bevent->button == 2)
601 gtk_object_set_user_data(GTK_OBJECT(dir_clist), GINT_TO_POINTER(row));
606 *-----------------------------------------------------------------------------
607 * file list callbacks
608 *-----------------------------------------------------------------------------
611 void file_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
616 gtk_clist_get_selection_info (GTK_CLIST (widget), bevent->x, bevent->y, &row, &col);
617 if (row == -1 || col == -1)
619 filelist_click_row = -1;
623 filelist_click_row = row;
625 if (bevent->button == 3)
627 file_clist_highlight_set();
628 gtk_menu_popup (GTK_MENU(menu_file_popup), NULL, NULL, NULL, NULL,
629 bevent->button, bevent->time);
633 void file_select_cb(GtkWidget *widget, gint row, gint col,
634 GdkEvent *event, gpointer data)
639 if (file_selection_count() != 1)
641 update_status_label(NULL);
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);
652 void file_unselect_cb(GtkWidget *widget, gint row, gint col,
653 GdkEvent *event, gpointer data)
659 name = gtk_clist_get_row_data(GTK_CLIST(file_clist), row);
660 path = g_strconcat(current_path, "/", name, NULL);
662 if (strcmp(path, image_get_path()) == 0)
664 if (file_selection_count() > 0 && !file_is_selected(find_file_in_list(image_get_path())) )
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);
675 update_status_label(NULL);
679 *-----------------------------------------------------------------------------
680 * file list highlight utils
681 *-----------------------------------------------------------------------------
684 void file_clist_highlight_set()
686 if (file_clicked_is_selected()) return;
688 gtk_clist_set_background(GTK_CLIST(file_clist), filelist_click_row,
689 >K_WIDGET (file_clist)->style->bg[GTK_STATE_PRELIGHT]);
690 gtk_clist_set_foreground(GTK_CLIST(file_clist), filelist_click_row,
691 >K_WIDGET (file_clist)->style->fg[GTK_STATE_PRELIGHT]);
694 void file_clist_highlight_unset()
696 if (file_clicked_is_selected()) return;
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);
703 *-----------------------------------------------------------------------------
704 * path entry and history menu
705 *-----------------------------------------------------------------------------
708 void path_entry_cb(gchar *newdir, gpointer data)
710 gchar *new_path = g_strdup(newdir);
711 parse_out_relatives(new_path);
713 filelist_change_to(new_path);
714 else if (isfile(new_path))
716 gchar *path = remove_level_from_path(new_path);
717 filelist_change_to(path);
719 image_change_to(new_path);
724 static void history_menu_select_cb(GtkWidget *widget, gpointer data)
726 gchar *new_path = data;
727 filelist_change_to(new_path);
730 static gchar *truncate_hist_text(gchar *t, gint l)
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.
741 if (tp >= t + strlen(t)) tp = t + strlen(t) - l;
742 tbuf = g_strconcat("/...", tp, NULL);
746 static void filelist_set_history(gchar *path)
748 static GList *history_list = NULL;
756 gtk_entry_set_text(GTK_ENTRY(path_entry), current_path);
760 g_list_foreach(history_list, (GFunc)g_free, NULL);
761 g_list_free(history_list);
765 menu = gtk_menu_new();
767 buf = g_strdup(path);
768 buf_ptr = buf + strlen(buf) - 1 ;
769 while (buf_ptr > buf)
773 truncated = truncate_hist_text(buf, 32);
775 full_path = g_strdup(buf);
776 history_list = g_list_append(history_list, full_path);
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);
782 gtk_menu_append (GTK_MENU (menu), item);
783 gtk_widget_show (item);
787 while (buf_ptr[0] != '/' && buf_ptr > buf) buf_ptr--;
792 item = gtk_menu_item_new_with_label ("/");
794 gtk_signal_connect (GTK_OBJECT (item), "activate",
795 (GtkSignalFunc) history_menu_select_cb, "/");
797 gtk_menu_append (GTK_MENU (menu), item);
798 gtk_widget_show (item);
800 gtk_option_menu_set_menu(GTK_OPTION_MENU(history_menu), menu);
804 *-----------------------------------------------------------------------------
805 * list update routines (public)
806 *-----------------------------------------------------------------------------
809 static gint thumbs_running = 0;
811 void interrupt_thumbs()
813 if (thumbs_running > 0) thumbs_running ++;
816 void filelist_populate_clist()
822 gchar *image_name = NULL;
833 filelist_set_history(current_path);
835 gtk_clist_freeze (GTK_CLIST (dir_clist));
836 gtk_clist_clear (GTK_CLIST (dir_clist));
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;
852 gtk_clist_set_column_width(GTK_CLIST(dir_clist), 0, width);
853 gtk_clist_thaw(GTK_CLIST (dir_clist));
855 buf = remove_level_from_path(image_get_path());
856 if (buf && strcmp(buf, current_path) == 0)
858 image_name = image_get_name();
862 gtk_clist_freeze (GTK_CLIST (file_clist));
864 if (!thumbnails_enabled)
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);
872 gtk_clist_set_row_height (GTK_CLIST(file_clist), thumb_max_height + 2);
873 maintain_thumbnail_dir(current_path, FALSE);
883 gchar *name = work->data;
888 if (GTK_CLIST(file_clist)->rows > row_p)
890 if (gtk_clist_get_cell_type(GTK_CLIST(file_clist),row_p, 0) == GTK_CELL_PIXTEXT)
892 gtk_clist_get_pixtext(GTK_CLIST(file_clist), row_p, 0, &text, &spacing, &nopixmap, &nomask);
897 gtk_clist_get_text(GTK_CLIST(file_clist), row_p, 0, &text);
900 match = strcmp(name, text);
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);
917 if (image_name && strcmp(name, image_name) == 0)
918 gtk_clist_select_row(GTK_CLIST(file_clist), row, 0);
922 gtk_clist_remove(GTK_CLIST(file_clist), row_p);
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*/)
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);
933 gtk_clist_set_row_data (GTK_CLIST(file_clist), row_p, name);
939 if (thumbnails_enabled)
940 tmp_width = gdk_string_width(file_clist->style->font, name) + thumb_max_width + 5;
942 tmp_width = gdk_string_width(file_clist->style->font, name);
943 if (tmp_width > width) width = tmp_width;
947 while (GTK_CLIST(file_clist)->rows > row_p)
948 gtk_clist_remove(GTK_CLIST(file_clist), row_p);
950 gtk_clist_set_column_width(GTK_CLIST(file_clist), 0, width);
951 gtk_clist_thaw(GTK_CLIST (file_clist));
953 if (thumbnails_enabled)
955 GList *done_list = NULL;
957 gint finished = FALSE;
960 update_status_label(_("Loading thumbs..."));
962 for (j = 0; j < GTK_CLIST(file_clist)->rows; j++)
964 done_list = g_list_prepend(done_list, GINT_TO_POINTER(FALSE));
969 while (!finished && done_list)
974 gtk_clist_get_selection_info (GTK_CLIST(file_clist), 1, 1, &r, &c);
977 work = g_list_nth(done_list, r);
980 if (gtk_clist_row_is_visible(GTK_CLIST(file_clist), r))
982 if (!GPOINTER_TO_INT(work->data))
984 work->data = GINT_TO_POINTER(TRUE);
1004 while(work && p == -1)
1006 if (!GPOINTER_TO_INT(work->data))
1009 work->data = GINT_TO_POINTER(TRUE);
1015 if (!work) finished = TRUE;
1022 if (!finished && gtk_clist_get_cell_type(GTK_CLIST(file_clist), p, 0) != GTK_CELL_PIXTEXT)
1024 GdkPixmap *pixmap = NULL;
1025 GdkBitmap *mask = NULL;
1030 past_run = thumbs_running;
1031 while(gtk_events_pending()) gtk_main_iteration();
1032 if (thumbs_running > past_run)
1034 thumbs_running -= 2;
1035 update_progressbar(0.0);
1036 update_status_label(NULL);
1037 g_list_free(done_list);
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);
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);
1049 update_progressbar((gfloat)(count) / GTK_CLIST(file_clist)->rows);
1052 update_progressbar(0.0);
1053 g_list_free(done_list);
1056 update_status_label(NULL);
1059 void filelist_refresh()
1061 filelist_read(current_path);
1062 filelist_populate_clist();
1063 filelist_click_row = -1;
1066 void filelist_change_to(gchar *path)
1068 if (!isdir(path)) return;
1070 g_free(current_path);
1071 current_path = g_strdup(path);