1
|
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 >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]);
|
|
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 }
|